diff --git "a/result.json" "b/result.json" --- "a/result.json" +++ "b/result.json" @@ -1,107 +1,3 @@ -{ - "algebra.mxpoly": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat choice seq.\nFrom mathcomp Require Import div fintype tuple finfun bigop fingroup perm.\nFrom mathcomp Require Import ssralg zmodp matrix mxalgebra poly polydiv.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GRing.Theory.\nImport Monoid.Theory.\n\nLocal Open Scope ring_scope.\n\nImport Pdiv.Idomain.\n\nSection RowPoly.\n\nVariables (R : nzRingType) (d : nat).\nImplicit Types u v : 'rV[R]_d.\nImplicit Types p q : {poly R}.\n\n(*This definition converts a row vector of ring elements into a univariate polynomial where the coefficient of each degree corresponds to the vector entry at that index, and coefficients for degrees beyond the vector's dimension are zero.*)\nDefinition rVpoly v := \\poly_(k < d) (if insub k is Some i then v 0 i else 0).\n(*This definition converts a univariate polynomial into a row vector of a specified dimension by taking the polynomial's coefficients for each degree up to one less than the dimension.*)\nDefinition poly_rV p := \\row_(i < d) p`_i.\n\n(*This lemma states that the coefficient for a given degree of a polynomial created from a row vector is the entry of the vector at the corresponding index if that index is within the vector's bounds, and zero otherwise.*)\nLemma coef_rVpoly v k : (rVpoly v)`_k = if insub k is Some i then v 0 i else 0.\n\n(*This lemma states that for an index within the bounds of a given row vector, the coefficient of the polynomial generated from that vector at that index is equal to the vector's entry at that same index.*)\nLemma coef_rVpoly_ord v (i : 'I_d) : (rVpoly v)`_i = v 0 i.\n\n(*This lemma states that converting a standard basis row vector, which has a one at a specific index and zeros elsewhere, into a polynomial results in the monomial 'X' raised to the power of that index.*)\nLemma rVpoly_delta i : rVpoly (delta_mx 0 i) = 'X^i.\n\n(*This lemma states that converting a row vector to a polynomial and then converting that polynomial back into a row vector of the same dimension yields the original row vector.*)\nLemma rVpolyK : cancel rVpoly poly_rV.\n\n(*This lemma states that for any polynomial whose size is less than or equal to a given dimension, converting it to a row vector of that dimension and then converting it back to a polynomial yields the original polynomial.*)\nLemma poly_rV_K p : size p <= d -> rVpoly (poly_rV p) = p.\n\n(*This lemma states that the conversion from a polynomial to a row vector is a linear transformation.*)\nLemma poly_rV_is_linear : linear poly_rV.\n\nHB.instance Definition _ := GRing.isSemilinear.Build R {poly R} 'rV_d _ poly_rV\n (GRing.semilinear_linear poly_rV_is_linear).\n\n(*This lemma states that the conversion from a row vector to a polynomial is a linear transformation.*)\nLemma rVpoly_is_linear : linear rVpoly.\n\n(*This defines a natural number as the sum of the degrees of two given polynomials, which corresponds to the dimension of the Sylvester matrix.*)\nLet dS := ((size q).-1 + (size p).-1)%N.\nLocal Notation band r := (lin1_mx (poly_rV \\o r \\o* rVpoly)).\n\n(*This definition constructs the Sylvester matrix for two given polynomials. The matrix is formed by concatenating two sub-matrices derived from the coefficients of the two polynomials.*)\nDefinition Sylvester_mx : 'M[R]_dS := col_mx (band p) (band q).\n\n(*This lemma provides an explicit formula for any entry of the Sylvester matrix. The value at a given row and column is determined by a specific coefficient of one of the two input polynomials, depending on which part of the matrix the row falls into.*)\nLemma Sylvester_mxE (i j : 'I_dS) :\n let S_ r k := r`_(j - k) *+ (k <= j) in\n Sylvester_mx i j = match split i with inl k => S_ p k | inr k => S_ q k end.\n\n(*This definition specifies the resultant of two polynomials as the determinant of their associated Sylvester matrix.*)\nDefinition resultant := \\det Sylvester_mx.\n\nEnd Resultant.\n\nPrenex Implicits Sylvester_mx resultant.\n\n(*This lemma states that for two non-constant polynomials over a commutative non-zero ring, their resultant can be expressed as a linear combination of the two polynomials with polynomial coefficients, where the degrees of these coefficient polynomials are bounded.*)\nLemma resultant_in_ideal (R : comNzRingType) (p q : {poly R}) :\n size p > 1 -> size q > 1 ->\n {uv : {poly R} * {poly R} | size uv.1 < size q /\\ size uv.2 < size p\n & (resultant p q)%:P = uv.1 * p + uv.2 * q}.\n\n(*This lemma states that over an integral domain, the resultant of two polynomials is zero if and only if the greatest common divisor of these polynomials is non-constant.*)\nLemma resultant_eq0 (R : idomainType) (p q : {poly R}) :\n (resultant p q == 0) = (size (gcdp p q) > 1).\n\nSection HornerMx.\n\nVariables (R : comNzRingType) (n' : nat).\n(*This local notation introduces `n` as a shorthand for a positive natural number, which is constructed as the successor of some underlying natural number. This is commonly used to specify dimensions, such as for matrices, that must be non-zero.*)\nLocal Notation n := n'.+1.\nImplicit Types (A B : 'M[R]_n) (p q : {poly R}).\n\nSection OneMatrix.\n\nVariable A : 'M[R]_n.\n\n(*This definition provides a function for evaluating a polynomial at a given square matrix, using an efficient evaluation scheme based on Horner's method.*)\nDefinition horner_mx := horner_morph (comm_mx_scalar^~ A).\nHB.instance Definition _ := GRing.RMorphism.on horner_mx.\n\n(*This lemma states that evaluating a constant polynomial at a matrix results in the corresponding scalar matrix, which is the constant multiplied by the identity matrix.*)\nLemma horner_mx_C a : horner_mx a%:P = a%:M.\n\n(*This lemma states that when the polynomial 'X' is evaluated at a square matrix, the result is the matrix itself.*)\nLemma horner_mx_X : horner_mx 'X = A. \n\n(*This lemma asserts that the matrix evaluation function for polynomials is scalable, meaning that scaling the input polynomial by a ring element results in the output matrix being scaled by the same element.*)\nLemma horner_mxZ : scalable horner_mx.\n\n(*This definition constructs a matrix where each row is the vectorized representation of a successive power of a given square matrix, starting from the identity matrix.*)\nDefinition powers_mx d := \\matrix_(i < d) mxvec (A ^+ i).\n\n(*This lemma states that evaluating a polynomial, which is generated from a row vector, at a square matrix yields the same result as the matrix product of the row vector and the matrix of that square matrix's powers, with the resulting product vector being reshaped into a square matrix.*)\nLemma horner_rVpoly m (u : 'rV_m) :\n horner_mx (rVpoly u) = vec_mx (u *m powers_mx m).\n\nEnd OneMatrix.\n\n(*This lemma states that evaluating a polynomial at a diagonal matrix is equivalent to creating a new diagonal matrix whose diagonal entries are the results of evaluating the polynomial at each of the original matrix's diagonal entries.*)\nLemma horner_mx_diag (d : 'rV[R]_n) (p : {poly R}) :\n horner_mx (diag_mx d) p = diag_mx (map_mx (horner p) d).\n\n(*This lemma states that if a matrix commutes with a second matrix, then it also commutes with the result of evaluating any polynomial at that second matrix.*)\nLemma comm_mx_horner A B p : comm_mx A B -> comm_mx A (horner_mx B p).\n\n(*This lemma states that if a matrix commutes with a second matrix, then the result of evaluating any polynomial at the first matrix will also commute with the second matrix.*)\nLemma comm_horner_mx A B p : comm_mx A B -> comm_mx (horner_mx A p) B.\n\n(*This lemma states that the results of evaluating any two polynomials at the same square matrix will always commute with each other.*)\nLemma comm_horner_mx2 A p q : GRing.comm (horner_mx A p) (horner_mx A q).\n\nEnd HornerMx.\n\n(*This lemma states that if a subspace is stable under the action of a given square matrix, it is also a stable subspace under the action of the matrix resulting from the evaluation of any polynomial at that given matrix.*)\nLemma horner_mx_stable (K : fieldType) m n p\n (V : 'M[K]_(n.+1, m.+1)) (f : 'M_m.+1) :\n stablemx V f -> stablemx V (horner_mx f p).\n\nPrenex Implicits horner_mx powers_mx.\n\nSection CharPoly.\n\nVariables (R : nzRingType) (n : nat) (A : 'M[R]_n).\nImplicit Types p q : {poly R}.\n\n(*This definition specifies the characteristic matrix of a given square matrix as the result of subtracting the matrix from the matrix 'X' times the identity, where matrix entries are treated as polynomials.*)\nDefinition char_poly_mx := 'X%:M - map_mx (@polyC R) A.\n(*This definition specifies the characteristic polynomial of a square matrix as the determinant of its characteristic matrix.*)\nDefinition char_poly := \\det char_poly_mx.\n\n(*This definition creates a finite sequence containing the diagonal elements of a given square matrix, ordered by their row and column index.*)\nLet diagA := [seq A i i | i <- index_enum _ & true].\n(*This lemma states that the length of the sequence of diagonal entries of a matrix `A` is equal to the dimension `n` of the matrix.*)\nLet size_diagA : size diagA = n.\n\n(*This lemma asserts the existence of a polynomial `q` such that the characteristic polynomial can be expressed as the sum of `q` and the product of linear factors `X minus x` for each diagonal entry `x` of the matrix. Furthermore, the degree of `q` is guaranteed to be less than the dimension of the matrix.*)\nLet split_diagA :\n exists2 q, \\prod_(x <- diagA) ('X - x%:P) + q = char_poly & size q <= n.-1.\n\n(*This lemma states that the size of the sequence of coefficients of the characteristic polynomial of an n-dimensional square matrix is equal to `n` plus one.*)\nLemma size_char_poly : size char_poly = n.+1.\n\n(*This lemma asserts that the characteristic polynomial of a matrix is monic, meaning its leading coefficient is one.*)\nLemma char_poly_monic : char_poly \\is monic.\n\n(*This lemma states that for a matrix `A` of dimension `n` greater than zero, the coefficient of the term of degree `n` minus one in the characteristic polynomial is equal to the negation of the trace of `A`.*)\nLemma char_poly_trace : n > 0 -> char_poly`_n.-1 = - \\tr A.\n\n(*This lemma states that the constant term, which is the coefficient of degree zero, of the characteristic polynomial of a matrix `A` of dimension `n` is equal to the determinant of `A` multiplied by negative one raised to the power of `n`.*)\nLemma char_poly_det : char_poly`_0 = (- 1) ^+ n * \\det A.\n\nEnd CharPoly.\n\nPrenex Implicits char_poly_mx char_poly.\n\n(*This lemma asserts the existence of a bijective ring homomorphism, denoted `phi`, that establishes an isomorphism between the ring of matrices with polynomial entries and the ring of polynomials with matrix coefficients. The lemma further specifies that this isomorphism maps a matrix of polynomials to the corresponding polynomial of matrices by applying the scalar matrix function to each coefficient, maps a constant matrix to its polynomial representation, and preserves the coefficients of the polynomials within the matrix entries.*)\nLemma mx_poly_ring_isom (R : nzRingType) n' (n := n'.+1) :\n exists phi : {rmorphism 'M[{poly R}]_n -> {poly 'M[R]_n}},\n [/\\ bijective phi,\n forall p, phi p%:M = map_poly scalar_mx p,\n forall A, phi (map_mx polyC A) = A%:P\n & forall A i j k, (phi A)`_k i j = (A i j)`_k].\n\n(*This theorem, known as the Cayley-Hamilton theorem, states that any square matrix satisfies its own characteristic equation. That is, when the characteristic polynomial of a matrix is evaluated at the matrix itself, the result is the zero matrix.*)\nTheorem Cayley_Hamilton (R : comNzRingType) n' (A : 'M[R]_n'.+1) :\n horner_mx A (char_poly A) = 0.\n\n(*This lemma states that for a matrix over a field, a scalar is an eigenvalue of the matrix if and only if that scalar is a root of the characteristic polynomial of the matrix.*)\nLemma eigenvalue_root_char (F : fieldType) n (A : 'M[F]_n) a :\n eigenvalue A a = root (char_poly A) a.\n\n(*This lemma states that for any triangular matrix over a commutative ring, its characteristic polynomial is the product of the linear factors `X minus d` for each diagonal entry `d` of the matrix.*)\nLemma char_poly_trig {R : comNzRingType} n (A : 'M[R]_n) : is_trig_mx A ->\n char_poly A = \\prod_(i < n) ('X - (A i i)%:P).\n\n(*This definition constructs the companion matrix for a given sequence of ring elements, which is interpreted as the coefficients of a polynomial. The matrix is defined such that its characteristic polynomial is related to the original polynomial.*)\nDefinition companionmx {R : nzRingType} (p : seq R) (d := (size p).-1) :=\n \\matrix_(i < d, j < d)\n if (i == d.-1 :> nat) then - p`_j else (i.+1 == j :> nat)%:R.\n\n(*This lemma states that for a monic polynomial `p`, the characteristic polynomial of the companion matrix generated from `p`'s coefficients is equal to the polynomial `p` itself.*)\nLemma companionmxK {R : comNzRingType} (p : {poly R}) :\n p \\is monic -> char_poly (companionmx p) = p.\n\n(*This lemma describes the result of left-multiplying the companion matrix of a polynomial `p` by a standard basis row vector. The result is another standard basis row vector, effectively demonstrating how the companion matrix acts on basis vectors.*)\nLemma mulmx_delta_companion (R : nzRingType) (p : seq R)\n (i: 'I_(size p).-1) (i_small : i.+1 < (size p).-1):\n delta_mx 0 i *m companionmx p = delta_mx 0 (Ordinal i_small) :> 'rV__.\n\n(*This lemma relates the characteristic matrix of a square matrix to the characteristic matrix of one of its principal submatrices. It states that the characteristic matrix of the submatrix obtained by removing the `i`-th row and `i`-th column is equal to the submatrix of the original characteristic matrix obtained by also removing the `i`-th row and `i`-th column.*)\nLemma row'_col'_char_poly_mx {R : nzRingType} m i (M : 'M[R]_m) :\n row' i (col' i (char_poly_mx M)) = char_poly_mx (row' i (col' i M)).\n\n(*This lemma states that the characteristic matrix of a block diagonal matrix is a block diagonal matrix whose blocks are the characteristic matrices of the original matrix's diagonal blocks.*)\nLemma char_block_diag_mx {R : nzRingType} m n (A : 'M[R]_m) (B : 'M[R]_n) :\n char_poly_mx (block_mx A 0 0 B) =\n block_mx (char_poly_mx A) 0 0 (char_poly_mx B).\n\nSection MinPoly.\n\nVariables (F : fieldType) (n' : nat).\n(*A local notation that defines a natural number as the successor of another natural number, typically used to represent the dimension of a square matrix.*)\nLocal Notation n := n'.+1.\nVariable A : 'M[F]_n.\nImplicit Types p q : {poly F}.\n\n(*This fact establishes the existence of a natural number `d` such that the set of the first `d` plus one powers of a given square matrix `A`, starting from the identity matrix, is linearly dependent. This is a foundational step for proving the existence of a minimal polynomial.*)\nFact degree_mxminpoly_proof : exists d, \\rank (powers_mx A d.+1) <= d.\n\n(*This definition specifies the degree of the minimal polynomial of a matrix as the smallest natural number `d` for which the set of matrix powers from zero to `d` is linearly dependent.*)\nDefinition degree_mxminpoly := ex_minn degree_mxminpoly_proof.\n(*This notation provides a local alias for `degree_mxminpoly`, representing the degree of the minimal polynomial of the matrix `A` within the current context.*)\nLocal Notation d := degree_mxminpoly.\n(*This notation provides a local alias for the matrix whose rows are the successive powers of the matrix `A`, starting from the identity matrix up to the power `d` minus one, where `d` is the degree of the minimal polynomial of `A`.*)\nLocal Notation Ad := (powers_mx A d).\n\n(*This lemma asserts that the degree of the minimal polynomial of a matrix is strictly greater than zero, implying that the minimal polynomial cannot be a non-zero constant.*)\nLemma mxminpoly_nonconstant : d > 0.\n\n(*This lemma states that the identity matrix is contained within the module span of the rows of the matrix of powers `Ad`. As the first row of `Ad` is the identity matrix itself, this property holds directly from its construction.*)\nLemma minpoly_mx1 : (1%:M \\in Ad)%MS.\n\n(*This lemma states that the rows of the matrix `Ad`, which correspond to the powers of matrix `A` from the zeroth power up to the power one less than the minimal polynomial degree, are linearly independent.*)\nLemma minpoly_mx_free : row_free Ad.\n\n(*This lemma states that for any polynomial `p`, the matrix resulting from evaluating `p` at the matrix `A` is an element of the module spanned by the rows of `Ad`, the matrix of powers of `A`. This reflects that any polynomial in `A` can be reduced to a linear combination of the basis powers.*)\nLemma horner_mx_mem p : (horner_mx A p \\in Ad)%MS.\n\n(*This definition describes a function that serves as the inverse of the Horner evaluation map on the space spanned by the powers of a matrix `A`. It takes a matrix `B` from this space and computes the unique polynomial of degree less than the minimal polynomial degree which evaluates to `B`.*)\nDefinition mx_inv_horner B := rVpoly (mxvec B *m pinvmx Ad).\n\n(*This lemma states that applying the inverse Horner evaluation function to the zero matrix yields the zero polynomial.*)\nLemma mx_inv_horner0 : mx_inv_horner 0 = 0.\n\n(*This lemma serves as a cancellation property, stating that if a matrix `B` lies in the span of the basis powers of matrix `A`, applying the inverse Horner evaluation to `B` and then evaluating the resulting polynomial at `A` returns the original matrix `B`.*)\nLemma mx_inv_hornerK B : (B \\in Ad)%MS -> horner_mx A (mx_inv_horner B) = B.\n\n(*This lemma asserts that the set of matrices spanned by the basis powers of matrix `A` is closed under matrix multiplication. In other words, the product of any two matrices in this set also belongs to the set.*)\nLemma minpoly_mxM B C : (B \\in Ad -> C \\in Ad -> B * C \\in Ad)%MS.\n\n(*This lemma asserts that the set of matrices spanned by the basis powers of a matrix `A` up to one less than the minimal polynomial degree forms a ring structure under standard matrix addition and multiplication.*)\nLemma minpoly_mx_ring : mxring Ad.\n\n(*This definition provides a constructive formula for the minimal polynomial of a matrix. It is defined as the monic polynomial of degree `d` that annihilates the matrix, constructed from the polynomial `X` to the power `d` minus the polynomial representation of the matrix raised to the power `d`.*)\nDefinition mxminpoly := 'X^d - mx_inv_horner (A ^+ d).\n(*This notation provides a shorthand for the minimal polynomial of a given square matrix.*)\nLocal Notation p_A := mxminpoly.\n\n(*This lemma states that the size of the minimal polynomial of a matrix, which corresponds to the number of its coefficients, is equal to the degree of that polynomial plus one.*)\nLemma size_mxminpoly : size p_A = d.+1.\n\n(*This lemma states that the minimal polynomial of a matrix is a monic polynomial, meaning its leading coefficient is one.*)\nLemma mxminpoly_monic : p_A \\is monic.\n\n(*This lemma states that for any polynomial, its remainder when divided by the minimal polynomial of a matrix will have a degree strictly less than the degree of that minimal polynomial.*)\nLemma size_mod_mxminpoly p : size (p %% p_A) <= d.\n\n(*This lemma states that a matrix is a root of its own minimal polynomial, meaning that substituting the matrix into its minimal polynomial yields the zero matrix.*)\nLemma mx_root_minpoly : horner_mx A p_A = 0.\n\n(*This lemma states that the process of converting a matrix expression, which results from evaluating a polynomial at a given matrix, back into a polynomial is the inverse of the evaluation map for polynomials of a specific bounded degree. Specifically, if a polynomial is formed from a row vector and evaluated at the matrix, the inverse Horner evaluation on the resulting matrix recovers the original polynomial.*)\nLemma horner_rVpolyK (u : 'rV_d) :\n mx_inv_horner (horner_mx A (rVpoly u)) = rVpoly u.\n\n(*This lemma states that for any polynomial and a given matrix, if the polynomial is evaluated at the matrix and the resulting matrix is then converted back to a polynomial representation, the result is the remainder of the original polynomial after division by the matrix's minimal polynomial.*)\nLemma horner_mxK p : mx_inv_horner (horner_mx A p) = p %% p_A.\n\n(*This lemma states that if a polynomial evaluates to the zero matrix when a given matrix is substituted for its variable, then the minimal polynomial of that matrix must divide that polynomial.*)\nLemma mxminpoly_min p : horner_mx A p = 0 -> p_A %| p.\n\n(*This lemma provides a logical equivalence, stating that a polynomial evaluates to the zero matrix when a given matrix is substituted for its variable if and only if the minimal polynomial of that matrix divides that polynomial.*)\nLemma mxminpoly_minP p : reflect (horner_mx A p = 0) (p_A %| p).\n\n(*This lemma states that the boolean result of testing whether a matrix's minimal polynomial divides a given polynomial is equal to the boolean result of testing whether that given polynomial evaluates to the zero matrix when the matrix is substituted.*)\nLemma dvd_mxminpoly p : (p_A %| p) = (horner_mx A p == 0).\n\n(*This lemma states that the function that first converts a row vector into a polynomial and then evaluates this polynomial at a given matrix is an injective mapping from the space of row vectors to the space of matrices.*)\nLemma horner_rVpoly_inj : injective (horner_mx A \\o rVpoly : 'rV_d -> 'M_n).\n\n(*This lemma states that a matrix's minimal polynomial has a degree of one or less if and only if the matrix is a scalar matrix, expressing this equivalence as a boolean equality.*)\nLemma mxminpoly_linear_is_scalar : (d <= 1) = is_scalar_mx A.\n\n(*This lemma states that the minimal polynomial of a matrix divides the characteristic polynomial of that same matrix.*)\nLemma mxminpoly_dvd_char : p_A %| char_poly A.\n\n(*This lemma states that a scalar value is an eigenvalue of a matrix if and only if it is a root of that matrix's minimal polynomial, with this equivalence expressed as a boolean equality.*)\nLemma eigenvalue_root_min a : eigenvalue A a = root p_A a.\n\n(*This lemma states that a scalar value is a root of a matrix's minimal polynomial if and only if it is also a root of that matrix's characteristic polynomial, with this equivalence expressed as a boolean equality.*)\nLemma root_mxminpoly a : root p_A a = root (char_poly A) a.\n\nEnd MinPoly.\n\n(*This lemma provides an explicit formula for the minimal polynomial of a diagonal matrix, stating that it is the product of linear factors of the form (X minus r), where each r is a distinct diagonal entry of the matrix.*)\nLemma mxminpoly_diag {F : fieldType} {n} (d : 'rV[F]_n.+1)\n (u := undup [seq d 0 i | i <- enum 'I_n.+1]) :\n mxminpoly (diag_mx d) = \\prod_(r <- u) ('X - r%:P).\n\nPrenex Implicits degree_mxminpoly mxminpoly mx_inv_horner.\n\nArguments mx_inv_hornerK {F n' A} [B] AnB.\nArguments horner_rVpoly_inj {F n' A} [u1 u2] eq_u12A : rename.\n\nSection MapRingMatrix.\n\nVariables (aR rR : nzRingType) (f : {rmorphism aR -> rR}).\n(*A notation for applying a given ring homomorphism to every entry of a matrix, resulting in a new matrix whose entries are in the target ring of the homomorphism.*)\nLocal Notation \"A ^f\" := (map_mx (GRing.RMorphism.sort f) A) : ring_scope.\n(*This notation provides a shorthand for the function that applies a ring homomorphism to each coefficient of a polynomial, yielding a new polynomial whose coefficients are in the target ring of the homomorphism.*)\nLocal Notation fp := (map_poly (GRing.RMorphism.sort f)).\nVariables (d n : nat) (A : 'M[aR]_n).\n\n(*This lemma states that applying a ring homomorphism to the coefficients of a polynomial that was generated from a row vector is equivalent to first applying the homomorphism to each entry of the row vector and then generating a polynomial from the transformed vector.*)\nLemma map_rVpoly (u : 'rV_d) : fp (rVpoly u) = rVpoly u^f.\n\n(*This lemma states that applying a ring homomorphism to each entry of the row vector formed from a polynomial's coefficients yields the same result as first applying the homomorphism to the polynomial's coefficients and then forming a row vector from the transformed polynomial.*)\nLemma map_poly_rV p : (poly_rV p)^f = poly_rV (fp p) :> 'rV_d.\n\n(*This lemma states that the operation of forming a characteristic matrix commutes with the application of a ring homomorphism to the matrix entries. Specifically, applying a homomorphism-induced polynomial map to the characteristic matrix gives the characteristic matrix of the homomorphically-mapped original matrix.*)\nLemma map_char_poly_mx : map_mx fp (char_poly_mx A) = char_poly_mx A^f.\n\n(*This lemma states that applying a ring homomorphism to the coefficients of a matrix's characteristic polynomial results in the characteristic polynomial of the matrix obtained by applying that same homomorphism to each of the original matrix's entries.*)\nLemma map_char_poly : fp (char_poly A) = char_poly A^f.\n\nEnd MapRingMatrix.\n\nSection MapResultant.\n\n(*This lemma states that for any two polynomials and a ring homomorphism, the homomorphism applied to the resultant of these polynomials is equal to the resultant of the polynomials that have been transformed by the homomorphism. This property holds under the condition that the leading coefficients of the original polynomials are not mapped to zero by the homomorphism.*)\nLemma map_resultant (aR rR : nzRingType) (f : {rmorphism {poly aR} -> rR}) p q :\n f (lead_coef p) != 0 -> f (lead_coef q) != 0 ->\n f (resultant p q)= resultant (map_poly f p) (map_poly f q).\n\nEnd MapResultant.\n\nSection MapComRing.\n\nVariables (aR rR : comNzRingType) (f : {rmorphism aR -> rR}).\n(**)\nLocal Notation \"A ^f\" := (map_mx f A) : ring_scope.\n(*This local notation defines `fp` as a function that converts a polynomial from one ring to another by applying a given ring morphism, `f`, to each of the polynomial's coefficients.*)\nLocal Notation fp := (map_poly f).\nVariables (n' : nat) (A : 'M[aR]_n'.+1).\n\n(*This lemma states that applying a ring morphism element-wise to the matrix that results from raising a base matrix to a natural number exponent yields the same result as first applying the morphism to the base matrix and then raising the resulting matrix to that same exponent.*)\nLemma map_powers_mx e : (powers_mx A e)^f = powers_mx A^f e.\n\n(*This lemma states that applying a ring morphism element-wise to the matrix resulting from evaluating a polynomial at a given matrix is equivalent to evaluating a new polynomial\u2014whose coefficients are the images of the original polynomial's coefficients under the morphism\u2014at a new matrix that is the image of the original matrix under the same morphism.*)\nLemma map_horner_mx p : (horner_mx A p)^f = horner_mx A^f (fp p).\n\nEnd MapComRing.\n\nSection MapField.\n\nVariables (aF rF : fieldType) (f : {rmorphism aF -> rF}).\n(*This notation represents the element-wise application of a ring morphism to a matrix. The resulting matrix has the same dimensions, with each entry being the image of the corresponding entry in the original matrix under the given morphism.*)\nLocal Notation \"A ^f\" := (map_mx f A) : ring_scope.\n(*This notation defines a function that transforms a polynomial by applying a given ring morphism to each of its coefficients, resulting in a new polynomial over the target ring of the morphism.*)\nLocal Notation fp := (map_poly f).\nVariables (n' : nat) (A : 'M[aF]_n'.+1) (p : {poly aF}).\n\n(*This lemma states that applying a ring morphism to the entries of the companion matrix of a polynomial is equivalent, up to a matrix size cast, to computing the companion matrix of the polynomial whose coefficients have been transformed by the same morphism.*)\nLemma map_mx_companion (e := congr1 predn (size_map_poly _ _)) :\n (companionmx p)^f = castmx (e, e) (companionmx (fp p)).\n\n(*This lemma states that the companion matrix of a polynomial whose coefficients have been transformed by a ring morphism is equivalent, up to a matrix size cast, to the matrix resulting from applying the same morphism to the entries of the original polynomial's companion matrix.*)\nLemma companion_map_poly (e := esym (congr1 predn (size_map_poly _ _))) :\n companionmx (fp p) = castmx (e, e) (companionmx p)^f.\n\n(*This lemma states that the degree of the minimal polynomial of a matrix remains unchanged after applying a field morphism to the matrix's entries.*)\nLemma degree_mxminpoly_map : degree_mxminpoly A^f = degree_mxminpoly A.\n\n(*This lemma states that the minimal polynomial of a matrix transformed by a field morphism is equal to the polynomial obtained by applying that same morphism to the coefficients of the original matrix's minimal polynomial.*)\nLemma mxminpoly_map : mxminpoly A^f = fp (mxminpoly A).\n\n(*This lemma states that applying a field morphism to the coefficients of the polynomial generated by the inverse Horner evaluation of a matrix and a vector yields the same result as performing the inverse Horner evaluation with the transformed matrix and transformed vector.*)\nLemma map_mx_inv_horner u : fp (mx_inv_horner A u) = mx_inv_horner A^f u^f.\n\nEnd MapField.\n\nSection KernelLemmas.\n\nVariable K : fieldType.\n\n(*This definition gives the kernel of a matrix polynomial, which is the subspace of vectors that are mapped to zero when the polynomial is evaluated at the given matrix. The result is returned as a projection matrix onto this kernel subspace.*)\nDefinition kermxpoly n (g : 'M_n) (p : {poly K}) : 'M_n :=\n kermx ((if n is n.+1 then horner_mx^~ p : 'M_n.+1 -> 'M_n.+1 else \\0) g).\n\n(*This lemma states that the kernel of a non-zero constant polynomial evaluated at any square matrix is the zero subspace, which is represented by the zero matrix.*)\nLemma kermxpolyC n (g : 'M_n) c : c != 0 -> kermxpoly g c%:P = 0.\n\n(*This lemma states that the kernel of the constant polynomial with value one, when evaluated at any square matrix, is the zero subspace, represented by the zero matrix.*)\nLemma kermxpoly1 n (g : 'M_n) : kermxpoly g 1 = 0.\n\n(*This lemma states that the kernel of the indeterminate polynomial evaluated at a given matrix is identical to the kernel of the matrix itself.*)\nLemma kermxpolyX n (g : 'M_n) : kermxpoly g 'X = kermx g.\n\n(*This lemma states that if the minimal polynomial of a matrix divides another polynomial, then the kernel of this second polynomial evaluated at the matrix is the entire vector space, and its corresponding projection matrix is the identity matrix.*)\nLemma kermxpoly_min n (g : 'M[K]_n.+1) p :\n mxminpoly g %| p -> (kermxpoly g p :=: 1)%MS.\n\n(*This lemma states that if two square matrices commute, then the kernel of any polynomial evaluated at the first matrix forms a subspace that is stable under the linear transformation represented by the second matrix.*)\nLemma comm_mx_stable_kermxpoly n (f g : 'M_n) (p : {poly K}) : comm_mx f g ->\n stablemx (kermxpoly f p) g.\n\n(*This lemma states that for any given matrix, the kernels of two coprime polynomials evaluated at that matrix have an intersection that is only the zero subspace.*)\nLemma mxdirect_kermxpoly n (g : 'M_n) (p q : {poly K}) :\n coprimep p q -> (kermxpoly g p :&: kermxpoly g q = 0)%MS.\n\n(*This lemma states that for any given matrix, the kernel of the product of two coprime polynomials evaluated at that matrix is the direct sum of the kernels of the individual polynomials evaluated at the same matrix.*)\nLemma kermxpolyM n (g : 'M_n) (p q : {poly K}) : coprimep p q ->\n (kermxpoly g (p * q) :=: kermxpoly g p + kermxpoly g q)%MS.\n\n(*This lemma generalizes the kernel decomposition property, stating that for a given matrix, the kernel of a product of a family of pairwise coprime polynomials is the direct sum of the kernels of the individual polynomials in that family.*)\nLemma kermxpoly_prod n (g : 'M_n)\n (I : finType) (P : {pred I}) (p_ : I -> {poly K}) :\n {in P &, forall i j, j != i -> coprimep (p_ i) (p_ j)} ->\n (kermxpoly g (\\prod_(i | P i) p_ i) :=: \\sum_(i | P i) kermxpoly g (p_ i))%MS.\n\n(*This lemma asserts that the sum of the projection matrices corresponding to the kernels of a family of pairwise coprime polynomials is a projection for a direct sum, meaning the underlying subspaces are in direct sum.*)\nLemma mxdirect_sum_kermx n (g : 'M_n)\n (I : finType) (P : {pred I}) (p_ : I -> {poly K}) :\n {in P &, forall i j, j != i -> coprimep (p_ i) (p_ j)} ->\n mxdirect (\\sum_(i | P i) kermxpoly g (p_ i))%MS.\n\n(*This lemma provides an identity for the eigenspace of a matrix corresponding to a scalar value, stating that it is equivalent to the kernel of the polynomial 'X minus the scalar' evaluated at the matrix.*)\nLemma eigenspace_poly n a (f : 'M_n) :\n eigenspace f a = kermxpoly f ('X - a%:P).\n\n(*This definition specifies the generalized eigenspace of a matrix for a given scalar value as the kernel of the polynomial '(X minus the scalar) to the power of the matrix dimension' evaluated at that matrix.*)\nDefinition geigenspace n (g : 'M_n) a := kermxpoly g (('X - a%:P) ^+ n).\n\n(*This lemma provides an explicit characterization of the generalized eigenspace of a matrix for a given scalar, defining it as the kernel of the matrix obtained by subtracting the scalar multiple of the identity matrix from the original matrix and raising the result to the power of the matrix dimension.*)\nLemma geigenspaceE n' (g : 'M_n'.+1) a :\n geigenspace g a = kermx ((g - a%:M) ^+ n'.+1).\n\n(*This lemma asserts that for any matrix and any scalar, the eigenspace associated with that scalar is a subspace of the corresponding generalized eigenspace.*)\nLemma eigenspace_sub_geigen n (g : 'M_n) a :\n (eigenspace g a <= geigenspace g a)%MS.\n\n(*This lemma states that the sum of the generalized eigenspaces corresponding to a set of distinct eigenvalues of a matrix forms a direct sum of subspaces.*)\nLemma mxdirect_sum_geigenspace\n (I : finType) (n : nat) (g : 'M_n) (P : {pred I}) (a_ : I -> K) :\n {in P &, injective a_} -> mxdirect (\\sum_(i | P i) geigenspace g (a_ i)).\n\n(*This definition establishes a predicate to identify an eigenpolynomial of a matrix, which is any polynomial for which its evaluation at the matrix results in a linear map with a non-trivial kernel.*)\nDefinition eigenpoly n (g : 'M_n) : pred {poly K} :=\n (fun p => kermxpoly g p != 0).\n\n(*This lemma provides a practical test for the eigenpolynomial predicate, stating that a polynomial is an eigenpolynomial of a matrix if and only if there exists a non-zero vector in the kernel of the polynomial evaluated at that matrix.*)\nLemma eigenpolyP n (g : 'M_n) (p : {poly K}) :\n reflect (exists2 v : 'rV_n, (v <= kermxpoly g p)%MS & v != 0) (eigenpoly g p).\n\n(*This lemma establishes the equivalence between the concept of an eigenvalue and an eigenpolynomial, stating that a scalar is an eigenvalue of a matrix if and only if the polynomial 'X minus the scalar' is an eigenpolynomial of that matrix.*)\nLemma eigenvalue_poly n a (f : 'M_n) : eigenvalue f a = eigenpoly f ('X - a%:P).\n\n(*This lemma states that if two square matrices commute, the generalized eigenspace of the first matrix is a stable subspace under the linear transformation represented by the second matrix.*)\nLemma comm_mx_stable_geigenspace n (f g : 'M_n) a : comm_mx f g ->\n stablemx (geigenspace f a) g.\n\nEnd KernelLemmas.\n\nSection MapKermxPoly.\nVariables (aF rF : fieldType) (f : {rmorphism aF -> rF}).\n\n(*This lemma demonstrates the compatibility of the kernel of a matrix polynomial with a field morphism. It states that applying the morphism to the projection matrix of a kernel is equivalent to computing the kernel for the morphism-applied polynomial and matrix.*)\nLemma map_kermxpoly (n : nat) (g : 'M_n) (p : {poly aF}) :\n map_mx f (kermxpoly g p) = kermxpoly (map_mx f g) (map_poly f p).\n\n(*This lemma shows how a generalized eigenspace transforms under a field morphism. It asserts that applying the morphism to the projection matrix for a generalized eigenspace yields the generalized eigenspace corresponding to the transformed matrix and transformed scalar.*)\nLemma map_geigenspace (n : nat) (g : 'M_n) (a : aF) :\n map_mx f (geigenspace g a) = geigenspace (map_mx f g) (f a).\n\n(*This lemma states that the property of a polynomial being an eigenpolynomial for a matrix is preserved by a field morphism. The transformed polynomial is an eigenpolynomial for the transformed matrix if and only if the original was.*)\nLemma eigenpoly_map n (g : 'M_n) (p : {poly aF}) :\n eigenpoly (map_mx f g) (map_poly f p) = eigenpoly g p.\n\nEnd MapKermxPoly.\n\nSection IntegralOverRing.\n\n(*This definition specifies the property of an element in a larger ring being integral over a subring. An element is considered integral if it is a root of some monic polynomial whose coefficients all belong to the subring.*)\nDefinition integralOver (R K : nzRingType) (RtoK : R -> K) (z : K) :=\n exists2 p, p \\is monic & root (map_poly RtoK p) z.\n\n(*This definition specifies the property of an integral extension, which holds if every element of a given ring is integral over a specified subring.*)\nDefinition integralRange R K RtoK := forall z, @integralOver R K RtoK z.\n\nVariables (B R K : nzRingType) (BtoR : B -> R) (RtoK : {rmorphism R -> K}).\n\n(*This lemma states that for three rings with morphisms between them, if an element of the intermediate ring is integral over the initial ring, then its image in the final ring is also integral over the initial ring via the composed morphism.*)\nLemma integral_rmorph x :\n integralOver BtoR x -> integralOver (RtoK \\o BtoR) (RtoK x).\n\n(*This lemma states that for a ring morphism from a ring R to a ring K, the image of any element of R within K is integral over R.*)\nLemma integral_id x : integralOver RtoK (RtoK x).\n\n(*This lemma states that any natural number, when viewed as an element of a ring via its canonical embedding, is integral over any specified subring.*)\nLemma integral_nat n : integralOver RtoK n%:R.\n\n(*This lemma states that the zero element of a ring is always integral over any of its subrings.*)\nLemma integral0 : integralOver RtoK 0. \n\n(*This lemma states that the multiplicative identity element of a ring is always integral over any of its subrings.*)\nLemma integral1 : integralOver RtoK 1. \n\n(*This lemma establishes an equivalence, stating that a polynomial's sequence of coefficients is considered an integral range if and only if each coefficient is individually an integral element over a given subring.*)\nLemma integral_poly (p : {poly K}) :\n (forall i, integralOver RtoK p`_i) <-> {in p : seq K, integralRange RtoK}.\n\nEnd IntegralOverRing.\n\nSection IntegralOverComRing.\n\nVariables (R K : comNzRingType) (RtoK : {rmorphism R -> K}).\n\n(*This lemma states that if a value is a root of a monic polynomial with integral coefficients, then applying another polynomial, which also has integral coefficients, to this value results in an integral element.*)\nLemma integral_horner_root w (p q : {poly K}) :\n p \\is monic -> root p w ->\n {in p : seq K, integralRange RtoK} -> {in q : seq K, integralRange RtoK} ->\n integralOver RtoK q.[w].\n\n(*This lemma asserts that any root of a monic polynomial whose coefficients are all integral over a given subring is itself an integral element over that subring.*)\nLemma integral_root_monic u p :\n p \\is monic -> root p u -> {in p : seq K, integralRange RtoK} ->\n integralOver RtoK u.\n\n(*This definition re-states the fact that the zero element is integral over a subring, intended for use by the proof assistant's automated tactics.*)\nLet integral0_RtoK := integral0 RtoK.\n(*This definition re-states the fact that the multiplicative identity is integral over a subring, intended for use by the proof assistant's automated tactics.*)\nLet integral1_RtoK := integral1 RtoK.\n(*This definition provides a proof that any polynomial of the form 'X minus a constant' is monic, for use by the proof assistant's automated tactics.*)\nLet monicXsubC_K := @monicXsubC K.\nHint Resolve integral0_RtoK integral1_RtoK monicXsubC_K : core.\n\n(*This lemma states that any ring element is a root of the polynomial 'X minus that element'.*)\nLet XsubC0 (u : K) : root ('X - u%:P) u. \n(*This lemma states that if the additive inverse of a ring element is integral over a subring, then the polynomial 'X minus that element' has all its coefficients integral over that same subring.*)\nLet intR_XsubC u :\n integralOver RtoK (- u) -> {in 'X - u%:P : seq K, integralRange RtoK}.\n\n(*This lemma states that if a ring element is integral over a subring, its additive inverse is also integral over that subring.*)\nLemma integral_opp u : integralOver RtoK u -> integralOver RtoK (- u).\n\n(*This lemma states that evaluating a polynomial with integral coefficients at an integral element yields a result that is also an integral element.*)\nLemma integral_horner (p : {poly K}) u :\n {in p : seq K, integralRange RtoK} -> integralOver RtoK u ->\n integralOver RtoK p.[u].\n\n(*This lemma states that the difference of two elements that are integral over a subring is also integral over that subring.*)\nLemma integral_sub u v :\n integralOver RtoK u -> integralOver RtoK v -> integralOver RtoK (u - v).\n\n(*This lemma states that the sum of two elements that are integral over a subring is also integral over that subring.*)\nLemma integral_add u v :\n integralOver RtoK u -> integralOver RtoK v -> integralOver RtoK (u + v).\n\n(*This lemma states that the product of two elements that are integral over a subring is also integral over that subring.*)\nLemma integral_mul u v :\n integralOver RtoK u -> integralOver RtoK v -> integralOver RtoK (u * v).\n\nEnd IntegralOverComRing.\n\nSection IntegralOverField.\n\nVariables (F E : fieldType) (FtoE : {rmorphism F -> E}).\n\n(*This definition describes an element of a field as being algebraic over a subfield if it is a root of some non-zero polynomial whose coefficients are from that subfield.*)\nDefinition algebraicOver (fFtoE : F -> E) u :=\n exists2 p, p != 0 & root (map_poly fFtoE p) u.\n\nNotation mk_mon p := ((lead_coef p)^-1 *: p).\n\n(*This lemma states that for an element in a field extension, being algebraic over a subfield is equivalent to being integral over that subfield.*)\nLemma integral_algebraic u : algebraicOver FtoE u <-> integralOver FtoE u.\n\n(*This lemma states that for a field morphism from a field F to a field E, the image of any element from F is algebraic over F.*)\nLemma algebraic_id a : algebraicOver FtoE (FtoE a).\n\n(*This lemma states that the zero element of a field is always algebraic over any of its subfields.*)\nLemma algebraic0 : algebraicOver FtoE 0.\n\n(*This lemma states that the multiplicative identity of a field is always algebraic over any of its subfields.*)\nLemma algebraic1 : algebraicOver FtoE 1.\n\n(*This lemma states that if a field element is algebraic over a subfield, its additive inverse is also algebraic over that subfield.*)\nLemma algebraic_opp x : algebraicOver FtoE x -> algebraicOver FtoE (- x).\n\n(*This lemma states that the sum of two elements that are algebraic over a subfield is also algebraic over that subfield.*)\nLemma algebraic_add x y :\n algebraicOver FtoE x -> algebraicOver FtoE y -> algebraicOver FtoE (x + y).\n\n(*This lemma states that the difference of two elements that are algebraic over a subfield is also algebraic over that subfield.*)\nLemma algebraic_sub x y :\n algebraicOver FtoE x -> algebraicOver FtoE y -> algebraicOver FtoE (x - y).\n\n(*This lemma states that the product of two elements that are algebraic over a subfield is also algebraic over that subfield.*)\nLemma algebraic_mul x y :\n algebraicOver FtoE x -> algebraicOver FtoE y -> algebraicOver FtoE (x * y).\n\n(*This lemma states that if a non-zero element is algebraic over a subfield, its multiplicative inverse is also algebraic over that subfield.*)\nLemma algebraic_inv u : algebraicOver FtoE u -> algebraicOver FtoE u^-1.\n\n(*This lemma states that the quotient of two elements that are algebraic over a subfield is also algebraic over that subfield, provided the denominator is non-zero.*)\nLemma algebraic_div x y :\n algebraicOver FtoE x -> algebraicOver FtoE y -> algebraicOver FtoE (x / y).\n\n(*This lemma states that for a given field extension, if an element is integral, then its multiplicative inverse is also integral.*)\nLemma integral_inv x : integralOver FtoE x -> integralOver FtoE x^-1.\n\n(*This lemma states that for a given field extension, if two elements are both integral, then their quotient is also integral.*)\nLemma integral_div x y :\n integralOver FtoE x -> integralOver FtoE y -> integralOver FtoE (x / y).\n\n(*This lemma states that if a field element is a root of a non-zero polynomial whose coefficients are all integral over a given field extension, then that element is itself integral over the same field extension.*)\nLemma integral_root p u :\n p != 0 -> root p u -> {in p : seq E, integralRange FtoE} ->\n integralOver FtoE u.\n\nEnd IntegralOverField.\n\nModule MatrixFormula.\n\nSection MatrixFormula.\n\nVariable F : fieldType.\n\n(*This notation represents the logical constant for falsehood within the language of ring formulas.*)\nLocal Notation False := GRing.False.\n(*This notation represents the logical constant for truth within the language of ring formulas.*)\nLocal Notation True := GRing.True.\n(*This notation represents the logical conjunction, or 'and' operation, between two ring formulas.*)\nLocal Notation And := GRing.And (only parsing).\n(*This notation represents the addition operation between two ring terms.*)\nLocal Notation Add := GRing.Add (only parsing).\nLocal Notation Bool b := (GRing.Bool b%bool).\n(*This notation represents the type for terms, which are formal polynomial expressions over a specified field, within the language of ring formulas.*)\nLocal Notation term := (GRing.term F).\n(*This notation represents the type for formulas, which are logical statements about terms, within the language of ring formulas.*)\nLocal Notation form := (GRing.formula F).\n(*This notation represents the evaluation function, which computes the value of a ring term or a ring formula in a given environment that assigns values to variables.*)\nLocal Notation eval := GRing.eval.\n(*This notation represents the predicate asserting that a ring formula is true for all possible environments, meaning it is universally valid.*)\nLocal Notation holds := GRing.holds.\n(*This notation represents the predicate asserting that a given ring formula is quantifier-free.*)\nLocal Notation qf_form := GRing.qf_form.\n(*This notation represents the evaluation function specifically for quantifier-free ring formulas, which computes the truth value of a formula in a given environment.*)\nLocal Notation qf_eval := GRing.qf_eval.\n\n(*This definition describes a function that evaluates a matrix of ring terms by applying the term evaluation function to each entry, given an environment mapping variables to field elements, resulting in a matrix of field elements.*)\nDefinition eval_mx (e : seq F) := @map_mx term F (eval e).\n\n(*This definition describes a function that converts a matrix of field elements into a matrix of constant ring terms.*)\nDefinition mx_term := @map_mx F term GRing.Const.\n\n(*This lemma states that converting a matrix of field elements to a matrix of constant terms and then evaluating it with any environment yields the original matrix of field elements.*)\nLemma eval_mx_term e m n (A : 'M_(m, n)) : eval_mx e (mx_term A) = A.\n\n(*This definition describes the symbolic multiplication of a matrix of ring terms by a matrix of field elements, producing a new matrix where each entry is a ring term representing the corresponding dot product.*)\nDefinition mulmx_term m n p (A : 'M[term]_(m, n)) (B : 'M_(n, p)) :=\n \\matrix_(i, k) (\\big[Add/0]_j (A i j * B j k))%T.\n\n(*This lemma states that evaluating the symbolic product of a matrix of terms and a matrix of field elements is equivalent to first evaluating the matrix of terms and then performing the standard matrix multiplication.*)\nLemma eval_mulmx e m n p (A : 'M[term]_(m, n)) (B : 'M_(n, p)) :\n eval_mx e (mulmx_term A B) = eval_mx e A *m eval_mx e B.\n\nLocal Notation morphAnd f := ((big_morph f) true andb).\n\n(*This definition computes the Schur complement of a matrix of ring terms with respect to its top-left entry, yielding a new, smaller matrix of ring terms.*)\nLet Schur m n (A : 'M[term]_(1 + m, 1 + n)) (a := A 0 0) :=\n \\matrix_(i, j) (drsubmx A i j - a^-1 * dlsubmx A i 0%R * ursubmx A 0%R j)%T.\n\n(*This definition recursively constructs a logical formula that is true if and only if a given matrix of terms has a specified rank. The formula is built using symbolic operations like the Schur complement.*)\nFixpoint mxrank_form (r m n : nat) : 'M_(m, n) -> form :=\n match m, n return 'M_(m, n) -> form with\n | m'.+1, n'.+1 => fun A : 'M_(1 + m', 1 + n') =>\n let nzA k := A k.1 k.2 != 0 in\n let xSchur k := Schur (xrow k.1 0%R (xcol k.2 0%R A)) in\n let recf k := Bool (r > 0) /\\ mxrank_form r.-1 (xSchur k) in\n GRing.Pick nzA recf (Bool (r == 0%N))\n | _, _ => fun _ => Bool (r == 0%N)\n end%T.\n\n(*This lemma states that the logical formula generated to represent the rank condition of a matrix is always quantifier-free.*)\nLemma mxrank_form_qf r m n (A : 'M_(m, n)) : qf_form (mxrank_form r A).\n\n(*This lemma states that evaluating the logical formula for the rank of a matrix of terms with a given environment yields true if and only if the rank of the resulting evaluated matrix is equal to the specified rank.*)\nLemma eval_mxrank e r m n (A : 'M_(m, n)) :\n qf_eval e (mxrank_form r A) = (\\rank (eval_mx e A) == r).\n\n(*This lemma states that evaluating a matrix that was constructed by reshaping a vector of terms is equivalent to first evaluating the vector of terms and then reshaping the resulting vector of field elements into a matrix.*)\nLemma eval_vec_mx e m n (u : 'rV_(m * n)) :\n eval_mx e (vec_mx u) = vec_mx (eval_mx e u).\n\n(*This lemma states that evaluating a vector that was created by flattening a matrix of terms is equivalent to first evaluating the matrix of terms and then flattening the resulting matrix of field elements into a vector.*)\nLemma eval_mxvec e m n (A : 'M_(m, n)) :\n eval_mx e (mxvec A) = mxvec (eval_mx e A).\n\nSection Subsetmx.\n\nVariables (m1 m2 n : nat) (A : 'M[term]_(m1, n)) (B : 'M[term]_(m2, n)).\n\n(*This definition constructs a logical formula that expresses the condition that the row space of a first matrix of terms is a subspace of the row space of a second matrix of terms, by comparing their ranks.*)\nDefinition submx_form :=\n \\big[And/True]_(r < n.+1) (mxrank_form r (col_mx A B) ==> mxrank_form r B)%T.\n\n(*This lemma states that evaluating the vertical concatenation of two term matrices is equivalent to first evaluating each matrix individually and then concatenating the two resulting matrices of field elements.*)\nLemma eval_col_mx e :\n eval_mx e (col_mx A B) = col_mx (eval_mx e A) (eval_mx e B).\n\n(*This lemma states that the logical formula expressing the row space inclusion relationship between two matrices is quantifier-free.*)\nLemma submx_form_qf : qf_form submx_form.\n\n(*This lemma states that evaluating the logical formula for row space inclusion with a given environment is equivalent to checking if the row space of the evaluated first matrix is a subspace of the row space of the evaluated second matrix.*)\nLemma eval_submx e : qf_eval e submx_form = (eval_mx e A <= eval_mx e B)%MS.\n\nEnd Subsetmx.\n\nSection Env.\n\nVariable d : nat.\n\n(*This definition describes a function that converts a row vector of field elements into a sequence of the same field elements.*)\nDefinition seq_of_rV (v : 'rV_d) : seq F := fgraph [ffun i => v 0 i].\n\n(*This lemma states that the length of a sequence created from a row vector is equal to the dimension of that vector.*)\nLemma size_seq_of_rV v : size (seq_of_rV v) = d.\n\n(*This lemma states that retrieving the element at a given index from a sequence created from a row vector is equivalent to accessing the element at that same column index in the original row vector.*)\nLemma nth_seq_of_rV x0 v (i : 'I_d) : nth x0 (seq_of_rV v) i = v 0 i.\n\n(*This definition constructs a row vector of formal variables, where the entry at a given column index is a variable whose own index is computed from a base natural number and the column index.*)\nDefinition row_var k : 'rV[term]_d := \\row_i ('X_(k * d + i))%T.\n\n(*This definition creates a flat sequence of values by concatenating the sequences corresponding to each row vector in a given sequence of row vectors.*)\nDefinition row_env (e : seq 'rV_d) := flatten (map seq_of_rV e).\n\n(*This lemma states that accessing an element in a flattened environment at an index computed from two natural numbers is equivalent to accessing the element in the corresponding row vector at the specified column from the original sequence of row vectors.*)\nLemma nth_row_env e k (i : 'I_d) : (row_env e)`_(k * d + i) = e`_k 0 i.\n\n(*This lemma states that evaluating a formal row of variables using an environment constructed from a sequence of row vectors results in the corresponding row vector from that sequence.*)\nLemma eval_row_var e k : eval_mx (row_env e) (row_var k) = e`_k :> 'rV_d.\n\n(*This definition constructs a new logical formula by applying existential quantification to an existing formula for each variable index corresponding to a specific row.*)\nDefinition Exists_row_form k (f : form) :=\n foldr GRing.Exists f (codom (fun i : 'I_d => k * d + i)%N).\n\n(*This lemma states that, for a positive dimension, the existence of a row vector that makes a formula true when substituted into an environment is equivalent to the formula with its corresponding row variables existentially quantified being true in the original environment.*)\nLemma Exists_rowP e k f :\n d > 0 ->\n ((exists v : 'rV[F]_d, holds (row_env (set_nth 0 e k v)) f)\n <-> holds (row_env e) (Exists_row_form k f)).\n\nEnd Env.\n\nEnd MatrixFormula.\n\nEnd MatrixFormula.\n\nSection ConjMx.\nContext {F : fieldType}.\n\n(*This definition computes the conjugation of a square matrix by another matrix, defined as the product of the second matrix, the square matrix, and the Moore-Penrose pseudo-inverse of the second matrix.*)\nDefinition conjmx (m n : nat)\n (V : 'M_(m, n)) (f : 'M[F]_n) : 'M_m := V *m f *m pinvmx V.\nNotation restrictmx V := (conjmx (row_base V)).\n\n(*This lemma states that if the column space of a second matrix is stable under a given square matrix, and the column space of a first matrix is stable under the conjugation of the square matrix by the second matrix, then the column space of the product of the first and second matrices is stable under the original square matrix.*)\nLemma stablemx_comp (m n p : nat) (V : 'M[F]_(m, n)) (W : 'M_(n, p)) (f : 'M_p) :\n stablemx W f -> stablemx V (conjmx W f) -> stablemx (V *m W) f.\n\n(*This lemma states that if the row space of a given matrix is stable under a square matrix, then the stability of a third matrix's column space under the restricted operator is equivalent to the stability of the column space of the product of the third matrix and a basis for the row space of the given matrix under the original square matrix.*)\nLemma stablemx_restrict m n (A : 'M[F]_n) (V : 'M_n) (W : 'M_(m, \\rank V)):\n stablemx V A -> stablemx W (restrictmx V A) = stablemx (W *m row_base V) A.\n\n(*This lemma states that for a given matrix, the conjugation operation is a matrix multiplication morphism on the set of all square matrices that leave the first matrix's column space invariant.*)\nLemma conjmxM (m n : nat) (V : 'M[F]_(m, n)) :\n {in [pred f | stablemx V f] &, {morph conjmx V : f g / f *m g}}.\n\n(*This lemma states that under conditions of row independence and subspace stability, the conjugation of a square matrix by a product of two other matrices is equal to the iterated conjugation, first by the second matrix and then by the first.*)\nLemma conjMmx (m n p : nat) (V : 'M[F]_(m, n)) (W : 'M_(n, p)) (f : 'M_p) :\n row_free (V *m W) -> stablemx W f -> stablemx V (conjmx W f) ->\n conjmx (V *m W) f = conjmx V (conjmx W f).\n\n(*This lemma states that if a square matrix is invertible and a second matrix has linearly independent rows and a column space stable under a third matrix, then the conjugation of the third matrix by the product of the first two is equal to the iterated conjugation.*)\nLemma conjuMmx (m n : nat) (V : 'M[F]_m) (W : 'M_(m, n)) (f : 'M_n) :\n V \\in unitmx -> row_free W -> stablemx W f ->\n conjmx (V *m W) f = conjmx V (conjmx W f).\n\n(*This lemma states that if a square matrix is invertible and a second matrix has linearly independent rows, the conjugation of a third matrix by their product is the same as iterated conjugation, provided the column space of the second matrix is stable under the conjugated third matrix.*)\nLemma conjMumx (m n : nat) (V : 'M[F]_(m, n)) (W f : 'M_n) :\n W \\in unitmx -> row_free V -> stablemx V (conjmx W f) ->\n conjmx (V *m W) f = conjmx V (conjmx W f).\n\n(*This lemma states that for three square matrices where the first two are invertible, the conjugation of the third by their product is equivalent to the iterated conjugation, first by the second matrix and then by the first.*)\nLemma conjuMumx (n : nat) (V W f : 'M[F]_n) :\n V \\in unitmx -> W \\in unitmx ->\n conjmx (V *m W) f = conjmx V (conjmx W f).\n\n(*This lemma states that conjugating a scalar matrix by any matrix with linearly independent rows yields a scalar matrix of the same value, but with dimensions matching the output of the conjugation.*)\nLemma conjmx_scalar (m n : nat) (V : 'M[F]_(m, n)) (a : F) :\n row_free V -> conjmx V a%:M = a%:M.\n\n(*This lemma states that the conjugation of any square matrix by a zero matrix results in a zero matrix.*)\nLemma conj0mx (m n : nat) f : conjmx (0 : 'M[F]_(m, n)) f = 0.\n\n(*This lemma states that the conjugation of a zero matrix by any other matrix results in a zero matrix.*)\nLemma conjmx0 (m n : nat) (V : 'M[F]_(m, n)) : conjmx V 0 = 0.\n\n(*This lemma states that for an invertible square matrix, the conjugation of a second square matrix by it simplifies to the product of the first matrix, the second matrix, and the inverse of the first matrix.*)\nLemma conjumx (n : nat) (V : 'M_n) (f : 'M[F]_n) : V \\in unitmx ->\n conjmx V f = V *m f *m invmx V.\n\n(*This lemma states that conjugating a square matrix by an identity matrix of the same dimension yields the original matrix.*)\nLemma conj1mx (n : nat) (f : 'M[F]_n) : conjmx 1%:M f = f.\n\n(*This lemma states that for an invertible square matrix, the conjugation of another square matrix by its inverse is given by the product of the inverse, the second matrix, and the original invertible matrix.*)\nLemma conjVmx (n : nat) (V : 'M_n) (f : 'M[F]_n) : V \\in unitmx ->\n conjmx (invmx V) f = invmx V *m f *m V.\n\n(*This lemma states that for an invertible square matrix, conjugating a second square matrix by the first and then conjugating the result by the inverse of the first matrix restores the second matrix.*)\nLemma conjmxK (n : nat) (V f : 'M[F]_n) :\n V \\in unitmx -> conjmx (invmx V) (conjmx V f) = f.\n\n(*This lemma states that for an invertible square matrix, conjugating a second square matrix by the inverse of the first and then conjugating the result by the first matrix restores the second matrix.*)\nLemma conjmxVK (n : nat) (V f : 'M[F]_n) :\n V \\in unitmx -> conjmx V (conjmx (invmx V) f) = f.\n\n(*This lemma states that, under conditions of row independence and subspace stability, evaluating a polynomial at a conjugated matrix is equivalent to conjugating the result of evaluating that same polynomial at the original matrix.*)\nLemma horner_mx_conj m n p (V : 'M[F]_(n.+1, m.+1)) (f : 'M_m.+1) :\n row_free V -> stablemx V f ->\n horner_mx (conjmx V f) p = conjmx V (horner_mx f p).\n\n(*This lemma states that for an invertible square matrix, evaluating a polynomial at a similarity transform of a second matrix is equivalent to applying the same similarity transform to the result of evaluating the polynomial at the second matrix.*)\nLemma horner_mx_uconj n p (V : 'M[F]_(n.+1)) (f : 'M_n.+1) :\n V \\is a GRing.unit ->\n horner_mx (V *m f *m invmx V) p = V *m horner_mx f p *m invmx V.\n\n(*This lemma states that for an invertible square matrix, evaluating a polynomial at a matrix transformed by the inverse of the invertible matrix is equivalent to applying the same transformation to the result of evaluating the polynomial at the original matrix.*)\nLemma horner_mx_uconjC n p (V : 'M[F]_(n.+1)) (f : 'M_n.+1) :\n V \\is a GRing.unit ->\n horner_mx (invmx V *m f *m V) p = invmx V *m horner_mx f p *m V.\n\n(*This lemma states that, under conditions of row independence and subspace stability, the minimal polynomial of a conjugated matrix divides the minimal polynomial of the original matrix.*)\nLemma mxminpoly_conj m n (V : 'M[F]_(m.+1, n.+1)) (f : 'M_n.+1) :\n row_free V -> stablemx V f -> mxminpoly (conjmx V f) %| mxminpoly f.\n\n(*This lemma states that for an invertible square matrix, the minimal polynomial of a matrix after a similarity transform is the same as the minimal polynomial of the original matrix.*)\nLemma mxminpoly_uconj n (V : 'M[F]_(n.+1)) (f : 'M_n.+1) :\n V \\in unitmx -> mxminpoly (conjmx V f) = mxminpoly f.\n\nSection fixed_stablemx_space.\n\nVariables (m n : nat).\n\nImplicit Types (V : 'M[F]_(m, n)) (A : 'M[F]_n).\nImplicit Types (a : F) (p : {poly F}).\n\nSection Sub.\nVariable (k : nat).\nImplicit Types (W : 'M[F]_(k, m)).\n\n(*This lemma states that, under conditions of stability and row independence, the property that a matrix's column space is a subspace of the kernel of a polynomial evaluated at a conjugated matrix is equivalent to the property that the column space of the product of that matrix and the conjugating matrix is a subspace of the kernel of the polynomial evaluated at the original matrix.*)\nLemma sub_kermxpoly_conjmx V f p W : stablemx V f -> row_free V ->\n (W <= kermxpoly (conjmx V f) p)%MS = (W *m V <= kermxpoly f p)%MS.\n\n(*This lemma states that, under conditions of stability and row independence, the property that a matrix's column space is a subspace of an eigenspace of a conjugated matrix is equivalent to the property that the column space of the product of that matrix and the conjugating matrix is a subspace of the corresponding eigenspace of the original matrix.*)\nLemma sub_eigenspace_conjmx V f a W : stablemx V f -> row_free V ->\n (W <= eigenspace (conjmx V f) a)%MS = (W *m V <= eigenspace f a)%MS.\n\nEnd Sub.\n\n(*This lemma states that if a subspace is stable under a given matrix and its basis vectors are linearly independent, then the multiset of eigenvalues of the matrix restricted to that subspace is included in the multiset of eigenvalues of the original matrix.*)\nLemma eigenpoly_conjmx V f : stablemx V f -> row_free V ->\n {subset eigenpoly (conjmx V f) <= eigenpoly f}.\n\n(*This lemma states that if a subspace is stable under a given matrix and its basis vectors are linearly independent, then the set of distinct eigenvalues of the matrix restricted to that subspace is a subset of the set of distinct eigenvalues of the original matrix.*)\nLemma eigenvalue_conjmx V f : stablemx V f -> row_free V ->\n {subset eigenvalue (conjmx V f) <= eigenvalue f}.\n\n(*This lemma states that if a subspace with linearly independent rows is contained within the eigenspace of a matrix corresponding to a specific eigenvalue, then the restriction of that matrix to the subspace is equal to the scalar matrix of that eigenvalue.*)\nLemma conjmx_eigenvalue a V f : (V <= eigenspace f a)%MS -> row_free V ->\n conjmx V f = a%:M.\n\nEnd fixed_stablemx_space.\nEnd ConjMx.\nNotation restrictmx V := (conjmx (row_base V)).\n\n(*This definition asserts that a given matrix is transformed, via a specified change-of-basis matrix, into a matrix that satisfies a given predicate.*)\nDefinition simmx_to_for {F : fieldType} {m n}\n (P : 'M_(m, n)) A (S : {pred 'M[F]_m}) := S (conjmx P A).\n(*This notation expresses that a matrix `A` is transformed by a change-of-basis matrix `P` into a matrix that belongs to a set `S`.*)\nNotation \"A ~_ P '{' 'in' S '}'\" := (simmx_to_for P A S)\n (at level 70, P at level 0, format \"A ~_ P '{' 'in' S '}'\") :\n ring_scope.\n\nNotation simmx_for P A B := (A ~_P {in PredOfSimpl.coerce (pred1 B)}).\n(*This notation expresses that a matrix `A` is transformed by a change-of-basis matrix `P` into a specific matrix `B`.*)\nNotation \"A ~_ P B\" := (simmx_for P A B) (format \"A ~_ P B\").\n\nNotation simmx_in S A B := (exists2 P, P \\in S & A ~_P B).\n(*This notation expresses that a matrix `A` is similar to a matrix `B`, where the change-of-basis matrix is guaranteed to exist within a specified set `S` of matrices.*)\nNotation \"A '~_{in' S '}' B\" := (simmx_in S A B)\n (at level 70, format \"A '~_{in' S '}' B\").\n\nNotation simmx_in_to S A S' := (exists2 P, P \\in S & A ~_P {in S'}).\n(*This notation expresses that a matrix `A` is similar to some matrix in a target set `S'`, where the change-of-basis matrix is guaranteed to exist within a specified source set `S`.*)\nNotation \"A '~_{in' S '}' '{' 'in' S' '}'\" := (simmx_in_to S A S')\n (format \"A '~_{in' S '}' '{' 'in' S' '}'\").\n\nNotation all_simmx_in S As S' :=\n (exists2 P, P \\in S & all [pred A | A ~_P {in S'}] As).\n\nNotation diagonalizable_for P A := (A ~_P {in is_diag_mx}).\nNotation diagonalizable_in S A := (A ~_{in S} {in is_diag_mx}).\nNotation diagonalizable A := (diagonalizable_in unitmx A).\nNotation codiagonalizable_in S As := (all_simmx_in S As is_diag_mx).\nNotation codiagonalizable As := (codiagonalizable_in unitmx As).\n\nSection Simmxity.\nContext {F : fieldType}.\n\n(*This lemma states that if the subspace spanned by the rows of a matrix `P` is stable under a matrix `A`, and matrix `A` becomes matrix `B` when expressed in the basis of `P`, then the product of `P` and `A` is equal to the product of `B` and `P`.*)\nLemma simmxPp m n {P : 'M[F]_(m, n)} {A B} :\n stablemx P A -> A ~_P B -> P *m A = B *m P.\n\n(*This lemma states that if a matrix `P` has linearly independent rows and satisfies the intertwining relation where the product of `P` and `A` equals the product of `B` and `P`, then `A` transforms to `B` under the change of basis represented by `P`.*)\nLemma simmxW m n {P : 'M[F]_(m, n)} {A B} : row_free P ->\n P *m A = B *m P -> A ~_P B.\n\nSection Simmx.\n\nContext {n : nat}.\nImplicit Types (A B P : 'M[F]_n) (As : seq 'M[F]_n) (d : 'rV[F]_n).\n\n(*This lemma states that for an invertible square matrix `P`, the similarity relation where `A` is transformed to `B` via `P` is logically equivalent to the intertwining relation where the product of `P` and `A` equals the product of `B` and `P`.*)\nLemma simmxP {P A B} : P \\in unitmx ->\n reflect (P *m A = B *m P) (A ~_P B).\n\n(*This lemma states that for an invertible square matrix `P`, the similarity relation where `A` is transformed to `B` via `P` is logically equivalent to `B` being the result of the matrix product of `P`, `A`, and the inverse of `P`.*)\nLemma simmxRL {P A B} : P \\in unitmx ->\n reflect (B = P *m A *m invmx P) (A ~_P B).\n\n(*This lemma states that for an invertible square matrix `P`, the similarity relation where `A` is transformed to `B` via `P` is logically equivalent to `A` being the result of the matrix product of the inverse of `P`, `B`, and `P`.*)\nLemma simmxLR {P A B} : P \\in unitmx ->\n reflect (A = conjmx (invmx P) B) (A ~_P B).\n\nEnd Simmx.\n\n(*This lemma states that if two square matrices are similar, they share the same minimal polynomial.*)\nLemma simmx_minpoly {n} {P A B : 'M[F]_n.+1} : P \\in unitmx ->\n A ~_P B -> mxminpoly A = mxminpoly B.\n\n(*This lemma states that a matrix `A` is diagonalizable with respect to the row basis of another matrix `P` if and only if the representation of `A` restricted to the subspace spanned by the rows of `P` is a diagonal matrix.*)\nLemma diagonalizable_for_row_base m n (P : 'M[F]_(m, n)) (A : 'M_n) :\n diagonalizable_for (row_base P) A = is_diag_mx (restrictmx P A).\n\n(*This lemma provides a logical equivalence for a matrix being diagonalizable with respect to a change-of-basis matrix `P`, stating this holds if and only if all off-diagonal entries of the matrix resulting from the change of basis are zero.*)\nLemma diagonalizable_forPp m n (P : 'M[F]_(m, n)) A :\n reflect (forall i j : 'I__, i != j :> nat -> conjmx P A i j = 0)\n (diagonalizable_for P A).\n\n(*This lemma states that for an invertible square change-of-basis matrix `P`, a matrix `A` is diagonalizable by `P` if and only if all off-diagonal entries of the matrix product of `P`, `A`, and the inverse of `P` are zero.*)\nLemma diagonalizable_forP n (P : 'M[F]_n) A : P \\in unitmx ->\n reflect (forall i j : 'I__, i != j :> nat -> (P *m A *m invmx P) i j = 0)\n (diagonalizable_for P A).\n\n(*This lemma provides a logical equivalence for a matrix being diagonalizable with respect to a change-of-basis matrix `P`, stating this holds if and only if there exists a vector of scalars such that the original matrix transforms, via `P`, into the diagonal matrix formed from that vector.*)\nLemma diagonalizable_forPex {m} {n} {P : 'M[F]_(m, n)} {A} :\n reflect (exists D, A ~_P (diag_mx D)) (diagonalizable_for P A).\n\n(*This lemma states that for an invertible square change-of-basis matrix `P`, a matrix `A` is diagonalizable by `P` if and only if there exists a vector of scalars such that `A` is equal to the product of the inverse of `P`, the diagonal matrix formed from the vector, and `P`.*)\nLemma diagonalizable_forLR n {P : 'M[F]_n} {A} : P \\in unitmx ->\n reflect (exists D, A = conjmx (invmx P) (diag_mx D)) (diagonalizable_for P A).\n\n(*This lemma states that if a square matrix is diagonalizable via an invertible change-of-basis matrix, then its minimal polynomial is the product of linear factors of the form 'variable minus a scalar', where each scalar is a distinct diagonal entry of the resulting diagonalized matrix.*)\nLemma diagonalizable_for_mxminpoly {n} {P A : 'M[F]_n.+1}\n (rs := undup [seq conjmx P A i i | i <- enum 'I_n.+1]) :\n P \\in unitmx -> diagonalizable_for P A ->\n mxminpoly A = \\prod_(r <- rs) ('X - r%:P).\n\nEnd Simmxity.\n\n(*This lemma states that for a matrix and a collection of subspaces that form a direct sum decomposition, if each subspace is stable under the matrix and is spanned by linearly independent vectors, then the matrix is diagonalizable over the entire space if and only if it is diagonalizable on each individual subspace.*)\nLemma diagonalizable_for_sum (F : fieldType) (m n : nat) (p_ : 'I_n -> nat)\n (V_ : forall i, 'M[F]_(p_ i, m)) (A : 'M[F]_m) :\n mxdirect (\\sum_i <>) ->\n (forall i, stablemx (V_ i) A) ->\n (forall i, row_free (V_ i)) ->\n diagonalizable_for (\\mxcol_i V_ i) A = [forall i, diagonalizable_for (V_ i) A].\n\nSection Diag.\nVariable (F : fieldType).\n\n(*This lemma states that a sequence containing a single matrix is codiagonalizable if and only if that matrix is diagonalizable.*)\nLemma codiagonalizable1 n (A : 'M[F]_n) :\n codiagonalizable [:: A] <-> diagonalizable A.\n\n(*This definition provides an equivalence for the codiagonalizability of a sequence of matrices, asserting that this holds if and only if there exists a single change-of-basis matrix with full row rank that simultaneously diagonalizes every matrix in the sequence.*)\nDefinition codiagonalizablePfull n (As : seq 'M[F]_n) :\n codiagonalizable As\n <-> exists m, exists2 P : 'M_(m, n), row_full P &\n all [pred A | diagonalizable_for P A] As.\n\n(*This lemma provides a sufficient condition for a sequence of matrices to be codiagonalizable, stating that if the vector space is a direct sum of subspaces, each matrix in the sequence leaves these subspaces invariant, and the sequence of restricted matrices on each subspace is codiagonalizable, then the original sequence of matrices is also codiagonalizable.*)\nLemma codiagonalizable_on m n (V_ : 'I_n -> 'M[F]_m) (As : seq 'M[F]_m) :\n (\\sum_i V_ i :=: 1%:M)%MS -> mxdirect (\\sum_i V_ i) ->\n (forall i, all (fun A => stablemx (V_ i) A) As) ->\n (forall i, codiagonalizable (map (restrictmx (V_ i)) As)) ->\n codiagonalizable As.\n\n(*This lemma states that any diagonal matrix is diagonalizable.*)\nLemma diagonalizable_diag {n} (d : 'rV[F]_n) : diagonalizable (diag_mx d).\n\nHint Resolve diagonalizable_diag : core.\n\n(*This lemma states that any scalar matrix is diagonalizable.*)\nLemma diagonalizable_scalar {n} (a : F) : diagonalizable (a%:M : 'M_n).\n\nHint Resolve diagonalizable_scalar : core.\n\n(*This lemma states that the zero matrix is diagonalizable.*)\nLemma diagonalizable0 {n} : diagonalizable (0 : 'M[F]_n).\n\nHint Resolve diagonalizable0 : core.\n\n(*This lemma provides an equivalence for the diagonalizability of a square matrix, stating that a matrix is diagonalizable if and only if the direct sum of its eigenspaces spans the entire vector space.*)\nLemma diagonalizablePeigen {n} {A : 'M[F]_n} :\n diagonalizable A <->\n exists2 rs, uniq rs & (\\sum_(r <- rs) eigenspace A r :=: 1%:M)%MS.\n\n(*This lemma provides an equivalence for the diagonalizability of a square matrix, stating that a matrix is diagonalizable if and only if its minimal polynomial factors into a product of distinct linear polynomials.*)\nLemma diagonalizableP n' (n := n'.+1) (A : 'M[F]_n) :\n diagonalizable A <->\n exists2 rs, uniq rs & mxminpoly A %| \\prod_(x <- rs) ('X - x%:P).\n\n(*This lemma states that any matrix that is similar to a diagonal matrix is itself diagonalizable.*)\nLemma diagonalizable_conj_diag m n (V : 'M[F]_(m, n)) (d : 'rV[F]_n) :\n stablemx V (diag_mx d) -> row_free V -> diagonalizable (conjmx V (diag_mx d)).\n\n(*This definition establishes the property of a sequence of matrices being simultaneously diagonalizable. A sequence of matrices has this property if there exists a single invertible matrix that transforms every matrix in the sequence into a diagonal matrix through conjugation.*)\nLemma codiagonalizableP n (As : seq 'M[F]_n) :\n {in As &, forall A B, comm_mx A B} /\\ {in As, forall A, diagonalizable A}\n <-> codiagonalizable As.", - "algebra.sesquilinear": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype tuple bigop ssralg finset fingroup.\nFrom mathcomp Require Import zmodp poly order ssrnum matrix mxalgebra vector.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nReserved Notation \"M ^t phi\"\n (at level 39, left associativity, format \"M ^t phi\").\nReserved Notation \"A ^!\" (format \"A ^!\").\nReserved Notation \"A ^_|_\" (format \"A ^_|_\").\nReserved Notation \"A ''_|_' B\" (at level 69, format \"A ''_|_' B\").\nReserved Notation \"eps_theta .-sesqui\" (format \"eps_theta .-sesqui\").\n\nLocal Open Scope ring_scope.\nImport GRing.Theory Order.Theory Num.Theory.\n\n(*This notation represents the standard basis row vector where the entry in the j-th column is one and all other entries are zero.*)\nNotation \"''e_' j\" := (delta_mx 0 j)\n (format \"''e_' j\", at level 8, j at level 2) : ring_scope.\n\nDeclare Scope sesquilinear_scope.\nDelimit Scope sesquilinear_scope with sesqui.\nLocal Open Scope sesquilinear_scope.\n\n(*This notation represents the result of applying a given function element-wise to all entries of a matrix.*)\nNotation \"M ^ phi\" := (map_mx phi M) : sesquilinear_scope.\n(*This notation represents the result of applying a given function element-wise to the transpose of a matrix.*)\nNotation \"M ^t phi\" := ((M ^T) ^ phi) : sesquilinear_scope.\n\n(*This lemma states that applying the identity function to each element of a matrix results in the original matrix.*)\nLemma eq_map_mx_id (R : nzRingType) m n (M : 'M[R]_(m, n)) (f : R -> R) :\n f =1 id -> M ^ f = M.\n\n(*This record provides a structure for functions over a nonzero ring that are involutive, meaning applying the function twice returns the original input.*)\nHB.mixin Record isInvolutive (R : nzRingType) (f : R -> R) :=\n { involutive_subproof : involutive f }.\n\n#[short(type=\"involutive_rmorphism\")]\n(*This structure defines an involutive ring morphism, which is a function from a nonzero ring to itself that both preserves the ring structure and is its own inverse.*)\nHB.structure Definition InvolutiveRMorphism (R : nzRingType) :=\n { f of @GRing.RMorphism R R f & @isInvolutive R f }.\n\nSection InvolutiveTheory.\nVariable R : nzRingType.\n\n(*This definition provides the proof that the identity function on a nonzero ring is involutive.*)\nLet idfunK : involutive (@idfun R). \n\n(*This lemma states that any function defined as an involutive ring morphism is involutive, meaning applying it twice yields the identity.*)\nLemma rmorphK (f : involutive_rmorphism R) : involutive f.\n\nEnd InvolutiveTheory.\n\n(*This definition specifies the complex conjugation function for elements of a numerically closed field.*)\nDefinition conjC {C : numClosedFieldType} (c : C) : C := c^*.\n\nHB.instance Definition _ (C : numClosedFieldType) :=\n GRing.RMorphism.on (@conjC C).\n\nSection conjC_involutive.\nVariable C : numClosedFieldType.\n\n(*This definition provides the proof that the complex conjugation function is involutive, meaning that conjugating a number twice returns the original number.*)\nLet conjCfun_involutive : involutive (@conjC C). \n\n(*This lemma states that applying the complex conjugation function to every entry of a matrix twice yields the original matrix.*)\nLemma map_mxCK {C : numClosedFieldType} m n (A : 'M[C]_(m, n)) :\n (A ^ conjC) ^ conjC = A.\n\n(*This record specifies the properties for a function to be bilinear, requiring it to be a group homomorphism and scalable in each of its two arguments, where the scaling laws can be different for each argument.*)\nHB.mixin Record isBilinear (R : nzRingType) (U U' : lmodType R) (V : zmodType)\n (s : R -> V -> V) (s' : R -> V -> V) (f : U -> U' -> V) := {\n zmod_morphisml_subproof : forall u', zmod_morphism (f ^~ u') ;\n zmod_morphismr_subproof : forall u, zmod_morphism (f u) ;\n linearl_subproof : forall u', scalable_for s (f ^~ u') ;\n linearr_subproof : forall u, scalable_for s' (f u)\n}.\n\n#[short(type=\"bilinear\")]\n(*This structure encapsulates a bilinear map, which is a function from two modules into an additive group that satisfies the properties of being bilinear.*)\nHB.structure Definition Bilinear (R : nzRingType) (U U' : lmodType R)\n (V : zmodType) (s : R -> V -> V) (s' : R -> V -> V) :=\n {f of isBilinear R U U' V s s' f}.\n\n(*This definition specifies the type for a function from two modules to an additive group to be bilinear, by simultaneously requiring that the function is linear in its first argument for any fixed second argument, and linear in its second argument for any fixed first argument.*)\nDefinition bilinear_for (R : nzRingType) (U U' : lmodType R) (V : zmodType)\n (s : GRing.Scale.law R V) (s' : GRing.Scale.law R V) (f : U -> U' -> V) :=\n ((forall u', GRing.linear_for (s : R -> V -> V) (f ^~ u'))\n * (forall u, GRing.linear_for s' (f u)))%type.\n\n(*This factory record provides a mechanism to construct a proof of the `isBilinear` property from a proof that a function is linear in each of its arguments separately.*)\nHB.factory Record bilinear_isBilinear (R : nzRingType) (U U' : lmodType R)\n (V : zmodType) (s : GRing.Scale.law R V) (s' : GRing.Scale.law R V)\n (f : U -> U' -> V) := {\n bilinear_subproof : bilinear_for s s' f\n}.\n\nHB.builders Context R U U' V s s' f of bilinear_isBilinear R U U' V s s' f.\nHB.instance Definition _ := isBilinear.Build R U U' V s s' f\n (fun u' => zmod_morphism_linear (bilinear_subproof.1 u'))\n (fun u => zmod_morphism_linear (bilinear_subproof.2 u))\n (fun u' => scalable_linear (bilinear_subproof.1 u'))\n (fun u => scalable_linear (bilinear_subproof.2 u)).\nHB.end.\n\nModule BilinearExports.\n\nModule Bilinear.\nSection bilinear.\nVariables (R : nzRingType) (U U' : lmodType R) (V : zmodType) (s s' : R -> V -> V).\n\nLocal Notation bilinear f := (bilinear_for *:%R *:%R f).\nLocal Notation biscalar f := (bilinear_for *%R *%R f).\n\n(*This is an alias for the type of bilinear functions from two specified source modules to a target additive group, with given scalar actions.*)\nNotation mapUUV := (@Bilinear.type R U U' V s s').\n(*This defines an alias for the type representing bilinear functions between two modules and an additive group.*)\nDefinition map_class := mapUUV.\n(*This defines an alias for the type of bilinear functions, intended for contexts involving a specific scalar element associated with the left argument's scaling law.*)\nDefinition map_at_left (a : R) := mapUUV.\n(*This defines an alias for the type of bilinear functions, intended for contexts involving a specific scalar element associated with the right argument's scaling law.*)\nDefinition map_at_right (b : R) := mapUUV.\n(*This defines an alias for the type of bilinear functions, intended for contexts involving specific scalar elements associated with the scaling laws of both arguments.*)\nDefinition map_at_both (a b : R) := mapUUV.\n(*This structure bundles a bilinear map with a proof that the left scaling action at a specific ring element is equal to a given function.*)\nStructure map_for_left a s_a :=\n MapForLeft {map_for_left_map : mapUUV; _ : s a = s_a }.\n(*This structure bundles a bilinear map with a proof that the right scaling action at a specific ring element is equal to a given function.*)\nStructure map_for_right b s'_b :=\n MapForRight {map_for_right_map : mapUUV; _ : s' b = s'_b }.\n(*This structure bundles a bilinear map with proofs that the left and right scaling actions at specific ring elements are equal to given functions.*)\nStructure map_for_both a b s_a s'_b :=\n MapForBoth {map_for_both_map : mapUUV; _ : s a = s_a ; _ : s' b = s'_b }.\n(*This definition takes a bilinear map and wraps it into a structure that includes a trivial proof about its left scaling action, used for type unification.*)\nDefinition unify_map_at_left a (f : map_at_left a) :=\n MapForLeft f (erefl (s a)).\n(*This definition takes a bilinear map and wraps it into a structure that includes a trivial proof about its right scaling action, used for type unification.*)\nDefinition unify_map_at_right b (f : map_at_right b) :=\n MapForRight f (erefl (s' b)).\n(*This definition takes a bilinear map and wraps it into a structure that includes trivial proofs about its left and right scaling actions, used for type unification.*)\nDefinition unify_map_at_both a b (f : map_at_both a b) :=\n MapForBoth f (erefl (s a)) (erefl (s' b)).\n(*This structure provides a simple wrapper for a bilinear map, often used to manage type class inference.*)\nStructure wrapped := Wrap {unwrap : mapUUV}.\n(*This definition constructs an instance of the wrapped bilinear map structure from a given bilinear map.*)\nDefinition wrap (f : map_class) := Wrap f.\nEnd bilinear.\nEnd Bilinear.\n\n(*This notation represents the type of all bilinear functions from a module U and a module V into an additive group W, where the linearity in the first argument is with respect to the scaling action s and in the second argument is with respect to the scaling action t.*)\nNotation \"{ 'bilinear' U -> V -> W | s & t }\" :=\n (@Bilinear.type _ U%type V%type W%type s t)\n (U at level 98, V at level 98, W at level 99,\n format \"{ 'bilinear' U -> V -> W | s & t }\") : ring_scope.\n(*This notation represents the type of all bilinear functions from a module U and a module V into an additive group W, where the linearity in both arguments is with respect to the same scaling action s.*)\nNotation \"{ 'bilinear' U -> V -> W | s }\" :=\n ({bilinear U -> V -> W | s.1 & s.2})\n (U at level 98, V at level 98, W at level 99,\n format \"{ 'bilinear' U -> V -> W | s }\") : ring_scope.\n(*This notation represents the type of bilinear functions from two left modules to an additive group, using the default scalar actions of the ring.*)\nNotation \"{ 'bilinear' U -> V -> W }\" := {bilinear U -> V -> W | *:%R & *:%R}\n (U at level 98, V at level 98, W at level 99,\n format \"{ 'bilinear' U -> V -> W }\") : ring_scope.\n(*This notation defines the type of bilinear functions that take two elements from the same left module and produce a value in an inferred additive group, using the default scalar actions of the ring.*)\nNotation \"{ 'biscalar' U }\" := {bilinear U%type -> U%type -> _ | *%R & *%R}\n (format \"{ 'biscalar' U }\") : ring_scope.\nEnd BilinearExports.\n\nExport BilinearExports.\n\n#[non_forgetful_inheritance]\nHB.instance Definition _ (R : nzRingType) (U U' : lmodType R) (V : zmodType)\n (s : R -> V -> V) (s' : R -> V -> V)\n (f : {bilinear U -> U' -> V | s & s'}) (u : U)\n := @GRing.isZmodMorphism.Build U' V (f u) (@zmod_morphismr_subproof _ _ _ _ _ _ f u).\n\n#[non_forgetful_inheritance]\nHB.instance Definition _ (R : nzRingType) (U U' : lmodType R) (V : zmodType)\n (s : R -> V -> V) (s' : R -> V -> V) (f : @bilinear R U U' V s s') (u : U)\n := @GRing.isScalable.Build _ _ _ _ (f u) (@linearr_subproof _ _ _ _ _ _ f u).\n\nSection applyr.\nVariables (R : nzRingType) (U U' : lmodType R) (V : zmodType)\n (s s' : R -> V -> V).\n\n(*This definition provides a helper function that takes a binary function and two arguments, and applies the function to the arguments in reversed order.*)\nDefinition applyr_head t (f : U -> U' -> V) u v := let: tt := t in f v u.\n\nEnd applyr.\n\n(*This notation provides a convenient way to refer to the function that swaps the arguments of a given binary function. Applying this notation to a binary function results in a new binary function with its arguments reversed.*)\nNotation applyr := (applyr_head tt).\n\nCoercion Bilinear.map_for_left_map : Bilinear.map_for_left >-> Bilinear.type.\nCoercion Bilinear.map_for_right_map : Bilinear.map_for_right >-> Bilinear.type.\nCoercion Bilinear.map_for_both_map : Bilinear.map_for_both >-> Bilinear.type.\nCoercion Bilinear.unify_map_at_left : Bilinear.map_at_left >-> Bilinear.map_for_left.\nCoercion Bilinear.unify_map_at_right : Bilinear.map_at_right >-> Bilinear.map_for_right.\nCoercion Bilinear.unify_map_at_both : Bilinear.map_at_both >-> Bilinear.map_for_both.\nCanonical Bilinear.unify_map_at_left.\nCanonical Bilinear.unify_map_at_right.\nCanonical Bilinear.unify_map_at_both.\nCoercion Bilinear.unwrap : Bilinear.wrapped >-> Bilinear.type.\nCoercion Bilinear.wrap : Bilinear.map_class >-> Bilinear.wrapped.\nCanonical Bilinear.wrap.\n\nSection BilinearTheory.\nVariable R : nzRingType.\n\nSection GenericProperties.\nVariables (U U' : lmodType R) (V : zmodType) (s : R -> V -> V) (s' : R -> V -> V).\nVariable f : {bilinear U -> U' -> V | s & s'}.\n\nSection GenericPropertiesr.\nVariable z : U.\n\n#[local, non_forgetful_inheritance, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ :=\n GRing.isZmodMorphism.Build _ _ (f z) (@zmod_morphismr_subproof _ _ _ _ _ _ f z).\n#[local, non_forgetful_inheritance]\n(*This lemma states that for any bilinear function, applying it to any element in the first input module and the zero element of the second input module results in the zero element of the output additive group.*)\nLemma linear0r : f z 0 = 0. \n(*This lemma states that for any bilinear function, when the first argument is fixed, the resulting function from the second input module to the output additive group preserves the additive inverse operation.*)\nLemma linearNr : {morph f z : x / - x}. \n(*This lemma states that for any bilinear function, when the first argument is fixed, the resulting function from the second input module to the output additive group preserves the addition operation.*)\nLemma linearDr : {morph f z : x y / x + y}. \n(*This lemma states that for any bilinear function, when the first argument is fixed, the resulting function from the second input module to the output additive group preserves the subtraction operation.*)\nLemma linearBr : {morph f z : x y / x - y}. \n(*This lemma states that for any bilinear function, when the first argument is fixed, the resulting function commutes with scalar multiplication by a natural number on its second argument.*)\nLemma linearMnr n : {morph f z : x / x *+ n}. \n(*This lemma states that for any bilinear function, when the first argument is fixed, the resulting function commutes with scalar multiplication by an integer on its second argument.*)\nLemma linearMNnr n : {morph f z : x / x *- n}. \n(*This lemma states that for any bilinear function, when the first argument is fixed, applying the function to a finite sum in the second argument is equivalent to the sum of the function applied to each term of the sum individually.*)\nLemma linear_sumr I r (P : pred I) E :\n f z (\\sum_(i <- r | P i) E i) = \\sum_(i <- r | P i) f z (E i).\n\n(*This lemma states that for any bilinear function, fixing the first argument results in a function from the second input module to the output additive group that is scalable, meaning it respects the scalar multiplication law defined for the second argument.*)\nLemma linearZr_LR : scalable_for s' (f z). \n(*This lemma states a combined addition and scaling property for a bilinear function in its second argument: for a fixed first argument, applying the function to a sum of a scaled element and another element is equivalent to the sum of the scaled function application and the unscaled function application.*)\nLemma linearPr a : {morph f z : u v / a *: u + v >-> s' a u + v}.\n\nEnd GenericPropertiesr.\n\n(*This lemma states that swapping the arguments of a bilinear function using the dedicated swapping function yields a function that is extensionally equal to the one obtained by using the transpose notation.*)\nLemma applyrE x : applyr f x =1 f^~ x. \n\nSection GenericPropertiesl.\nVariable z : U'.\n\nHB.instance Definition _ :=\n GRing.isZmodMorphism.Build _ _ (applyr f z) (@zmod_morphisml_subproof _ _ _ _ _ _ f z).\n(*This lemma states that for any bilinear function, applying it to the zero element of the first input module and any element of the second input module results in the zero element of the output additive group.*)\nLemma linear0l : f 0 z = 0. \n(*This lemma states that for any bilinear function, when the second argument is fixed, the resulting function from the first input module to the output additive group preserves the additive inverse operation.*)\nLemma linearNl : {morph f^~ z : x / - x}.\n\n(*This lemma states that for any bilinear function, when the second argument is fixed, the resulting function from the first input module to the output additive group preserves the addition operation.*)\nLemma linearDl : {morph f^~ z : x y / x + y}.\n\n(*This lemma states that for any bilinear function, when the second argument is fixed, the resulting function from the first input module to the output additive group preserves the subtraction operation.*)\nLemma linearBl : {morph f^~ z : x y / x - y}.\n\n(*This lemma states that for any bilinear function, when the second argument is fixed, the resulting function commutes with scalar multiplication by a natural number on its first argument.*)\nLemma linearMnl n : {morph f^~ z : x / x *+ n}.\n\n(*This lemma states that for any bilinear function, when the second argument is fixed, the resulting function commutes with scalar multiplication by an integer on its first argument.*)\nLemma linearMNnl n : {morph f^~ z : x / x *- n}.\n\n(*This lemma states that for any bilinear function, when the second argument is fixed, applying the function to a finite sum in the first argument is equivalent to the sum of the function applied to each term of the sum individually.*)\nLemma linear_sumlz I r (P : pred I) E :\n f (\\sum_(i <- r | P i) E i) z = \\sum_(i <- r | P i) f (E i) z.\n\n(*This lemma states that for any bilinear function, fixing the second argument results in a function from the first input module to the output additive group that is scalable, meaning it respects the scalar multiplication law defined for the first argument.*)\nLemma linearZl_LR : scalable_for s (f ^~ z).\n\n(*This lemma states a combined addition and scaling property for a bilinear function in its first argument: for a fixed second argument, applying the function to a sum of a scaled element and another element is equivalent to the sum of the scaled function application and the unscaled function application.*)\nLemma linearPl a : {morph f^~ z : u v / a *: u + v >-> s a u + v}.\n\nEnd GenericPropertiesl.\n\nEnd GenericProperties.\n\nSection BidirectionalLinearZ.\nVariables (U U' : lmodType R) (V : zmodType) (s s' : R -> V -> V).\nVariables (S : nzRingType) (h : GRing.Scale.law S V) (h' : GRing.Scale.law S V).\n\n(*This lemma states that for a bilinear function with a specific left-scaling property, scaling the first input by a ring element results in applying the corresponding scaling law to the value of the function on the unscaled input.*)\nLemma linearZl z (c : S) (a : R) (h_c := h c)\n (f : Bilinear.map_for_left U U' s s' a h_c) u :\n f (a *: u) z = h_c (Bilinear.wrap f u z).\n\n(*This lemma states that for a bilinear function with a specific right-scaling property, scaling the second input by a ring element results in applying the corresponding scaling law to the value of the function on the unscaled input.*)\nLemma linearZr z c' b (h'_c' := h' c')\n (f : Bilinear.map_for_right U U' s s' b h'_c') u :\n f z (b *: u) = h'_c' (Bilinear.wrap f z u).\n\n(*This lemma describes how a bilinear function with specific scaling properties for both inputs behaves when both arguments are scaled simultaneously. The result is obtained by sequentially applying the right scaling law and then the left scaling law to the value of the function on the unscaled inputs.*)\nLemma linearZlr c c' a b (h_c := h c) (h'_c' := h' c')\n (f : Bilinear.map_for_both U U' s s' a b h_c h'_c') u v :\n f (a *: u) (b *: v) = h_c (h'_c' (Bilinear.wrap f u v)).\n\n(*This lemma describes how a bilinear function with specific scaling properties for both inputs behaves when both arguments are scaled simultaneously. The result is obtained by sequentially applying the left scaling law and then the right scaling law to the value of the function on the unscaled inputs.*)\nLemma linearZrl c c' a b (h_c := h c) (h'_c' := h' c')\n (f : Bilinear.map_for_both U U' s s' a b h_c h'_c') u v :\n f (a *: u) (b *: v) = h'_c' (h_c (Bilinear.wrap f u v)).\n\nEnd BidirectionalLinearZ.\n\nEnd BilinearTheory.\n\n(*This lemma states that matrix multiplication over a commutative non-zero ring is a bilinear function, where the inputs are matrices of compatible dimensions.*)\nLemma mulmx_is_bilinear (R : comNzRingType) m n p : bilinear_for\n (GRing.Scale.Law.clone _ _ *:%R _) (GRing.Scale.Law.clone _ _ *:%R _)\n (@mulmx R m n p).\n\nHB.instance Definition _ (R : comNzRingType) m n p := bilinear_isBilinear.Build R\n [the lmodType R of 'M[R]_(m, n)] [the lmodType R of 'M[R]_(n, p)]\n [the zmodType of 'M[R]_(m, p)] _ _ (@mulmx R m n p)\n (mulmx_is_bilinear R m n p).\n\nSection BilinearForms.\nVariables (R : fieldType) (theta : {rmorphism R -> R}).\nVariables (n : nat) (M : 'M[R]_n).\nImplicit Types (a b : R) (u v : 'rV[R]_n) (N P Q : 'M[R]_n).\n\n(*This definition constructs a bilinear form from a given matrix. The form takes two row vectors, multiplies the first vector by the matrix, then by the element-wise transformed transpose of the second vector, and returns the single element of the resulting one-by-one matrix.*)\nDefinition form u v := (u *m M *m (v ^t theta)) 0 0.\n\n(**)\nLocal Notation \"''[' u , v ]\" := (form u%R v%R) : ring_scope.\n(**)\nLocal Notation \"''[' u ]\" := '[u, u] : ring_scope.\n\n(*This lemma states that the result of applying a bilinear form is zero if the first vector argument is the zero vector.*)\nLemma form0l u : '[0, u] = 0. \n\n(*This lemma states that the result of applying a bilinear form is zero if the second vector argument is the zero vector.*)\nLemma form0r u : '[u, 0] = 0.\n\n(*This lemma states that a bilinear form is additive in its first argument, meaning the form applied to a sum of two vectors combined with a third vector equals the sum of the forms applied to each of the first two vectors with the third vector.*)\nLemma formDl u v w : '[u + v, w] = '[u, w] + '[v, w].\n\n(*This lemma states that a bilinear form is additive in its second argument, meaning the form applied to a first vector and a sum of two other vectors equals the sum of the forms applied to the first vector with each of the other two vectors.*)\nLemma formDr u v w : '[u, v + w] = '[u, v] + '[u, w].\n\n(*This lemma states that for a sesquilinear form, scaling the second vector argument by a ring element is equivalent to applying the form to the original vectors and then multiplying the result by the ring element transformed by the associated ring morphism.*)\nLemma formZr a u v : '[u, a *: v] = theta a * '[u, v].\n\n(*This lemma states that for a sesquilinear form, scaling the first vector argument by a ring element is equivalent to multiplying the result of the form on the original vectors by that same ring element, demonstrating linearity in the first argument.*)\nLemma formZl a u v : '[a *: u, v] = a * '[u, v].\n\n(*This lemma states that applying a bilinear form to the additive inverse of a vector in the first argument is equivalent to taking the additive inverse of the result of the form on the original vector.*)\nLemma formNl u v : '[- u, v] = - '[u, v].\n\n(*This lemma states that applying a bilinear form to the additive inverse of a vector in the second argument is equivalent to taking the additive inverse of the result of the form on the original vector.*)\nLemma formNr u v : '[u, - v] = - '[u, v].\n\n(*This lemma states that applying a bilinear form to two canonical basis vectors returns the element at the corresponding row and column indices of the matrix representation of the form.*)\nLemma formee i j : '['e_i, 'e_j] = M i j.\n\n(*This lemma states that if the matrix representing a bilinear form is the zero matrix, then the form will evaluate to zero for any pair of input vectors.*)\nLemma form0_eq0 : M = 0 -> forall u v, '[u, v] = 0.\n\nEnd BilinearForms.\n\n(*This record mixin defines the property for a function of two module vectors to be Hermitian or skew-Hermitian. This property requires that applying the function to two vectors is equivalent to applying an associated ring morphism to the result of the function with swapped vector arguments, and then optionally multiplying by negative one depending on a boolean flag.*)\nHB.mixin Record isHermitianSesquilinear (R : nzRingType) (U : lmodType R)\n (eps : bool) (theta : R -> R) (f : U -> U -> R) := {\n hermitian_subproof : forall x y : U, f x y = (-1) ^+ eps * theta (f y x)\n}.\n\n(*This definition specifies the structure of a Hermitian form, which is a function that is both a sesquilinear form and satisfies the Hermitian symmetry property relating the value on a pair of vectors to the value on the swapped pair.*)\nHB.structure Definition Hermitian (R : nzRingType) (U : lmodType R)\n (eps : bool) (theta : R -> R) :=\n {f of @Bilinear R U U _ ( *%R ) (theta \\; *%R) f &\n @isHermitianSesquilinear R U eps theta f}.\n\n(*This notation provides a syntax for expressing the type of all Hermitian forms over a given module, parameterized by a boolean symmetry flag and a ring morphism.*)\nNotation \"{ 'hermitian' U 'for' eps & theta }\" := (@Hermitian.type _ U eps theta)\n (format \"{ 'hermitian' U 'for' eps & theta }\") : ring_scope.\n\n#[non_forgetful_inheritance]\nHB.instance Definition _ (R : nzRingType) (U : lmodType R)\n (eps : bool) (theta : R -> R) (f : {hermitian U for eps & theta}) (u : U) :=\n @GRing.isZmodMorphism.Build _ _ (f u) (@zmod_morphismr_subproof _ _ _ _ _ _ f u).\n\n#[non_forgetful_inheritance]\nHB.instance Definition _ (R : nzRingType) (U : lmodType R)\n (eps : bool) (theta : R -> R) (f : {hermitian U for eps & theta}) (u : U) :=\n @GRing.isScalable.Build _ _ _ _ (f u) (@linearr_subproof _ _ _ _ _ _ f u).\n\n(*This definition computes a projection matrix representing the orthogonal complement of the subspace spanned by the columns of an input matrix. Orthogonality is defined with respect to a sesquilinear form given by another matrix and an associated ring morphism.*)\nDefinition orthomx {R : fieldType} (theta : R -> R) n m M (B : 'M_(m, n)) : 'M_n :=\n kermx (M *m (B ^t theta)).\n\nSection Sesquilinear.\nVariables (R : fieldType) (n : nat).\nImplicit Types (a b : R) (u v : 'rV[R]_n) (N P Q : 'M[R]_n).\n\nSection Def.\nVariable eps_theta : bool * {rmorphism R -> R}.\n\n(*This definition specifies a predicate for square matrices that identifies those representing Hermitian or skew-Hermitian forms. A matrix satisfies this property if it is equal to its own conjugate transpose, optionally negated depending on a boolean parameter.*)\nDefinition sesqui :=\n [qualify M : 'M_n | M == ((-1) ^+ eps_theta.1) *: M ^t eps_theta.2].\n(*This statement asserts that the 'sesqui' predicate, which identifies matrices representing Hermitian forms, is a well-behaved property that can be used effectively within the library's framework for structured types.*)\nFact sesqui_key : pred_key sesqui. \n\nCanonical sesqui_keyed := KeyedQualifier sesqui_key.\n\nEnd Def.\n\n(*A notation that, given a pair composed of a boolean and a ring morphism, denotes a predicate on a square matrix. This predicate is satisfied if the matrix is equal to its own transpose, where each element is first mapped by the ring morphism, and the resulting matrix is then scaled by one if the boolean is false, and by negative one if the boolean is true.*)\nLocal Notation \"eps_theta .-sesqui\" := (sesqui eps_theta).\n\nVariables (eps : bool) (theta : {rmorphism R -> R}) (M : 'M[R]_n).\n(*This notation represents the application of a sesquilinear form to two vectors, where the form is defined by a specific matrix and a ring morphism that acts on the second vector argument.*)\nLocal Notation \"''[' u , v ]\" := (form theta M u%R v%R) : ring_scope.\n(*This notation provides a shorthand for applying a bilinear form to a single vector twice, effectively representing the quadratic form associated with the bilinear form.*)\nLocal Notation \"''[' u ]\" := '[u, u] : ring_scope.\n\n(*This lemma states that a matrix has the specified sesquilinear property if and only if it is equal to the matrix obtained by taking its theta-transpose and scaling it by negative one raised to the power of a given boolean.*)\nLemma sesquiE : (M \\is (eps, theta).-sesqui) = (M == (-1) ^+ eps *: M ^t theta).\n\n(*This lemma provides a boolean reflection, establishing that a matrix has a given sesquilinear property is logically equivalent to the proposition that the matrix equals its theta-transpose scaled by negative one raised to the power of a given boolean.*)\nLemma sesquiP : reflect (M = (-1) ^+ eps *: M ^t theta)\n (M \\is (eps, theta).-sesqui).\n\nHypotheses (thetaK : involutive theta) (M_sesqui : M \\is (eps, theta).-sesqui).\n\n(*This lemma states that for a matrix with a given sesquilinear property, its transpose is equal to its theta-conjugate scaled by negative one raised to the power of a given boolean.*)\nLemma trmx_sesqui : M^T = (-1) ^+ eps *: M ^ theta.\n\n(*This lemma states that for a matrix with a given sesquilinear property, its theta-transpose is equal to the original matrix scaled by negative one raised to the power of a given boolean.*)\nLemma maptrmx_sesqui : M^t theta = (-1) ^+ eps *: M.\n\n(*This lemma describes the commutativity property of the sesquilinear form, stating that the form applied to two vectors is equal to the result of applying a theta-involution to the form with the vectors swapped, all scaled by negative one raised to the power of a given boolean.*)\nLemma formC u v : '[u, v] = (-1) ^+ eps * theta '[v, u].\n\n(*This lemma states that the boolean proposition that the sesquilinear form applied to two vectors equals zero is equivalent to the proposition that the form applied to the same vectors in reversed order equals zero.*)\nLemma form_eq0C u v : ('[u, v] == 0) = ('[v, u] == 0).\n\n(*This definition provides a function for computing the orthogonal complement of the subspace spanned by the rows of a given matrix, with respect to the ambient sesquilinear form.*)\nDefinition ortho m (B : 'M_(m, n)) := orthomx theta M B.\n(*A notation for the orthogonal complement of the subspace spanned by the rows of a given matrix, with respect to the ambient sesquilinear form.*)\nLocal Notation \"B ^_|_\" := (ortho B) : ring_scope.\n(*A notation to express that the subspace spanned by the rows of a first matrix is orthogonal to the subspace spanned by the rows of a second matrix, which means every vector in the first subspace is orthogonal to every vector in the second.*)\nLocal Notation \"A '_|_ B\" := (A%MS <= B^_|_)%MS : ring_scope.\n\n(*This lemma states that the orthogonality relationship between two vectors is equivalent to the boolean proposition that the sesquilinear form applied to them is equal to zero.*)\nLemma normalE u v : (u '_|_ v) = ('[u, v] == 0).\n\n(*This lemma provides a boolean reflection of vector orthogonality, stating that two vectors are orthogonal if and only if the proposition that the sesquilinear form applied to them equals zero is true.*)\nLemma form_eq0P {u v} : reflect ('[u, v] = 0) (u '_|_ v).\n\n(*This lemma provides a boolean reflection of matrix orthogonality, stating that two matrices are orthogonal if and only if for every vector in the subspace spanned by the rows of the first matrix and every vector in the subspace spanned by the rows of the second matrix, the two vectors are orthogonal.*)\nLemma normalP p q (A : 'M_(p, n)) (B :'M_(q, n)) :\n reflect (forall (u v : 'rV_n), (u <= A)%MS -> (v <= B)%MS -> u '_|_ v)\n (A '_|_ B).\n\n(*This lemma states that the orthogonality relationship between the subspaces spanned by the rows of two matrices is symmetric.*)\nLemma normalC p q (A : 'M_(p, n)) (B : 'M_(q, n)) : (A '_|_ B) = (B '_|_ A).\n\n(*This lemma states that for any given matrix, the subspace spanned by its rows is orthogonal to its own orthogonal complement.*)\nLemma normal_ortho_mx p (A : 'M_(p, n)) : ((A^_|_) '_|_ A).\n\n(*This lemma states that for any given matrix, its orthogonal complement is orthogonal to the subspace spanned by its rows.*)\nLemma normal_mx_ortho p (A : 'M_(p, n)) : (A '_|_ (A^_|_)).\n\n(*This lemma states that the rank of the orthogonal complement of a single vector is at least the dimension of the space minus one.*)\nLemma rank_normal u : (\\rank (u ^_|_) >= n.-1)%N.\n\n(*This definition specifies the radical of the sesquilinear form as the orthogonal complement of the entire vector space.*)\nDefinition rad := 1%:M^_|_.\n\n(*This lemma states that the radical of the sesquilinear form is equal to the kernel of the matrix representing the form.*)\nLemma rad_ker : rad = kermx M.\n\n(*This theorem states that if two vectors are orthogonal, the value of the quadratic form applied to their sum equals the sum of the values of the quadratic form applied to each vector individually.*)\nTheorem formDd u v : u '_|_ v -> '[u + v] = '[u] + '[v].\n\n(*This lemma shows how the quadratic form interacts with scalar multiplication, stating that the form applied to a scaled vector is equal to the original form's value multiplied by the product of the scalar and its image under the theta-involution.*)\nLemma formZ a u : '[a *: u]= (a * theta a) * '[u].\n\n(*This lemma states that the value of the quadratic form applied to the negation of a vector is equal to the value of the form applied to the original vector.*)\nLemma formN u : '[- u] = '[u].\n\n(*This lemma states that scaling a vector by positive one or negative one does not change the value of the quadratic form applied to it.*)\nLemma form_sign m u : '[(-1) ^+ m *: u] = '[u].\n\n(*This lemma provides an expansion for the quadratic form of a sum of two vectors, expressing it as the sum of their individual quadratic forms plus a term involving the sesquilinear form applied to both vectors.*)\nLemma formD u v : let d := '[u, v] in\n '[u + v] = '[u] + '[v] + (d + (-1) ^+ eps * theta d).\n\n(*This lemma provides an expansion for the quadratic form of a difference of two vectors, expressing it as the sum of their individual quadratic forms minus a term involving the sesquilinear form applied to both vectors.*)\nLemma formB u v : let d := '[u, v] in\n '[u - v] = '[u] + '[v] - (d + (-1) ^+ eps * theta d).\n\n(*This theorem states that if two vectors are orthogonal, the value of the quadratic form applied to their difference equals the sum of the values of the quadratic form applied to each vector individually.*)\nLemma formBd u v : u '_|_ v -> '[u - v] = '[u] + '[v].\n\nEnd Sesquilinear.\n(*A notation that combines a boolean and an involution into a single parameter pair to specify a sesquilinear property.*)\nNotation \"eps_theta .-sesqui\" := (sesqui _ eps_theta) : ring_scope.\n\n(*A notation for the property of being a symmetric bilinear form, which is a special case of a sesquilinear form where the scaling factor is one and the involution is the identity function.*)\nNotation symmetric_form := (false, idfun).-sesqui.\n(*A notation for the property of being a skew-symmetric bilinear form, which is a special case of a sesquilinear form where the scaling factor is negative one and the involution is the identity function.*)\nNotation skew := (true, idfun).-sesqui.\n(*A notation for the property of being a Hermitian form, a special case of a sesquilinear form where the scaling factor is one and the involution is the conjugation operation of the underlying field.*)\nNotation hermitian := (false, @Num.conj_op _).-sesqui.\n\n(*This record structure defines the property of being a dot product, which requires that for any non-zero vector, applying the underlying bilinear form to the vector with itself yields a result strictly greater than zero.*)\nHB.mixin Record isDotProduct (R : numDomainType) (U : lmodType R)\n (op : U -> U -> R) := { neq0_dnorm_gt0 : forall u, u != 0 -> 0 < op u u }.\n\n(*This definition specifies a dot product structure on a module over a numeric domain, which is a positive-definite Hermitian form.*)\nHB.structure Definition Dot (R : numDomainType) (U : lmodType R)\n (theta : R -> R) :=\n {op of isDotProduct R U op & @Hermitian R U false theta op}.\n\n(*This notation represents the type of dot product structures on a given module, parameterized by a ring morphism.*)\nNotation \"{ 'dot' U 'for' theta }\" := (@Dot.type _ U theta)\n (format \"{ 'dot' U 'for' theta }\") : ring_scope.\n\n#[non_forgetful_inheritance]\nHB.instance Definition _ (R : numDomainType) (U : lmodType R)\n (theta : R -> R) (f : {dot U for theta}) (u : U) :=\n @GRing.isZmodMorphism.Build _ _ (f u) (@zmod_morphismr_subproof _ _ _ _ _ _ f u).\n\n#[non_forgetful_inheritance]\n(*This notation represents the type of symmetric forms on a given module, which are a special case of Hermitian forms using the identity ring morphism.*)\nNotation \"{ 'symmetric' U }\" := ({hermitian U for false & idfun})\n (format \"{ 'symmetric' U }\") : ring_scope.\n(*This notation represents the type of skew-symmetric forms on a given module, which are a special case of Hermitian forms using the identity ring morphism.*)\nNotation \"{ 'skew_symmetric' U }\" := ({hermitian U for true & idfun})\n (format \"{ 'skew_symmetric' U }\") : ring_scope.\n(*This notation represents the type of Hermitian symmetric forms on a given module for a specific ring morphism.*)\nNotation \"{ 'hermitian_sym' U 'for' theta }\" := ({hermitian U for false & theta})\n (format \"{ 'hermitian_sym' U 'for' theta }\") : ring_scope.\n\n(*This definition checks if a given Hermitian form is skew-symmetric by testing if its boolean parameter is true and its associated ring morphism is the identity function.*)\nDefinition is_skew (R : nzRingType) (eps : bool) (theta : R -> R)\n (U : lmodType R) (form : {hermitian U for eps & theta}) :=\n (eps = true) /\\ (theta =1 id).\n(*This definition checks if a given Hermitian form is symmetric by testing if its boolean parameter is false and its associated ring morphism is the identity function.*)\nDefinition is_sym (R : nzRingType) (eps : bool) (theta : R -> R)\n (U : lmodType R) (form : {hermitian U for eps & theta}) :=\n (eps = false) /\\ (theta =1 id).\n(*This definition checks if a given Hermitian form is Hermitian-symmetric by testing if its boolean parameter is false.*)\nDefinition is_hermsym (R : nzRingType) (eps : bool) (theta : R -> R)\n (U : lmodType R) (form : {hermitian U for eps & theta}) :=\n (eps = false).\n\nSection HermitianModuleTheory.\nVariables (R : nzRingType) (eps : bool) (theta : {rmorphism R -> R}).\nVariables (U : lmodType R) (form : {hermitian U for eps & theta}).\n\n(**)\nLocal Notation \"''[' u , v ]\" := (form u%R v%R) : ring_scope.\n(**)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n\n(*This lemma states that applying the Hermitian form to two vectors is equivalent to applying the associated ring morphism to the result of the form on the swapped vectors, scaled by a sign factor determined by the boolean parameter of the form.*)\nLemma hermC u v : '[u, v] = (-1) ^+ eps * theta '[v, u].\n\n(*This lemma states that the quadratic form associated with a Hermitian form yields the same value for a vector and its additive inverse.*)\nLemma hnormN u : '[- u] = '[u].\n\n(*This lemma states that scaling a vector by positive one or negative one does not change the value of the associated quadratic form.*)\nLemma hnorm_sign n u : '[(-1) ^+ n *: u] = '[u].\n\n(*This lemma expresses the value of the quadratic form on the sum of two vectors in terms of the quadratic forms of the individual vectors and the Hermitian form applied to the pair of vectors.*)\nLemma hnormD u v :\n let d := '[u, v] in '[u + v] = '[u] + '[v] + (d + (-1) ^+ eps * theta d).\n\n(*This lemma expresses the value of the quadratic form on the difference of two vectors in terms of the quadratic forms of the individual vectors and the Hermitian form applied to the pair of vectors.*)\nLemma hnormB u v :\n let d := '[u, v] in '[u - v] = '[u] + '[v] - (d + (-1) ^+ eps * theta d).\n\n(*This lemma states that if two vectors are orthogonal, the value of the quadratic form on their sum is the sum of the values of the quadratic form on each vector.*)\nLemma hnormDd u v : '[u, v] = 0 -> '[u + v] = '[u] + '[v].\n\n(*This lemma states that if two vectors are orthogonal, the value of the quadratic form on their difference is the sum of the values of the quadratic form on each vector.*)\nLemma hnormBd u v : '[u, v] = 0 -> '[u - v] = '[u] + '[v].\n\n(*This notation defines the orthogonality relation between two vectors, which holds if the Hermitian form applied to them evaluates to zero.*)\nLocal Notation \"u '_|_ v\" := ('[u, v] == 0) : ring_scope.\n\n(*This definition checks if every vector in a first finite sequence is orthogonal to every vector in a second finite sequence.*)\nDefinition ortho_rec (s1 s2 : seq U) :=\n all [pred u | all [pred v | u '_|_ v] s2] s1.\n\n(*This recursive function checks if all vectors in a given finite sequence are pairwise orthogonal to each other.*)\nFixpoint pair_ortho_rec (s : seq U) :=\n if s is v :: s' then ortho_rec [:: v] s' && pair_ortho_rec s' else true.\n\n(*This definition checks if a finite sequence of vectors consists of non-zero vectors that are all pairwise orthogonal.*)\nDefinition pairwise_orthogonal s := (0 \\notin s) && pair_ortho_rec s.\n\n(*This definition checks if two finite sequences of vectors are mutually orthogonal, meaning that every vector from the first sequence is orthogonal to every vector from the second sequence.*)\nDefinition orthogonal s1 s2 := (@ortho_rec s1 s2).\nArguments orthogonal : simpl never.\n\n(*This lemma states that a non-empty sequence is orthogonal to a second sequence if and only if both its head element and its tail sequence are orthogonal to the second sequence.*)\nLemma orthogonal_cons u us vs :\n orthogonal (u :: us) vs = orthogonal [:: u] vs && orthogonal us vs.\n\n(*This definition checks if a finite sequence of vectors is orthonormal, which means that all vectors in the sequence have a quadratic form value of one and are pairwise orthogonal.*)\nDefinition orthonormal s := all [pred v | '[v] == 1] s && pair_ortho_rec s.\n\n(*This lemma states that an orthonormal sequence of vectors cannot contain the zero vector.*)\nLemma orthonormal_not0 S : orthonormal S -> 0 \\notin S.\n\n(*This lemma provides an equivalent characterization of an orthonormal sequence, stating that it is a sequence where every vector has a quadratic form value of one and the vectors are non-zero and pairwise orthogonal.*)\nLemma orthonormalE S :\n orthonormal S = all [pred phi | '[phi] == 1] S && pairwise_orthogonal S.\n\n(*This lemma states that any orthonormal sequence of vectors is also a pairwise orthogonal sequence of non-zero vectors.*)\nLemma orthonormal_orthogonal S : orthonormal S -> pairwise_orthogonal S.\n\nEnd HermitianModuleTheory.\nArguments orthogonal {R eps theta U} form s1 s2.\nArguments pairwise_orthogonal {R eps theta U} form s.\nArguments orthonormal {R eps theta U} form s.\n\nSection HermitianIsometry.\nVariables (R : nzRingType) (eps : bool) (theta : {rmorphism R -> R}).\nVariables (U1 U2 : lmodType R) (form1 : {hermitian U1 for eps & theta})\n (form2 : {hermitian U2 for eps & theta}).\n\n(*This notation represents the application of the first of two ambient Hermitian forms to a pair of vectors, yielding a scalar value.*)\nLocal Notation \"''[' u , v ]_1\" := (form1 u%R v%R) : ring_scope.\n(*This notation represents the application of the second of two ambient Hermitian forms to a pair of vectors, yielding a scalar value.*)\nLocal Notation \"''[' u , v ]_2\" := (form2 u%R v%R) : ring_scope.\n(*A notation for applying the first hermitian form to a vector with itself, yielding the associated quadratic form value.*)\nLocal Notation \"''[' u ]_1\" := (form1 u%R u%R) : ring_scope.\n(*A notation for applying the second hermitian form to a vector with itself, yielding the associated quadratic form value.*)\nLocal Notation \"''[' u ]_2\" := (form2 u%R u%R): ring_scope.\n\n(*This definition characterizes a function as an isometry by requiring that for any two vectors, the value of the first hermitian form on their images under the function is equal to the value of the second hermitian form on the original two vectors.*)\nDefinition isometry tau := forall u v, form1 (tau u) (tau v) = form2 u%R v%R.\n\n(*This definition describes a function as an isometry from a source set to a target set. It combines two properties: that the function preserves the hermitian form for all pairs of vectors within the source set, and that the function maps every vector from the source set to a vector within the target set.*)\nDefinition isometry_from_to mD tau mR :=\n prop_in2 mD (inPhantom (isometry tau)) /\\\n prop_in1 mD (inPhantom (forall u, in_mem (tau u) mR)).\n\n(*A notation for the proposition that a given function is an isometry from a source set to a target set. This means the function both preserves the hermitian form for vectors in the source set and maps these vectors into the target set.*)\nLocal Notation \"{ 'in' D , 'isometry' tau , 'to' R }\" :=\n (isometry_from_to (mem D) tau (mem R))\n (format \"{ 'in' D , 'isometry' tau , 'to' R }\")\n : type_scope.\n\nEnd HermitianIsometry.\n\nSection HermitianVectTheory.\nVariables (R : fieldType) (eps : bool) (theta : {rmorphism R -> R}).\nVariable (U : lmodType R) (form : {hermitian U for eps & theta}).\n\n(**)\nLocal Notation \"''[' u , v ]\" := (form u%R v%R) : ring_scope.\n(**)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n\n(*This lemma states that the hermitian form of two vectors evaluates to zero if and only if the hermitian form of the same vectors in reversed order also evaluates to zero.*)\nLemma herm_eq0C u v : ('[u, v] == 0) = ('[v, u] == 0).\n\nEnd HermitianVectTheory.\n\nSection HermitianFinVectTheory.\nVariables (F : fieldType) (eps : bool) (theta : {rmorphism F -> F}).\nVariables (vT : vectType F) (form : {hermitian vT for eps & theta}).\n(*This definition sets 'n' to be the dimension of the finite-dimensional vector space being considered.*)\nLet n := \\dim {:vT}.\nImplicit Types (u v : vT) (U V : {vspace vT}).\n\n(**)\nLocal Notation \"''[' u , v ]\" := (form u%R v%R) : ring_scope.\n(**)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n\n(*This definition defines a mapping from a vector to its corresponding linear form. The resulting linear form, when applied to another vector, computes the scalar value of the bilinear form between the new vector and the original one.*)\nLet alpha v := (linfun (applyr form v : vT -> F^o)).\n\n(*This definition computes the orthogonal complement of a given vector subspace. The orthogonal complement is the subspace containing all vectors that are orthogonal to every vector in the original subspace, with respect to the underlying bilinear form.*)\nDefinition orthov V := (\\bigcap_(i < \\dim V) lker (alpha (vbasis V)`_i))%VS.\n\n(*This notation expresses that two vector subspaces are orthogonal to each other. It holds if every vector in the first subspace is orthogonal to every vector in the second subspace with respect to the underlying bilinear form.*)\nLocal Notation \"U '_|_ V\" := (U <= orthov V)%VS : vspace_scope.\n\n(*This lemma states that a vector is not in the orthogonal complement of a given subspace if and only if there exists at least one vector in that subspace to which it is not orthogonal.*)\nLemma mem_orthovPn V u : reflect (exists2 v, v \\in V & '[u, v] != 0) (u \\notin orthov V).\n\n(*This lemma states that a vector belongs to the orthogonal complement of a subspace if and only if it is orthogonal to every vector within that subspace.*)\nLemma mem_orthovP V u : reflect {in V, forall v, '[u, v] = 0} (u \\in orthov V).\n\n(*This lemma states that the orthogonal complement of the subspace spanned by a single vector is equal to the kernel of the linear form associated with that vector.*)\nLemma orthov1E u : orthov <[u]> = lker (alpha u).\n\n(*This lemma states that two subspaces are orthogonal if and only if the bilinear form evaluates to zero for any pair of vectors, with one chosen from each subspace.*)\nLemma orthovP U V : reflect {in U & V, forall u v, '[u, v] = 0} (U '_|_ V)%VS.\n\n(*This lemma states that the orthogonality relationship between two vector subspaces is symmetric; that is, the first subspace is orthogonal to the second if and only if the second is orthogonal to the first.*)\nLemma orthov_sym U V : (U '_|_ V)%VS = (V '_|_ U)%VS.\n\n(*This lemma provides a boolean equality stating that a vector belongs to the orthogonal complement of the subspace spanned by a second vector if and only if the bilinear form applied to the two vectors equals zero.*)\nLemma mem_orthov1 v u : (u \\in orthov <[v]>) = ('[u, v] == 0).\n\n(*This lemma provides a boolean equality stating that the subspace spanned by a first vector is orthogonal to the subspace spanned by a second vector if and only if the bilinear form applied to the two vectors equals zero.*)\nLemma orthov11 u v : (<[u]> '_|_ <[v]>)%VS = ('[u, v] == 0).\n\n(*This lemma states that the property of a vector belonging to the orthogonal complement of the subspace spanned by another vector is symmetric.*)\nLemma mem_orthov1_sym v u : (u \\in orthov <[v]>) = (v \\in orthov <[u]>).\n\n(*This lemma states that the orthogonal complement of the zero subspace is the entire vector space.*)\nLemma orthov0 : orthov 0 = fullv.\n\n(*This lemma provides a boolean equality stating that a vector is in the orthogonal complement of a subspace if and only if that subspace is contained within the orthogonal complement of the subspace spanned by the single vector.*)\nLemma mem_orthov_sym V u : (u \\in orthov V) = (V <= orthov <[u]>)%VS.\n\n(*This lemma states that the dimension of the intersection of a subspace and the orthogonal complement of a single vector is at least the dimension of the original subspace minus one.*)\nLemma leq_dim_orthov1 u V : ((\\dim V).-1 <= \\dim (V :&: orthov <[u]>))%N.\n\n(*This lemma states that if a vector is not in the orthogonal complement of a given subspace, then the dimension of the image of that subspace under the linear form associated with the vector is one.*)\nLemma dim_img_form_eq1 u V : u \\notin orthov V -> \\dim (alpha u @: V)%VS = 1%N.\n\n(*This lemma states that if a vector is not in the orthogonal complement of a given subspace, then the dimension of the intersection of that subspace with the orthogonal complement of the single vector is exactly the dimension of the original subspace minus one.*)\nLemma eq_dim_orthov1 u V : u \\notin orthov V -> (\\dim V).-1 = \\dim (V :&: orthov <[u]>).\n\n(*This lemma states that if a vector is in the orthogonal complement of a given subspace, then the dimension of the image of that subspace under the linear form associated with the vector is zero.*)\nLemma dim_img_form_eq0 u V : u \\in orthov V -> \\dim (alpha u @: V)%VS = 0%N.\n\n(*This lemma states that for a subspace with positive dimension, if a vector is in its orthogonal complement, then the dimension of the intersection of that subspace with the orthogonal complement of the single vector is strictly greater than the original subspace's dimension minus one.*)\nLemma neq_dim_orthov1 u V : (\\dim V > 0)%N ->\n u \\in orthov V -> ((\\dim V).-1 < \\dim (V :&: orthov <[u]>))%N.\n\n(*This lemma states that for a subspace with a positive dimension, the dimension of its intersection with the orthogonal complement of a single vector is equal to the subspace's dimension minus one if and only if that vector is not in the orthogonal complement of the subspace.*)\nLemma leqif_dim_orthov1 u V : (\\dim V > 0)%N ->\n ((\\dim V).-1 <= \\dim (V :&: orthov <[u]>) ?= iff (u \\notin orthov V))%N.\n\n(*This lemma states that for a vector space of positive dimension, the dimension of the orthogonal complement of the subspace spanned by a single vector is equal to the total space's dimension minus one if and only if that vector does not belong to the radical of the space.*)\nLemma leqif_dim_orthov1_full u : (n > 0)%N ->\n ((\\dim {:vT}).-1 <= \\dim (orthov <[u]>) ?= iff (u \\notin orthov fullv))%N.\n\n(*This lemma states that two singleton sequences of vectors are orthogonal with respect to a given bilinear form if and only if the bilinear form applied to the two vectors evaluates to zero.*)\nLemma orthogonal1P u v : reflect ('[u, v] = 0) (orthogonal form [:: u] [:: v]).\n\n(*This lemma states that two sequences of vectors are orthogonal with respect to a given form if and only if the form evaluates to zero for every pair of vectors, with one taken from each sequence.*)\nLemma orthogonalP us vs :\n reflect {in us & vs, forall u v, '[u, v] = 0} (orthogonal form us vs).\n\n(*This lemma provides a boolean equality stating that a sequence of vectors is orthogonal to a second sequence if and only if it is also orthogonal to the sequence obtained by taking the additive inverse of each vector in the second sequence.*)\nLemma orthogonal_oppr S R : orthogonal form S (map -%R R) = orthogonal form S R.\n\n(*This lemma provides a boolean equality stating that two sequences of vectors are orthogonal with respect to a form if and only if the subspaces they span are orthogonal.*)\nLemma orthogonalE us vs : (orthogonal form us vs) = (<> '_|_ <>)%VS.\n\n(*This lemma provides a boolean equality stating that two subspaces are orthogonal if and only if a basis for the first subspace is orthogonal to a basis for the second subspace, with respect to the given bilinear form.*)\nLemma orthovE U V : (U '_|_ V)%VS = orthogonal form (vbasis U) (vbasis V).\n\n(*This notation defines the radical of the vector space, which is the subspace containing all vectors that are orthogonal to every vector in the entire space.*)\nNotation radv := (orthov fullv).\n\n(*This lemma provides a boolean equality stating that the sum of two subspaces is orthogonal to a third subspace if and only if each of the two initial subspaces is individually orthogonal to the third.*)\nLemma orthoDv U V W : (U + V '_|_ W)%VS = (U '_|_ W)%VS && (V '_|_ W)%VS.\n\n(*This lemma provides a boolean equality stating that a subspace is orthogonal to the sum of two other subspaces if and only if it is orthogonal to each of those two subspaces individually.*)\nLemma orthovD U V W : (U '_|_ V + W)%VS = (U '_|_ V)%VS && (U '_|_ W)%VS.\n\n(*This definition characterizes a form as nondegenerate when its radical, consisting of all vectors orthogonal to every vector in the space, contains only the zero vector.*)\nDefinition nondegenerate := radv == 0%VS.\n(*This definition specifies that a form is pseudo-symplectic if it is nondegenerate, skew-symmetric, and for any vector, the form applied to the vector with itself yields zero, with the latter condition being explicitly checked only when the characteristic of the field is not two.*)\nDefinition is_psymplectic := [/\\ nondegenerate, is_skew form &\n 2 \\in [pchar F] -> forall u, '[u, u] = 0].\n(*This definition specifies that a form is pseudo-orthogonal if it is nondegenerate, symmetric, and for any vector, the form applied to the vector with itself yields zero, with the latter condition being explicitly checked only when the characteristic of the field is not two.*)\nDefinition is_porthogonal := [/\\ nondegenerate, is_sym form &\n 2 \\in [pchar F] -> forall u, '[u, u] = 0].\n(*This definition states that a form is unitary if it is both nondegenerate and Hermitian.*)\nDefinition is_unitary := nondegenerate /\\ (is_hermsym form).\n\nEnd HermitianFinVectTheory.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use is_psymplectic instead.\")]\n(*This notation is a deprecated parsing-only alias for the property of a form being pseudo-symplectic.*)\nNotation is_symplectic := is_psymplectic (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use is_porthogonal instead.\")]\n(*This notation is a deprecated parsing-only alias for the property of a form being pseudo-orthogonal.*)\nNotation is_orthogonal := is_porthogonal (only parsing).\n\nArguments orthogonalP {F eps theta vT form us vs}.\nArguments orthovP {F eps theta vT form U V}.\nArguments mem_orthovPn {F eps theta vT form V u}.\nArguments mem_orthovP {F eps theta vT form V u}.\n\nSection DotVectTheory.\nVariables (C : numClosedFieldType).\nVariable (U : lmodType C) (form : {dot U for conjC}).\n\n(**)\nLocal Notation \"''[' u , v ]\" := (form u%R v%R) : ring_scope.\n(**)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n\n(*This lemma asserts an equivalence between the boolean statement that the squared norm of a vector is greater than or equal to zero and the boolean statement that the vector is the zero vector.*)\nLemma dnorm_geiff0 u : 0 <= '[u] ?= iff (u == 0).\n\n(*This lemma states that the squared norm of any vector, derived from a dot product, is greater than or equal to zero.*)\nLemma dnorm_ge0 u : 0 <= '[u]. \n\n(*This lemma states that the squared norm of a vector equals zero if and only if the vector itself is the zero vector.*)\nLemma dnorm_eq0 u : ('[u] == 0) = (u == 0).\n\n(*This lemma states that the squared norm of a vector is strictly greater than zero if and only if the vector is not the zero vector.*)\nLemma dnorm_gt0 u : (0 < '[u]) = (u != 0).\n\n(*This lemma states that the principal square root of the squared norm of any vector is greater than or equal to zero.*)\nLemma sqrt_dnorm_ge0 u : 0 <= sqrtC '[u].\n\n(*This lemma states that the principal square root of the squared norm of a vector is equal to zero if and only if the vector is the zero vector.*)\nLemma sqrt_dnorm_eq0 u : (sqrtC '[u] == 0) = (u == 0).\n\n(*This lemma states that the principal square root of the squared norm of a vector is strictly greater than zero if and only if the vector is not the zero vector.*)\nLemma sqrt_dnorm_gt0 u : (sqrtC '[u] > 0) = (u != 0).\n\n(*This lemma states that the squared norm of a vector scaled by a scalar is equal to the product of the squared modulus of the scalar and the squared norm of the original vector.*)\nLemma dnormZ a u : '[a *: u]= `|a| ^+ 2 * '[u].\n\n(*This lemma states that the squared norm of the sum of two vectors is equal to the sum of their individual squared norms plus the sum of their inner product and its conjugate.*)\nLemma dnormD u v : let d := '[u, v] in '[u + v] = '[u] + '[v] + (d + d^.\n\n(*This lemma states that the squared norm of the difference of two vectors is equal to the sum of their individual squared norms minus the sum of their inner product and its conjugate.*)\nLemma dnormB u v : let d := '[u, v] in '[u - v] = '[u] + '[v] - (d + d^.\n\nEnd DotVectTheory.\n#[global]\nHint Extern 0 (is_true (0 <= Dot.sort _ _ _\n ))\n => apply: dnorm_ge0 : core.\n\nSection HermitianTheory.\nVariables (C : numClosedFieldType) (eps : bool) (theta : {rmorphism C -> C}).\nVariable (U : lmodType C) (form : {dot U for conjC}).\n(**)\nLocal Notation \"''[' u , v ]\" := (form u%R v%R) : ring_scope.\n(**)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n\n(*This lemma states that a sequence of vectors is pairwise orthogonal if and only if two conditions are met: the sequence does not contain the zero vector and all its elements are unique, and the inner product of any two distinct vectors in the sequence is zero.*)\nLemma pairwise_orthogonalP S :\n reflect (uniq (0 :: S)\n /\\ {in S &, forall phi psi, phi != psi -> '[phi, psi] = 0})\n (pairwise_orthogonal form S).\n\n(*This lemma states that the concatenation of two sequences of vectors is pairwise orthogonal if and only if each of the original sequences is pairwise orthogonal and every vector from the first sequence is orthogonal to every vector from the second sequence.*)\nLemma pairwise_orthogonal_cat R S :\n pairwise_orthogonal form (R ++ S) =\n [&& pairwise_orthogonal form R, pairwise_orthogonal form S & orthogonal form R S].\n\n(*This lemma states that the concatenation of two sequences of vectors is orthonormal if and only if each of the original sequences is individually orthonormal, and every vector from the first sequence is orthogonal to every vector from the second sequence.*)\nLemma orthonormal_cat R S :\n orthonormal form (R ++ S) =\n [&& orthonormal form R, orthonormal form S & orthogonal form R S].\n\n(*This lemma states that a sequence of vectors is orthonormal if and only if it consists of unique vectors and the inner product of any two vectors from the sequence is one if they are the same vector and zero otherwise.*)\nLemma orthonormalP S :\n reflect (uniq S /\\ {in S &, forall phi psi, '[phi, psi] = (phi == psi)%:R})\n (orthonormal form S).\n\n(*This lemma states that a sequence of vectors is orthonormal if it is composed of unique elements that are all members of a larger orthonormal sequence.*)\nLemma sub_orthonormal S1 S2 :\n {subset S1 <= S2} -> uniq S1 -> orthonormal form S2 -> orthonormal form S1.\n\n(*This lemma states that a sequence of two vectors is orthonormal if and only if their inner product is zero and the inner product of each vector with itself is one.*)\nLemma orthonormal2P phi psi :\n reflect [/\\ '[phi, psi] = 0, '[phi] = 1 & '[psi] = 1]\n (orthonormal form [:: phi; psi]).\n\nEnd HermitianTheory.\n\nSection DotFinVectTheory.\nVariable C : numClosedFieldType.\nVariables (U : vectType C) (form : {dot U for conjC}).\n\n(*This notation represents the application of the underlying bilinear form to two vectors, resulting in a scalar from the base field.*)\nLocal Notation \"''[' u , v ]\" := (form u%R v%R) : ring_scope.\n(**)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n\n(*This lemma states that for any two finite sequences of vectors, if the first is a subset of the second, has unique elements, and the second sequence is pairwise orthogonal, then the first sequence is also pairwise orthogonal.*)\nLemma sub_pairwise_orthogonal S1 S2 :\n {subset S1 <= S2} -> uniq S1 ->\n pairwise_orthogonal form S2 -> pairwise_orthogonal form S1.\n\n(*This lemma states that a finite sequence of pairwise orthogonal vectors is linearly independent.*)\nLemma orthogonal_free S : pairwise_orthogonal form S -> free S.\n\n(*This lemma states that if a finite sequence of vectors is pairwise orthogonal, then any subsequence created by filtering the original sequence with a boolean predicate is also pairwise orthogonal.*)\nLemma filter_pairwise_orthogonal S p :\n pairwise_orthogonal form S -> pairwise_orthogonal form (filter p S).\n\n(*This lemma states that a finite sequence of orthonormal vectors is linearly independent.*)\nLemma orthonormal_free S : orthonormal form S -> free S.\n\n(*This theorem states the Cauchy-Schwarz inequality, asserting that the squared absolute value of the inner product of two vectors is less than or equal to the product of their squared norms. Equality holds if and only if the two vectors are linearly dependent.*)\nTheorem CauchySchwarz (u v : U) :\n `|'[u, v]| ^+ 2 <= '[u] * '[v] ?= iff ~~ free [:: u; v].\n\n(*This lemma provides a variant of the Cauchy-Schwarz inequality, stating that the absolute value of the inner product of two vectors is less than or equal to the product of their norms. Equality holds if and only if the two vectors are linearly dependent.*)\nLemma CauchySchwarz_sqrt u v :\n `|'[u, v]| <= sqrtC '[u] * sqrtC '[v] ?= iff ~~ free [:: u; v].\n\n(*This lemma provides a boolean reflection stating that two vectors are considered orthogonal with respect to a given form if and only if their inner product is zero.*)\nLemma orthoP phi psi : reflect ('[phi, psi] = 0) (orthogonal form [:: phi] [:: psi]).\n\n(*This lemma provides a boolean reflection stating that a single vector is orthogonal to a finite sequence of vectors if and only if its inner product with every vector in the sequence is zero.*)\nLemma orthoPl phi S :\n reflect {in S, forall psi, '[phi, psi] = 0} (orthogonal form [:: phi] S).\n\nArguments orthoPl {phi S}.\n\n(*This lemma states that the orthogonality relation between two finite sequences of vectors is symmetric.*)\nLemma orthogonal_sym : symmetric (orthogonal form).\n\n(*This lemma provides a boolean reflection stating that a finite sequence of vectors is orthogonal to a single vector if and only if the inner product of every vector in the sequence with the single vector is zero.*)\nLemma orthoPr S psi :\n reflect {in S, forall phi, '[phi, psi] = 0} (orthogonal form S [:: psi]).\n\n(*This lemma states that the concatenation of two finite sequences of vectors is orthogonal to a third sequence if and only if both original sequences are individually orthogonal to the third sequence.*)\nLemma orthogonal_catl R1 R2 S :\n orthogonal form (R1 ++ R2) S = orthogonal form R1 S && orthogonal form R2 S.\n\n(*This lemma states that a finite sequence of vectors is orthogonal to the concatenation of two other sequences if and only if the first sequence is orthogonal to each of the other two sequences individually.*)\nLemma orthogonal_catr R S1 S2 :\n orthogonal form R (S1 ++ S2) = orthogonal form R S1 && orthogonal form R S2.\n\n(*This lemma states that the property of a finite sequence of vectors being pairwise orthogonal is equivalent for any two sequences that are permutations of each other.*)\nLemma eq_pairwise_orthogonal R S :\n perm_eq R S -> pairwise_orthogonal form R = pairwise_orthogonal form S.\n\n(*This lemma states that the property of a finite sequence of vectors being orthonormal is equivalent for any two sequences that are permutations of each other.*)\nLemma eq_orthonormal S0 S : perm_eq S0 S -> orthonormal form S0 = orthonormal form S.\n\n(*This lemma states that a finite sequence of vectors is orthogonal to a second sequence if and only if the sequence of their additive inverses is also orthogonal to the second sequence.*)\nLemma orthogonal_oppl S R : orthogonal form (map -%R S) R = orthogonal form S R.\n\n(*This lemma establishes the triangle inequality for vector norms, stating that the norm of the sum of two vectors is less than or equal to the sum of their individual norms. Equality holds precisely when the vectors are linearly dependent and one is a non-negative scalar multiple of the other.*)\nLemma triangle_lerif u v :\n sqrtC '[u + v] <= sqrtC '[u] + sqrtC '[v]\n ?= iff ~~ free [:: u; v] && (0 <= coord [tuple v] 0 u).\n\n(*This lemma states that if two sets of vectors are orthogonal, then any vector from the linear span of the first set is orthogonal to any vector from the linear span of the second set.*)\nLemma span_orthogonal S1 S2 phi1 phi2 :\n orthogonal form S1 S2 -> phi1 \\in <>%VS -> phi2 \\in <>%VS ->\n '[phi1, phi2] = 0.\n\n(*This lemma asserts that any vector can be decomposed into the sum of two components: one lying within the linear span of a given finite sequence of vectors, and the other being orthogonal to every vector in that sequence, with the two components also being orthogonal to each other.*)\nLemma orthogonal_split S beta :\n {X : U & X \\in <>%VS &\n {Y :U | [/\\ beta = X + Y, '[X, Y] = 0 & orthogonal form [:: Y] S]}}.\n\nEnd DotFinVectTheory.\nArguments orthoP {C U form phi psi}.\nArguments pairwise_orthogonalP {C U form S}.\nArguments orthonormalP {C U form S}.\nArguments orthoPl {C U form phi S}.\nArguments orthoPr {C U form S psi}.\n\nSection BuildIsometries.\nVariables (C : numClosedFieldType) (U U1 U2 : vectType C).\nVariables (form : {dot U for conjC}) (form1 : {dot U1 for conjC})\n (form2 : {dot U2 for conjC}).\n\n(*This definition creates a function that calculates the squared norm of a vector from a first vector space using the inner product defined on that space.*)\nDefinition normf1 := fun u => form1 u u.\n(*This definition creates a function that calculates the squared norm of a vector from a second vector space using the inner product defined on that space.*)\nDefinition normf2 := fun u => form2 u u.\n\n(*This lemma shows how to construct a linear map that is an isometry on the span of a sequence of vectors, given that the initial sequence is pairwise orthogonal and its image under a mapping is also pairwise orthogonal and preserves the squared norms for each vector.*)\nLemma isometry_of_dnorm S tauS :\n pairwise_orthogonal form1 S -> pairwise_orthogonal form2 tauS ->\n map normf2 tauS = map normf1 S ->\n {tau : {linear U1 -> U2} | map tau S = tauS\n & {in <>%VS &, isometry form2 form1 tau}}.\n\n(*This lemma states that a function that acts as an isometry on a linearly independent sequence of vectors can be extended to a linear transformation that is an isometry on the entire linear span of that sequence.*)\nLemma isometry_of_free S f :\n free S -> {in S &, isometry form2 form1 f} ->\n {tau : {linear U1 -> U2} |\n {in S, tau =1 f} & {in <>%VS &, isometry form2 form1 tau}}.\n\n(*This lemma asserts that any additive function between vector spaces that is also an isometry on a subset closed under subtraction must be an injective function on that subset.*)\nLemma isometry_raddf_inj (tau : {additive U1 -> U2}) :\n {in U1 &, isometry form2 form1 tau} ->\n {in U1 &, forall u v, u - v \\in U1} ->\n {in U1 &, injective tau}.\n\nEnd BuildIsometries.\n\nSection MatrixForms.\nVariables (R : fieldType) (n : nat).\nImplicit Types (a b : R) (u v : 'rV[R]_n) (M N P Q : 'M[R]_n).\n\nSection Def.\nVariable theta : R -> R.\n\n(*This definition specifies a bilinear form on a space of matrices, calculated as the trace of the product of the first matrix, a given square matrix, and the transpose of the second matrix under a specified ring morphism.*)\nDefinition form_of_matrix m M (U V : 'M_(m, n)) := \\tr (U *m M *m (V ^t theta)).\n(*This definition constructs the matrix representation of a bilinear form on a vector space with respect to the canonical basis, where the entry at a given row and column is the result of applying the form to the corresponding pair of basis vectors.*)\nDefinition matrix_of_form (form : 'rV[R]_n -> 'rV[R]_n -> R) : 'M[R]_n :=\n \\matrix_(i, j) form 'e_i 'e_j.\n\nImplicit Type form : {bilinear 'rV[R]_n -> 'rV[R]_n -> R | *%R & theta \\; *%R}.\n\n(*This lemma clarifies the definition of the matrix of a form, stating that the element at a specific row and column is precisely the value of the form applied to the corresponding pair of canonical basis vectors.*)\nLemma matrix_of_formE form i j : matrix_of_form form i j = form 'e_i 'e_j.\n\nEnd Def.\n\nSection FormOfMatrix.\nVariables (m : nat) (M : 'M[R]_n).\nImplicit Types (U V : 'M[R]_(m, n)).\nVariables (theta : {rmorphism R -> R}).\n\n(*This notation provides syntax for applying a bilinear form, defined by a matrix, to a pair of matrices.*)\nLocal Notation \"''[' U , V ]\" := (form_of_matrix theta M U%R V%R) : ring_scope.\n(*This notation provides syntax for the quadratic form associated with a matrix-defined bilinear form, applied to a single matrix.*)\nLocal Notation \"''[' U ]\" := '[U, U]%R : ring_scope.\n\n(*This lemma states that for a given matrix and a ring morphism, the function created by fixing the first vector argument of the associated sesquilinear form is a linear map, where linearity is defined with respect to a scalar multiplication twisted by the ring morphism.*)\nLet form_of_matrix_is_linear U :\n linear_for (theta \\; *%R) (form_of_matrix theta M U).\n\nHB.instance Definition _ U := @GRing.isLinear.Build _ _ _ _\n (form_of_matrix theta M U) (form_of_matrix_is_linear U).\n\n(*This definition creates a unary function from a sesquilinear form by fixing its second vector argument.*)\nDefinition form_of_matrixr U := (form_of_matrix theta M)^~U.\n\n(*This lemma states that for a given matrix, the function created by fixing the second vector argument of the associated form is a linear map with respect to the standard scalar multiplication.*)\nLet form_of_matrixr_is_linear U : linear_for *%R (form_of_matrixr U).\n\nHB.instance Definition _ U := @GRing.isLinear.Build _ _ _ _\n (form_of_matrixr U) (form_of_matrixr_is_linear U).\n\n(*This lemma states that the function constructed from a matrix and a ring morphism, which takes two vectors as input, is a sesquilinear form. This form is linear in its second argument and semilinear in its first argument with respect to the given ring morphism.*)\nLemma form_of_matrix_is_bilinear :\n bilinear_for\n (GRing.Scale.Law.clone _ _ ( *%R ) _) (GRing.Scale.Law.clone _ _ (theta \\; *%R ) _)\n (@form_of_matrix theta m M).\n\n(**)\nLocal Notation \"''[' u , v ]\" := (form_of_matrix theta M u%R v%R) : ring_scope.\n(**)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n\n(*This lemma states that applying the sesquilinear form corresponding to a matrix to the i-th and j-th canonical basis vectors yields the entry of the matrix at row i and column j.*)\nLemma rV_formee i j : '['e_i :'rV__, 'e_j] = M i j.\n\n(*This lemma asserts that if a sesquilinear form is created from a matrix, then converting this form back into a matrix representation yields the original matrix.*)\nLemma form_of_matrixK : matrix_of_form (form_of_matrix theta M) = M.\n\n(*This lemma states that if the matrix underlying a sesquilinear form is the zero matrix, the form will evaluate to the zero element for all pairs of input vectors.*)\nLemma rV_form0_eq0 : M = 0 -> forall u v, '[u, v] = 0.\n\nEnd FormOfMatrix1.\n\nSection MatrixOfForm.\nVariable (theta : {rmorphism R -> R}).\nVariable form : {bilinear 'rV[R]_n -> 'rV[R]_n -> R | *%R & theta \\; *%R}.\n\n(*This lemma states that converting a sesquilinear form to its matrix representation and then converting that matrix back into a form yields a function that is extensionally equal to the original form.*)\nLemma matrix_of_formK : form_of_matrix theta (matrix_of_form form) =2 form.\n\nEnd MatrixOfForm.\n\nSection HermitianMx.\nVariable eps : bool.\n\nSection HermitianMxDef.\nVariable theta : R -> R.\n\n(*This definition specifies the property of a square matrix being Hermitian, which holds if the matrix is equal to its conjugate transpose, possibly scaled by negative one, where the conjugation corresponds to a given ring morphism.*)\nDefinition hermitianmx :=\n [qualify M : 'M_n | M == ((-1) ^+ eps) *: M ^t theta].\n(*This fact establishes the Hermitian property of a matrix as a keyed qualifier, allowing it to be used for defining canonical structures over types of Hermitian matrices.*)\nFact hermitianmx_key : pred_key hermitianmx. \nCanonical hermitianmx_keyed := KeyedQualifier hermitianmx_key.\n\n(*This structure represents a Hermitian matrix by bundling a square matrix with a proof that it satisfies the Hermitian property.*)\nStructure hermitian_matrix := HermitianMx {\n(*This function extracts the underlying matrix from a structure representing a hermitian form.*)\n mx_of_hermitian :> 'M[R]_n;\n _ : mx_of_hermitian \\is hermitianmx }.\n\n(*This lemma provides an equational characterization of the Hermitian property, stating that a matrix is Hermitian if and only if it is equal to its scaled conjugate transpose.*)\nLemma is_hermitianmxE M :\n (M \\is hermitianmx) = (M == (-1) ^+ eps *: M ^t theta).\n\n(*This lemma provides a boolean reflection of the propositional definition of a Hermitian matrix, connecting the computational check of the property to its mathematical definition.*)\nLemma is_hermitianmxP M :\n reflect (M = (-1) ^+ eps *: M ^t theta) (M \\is hermitianmx).\n\n(*This lemma states that any matrix conforming to the Hermitian matrix structure is equal to its own scaled conjugate transpose, unwrapping the property from the structure's definition.*)\nLemma hermitianmxE (M : hermitian_matrix) :\n M = ((-1) ^+ eps) *: M ^t theta :> 'M__.\n\n(*This lemma states that for a Hermitian matrix defined using an involutive ring morphism, its transpose is equal to the matrix obtained by applying the morphism to each element, scaled by a factor determined by the Hermitian definition.*)\nLemma trmx_hermitian (M : hermitian_matrix) :\n M^T = ((-1) ^+ eps) *: M ^ theta :> 'M__.\n\nEnd HermitianMxDef.\n\nSection HermitianMxTheory.\nVariables (theta : involutive_rmorphism R) (M : hermitian_matrix theta).\n\n(*This lemma states that the conjugate transpose of a Hermitian matrix is equal to the original matrix scaled by a factor of one or negative one.*)\nLemma maptrmx_hermitian : M^t theta = (-1) ^+ eps *: (M : 'M__).\n\n(*This lemma states that the sesquilinear form induced by a Hermitian matrix exhibits the Hermitian property, meaning that swapping its arguments results in the conjugate of the original value, possibly scaled by negative one.*)\nLemma form_of_matrix_is_hermitian m x y :\n (@form_of_matrix theta m M) x y =\n (-1) ^+ eps * theta ((@form_of_matrix theta m M) y x).\n\n(*This notation represents the application of the sesquilinear form, which is defined by an implicit matrix and a ring morphism, to two vectors.*)\nLocal Notation \"''[' u , v ]\" := (form_of_matrix theta M u%R v%R) : ring_scope.\n(*This notation represents the application of the quadratic form associated with a bilinear form to a single vector, which is equivalent to applying the bilinear form to that vector twice.*)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n(*This notation represents the orthogonal complement of the subspace generated by the rows of a given matrix, with respect to the ambient Hermitian form.*)\nLocal Notation \"B ^!\" := (orthomx theta M B) : matrix_set_scope.\n(*This notation asserts that the subspace generated by the rows of a first matrix is orthogonal to the subspace generated by the rows of a second matrix.*)\nLocal Notation \"A '_|_ B\" := (A%MS <= B%MS^!)%MS : matrix_set_scope.\n\n(*This lemma states that two vectors are orthogonal if and only if the value of the ambient Hermitian form applied to them is zero.*)\nLemma orthomxE u v : (u '_|_ v)%MS = ('[u, v] == 0).\n\n(*This lemma states the logical equivalence between the proposition that the Hermitian form applied to two vectors is zero and the boolean statement that the two vectors are orthogonal.*)\nLemma hermmx_eq0P {u v} : reflect ('[u, v] = 0) (u '_|_ v)%MS.\n\n(*This lemma states that the subspace generated by the rows of a first matrix is orthogonal to the subspace generated by the rows of a second matrix if and only if every vector in the first subspace is orthogonal to every vector in the second subspace.*)\nLemma orthomxP p q (A : 'M_(p, n)) (B :'M_(q, n)) :\n reflect (forall (u v : 'rV_n), u <= A -> v <= B -> u '_|_ v)%MS\n (A '_|_ B)%MS.\n\n(*This lemma states that the relation of orthogonality between two subspaces generated by matrices is symmetric.*)\nLemma orthomx_sym p q (A : 'M_(p, n)) (B :'M_(q, n)) :\n (A '_|_ B)%MS = (B '_|_ A)%MS.\n\n(*This lemma states that the orthogonal complement of the subspace generated by a matrix is itself orthogonal to the original subspace.*)\nLemma ortho_ortho_mx p (A : 'M_(p, n)) : (A^! '_|_ A)%MS. \n\n(*This lemma states that the subspace generated by a matrix is orthogonal to its own orthogonal complement.*)\nLemma ortho_mx_ortho p (A : 'M_(p, n)) : (A '_|_ A^!)%MS.\n\n(*This lemma states that the rank of the subspace that is the orthogonal complement of a single vector is at least the dimension of the ambient space minus one.*)\nLemma rank_orthomx u : (\\rank (u ^!) >= n.-1)%N.\n\n(*This notation defines the radical of the ambient Hermitian form as the orthogonal complement of the entire space.*)\nLocal Notation radmx := (1%:M^!)%MS.\n\n(*This lemma states that the radical of the ambient Hermitian form is equal to the subspace corresponding to the kernel of the matrix representing the form.*)\nLemma radmxE : radmx = kermx M.\n\n(*This lemma states that the orthogonality relationship between two subspaces is preserved when the matrix representing the first subspace is replaced by its additive inverse.*)\nLemma orthoNmx k m (A : 'M[R]_(k, n)) (B : 'M[R]_(m, n)) :\n ((- A) '_|_ B)%MS = (A '_|_ B)%MS.\n\n(*This lemma states that the orthogonality relationship between two subspaces is preserved when the matrix representing the second subspace is replaced by its additive inverse.*)\nLemma orthomxN k m (A : 'M[R]_(k, n)) (B : 'M[R]_(m, n)) :\n (A '_|_ (- B))%MS = (A '_|_ B)%MS.\n\n(*This lemma states that the sum of two subspaces is orthogonal to a third subspace if and only if each of the first two subspaces is individually orthogonal to the third.*)\nLemma orthoDmx k m p (A : 'M[R]_(k, n)) (B : 'M[R]_(m, n)) (C : 'M[R]_(p, n)) :\n (A + B '_|_ C)%MS = (A '_|_ C)%MS && (B '_|_ C)%MS.\n\n(*This lemma states that a first subspace is orthogonal to the sum of two other subspaces if and only if the first subspace is orthogonal to each of the other two subspaces individually.*)\nLemma orthomxD k m p (A : 'M[R]_(k, n)) (B : 'M[R]_(m, n)) (C : 'M[R]_(p, n)) :\n (A '_|_ B + C)%MS = (A '_|_ B)%MS && (A '_|_ C)%MS.\n\n(*This lemma states that, given a non-zero scalar, the orthogonality relationship between two subspaces is preserved when the matrix representing the first subspace is scaled by that scalar.*)\nLemma orthoZmx p m a (A : 'M[R]_(p, n)) (B : 'M[R]_(m, n)) : a != 0 ->\n (a *: A '_|_ B)%MS = (A '_|_ B)%MS.\n\n(*This lemma states that, given a non-zero scalar, the orthogonality relationship between two subspaces is preserved when the matrix representing the second subspace is scaled by that scalar.*)\nLemma orthomxZ p m a (A : 'M[R]_(p, n)) (B : 'M[R]_(m, n)) : a != 0 ->\n (A '_|_ (a *: B))%MS = (A '_|_ B)%MS.\n\n(*This lemma states that if two matrices generate the same subspace, then their respective orthogonal complements also generate the same subspace.*)\nLemma eqmx_ortho p m (A : 'M[R]_(p, n)) (B : 'M[R]_(m, n)) :\n (A :=: B)%MS -> (A^! :=: B^!)%MS.\n\n(*This lemma states that the orthogonal complement of the canonical representation of a subspace generated by a matrix is identical to the orthogonal complement of the original subspace.*)\nLemma genmx_ortho p (A : 'M[R]_(p, n)) : (<>^! :=: A^!)%MS.\n\nEnd HermitianMxTheory.\nEnd HermitianMx.\nEnd MatrixForms.\n\n(*This notation defines a symmetric matrix as an instance of a Hermitian matrix where the associated conjugation is the identity function and the transpose is not negated.*)\nNotation symmetricmx := (hermitianmx _ false idfun).\n(*This notation defines a skew-symmetric matrix as an instance of a Hermitian matrix where the associated conjugation is the identity function and the transpose is negated.*)\nNotation skewmx := (hermitianmx _ true idfun).\n(*This notation defines a standard Hermitian matrix as an instance where the matrix is equal to its conjugate transpose, without negation.*)\nNotation hermsymmx := (hermitianmx _ false conjC).\n\n(*This lemma states that the identity matrix over any numerically closed field is a standard Hermitian matrix.*)\nLemma hermitian1mx_subproof {C : numClosedFieldType} n : (1%:M : 'M[C]_n) \\is hermsymmx.\n\nCanonical hermitian1mx {C : numClosedFieldType} n :=", - "algebra.interval_inference": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool ssrnat eqtype choice.\nFrom mathcomp Require Import order ssralg ssrnum ssrint interval.\n\nReserved Notation \"{ 'itv' R & i }\"\n (R at level 200, i at level 200, format \"{ 'itv' R & i }\").\nReserved Notation \"{ 'i01' R }\"\n (R at level 200, format \"{ 'i01' R }\").\nReserved Notation \"{ 'posnum' R }\" (format \"{ 'posnum' R }\").\nReserved Notation \"{ 'nonneg' R }\" (format \"{ 'nonneg' R }\").\n\nReserved Notation \"x %:itv\" (format \"x %:itv\").\nReserved Notation \"x %:i01\" (format \"x %:i01\").\nReserved Notation \"x %:pos\" (format \"x %:pos\").\nReserved Notation \"x %:nng\" (format \"x %:nng\").\nReserved Notation \"x %:inum\" (format \"x %:inum\").\nReserved Notation \"x %:num\" (format \"x %:num\").\nReserved Notation \"x %:posnum\" (format \"x %:posnum\").\nReserved Notation \"x %:nngnum\" (format \"x %:nngnum\").\n\nReserved Notation \"[ 'itv' 'of' x ]\" (format \"[ 'itv' 'of' x ]\").\nReserved Notation \"[ 'gt0' 'of' x ]\" (format \"[ 'gt0' 'of' x ]\").\nReserved Notation \"[ 'lt0' 'of' x ]\" (format \"[ 'lt0' 'of' x ]\").\nReserved Notation \"[ 'ge0' 'of' x ]\" (format \"[ 'ge0' 'of' x ]\").\nReserved Notation \"[ 'le0' 'of' x ]\" (format \"[ 'le0' 'of' x ]\").\nReserved Notation \"[ 'cmp0' 'of' x ]\" (format \"[ 'cmp0' 'of' x ]\").\nReserved Notation \"[ 'neq0' 'of' x ]\" (format \"[ 'neq0' 'of' x ]\").\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\nImport Order.TTheory Order.Syntax.\nImport GRing.Theory Num.Theory.\n\nLocal Open Scope ring_scope.\nLocal Open Scope order_scope.\n\n(*This definition applies a given function to the value of an interval bound. If the bound is finite, the function is applied to its value; if the bound is infinite, it remains infinite.*)\nDefinition map_itv_bound S T (f : S -> T) (b : itv_bound S) : itv_bound T :=\n match b with\n | BSide b x => BSide b (f x)\n | BInfty b => BInfty _ b\n end.\n\n(*This lemma states that applying an interval bound mapping with a composite function is equivalent to applying the mappings for each function in sequence.*)\nLemma map_itv_bound_comp S T U (f : T -> S) (g : U -> T) (b : itv_bound U) :\n map_itv_bound (f \\o g) b = map_itv_bound f (map_itv_bound g b).\n\n(*This definition transforms an interval by applying a given function to its lower and upper bounds.*)\nDefinition map_itv S T (f : S -> T) (i : interval S) : interval T :=\n let 'Interval l u := i in Interval (map_itv_bound f l) (map_itv_bound f u).\n\n(*This lemma states that applying an interval mapping with a composite function is equivalent to applying the mappings for each function in sequence.*)\nLemma map_itv_comp S T U (f : T -> S) (g : U -> T) (i : interval U) :\n map_itv (f \\o g) i = map_itv f (map_itv g i).\n\nModule IntItv.\nImplicit Types (b : itv_bound int) (i j : interval int).\n\n(*This definition computes the opposite of an interval bound of integers. For a finite bound, the value is negated and the openness of the bound is flipped. For an infinite bound, positive infinity becomes negative infinity and vice versa.*)\nDefinition opp_bound b :=\n match b with\n | BSide b x => BSide (~~ b) (intZmod.oppz x)\n | BInfty b => BInfty _ (~~ b)\n end.\n\n(*This lemma states that the opposite of an integer interval bound is greater than or equal to a closed lower bound of zero if and only if the original bound is less than or equal to a closed upper bound of zero.*)\nLemma opp_bound_ge0 b : (BLeft 0%R <= opp_bound b)%O = (b <= BRight 0%R)%O.\n\n(*This lemma states that the opposite of an integer interval bound is greater than an open lower bound of zero if and only if the original bound is less than an open upper bound of zero.*)\nLemma opp_bound_gt0 b : (BRight 0%R <= opp_bound b)%O = (b <= BLeft 0%R)%O.\n\n(*This definition computes the opposite of an integer interval, where the new lower bound is the opposite of the original upper bound, and the new upper bound is the opposite of the original lower bound.*)\nDefinition opp i :=\n let: Interval l u := i in Interval (opp_bound u) (opp_bound l).\nArguments opp /.\n\n(*This definition computes the lower bound for the sum of two integer intervals. If both input bounds are finite, the result is a finite bound at their sum, which is closed only if both inputs are closed. Otherwise, the result is negative infinity.*)\nDefinition add_boundl b1 b2 :=\n match b1, b2 with\n | BSide b1 x1, BSide b2 x2 => BSide (b1 && b2) (intZmod.addz x1 x2)\n | _, _ => BInfty _ true\n end.\n\n(*This definition computes the upper bound for the sum of two integer intervals. If both input bounds are finite, the result is a finite bound at their sum, which is closed only if both inputs are closed. Otherwise, the result is positive infinity.*)\nDefinition add_boundr b1 b2 :=\n match b1, b2 with\n | BSide b1 x1, BSide b2 x2 => BSide (b1 || b2) (intZmod.addz x1 x2)\n | _, _ => BInfty _ false\n end.\n\n(*This definition computes the sum of two integer intervals by calculating the sum of their lower bounds and the sum of their upper bounds.*)\nDefinition add i1 i2 :=\n let: Interval l1 u1 := i1 in let: Interval l2 u2 := i2 in\n Interval (add_boundl l1 l2) (add_boundr u1 u2).\nArguments add /.\n\n(*This type represents the sign of an integer interval bound relative to zero, which can be exactly zero, non-negative, or non-positive.*)\nVariant signb := EqZero | NonNeg | NonPos.\n\n(*This definition determines the sign of a lower interval bound for an integer by comparing it to a closed lower bound of zero, classifying it as equal to zero, non-positive, or non-negative.*)\nDefinition sign_boundl b :=\n let: b0 := BLeft 0%Z in\n if b == b0 then EqZero else if (b <= b0)%O then NonPos else NonNeg.\n\n(*This definition determines the sign of an upper interval bound for an integer by comparing it to a closed upper bound of zero, classifying it as equal to zero, non-positive, or non-negative.*)\nDefinition sign_boundr b :=\n let: b0 := BRight 0%Z in\n if b == b0 then EqZero else if (b <= b0)%O then NonPos else NonNeg.\n\n(*This type represents the sign of an entire integer interval, which can be known as zero, non-negative, or non-positive; unknown if it contains both positive and negative values; or empty.*)\nVariant signi := Known of signb | Unknown | Empty.\n\n(*This definition computes the sign of an integer interval by analyzing the signs of its lower and upper bounds, determining if the interval is empty, known to contain only zero, only non-negative numbers, only non-positive numbers, or if its sign is unknown.*)\nDefinition sign i : signi :=\n let: Interval l u := i in\n match sign_boundl l, sign_boundr u with\n | EqZero, NonPos\n | NonNeg, EqZero\n | NonNeg, NonPos => Empty\n | EqZero, EqZero => Known EqZero\n | NonPos, EqZero\n | NonPos, NonPos => Known NonPos\n | EqZero, NonNeg\n | NonNeg, NonNeg => Known NonNeg\n | NonPos, NonNeg => Unknown\n end.\n\n(*This definition computes a lower bound for the product of two numbers, intended for use with bounds of non-negative intervals. If both input bounds are finite, it returns their product. If either bound is a closed lower bound of zero or an infinite bound, it returns a closed lower bound of zero.*)\nDefinition mul_boundl b1 b2 :=\n match b1, b2 with\n | BInfty _, _\n | _, BInfty _\n | BLeft 0%Z, _\n | _, BLeft 0%Z => BLeft 0%Z\n | BSide b1 x1, BSide b2 x2 => BSide (b1 && b2) (intRing.mulz x1 x2)\n end.\n\n(*This definition computes an upper bound for the product of two numbers, intended for use with bounds of non-negative intervals. If both input bounds are finite, it returns their product. If either input bound is positive infinity, the result is positive infinity. It includes specific handling for bounds that are exactly zero.*)\nDefinition mul_boundr b1 b2 :=\n match b1, b2 with\n | BLeft 0%Z, _\n | _, BLeft 0%Z => BLeft 0%Z\n | BRight 0%Z, _\n | _, BRight 0%Z => BRight 0%Z\n | BSide b1 x1, BSide b2 x2 => BSide (b1 || b2) (intRing.mulz x1 x2)\n | _, BInfty _\n | BInfty _, _ => +oo%O\n end.\n\n(*This lemma states that the computation of the upper bound of an interval product is commutative with respect to its two input bounds.*)\nLemma mul_boundrC b1 b2 : mul_boundr b1 b2 = mul_boundr b2 b1.\n\n(*This lemma states that if two integer interval bounds are each greater than an open lower bound of zero, then the upper bound of their product is also greater than an open lower bound of zero.*)\nLemma mul_boundr_gt0 b1 b2 :\n (BRight 0%Z <= b1 -> BRight 0%Z <= b2 -> BRight 0%Z <= mul_boundr b1 b2)%O.\n\n(*This definition computes the product of two integer intervals. It performs a case analysis on the signs of the input intervals, such as positive, negative, or spanning zero, to determine the correct formulas for the lower and upper bounds of the resulting product interval.*)\nDefinition mul i1 i2 :=\n let: Interval l1 u1 := i1 in let: Interval l2 u2 := i2 in\n let: opp := opp_bound in\n let: mull := mul_boundl in let: mulr := mul_boundr in\n match sign i1, sign i2 with\n | Empty, _ | _, Empty => `[1, 0]\n | Known EqZero, _ | _, Known EqZero => `[0, 0]\n | Known NonNeg, Known NonNeg =>\n Interval (mull l1 l2) (mulr u1 u2)\n | Known NonPos, Known NonPos =>\n Interval (mull (opp u1) (opp u2)) (mulr (opp l1) (opp l2))\n | Known NonNeg, Known NonPos =>\n Interval (opp (mulr u1 (opp l2))) (opp (mull l1 (opp u2)))\n | Known NonPos, Known NonNeg =>\n Interval (opp (mulr (opp l1) u2)) (opp (mull (opp u1) l2))\n | Known NonNeg, Unknown =>\n Interval (opp (mulr u1 (opp l2))) (mulr u1 u2)\n | Known NonPos, Unknown =>\n Interval (opp (mulr (opp l1) u2)) (mulr (opp l1) (opp l2))\n | Unknown, Known NonNeg =>\n Interval (opp (mulr (opp l1) u2)) (mulr u1 u2)\n | Unknown, Known NonPos =>\n Interval (opp (mulr u1 (opp l2))) (mulr (opp l1) (opp l2))\n | Unknown, Unknown =>\n Interval\n (Order.min (opp (mulr (opp l1) u2)) (opp (mulr u1 (opp l2))))\n (Order.max (mulr (opp l1) (opp l2)) (mulr u1 u2))\n end.\nArguments mul /.\n\n(*This definition computes a new interval representing the element-wise minimum of two input intervals, where the new lower bound is the minimum of the original lower bounds and the new upper bound is the minimum of the original upper bounds.*)\nDefinition min i j :=\n let: Interval li ui := i in let: Interval lj uj := j in\n Interval (Order.min li lj) (Order.min ui uj).\nArguments min /.\n\n(*This definition computes a new interval representing the element-wise maximum of two input intervals, where the new lower bound is the maximum of the original lower bounds and the new upper bound is the maximum of the original upper bounds.*)\nDefinition max i j :=\n let: Interval li ui := i in let: Interval lj uj := j in\n Interval (Order.max li lj) (Order.max ui uj).\nArguments max /.\n\n(*This definition transforms an integer interval bound to reflect an intersection with the non-negative integers. For a bound on a positive number, it returns a closed lower bound of zero. For a bound on a negative number or an infinite bound, it returns negative infinity.*)\nDefinition keep_nonneg_bound b :=\n match b with\n | BSide _ (Posz _) => BLeft 0%Z\n | BSide _ (Negz _) => -oo%O\n | BInfty _ => -oo%O\n end.\nArguments keep_nonneg_bound /.\n\n(*This definition transforms an integer interval bound to compute a new lower bound, reflecting an intersection with the positive integers. For a strictly positive bound value, it returns an open lower bound of zero. For a bound at zero, it remains at zero. For a negative value or an infinite bound, it returns negative infinity.*)\nDefinition keep_pos_bound b :=\n match b with\n | BSide b 0%Z => BSide b 0%Z\n | BSide _ (Posz (S _)) => BRight 0%Z\n | BSide _ (Negz _) => -oo\n | BInfty _ => -oo\n end.\nArguments keep_pos_bound /.\n\n(*This definition transforms an integer interval bound to reflect an intersection with the non-positive integers. For a bound on a negative number or zero, it returns a closed upper bound of zero. For a bound on a strictly positive number or an infinite bound, it returns positive infinity.*)\nDefinition keep_nonpos_bound b :=\n match b with\n | BSide _ (Negz _) | BSide _ (Posz 0) => BRight 0%Z\n | BSide _ (Posz (S _)) => +oo%O\n | BInfty _ => +oo%O\n end.\nArguments keep_nonpos_bound /.\n\n(*This definition transforms an integer interval bound to compute a new upper bound, reflecting an intersection with the negative integers. For a negative bound value, it returns an open upper bound of zero. For a bound at zero, it remains at zero. For a positive value or an infinite bound, it returns positive infinity.*)\nDefinition keep_neg_bound b :=\n match b with\n | BSide b 0%Z => BSide b 0%Z\n | BSide _ (Negz _) => BLeft 0%Z\n | BSide _ (Posz _) => +oo\n | BInfty _ => +oo\n end.\nArguments keep_neg_bound /.\n\n(*This definition constructs a new integer interval from an existing one. The new lower bound is computed by restricting the original lower bound to be positive, and the new upper bound is computed by restricting the original upper bound to be negative.*)\nDefinition inv i :=\n let: Interval l u := i in\n Interval (keep_pos_bound l) (keep_neg_bound u).\nArguments inv /.\n\n(*This definition computes an interval bound based on two input bounds, likely for an exponentiation operation. The function returns positive infinity unless the second bound is a finite bound at the integer one and the first bound is greater than or equal to negative one, in which case it returns an open upper bound of one.*)\nDefinition exprn_le1_bound b1 b2 :=\n if b2 isn't BSide _ 1%Z then +oo\n else if (BLeft (-1)%Z <= b1)%O then BRight 1%Z else +oo.\nArguments exprn_le1_bound /.\n\n(*This definition computes the result of raising an integer interval to the power of a natural number. The implementation handles different cases based on the properties of the base interval and the exponent.*)\nDefinition exprn i :=\n let: Interval l u := i in\n Interval (keep_pos_bound l) (exprn_le1_bound l u).\nArguments exprn /.\n\n(*This function computes a result interval for a power-like operation, given a base interval and an exponent interval. If the exponent interval is guaranteed to contain only positive numbers, it delegates the computation to another function on the base interval. Otherwise, it returns an interval starting from a positive lower bound derived from the base interval and extending to positive infinity.*)\nDefinition exprz i1 i2 :=\n let: Interval l2 _ := i2 in\n if l2 is BSide _ (Posz _) then exprn i1 else\n let: Interval l u := i1 in\n Interval (keep_pos_bound l) +oo.\nArguments exprz /.\n\n(*This function transforms an integer interval into a new interval. The new interval's lower bound is at least zero, derived from the original lower bound, and its upper bound is at most zero, derived from the original upper bound. This typically results in an interval representing zero if the original interval spanned zero, and an empty interval otherwise.*)\nDefinition keep_sign i :=\n let: Interval l u := i in\n Interval (keep_nonneg_bound l) (keep_nonpos_bound u).\n\n(*This function takes an integer interval and returns a new interval representing all numbers up to a new upper bound, which is the lesser of the original upper bound and zero.*)\nDefinition keep_nonpos i :=\n let 'Interval l u := i in\n Interval -oo%O (keep_nonpos_bound u).\nArguments keep_nonpos /.\n\n(*This function takes an integer interval and returns a new interval representing all numbers from a new lower bound, which is the greater of the original lower bound and zero, to positive infinity.*)\nDefinition keep_nonneg i :=\n let 'Interval l u := i in\n Interval (keep_nonneg_bound l) +oo%O.\nArguments keep_nonneg /.\n\nEnd IntItv.\n\nModule Itv.\n\n(*This variant type represents an interval-related value, which is either a concrete integer interval, tagged as `Real`, or a special `Top` value representing an unconstrained or universal set of numbers.*)\nVariant t := Top | Real of interval int.\n\n(*This function determines if a first interval value is a subset of a second. Any `Real` interval is considered a subset of `Top`, `Top` is only a subset of itself, and for two `Real` intervals, it checks for standard interval inclusion.*)\nDefinition sub (x y : t) :=\n match x, y with\n | _, Top => true\n | Top, Real _ => false\n | Real xi, Real yi => subitv xi yi\n end.\n\nSection Itv.\nContext T (sem : interval int -> T -> bool).\n\n(*This function defines a predicate on a value with respect to an interval-related type. The predicate is always true if the interval type is `Top`, and is determined by a given semantic function if it is a `Real` interval.*)\nDefinition spec (i : t) (x : T) := if i is Real i then sem i x else true.\n\n(*This record encapsulates a value along with a proof that this value satisfies the specification associated with a given interval-related type.*)\nRecord def (i : t) := Def {\n r : T;\n #[canonical=no]\n P : spec i r\n}.\n\nEnd Itv.\n\n(*This record describes a type whose values are all guaranteed to satisfy the specification associated with a given interval-related type. It includes the type itself, a semantic function for interpretation, and a proof of this universal property.*)\nRecord typ i := Typ {\n sort : Type;\n #[canonical=no]\n sort_sem : interval int -> sort -> bool;\n #[canonical=no]\n allP : forall x : sort, spec sort_sem i x\n}.\n\n(*This function constructs an entity that combines a value with a proof certifying that the value satisfies a property related to a given interval specification.*)\nDefinition mk {T f} i x P : @def T f i := @Def T f i x P.\n\n(*This function acts as an identity map on a dependently typed record, returning the record itself. It is primarily used with a phantom argument to assist the type checker in inferring the underlying type of the value contained in the record.*)\nDefinition from {T f i} {x : @def T f i} (phx : phantom T (r x)) := x.\n\n(*This function extracts the proof component from a dependently typed record that pairs a value with a property. A phantom argument is used to guide type inference.*)\nDefinition fromP {T f i} {x : @def T f i} (phx : phantom T (r x)) := P x.\n\n(*This function defines a semantic predicate for elements of a numerical domain. It returns true if and only if a given element is a real number and is contained within the specified integer interval after it is mapped to the numerical domain.*)\nDefinition num_sem (R : numDomainType) (i : interval int) (x : R) : bool :=\n (x \\in Num.real) && (x \\in map_itv intr i).\n\n(*This function serves as a semantic predicate for natural numbers, returning true if and only if the number, when viewed as an integer, falls within the specified integer interval.*)\nDefinition nat_sem (i : interval int) (x : nat) : bool := Posz x \\in i.\n\n(*This defines a type for positive numbers within a specified numerical domain. It consists of a number paired with a proof that it is strictly greater than zero.*)\nDefinition posnum (R : numDomainType) of phant R :=\n def (@num_sem R) (Real `]0, +oo[).\n\n(*This defines a type for non-negative numbers within a specified numerical domain. It consists of a number paired with a proof that it is greater than or equal to zero.*)\nDefinition nonneg (R : numDomainType) of phant R :=\n def (@num_sem R) (Real `[0, +oo[).\n\n(*This function lifts a unary operation on integer intervals to an operation on the extended interval type. The operation is applied to the wrapped interval for a `Real` value, while `Top` is propagated.*)\nDefinition real1 (op1 : interval int -> interval int) (x : Itv.t) : Itv.t :=\n match x with Itv.Top => Itv.Top | Itv.Real x => Itv.Real (op1 x) end.\n\n(*This function lifts a binary operation on integer intervals to an operation on the extended interval type. It applies the operation to the wrapped intervals of two `Real` values and propagates `Top` if either input is `Top`.*)\nDefinition real2 (op2 : interval int -> interval int -> interval int)\n (x y : Itv.t) : Itv.t :=\n match x, y with\n | Itv.Top, _ | _, Itv.Top => Itv.Top\n | Itv.Real x, Itv.Real y => Itv.Real (op2 x y)\n end.\n\n(*This lemma states that a unary operation on values preserves an interval-based specification, provided that the operation on values is consistent with a corresponding operation on intervals. If a value satisfies a specification for a given interval, the result of applying the operation will satisfy the specification for the transformed interval.*)\nLemma spec_real1 T f (op1 : T -> T) (op1i : interval int -> interval int) :\n forall (x : T), (forall xi, f xi x = true -> f (op1i xi) (op1 x) = true) ->\n forall xi, spec f xi x -> spec f (real1 op1i xi) (op1 x).\n\n(*This lemma states that a binary operation on values preserves an interval-based specification, provided that the operation on values is consistent with a corresponding operation on intervals. If two values satisfy specifications for their respective intervals, the result of applying the operation will satisfy the specification for the transformed interval.*)\nLemma spec_real2 T f (op2 : T -> T -> T)\n (op2i : interval int -> interval int -> interval int) (x y : T) :\n (forall xi yi, f xi x = true -> f yi y = true ->\n f (op2i xi yi) (op2 x y) = true) ->\n forall xi yi, spec f xi x -> spec f yi y ->\n spec f (real2 op2i xi yi) (op2 x y).\n\nModule Exports.\nArguments r {T sem i}.\n(*This notation denotes the type of numbers from a given numerical domain `R` that are certified to lie within a specific real interval `i`.*)\nNotation \"{ 'itv' R & i }\" := (def (@num_sem R) (Itv.Real i%Z)) : type_scope.\n(*This notation denotes the type of numbers from a given numerical domain `R` that are certified to lie within the closed interval from zero to one.*)\nNotation \"{ 'i01' R }\" := {itv R & `[0, 1]} : type_scope.\n(*This notation denotes the type of positive numbers from a given numerical domain `R`, where each number is packaged with a proof of its positivity.*)\nNotation \"{ 'posnum' R }\" := (@posnum _ (Phant R)) : ring_scope.\n(*This notation denotes the type of non-negative numbers from a given numerical domain `R`, where each number is packaged with a proof of its non-negativity.*)\nNotation \"{ 'nonneg' R }\" := (@nonneg _ (Phant R)) : ring_scope.\n(*This notation coerces a value coming from a type with an interval constraint to its full dependent record form, which includes both the value and its associated proof of property, mainly to aid type inference.*)\nNotation \"x %:itv\" := (from (Phantom _ x)) : ring_scope.\n(*This notation extracts the proof component from a value that is certified to be in a certain interval, providing the formal evidence of this property.*)\nNotation \"[ 'itv' 'of' x ]\" := (fromP (Phantom _ x)) : ring_scope.\n(*This notation serves as an alias for extracting the underlying value from a dependently typed record that pairs the value with an interval property proof.*)\nNotation num := r.\n(*This is a parsing-only notation that extracts the underlying numerical value from a dependent record that includes an interval property proof.*)\nNotation \"x %:inum\" := (r x) (only parsing) : ring_scope.\n(*This notation retrieves the underlying numerical value from a value that has been typed with an interval constraint.*)\nNotation \"x %:num\" := (r x) : ring_scope.\n(*This notation retrieves the underlying positive real number from a value that has been typed with a strictly positive real interval constraint.*)\nNotation \"x %:posnum\" := (@r _ _ (Real `]0%Z, +oo[) x) : ring_scope.\n(*This notation retrieves the underlying non-negative real number from a value that has been typed with a non-negative real interval constraint.*)\nNotation \"x %:nngnum\" := (@r _ _ (Real `[0%Z, +oo[) x) : ring_scope.\nEnd Exports.\nEnd Itv.\nExport Itv.Exports.\n\n(*This local notation defines a predicate that asserts a numerical value belongs to the set of numbers represented by a given interval.*)\nLocal Notation num_spec := (Itv.spec (@Itv.num_sem _)).\nLocal Notation num_def R := (Itv.def (@Itv.num_sem R)).\nLocal Notation num_itv_bound R := (@map_itv_bound _ R intr).\n\n(*This local notation defines a predicate that asserts a natural number belongs to the set of numbers represented by a given interval.*)\nLocal Notation nat_spec := (Itv.spec Itv.nat_sem).\n(*This local notation defines the type of natural numbers that are guaranteed to belong to a specific interval.*)\nLocal Notation nat_def := (Itv.def Itv.nat_sem).\n\nSection POrder.\nContext d (T : porderType d) (f : interval int -> T -> bool) (i : Itv.t).\n(*This local notation defines a subtype of a preordered type, consisting of all elements that satisfy a given boolean predicate associated with an interval.*)\nLocal Notation itv := (Itv.def f i).\nHB.instance Definition _ := [isSub for @Itv.r T f i].\n(*A local notation that provides access to the underlying numerical value from a corresponding interval-bounded number.*)\nLocal Notation nR := (num_def R (Itv.Real i)).\n\n(*This lemma asserts that the 'less than or equal to' relation is total on the type of numbers constrained to a specific real interval, which means that for any two numbers in this type, one is less than or equal to the other.*)\nLemma itv_le_total_subproof : total (<=%O : rel nR).\n\n(*This lemma states that for any given element of a type, that element satisfies the predicate associated with the universal interval.*)\nLemma top_typ_spec T f (x : T) : Itv.spec f Itv.Top x.\n\nCanonical top_typ T f := Itv.Typ (@top_typ_spec T f).\n\n(*This lemma states that any element of a real domain type satisfies the predicate for belonging to the interval of all real numbers.*)\nLemma real_domain_typ_spec (R : realDomainType) (x : R) :\n num_spec (Itv.Real `]-oo, +oo[) x.\n\nCanonical real_domain_typ (R : realDomainType) :=\n Itv.Typ (@real_domain_typ_spec R).\n\n(*This lemma states that any element of a real field type satisfies the predicate for belonging to the interval of all real numbers.*)\nLemma real_field_typ_spec (R : realFieldType) (x : R) :\n num_spec (Itv.Real `]-oo, +oo[) x.\n\nCanonical real_field_typ (R : realFieldType) :=\n Itv.Typ (@real_field_typ_spec R).\n\n(*This lemma states that any natural number satisfies the predicate for belonging to the interval of non-negative real numbers.*)\nLemma nat_typ_spec (x : nat) : nat_spec (Itv.Real `[0, +oo[) x.\n\nCanonical nat_typ := Itv.Typ nat_typ_spec.\n\n(*This lemma states that for any element belonging to a type constrained by an interval, the element satisfies the predicate for that same interval.*)\nLemma typ_inum_spec (i : Itv.t) (xt : Itv.typ i) (x : Itv.sort xt) :\n Itv.spec (@Itv.sort_sem _ xt) i x.\n\nCanonical typ_inum (i : Itv.t) (xt : Itv.typ i) (x : Itv.sort xt) :=\n Itv.mk (typ_inum_spec x).\n\nEnd TypInstances.\nExport (canonicals) TypInstances.\n\n(*This class provides a mechanism to assert that a given boolean binary predicate evaluates to true for two specific inputs, enabling typeclass-based proof search.*)\nClass unify {T} f (x y : T) := Unify : f x y = true.\n#[export] Hint Mode unify + + + + : typeclass_instances.\n(*This class provides a mechanism, intended to be resolved by computation, to assert that a given boolean binary predicate evaluates to true for two specific inputs.*)\nClass unify' {T} f (x y : T) := Unify' : f x y = true.\n(*This instance provides a rule that allows a proof of the computationally-solvable unification predicate to be used as a proof for the general unification predicate.*)\n#[export] Instance unify'P {T} f (x y : T) : unify' f x y -> unify f x y := id.\n#[export]\nHint Extern 0 (unify' _ _ _) => vm_compute; reflexivity : typeclass_instances.\n\nNotation unify_itv ix iy := (unify Itv.sub ix iy).\n\n(*This instance declares that any interval is a sub-interval of the universal interval.*)\n#[export] Instance top_wider_anything i : unify_itv i Itv.Top.\n\n(*This instance declares that any given real interval is a sub-interval of the interval representing all real numbers.*)\n#[export] Instance real_wider_anyreal i :\n unify_itv (Itv.Real i) (Itv.Real `]-oo, +oo[).\n\nSection NumDomainTheory.\nContext {R : numDomainType} {i : Itv.t}.\nImplicit Type x : num_def R i.\n\n(*This lemma states that the boolean result of comparing two numerical interval bounds within a numerical domain is the same as the boolean result of comparing their original symbolic integer representations.*)\nLemma le_num_itv_bound (x y : itv_bound int) :\n (num_itv_bound R x <= num_itv_bound R y)%O = (x <= y)%O.\n\n(*This lemma states that comparing a numerical value derived from a symbolic interval bound to a specified left endpoint in a numerical domain is equivalent to comparing the original symbolic bound to the symbolic representation of that left endpoint.*)\nLemma num_itv_bound_le_BLeft (x : itv_bound int) (y : int) :\n (num_itv_bound R x <= BLeft (y%:~R : R))%O = (x <= BLeft y)%O.\n\n(*This lemma states that comparing a specified right endpoint in a numerical domain to a numerical value derived from a symbolic interval bound is equivalent to comparing the symbolic representation of that right endpoint to the original symbolic bound.*)\nLemma BRight_le_num_itv_bound (x : int) (y : itv_bound int) :\n (BRight (x%:~R : R) <= num_itv_bound R y)%O = (BRight x <= y)%O.\n\n(*This lemma states that if one interval is a sub-interval of another, then any number satisfying the predicate for the first interval also satisfies the predicate for the second interval.*)\nLemma num_spec_sub (x y : Itv.t) : Itv.sub x y ->\n forall z : R, num_spec x z -> num_spec y z.\n\n(*This definition specifies an empty interval, represented as the real interval from one to zero.*)\nDefinition empty_itv := Itv.Real `[1, 0]%Z.\n\n(*This lemma states that a given non-empty interval cannot be a sub-interval of the empty interval.*)\nLemma bottom x : ~ unify_itv i empty_itv.\n\n(*This lemma states that if a number belongs to an interval that is a sub-interval of the strictly positive real numbers, then its numerical value is greater than zero.*)\nLemma gt0 x : unify_itv i (Itv.Real `]0%Z, +oo[) -> 0 < x%:num :> R.\n\n(*This lemma states that if a number belongs to an interval that is a sub-interval of the strictly positive real numbers, then the proposition that its numerical value is less than or equal to zero is false.*)\nLemma le0F x : unify_itv i (Itv.Real `]0%Z, +oo[) -> x%:num <= 0 :> R = false.\n\n(*This lemma states that if a number belongs to an interval that is a sub-interval of the strictly negative real numbers, then its numerical value is less than zero.*)\nLemma lt0 x : unify_itv i (Itv.Real `]-oo, 0%Z[) -> x%:num < 0 :> R.\n\n(*This lemma states that if a number belongs to an interval that is a sub-interval of the strictly negative real numbers, then the proposition that its numerical value is greater than or equal to zero is false.*)\nLemma ge0F x : unify_itv i (Itv.Real `]-oo, 0%Z[) -> 0 <= x%:num :> R = false.\n\n(*This lemma states that if a number belongs to an interval that is a sub-interval of the non-negative real numbers, then its numerical value is greater than or equal to zero.*)\nLemma ge0 x : unify_itv i (Itv.Real `[0%Z, +oo[) -> 0 <= x%:num :> R.\n\n(*This lemma states that for a number known to be in the interval from zero inclusive to positive infinity, the proposition that this number is strictly less than zero is false.*)\nLemma lt0F x : unify_itv i (Itv.Real `[0%Z, +oo[) -> x%:num < 0 :> R = false.\n\n(*This lemma states that if a number is known to be in the interval from negative infinity to zero inclusive, then that number is less than or equal to zero.*)\nLemma le0 x : unify_itv i (Itv.Real `]-oo, 0%Z]) -> x%:num <= 0 :> R.\n\n(*This lemma states that for a number known to be in the interval from negative infinity to zero inclusive, the proposition that zero is strictly less than this number is false.*)\nLemma gt0F x : unify_itv i (Itv.Real `]-oo, 0%Z]) -> 0 < x%:num :> R = false.\n\n(*This lemma states that any number known to be in the interval from negative infinity to positive infinity is comparable to zero.*)\nLemma cmp0 x : unify_itv i (Itv.Real `]-oo, +oo[) -> 0 >=< x%:num.\n\n(*This lemma states that if the interval associated with a number does not contain zero, then that number is not equal to zero.*)\nLemma neq0 x :\n unify (fun ix iy => ~~ Itv.sub ix iy) (Itv.Real `[0%Z, 0%Z]) i ->\n x%:num != 0 :> R.\n\n(*This lemma states that if the interval associated with a number does not contain zero, then the proposition that this number is equal to zero is false.*)\nLemma eq0F x :\n unify (fun ix iy => ~~ Itv.sub ix iy) (Itv.Real `[0%Z, 0%Z]) i ->\n x%:num == 0 :> R = false.\n\n(*This lemma states that if a number is known to be in the interval from negative infinity to one exclusive, then that number is strictly less than one.*)\nLemma lt1 x : unify_itv i (Itv.Real `]-oo, 1%Z[) -> x%:num < 1 :> R.\n\n(*This lemma states that for a number known to be in the interval from negative infinity to one exclusive, the proposition that one is less than or equal to this number is false.*)\nLemma ge1F x : unify_itv i (Itv.Real `]-oo, 1%Z[) -> 1 <= x%:num :> R = false.\n\n(*This lemma states that if a number is known to be in the interval from negative infinity to one inclusive, then that number is less than or equal to one.*)\nLemma le1 x : unify_itv i (Itv.Real `]-oo, 1%Z]) -> x%:num <= 1 :> R.\n\n(*This lemma states that for a number known to be in the interval from negative infinity to one inclusive, the proposition that one is strictly less than this number is false.*)\nLemma gt1F x : unify_itv i (Itv.Real `]-oo, 1%Z]) -> 1 < x%:num :> R = false.\n\n(*This lemma states that if a number satisfies the specification for a given interval, and that interval is a sub-interval of a second, wider interval, then the number also satisfies the specification for the wider interval.*)\nLemma widen_itv_subproof x i' : Itv.sub i i' -> num_spec i' x%:num.\n\n(*This definition takes a number with an associated interval and a proof that this interval is contained within a second, wider interval, and returns a value representing the same number, but now formally associated with the wider interval.*)\nDefinition widen_itv x i' (uni : unify_itv i i') :=\n Itv.mk (widen_itv_subproof x uni).\n\n(*This lemma states that applying an interval widening operation to a number without actually changing the interval results in a value equal to the original number.*)\nLemma widen_itvE x (uni : unify_itv i i) : @widen_itv x i uni = x.\n\n(*This lemma states that if a number's associated interval is a sub-interval of the positive real numbers, then widening its interval to be the interval of all positive real numbers does not change its underlying numerical value.*)\nLemma posE x (uni : unify_itv i (Itv.Real `]0%Z, +oo[)) :\n (widen_itv x%:num%:itv uni)%:num = x%:num.\n\n(*This lemma states that if a number's associated interval is a sub-interval of the non-negative real numbers, then widening its interval to be the interval of all non-negative real numbers does not change its underlying numerical value.*)\nLemma nngE x (uni : unify_itv i (Itv.Real `[0%Z, +oo[)) :\n (widen_itv x%:num%:itv uni)%:num = x%:num.\n\nEnd NumDomainTheory.\n\nArguments bottom {R i} _ {_}.\nArguments gt0 {R i} _ {_}.\nArguments le0F {R i} _ {_}.\nArguments lt0 {R i} _ {_}.\nArguments ge0F {R i} _ {_}.\nArguments ge0 {R i} _ {_}.\nArguments lt0F {R i} _ {_}.\nArguments le0 {R i} _ {_}.\nArguments gt0F {R i} _ {_}.\nArguments cmp0 {R i} _ {_}.\nArguments neq0 {R i} _ {_}.\nArguments eq0F {R i} _ {_}.\nArguments lt1 {R i} _ {_}.\nArguments ge1F {R i} _ {_}.\nArguments le1 {R i} _ {_}.\nArguments gt1F {R i} _ {_}.\nArguments widen_itv {R i} _ {_ _}.\nArguments widen_itvE {R i} _ {_}.\nArguments posE {R i} _ {_}.\nArguments nngE {R i} _ {_}.\n\n(*A notation used in proofs to automatically apply the lemma which proves that a number is strictly greater than zero based on its known interval information.*)\nNotation \"[ 'gt0' 'of' x ]\" := (ltac:(refine (gt0 x%:itv))) (only parsing).\n(*A notation used in proofs to automatically apply the lemma which proves that a number is strictly less than zero based on its known interval information.*)\nNotation \"[ 'lt0' 'of' x ]\" := (ltac:(refine (lt0 x%:itv))) (only parsing).\n(*A notation used in proofs to automatically apply the lemma which proves that a number is greater than or equal to zero based on its known interval information.*)\nNotation \"[ 'ge0' 'of' x ]\" := (ltac:(refine (ge0 x%:itv))) (only parsing).\n(*A notation used in proofs to automatically apply the lemma which proves that a number is less than or equal to zero based on its known interval information.*)\nNotation \"[ 'le0' 'of' x ]\" := (ltac:(refine (le0 x%:itv))) (only parsing).\n(*A notation used in proofs to automatically apply the lemma which proves that a number is comparable to zero based on its known interval information.*)\nNotation \"[ 'cmp0' 'of' x ]\" := (ltac:(refine (cmp0 x%:itv))) (only parsing).\n(*A notation used in proofs to automatically apply the lemma which proves that a number is not equal to zero based on its known interval information.*)\nNotation \"[ 'neq0' 'of' x ]\" := (ltac:(refine (neq0 x%:itv))) (only parsing).\n\n#[export] Hint Extern 0 (is_true (0%R < _)%R) => solve [apply: gt0] : core.\n#[export] Hint Extern 0 (is_true (_ < 0%R)%R) => solve [apply: lt0] : core.\n#[export] Hint Extern 0 (is_true (0%R <= _)%R) => solve [apply: ge0] : core.\n#[export] Hint Extern 0 (is_true (_ <= 0%R)%R) => solve [apply: le0] : core.\n#[export] Hint Extern 0 (is_true (_ \\is Num.real)) => solve [apply: cmp0]\n : core.\n#[export] Hint Extern 0 (is_true (0%R >=< _)%R) => solve [apply: cmp0] : core.\n#[export] Hint Extern 0 (is_true (_ != 0%R)) => solve [apply: neq0] : core.\n#[export] Hint Extern 0 (is_true (_ < 1%R)%R) => solve [apply: lt1] : core.\n#[export] Hint Extern 0 (is_true (_ <= 1%R)%R) => solve [apply: le1] : core.\n\nNotation \"x %:i01\" := (widen_itv x%:itv : {i01 _}) (only parsing) : ring_scope.\n(*A notation that widens the interval of a given number to the interval from zero to one inclusive, effectively coercing the number into a type that certifies it belongs to this range.*)\nNotation \"x %:i01\" := (@widen_itv _ _\n (@Itv.from _ _ _ (Phantom _ x)) (Itv.Real `[0, 1]%Z) _)\n (only printing) : ring_scope.\nNotation \"x %:pos\" := (widen_itv x%:itv : {posnum _}) (only parsing)\n : ring_scope.\n(*A notation that widens the interval of a given number to the interval of strictly positive real numbers, from zero exclusive to positive infinity, effectively coercing the number into a type that certifies it is positive.*)\nNotation \"x %:pos\" := (@widen_itv _ _\n (@Itv.from _ _ _ (Phantom _ x)) (Itv.Real `]0%Z, +oo[) _)\n (only printing) : ring_scope.\nNotation \"x %:nng\" := (widen_itv x%:itv : {nonneg _}) (only parsing)\n : ring_scope.\n(*A notation that widens the interval of a given number to the interval of non-negative real numbers, from zero inclusive to positive infinity, effectively coercing the number into a type that certifies it is non-negative.*)\nNotation \"x %:nng\" := (@widen_itv _ _\n (@Itv.from _ _ _ (Phantom _ x)) (Itv.Real `[0%Z, +oo[) _)\n (only printing) : ring_scope.\n\nLocal Open Scope ring_scope.\n\nModule Instances.\n\nImport IntItv.\n\nSection NumDomainInstances.\nContext {R : numDomainType}.\n\n(*This lemma states that the number zero satisfies the numerical specification for the point interval containing only zero.*)\nLemma num_spec_zero : num_spec (Itv.Real `[0, 0]) (0 : R).\n\nCanonical zero_inum := Itv.mk num_spec_zero.\n\n(*This lemma states that the number one satisfies the numerical specification for the point interval containing only one.*)\nLemma num_spec_one : num_spec (Itv.Real `[1, 1]) (1 : R).\n\nCanonical one_inum := Itv.mk num_spec_one.\n\n(*This lemma establishes an equivalence for interval bounds, stating that an upper bound condition on the additive inverse of a number is equivalent to a lower bound condition on the original number.*)\nLemma opp_boundr (x : R) b :\n (BRight (- x)%R <= num_itv_bound R (opp_bound b))%O\n = (num_itv_bound R b <= BLeft x)%O.\n\n(*This lemma establishes an equivalence for interval bounds, stating that a lower bound condition on the additive inverse of a number is equivalent to an upper bound condition on the original number.*)\nLemma opp_boundl (x : R) b :\n (num_itv_bound R (opp_bound b) <= BLeft (- x)%R)%O\n = (BRight x <= num_itv_bound R b)%O.\n\n(*This lemma states that if a number belongs to a certain interval, then its additive inverse belongs to the corresponding opposite interval, which is obtained by negating the bounds and swapping them.*)\nLemma num_spec_opp (i : Itv.t) (x : num_def R i) (r := Itv.real1 opp i) :\n num_spec r (- x%:num).\n\nCanonical opp_inum (i : Itv.t) (x : num_def R i) := Itv.mk (num_spec_opp x).\n\n(*This lemma states that if the real number equivalent of a first interval bound is less than or equal to the lower bound defining a first real number, and the real number equivalent of a second interval bound is less than or equal to the lower bound defining a second real number, then the real number equivalent of the lower bound of their sum is less than or equal to the lower bound defining their sum.*)\nLemma num_itv_add_boundl (x1 x2 : R) b1 b2 :\n (num_itv_bound R b1 <= BLeft x1)%O -> (num_itv_bound R b2 <= BLeft x2)%O ->\n (num_itv_bound R (add_boundl b1 b2) <= BLeft (x1 + x2)%R)%O.\n\n(*This lemma states that if the upper bound defining a first real number is less than or equal to the real number equivalent of a first interval bound, and the upper bound defining a second real number is less than or equal to the real number equivalent of a second interval bound, then the upper bound defining their sum is less than or equal to the real number equivalent of the upper bound of their sum.*)\nLemma num_itv_add_boundr (x1 x2 : R) b1 b2 :\n (BRight x1 <= num_itv_bound R b1)%O -> (BRight x2 <= num_itv_bound R b2)%O ->\n (BRight (x1 + x2)%R <= num_itv_bound R (add_boundr b1 b2))%O.\n\n(*This lemma states that the sum of the real values of two interval-defined numbers satisfies the specification for membership in the interval computed by adding their respective defining intervals.*)\nLemma num_spec_add (xi yi : Itv.t) (x : num_def R xi) (y : num_def R yi)\n (r := Itv.real2 add xi yi) :\n num_spec r (x%:num + y%:num).\n\nCanonical add_inum (xi yi : Itv.t) (x : num_def R xi) (y : num_def R yi) :=\n Itv.mk (num_spec_add x y).\n\n(*This inductive type specifies the sign of a real number based on its interval bounds. It provides constructors for cases where the number is known to be zero, non-negative, non-positive, or when its sign cannot be determined from the interval.*)\nVariant sign_spec (l u : itv_bound int) (x : R) : signi -> Set :=\n(**)\n | ISignEqZero : l = BLeft 0 -> u = BRight 0 -> x = 0 ->\n sign_spec l u x (Known EqZero)\n(**)\n | ISignNonNeg : (BLeft 0%:Z <= l)%O -> (BRight 0%:Z < u)%O -> 0 <= x ->\n sign_spec l u x (Known NonNeg)\n(**)\n | ISignNonPos : (l < BLeft 0%:Z)%O -> (u <= BRight 0%:Z)%O -> x <= 0 ->\n sign_spec l u x (Known NonPos)\n(*A constructor for an interval sign type, indicating that the interval contains both positive and negative numbers.*)\n | ISignBoth : (l < BLeft 0%:Z)%O -> (BRight 0%:Z < u)%O -> x \\in Num.real ->\n sign_spec l u x Unknown.\n\n(*This lemma states that for any real number lying within an interval defined by a lower and an upper integer bound, the sign specification for that number corresponds to the sign computed directly from that interval.*)\nLemma signP (l u : itv_bound int) (x : R) :\n (num_itv_bound R l <= BLeft x)%O -> (BRight x <= num_itv_bound R u)%O ->\n x \\in Num.real ->\n sign_spec l u x (sign (Interval l u)).\n\n(*This lemma states that if two interval bounds are both non-negative, and two real numbers are respectively lower-bounded by the real equivalents of these bounds, then the product of the two real numbers is lower-bounded by the real equivalent of the lower bound of the product of the intervals.*)\nLemma num_itv_mul_boundl b1 b2 (x1 x2 : R) :\n (BLeft 0%:Z <= b1 -> BLeft 0%:Z <= b2 ->\n num_itv_bound R b1 <= BLeft x1 ->\n num_itv_bound R b2 <= BLeft x2 ->\n num_itv_bound R (mul_boundl b1 b2) <= BLeft (x1 * x2))%O.\n\n(*This lemma states that if two real numbers are non-negative and are respectively upper-bounded by the real equivalents of two interval bounds, then their product is upper-bounded by the real equivalent of the upper bound of the product of the intervals.*)\nLemma num_itv_mul_boundr b1 b2 (x1 x2 : R) :\n (0 <= x1 -> 0 <= x2 ->\n BRight x1 <= num_itv_bound R b1 ->\n BRight x2 <= num_itv_bound R b2 ->\n BRight (x1 * x2) <= num_itv_bound R (mul_boundr b1 b2))%O.\n\n(*This lemma establishes a condition for the upper bound of a product of two real numbers. It states that if a first real number is non-negative, a second real number is valid, the interval bound for the second number is greater than or equal to the upper bound of zero, and both numbers are upper-bounded by the real equivalents of their respective interval bounds, then their product is upper-bounded by the real equivalent of the upper bound of the product of the intervals.*)\nLemma BRight_le_mul_boundr b1 b2 (x1 x2 : R) :\n (0 <= x1 -> x2 \\in Num.real -> BRight 0%Z <= b2 ->\n BRight x1 <= num_itv_bound R b1 ->\n BRight x2 <= num_itv_bound R b2 ->\n BRight (x1 * x2) <= num_itv_bound R (mul_boundr b1 b2))%O.\n\n(*This lemma states that the real number representations of any two integer interval bounds are always comparable.*)\nLemma comparable_num_itv_bound (x y : itv_bound int) :\n (num_itv_bound R x >=< num_itv_bound R y)%O.\n\n(*This lemma states that the real number equivalent of the minimum of two integer interval bounds is equal to the minimum of their individual real number equivalents.*)\nLemma num_itv_bound_min (x y : itv_bound int) :\n num_itv_bound R (Order.min x y)\n = Order.min (num_itv_bound R x) (num_itv_bound R y).\n\n(*This lemma states that the real number equivalent of the maximum of two integer interval bounds is equal to the maximum of their individual real number equivalents.*)\nLemma num_itv_bound_max (x y : itv_bound int) :\n num_itv_bound R (Order.max x y)\n = Order.max (num_itv_bound R x) (num_itv_bound R y).\n\n(*This lemma states that the product of the real values of two interval-defined numbers satisfies the specification for membership in the interval computed by multiplying their respective defining intervals.*)\nLemma num_spec_mul (xi yi : Itv.t) (x : num_def R xi) (y : num_def R yi)\n (r := Itv.real2 mul xi yi) :\n num_spec r (x%:num * y%:num).\n\nCanonical mul_inum (xi yi : Itv.t) (x : num_def R xi) (y : num_def R yi) :=\n Itv.mk (num_spec_mul x y).\n\n(*This lemma states that the minimum of the real values of two interval-defined numbers satisfies the specification for membership in the interval computed by applying the minimum operation to their respective defining intervals.*)\nLemma num_spec_min (xi yi : Itv.t) (x : num_def R xi) (y : num_def R yi)\n (r := Itv.real2 min xi yi) :\n num_spec r (Order.min x%:num y%:num).\n\n(*This lemma states that the maximum of the real values of two interval-defined numbers satisfies the specification for membership in the interval computed by applying the maximum operation to their respective defining intervals.*)\nLemma num_spec_max (xi yi : Itv.t) (x : num_def R xi) (y : num_def R yi)\n (r := Itv.real2 max xi yi) :\n num_spec r (Order.max x%:num y%:num).\n\n(*This record defines a structure for types that support minimum and maximum operations compatible with interval arithmetic. It packages a preordered type, a semantic function mapping elements to integer intervals, and proofs ensuring that the minimum and maximum of interval-defined elements respect the interval computations.*)\nRecord min_max_typ d := MinMaxTyp {\n min_max_sort : porderType d;\n #[canonical=no]\n min_max_sem : interval int -> min_max_sort -> bool;\n #[canonical=no]\n min_max_minP : forall (xi yi : Itv.t) (x : Itv.def min_max_sem xi)\n (y : Itv.def min_max_sem yi),\n let: r := Itv.real2 min xi yi in\n Itv.spec min_max_sem r (Order.min x%:num y%:num);\n #[canonical=no]\n min_max_maxP : forall (xi yi : Itv.t) (x : Itv.def min_max_sem xi)\n (y : Itv.def min_max_sem yi),\n let: r := Itv.real2 max xi yi in\n Itv.spec min_max_sem r (Order.max x%:num y%:num);\n}.\n\nCanonical min_typ_inum d (t : min_max_typ d) (xi yi : Itv.t)\n (x : Itv.def (@min_max_sem d t) xi) (y : Itv.def (@min_max_sem d t) yi)\n (r := Itv.real2 min xi yi) :=\n Itv.mk (min_max_minP x y).\n\nCanonical max_typ_inum d (t : min_max_typ d) (xi yi : Itv.t)\n (x : Itv.def (@min_max_sem d t) xi) (y : Itv.def (@min_max_sem d t) yi)\n (r := Itv.real2 min xi yi) :=\n Itv.mk (min_max_maxP x y).\n\nCanonical num_min_max_typ := MinMaxTyp num_spec_min num_spec_max.\n\n(*This lemma states that the interval specification for a natural number is equivalent to the interval specification for its embedding as a real number.*)\nLemma nat_num_spec (i : Itv.t) (n : nat) : nat_spec i n = num_spec i (n%:R : R).\n\n(*This definition computes the resulting interval from multiplying an interval by another interval, with special handling for unbounded intervals. It is used for operations involving scalar multiplication by a natural number.*)\nDefinition natmul_itv (i1 i2 : Itv.t) : Itv.t :=\n match i1, i2 with\n | Itv.Top, _ => Itv.Top\n | _, Itv.Top => Itv.Real `]-oo, +oo[\n | Itv.Real i1, Itv.Real i2 => Itv.Real (mul i1 i2)\n end.\nArguments natmul_itv /.\n\n(*This lemma states that the scalar product of an interval-defined real number and an interval-defined natural number satisfies the specification for membership in the interval computed for natural number multiplication.*)\nLemma num_spec_natmul (xi ni : Itv.t) (x : num_def R xi) (n : nat_def ni)\n (r := natmul_itv xi ni) :\n num_spec r (x%:num *+ n%:num).\n\nCanonical natmul_inum (xi ni : Itv.t) (x : num_def R xi) (n : nat_def ni) :=\n Itv.mk (num_spec_natmul x n).\n\n(*This lemma states that the interval specification for an integer is equivalent to the interval specification for its embedding as a real number.*)\nLemma num_spec_int (i : Itv.t) (n : int) :\n num_spec i n = num_spec i (n%:~R : R).\n\n(*This lemma states that the scalar product of an interval-defined real number and an interval-defined integer satisfies the specification for membership in the interval computed for integer multiplication.*)\nLemma num_spec_intmul (xi ii : Itv.t) (x : num_def R xi) (i : num_def int ii)\n (r := natmul_itv xi ii) :\n num_spec r (x%:num *~ i%:num).\n\nCanonical intmul_inum (xi ni : Itv.t) (x : num_def R xi) (n : num_def int ni) :=\n Itv.mk (num_spec_intmul x n).\n\n(*This lemma states that for a function that is monotonic on the non-negative real numbers, if a real number has a specific lower interval bound, then the result of applying the function to that number is lower-bounded by a new bound derived from the original.*)\nLemma num_itv_bound_keep_pos (op : R -> R) (x : R) b :\n {homo op : x / 0 <= x} -> {homo op : x / 0 < x} ->\n (num_itv_bound R b <= BLeft x)%O ->\n (num_itv_bound R (keep_pos_bound b) <= BLeft (op x))%O.\n\n(*This lemma states that for a function that is monotonic on the non-positive real numbers, if a real number has a specific upper interval bound, then the result of applying the function to that number is upper-bounded by a new bound derived from the original.*)\nLemma num_itv_bound_keep_neg (op : R -> R) (x : R) b :\n {homo op : x / x <= 0} -> {homo op : x / x < 0} ->\n (BRight x <= num_itv_bound R b)%O ->\n (BRight (op x) <= num_itv_bound R (keep_neg_bound b))%O.\n\n(*This lemma states that the multiplicative inverse of an interval-defined real number satisfies the specification for membership in the interval computed by applying the inversion operation to its defining interval.*)\nLemma num_spec_inv (i : Itv.t) (x : num_def R i) (r := Itv.real1 inv i) :\n num_spec r (x%:num^-1).\n\nCanonical inv_inum (i : Itv.t) (x : num_def R i) := Itv.mk (num_spec_inv x).\n\n(*This lemma provides an upper bound for the exponentiation of a real number by a natural number. It asserts that if a real number is contained within an interval defined by a lower and an upper bound, its power is upper-bounded by a value computed from these bounds, particularly for cases where the number's magnitude is less than or equal to one.*)\nLemma num_itv_bound_exprn_le1 (x : R) n l u :\n (num_itv_bound R l <= BLeft x)%O ->\n (BRight x <= num_itv_bound R u)%O ->\n (BRight (x ^+ n) <= num_itv_bound R (exprn_le1_bound l u))%O.\n\n(*This lemma states that the natural number power of an interval-defined real number satisfies the specification for membership in the interval computed by applying the exponentiation operation to its defining interval.*)\nLemma num_spec_exprn (i : Itv.t) (x : num_def R i) n (r := Itv.real1 exprn i) :\n num_spec r (x%:num ^+ n).\n\nCanonical exprn_inum (i : Itv.t) (x : num_def R i) n :=\n Itv.mk (num_spec_exprn x n).\n\n(*This lemma states that raising an interval-defined real number to the power of an interval-defined integer results in a value that satisfies the specification for membership in the interval computed by applying the integer exponentiation operation to their respective defining intervals.*)\nLemma num_spec_exprz (xi ki : Itv.t) (x : num_def R xi) (k : num_def int ki)\n (r := Itv.real2 exprz xi ki) :\n num_spec r (x%:num ^ k%:num).\n\nCanonical exprz_inum (xi ki : Itv.t) (x : num_def R xi) (k : num_def int ki) :=\n Itv.mk (num_spec_exprz x k).\n\n(*This lemma states that the norm of an element from a normed module over the real numbers satisfies the interval specification corresponding to the set of all non-negative real numbers.*)\nLemma num_spec_norm {V : normedZmodType R} (x : V) :\n num_spec (Itv.Real `[0, +oo[) `|x|.\n\nCanonical norm_inum {V : normedZmodType R} (x : V) := Itv.mk (num_spec_norm x).\n\nEnd NumDomainInstances.\n\nSection RcfInstances.\nContext {R : rcfType}.\n\n(*This definition computes a new interval that contains the real square root of every non-negative number within a given input interval, resulting in an interval of non-negative or strictly positive numbers.*)\nDefinition sqrt_itv (i : Itv.t) : Itv.t :=\n match i with\n | Itv.Top => Itv.Real `[0%Z, +oo[\n | Itv.Real (Interval l u) =>\n match l with\n | BSide b 0%Z => Itv.Real (Interval (BSide b 0%Z) +oo)\n | BSide b (Posz (S _)) => Itv.Real `]0%Z, +oo[\n | _ => Itv.Real `[0, +oo[\n end\n end.\nArguments sqrt_itv /.\n\n(*This lemma states that the real square root of a numerical value from a given interval is contained within the interval computed by the corresponding interval square root function.*)\nLemma num_spec_sqrt (i : Itv.t) (x : num_def R i) (r := sqrt_itv i) :\n num_spec r (Num.sqrt x%:num).\n\nCanonical sqrt_inum (i : Itv.t) (x : num_def R i) := Itv.mk (num_spec_sqrt x).\n\nEnd RcfInstances.\n\nSection NumClosedFieldInstances.\nContext {R : numClosedFieldType}.\n\n(*This definition computes an output real interval for a value obtained by applying the complex square root function. It yields an unbounded real interval if the input number's interval can contain non-positive values, and the interval of non-negative real numbers otherwise.*)\nDefinition sqrtC_itv (i : Itv.t) : Itv.t :=\n match i with\n | Itv.Top => Itv.Top\n | Itv.Real (Interval l u) =>\n match l with\n | BSide b (Posz _) => Itv.Real (Interval (BSide b 0%Z) +oo)\n | _ => Itv.Top\n end\n end.\nArguments sqrtC_itv /.\n\n(*This lemma states that the numerical value resulting from a complex square root operation on a number from a given interval is correctly bounded by the interval computed by the complex square root interval function.*)\nLemma num_spec_sqrtC (i : Itv.t) (x : num_def R i) (r := sqrtC_itv i) :\n num_spec r (sqrtC x%:num).\n\nCanonical sqrtC_inum (i : Itv.t) (x : num_def R i) := Itv.mk (num_spec_sqrtC x).\n\nEnd NumClosedFieldInstances.\n\nSection NatInstances.\nLocal Open Scope nat_scope.\nImplicit Type (n : nat).\n\n(*This lemma states that the natural number zero belongs to the singleton interval containing only the real number zero.*)\nLemma nat_spec_zero : nat_spec (Itv.Real `[0, 0]%Z) 0. \n\nCanonical zeron_inum := Itv.mk nat_spec_zero.\n\n(*This lemma states that the sum of two natural numbers is contained within the interval that results from the interval addition of their respective containing intervals.*)\nLemma nat_spec_add (xi yi : Itv.t) (x : nat_def xi) (y : nat_def yi)\n (r := Itv.real2 add xi yi) :\n nat_spec r (x%:num + y%:num).\n\nCanonical addn_inum (xi yi : Itv.t) (x : nat_def xi) (y : nat_def yi) :=\n Itv.mk (nat_spec_add x y).\n\n(*This lemma states that the successor of a natural number is contained within the interval obtained by adding the number's containing interval to the singleton interval containing one.*)\nLemma nat_spec_succ (i : Itv.t) (n : nat_def i)\n (r := Itv.real2 add i (Itv.Real `[1, 1]%Z)) :\n nat_spec r (S n%:num).\n\nCanonical succn_inum (i : Itv.t) (n : nat_def i) := Itv.mk (nat_spec_succ n).\n\n(*This lemma states that twice a natural number is contained within the interval resulting from the interval addition of the number's containing interval with itself.*)\nLemma nat_spec_double (i : Itv.t) (n : nat_def i) (r := Itv.real2 add i i) :\n nat_spec r (n%:num.*2).\n\nCanonical double_inum (i : Itv.t) (x : nat_def i) := Itv.mk (nat_spec_double x).\n\n(*This lemma states that the product of two natural numbers is contained within the interval that results from the interval multiplication of their respective containing intervals.*)\nLemma nat_spec_mul (xi yi : Itv.t) (x : nat_def xi) (y : nat_def yi)\n (r := Itv.real2 mul xi yi) :\n nat_spec r (x%:num * y%:num).\n\nCanonical muln_inum (xi yi : Itv.t) (x : nat_def xi) (y : nat_def yi) :=\n Itv.mk (nat_spec_mul x y).\n\n(*This lemma states that a natural number raised to a natural number power is contained within the interval computed by applying the corresponding interval exponentiation function to the containing interval of the base.*)\nLemma nat_spec_exp (i : Itv.t) (x : nat_def i) n (r := Itv.real1 exprn i) :\n nat_spec r (x%:num ^ n).\n\nCanonical expn_inum (i : Itv.t) (x : nat_def i) n := Itv.mk (nat_spec_exp x n).\n\n(*This lemma states that the minimum of two natural numbers is contained within the interval resulting from the interval minimum of their respective containing intervals.*)\nLemma nat_spec_min (xi yi : Itv.t) (x : nat_def xi) (y : nat_def yi)\n (r := Itv.real2 min xi yi) :\n nat_spec r (minn x%:num y%:num).\n\nCanonical minn_inum (xi yi : Itv.t) (x : nat_def xi) (y : nat_def yi) :=\n Itv.mk (nat_spec_min x y).\n\n(*This lemma states that the maximum of two natural numbers is contained within the interval resulting from the interval maximum of their respective containing intervals.*)\nLemma nat_spec_max (xi yi : Itv.t) (x : nat_def xi) (y : nat_def yi)\n (r := Itv.real2 max xi yi) :\n nat_spec r (maxn x%:num y%:num).\n\nCanonical maxn_inum (xi yi : Itv.t) (x : nat_def xi) (y : nat_def yi) :=\n Itv.mk (nat_spec_max x y).\n\nCanonical nat_min_max_typ := MinMaxTyp nat_spec_min nat_spec_max.\n\n(*This lemma states that the factorial of any natural number is a value contained in the interval of real numbers greater than or equal to one.*)\nLemma nat_spec_factorial (n : nat) : nat_spec (Itv.Real `[1%Z, +oo[) n`!.\n\nCanonical factorial_inum n := Itv.mk (nat_spec_factorial n).\n\nEnd NatInstances.\n\nSection IntInstances.\n\n(*This lemma states that any non-negative integer is contained within the interval of real numbers greater than or equal to zero.*)\nLemma num_spec_Posz n : num_spec (Itv.Real `[0, +oo[) (Posz n).\n\nCanonical Posz_inum n := Itv.mk (num_spec_Posz n).\n\n(*This lemma states that any negative integer is contained within the interval of real numbers less than or equal to negative one.*)\nLemma num_spec_Negz n : num_spec (Itv.Real `]-oo, -1]) (Negz n).\n\nCanonical Negz_inum n := Itv.mk (num_spec_Negz n).\n\nEnd IntInstances.\n\nEnd Instances.\nExport (canonicals) Instances.\n\nSection Morph.\nContext {R : numDomainType} {i : Itv.t}.\n(*This notation provides a shorthand for the type of numbers that are known to belong to a specific interval.*)\nLocal Notation nR := (num_def R i).\nImplicit Types x y : nR.\n(*A local notation representing the numerical value component associated with a number that is certified to be within a specific interval.*)\nLocal Notation num := (@num R (@Itv.num_sem R) i).\n\n(*This lemma states that the function for extracting the underlying numerical value from a number with an associated interval preserves equality.*)\nLemma num_eq : {mono num : x y / x == y}. \n(*This lemma states that the function for extracting an underlying numerical value is monotonic with respect to the less-than-or-equal relation.*)\nLemma num_le : {mono num : x y / (x <= y)%O}. \n(*This lemma states that the function for extracting an underlying numerical value is monotonic with respect to the strict less-than relation.*)\nLemma num_lt : {mono num : x y / (x < y)%O}. \n(*This lemma states that extracting the underlying value of the minimum of two numbers with interval information is equivalent to taking the minimum of their extracted underlying values.*)\nLemma num_min : {morph num : x y / Order.min x y}.\n\n(*This lemma states that extracting the underlying value of the maximum of two numbers with interval information is equivalent to taking the maximum of their extracted underlying values.*)\nLemma num_max : {morph num : x y / Order.max x y}.\n\nEnd Morph.\n\nSection MorphNum.\nContext {R : numDomainType}.\n\n(*This lemma states that the absolute value of a number, when viewed as a non-negative numerical type, is zero if and only if the original number is zero.*)\nLemma num_abs_eq0 (a : R) : (`|a|%:nng == 0%:nng) = (a == 0).\n\nEnd MorphNum.\n\nSection MorphReal.\nContext {R : numDomainType} {i : interval int}.\n(*This local notation defines the type of numbers from a given numerical domain that are guaranteed to belong to a specific real interval.*)\nLocal Notation nR := (num_def R (Itv.Real i)).\nImplicit Type x y : nR.\n(*A notation that provides a coercion to view elements of the non-negative numerical type as numbers, enabling the use of standard numerical operations like maximum and minimum.*)\nLocal Notation num := (@num R (@Itv.num_sem R) i).\n\n(*This lemma states that a number is less than or equal to the maximum of two other numbers if and only if it is less than or equal to at least one of those two numbers.*)\nLemma num_le_max a x y :\n a <= Num.max x%:num y%:num = (a <= x%:num) || (a <= y%:num).\n\n(*This lemma states that the maximum of two numbers is less than or equal to a third number if and only if both of the original two numbers are less than or equal to that third number.*)\nLemma num_ge_max a x y :\n Num.max x%:num y%:num <= a = (x%:num <= a) && (y%:num <= a).\n\n(*This lemma states that a number is less than or equal to the minimum of two other numbers if and only if it is less than or equal to both of those numbers.*)\nLemma num_le_min a x y :\n a <= Num.min x%:num y%:num = (a <= x%:num) && (a <= y%:num).\n\n(*This lemma states that the minimum of two numbers is less than or equal to a third number if and only if at least one of the original two numbers is less than or equal to that third number.*)\nLemma num_ge_min a x y :\n Num.min x%:num y%:num <= a = (x%:num <= a) || (y%:num <= a).\n\n(*This lemma states that a number is strictly less than the maximum of two other numbers if and only if it is strictly less than at least one of those two numbers.*)\nLemma num_lt_max a x y :\n a < Num.max x%:num y%:num = (a < x%:num) || (a < y%:num).\n\n(*This lemma states that the maximum of two numbers is strictly less than a third number if and only if both of the original two numbers are strictly less than that third number.*)\nLemma num_gt_max a x y :\n Num.max x%:num y%:num < a = (x%:num < a) && (y%:num < a).\n\n(*This lemma states that a number is strictly less than the minimum of two other numbers if and only if it is strictly less than both of those numbers.*)\nLemma num_lt_min a x y :\n a < Num.min x%:num y%:num = (a < x%:num) && (a < y%:num).\n\n(*This lemma states that the minimum of two numbers is strictly less than a third number if and only if at least one of the original two numbers is strictly less than that third number.*)\nLemma num_gt_min a x y :\n Num.min x%:num y%:num < a = (x%:num < a) || (y%:num < a).\n\nEnd MorphReal.\n\nSection MorphGe0.\nContext {R : numDomainType}.\n(*A generic type representing a numerical domain, which serves as the base type for various number and interval definitions.*)\nLocal Notation nR := (num_def R (Itv.Real `[0%Z, +oo[)).\nImplicit Type x y : nR.\n(*A notation for the type of non-negative numbers, defined as the set of values greater than or equal to zero within a given numerical domain.*)\nLocal Notation num := (@num R (@Itv.num_sem R) (Itv.Real `[0%Z, +oo[)).\n\n(*This lemma states that for a number known to be non-negative, the proposition that its absolute value is less than or equal to a second number is equivalent to the proposition that the original number itself is less than or equal to the second number.*)\nLemma num_abs_le a x : 0 <= a -> (`|a|%:nng <= x) = (a <= x%:num).\n\n(*This lemma states that for a number known to be non-negative, the proposition that its absolute value is strictly less than a second number is equivalent to the proposition that the original number itself is strictly less than the second number.*)\nLemma num_abs_lt a x : 0 <= a -> (`|a|%:nng < x) = (a < x%:num).\n\nEnd MorphGe0.\n\nSection ItvNum.\nContext (R : numDomainType).\nContext (x : R) (l u : itv_bound int).\nContext (x_real : x \\in Num.real).\nContext (l_le_x : (num_itv_bound R l <= BLeft x)%O).\nContext (x_le_u : (BRight x <= num_itv_bound R u)%O).\n(*This lemma asserts that a given number from a numerical domain satisfies the specification of belonging to the real interval defined by a lower and an upper integer bound, given proofs that the number is indeed between these bounds.*)\nLemma itvnum_subdef : num_spec (Itv.Real (Interval l u)) x.\n\n(*This definition constructs a number object that bundles a given number from a numerical domain with a proof that this number lies within a specific real interval defined by a lower and an upper integer bound.*)\nDefinition ItvNum : num_def R (Itv.Real (Interval l u)) := Itv.mk itvnum_subdef.\nEnd ItvNum.\n\nSection ItvReal.\nContext (R : realDomainType).\nContext (x : R) (l u : itv_bound int).\nContext (l_le_x : (num_itv_bound R l <= BLeft x)%O).\nContext (x_le_u : (BRight x <= num_itv_bound R u)%O).\n(*This lemma asserts that a given number from a real number domain satisfies the specification of belonging to the real interval defined by a lower and an upper integer bound, given proofs that the number is indeed between these bounds.*)\nLemma itvreal_subdef : num_spec (Itv.Real (Interval l u)) x.\n\n(*This definition constructs a number object that bundles a given real number with a proof that this number lies within a specific real interval defined by a lower and an upper integer bound.*)\nDefinition ItvReal : num_def R (Itv.Real (Interval l u)) :=\n Itv.mk itvreal_subdef.\nEnd ItvReal.\n\nSection Itv01.\nContext (R : numDomainType).\nContext (x : R) (x_ge0 : 0 <= x) (x_le1 : x <= 1).\n(*This lemma asserts that a given number from a numerical domain satisfies the specification of belonging to the real interval from zero to one, given proofs that the number is greater than or equal to zero and less than or equal to one.*)\nLemma itv01_subdef : num_spec (Itv.Real `[0%Z, 1%Z]) x.\n\n(*This definition constructs a number object that bundles a given number from a numerical domain with a proof that this number lies within the real interval from zero to one.*)\nDefinition Itv01 : num_def R (Itv.Real `[0%Z, 1%Z]) := Itv.mk itv01_subdef.\nEnd Itv01.\n\nSection Posnum.\nContext (R : numDomainType) (x : R) (x_gt0 : 0 < x).\n(*This lemma asserts that a given number from a numerical domain satisfies the specification of being a positive number, given a proof that the number is strictly greater than zero.*)\nLemma posnum_subdef : num_spec (Itv.Real `]0, +oo[) x.\n\n(*This definition constructs a positive number object by bundling a given number from a numerical domain with a proof that this number is strictly greater than zero.*)\nDefinition PosNum : {posnum R} := Itv.mk posnum_subdef.\nEnd Posnum.\n\nSection Nngnum.\nContext (R : numDomainType) (x : R) (x_ge0 : 0 <= x).\n(*This lemma asserts that a given number from a numerical domain satisfies the specification of being a non-negative number, given a proof that the number is greater than or equal to zero.*)\nLemma nngnum_subdef : num_spec (Itv.Real `[0, +oo[) x.\n\n(*This definition constructs a non-negative number object by bundling a given number from a numerical domain with a proof that this number is greater than or equal to zero.*)\nDefinition NngNum : {nonneg R} := Itv.mk nngnum_subdef.\nEnd Nngnum.\n\n(*This inductive type defines a specification for a number being strictly positive. It is used to connect a proof of positivity with computable boolean checks for being equal to zero, being non-negative, and being strictly positive.*)\nVariant posnum_spec (R : numDomainType) (x : R) :\n R -> bool -> bool -> bool -> Type :=\n(**)\n| IsPosnum (p : {posnum R}) : posnum_spec x (p%:num) false true true.\n\n(*This lemma provides a way to construct a `posnum_spec` certificate for any number that is proven to be strictly greater than zero, linking the mathematical property to its boolean-testable representation.*)\nLemma posnumP (R : numDomainType) (x : R) : 0 < x ->\n posnum_spec x x (x == 0) (0 <= x) (0 < x).\n\n(*This inductive type defines a specification for a number being non-negative. It is used to connect a proof of non-negativity with a computable boolean check asserting that the number is greater than or equal to zero.*)\nVariant nonneg_spec (R : numDomainType) (x : R) : R -> bool -> Type :=\n(**)\n| IsNonneg (p : {nonneg R}) : nonneg_spec x (p%:num) true.\n\n(*This lemma provides a way to construct a `nonneg_spec` certificate for any number that is proven to be greater than or equal to zero, linking the mathematical property to its boolean-testable representation.*)\nLemma nonnegP (R : numDomainType) (x : R) : 0 <= x -> nonneg_spec x x (0 <= x).\n\nSection Test1.\n\nVariable R : numDomainType.\nVariable x : {i01 R}.\n\nGoal 0%:i01 = 1%:i01 :> {i01 R}.\n\nGoal (- x%:num)%:itv = (- x%:num)%:itv :> {itv R & `[-1, 0]}.\n\nGoal (1 - x%:num)%:i01 = x.\n\nEnd Test1.\n\nSection Test2.\n\nVariable R : realDomainType.\nVariable x y : {i01 R}.\n\nGoal (x%:num * y%:num)%:i01 = x%:num%:i01.\n\nEnd Test2.\n\nModule Test3.\nSection Test3.\nVariable R : realDomainType.\n\n(*This definition specifies a function that takes two numbers from the inclusive interval from zero to one and returns a third number in the same interval, computed as one minus the product of one minus the first number and one minus the second number.*)\nDefinition s_of_pq (p q : {i01 R}) : {i01 R} :=\n (1 - ((1 - p%:num)%:i01%:num * (1 - q%:num)%:i01%:num))%:i01.\n\n(*This lemma states that applying the `s_of_pq` function to a number from the inclusive interval from zero to one and the number zero yields the original number, establishing zero as the right-neutral element for this operation.*)\nLemma s_of_p0 (p : {i01 R}) : s_of_pq p 0%:i01 = p.\n\nEnd Test3.", - "algebra.rat": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import prime fintype finfun bigop order tuple ssralg.\nFrom mathcomp Require Import countalg div ssrnum ssrint archimedean poly zmodp.\nFrom mathcomp Require Import polydiv intdiv matrix mxalgebra vector.\n\nImport Order.TTheory GRing.Theory Num.Theory.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nReserved Notation \"[ 'rat' x // y ]\" (format \"[ 'rat' x // y ]\").\nReserved Notation \"n %:Q\" (left associativity, format \"n %:Q\").\n\nLocal Open Scope ring_scope.\n(*This notation provides a local alias for the standard sign function on numerical types.*)\nLocal Notation sgr := Num.sg.\n\n(*This record defines a rational number from a pair of integers representing the numerator and denominator, with the constraints that the denominator must be positive and that the absolute values of the numerator and denominator must be coprime.*)\nRecord rat : Set := Rat {\n valq : (int * int);\n _ : (0 < valq.2) && coprime `|valq.1| `|valq.2|\n}.\n\nBind Scope ring_scope with rat.\nDelimit Scope rat_scope with Q.\n\n(*This definition constructs a rational number from a given integer by setting the numerator to the integer and the denominator to one.*)\nDefinition ratz (n : int) := @Rat (n, 1) (coprimen1 _).\n\n(*This instance declares that the type of rational numbers can be treated as a subtype, where the embedding is given by the function that extracts the underlying canonical pair of integers.*)\nDefinition rat_isSub := Eval hnf in [isSub for valq].\nHB.instance Definition _ := rat_isSub.\n#[hnf] HB.instance Definition _ := [Equality of rat by <:].\nHB.instance Definition _ := [Countable of rat by <:].\n\n(*This definition provides a function that returns the integer numerator of a given rational number.*)\nDefinition numq x := (valq x).1.\n(*This definition provides a function that returns the integer denominator of a given rational number.*)\nDefinition denq x := (valq x).2.\nArguments numq : simpl never.\nArguments denq : simpl never.\n\n(*This lemma states that the denominator of any rational number is strictly greater than zero.*)\nLemma denq_gt0 x : 0 < denq x.\n\n#[global] Hint Resolve denq_gt0 : core.\n\n(*This definition establishes that the denominator of any rational number is greater than or equal to zero, a property derived from it being strictly positive.*)\nDefinition denq_ge0 x := ltW (denq_gt0 x).\n\n(*This lemma states that the proposition that the denominator of a rational number is less than zero is always false.*)\nLemma denq_lt0 x : (denq x < 0) = false. \n\n(*This lemma states that the denominator of a rational number is never equal to zero.*)\nLemma denq_neq0 x : denq x != 0.\n\n#[global] Hint Resolve denq_neq0 : core.\n\n(*This lemma states that the boolean comparison of the denominator of a rational number with zero always evaluates to false.*)\nLemma denq_eq0 x : (denq x == 0) = false.\n\n(*This lemma states that the absolute value of the numerator and the absolute value of the denominator of any rational number are coprime.*)\nLemma coprime_num_den x : coprime `|numq x| `|denq x|.\n\n(*This fact states that constructing a rational number using the numerator and denominator of an existing rational number yields the original rational number.*)\nFact RatK x P : @Rat (numq x, denq x) P = x.\n\n(*This definition specifies a function that takes a pair of integers representing a fraction and returns a canonical pair of integers. If the input denominator is non-zero, it simplifies the fraction by dividing the numerator and denominator by the greatest common divisor of their absolute values and adjusts the sign to ensure the denominator is positive. If the input denominator is zero, it returns the pair representing zero over one.*)\nDefinition fracq_subdef x :=\n if x.2 != 0 then let g := gcdn `|x.1| `|x.2| in\n ((-1) ^ ((x.2 < 0) (+) (x.1 < 0)) * (`|x.1| %/ g)%:Z, (`|x.2| %/ g)%:Z)\n else (0, 1).\nArguments fracq_subdef /.\n\n(*This definition provides an optimized function that checks if a given pair of integers representing a fraction is already in canonical form, which means having a positive denominator and coprime components. If so, the function returns the pair unchanged; otherwise, it applies a full simplification procedure.*)\nDefinition fracq_opt_subdef (x : int * int) :=\n if (0 < x.2) && coprime `|x.1| `|x.2| then x else fracq_subdef x.\n\n(*This lemma states that the result of applying the optimized fraction simplification function to a pair of integers is always equal to the result of applying the standard simplification function.*)\nLemma fracq_opt_subdefE x : fracq_opt_subdef x = fracq_subdef x.\n\n(*This fact asserts that for any given pair of integers, the pair resulting from the fraction simplification function always has a positive second component, and the absolute values of its two components are coprime.*)\nFact fracq_subproof x (y := fracq_opt_subdef x) :\n (0 < y.2) && (coprime `|y.1| `|y.2|).\n\n(*This lemma states that applying the optimized fraction simplification function twice to a pair of integers produces the same result as applying the standard simplification function once.*)\nLemma fracq_opt_subdef_id x :\n fracq_opt_subdef (fracq_opt_subdef x) = fracq_subdef x.\n\n(*This definition constructs a canonical rational number from a given pair of integers by first simplifying the pair into a canonical form and then packaging it into the rational number type.*)\nDefinition fracq '((n', d')) : rat :=\n match d', n' with\n | Posz 0 as d, _ as n => Rat (fracq_subproof (1, 0))\n | _ as d, Posz _ as n | _ as d, _ as n =>\n Rat (fracq_subproof (fracq_opt_subdef (n, d)))\n end.\nArguments fracq : simpl never.\n\n(*This variant defines a type to encapsulate a proof required by the number notation system, with a single constructor that takes a pair of integers and asserts it represents a canonical fraction.*)\nVariant Irat_prf := Ifracq_subproof : (int * int) -> Irat_prf.\n(*This variant defines a type that bundles a pair of integers with its corresponding canonical form proof, serving as an intermediate representation for the number notation system.*)\nVariant Irat := IRat : (int * int) -> Irat_prf -> Irat.\n\n(*This definition provides a function to parse a number represented in standard decimal format into an optional intermediate rational number representation. It correctly handles positive and negative decimal numbers by converting them into a canonical integer fraction, but returns no value for numbers given in exponential or hexadecimal format.*)\nDefinition parse (x : Number.number) : option Irat :=\n let parse_pos i f :=\n let nf := Decimal.nb_digits f in\n let d := (10 ^ nf)%nat in\n let n := (Nat.of_uint i * d + Nat.of_uint f)%nat in\n valq (fracq (Posz n, Posz d)) in\n let parse i f :=\n match i with\n | Decimal.Pos i => parse_pos i f\n | Decimal.Neg i => let (n, d) := parse_pos i f in ((- n)%R, d)\n end in\n match x with\n | Number.Decimal (Decimal.Decimal i f) =>\n let nd := parse i f in\n Some (IRat nd (Ifracq_subproof nd))\n | Number.Decimal (Decimal.DecimalExp _ _ _) => None\n | Number.Hexadecimal _ => None\n end.\n\n(*This definition provides a function to convert an intermediate rational number representation back into an optional standard decimal number format. The conversion is successful only if the denominator's prime factorization contains no primes other than two and five; otherwise, it returns no value.*)\nDefinition print (r : Irat) : option Number.number :=\n let print_pos n d :=\n if d == 1%nat then Some (Nat.to_uint n, Decimal.Nil) else\n let d2d5 :=\n match prime_decomp d with\n | [:: (2, d2); (5, d5)] => Some (d2, d5)\n | [:: (2, d2)] => Some (d2, O)\n | [:: (5, d5)] => Some (O, d5)\n | _ => None\n end in\n match d2d5 with\n | Some (d2, d5) =>\n let f := (2 ^ (d5 - d2) * 5 ^ (d2 - d5))%nat in\n let (i, f) := edivn (n * f) (d * f) in\n Some (Nat.to_uint i, Nat.to_uint f)\n | None => None\n end in\n let print_IRat nd :=\n match nd with\n | (Posz n, Posz d) =>\n match print_pos n d with\n | Some (i, f) => Some (Decimal.Pos i, f)\n | None => None\n end\n | (Negz n, Posz d) =>\n match print_pos n.+1 d with\n | Some (i, f) => Some (Decimal.Neg i, f)\n | None => None\n end\n | (_, Negz _) => None\n end in\n match r with\n | IRat nd _ =>\n match print_IRat nd with\n | Some (i, f) => Some (Number.Decimal (Decimal.Decimal i f))\n | None => None\n end\n end.\n\nNumber Notation rat parse print (via Irat\n mapping [Rat => IRat, fracq_subproof => Ifracq_subproof])\n : rat_scope.\n\n(*This lemma states that extracting the underlying canonical integer pair from a rational number created from an arbitrary integer pair is equivalent to directly applying the standard fraction simplification function to that arbitrary pair.*)\nLemma val_fracq x : val (fracq x) = fracq_subdef x.\n\n(*This lemma provides an explicit formula for the numerator of a rational number constructed from a given pair of integers. If the second integer is non-zero, the numerator is the result of simplifying the fraction and adjusting the sign appropriately; otherwise, the numerator is zero.*)\nLemma num_fracq x : numq (fracq x) = if x.2 != 0 then\n (-1) ^ ((x.2 < 0) (+) (x.1 < 0)) * (`|x.1| %/ gcdn `|x.1| `|x.2|)%:Z else 0.\n\n(*This lemma provides an explicit formula for the denominator of a rational number constructed from a given pair of integers. If the second integer is non-zero, the resulting denominator is its simplified, positive counterpart; otherwise, the denominator is one.*)\nLemma den_fracq x : denq (fracq x) =\n if x.2 != 0 then (`|x.2| %/ gcdn `|x.1| `|x.2|)%:Z else 1.\n\n(*This fact states that creating a rational number from a single integer is equivalent to creating a rational number from the pair consisting of that integer as the numerator and one as the denominator.*)\nFact ratz_frac n : ratz n = fracq (n, 1).\n\n(*This fact states that creating a new rational number from the underlying canonical integer pair of an existing rational number yields the original rational number.*)\nFact valqK x : fracq (valq x) = x.\n\n(*This definition computes the integer scaling factor that relates an arbitrary integer fraction to its canonical representation. The factor is calculated as the product of the sign of the denominator and the greatest common divisor of the absolute values of the numerator and denominator.*)\nDefinition scalq '(n, d) := sgr d * (gcdn `|n| `|d|)%:Z.\n(*This lemma restates the formula for the integer scaling factor of a pair of integers, asserting it is the product of the sign of the second component and the greatest common divisor of the absolute values of the first and second components.*)\nLemma scalq_def x : scalq x = sgr x.2 * (gcdn `|x.1| `|x.2|)%:Z.\n\n(*This fact asserts that the scaling factor of a pair of integers is zero if and only if the second integer in the pair is zero.*)\nFact scalq_eq0 x : (scalq x == 0) = (x.2 == 0).\n\n(*This lemma states that the sign of the scaling factor of a pair of integers is equal to the sign of the second integer in the pair.*)\nLemma sgr_scalq x : sgr (scalq x) = sgr x.2.\n\n(*This lemma states that the scaling factor of a pair of integers is negative if and only if the second integer of the pair is negative.*)\nLemma signr_scalq x : (scalq x < 0) = (x.2 < 0).\n\n(*This lemma provides an explicit formula for the scaling factor of a pair of integers when the second integer is non-zero. The scaling factor is computed as the product of the sign of the second integer and the greatest common divisor of the absolute values of both integers.*)\nLemma scalqE x :\n x.2 != 0 -> scalq x = (-1) ^+ (x.2 < 0)%R * (gcdn `|x.1| `|x.2|)%:Z.\n\n(*This fact states that a non-degenerate pair of integers can be reconstructed by multiplying the numerator and the denominator of its corresponding normalized fraction by its scaling factor.*)\nFact valq_frac x :\n x.2 != 0 -> x = (scalq x * numq (fracq x), scalq x * denq (fracq x)).\n\n(**)\nDefinition zeroq := 0%Q.\n(*This definition introduces an alias for the rational number one.*)\nDefinition oneq := 1%Q.\n\n(*This fact asserts that the rational number constructed from a pair of integers is zero if the first integer of the pair is zero.*)\nFact frac0q x : fracq (0, x) = zeroq.\n\n(*This fact asserts that the rational number constructed from a pair of integers is zero if the second integer of the pair is zero.*)\nFact fracq0 x : fracq (x, 0) = zeroq. \n\n(*This inductive type specifies the properties of the fraction construction function. It provides two cases: one handling pairs of integers where the second component is zero, resulting in the rational number zero, and another for pairs where a non-zero scaling factor relates the pair to the numerator and denominator of the resulting normalized rational number.*)\nVariant fracq_spec (x : int * int) : int * int -> rat -> Type :=\n(**)\n | FracqSpecN of x.2 = 0 : fracq_spec x (x.1, 0) zeroq\n(**)\n | FracqSpecP k fx of k != 0 : fracq_spec x (k * numq fx, k * denq fx) fx.\n\n(*This fact states that the fraction construction function satisfies its specification, relating an input pair of integers to its resulting normalized rational number.*)\nFact fracqP x : fracq_spec x x (fracq x).\n\n(*This lemma states that two rational numbers are equal if and only if their numerators are equal and their denominators are equal.*)\nLemma rat_eqE x y : (x == y) = (numq x == numq y) && (denq x == denq y).\n\n(*This lemma states that the sign of the denominator of any normalized rational number is always one, implying the denominator is positive.*)\nLemma sgr_denq x : sgr (denq x) = 1. \n\n(*This lemma states that the absolute value of the denominator of a normalized rational number is equal to the denominator itself.*)\nLemma normr_denq x : `|denq x| = denq x. \n\n(*This lemma states that the absolute value of the denominator of a normalized rational number, when converted from a natural number back to an integer, is equal to the denominator itself.*)\nLemma absz_denq x : `|denq x|%N = denq x :> int.\n\n(*This lemma provides the cross-multiplication criterion for equality of two rational numbers: two rationals are equal if and only if the product of the numerator of the first and the denominator of the second is equal to the product of the numerator of the second and the denominator of the first.*)\nLemma rat_eq x y : (x == y) = (numq x * denq y == numq y * denq x).\n\n(*This fact states that for two pairs of integers with non-zero second components, their corresponding normalized rational numbers are equal if and only if the cross-product of their components is equal. Specifically, the first component of the first pair times the second of the second pair must equal the first of the second pair times the second of the first pair.*)\nFact fracq_eq x y : x.2 != 0 -> y.2 != 0 ->\n (fracq x == fracq y) = (x.1 * y.2 == y.1 * x.2).\n\n(*This fact states that a rational number constructed from a pair of integers is equal to zero if and only if the first integer is zero or the second integer is zero.*)\nFact fracq_eq0 x : (fracq x == zeroq) = (x.1 == 0) || (x.2 == 0).\n\n(*This fact asserts the cancellation property for constructing rational numbers: multiplying both integers in a pair by the same non-zero integer does not change the resulting normalized rational number.*)\nFact fracqMM x n d : x != 0 -> fracq (x * n, x * d) = fracq (n, d).\n\n(*This definition provides the underlying implementation for adding two pairs of integers, representing unnormalized fractions. It computes the resulting pair by cross-multiplication and addition for the new numerator and multiplication for the new denominator, with special cases for efficiency when one or both denominators are one.*)\nDefinition addq_subdef (x y : int * int) :=\n let: (x1, x2) := x in\n let: (y1, y2) := y in\n match x2, y2 with\n | Posz 1, Posz 1 =>\n match x1, y1 with\n | Posz 0, _ => (y1, 1)\n | _, Posz 0 => (x1, 1)\n | Posz n, Posz 1 => (Posz n.+1, 1)\n | Posz 1, Posz n => (Posz n.+1, 1)\n | _, _ => (x1 + y1, 1)\n end\n | Posz 1, _ => (x1 * y2 + y1, y2)\n | _, Posz 1 => (x1 + y1 * x2, x2)\n | _, _ => (x1 * y2 + y1 * x2, x2 * y2)\n end.\n(*This definition specifies the addition of two rational numbers. The operation is performed by applying the addition rule to their underlying integer pair representations and then normalizing the result to produce a canonical rational number.*)\nDefinition addq '(Rat x xP) '(Rat y yP) := fracq (addq_subdef x y).\n(*This lemma states that the sum of two rational numbers is equivalent to creating a normalized fraction from the result of applying the underlying addition rule to the integer pairs representing each rational number.*)\nLemma addq_def x y : addq x y = fracq (addq_subdef (valq x) (valq y)).\n\n(*This lemma states that the underlying addition operation on two pairs of integers is equivalent to computing a new pair where the first component is the sum of the cross-products of the components and the second component is the product of the second components.*)\nLemma addq_subdefE x y : addq_subdef x y = (x.1 * y.2 + y.1 * x.2, x.2 * y.2).\n\n(*This definition specifies the underlying negation operation for a pair of integers, which is defined as negating the first integer while keeping the second one unchanged.*)\nDefinition oppq_subdef (x : int * int) := (- x.1, x.2).\n(*This definition specifies the additive inverse of a rational number. The operation is performed by applying the underlying negation rule to its integer pair representation and then normalizing the result.*)\nDefinition oppq '(Rat x xP) := fracq (oppq_subdef x).\n(*This lemma states that the additive inverse of a rational number is equivalent to creating a normalized fraction from the result of applying the underlying negation rule to the integer pair representing the rational number.*)\nDefinition oppq_def x : oppq x = fracq (oppq_subdef (valq x)).\n\n(*This fact asserts that the underlying addition operation for pairs of integers is commutative.*)\nFact addq_subdefC : commutative addq_subdef.\n\n(*This fact asserts that the underlying addition operation for pairs of integers is associative.*)\nFact addq_subdefA : associative addq_subdef.\n\n(*This fact states that for two pairs of integers with non-zero second components, adding the rational numbers derived from each pair yields the same result as deriving a rational number from the pair-wise sum.*)\nFact addq_frac x y : x.2 != 0 -> y.2 != 0 ->\n (addq (fracq x) (fracq y)) = fracq (addq_subdef x y).\n\n(*This fact asserts that the function embedding integers into rational numbers is a morphism for addition, meaning that adding two integers and then embedding the result is equivalent to embedding each integer first and then adding the resulting rational numbers.*)\nFact ratzD : {morph ratz : x y / x + y >-> addq x y}.\n\n(*This fact states that the additive inverse of a rational number constructed from a pair of integers is equal to the rational number constructed from applying the sub-definition for additive inverse to that pair of integers.*)\nFact oppq_frac x : oppq (fracq x) = fracq (oppq_subdef x).\n\n(*This fact asserts that the function embedding integers into rational numbers is a morphism for additive inverse, meaning it maps the negation of an integer to the additive inverse of the corresponding rational number.*)\nFact ratzN : {morph ratz : x / - x >-> oppq x}.\n\n(*This fact asserts that the addition operation on rational numbers is commutative.*)\nFact addqC : commutative addq.\n\n(*This fact asserts that the addition operation on rational numbers is associative.*)\nFact addqA : associative addq.\n\n(*This fact asserts that the rational number zero is the left identity element for the addition of rational numbers.*)\nFact add0q : left_id zeroq addq.\n\n(*This fact asserts that for any rational number, its additive inverse is a left inverse with respect to rational addition, yielding the rational number zero.*)\nFact addNq : left_inverse (fracq (0, 1)) oppq addq.\n\nHB.instance Definition _ := GRing.isZmodule.Build rat addqA addqC add0q addNq.\n\n(*This definition specifies a helper function for multiplying two rational numbers, operating on their unnormalized integer-pair representations. It computes the product by multiplying the numerators and denominators, with optimized handling for cases where one or both denominators are one.*)\nDefinition mulq_subdef (x y : int * int) :=\n let: (x1, x2) := x in\n let: (y1, y2) := y in\n match x2, y2 with\n | Posz 1, Posz 1 => (x1 * y1, 1)\n | Posz 1, _ => (x1 * y1, y2)\n | _, Posz 1 => (x1 * y1, x2)\n | _, _ => (x1 * y1, x2 * y2)\n end.\n(*This definition specifies the multiplication of two rational numbers. It is implemented by applying a sub-definition for multiplication to the underlying integer-pair representations of the rational numbers and then normalizing the result.*)\nDefinition mulq '(Rat x xP) '(Rat y yP) := fracq (mulq_subdef x y).\n(*This lemma states that the product of two rational numbers is equal to the normalized rational number obtained by applying the multiplication sub-definition to their underlying integer-pair representations.*)\nLemma mulq_def x y : mulq x y = fracq (mulq_subdef (valq x) (valq y)).\n\n(*This lemma states that the multiplication sub-definition for integer pairs, used in rational multiplication, is equivalent to component-wise multiplication of the pairs.*)\nLemma mulq_subdefE x y : mulq_subdef x y = (x.1 * y.1, x.2 * y.2).\n\n(*This fact asserts that the sub-definition for multiplying integer pairs, used in rational multiplication, is a commutative operation.*)\nFact mulq_subdefC : commutative mulq_subdef.\n\n(*This fact asserts that the sub-definition for multiplying integer pairs, used in rational multiplication, is an associative operation.*)\nFact mul_subdefA : associative mulq_subdef.\n\n(*This definition specifies a helper function for computing the multiplicative inverse of a rational number's unnormalized integer-pair representation by swapping its two components.*)\nDefinition invq_subdef (x : int * int) := (x.2, x.1).\n(*This definition specifies the multiplicative inverse of a rational number. It is implemented by applying the sub-definition for inversion to the number's underlying integer-pair representation and then normalizing the result.*)\nDefinition invq '(Rat x xP) := fracq (invq_subdef x).\n(*This lemma states that the multiplicative inverse of a rational number is equal to the normalized rational number obtained by applying the inversion sub-definition to its underlying integer-pair representation.*)\nLemma invq_def x : invq x = fracq (invq_subdef (valq x)).\n\n(*This fact states that multiplying two rational numbers, each constructed from an integer pair, yields the same result as constructing a single rational number from the unnormalized product of those two pairs.*)\nFact mulq_frac x y : (mulq (fracq x) (fracq y)) = fracq (mulq_subdef x y).\n\n(*This fact asserts that the function embedding integers into rational numbers is a morphism for multiplication, meaning that multiplying two integers and then embedding the result is equivalent to embedding each integer first and then multiplying the resulting rational numbers.*)\nFact ratzM : {morph ratz : x y / x * y >-> mulq x y}.\n\n(*This fact states that for any pair of non-zero integers, the multiplicative inverse of the rational number constructed from this pair is equal to the rational number constructed from the pair with its components swapped.*)\nFact invq_frac x :\n x.1 != 0 -> x.2 != 0 -> invq (fracq x) = fracq (invq_subdef x).\n\n(*This fact asserts that the multiplication operation on rational numbers is commutative.*)\nFact mulqC : commutative mulq.\n\n(*This fact asserts that the multiplication operation on rational numbers is associative.*)\nFact mulqA : associative mulq.\n\n(*This fact asserts that the rational number one is the left identity element for the multiplication of rational numbers.*)\nFact mul1q : left_id oneq mulq.\n\n(*This fact asserts that multiplication of rational numbers is left-distributive over the addition of rational numbers.*)\nFact mulq_addl : left_distributive mulq addq.\n\n(*This fact asserts that the rational number one is not equal to the rational number zero.*)\nFact nonzero1q : oneq != zeroq. \n\nHB.instance Definition _ :=\n GRing.Zmodule_isComNzRing.Build rat mulqA mulqC mul1q mulq_addl nonzero1q.\n\n(*This fact asserts that for any non-zero rational number, the product of its multiplicative inverse and itself is equal to the rational number one.*)\nFact mulVq x : x != 0 -> mulq (invq x) x = 1.\n\n(*This fact states that the multiplicative inverse of the rational number zero is defined to be zero.*)\nFact invq0 : invq 0 = 0. \n\nHB.instance Definition _ := GRing.ComNzRing_isField.Build rat mulVq invq0.\n\n(*This lemma states that the boolean equality check between the numerator of a rational number and the integer zero is equivalent to the boolean equality check between the rational number and the rational number zero.*)\nLemma numq_eq0 x : (numq x == 0) = (x == 0).\n\n(*This notation provides a short-hand for embedding an integer into the type of rational numbers.*)\nNotation \"n %:Q\" := ((n : int)%:~R : rat) : ring_scope.\n\n#[global] Hint Resolve denq_neq0 denq_gt0 denq_ge0 : core.\n\n(*This definition specifies the subtraction of two rational numbers as the sum of the first number and the additive inverse of the second number.*)\nDefinition subq (x y : rat) : rat := (addq x (oppq y)).\n(*This definition specifies the division of two rational numbers as the product of the first number and the multiplicative inverse of the second number.*)\nDefinition divq (x y : rat) : rat := (mulq x (invq y)).\n\nInfix \"+\" := addq : rat_scope.\n(*This notation defines the unary minus prefix for a rational number as its additive inverse.*)\nNotation \"- x\" := (oppq x) : rat_scope.\nInfix \"*\" := mulq : rat_scope.\n(*This notation defines the postfix inverse operator for a rational number as its multiplicative inverse.*)\nNotation \"x ^-1\" := (invq x) : rat_scope.\nInfix \"-\" := subq : rat_scope.\nInfix \"/\" := divq : rat_scope.\n\n(*This lemma states that embedding an integer into the rational numbers using the standard function is equivalent to using the standard coercion from an integer to a rational number.*)\nLemma ratzE n : ratz n = n%:Q.\n\n(*This lemma states that the numerator of a rational number formed by embedding an integer is equal to that same integer.*)\nLemma numq_int n : numq n%:Q = n. \n(*This lemma states that the denominator of a rational number formed by embedding an integer is equal to one.*)\nLemma denq_int n : denq n%:Q = 1. \n\n(*This lemma states that embedding the integer zero into the rational numbers yields the rational number zero.*)\nLemma rat0 : 0%:Q = 0. \n(*This lemma states that embedding the integer one into the rational numbers yields the rational number one.*)\nLemma rat1 : 1%:Q = 1. \n\n(*This lemma states that the numerator of the additive inverse of a rational number is the additive inverse of the original rational number's numerator.*)\nLemma numqN x : numq (- x) = - numq x.\n\n(*This lemma states that the denominator of the additive inverse of a rational number is the same as the denominator of the original rational number.*)\nLemma denqN x : denq (- x) = denq x.\n\n(*This fact states that a rational number formed by embedding an integer is equal to zero if and only if the original integer is zero.*)\nFact intq_eq0 n : (n%:~R == 0 :> rat) = (n == 0)%N.\n\n(*This lemma states that constructing a rational number from a pair of integers is equivalent to dividing the rational representation of the first integer by the rational representation of the second integer.*)\nLemma fracqE x : fracq x = x.1%:Q / x.2%:Q.\n\n(*This lemma states that any rational number is equal to the result of dividing its numerator by its denominator, where both are first embedded into the rational numbers.*)\nLemma divq_num_den x : (numq x)%:Q / (denq x)%:Q = x.\n\n(*This inductive type specifies the evaluation of a fraction of two integers. It defines a relation between an initial numerator and denominator, an intermediate representation of that fraction, and the final simplified rational number.*)\nVariant divq_spec (n d : int) : int -> int -> rat -> Type :=\n(**)\n| DivqSpecN of d = 0 : divq_spec n d n 0 0\n(**)\n| DivqSpecP k x of k != 0 : divq_spec n d (k * numq x) (k * denq x) x.\n\n(*This lemma asserts that the division of two integers, when embedded into the rationals, satisfies the division specification, where the initial and intermediate numerators and denominators are the same.*)\nLemma divqP n d : divq_spec n d n d (n%:Q / d%:Q).\n\n(**)\nVariant rat_spec : rat -> int -> int -> Type :=\n Rat_spec (n : int) (d : nat) & coprime `|n| d.+1\n : rat_spec (n%:Q / d.+1%:Q) n d.+1.\n\n(*This lemma states that any rational number satisfies the canonical representation specification, meaning its numerator and denominator form an irreducible fraction.*)\nLemma ratP x : rat_spec x (numq x) (denq x).\n\n(*This lemma states that if the absolute values of two integers are coprime, the numerator of their rational division is the first integer multiplied by the sign of the second integer.*)\nLemma coprimeq_num n d : coprime `|n| `|d| -> numq (n%:~R / d%:~R) = sgr d * n.\n\n(*This lemma states that if the absolute values of two integers are coprime, the denominator of their rational division is one if the second integer is zero, and the absolute value of the second integer otherwise.*)\nLemma coprimeq_den n d :\n coprime `|n| `|d| -> denq (n%:~R / d%:~R) = (if d == 0 then 1 else `|d|).\n\n(*This lemma states that for any non-zero integer, the denominator of its multiplicative inverse as a rational number is the absolute value of that integer.*)\nLemma denqVz (i : int) : i != 0 -> denq (i%:~R^-1) = `|i|.\n\n(*This lemma provides a definitional equation for a rational number's numerator, stating that the numerator embedded as a rational number is equal to the original rational number multiplied by its denominator embedded as a rational number.*)\nLemma numqE x : (numq x)%:~R = x * (denq x)%:~R.\n\n(*This lemma asserts that the denominator of any rational number is always a positive natural number.*)\nLemma denqP x : {d | denq x = d.+1}.\n\n(*This definition specifies the norm of a rational number as the rational number constructed from the absolute value of its internal numerator and its original internal denominator.*)\nDefinition normq '(Rat x _) : rat := `|x.1|%:~R / (x.2)%:~R.\n(*This definition specifies the less-than-or-equal-to relation between two rational numbers by comparing the integer results of cross-multiplying their internal numerators and denominators.*)\nDefinition le_rat '(Rat x _) '(Rat y _) := x.1 * y.2 <= y.1 * x.2.\n(*This definition specifies the strict less-than relation between two rational numbers by comparing the integer results of cross-multiplying their internal numerators and denominators.*)\nDefinition lt_rat '(Rat x _) '(Rat y _) := x.1 * y.2 < y.1 * x.2.\n\n(*This lemma states that the norm of a rational number is equal to the rational number formed by dividing the absolute value of its canonical numerator by its canonical denominator.*)\nLemma normqE x : normq x = `|numq x|%:~R / (denq x)%:~R.\n\n(*This lemma states that the less-than-or-equal-to relation on two rational numbers is equivalent to the corresponding integer inequality obtained by cross-multiplying their canonical numerators and denominators.*)\nLemma le_ratE x y : le_rat x y = (numq x * denq y <= numq y * denq x).\n\n(*This lemma states that the strict less-than relation on two rational numbers is equivalent to the corresponding strict integer inequality obtained by cross-multiplying their canonical numerators and denominators.*)\nLemma lt_ratE x y : lt_rat x y = (numq x * denq y < numq y * denq x).\n\n(*This lemma states that a rational number is strictly greater than zero if and only if its numerator is a positive integer.*)\nLemma gt_rat0 x : lt_rat 0 x = (0 < numq x).\n\n(*This lemma states that a rational number is strictly less than zero if and only if its integer numerator is strictly less than zero.*)\nLemma lt_rat0 x : lt_rat x 0 = (numq x < 0).\n\n(*This lemma states that a rational number is greater than or equal to zero if and only if its integer numerator is greater than or equal to zero.*)\nLemma ge_rat0 x : le_rat 0 x = (0 <= numq x).\n\n(*This lemma states that a rational number is less than or equal to zero if and only if its integer numerator is less than or equal to zero.*)\nLemma le_rat0 x : le_rat x 0 = (numq x <= 0).\n\n(*This fact states that the sum of two non-negative rational numbers is also a non-negative rational number.*)\nFact le_rat0D x y : le_rat 0 x -> le_rat 0 y -> le_rat 0 (x + y).\n\n(*This fact states that the product of two non-negative rational numbers is also a non-negative rational number.*)\nFact le_rat0M x y : le_rat 0 x -> le_rat 0 y -> le_rat 0 (x * y).\n\n(*This fact states that if a rational number is both greater than or equal to zero and less than or equal to zero, then that rational number must be zero.*)\nFact le_rat0_anti x : le_rat 0 x -> le_rat x 0 -> x = 0.\n\n(*This lemma states that the sign of the integer numerator of a rational number constructed from the division of two integers is equal to the product of the signs of those two integers.*)\nLemma sgr_numq_div (n d : int) : sgr (numq (n%:Q / d%:Q)) = sgr n * sgr d.\n\n(*This fact states that one rational number is less than or equal to another rational number if and only if the difference of the second and the first number is non-negative.*)\nFact subq_ge0 x y : le_rat 0 (y - x) = le_rat x y.\n\n(*This fact states that the less-than-or-equal relation on rational numbers is total, meaning for any two rational numbers, one must be less than or equal to the other.*)\nFact le_rat_total : total le_rat.\n\n(*This fact states that the numerator of a rational number multiplied by a sign factor, which is determined by a boolean, is equal to the product of that sign factor and the numerator of the original rational number.*)\nFact numq_sign_mul (b : bool) x : numq ((-1) ^+ b * x) = (-1) ^+ b * numq x.\n\n(*This fact states that for two non-zero integers, the numerator of the rational number resulting from their division is negative if and only if exactly one of the two integers is negative.*)\nFact numq_div_lt0 n d : n != 0 -> d != 0 ->\n (numq (n%:~R / d%:~R) < 0)%R = (n < 0)%R (+) (d < 0)%R.\n\n(*This lemma states that the absolute value of the numerator of a rational number formed from the division of two integers is equal to the numerator of the rational number formed from the division of their absolute values.*)\nLemma normr_num_div n d : `|numq (n%:~R / d%:~R)| = numq (`|n|%:~R / `|d|%:~R).\n\n(*This fact states that the absolute value of the additive inverse of a rational number is equal to the absolute value of the original rational number.*)\nFact norm_ratN x : normq (- x) = normq x.\n\n(*This fact states that for any non-negative rational number, its absolute value is equal to the number itself.*)\nFact ge_rat0_norm x : le_rat 0 x -> normq x = x.\n\n(*This fact states that one rational number is strictly less than another if and only if they are not equal and the first is less than or equal to the second.*)\nFact lt_rat_def x y : (lt_rat x y) = (y != x) && (le_rat x y).\n\nHB.instance Definition _ :=\n Num.IntegralDomain_isLeReal.Build rat le_rat0D le_rat0M le_rat0_anti\n subq_ge0 (@le_rat_total 0) norm_ratN ge_rat0_norm lt_rat_def.\n\n(*This lemma states that the integer numerator of a rational number is non-negative if and only if the rational number itself is non-negative.*)\nLemma numq_ge0 x : (0 <= numq x) = (0 <= x).\n\n(*This lemma states that the integer numerator of a rational number is non-positive if and only if the rational number itself is non-positive.*)\nLemma numq_le0 x : (numq x <= 0) = (x <= 0).\n\n(*This lemma states that the integer numerator of a rational number is positive if and only if the rational number itself is positive.*)\nLemma numq_gt0 x : (0 < numq x) = (0 < x).\n\n(*This lemma states that the integer numerator of a rational number is negative if and only if the rational number itself is negative.*)\nLemma numq_lt0 x : (numq x < 0) = (x < 0).\n\n(*This lemma states that the sign of the integer numerator of a rational number is equal to the sign of the rational number itself.*)\nLemma sgr_numq x : sgz (numq x) = sgz x.\n\n(*This lemma states that the denominator of a rational number remains unchanged when the rational number is multiplied by either positive one or negative one.*)\nLemma denq_mulr_sign (b : bool) x : denq ((-1) ^+ b * x) = denq x.\n\n(*This lemma states that the denominator of the absolute value of a rational number is the same as the denominator of the original rational number.*)\nLemma denq_norm x : denq `|x| = denq x.\n\nModule ratArchimedean.\nSection ratArchimedean.\n\nImplicit Types x : rat.\n\n(*This definition defines the floor of a rational number as the integer resulting from the Euclidean division of its numerator by its denominator.*)\nDefinition floor x : int := (numq x %/ denq x)%Z.\n\n(*This definition defines the ceiling of a rational number as the additive inverse of the integer resulting from the Euclidean division of the negated numerator by the denominator.*)\nDefinition ceil x : int := - (- numq x %/ denq x)%Z.\n\n(*This definition defines the truncation of a rational number to a natural number. If the rational number is non-negative, it returns the natural number obtained by dividing the absolute value of its numerator by the absolute value of its denominator; otherwise, it returns zero.*)\nDefinition truncn x : nat :=\n if 0 <= x then (`|numq x| %/ `|denq x|)%N else 0%N.\n\n(*This definition provides a boolean test to check if a rational number is an integer, which is true if its canonical denominator is one.*)\nLet is_int x := denq x == 1.\n\n(*This definition provides a boolean test to check if a rational number corresponds to a natural number, which is true if it is non-negative and its canonical denominator is one.*)\nLet is_nat x := (0 <= x) && (denq x == 1).\n\n(*This fact states the characteristic property of the floor function for a rational number: the integer floor, when viewed as a rational number, is less than or equal to the given rational number, which in turn is strictly less than the floor plus one.*)\nFact floorP x :\n if x \\is Num.real then (floor x)%:~R <= x < (floor x + 1)%:~R\n else floor x == 0.\n\n(*This fact states that the ceiling of a rational number is equal to the additive inverse of the floor of the additive inverse of that number.*)\nFact ceilP x : ceil x = - floor (- x).\n\n(*This fact relates the natural number truncation of a rational number to its floor: the truncation is equal to the floor if the floor is a positive integer, and it is zero otherwise.*)\nFact truncnP x : truncn x = if floor x is Posz n then n else 0.\n\n(*This fact asserts that a rational number is an integer if and only if there exists an integer that, when embedded into the rationals, is equal to that rational number.*)\nFact intrP x : reflect (exists n, x = n%:~R) (is_int x).\n\n(*This fact asserts that a rational number is a natural number if and only if there exists a natural number that, when embedded into the rationals, is equal to that rational number.*)\nFact natrP x : reflect (exists n, x = n%:R) (is_nat x).\n\nEnd ratArchimedean.\nEnd ratArchimedean.\n\n(*This lemma states that the floor of a rational number is equal to the integer division of its numerator by its denominator.*)\nLemma floorErat (x : rat) : Num.floor x = (numq x %/ denq x)%Z.\n\n(*This lemma states that the ceiling of a rational number is equal to the opposite of the integer division of its negated numerator by its denominator.*)\nLemma ceilErat (x : rat) : Num.ceil x = - (- numq x %/ denq x)%Z.\n\n(*This lemma states that a rational number is an integer if and only if its denominator is equal to one.*)\nLemma Qint_def (x : rat) : (x \\is a Num.int) = (denq x == 1). \n\n(*This lemma states that taking the numerator of a rational number that was created by embedding an integer recovers the original integer.*)\nLemma numqK : {in Num.int, cancel (fun x => numq x) intr}.\n\n(*This lemma states that if a first natural number divides a second natural number, then embedding their natural number quotient into the rationals yields the same result as dividing the rational embedding of the second number by the rational embedding of the first.*)\nLemma natq_div m n : (n %| m)%N -> (m %/ n)%:R = m%:R / n%:R :> rat.\n\nSection InRing.\n\nVariable R : unitRingType.\n\n(*This definition provides a canonical embedding of a rational number into an arbitrary unit ring by dividing the ring embedding of its numerator by the ring embedding of its denominator.*)\nDefinition ratr x : R := (numq x)%:~R / (denq x)%:~R.\n\n(*This lemma states that embedding a rational number, which was formed from an integer, into a unit ring results in the direct ring embedding of that original integer.*)\nLemma ratr_int z : ratr z%:~R = z%:~R.\n\n(*This lemma states that embedding a rational number, which was formed from a natural number, into a unit ring results in the direct ring embedding of that original natural number.*)\nLemma ratr_nat n : ratr n%:R = n%:R.\n\n(*This lemma states that the embedding of any rational number into a unit ring is an element of any given subring that is closed under division.*)\nLemma rpred_rat (S : divringClosed R) a : ratr a \\in S.\n\nEnd InRing.\n\nSection Fmorph.\n\nImplicit Type rR : unitRingType.\n\n(*This lemma states that applying a ring morphism between two fields to the embedding of a rational number in the source field is equivalent to directly embedding that rational number into the target field.*)\nLemma fmorph_rat (aR : fieldType) rR (f : {rmorphism aR -> rR}) a :\n f (ratr _ a) = ratr _ a.\n\n(*This lemma states that any ring morphism from the field of rational numbers to another ring is uniquely defined as the canonical embedding of rational numbers into that ring.*)\nLemma fmorph_eq_rat rR (f : {rmorphism rat -> rR}) : f =1 ratr _.\n\nEnd Fmorph.\n\nSection Linear.\n\nImplicit Types (U V : lmodType rat) (A B : lalgType rat).\n\n(*This lemma states that for vector spaces over the rational numbers, any function that preserves addition is automatically a linear map.*)\nLemma rat_linear U V (f : U -> V) : zmod_morphism f -> scalable f.\n\nEnd Linear.\n\nSection InPrealField.\n\nVariable F : numFieldType.\n\n(*This fact asserts that the canonical embedding of rational numbers into a numeric field preserves the addition operation.*)\nFact ratr_is_zmod_morphism : zmod_morphism (@ratr F).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `ratr_is_additive` instead\")]\n(*This definition is a deprecated alias, providing an alternative name for the fact that the canonical embedding of rational numbers into a numeric field preserves addition.*)\nDefinition ratr_is_additive := ratr_is_zmod_morphism.\n\n(*This fact asserts that the canonical embedding of rational numbers into a numeric field preserves the multiplication operation and the multiplicative identity.*)\nFact ratr_is_monoid_morphism : monoid_morphism (@ratr F).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `ratr_is_monoid_morphism` instead\")]\n(*This definition is a deprecated alias, providing an alternative name for the fact that the canonical embedding of rational numbers into a numeric field preserves multiplication and the multiplicative identity.*)\nDefinition ratr_is_multiplicative :=\n (fun g => (g.2,g.1)) ratr_is_monoid_morphism.\n\nHB.instance Definition _ := GRing.isZmodMorphism.Build rat F (@ratr F)\n ratr_is_zmod_morphism.\n(*This lemma states that the canonical embedding of rational numbers into a numeric field is monotonic, meaning it preserves the less-than-or-equal-to relation.*)\nLemma ler_rat : {mono (@ratr F) : x y / x <= y}.\n\n(*This lemma states that the canonical embedding of rational numbers into a numeric field is strictly monotonic, meaning it preserves the strict less-than relation.*)\nLemma ltr_rat : {mono (@ratr F) : x y / x < y}.\n\n(*This lemma states that the embedding of a rational number into a numeric field is greater than or equal to zero if and only if the original rational number is greater than or equal to zero.*)\nLemma ler0q x : (0 <= ratr F x) = (0 <= x).\n\n(*This lemma states that the embedding of a rational number into a numeric field is less than or equal to zero if and only if the original rational number is less than or equal to zero.*)\nLemma lerq0 x : (ratr F x <= 0) = (x <= 0).\n\n(*This lemma states that the embedding of a rational number into a numeric field is strictly greater than zero if and only if the original rational number is strictly greater than zero.*)\nLemma ltr0q x : (0 < ratr F x) = (0 < x).\n\n(*This lemma states that the embedding of a rational number into a numeric field is strictly less than zero if and only if the original rational number is strictly less than zero.*)\nLemma ltrq0 x : (ratr F x < 0) = (x < 0).\n\n(*This lemma states that the embedding of the sign of a rational number into a numeric field is equal to the sign of the embedding of that rational number.*)\nLemma ratr_sg x : ratr F (sgr x) = sgr (ratr F x).\n\n(*This lemma states that the embedding of the absolute value of a rational number into a numeric field is equal to the absolute value of the embedding of that rational number.*)\nLemma ratr_norm x : ratr F `|x| = `|ratr F x|.\n\n(*This lemma states that the canonical embedding of rational numbers into a numeric field preserves the minimum operation.*)\nLemma minr_rat : {morph ratr F : x y / Num.min x y}.\n\n(*This lemma states that the canonical embedding of rational numbers into a numeric field preserves the maximum operation.*)\nLemma maxr_rat : {morph ratr F : x y / Num.max x y}.\n\nEnd InPrealField.\n\nSection InParchiField.\n\nVariable F : archiNumFieldType.\n\n(*This lemma states that the function mapping a rational number to the embedding of its floor into an Archimedean numeric field is monotonic.*)\nLemma floor_rat : {mono (@ratr F) : x / Num.floor x}.\n\n(*This lemma states that the function mapping a rational number to the embedding of its ceiling into an Archimedean numeric field is monotonic.*)\nLemma ceil_rat : {mono (@ratr F) : x / Num.ceil x}.\n\nEnd InParchiField.\n\nArguments ratr {R}.\n\n(*This lemma states that if an integer divides another integer, then the quotient of their corresponding representations as rational numbers is a rational number that represents an integer.*)\nLemma Qint_dvdz (m d : int) : (d %| m)%Z -> (m%:~R / d%:~R : rat) \\is a Num.int.\n\n(*This lemma states that if a natural number divides another natural number, then the quotient of their corresponding representations as rational numbers is a rational number that represents a natural number.*)\nLemma Qnat_dvd (m d : nat) : (d %| m)%N -> (m%:R / d%:R : rat) \\is a Num.nat.\n\nSection ZpolyScale.\n\n(*This notation defines an operation that converts a polynomial with integer coefficients into a polynomial with rational coefficients by individually converting each integer coefficient to its rational equivalent.*)\nLocal Notation pZtoQ := (map_poly (intr : int -> rat)).\n\n(*This lemma states that the size of a polynomial is unchanged when its integer coefficients are converted to their rational number equivalents.*)\nLemma size_rat_int_poly p : size (pZtoQ p) = size p.\n\n(*This lemma states that any polynomial with rational coefficients can be expressed as a polynomial with integer coefficients scaled by the multiplicative inverse of a non-zero integer.*)\nLemma rat_poly_scale (p : {poly rat}) :\n {q : {poly int} & {a | a != 0 & p = a%:~R^-1 *: pZtoQ q}}.\n\n(*This lemma states that for two polynomials with integer coefficients, one divides the other if and only if their corresponding versions with rational coefficients also exhibit the same divisibility relationship.*)\nLemma dvdp_rat_int p q : (pZtoQ p %| pZtoQ q) = (p %| q).\n\n(*This lemma specifies that if a polynomial with integer coefficients divides another polynomial after its coefficients are converted to rational numbers, then the first polynomial must be the product of a non-zero integer and another integer polynomial, where this new integer polynomial is a factor of the second original polynomial.*)\nLemma dvdpP_rat_int p q :\n p %| pZtoQ q ->\n {p1 : {poly int} & {a | a != 0 & p = a *: pZtoQ p1} & {r | q = p1 * r}}.\n\n(*This lemma states that a polynomial with integer coefficients is irreducible if and only if the corresponding polynomial with rational coefficients is also irreducible.*)\nLemma irreducible_rat_int p :\n irreducible_poly (pZtoQ p) <-> irreducible_poly p.\n\nEnd ZpolyScale.\n\n(*This definition describes the property of a vector being in the integer span of a collection of vectors, which holds if the vector can be written as a linear combination of the collection's vectors using only integer coefficients.*)\nDefinition inIntSpan (V : zmodType) m (s : m.-tuple V) v :=\n exists a : int ^ m, v = \\sum_(i < m) s`_i *~ a i.\n\n(*This lemma provides a procedure for solving integer linear combination problems over rational vectors. For a given vector and a sequence of vectors, it either demonstrates that the vector cannot be expressed as an integer linear combination of the sequence, or it provides a particular integer-coefficient solution along with a basis for all possible integer solutions.*)\nLemma solve_Qint_span (vT : vectType rat) m (s : m.-tuple vT) v :\n {b : int ^ m &\n {p : seq (int ^ m) &\n forall a : int ^ m,\n v = \\sum_(i < m) s`_i *~ a i <->\n exists c : seq int, a = b + \\sum_(i < size p) p`_i *~ c`_i}} +\n (~ inIntSpan s v).\n\n(*This lemma states that it is decidable whether a given vector with rational components lies within the integer span of a finite sequence of vectors with rational components.*)\nLemma dec_Qint_span (vT : vectType rat) m (s : m.-tuple vT) v :\n decidable (inIntSpan s v).\n\n(*This lemma provides the Eisenstein criterion for polynomial irreducibility, stating that a non-constant polynomial with integer coefficients is irreducible if there exists a prime number that divides every coefficient except for the leading one, does not divide the leading coefficient, and whose square does not divide the constant term.*)\nLemma eisenstein_crit (p : nat) (q : {poly int}) : prime p -> (size q != 1)%N ->\n ~~ (p %| lead_coef q)%Z -> ~~ (p ^+ 2 %| q`_0)%Z ->\n (forall i, (i < (size q).-1)%N -> p %| q`_i)%Z ->\n irreducible_poly q.\n\n(*This tactic rewrites expressions involving specific rational number operations and constants into their equivalent forms using generic ring notations.*)\nLtac rat_to_ring :=\n rewrite -?[0%Q]/(0 : rat)%R -?[1%Q]/(1 : rat)%R\n -?[(_ - _)%Q]/(_ - _ : rat)%R -?[(_ / _)%Q]/(_ / _ : rat)%R\n -?[(_ + _)%Q]/(_ + _ : rat)%R -?[(_ * _)%Q]/(_ * _ : rat)%R\n -?[(- _)%Q]/(- _ : rat)%R -?[(_ ^-1)%Q]/(_ ^-1 : rat)%R /=.\n\n(*This tactic rewrites expressions involving generic ring operations and constants back into their specific forms for rational numbers.*)\nLtac ring_to_rat :=\n rewrite -?[0%R]/0%Q -?[1%R]/1%Q\n -?[(_ - _)%R]/(_ - _)%Q -?[(_ / _)%R]/(_ / _)%Q\n -?[(_ + _)%R]/(_ + _)%Q -?[(_ * _)%R]/(_ * _)%Q\n -?[(- _)%R]/(- _)%Q -?[(_ ^-1)%R]/(_ ^-1)%Q /=.\n\nNotation \"[ 'rat' x // y ]\" := (@Rat (x, y) _) (only printing) : ring_scope.\n\n(*This notation provides a syntax for constructing a rational number from an integer numerator and an integer denominator, and it is also used for displaying rational numbers in this format.*)\nNotation \"[ 'rat' x // y ]\" :=\n (@Rat (x : int, y : int) (fracq_subproof (x : int, y : int))) : ring_scope.\n\n(*This lemma states that any rational number is equal to the fraction formed by its canonical integer numerator and its canonical positive integer denominator.*)\nLemma rat_vm_compute n (x : rat) : vm_compute_eq n%:Q x -> n%:Q = x.", - "algebra.polyXY": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype choice ssrnat seq.\nFrom mathcomp Require Import fintype tuple finfun bigop fingroup perm div.\nFrom mathcomp Require Import ssralg zmodp matrix mxalgebra.\nFrom mathcomp Require Import poly polydiv mxpoly binomial.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope ring_scope.\nImport GRing.Theory.\n\n(*This notation represents the application of a function to each coefficient of a polynomial, resulting in a new polynomial.*)\nLocal Notation \"p ^ f\" := (map_poly f p) : ring_scope.\n(*This notation represents the evaluation of a polynomial at a specific point, yielding a value in the coefficient ring.*)\nLocal Notation eval := horner_eval.\n\n(*This notation represents the indeterminate 'Y' in a ring of bivariate polynomials, where polynomials are structured as polynomials in 'X' with coefficients that are themselves polynomials in 'Y'.*)\nNotation \"'Y\" := 'X%:P : ring_scope.\n(*This notation lifts a univariate polynomial over a ring to a bivariate polynomial. It reinterprets the polynomial as having the other indeterminate as its variable, with its original coefficients lifted to be constant polynomials.*)\nNotation \"p ^:P\" := (p ^ polyC) (format \"p ^:P\") : ring_scope.\n(*This notation represents the evaluation of a bivariate polynomial at a specific point. It takes a polynomial in two variables and two ring elements, substituting the first ring element for the first variable and the second ring element for the second variable, and returns the resulting ring element.*)\nNotation \"p .[ x , y ]\" := (p.[x%:P].[y])\n (left associativity, format \"p .[ x , y ]\") : ring_scope.\n\nSection PolyXY_NzRing.\n\nVariable R : nzRingType.\nImplicit Types (u : {poly {poly R}}) (p q : {poly R}) (x : R).\n\n(*This fact provides an opaque key used to lock the definition of `swapXY`, preventing its premature unfolding during proofs.*)\nFact swapXY_key : unit. \n(*This definition provides the underlying implementation for the `swapXY` function, which swaps the two indeterminates of a bivariate polynomial.*)\nDefinition swapXY_def u : {poly {poly R}} := (u ^ map_poly polyC).['Y].\n(*This definition introduces a function that swaps the two indeterminates of a bivariate polynomial. The definition is locked to ensure stable behavior in proofs.*)\nDefinition swapXY := locked_with swapXY_key swapXY_def.\nCanonical swapXY_unlockable := [unlockable fun swapXY].\n\n(*This definition computes the total degree of a bivariate polynomial with respect to its second indeterminate, 'Y', by taking the maximum degree among all its polynomial coefficients.*)\nDefinition sizeY u : nat := \\max_(i < size u) (size u`_i).\n(*This definition transforms a univariate polynomial into a bivariate polynomial by substituting the sum of the two indeterminates, 'X' plus 'Y', for the original variable.*)\nDefinition poly_XaY p : {poly {poly R}} := p^:P \\Po ('X + 'Y).\n(*This definition transforms a univariate polynomial into a bivariate polynomial by substituting the product of the two indeterminates, 'X' times 'Y', for the original variable.*)\nDefinition poly_XmY p : {poly {poly R}} := p^:P \\Po ('X * 'Y).\n(*This definition computes the resultant of two polynomials to create a new polynomial whose roots are the differences between the roots of the input polynomials. The resultant is calculated with respect to the second indeterminate, 'Y'.*)\nDefinition sub_annihilant p q := resultant (poly_XaY p) q^:P.\n(*This definition computes the resultant of two polynomials to create a new polynomial whose roots are the quotients of the roots of the input polynomials. The resultant is calculated with respect to the second indeterminate, 'Y'.*)\nDefinition div_annihilant p q := resultant (poly_XmY p) q^:P.\n\n(*This lemma states that swapping the indeterminates of a constant bivariate polynomial, which was created by lifting a univariate polynomial, is equivalent to reinterpreting that original univariate polynomial with respect to the other indeterminate.*)\nLemma swapXY_polyC p : swapXY p%:P = p^:P.\n\n(*This lemma states that swapping the indeterminates of the bivariate polynomial representing 'X' results in the bivariate polynomial representing 'Y'.*)\nLemma swapXY_X : swapXY 'X = 'Y.\n\n(*This lemma states that swapping the indeterminates of the bivariate polynomial representing 'Y' results in the bivariate polynomial representing 'X'.*)\nLemma swapXY_Y : swapXY 'Y = 'X.\n\n(*This lemma states that the function for swapping indeterminates in a bivariate polynomial is a Z-module morphism, meaning it preserves the structure of addition and the zero element.*)\nLemma swapXY_is_zmod_morphism : zmod_morphism swapXY.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `swapXY_is_zmod_morphism` instead\")]\n(*This is a deprecated definition, aliasing the fact that the indeterminate-swapping function is an additive homomorphism.*)\nDefinition swapXY_is_additive := swapXY_is_zmod_morphism.\nHB.instance Definition _ :=\n GRing.isZmodMorphism.Build {poly {poly R}} {poly {poly R}} swapXY\n swapXY_is_zmod_morphism.\n\n(*This lemma states that for a bivariate polynomial, the coefficient corresponding to the i-th power of the first indeterminate and the j-th power of the second in its swapped form is equal to the original coefficient of the j-th power of the first and i-th power of the second.*)\nLemma coef_swapXY u i j : (swapXY u)`_i`_j = u`_j`_i.\n\n(*This lemma states that the function for swapping indeterminates in a bivariate polynomial is an involution, meaning that applying it twice returns the original polynomial.*)\nLemma swapXYK : involutive swapXY.\n\n(*This lemma states that swapping the indeterminates of a bivariate polynomial that was formed by lifting a univariate polynomial is equivalent to creating a constant bivariate polynomial from the original univariate polynomial.*)\nLemma swapXY_map_polyC p : swapXY p^:P = p%:P.\n\n(*This lemma states that a bivariate polynomial is the zero polynomial if and only if the polynomial obtained by swapping its indeterminates is also the zero polynomial.*)\nLemma swapXY_eq0 u : (swapXY u == 0) = (u == 0).\n\n(*This lemma states that the function for swapping indeterminates in a bivariate polynomial is a monoid morphism, meaning it preserves multiplication and the unit element.*)\nLemma swapXY_is_monoid_morphism : monoid_morphism swapXY.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `swapXY_is_monoid_morphism` instead\")]\n(*This is a deprecated definition asserting the multiplicative property of the indeterminate-swapping function, which is derived from it being a monoid morphism.*)\nDefinition swapXY_is_multiplicative :=\n (fun g => (g.2,g.1)) swapXY_is_monoid_morphism.\nHB.instance Definition _ :=\n GRing.isMonoidMorphism.Build {poly {poly R}} {poly {poly R}} swapXY\n swapXY_is_monoid_morphism.\n\n(*This lemma states that the indeterminate-swapping function is compatible with scalar multiplication; swapping the indeterminates of a scaled polynomial is equivalent to scaling the polynomial after swapping its indeterminates.*)\nLemma swapXY_is_scalable : scalable_for (map_poly polyC \\; *%R) swapXY.\n\n(*This lemma states that swapping the indeterminates of a polynomial composition is equivalent to first swapping the indeterminates of the inner bivariate polynomial and then performing the composition with the outer lifted univariate polynomial.*)\nLemma swapXY_comp_poly p u : swapXY (p^:P \\Po u) = p^:P \\Po swapXY u.\n\n(*This lemma states that for a bivariate polynomial, the degree of any of its coefficient polynomials with respect to the second indeterminate is less than or equal to the total degree of the bivariate polynomial in that same indeterminate.*)\nLemma max_size_coefXY u i : size u`_i <= sizeY u.\n\n(*This lemma states that the degree of the leading coefficient of a bivariate polynomial, taken with respect to the first indeterminate, is bounded above by the polynomial's total degree in the second indeterminate.*)\nLemma max_size_lead_coefXY u : size (lead_coef u) <= sizeY u.\n\n(*This lemma provides an upper bound on the degree of the univariate polynomial resulting from the evaluation of a bivariate polynomial where the first indeterminate is substituted by the second indeterminate. This bound is the sum of the maximum degree of its coefficient polynomials and its own degree minus one.*)\nLemma max_size_evalX u : size u.['X] <= sizeY u + (size u).-1.\n\n(*This lemma states that the degree of the polynomial resulting from evaluating a bivariate polynomial's first indeterminate at a constant value is bounded by the maximum degree of its original coefficient polynomials.*)\nLemma max_size_evalC u x : size u.[x%:P] <= sizeY u.\n\n(*This lemma states that the degree of a bivariate polynomial with respect to its second variable is equal to the total degree of the polynomial that results from swapping its variables.*)\nLemma sizeYE u : sizeY u = size (swapXY u).\n\n(*This lemma states that the maximum degree of the coefficients of a bivariate polynomial, when viewed as a polynomial in its first variable, is zero if and only if the bivariate polynomial itself is the zero polynomial.*)\nLemma sizeY_eq0 u : (sizeY u == 0) = (u == 0).\n\n(*This lemma states that multiplying a bivariate polynomial by its first variable does not change the maximum degree of its coefficients with respect to the second variable.*)\nLemma sizeY_mulX u : sizeY (u * 'X) = sizeY u.\n\n(*This lemma states that creating a bivariate polynomial by substituting the sum of two variables into a univariate polynomial results in a polynomial that is symmetric with respect to swapping those two variables.*)\nLemma swapXY_poly_XaY p : swapXY (poly_XaY p) = poly_XaY p.\n\n(*This lemma states that creating a bivariate polynomial by substituting the product of two variables into a univariate polynomial results in a polynomial that is symmetric with respect to swapping those two variables.*)\nLemma swapXY_poly_XmY p : swapXY (poly_XmY p) = poly_XmY p.\n\n(*This lemma states that substituting the sum of two variables into the zero univariate polynomial yields the zero bivariate polynomial.*)\nLemma poly_XaY0 : poly_XaY 0 = 0.\n\n(*This lemma states that substituting the product of two variables into the zero univariate polynomial yields the zero bivariate polynomial.*)\nLemma poly_XmY0 : poly_XmY 0 = 0.\n\nEnd PolyXY_NzRing.\n\nPrenex Implicits swapXY sizeY poly_XaY poly_XmY sub_annihilant div_annihilant.\nPrenex Implicits swapXYK.\n\n(*This lemma states that for a bivariate polynomial, applying a coefficient-wise map commutes with the operation of swapping the two variables.*)\nLemma swapXY_map (R S : nzRingType) (f : {additive R -> S}) u :\n swapXY (u ^ map_poly f) = swapXY u ^ map_poly f.\n\nSection PolyXY_ComNzRing.\n\nVariable R : comNzRingType.\nImplicit Types (u : {poly {poly R}}) (p : {poly R}) (x y : R).\n\n(*This lemma states that evaluating a variable-swapped bivariate polynomial at a given ring element for its new second variable is equivalent to evaluating the original polynomial's coefficients at that same ring element.*)\nLemma horner_swapXY u x : (swapXY u).[x%:P] = u ^ eval x.\n\n(*This lemma states an identity involving the evaluation of a bivariate polynomial, asserting that evaluating the polynomial in its first variable at a ring element is equivalent to first swapping the variables and then applying a coefficient-wise evaluation at the same ring element to the resulting polynomial.*)\nLemma horner_polyC u x : u.[x%:P] = swapXY u ^ eval x.\n\n(*This lemma states that evaluating a variable-swapped bivariate polynomial at two ring elements is equivalent to evaluating the original polynomial at those same two elements, but with their roles reversed.*)\nLemma horner2_swapXY u x y : (swapXY u).[x, y] = u.[y, x].\n\n(*This lemma states that evaluating the bivariate polynomial formed by substituting the sum of two variables into a univariate polynomial at a ring element for the first variable is equivalent to composing the original polynomial with a new polynomial formed by the sum of that ring element and the second variable.*)\nLemma horner_poly_XaY p v : (poly_XaY p).[v] = p \\Po (v + 'X).\n\n(*This lemma states that evaluating the bivariate polynomial formed by substituting the product of two variables into a univariate polynomial at a ring element for the first variable is equivalent to composing the original polynomial with a new polynomial formed by the product of that ring element and the second variable.*)\nLemma horner_poly_XmY p v : (poly_XmY p).[v] = p \\Po (v * 'X).\n\nEnd PolyXY_ComNzRing.\n\nSection PolyXY_Idomain.\n\nVariable R : idomainType.\nImplicit Types (p q : {poly R}) (x y : R).\n\n(*This lemma states that the size of a bivariate polynomial created by substituting the sum of two variables into a univariate polynomial is the same as the size of the original univariate polynomial.*)\nLemma size_poly_XaY p : size (poly_XaY p) = size p.\n\n(*This lemma states that a bivariate polynomial created by substituting the sum of two variables into a univariate polynomial is the zero polynomial if and only if the original univariate polynomial is the zero polynomial.*)\nLemma poly_XaY_eq0 p : (poly_XaY p == 0) = (p == 0).\n\n(*This lemma states that the size of a bivariate polynomial created by substituting the product of two variables into a univariate polynomial is the same as the size of the original univariate polynomial.*)\nLemma size_poly_XmY p : size (poly_XmY p) = size p.\n\n(*This lemma states that a bivariate polynomial created by substituting the product of two variables into a univariate polynomial is the zero polynomial if and only if the original univariate polynomial is the zero polynomial.*)\nLemma poly_XmY_eq0 p : (poly_XmY p == 0) = (p == 0).\n\n(*This lemma states that the leading coefficient of the bivariate polynomial created by substituting the sum of two variables into a univariate polynomial is the constant polynomial corresponding to the leading coefficient of the original univariate polynomial.*)\nLemma lead_coef_poly_XaY p : lead_coef (poly_XaY p) = (lead_coef p)%:P.\n\n(*This lemma asserts the existence of a specific ideal membership for the subtraction anihilant of two univariate polynomials. For two non-constant polynomials, it guarantees the existence of a pair of bivariate polynomials with bounded degrees, such that for any two ring elements, the subtraction anihilant evaluated at the second element can be expressed as a linear combination of the first polynomial evaluated at their sum and the second polynomial evaluated at the first element, with the bivariate polynomials serving as coefficients.*)\nLemma sub_annihilant_in_ideal p q :\n 1 < size p -> 1 < size q ->\n {uv : {poly {poly R}} * {poly {poly R}}\n | size uv.1 < size q /\\ size uv.2 < size p\n & forall x y,\n (sub_annihilant p q).[y] = uv.1.[x, y] * p.[x + y] + uv.2.[x, y] * q.[x]}.\n\n(*This lemma states a fundamental property of the subtraction anihilant of two non-zero univariate polynomials: if one ring element is a root of the first polynomial and another ring element is a root of the second, then their difference is a root of the subtraction anihilant.*)\nLemma sub_annihilantP p q x y :\n p != 0 -> q != 0 -> p.[x] = 0 -> q.[y] = 0 ->\n (sub_annihilant p q).[x - y] = 0.\n\n(*This lemma states that the subtraction anihilant of two non-zero univariate polynomials is also a non-zero polynomial.*)\nLemma sub_annihilant_neq0 p q : p != 0 -> q != 0 -> sub_annihilant p q != 0.\n\n(*This lemma asserts the existence of a specific ideal membership for the division anihilant of two univariate polynomials. For two non-constant polynomials, it guarantees the existence of a pair of bivariate polynomials with bounded degrees, such that for any two ring elements, the division anihilant evaluated at the second element can be expressed as a linear combination of the first polynomial evaluated at their product and the second polynomial evaluated at the first element, with the bivariate polynomials serving as coefficients.*)\nLemma div_annihilant_in_ideal p q :\n 1 < size p -> 1 < size q ->\n {uv : {poly {poly R}} * {poly {poly R}}\n | size uv.1 < size q /\\ size uv.2 < size p\n & forall x y,\n (div_annihilant p q).[y] = uv.1.[x, y] * p.[x * y] + uv.2.[x, y] * q.[x]}.\n\n(*This lemma states that the division anihilant of two univariate polynomials is a non-zero polynomial, provided that the first polynomial is non-zero and the second polynomial does not have zero as a root.*)\nLemma div_annihilant_neq0 p q : p != 0 -> q.[0] != 0 -> div_annihilant p q != 0.\n\nEnd PolyXY_Idomain.\n\nSection PolyXY_Field.\n\nVariables (F E : fieldType) (FtoE : {rmorphism F -> E}).\n\n(*This notation defines a shorthand for applying a ring morphism between two fields to the coefficients of a polynomial, effectively casting the polynomial from the source field to the target field.*)\nLocal Notation pFtoE := (map_poly (GRing.RMorphism.sort FtoE)).\n\n(*This lemma states a fundamental property of the division anihilant over a field: for two non-zero polynomials, if one element is a root of the first polynomial and a second, non-zero element is a root of the second polynomial, then their quotient is a root of the division anihilant.*)\nLemma div_annihilantP (p q : {poly E}) (x y : E) :\n p != 0 -> q != 0 -> y != 0 -> p.[x] = 0 -> q.[y] = 0 ->\n (div_annihilant p q).[x / y] = 0.\n\n(*This lemma states that the subtraction anihilant property is preserved under field extensions. If two polynomials with coefficients in a base field have roots in an extension field, then the difference of these roots is a root of the subtraction anihilant polynomial, when its coefficients are mapped to the extension field.*)\nLemma map_sub_annihilantP (p q : {poly F}) (x y : E) :\n p != 0 -> q != 0 ->(p ^ FtoE).[x] = 0 -> (q ^ FtoE).[y] = 0 ->\n (sub_annihilant p q ^ FtoE).[x - y] = 0.\n\n(*This lemma states that the division anihilant property is preserved under field extensions. If two polynomials with coefficients in a base field have roots in an extension field, with the second root being non-zero, then the quotient of these roots is a root of the division anihilant polynomial, when its coefficients are mapped to the extension field.*)\nLemma map_div_annihilantP (p q : {poly F}) (x y : E) :\n p != 0 -> q != 0 -> y != 0 -> (p ^ FtoE).[x] = 0 -> (q ^ FtoE).[y] = 0 ->\n (div_annihilant p q ^ FtoE).[x / y] = 0.\n\n(*This lemma states that applying a polynomial with coefficients from a base field to an algebraic element over that field yields another algebraic element. Specifically, if an element is algebraic over a field and evaluating a polynomial at this element results in a non-zero value, then there exists a non-zero polynomial with coefficients in the base field that has this value as a root.*)\nLemma root_annihilant x p (pEx := (p ^ pFtoE).[x%:P]) :\n pEx != 0 -> algebraicOver FtoE x ->\n exists2 r : {poly F}, r != 0 & forall y, root pEx y -> root (r ^ FtoE) y.\n\n(*This definition provides a constructive function that, for a given algebraic element, computes an annihilating polynomial for the value obtained by applying a given polynomial to that element. It leverages an existence proof to define a function which takes two polynomials\u2014one of which has the algebraic element as a root\u2014and returns a non-zero polynomial that annihilates the result of evaluating the second polynomial at that element.*)\nLemma algebraic_root_polyXY x y :\n (let pEx p := (p ^ map_poly FtoE).[x%:P] in\n exists2 p, pEx p != 0 & root (pEx p) y) ->\n algebraicOver FtoE x -> algebraicOver FtoE y.", - "algebra.zmodp": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool choice eqtype ssrnat seq.\nFrom mathcomp Require Import div fintype bigop finset prime fingroup perm.\nFrom mathcomp Require Import ssralg finalg countalg.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope ring_scope.\n\nSection ZpDef.\n\nSection Generic.\nVariable p : nat.\nImplicit Types i j : 'I_p.\n\n(*This lemma states that for any natural number p and an ordinal i less than p, the remainder of the subtraction of i from p divided by p is strictly less than p. This ensures that the result is a valid ordinal in the type of integers modulo p.*)\nLemma Zp_opp_subproof i : (p - i) %% p < p.\n\n(*This definition specifies the additive inverse of an element in the ring of integers modulo a natural number p. For an input ordinal representing a value, it returns a new ordinal corresponding to the value p minus the input value, reduced modulo p.*)\nDefinition Zp_opp i := Ordinal (Zp_opp_subproof i).\n\n(*This lemma states that for any natural number p and two ordinals less than p, the remainder of their sum divided by p is strictly less than p. This ensures that their sum is a valid ordinal in the type of integers modulo p.*)\nLemma Zp_add_subproof i j : (i + j) %% p < p.\n\n(*This definition specifies the addition operation for two elements in the ring of integers modulo a natural number p. For two input ordinals, it returns a new ordinal corresponding to their sum, reduced modulo p.*)\nDefinition Zp_add i j := Ordinal (Zp_add_subproof i j).\n\n(*This lemma states that for any natural number p and two ordinals less than p, the remainder of their product divided by p is strictly less than p. This ensures that their product is a valid ordinal in the type of integers modulo p.*)\nLemma Zp_mul_subproof i j : (i * j) %% p < p.\n\n(*This definition specifies the multiplication operation for two elements in the ring of integers modulo a natural number p. For two input ordinals, it returns a new ordinal corresponding to their product, reduced modulo p.*)\nDefinition Zp_mul i j := Ordinal (Zp_mul_subproof i j).\n\n(*This lemma states that for any natural number p and an ordinal less than p, the first B\u00e9zout coefficient from the extended Euclidean algorithm for the ordinal's value and p, when reduced modulo p, is strictly less than p. This property is used to define the multiplicative inverse.*)\nLemma Zp_inv_subproof i : (egcdn i p).1 %% p < p.\n\n(*This definition specifies the multiplicative inverse of an element in the ring of integers modulo a natural number p. If the input ordinal's value is coprime to p, it returns a new ordinal representing the multiplicative inverse; otherwise, it returns the original ordinal.*)\nDefinition Zp_inv i := if coprime p i then Ordinal (Zp_inv_subproof i) else i.\n\n(*This lemma states that the addition operation defined for the integers modulo a natural number p is associative.*)\nLemma Zp_addA : associative Zp_add.\n\n(*This lemma states that the addition operation defined for the integers modulo a natural number p is commutative.*)\nLemma Zp_addC : commutative Zp_add.\n\n(*This lemma states that the multiplication operation defined for the integers modulo a natural number p is commutative.*)\nLemma Zp_mulC : commutative Zp_mul.\n\n(*This lemma states that the multiplication operation defined for the integers modulo a natural number p is associative.*)\nLemma Zp_mulA : associative Zp_mul.\n\n(*This lemma states that the multiplication operation defined for the integers modulo a natural number p is right distributive over the addition operation.*)\nLemma Zp_mul_addr : right_distributive Zp_mul Zp_add.\n\n(*This lemma states that the multiplication operation defined for the integers modulo a natural number p is left distributive over the addition operation.*)\nLemma Zp_mul_addl : left_distributive Zp_mul Zp_add.\n\n(*This lemma states that if the value of an ordinal is not coprime to the modulus p, then its multiplicative inverse is defined to be the ordinal itself.*)\nLemma Zp_inv_out i : ~~ coprime p i -> Zp_inv i = i.\n\nEnd Generic.\n\nArguments Zp_opp {p}.\nArguments Zp_add {p}.\nArguments Zp_mul {p}.\nArguments Zp_inv {p}.\n\nVariable p' : nat.\n(*A notation that defines a positive natural number as the successor of another natural number, which is used as the modulus for the ring of integers.*)\nLocal Notation p := p'.+1.\n\nImplicit Types x y z : 'I_p.\n\n(*This definition defines a function that converts a given natural number into a canonical representative element of the ring of integers modulo a positive natural number p by taking the remainder of its division by p.*)\nDefinition inZp i := Ordinal (ltn_pmod i (ltn0Sn p')).\n(*This lemma states that for any element in the ring of integers modulo a positive natural number p, taking the remainder of its value when divided by p yields the original value, because it is already in the canonical range.*)\nLemma modZp x : x %% p = x.\n\n(*This lemma states that converting an element from the ring of integers modulo a positive natural number p to its underlying natural number value and then converting it back to an element of the ring yields the original element.*)\nLemma valZpK x : inZp x = x.\n\n(*This definition specifies the additive identity, or zero element, in the ring of integers modulo a positive natural number p.*)\nDefinition Zp0 : 'I_p := ord0.\n(*This definition specifies the multiplicative identity, or one element, in the ring of integers modulo a positive natural number p.*)\nDefinition Zp1 := inZp 1.\n\n(*This lemma states that the zero element is the left identity for the addition operation in the ring of integers modulo a positive natural number p.*)\nLemma Zp_add0z : left_id Zp0 Zp_add.\n\n(*This lemma states that for every element in the ring of integers modulo a positive natural number p, its defined additive inverse is a true left inverse, resulting in the zero element when added to the original element.*)\nLemma Zp_addNz : left_inverse Zp0 Zp_opp Zp_add.\n\nHB.instance Definition _ :=\n GRing.isZmodule.Build 'I_p (@Zp_addA _) (@Zp_addC _) Zp_add0z Zp_addNz.\n\n(*This lemma states that the one element is the left identity for the multiplication operation in the ring of integers modulo a positive natural number p.*)\nLemma Zp_mul1z : left_id Zp1 Zp_mul.\n\n(*This lemma states that the one element is the right identity for the multiplication operation in the ring of integers modulo a positive natural number p.*)\nLemma Zp_mulz1 : right_id Zp1 Zp_mul.\n\n(*This lemma states that for any element in the ring of integers modulo a positive natural number p whose value is coprime to p, multiplying its multiplicative inverse by the element itself yields the one element.*)\nLemma Zp_mulVz x : coprime p x -> Zp_mul (Zp_inv x) x = Zp1.\n\n(*This lemma states that for any element in the ring of integers modulo a positive natural number p whose value is coprime to p, multiplying the element by its multiplicative inverse yields the one element.*)\nLemma Zp_mulzV x : coprime p x -> Zp_mul x (Zp_inv x) = Zp1.\n\n(*This lemma states that if the product of two elements in the ring of integers modulo a positive natural number p is equal to the one element, then the value of the second element is coprime to p.*)\nLemma Zp_intro_unit x y : Zp_mul y x = Zp1 -> coprime p x.\n\n(*This lemma states that repeatedly adding an element of the ring of integers modulo p to itself a given number of times is equivalent to multiplying the element's underlying numerical value by that number and then converting the result into an element of the ring.*)\nLemma Zp_mulrn x n : x *+ n = inZp (x * n).\n\nImport GroupScope.\n\n(*This lemma states that the multiplication operation within the group of units of the ring of integers modulo a positive natural number p is commutative.*)\nLemma Zp_mulgC : @commutative 'I_p _ mulg.\n\n(*This lemma states that the additive group structure on the finite cyclic group of a given order is commutative.*)\nLemma Zp_abelian : abelian [set: 'I_p].\n\n(*This lemma states that repeated addition of an element in a finite cyclic group of a given order is equivalent to the group element corresponding to the product of the natural number representations of the element and the repetition count.*)\nLemma Zp_expg x n : x ^+ n = inZp (x * n).\n\n(*This lemma states that repeatedly adding the generator of a finite cyclic group to itself a number of times results in the group element corresponding to that number.*)\nLemma Zp1_expgz x : Zp1 ^+ x = x.\n\n(*This lemma states that the entire set of elements in a finite cyclic group is generated by the single element one.*)\nLemma Zp_cycle : setT = <[Zp1]>.\n\n(*This lemma states that the order of the generator of a finite cyclic group is equal to the order of the group itself.*)\nLemma order_Zp1 : #[Zp1] = p.\n\nEnd ZpDef.\n\nArguments Zp0 {p'}.\nArguments Zp1 {p'}.\nArguments inZp {p'} i.\nArguments valZpK {p'} x.\n\n(*This lemma states that all elements of a finite type with exactly one element are equal to the zero element.*)\nLemma ord1 : all_equal_to (0 : 'I_1).\n\n(*This lemma states that left-shifting the zero element of a finite ordinal type by any amount results in the zero element of the correspondingly larger finite ordinal type.*)\nLemma lshift0 m n : lshift m (0 : 'I_n.+1) = (0 : 'I_(n + m).+1).\n\n(*This lemma states that the function that performs a right shift by one bit on elements of a finite ordinal type is equivalent to the function that lifts the zero element of the smaller finite ordinal type.*)\nLemma rshift1 n : @rshift 1 n =1 lift (0 : 'I_n.+1).\n\n(*This lemma provides a specific decomposition for an element of a finite ordinal type of size one plus a given natural number, expressing it as a combination of injections and unlifting operations.*)\nLemma split1 n i :\n split (i : 'I_(1 + n)) = oapp (@inr _ _) (inl _ 0) (unlift 0 i).\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use bigop.big_ord1 instead.\")]\n(*A deprecated notation for indexed operations over the unique element of a type with a single element.*)\nNotation big_ord1 := big_ord1 (only parsing).\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use bigop.big_ord1_cond instead.\")]\n(*A deprecated notation for conditional indexed operations over the unique element of a type with a single element.*)\nNotation big_ord1_cond := big_ord1_cond (only parsing).\n\nSection ZpNzRing.\n\nVariable p' : nat.\n(*A local notation that defines a natural number as a given natural number plus two, ensuring it is at least two.*)\nLocal Notation p := p'.+2.\n\n(*This lemma states that for any modulus greater than one, the element one in the corresponding finite cyclic ring is not equal to the zero element.*)\nLemma Zp_nontrivial : Zp1 != 0 :> 'I_p. \n\nHB.instance Definition _ :=\n GRing.Zmodule_isComNzRing.Build 'I_p\n (@Zp_mulA _) (@Zp_mulC _) (@Zp_mul1z _) (@Zp_mul_addl _) Zp_nontrivial.\n(*This lemma states that the canonical embedding of a natural number into the finite cyclic ring of a given order is equal to the element of that ring corresponding to the natural number.*)\nLemma Zp_nat n : n%:R = inZp n :> 'I_p.\n\n(*This lemma states that the canonical embedding of an element from a finite cyclic ring into that same ring is the identity operation.*)\nLemma natr_Zp (x : 'I_p) : x%:R = x.\n\n(*This lemma states that the canonical ring embedding of the additive inverse of an element from a finite cyclic ring is equal to the additive inverse of that element within the ring.*)\nLemma natr_negZp (x : 'I_p) : (- x)%:R = - x.\n\nImport GroupScope.\n\n(*This lemma states that multiplication is commutative for the group of units of a finite cyclic ring.*)\nLemma unit_Zp_mulgC : @commutative {unit 'I_p} _ mulg.\n\n(*This lemma states that the value of a unit raised to a natural number power in the group of units of a finite cyclic ring is equal to the ring element obtained by taking the value of the unit, raising it to the same power as a natural number, and then mapping the result back into the ring.*)\nLemma unit_Zp_expg (u : {unit 'I_p}) n :\n val (u ^+ n) = inZp (val u ^ n) :> 'I_p.\n\nEnd ZpNzRing.\n\n(*This definition computes a natural number by subtracting two from a given natural number, yielding zero if the given number is less than two.*)\nDefinition Zp_trunc p := p.-2.\n\n(*This notation provides a shorthand for the type of integers modulo a given natural number. It represents the finite ring of integers under arithmetic operations modulo the specified number.*)\nNotation \"''Z_' p\" := 'I_(Zp_trunc p).+2\n (at level 0, p at level 2, format \"''Z_' p\") : type_scope.\n(*This notation provides a shorthand for the type representing a prime finite field. Given a natural number, it constructs the field of integers modulo the smallest prime divisor of that number. If the input number is itself prime, this corresponds to the finite field with that many elements.*)\nNotation \"''F_' p\" := 'Z_(pdiv p)\n (at level 0, p at level 2, format \"''F_' p\") : type_scope.\n\nArguments natr_Zp {p'} x.\n\nSection ZpNzRing.\n\nImport GRing.Theory.\n\n(*This lemma states that adding one to an element in the ring of integers modulo a given number is equivalent to taking the successor of that element in the underlying finite ordinal representation.*)\nLemma add_1_Zp p (x : 'Z_p) : 1 + x = ordS x.\n\n(*This lemma states that adding an element in the ring of integers modulo a given number to one is equivalent to taking the successor of that element in the underlying finite ordinal representation.*)\nLemma add_Zp_1 p (x : 'Z_p) : x + 1 = ordS x.\n\n(*This lemma states that subtracting one from an element in the ring of integers modulo a given number is equivalent to taking the predecessor of that element in the underlying finite ordinal representation.*)\nLemma sub_Zp_1 p (x : 'Z_p) : x - 1 = ord_pred x.\n\n(*This lemma states that adding the additive inverse of one to an element in the ring of integers modulo a given number is equivalent to taking the predecessor of that element in the underlying finite ordinal representation.*)\nLemma add_N1_Zp p (x : 'Z_p) : -1 + x = ord_pred x.\n\nEnd ZpNzRing.\n\nSection Groups.\n\nVariable p : nat.\n\n(*This definition provides the additive group of integers modulo a given natural number. If the number is greater than one, it yields the full set of elements of the corresponding ring; otherwise, it yields the trivial group.*)\nDefinition Zp := if p > 1 then [set: 'Z_p] else 1%g.\n(*This definition provides the multiplicative group of units, which are the invertible elements, for the ring of integers modulo a given natural number.*)\nDefinition units_Zp := [set: {unit 'Z_p}].\n\n(*This lemma states that for any natural number greater than one, the expression used to define the modulus of the corresponding ring of integers simplifies back to the original number.*)\nLemma Zp_cast : p > 1 -> (Zp_trunc p).+2 = p.\n\n(*This lemma states that for a modulus greater than one, the underlying natural number representation of the ring element corresponding to a given natural number is equal to the remainder of that number when divided by the modulus.*)\nLemma val_Zp_nat (p_gt1 : p > 1) n : (n%:R : 'Z_p) = (n %% p)%N :> nat.\n\n(*This lemma states that for a modulus greater than one, embedding a natural number into the ring of integers modulo that number yields the same element as first taking the remainder of the number modulo the modulus and then embedding the result.*)\nLemma Zp_nat_mod (p_gt1 : p > 1)m : (m %% p)%:R = m%:R :> 'Z_p.\n\n(*This lemma states that for a natural number p greater than one, its representation in the ring of integers modulo p is equal to the zero element.*)\nLemma pchar_Zp : p > 1 -> p%:R = 0 :> 'Z_p.\n\n(*This lemma states that for a natural number p greater than one, an element in the ring of integers modulo p is a unit if and only if the natural number it represents is coprime to p.*)\nLemma unitZpE x : p > 1 -> ((x%:R : 'Z_p) \\is a GRing.unit) = coprime p x.\n\n(*This lemma states that the type of integers modulo a natural number p forms a group under addition.*)\nLemma Zp_group_set : group_set Zp.\n\nCanonical Zp_group := Group Zp_group_set.\n\n(*This lemma states that for any positive natural number p, the cardinality of the ring of integers modulo p is equal to p.*)\nLemma card_Zp : p > 0 -> #|Zp| = p.\n\n(*This lemma states that any element of the ring of integers modulo p is a member of the underlying set of that ring, provided p is greater than one.*)\nLemma mem_Zp x : p > 1 -> x \\in Zp. \n\nCanonical units_Zp_group := [group of units_Zp].\n\n(*This lemma states that for a positive natural number p, the number of units in the ring of integers modulo p is equal to the value of Euler's totient function at p.*)\nLemma card_units_Zp : p > 0 -> #|units_Zp| = totient p.\n\n(*This lemma states that the group of units of the ring of integers modulo a natural number is an abelian group.*)\nLemma units_Zp_abelian : abelian units_Zp.\n\nEnd Groups.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar_Zp instead.\")]\n(*This is a deprecated notation, which was an alias for the lemma `pchar_Zp` and is provided for parsing compatibility only. Use of `pchar_Zp` is recommended instead.*)\nNotation char_Zp := (pchar_Zp) (only parsing).\n\nSection PrimeField.\n\nOpen Scope ring_scope.\n\nVariable p : nat.\n\nSection F_prime.\n\nHypothesis p_pr : prime p.\n\n(*This lemma states that, for a prime number p, casting the integer p to the prime field with p elements yields the same result as casting the natural number p.*)\nLemma Fp_Zcast : Zp_trunc (pdiv p) = Zp_trunc p.\n\n(*This lemma states that the modulus associated with the canonical casting from integers to the prime field with p elements is indeed the natural number p.*)\nLemma Fp_cast : (Zp_trunc (pdiv p)).+2 = p.\n\n(*This lemma states that for a prime number p, the cardinality of the prime field with p elements is equal to p.*)\nLemma card_Fp : #|'F_p| = p.\n\n(*This lemma states that for a prime number p, when a natural number is cast into the prime field with p elements, the canonical natural number representation of the result is equal to the original natural number modulo p.*)\nLemma val_Fp_nat n : (n%:R : 'F_p) = (n %% p)%N :> nat.\n\n(*This lemma states that for a prime number p, casting a natural number into the prime field with p elements gives the same result as casting that number's remainder after division by p.*)\nLemma Fp_nat_mod m : (m %% p)%:R = m%:R :> 'F_p.\n\n(*This lemma states that for a prime number p, p is a member of the set of positive characteristics of the prime field with p elements.*)\nLemma pchar_Fp : p \\in [pchar 'F_p].\n\n(*This lemma states that for a prime number p, casting the natural number p into the prime field with p elements results in the zero element of the field.*)\nLemma pchar_Fp_0 : p%:R = 0 :> 'F_p.\n\n(*This lemma states that for a prime number p, an element in the prime field with p elements that corresponds to a natural number is a unit if and only if that natural number is coprime to p.*)\nLemma unitFpE x : ((x%:R : 'F_p) \\is a GRing.unit) = coprime p x.\n\nEnd F_prime.\n\n(*This lemma states that the prime field with p elements is a field, meaning it is a commutative ring in which every nonzero element has a multiplicative inverse.*)\nLemma Fp_fieldMixin : GRing.ComUnitRing_isField 'F_p.\n\nHB.instance Definition _ := Fp_fieldMixin.\n(*This lemma states that for any natural number n, the symmetric group on n plus one elements is generated by the set of transpositions that swap an index i with the sum of i and k for all i from zero to n, provided k is a natural number coprime to n plus one. All arithmetic on indices is modulo n plus one.*)\nLemma gen_tperm_step n (k : 'I_n.+1) : coprime n.+1 k ->\n <<[set tperm i (i + k) | i : 'I_n.+1]>>%g = [set: 'S_n.+1].\n\n(*This lemma specifies the result of applying a composite permutation to an element of a finite set of integers modulo n plus one. It states that repeatedly applying a permutation defined as addition by m for j times to an element k is equivalent to adding the product of m and j to k.*)\nLemma perm_addr1X n m (j k : 'I_n.+1) : (perm (addrI m%R) ^+ j)%g k = m *+ j + k.\n\n(*This lemma states that the symmetric group on n plus two elements is generated by two permutations: a single transposition and a full-length cycle, provided the distance between the two elements of the transposition is coprime to n plus two.*)\nLemma gen_tpermn_circular_shift n (i j : 'I_n.+2)\n (c := perm (addrI 1)) : coprime n.+2 (j - i)%R ->\n <<[set tperm i j ; c]>>%g = [set: 'S_n.+2].\n\nEnd Sym.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar_Fp instead.\")]\n(*This is a deprecated notation, which was an alias for the lemma `pchar_Fp` and is provided for parsing compatibility only. Use of `pchar_Fp` is recommended instead.*)\nNotation char_Fp := (pchar_Fp) (only parsing).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar_Fp_0 instead.\")]\n(*This is a deprecated notation, which was an alias for the lemma `pchar_Fp_0` and is provided for parsing compatibility only. Use of `pchar_Fp_0` is recommended instead.*)", - "algebra.fraction": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat div seq.\nFrom mathcomp Require Import ssrAC choice tuple bigop ssralg poly polydiv.\nFrom mathcomp Require Import generic_quotient.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GRing.Theory.\nLocal Open Scope ring_scope.\nLocal Open Scope quotient_scope.\n\nReserved Notation \"{ 'ratio' T }\" (format \"{ 'ratio' T }\").\nReserved Notation \"{ 'fraction' T }\" (format \"{ 'fraction' T }\").\nReserved Notation \"x %:F\" (format \"x %:F\").\n\nSection FracDomain.\nVariable R : nzRingType.\n\n(*This inductive type defines a ratio as a pair of ring elements, where the second element, representing the denominator, is constrained to be non-zero. It serves as the underlying representation for fractions before considering equivalence.*)\nInductive ratio := mkRatio { frac :> R * R; _ : frac.2 != 0 }.\n\nHB.instance Definition _ := [isSub for frac].\n(*This lemma states that for any given ratio, its denominator is guaranteed to be a non-zero element.*)\nLemma denom_ratioP : forall f : ratio, f.2 != 0. \n\n(*This definition establishes the zero ratio as the fraction represented by zero divided by one.*)\nDefinition ratio0 := (@mkRatio (0, 1) (oner_neq0 _)).\n(*This definition provides a safe constructor for a ratio from two ring elements, a numerator and a denominator. If the provided denominator is non-zero, it returns the ratio of the numerator over the denominator; otherwise, it returns the canonical zero ratio.*)\nDefinition Ratio x y : ratio := insubd ratio0 (x, y).\n\n(*This lemma states that for a ratio constructed with a non-zero denominator, its numerator is equal to the first input provided to the constructor.*)\nLemma numer_Ratio x y : y != 0 -> (Ratio x y).1 = x.\n\n(*This lemma states that for a ratio constructed with a non-zero denominator, its denominator is equal to the second input provided to the constructor.*)\nLemma denom_Ratio x y : y != 0 -> (Ratio x y).2 = y.\n\n(*This definition packages two lemmas together, one asserting the property of the numerator and the other asserting the property of the denominator for a ratio constructed with a non-zero denominator.*)\nDefinition numden_Ratio := (numer_Ratio, denom_Ratio).\n\n(*This inductive type specifies the outcome of the safe ratio constructor. It has two cases: one for when the denominator is zero, resulting in the zero ratio, and another for when the denominator is non-zero, resulting in a specific ratio with the given numerator and denominator.*)\nVariant Ratio_spec (n d : R) : ratio -> R -> R -> Type :=\n(**)\n | RatioNull of d = 0 : Ratio_spec n d ratio0 n 0\n(**)\n | RatioNonNull (d_neq0 : d != 0) :\n Ratio_spec n d (@mkRatio (n, d) d_neq0) n d.\n\n(*This lemma proves that the safe ratio constructor always produces an output that conforms to its specification, correctly handling both zero and non-zero denominator cases.*)\nLemma RatioP n d : Ratio_spec n d (Ratio n d) n d.\n\n(*This lemma states that constructing a ratio with any numerator and a zero denominator results in the canonical zero ratio.*)\nLemma Ratio0 x : Ratio x 0 = ratio0.\n\nEnd FracDomain.\n\nArguments ratio R%_type.\n\n(*This notation provides a syntax for the type of raw fractions, representing pairs of ring elements where the second element is non-zero.*)\nNotation \"{ 'ratio' T }\" := (ratio T) : type_scope.\n\n(*This notation provides a syntax to access the numerator of a raw fraction.*)\nNotation \"'\\n_' x\" := (frac x).1\n (at level 8, x at level 2, format \"'\\n_' x\").\n(*This notation provides a syntax to access the denominator of a raw fraction.*)\nNotation \"'\\d_' x\" := (frac x).2\n (at level 8, x at level 2, format \"'\\d_' x\").\n\nModule FracField.\nSection FracField.\n\nVariable R : idomainType.\n\n(*This field acts as a coercion to extract the underlying pair of ring elements, the numerator and the denominator, from a raw fraction object.*)\nLocal Notation frac := (R * R).\n(*This notation serves as a local alias for the type of raw fractions over the underlying integral domain.*)\nLocal Notation dom := (ratio R).\n(*This notation serves as a local alias for the lemma which asserts that the denominator of any raw fraction is non-zero.*)\nLocal Notation domP := denom_ratioP.\n\nImplicit Types x y z : dom.\n\nLocal Notation equivf_notation x y := (\\n_x * \\d_y == \\d_x * \\n_y).\n(*This definition establishes the equivalence relation for raw fractions, where two fractions are considered equivalent if the product of the numerator of the first and the denominator of the second is equal to the product of the denominator of the first and the numerator of the second.*)\nDefinition equivf x y := equivf_notation x y.\n\n(*This lemma states that the equivalence relation on raw fractions is definitionally equal to the cross-multiplication equality check.*)\nLemma equivfE x y : equivf x y = equivf_notation x y.\n\n(*This lemma states that the equivalence relation for raw fractions is reflexive, meaning any raw fraction is equivalent to itself.*)\nLemma equivf_refl : reflexive equivf.\n\n(*This lemma states that the equivalence relation for raw fractions is symmetric, meaning if a first fraction is equivalent to a second, then the second is also equivalent to the first.*)\nLemma equivf_sym : symmetric equivf.\n\n(*This lemma states that the equivalence relation for raw fractions is transitive, meaning if a first fraction is equivalent to a second, and the second is equivalent to a third, then the first is equivalent to the third.*)\nLemma equivf_trans : transitive equivf.\n\nCanonical equivf_equiv := EquivRel equivf equivf_refl equivf_sym equivf_trans.\n\n(*This definition establishes the type for the field of fractions, which is constructed as the quotient of the type of raw fractions by the standard fraction equivalence relation.*)\nDefinition type := {eq_quot equivf}.\n\nHB.instance Definition _ : EqQuotient _ equivf type := EqQuotient.on type.\nHB.instance Definition _ := Choice.on type.\n\n(*This lemma states that the equality of two elements in the quotient type for fractions is equivalent to their representatives being related by the cross-multiplication equivalence relation.*)\nLemma equivf_def (x y : ratio R) : x == y %[mod type]\n = (\\n_x * \\d_y == \\d_x * \\n_y).\n\n(*This lemma states that any given raw fraction is equivalent to the canonical representative of its equivalence class.*)\nLemma equivf_r x : \\n_x * \\d_(repr (\\pi_type x)) = \\d_x * \\n_(repr (\\pi_type x)).\n\n(*This lemma states that the canonical representative of an equivalence class of a raw fraction is equivalent to that original raw fraction.*)\nLemma equivf_l x : \\n_(repr (\\pi_type x)) * \\d_x = \\d_(repr (\\pi_type x)) * \\n_x.\n\n(*This lemma states that a raw fraction has a zero numerator if and only if it is equivalent to the canonical zero ratio.*)\nLemma numer0 x : (\\n_x == 0) = (x == (ratio0 R) %[mod_eq equivf]).\n\n(*This lemma states that a fraction is equivalent to the raw fraction constructed from its own canonical numerator and denominator.*)\nLemma Ratio_numden : forall x, Ratio \\n_x \\d_x = x.\n\n(*This definition provides a function that embeds an element from an integral domain into its field of fractions by representing it as a fraction with a denominator of one.*)\nDefinition tofrac := lift_embed type (fun x : R => Ratio x 1).\nCanonical tofrac_pi_morph := PiEmbed tofrac.\n\n(*This notation provides a syntax to embed an element from an integral domain into its corresponding field of fractions.*)\nNotation \"x %:F\" := (@tofrac x).\n\nImplicit Types a b c : type.\n\n(*This definition specifies the addition of two raw fractions by computing a new fraction whose numerator is the sum of the cross-products of the numerators and denominators, and whose denominator is the product of the original denominators.*)\nDefinition addf x y : dom := Ratio (\\n_x * \\d_y + \\n_y * \\d_x) (\\d_x * \\d_y).\n(*This definition defines the addition operation on the field of fractions by lifting the raw fraction addition to the canonical representation.*)\nDefinition add := lift_op2 type addf.\n\n(*This lemma states that the canonical projection from raw fractions to the field of fractions is a morphism with respect to addition, meaning that adding two raw fractions and then projecting is equivalent to projecting the fractions first and then adding them.*)\nLemma pi_add : {morph \\pi : x y / addf x y >-> add x y}.\n\nCanonical pi_add_morph := PiMorph2 pi_add.\n\n(*This definition specifies the additive inverse of a raw fraction by creating a new fraction with the negated numerator and the same denominator.*)\nDefinition oppf x : dom := Ratio (- \\n_x) \\d_x.\n(*This definition defines the additive inverse operation on the field of fractions by lifting the raw fraction negation to the canonical representation.*)\nDefinition opp := lift_op1 type oppf.\n(*This lemma states that the canonical projection from raw fractions to the field of fractions is a morphism with respect to additive inversion, meaning that negating a raw fraction and then projecting is equivalent to projecting the fraction first and then negating it.*)\nLemma pi_opp : {morph \\pi : x / oppf x >-> opp x}.\n\nCanonical pi_opp_morph := PiMorph1 pi_opp.\n\n(*This definition specifies the multiplication of two raw fractions by computing a new fraction whose numerator is the product of the original numerators and whose denominator is the product of the original denominators.*)\nDefinition mulf x y : dom := Ratio (\\n_x * \\n_y) (\\d_x * \\d_y).\n(*This definition defines the multiplication operation on the field of fractions by lifting the raw fraction multiplication to the canonical representation.*)\nDefinition mul := lift_op2 type mulf.\n\n(*This lemma states that the canonical projection from raw fractions to the field of fractions is a morphism with respect to multiplication, meaning that multiplying two raw fractions and then projecting is equivalent to projecting the fractions first and then multiplying them.*)\nLemma pi_mul : {morph \\pi : x y / mulf x y >-> mul x y}.\n\nCanonical pi_mul_morph := PiMorph2 pi_mul.\n\n(*This definition specifies the multiplicative inverse of a raw fraction by creating a new fraction where the original numerator and denominator are swapped.*)\nDefinition invf x : dom := Ratio \\d_x \\n_x.\n(*This definition defines the multiplicative inverse operation on the field of fractions by lifting the raw fraction inversion to the canonical representation.*)\nDefinition inv := lift_op1 type invf.\n\n(*This lemma states that the canonical projection from raw fractions to the field of fractions is a morphism with respect to multiplicative inversion, meaning that inverting a raw fraction and then projecting is equivalent to projecting the fraction first and then inverting it.*)\nLemma pi_inv : {morph \\pi : x / invf x >-> inv x}.\n\nCanonical pi_inv_morph := PiMorph1 pi_inv.\n\n(*This lemma states that the addition operation on the field of fractions is associative.*)\nLemma addA : associative add.\n\n(*This lemma states that the addition operation on the field of fractions is commutative.*)\nLemma addC : commutative add.\n\n(*This lemma states that the fractional representation of zero is the left identity for addition in the field of fractions.*)\nLemma add0_l : left_id 0%:F add.\n\n(*This lemma states that for any element in the field of fractions, its additive inverse is a left inverse with respect to addition, yielding the additive identity.*)\nLemma addN_l : left_inverse 0%:F opp add.\n\nHB.instance Definition _ := GRing.isZmodule.Build type addA addC add0_l addN_l.\n\n(*This lemma states that the multiplication operation on the field of fractions is associative.*)\nLemma mulA : associative mul.\n\n(*This lemma states that the multiplication operation on the field of fractions is commutative.*)\nLemma mulC : commutative mul.\n\n(*This lemma states that the fractional representation of one is the left identity for multiplication in the field of fractions.*)\nLemma mul1_l : left_id 1%:F mul.\n\n(*This lemma states that multiplication is left-distributive over addition in the field of fractions.*)\nLemma mul_addl : left_distributive mul add.\n\n(*This lemma states that the multiplicative identity and the additive identity in the field of fractions are distinct.*)\nLemma nonzero1 : 1%:F != 0%:F :> type.\n\nHB.instance Definition _ :=\n GRing.Zmodule_isComNzRing.Build type mulA mulC mul1_l mul_addl nonzero1.\n\n(*This lemma states that for any non-zero element in the field of fractions, its multiplicative inverse is a left inverse with respect to multiplication, yielding the multiplicative identity.*)\nLemma mulV_l : forall a, a != 0%:F -> mul (inv a) a = 1%:F.\n\n(*This lemma states that the multiplicative inverse of the additive identity in the field of fractions is defined to be the additive identity itself.*)\nLemma inv0 : inv 0%:F = 0%:F.\n\n(*This notation represents the type of the field of fractions constructed from a given integral domain.*)\nNotation \"{ 'fraction' T }\" := (FracField.type T).\n(*This notation represents the equivalence relation on raw fractions, where two fractions are considered equivalent if their cross-products are equal.*)\nNotation equivf := (@FracField.equivf _).\n#[global] Hint Resolve denom_ratioP : core.\n\n#[warning=\"-HB.no-new-instance\"]\n(*This lemma states that the numerator and the denominator of the canonical representation of a fraction are coprime integers.*)\nLemma Ratio_numden (x : {ratio R}) : Ratio \\n_x \\d_x = x.\n\n(*This function defines the canonical embedding of an element from an integral domain into its corresponding field of fractions.*)\nLocal Notation tofrac := (@FracField.tofrac R).\n(*This notation represents the canonical embedding of an element from an integral domain into its field of fractions, which maps the element to a fraction with that element as the numerator and one as the denominator.*)\nLocal Notation \"x %:F\" := (tofrac x).\n\n(*This lemma states that the canonical embedding from an integral domain into its field of fractions is a Z-module morphism. This means the function preserves the additive group structure, mapping the zero of the domain to the zero of the fraction field and preserving the addition operation.*)\nLemma tofrac_is_zmod_morphism: zmod_morphism tofrac.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `tofrac_is_zmod_morphism` instead\")]\n(*This definition, now deprecated, asserts that the canonical embedding into the field of fractions preserves the additive structure, meaning it is a morphism for the additive group.*)\nDefinition tofrac_is_additive := tofrac_is_zmod_morphism.\n\nHB.instance Definition _ := GRing.isZmodMorphism.Build R {fraction R} tofrac\n tofrac_is_zmod_morphism.\n\n(*This lemma states that the canonical embedding from an integral domain into its field of fractions is a monoid morphism. This means the function preserves the multiplicative monoid structure, mapping the multiplicative identity of the domain to the multiplicative identity of the fraction field and preserving the multiplication operation.*)\nLemma tofrac_is_monoid_morphism: monoid_morphism tofrac.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `tofrac_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, asserts that the canonical embedding into the field of fractions preserves the multiplicative structure, meaning it is a morphism for the multiplicative monoid.*)\nDefinition tofrac_is_multiplicative := tofrac_is_monoid_morphism.\n\n(*This lemma states that embedding the zero element of an integral domain into its field of fractions yields the zero element of that field.*)\nLemma tofrac0 : 0%:F = 0. \n(*This lemma states that the embedding of the additive inverse of an element is equal to the additive inverse of the embedding of that element.*)\nLemma tofracN : {morph tofrac: x / - x}. \n(*This lemma states that the embedding of the sum of two elements is equal to the sum of their individual embeddings.*)\nLemma tofracD : {morph tofrac: x y / x + y}. \n(*This lemma states that the embedding of the difference of two elements is equal to the difference of their individual embeddings.*)\nLemma tofracB : {morph tofrac: x y / x - y}. \n(*This lemma states that the embedding of an element multiplied by a natural number scalar is equal to the embedding of that element multiplied by the same scalar in the field of fractions.*)\nLemma tofracMn n : {morph tofrac: x / x *+ n}. \n(*This lemma states that the embedding of an element multiplied by an integer scalar is equal to the embedding of that element multiplied by the same scalar in the field of fractions.*)\nLemma tofracMNn n : {morph tofrac: x / x *- n}. \n(*This lemma states that embedding the multiplicative identity of an integral domain into its field of fractions yields the multiplicative identity of that field.*)\nLemma tofrac1 : 1%:F = 1. \n(*This lemma states that the embedding of the product of two elements is equal to the product of their individual embeddings.*)\nLemma tofracM : {morph tofrac: x y / x * y}. \n(*This lemma states that the embedding of an element raised to a natural number power is equal to the embedding of that element raised to the same power in the field of fractions.*)\nLemma tofracXn n : {morph tofrac: x / x ^+ n}. \n\n(*This lemma states that two elements from an integral domain are equal if and only if their embeddings into the field of fractions are equal.*)\nLemma tofrac_eq (p q : R): (p%:F == q%:F) = (p == q).\n\n(*This lemma states that the embedding of an element from an integral domain is equal to zero if and only if the element itself is zero.*)\nLemma tofrac_eq0 (p : R): (p%:F == 0) = (p == 0).", - "algebra.matrix": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype finfun finset fingroup perm order div.\nFrom mathcomp Require Import prime binomial ssralg countalg finalg zmodp bigop.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\nImport GRing.Theory.\nLocal Open Scope ring_scope.\n\nReserved Notation \"''M_' n\" (at level 0, n at level 2, format \"''M_' n\").\nReserved Notation \"''rV_' n\" (at level 0, n at level 2, format \"''rV_' n\").\nReserved Notation \"''cV_' n\" (at level 0, n at level 2, format \"''cV_' n\").\nReserved Notation \"''M_' ( n )\". \nReserved Notation \"''M_' ( m , n )\" (format \"''M_' ( m , n )\").\nReserved Notation \"''M[' R ]_ n\" (at level 0, n at level 2). \nReserved Notation \"''rV[' R ]_ n\" (at level 0, n at level 2). \nReserved Notation \"''cV[' R ]_ n\" (at level 0, n at level 2). \nReserved Notation \"''M[' R ]_ ( n )\". \nReserved Notation \"''M[' R ]_ ( m , n )\". \n\nReserved Notation \"\\matrix_ i E\"\n (at level 36, E at level 36, i at level 2,\n format \"\\matrix_ i E\").\nReserved Notation \"\\matrix_ ( i < n ) E\"\n (E at level 36, i, n at level 50). \nReserved Notation \"\\matrix_ ( i , j ) E\"\n (E at level 36, j at level 50,\n format \"\\matrix_ ( i , j ) E\").\nReserved Notation \"\\matrix[ k ]_ ( i , j ) E\"\n (at level 36, E at level 36, i, j at level 50,\n format \"\\matrix[ k ]_ ( i , j ) E\").\nReserved Notation \"\\matrix_ ( i < m , j < n ) E\"\n (E at level 36, j, n at level 50). \nReserved Notation \"\\matrix_ ( i , j < n ) E\"\n (E at level 36, j, n at level 50). \nReserved Notation \"\\row_ j E\"\n (at level 36, E at level 36, j at level 2,\n format \"\\row_ j E\").\nReserved Notation \"\\row_ ( j < n ) E\"\n (at level 36, E at level 36, j, n at level 50). \nReserved Notation \"\\col_ j E\"\n (at level 36, E at level 36, j at level 2,\n format \"\\col_ j E\").\nReserved Notation \"\\col_ ( j < n ) E\"\n (at level 36, E at level 36, j, n at level 50). \nReserved Notation \"\\mxblock_ ( i , j ) E\"\n (at level 36, E at level 36, i, j at level 50,\n format \"\\mxblock_ ( i , j ) E\").\nReserved Notation \"\\mxblock_ ( i < m , j < n ) E\"\n (E at level 36, i, m, j, n at level 50). \nReserved Notation \"\\mxblock_ ( i , j < n ) E\"\n (E at level 36, i, j, n at level 50). \nReserved Notation \"\\mxrow_ j E\"\n (at level 36, E at level 36, j at level 2,\n format \"\\mxrow_ j E\").\nReserved Notation \"\\mxrow_ ( j < n ) E\"\n (E at level 36, j, n at level 50). \nReserved Notation \"\\mxcol_ j E\"\n (at level 36, E at level 36, j at level 2,\n format \"\\mxcol_ j E\").\nReserved Notation \"\\mxcol_ ( j < n ) E\"\n (E at level 36, j, n at level 50). \nReserved Notation \"\\mxdiag_ j E\"\n (at level 36, E at level 36, j at level 2,\n format \"\\mxdiag_ j E\").\nReserved Notation \"\\mxdiag_ ( j < n ) E\"\n (E at level 36, j, n at level 50). \n\nReserved Notation \"x %:M\" (format \"x %:M\").\nReserved Notation \"A *m B\" (at level 40, left associativity, format \"A *m B\").\nReserved Notation \"A ^T\" (format \"A ^T\").\nReserved Notation \"\\tr A\" (at level 10, A at level 8, format \"\\tr A\").\nReserved Notation \"\\det A\" (at level 10, A at level 8, format \"\\det A\").\nReserved Notation \"\\adj A\" (at level 10, A at level 8, format \"\\adj A\").\n\nReserved Notation \"{ ''GL_' n [ R ] }\"\n (n at level 2, format \"{ ''GL_' n [ R ] }\").\nReserved Notation \"{ ''GL_' n ( p ) }\"\n (p at level 10, format \"{ ''GL_' n ( p ) }\").\n\n(*This local notation defines a simplification hint named 'simp' which combines a monoid simplification tactic with a lemma stating that the opposite of a ring element is zero if and only if the element itself is zero.*)\nLocal Notation simp := (Monoid.Theory.simpm, oppr0).\n\nSection MatrixDef.\n\nVariable R : Type.\nVariables m n : nat.\n\n(*A type for matrices with a specified number of rows and columns, where entries are drawn from a given base type. A matrix is represented as a function that maps a pair of row and column indices to an entry.*)\nVariant matrix : predArgType := Matrix of {ffun 'I_m * 'I_n -> R}.\n\n(*This definition extracts the underlying representation of a matrix, which is a finite function mapping pairs of row and column indices to the matrix entries.*)\nDefinition mx_val A := let: Matrix g := A in g.\n\n(*This definition provides a function that, given a matrix, a row index, and a column index, returns the element located at that specific entry in the matrix.*)\nDefinition fun_of_matrix A (i : 'I_m) (j : 'I_n) := mx_val A (i, j).\n\nCoercion fun_of_matrix : matrix >-> Funclass.\n\nEnd MatrixDef.\n\n(*This fact provides a unique, opaque term of the unit type, used as a key to ensure the canonicity of the function-to-matrix conversion.*)\nFact matrix_key : unit. \n\nHB.lock\n(*This definition constructs a matrix from a given function. It takes as input the type of the matrix elements, the number of rows and columns, a key, and a function that maps a pair of row and column indices to the corresponding matrix entry.*)\nDefinition matrix_of_fun R (m n : nat) (k : unit) (F : 'I_m -> 'I_n -> R) :=\n @Matrix R m n [ffun ij => F ij.1 ij.2].\nCanonical matrix_unlockable := Unlockable matrix_of_fun.unlock.\n\nSection MatrixDef2.\n\nVariable R : Type.\nVariables m n : nat.\nImplicit Type F : 'I_m -> 'I_n -> R.\n\n(*This lemma states that a matrix constructed from a function is extensionally equal to that original function, meaning they produce the same output for any given pair of row and column indices.*)\nLemma mxE k F : matrix_of_fun k F =2 F.\n\n(*This lemma states that two matrices of the same dimensions are definitionally equal if and only if they are extensionally equal, which means they have identical entries at every corresponding position.*)\nLemma matrixP (A B : matrix R m n) : A =2 B <-> A = B.\n\n(*This lemma states that if two functions mapping indices to matrix entries are extensionally equal, then the matrices constructed from these functions are definitionally equal.*)\nLemma eq_mx k F1 F2 : (F1 =2 F2) -> matrix_of_fun k F1 = matrix_of_fun k F2.\n\nEnd MatrixDef2.\n\nArguments eq_mx {R m n k} [F1] F2 eq_F12.\n\nBind Scope ring_scope with matrix.\n\n(*This notation defines the type of matrices with a specified number of rows and columns, containing elements of a given type.*)\nNotation \"''M[' R ]_ ( m , n )\" := (matrix R m n) (only parsing): type_scope.\n(*This notation represents the type of row vectors of a given length, whose elements are of a specified type. A row vector is represented as a matrix with one row.*)\nNotation \"''rV[' R ]_ n\" := 'M[R]_(1, n) (only parsing) : type_scope.\n(*This notation represents the type of column vectors of a given length, whose elements are of a specified type. A column vector is represented as a matrix with one column.*)\nNotation \"''cV[' R ]_ n\" := 'M[R]_(n, 1) (only parsing) : type_scope.\n(*This notation represents the type of square matrices of a given size, whose elements are of a specified type.*)\nNotation \"''M[' R ]_ n\" := 'M[R]_(n, n) (only parsing) : type_scope.\n(*This notation serves as an alternative representation for the type of square matrices of a given size, containing elements of a specified type.*)\nNotation \"''M[' R ]_ ( n )\" := 'M[R]_n (only parsing) : type_scope.\n(*This notation defines the type of matrices with a specified number of rows and columns, where the type of the matrix elements is inferred from the context.*)\nNotation \"''M_' ( m , n )\" := 'M[_]_(m, n) : type_scope.\n(*This notation represents the type of row vectors of a given length, where the type of the vector's elements is inferred from the context. A row vector is implemented as a matrix with one row.*)\nNotation \"''rV_' n\" := 'M_(1, n) : type_scope.\n(*This notation represents the type of column vectors of a given length, where the type of the vector's elements is inferred from the context. A column vector is implemented as a matrix with one column.*)\nNotation \"''cV_' n\" := 'M_(n, 1) : type_scope.\n(*This notation represents the type of square matrices of a given size, where the type of the matrix elements is inferred from the context.*)\nNotation \"''M_' n\" := 'M_(n, n) : type_scope.\n(*This notation serves as an alternative representation for the type of square matrices of a given size, where the element type is inferred from the context.*)\nNotation \"''M_' ( n )\" := 'M_n (only parsing) : type_scope.\n\n(*This notation constructs a matrix whose dimensions are inferred from the context. The entry at a given row and column is determined by an expression that depends on the row and column indices. The notation includes a key for managing canonical structures.*)\nNotation \"\\matrix[ k ]_ ( i , j ) E\" := (matrix_of_fun k (fun i j => E)) :\n ring_scope.\n\n(*This notation constructs a matrix with a specified number of rows and columns. The value of each entry is determined by an expression that depends on the corresponding row and column indices, which range up to the specified dimensions.*)\nNotation \"\\matrix_ ( i < m , j < n ) E\" :=\n (@matrix_of_fun _ m n matrix_key (fun i j => E)) (only parsing) : ring_scope.\n\n(*This notation provides a shorthand for constructing a square matrix of a given size. The value of each entry is determined by an expression that depends on the corresponding row and column indices.*)\nNotation \"\\matrix_ ( i , j < n ) E\" :=\n (\\matrix_(i < n, j < n) E) (only parsing) : ring_scope.\n\n(*This notation constructs a matrix whose dimensions are inferred from the context. The value of each entry is determined by an expression that depends on the corresponding row and column indices.*)\nNotation \"\\matrix_ ( i , j ) E\" := (\\matrix_(i < _, j < _) E) : ring_scope.\n\n(*This notation constructs a matrix with a specified number of rows, where each row is defined by an expression that evaluates to a row vector. The number of columns is inferred from the length of these row vectors.*)\nNotation \"\\matrix_ ( i < m ) E\" :=\n (\\matrix_(i < m, j < _) @fun_of_matrix _ 1 _ E 0 j)\n (only parsing) : ring_scope.\n(*This notation constructs a matrix where each row is defined by an expression that evaluates to a row vector. The number of rows and columns are both inferred from the context.*)\nNotation \"\\matrix_ i E\" := (\\matrix_(i < _) E) : ring_scope.\n\n(*This notation constructs a column vector of a specified length. The value of each entry is determined by an expression that depends on the corresponding row index.*)\nNotation \"\\col_ ( i < n ) E\" := (@matrix_of_fun _ n 1 matrix_key (fun i _ => E))\n (only parsing) : ring_scope.\n(*This notation constructs a column vector whose length is inferred from the context. The value of each entry is determined by an expression that depends on the corresponding row index.*)\nNotation \"\\col_ i E\" := (\\col_(i < _) E) : ring_scope.\n\n(*This notation constructs a row vector of a specified length. The value of each entry is determined by an expression that depends on the corresponding column index.*)\nNotation \"\\row_ ( j < n ) E\" := (@matrix_of_fun _ 1 n matrix_key (fun _ j => E))\n (only parsing) : ring_scope.\n(*This notation constructs a row vector whose length is inferred from the context. The value of each entry is determined by an expression that depends on the corresponding column index.*)\nNotation \"\\row_ j E\" := (\\row_(j < _) E) : ring_scope.\n\nHB.instance Definition _ (R : eqType) m n := [Equality of 'M[R]_(m, n) by <:].\nHB.instance Definition _ (R : choiceType) m n := [Choice of 'M[R]_(m, n) by <:].\nHB.instance Definition _ (R : countType) m n := [Countable of 'M[R]_(m, n) by <:].\nHB.instance Definition _ (R : finType) m n := [Finite of 'M[R]_(m, n) by <:].\n\n(*This lemma states that the total number of distinct matrices with a given number of rows and columns over a finite type is equal to the cardinality of that base type raised to the power of the product of the number of rows and columns.*)\nLemma card_mx (F : finType) m n : (#|{: 'M[F]_(m, n)}| = #|F| ^ (m * n))%N.\n\nSection MatrixStructural.\n\nVariable R : Type.\n\n(*This fact provides a unique, opaque term of the unit type, used as a key for managing canonical structures related to constant matrices.*)\nFact const_mx_key : unit. \n(*This definition constructs a matrix of given row and column dimensions where every entry is assigned a specified constant value.*)\nDefinition const_mx m n a : 'M[R]_(m, n) := \\matrix[const_mx_key]_(i, j) a.\nArguments const_mx {m n}.\n\nSection FixedDim.\n\nVariables m n : nat.\nImplicit Type A : 'M[R]_(m, n).\n\n(*This definition changes the type-level dimensions of a matrix, given a proof that the original dimensions are equal to the new dimensions. This operation amounts to a type cast that does not alter the matrix data.*)\nDefinition castmx m' n' (eq_mn : (m = m') * (n = n')) A : 'M_(m', n') :=\n let: erefl in _ = m' := eq_mn.1 return 'M_(m', n') in\n let: erefl in _ = n' := eq_mn.2 return 'M_(m, n') in A.\n\n(*This definition attempts to change a matrix to a new set of dimensions. If the matrix's original dimensions are demonstrably equal to the target dimensions, it returns the original matrix cast to the new dimensions; otherwise, it returns a specified default matrix.*)\nDefinition conform_mx m' n' B A :=\n match m =P m', n =P n' with\n | ReflectT eq_m, ReflectT eq_n => castmx (eq_m, eq_n) A\n | _, _ => B\n end.\n\n(*This fact provides a unique key used internally by the notation for defining a matrix transpose.*)\nFact trmx_key : unit. \n(*This definition computes the transpose of a matrix. The entry at a given row and column in the resulting matrix is taken from the entry at the swapped column and row of the original matrix.*)\nDefinition trmx A := \\matrix[trmx_key]_(i, j) A j i.\n\n(*This fact provides a unique key used internally by the notation for defining a matrix with permuted rows.*)\nFact row_perm_key : unit. \n(*This definition reorders the rows of a matrix according to a given permutation. For each row index in the new matrix, the corresponding row is taken from the original matrix at the index determined by the permutation.*)\nDefinition row_perm (s : 'S_m) A := \\matrix[row_perm_key]_(i, j) A (s i) j.\n(*This fact provides a unique key used internally by the notation for defining a matrix with permuted columns.*)\nFact col_perm_key : unit. \n(*This definition reorders the columns of a matrix according to a given permutation. For each column index in the new matrix, the corresponding column is taken from the original matrix at the index determined by the permutation.*)\nDefinition col_perm (s : 'S_n) A := \\matrix[col_perm_key]_(i, j) A i (s j).\n\n(*This definition produces a new matrix by swapping two specified rows of an input matrix.*)\nDefinition xrow i1 i2 := row_perm (tperm i1 i2).\n(*This definition produces a new matrix by swapping two specified columns of an input matrix.*)\nDefinition xcol j1 j2 := col_perm (tperm j1 j2).\n\n(*This definition extracts a single row, specified by its index, from a matrix and returns it as a row vector.*)\nDefinition row i0 A := \\row_j A i0 j.\n(*This definition extracts a single column, specified by its index, from a matrix and returns it as a column vector.*)\nDefinition col j0 A := \\col_i A i j0.\n\n(*This definition creates a new matrix from an existing one by removing a row at a specified index, resulting in a matrix with one fewer row.*)\nDefinition row' i0 A := \\matrix_(i, j) A (lift i0 i) j.\n(*This definition creates a new matrix from an existing one by removing a column at a specified index, resulting in a matrix with one fewer column.*)\nDefinition col' j0 A := \\matrix_(i, j) A i (lift j0 j).\n\n(*This definition constructs a new matrix by taking a subselection of the entries of an original matrix. The selection is determined by two functions that map the row and column indices of the new matrix to indices of the original matrix.*)\nDefinition mxsub m' n' f g A := \\matrix_(i < m', j < n') A (f i) (g j).\nLocal Notation colsub g := (mxsub id g).\nLocal Notation rowsub f := (mxsub f id).\n\n(*This lemma states that changing the type-level dimensions of a constant matrix, based on a proof of dimensional equality, yields a constant matrix of the same value with the new dimensions.*)\nLemma castmx_const m' n' (eq_mn : (m = m') * (n = n')) a :\n castmx eq_mn (const_mx a) = const_mx a.\n\n(*This lemma states that the transpose of a constant matrix is a constant matrix of the same value, but with its row and column dimensions swapped.*)\nLemma trmx_const a : trmx (const_mx a) = const_mx a.\n\n(*This lemma states that applying any row permutation to a constant matrix yields the same constant matrix.*)\nLemma row_perm_const s a : row_perm s (const_mx a) = const_mx a.\n\n(*This lemma states that applying any column permutation to a constant matrix yields the same constant matrix.*)\nLemma col_perm_const s a : col_perm s (const_mx a) = const_mx a.\n\n(*This lemma states that swapping any two rows of a constant matrix results in the original constant matrix.*)\nLemma xrow_const i1 i2 a : xrow i1 i2 (const_mx a) = const_mx a.\n\n(*This lemma states that swapping any two columns of a constant matrix results in the original constant matrix.*)\nLemma xcol_const j1 j2 a : xcol j1 j2 (const_mx a) = const_mx a.\n\n(*This lemma states that two row vectors are equal if and only if their underlying sequences of elements are equal.*)\nLemma rowP (u v : 'rV[R]_n) : u 0 =1 v 0 <-> u = v.\n\n(*This lemma states that if a matrix is constructed from a family of row vectors indexed by a natural number, then extracting the row at a specific index returns the original row vector corresponding to that index.*)\nLemma rowK u_ i0 : row i0 (\\matrix_i u_ i) = u_ i0.\n\n(*This lemma provides an extensionality principle for matrices, stating that two matrices are equal if and only if for every row index, the corresponding rows of the two matrices are equal.*)\nLemma row_matrixP A B : (forall i, row i A = row i B) <-> A = B.\n\n(*This lemma states that two column vectors are equal if and only if the underlying element sequences of their transposes are equal.*)\nLemma colP (u v : 'cV[R]_m) : u^~ 0 =1 v^~ 0 <-> u = v.\n\n(*This lemma states that extracting any row from a constant matrix yields a constant row vector where every element is equal to the constant value of the matrix.*)\nLemma row_const i0 a : row i0 (const_mx a) = const_mx a.\n\n(*This lemma states that extracting any column from a constant matrix yields a constant column vector where every element is equal to the constant value of the matrix.*)\nLemma col_const j0 a : col j0 (const_mx a) = const_mx a.\n\n(*This lemma states that removing any row from a constant matrix produces another constant matrix of the same value, but with its row count decreased by one.*)\nLemma row'_const i0 a : row' i0 (const_mx a) = const_mx a.\n\n(*This lemma states that removing any column from a constant matrix produces another constant matrix of the same value, but with its column count decreased by one.*)\nLemma col'_const j0 a : col' j0 (const_mx a) = const_mx a.\n\n(*This lemma states that permuting the columns of a matrix using the identity permutation results in the original matrix.*)\nLemma col_perm1 A : col_perm 1 A = A.\n\n(*This lemma states that permuting the rows of a matrix using the identity permutation results in the original matrix.*)\nLemma row_perm1 A : row_perm 1 A = A.\n\n(*This lemma states that permuting the columns of a matrix by the composition of two permutations is equivalent to applying the column permutations successively.*)\nLemma col_permM s t A : col_perm (s * t) A = col_perm s (col_perm t A).\n\n(*This lemma states that permuting the rows of a matrix by the composition of two permutations is equivalent to applying the row permutations successively.*)\nLemma row_permM s t A : row_perm (s * t) A = row_perm s (row_perm t A).\n\n(*This lemma states that applying a column permutation and then a row permutation to a matrix yields the same result as applying the row permutation first and then the column permutation.*)\nLemma col_row_permC s t A :\n col_perm s (row_perm t A) = row_perm t (col_perm s A).\n\n(*This lemma states that the matrix transformation which creates a matrix where every row is a copy of a single specified row is equivalent to a general row substitution using a constant function that maps every new row index to the index of the single specified row.*)\nLemma rowEsub i : row i = rowsub (fun=> i). \n(*This lemma states that the matrix transformation which creates a matrix where every column is a copy of a single specified column is equivalent to a general column substitution using a constant function that maps every new column index to the index of the single specified column.*)\nLemma colEsub j : col j = colsub (fun=> j). \n\n(*This lemma states that the matrix transformation for deleting a specific row is equivalent to a general row substitution using a function that maps each row index of the new matrix to a row index in the original matrix, skipping over the index of the deleted row.*)\nLemma row'Esub i : row' i = rowsub (lift i). \n(*This lemma states that the matrix transformation for deleting a specific column is equivalent to a general column substitution using a function that maps each column index of the new matrix to a column index in the original matrix, skipping over the index of the deleted column.*)\nLemma col'Esub j : col' j = colsub (lift j). \n\n(*This lemma states that the matrix transformation for permuting rows is equivalent to a general row substitution using the corresponding permutation function.*)\nLemma row_permEsub s : row_perm s = rowsub s.\n\n(*This lemma states that the matrix transformation for permuting columns is equivalent to a general column substitution using the corresponding permutation function.*)\nLemma col_permEsub s : col_perm s = colsub s.\n\n(*This lemma states that the matrix transformation for exchanging two rows is equivalent to a general row substitution using a transposition permutation that swaps the indices of those two rows.*)\nLemma xrowEsub i1 i2 : xrow i1 i2 = rowsub (tperm i1 i2).\n\n(*This lemma states that the matrix transformation for exchanging two columns is equivalent to a general column substitution using a transposition permutation that swaps the indices of those two columns.*)\nLemma xcolEsub j1 j2 : xcol j1 j2 = colsub (tperm j1 j2).\n\n(*This lemma states that the matrix substitution transformation is equivalent to the identity transformation when the row and column index mapping functions are both the identity function.*)\nLemma mxsub_id : mxsub id id =1 id.\n\n(*This lemma states that if two row index mapping functions are equivalent, and two column index mapping functions are equivalent, then the corresponding matrix substitution transformations are also equivalent.*)\nLemma eq_mxsub m' n' f f' g g' : f =1 f' -> g =1 g' ->\n @mxsub m' n' f g =1 mxsub f' g'.\n\n(*This lemma states that if two row index mapping functions are equivalent, then the corresponding row substitution transformations are also equivalent.*)\nLemma eq_rowsub m' (f f' : 'I_m' -> 'I_m) : f =1 f' -> rowsub f =1 rowsub f'.\n\n(*This lemma states that if two column index mapping functions are equivalent, then the corresponding column substitution transformations are also equivalent.*)\nLemma eq_colsub n' (g g' : 'I_n' -> 'I_n) : g =1 g' -> colsub g =1 colsub g'.\n\n(*This lemma states that if the row index mapping function and the column index mapping function are both equivalent to the identity function, then the matrix substitution transformation is equivalent to the identity transformation.*)\nLemma mxsub_eq_id f g : f =1 id -> g =1 id -> mxsub f g =1 id.\n\n(*This lemma states that if the row index mapping function for a matrix substitution is equivalent to the identity function, then the matrix substitution transformation is equivalent to a column substitution using the given column index mapping function.*)\nLemma mxsub_eq_colsub n' f g : f =1 id -> @mxsub _ n' f g =1 colsub g.\n\n(*This lemma states that if the column index mapping function for a matrix substitution is equivalent to the identity function, then the matrix substitution transformation is equivalent to a row substitution using the given row index mapping function.*)\nLemma mxsub_eq_rowsub m' f g : g =1 id -> @mxsub m' _ f g =1 rowsub f.\n\n(*This lemma states that a matrix substitution transformation, when provided a row index map as a finite function object, is equivalent to the transformation that uses the underlying function directly.*)\nLemma mxsub_ffunl m' n' f g : @mxsub m' n' (finfun f) g =1 mxsub f g.\n\n(*This lemma states that a matrix substitution transformation, when provided a column index map as a finite function object, is equivalent to the transformation that uses the underlying function directly.*)\nLemma mxsub_ffunr m' n' f g : @mxsub m' n' f (finfun g) =1 mxsub f g.\n\n(*This lemma states that a matrix substitution transformation, when provided both row and column index maps as finite function objects, is equivalent to the transformation that uses the underlying functions directly.*)\nLemma mxsub_ffun m' n' f g : @mxsub m' n' (finfun f) (finfun g) =1 mxsub f g.\n\n(*This lemma states that applying a matrix substitution transformation to a constant matrix results in the same constant matrix.*)\nLemma mxsub_const m' n' f g a : @mxsub m' n' f g (const_mx a) = const_mx a.\n\nEnd FixedDim.\n\nLocal Notation colsub g := (mxsub id g).\nLocal Notation rowsub f := (mxsub f id).\n(*This notation defines the transpose of a matrix, which is the matrix obtained by swapping its rows and columns.*)\nLocal Notation \"A ^T\" := (trmx A) : ring_scope.\n\n(*This lemma states that casting a matrix to a type with the same dimensions, using a proof that the dimensions are identical, returns the original matrix.*)\nLemma castmx_id m n erefl_mn (A : 'M_(m, n)) : castmx erefl_mn A = A.\n\n(*This lemma states that casting a matrix's dimensions twice in succession is equivalent to a single cast using a proof of equality that is the composition of the two individual proofs of equality.*)\nLemma castmx_comp m1 n1 m2 n2 m3 n3 (eq_m1 : m1 = m2) (eq_n1 : n1 = n2)\n (eq_m2 : m2 = m3) (eq_n2 : n2 = n3) A :\n castmx (eq_m2, eq_n2) (castmx (eq_m1, eq_n1) A)\n = castmx (etrans eq_m1 eq_m2, etrans eq_n1 eq_n2) A.\n\n(*This lemma states that the operation of casting a matrix to a type with different dimensions is cancelled by casting it back using the symmetric proof of equality for the dimensions, effectively acting as an identity transformation.*)\nLemma castmxK m1 n1 m2 n2 (eq_m : m1 = m2) (eq_n : n1 = n2) :\n cancel (castmx (eq_m, eq_n)) (castmx (esym eq_m, esym eq_n)).\n\n(*This lemma states that casting a matrix using a symmetric proof of dimension equality is cancelled by casting it back with the original proof of equality, effectively acting as an identity transformation.*)\nLemma castmxKV m1 n1 m2 n2 (eq_m : m1 = m2) (eq_n : n1 = n2) :\n cancel (castmx (esym eq_m, esym eq_n)) (castmx (eq_m, eq_n)).\n\n(*This lemma states that if a first matrix is equal to a second matrix that has been dimension-cast to the size of the first, then the second matrix is equal to the first matrix cast back to the original dimensions of the second, using symmetric dimension equalities.*)\nLemma castmx_sym m1 n1 m2 n2 (eq_m : m1 = m2) (eq_n : n1 = n2) A1 A2 :\n A1 = castmx (eq_m, eq_n) A2 -> A2 = castmx (esym eq_m, esym eq_n) A1.\n\n(*This lemma states that the operation of casting a matrix to different dimensions is pointwise equal, regardless of the specific proofs used to establish the equality of those dimensions.*)\nLemma eq_castmx m1 n1 m2 n2 (eq_mn eq_mn' : (m1 = m2) * (n1 = n2)) :\n castmx eq_mn =1 castmx eq_mn'.\n\n(*This lemma states that the element at a given row and column of a dimension-cast matrix is equal to the element of the original matrix at indices that have been cast back to the original matrix's index types.*)\nLemma castmxE m1 n1 m2 n2 (eq_mn : (m1 = m2) * (n1 = n2)) A i j :\n castmx eq_mn A i j =\n A (cast_ord (esym eq_mn.1) i) (cast_ord (esym eq_mn.2) j).\n\n(*This lemma states that conforming a matrix to another matrix of the same dimensions results in the conformed matrix being returned unchanged.*)\nLemma conform_mx_id m n (B A : 'M_(m, n)) : conform_mx B A = A.\n\n(*This lemma states that attempting to conform a matrix to the dimensions of a target matrix will return the target matrix if the row or column dimensions of the two matrices are not equal.*)\nLemma nonconform_mx m m' n n' (B : 'M_(m', n')) (A : 'M_(m, n)) :\n (m != m') || (n != n') -> conform_mx B A = B.\n\n(*This lemma states that conforming a matrix with a dimension-cast version of a second matrix is equivalent to conforming it with the original, non-cast second matrix.*)\nLemma conform_castmx m1 n1 m2 n2 m3 n3\n (e_mn : (m2 = m3) * (n2 = n3)) (B : 'M_(m1, n1)) A :\n conform_mx B (castmx e_mn A) = conform_mx B A.\n\n(*This lemma states that the matrix transposition operation is its own inverse; applying transposition twice to any matrix returns the original matrix.*)\nLemma trmxK m n : cancel (@trmx m n) (@trmx n m).\n\n(*This lemma states that the matrix transposition operation is injective, meaning that if two matrices have the same transpose, they must be identical.*)\nLemma trmx_inj m n : injective (@trmx m n).\n\n(*This lemma states that the transpose of a dimension-cast matrix is equal to the transpose of the original matrix cast with swapped dimension equalities.*)\nLemma trmx_cast m1 n1 m2 n2 (eq_mn : (m1 = m2) * (n1 = n2)) A :\n (castmx eq_mn A)^T = castmx (eq_mn.2, eq_mn.1) A^T.\n\n(*This lemma states that the transpose of the result of a matrix conformation operation is equivalent to applying the conformation operation to the transposes of the two original matrices in the same order.*)\nLemma trmx_conform m' n' m n (B : 'M_(m', n')) (A : 'M_(m, n)) :\n (conform_mx B A)^T = conform_mx B^T A^T.\n\n(*This lemma states that the transpose of a matrix resulting from a row permutation is identical to the matrix obtained by applying the same permutation to the columns of the transposed original matrix.*)\nLemma tr_row_perm m n s (A : 'M_(m, n)) : (row_perm s A)^T = col_perm s A^T.\n\n(*This lemma states that the transpose of a matrix resulting from a column permutation is identical to the matrix obtained by applying the same permutation to the rows of the transposed original matrix.*)\nLemma tr_col_perm m n s (A : 'M_(m, n)) : (col_perm s A)^T = row_perm s A^T.\n\n(*This lemma states that the transpose of a matrix where two rows have been exchanged is equal to the transposed matrix where the corresponding two columns have been exchanged.*)\nLemma tr_xrow m n i1 i2 (A : 'M_(m, n)) : (xrow i1 i2 A)^T = xcol i1 i2 A^T.\n\n(*This lemma states that the transpose of a matrix where two columns have been exchanged is equal to the transposed matrix where the corresponding two rows have been exchanged.*)\nLemma tr_xcol m n j1 j2 (A : 'M_(m, n)) : (xcol j1 j2 A)^T = xrow j1 j2 A^T.\n\n(*This lemma states that extracting any row from a row vector yields the original row vector itself.*)\nLemma row_id n i (V : 'rV_n) : row i V = V.\n\n(*This lemma states that extracting any column from a column vector yields the original column vector itself.*)\nLemma col_id n j (V : 'cV_n) : col j V = V.\n\n(*This lemma states that if the row vector at a given index in a first matrix is equal to the row vector at another index in a second matrix, then the corresponding rows of the two matrices are pointwise equal.*)\nLemma row_eq m1 m2 n i1 i2 (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n row i1 A1 = row i2 A2 -> A1 i1 =1 A2 i2.\n\n(*This lemma states that if the column vector at a given index in a first matrix is equal to the column vector at another index in a second matrix, then the corresponding columns of the two matrices are pointwise equal.*)\nLemma col_eq m n1 n2 j1 j2 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n col j1 A1 = col j2 A2 -> A1^~ j1 =1 A2^~ j2.\n\n(*This lemma states that if two matrices become equal after removing the same row from each, then the original matrices must have been pointwise equal on all other rows.*)\nLemma row'_eq m n i0 (A B : 'M_(m, n)) :\n row' i0 A = row' i0 B -> {in predC1 i0, A =2 B}.\n\n(*This lemma states that if two matrices become equal after removing the same column from each, then for any given row, the corresponding row entries of the original matrices must have been pointwise equal at all other column positions.*)\nLemma col'_eq m n j0 (A B : 'M_(m, n)) :\n col' j0 A = col' j0 B -> forall i, {in predC1 j0, A i =1 B i}.\n\n(*This lemma states that the transpose of a specific row vector of a matrix is identical to the corresponding column vector of the transposed matrix.*)\nLemma tr_row m n i0 (A : 'M_(m, n)) : (row i0 A)^T = col i0 A^T.\n\n(*This lemma states that the transpose of a submatrix formed by removing a specific row is identical to the submatrix formed by removing the corresponding column from the transposed matrix.*)\nLemma tr_row' m n i0 (A : 'M_(m, n)) : (row' i0 A)^T = col' i0 A^T.\n\n(*This lemma states that the transpose of a specific column vector of a matrix is identical to the corresponding row vector of the transposed matrix.*)\nLemma tr_col m n j0 (A : 'M_(m, n)) : (col j0 A)^T = row j0 A^T.\n\n(*This lemma states that the transpose of a submatrix formed by removing a specific column is identical to the submatrix formed by removing the corresponding row from the transposed matrix.*)\nLemma tr_col' m n j0 (A : 'M_(m, n)) : (col' j0 A)^T = row' j0 A^T.\n\n(*This lemma states that creating a submatrix by applying composed row and column selection functions is equivalent to creating a submatrix from an existing submatrix using the second set of selection functions.*)\nLemma mxsub_comp m1 m2 m3 n1 n2 n3\n (f : 'I_m2 -> 'I_m1) (f' : 'I_m3 -> 'I_m2)\n (g : 'I_n2 -> 'I_n1) (g' : 'I_n3 -> 'I_n2) (A : 'M_(m1, n1)) :\n mxsub (f \\o f') (g \\o g') A = mxsub f' g' (mxsub f g A).\n\n(*This lemma states that creating a submatrix by selecting rows using a composed selection function is equivalent to sequentially applying the selection functions to form a submatrix of a submatrix.*)\nLemma rowsub_comp m1 m2 m3 n\n (f : 'I_m2 -> 'I_m1) (f' : 'I_m3 -> 'I_m2) (A : 'M_(m1, n)) :\n rowsub (f \\o f') A = rowsub f' (rowsub f A).\n\n(*This lemma states that creating a submatrix by selecting columns using a composed selection function is equivalent to sequentially applying the selection functions to form a submatrix of a submatrix.*)\nLemma colsub_comp m n n2 n3\n (g : 'I_n2 -> 'I_n) (g' : 'I_n3 -> 'I_n2) (A : 'M_(m, n)) :\n colsub (g \\o g') A = colsub g' (colsub g A).\n\n(*This lemma states that creating a submatrix by simultaneously selecting rows and columns is equivalent to first creating a submatrix by selecting the columns, and then from that result, creating a new submatrix by selecting the rows.*)\nLemma mxsubrc m1 m2 n n2 f g (A : 'M_(m1, n)) :\n mxsub f g A = rowsub f (colsub g A) :> 'M_(m2, n2).\n\n(*This lemma states that creating a submatrix by simultaneously selecting rows and columns is equivalent to first creating a submatrix by selecting the rows, and then from that result, creating a new submatrix by selecting the columns.*)\nLemma mxsubcr m1 m2 n n2 f g (A : 'M_(m1, n)) :\n mxsub f g A = colsub g (rowsub f A) :> 'M_(m2, n2).\n\n(*This lemma states that creating a submatrix using a row selection function derived from a proof of dimension equality is equivalent to casting the matrix's row dimension using that same proof, while keeping the column dimension unchanged.*)\nLemma rowsub_cast m1 m2 n (eq_m : m1 = m2) (A : 'M_(m2, n)) :\n rowsub (cast_ord eq_m) A = castmx (esym eq_m, erefl) A.\n\n(*This lemma states that creating a submatrix by selecting columns using a function derived from an equality between two natural numbers is equivalent to casting the matrix's dimensions using a reflexive row dimension equality and the symmetric version of the given column dimension equality.*)\nLemma colsub_cast m n1 n2 (eq_n : n1 = n2) (A : 'M_(m, n2)) :\n colsub (cast_ord eq_n) A = castmx (erefl, esym eq_n) A.\n\n(*This lemma states that creating a submatrix by selecting rows and columns using functions derived from equalities between row dimensions and column dimensions, respectively, is equivalent to casting the matrix's dimensions using the symmetric versions of both of those equalities.*)\nLemma mxsub_cast m1 m2 n1 n2 (eq_m : m1 = m2) (eq_n : n1 = n2) A :\n mxsub (cast_ord eq_m) (cast_ord eq_n) A = castmx (esym eq_m, esym eq_n) A.\n\n(*This lemma states that casting the dimensions of a matrix based on a pair of equalities for its row and column counts is equivalent to creating a submatrix using index-mapping functions derived from the symmetric versions of those same equalities.*)\nLemma castmxEsub m1 m2 n1 n2 (eq_mn : (m1 = m2) * (n1 = n2)) A :\n castmx eq_mn A = mxsub (cast_ord (esym eq_mn.1)) (cast_ord (esym eq_mn.2)) A.\n\n(*This lemma states that the transpose of a submatrix formed by applying row and column selection functions is equal to the submatrix of the transposed original matrix, formed by swapping the original row and column selection functions.*)\nLemma trmx_mxsub m1 m2 n1 n2 f g (A : 'M_(m1, n1)) :\n (mxsub f g A)^T = mxsub g f A^T :> 'M_(n2, m2).\n\n(*This lemma states that a given row of a submatrix, which is formed by applying both row and column selection functions, is equal to the row, selected by the row-selection function, of an intermediate matrix formed by applying only the column-selection function to the original matrix.*)\nLemma row_mxsub m1 m2 n1 n2\n (f : 'I_m2 -> 'I_m1) (g : 'I_n2 -> 'I_n1) (A : 'M_(m1, n1)) i :\n row i (mxsub f g A) = row (f i) (colsub g A).\n\n(*This lemma states that a given column of a submatrix, which is formed by applying both row and column selection functions, is equal to the column, selected by the column-selection function, of an intermediate matrix formed by applying only the row-selection function to the original matrix.*)\nLemma col_mxsub m1 m2 n1 n2\n (f : 'I_m2 -> 'I_m1) (g : 'I_n2 -> 'I_n1) (A : 'M_(m1, n1)) i :\n col i (mxsub f g A) = col (g i) (rowsub f A).\n\n(*This lemma states that a given row of a submatrix formed by applying a row-selection function to a matrix is equivalent to the row from the original matrix at the index specified by applying the selection function to the given row index.*)\nLemma row_rowsub m1 m2 n (f : 'I_m2 -> 'I_m1) (A : 'M_(m1, n)) i :\n row i (rowsub f A) = row (f i) A.\n\n(*This lemma states that a given column of a submatrix formed by applying a column-selection function to a matrix is equivalent to the column from the original matrix at the index specified by applying the selection function to the given column index.*)\nLemma col_colsub m n1 n2 (g : 'I_n2 -> 'I_n1) (A : 'M_(m, n1)) i :\n col i (colsub g A) = col (g i) A.\n\n(*A proof tactic designed to prove that two matrices are equal by reducing the goal to showing element-wise equality. It automatically applies the principle that two matrices are equal if and only if all their corresponding entries are equal, setting up subgoals for each entry.*)\nLtac split_mxE := apply/matrixP=> i j; do ![rewrite mxE | case: split => ?].\n\nSection CutPaste.\n\nVariables m m1 m2 n n1 n2 : nat.\n\n(*This fact serves as a unique, opaque identifier to seal the definition of the horizontal concatenation of two matrices, preventing its automatic expansion during proofs.*)\nFact row_mx_key : unit. \n(*This definition constructs a new matrix by horizontally concatenating two given matrices. The first matrix's columns form the left part of the new matrix, and the second matrix's columns form the right part. Both input matrices must have the same number of rows.*)\nDefinition row_mx (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) : 'M[R]_(m, n1 + n2) :=\n \\matrix[row_mx_key]_(i, j)\n match split j with inl j1 => A1 i j1 | inr j2 => A2 i j2 end.\n\n(*This fact serves as a unique, opaque identifier to seal the definition of the vertical concatenation of two matrices, preventing its automatic expansion during proofs.*)\nFact col_mx_key : unit. \n(*This definition constructs a new matrix by vertically concatenating two given matrices. The first matrix's rows form the upper part of the new matrix, and the second matrix's rows form the lower part. Both input matrices must have the same number of columns.*)\nDefinition col_mx (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) : 'M[R]_(m1 + m2, n) :=\n \\matrix[col_mx_key]_(i, j)\n match split i with inl i1 => A1 i1 j | inr i2 => A2 i2 j end.\n\n(*This fact serves as a unique, opaque identifier to seal the definition of extracting the left submatrix from a block matrix, preventing its automatic expansion during proofs.*)\nFact lsubmx_key : unit. \n(*This definition extracts the left-hand submatrix from a given matrix that is partitioned horizontally into two blocks. The resulting matrix consists of the columns from the first block.*)\nDefinition lsubmx (A : 'M[R]_(m, n1 + n2)) :=\n \\matrix[lsubmx_key]_(i, j) A i (lshift n2 j).\n\n(*This fact serves as a unique, opaque identifier to seal the definition of extracting the right submatrix from a block matrix, preventing its automatic expansion during proofs.*)\nFact rsubmx_key : unit. \n(*This definition extracts the right-hand submatrix from a given matrix that is partitioned horizontally into two blocks. The resulting matrix consists of the columns from the second block.*)\nDefinition rsubmx (A : 'M[R]_(m, n1 + n2)) :=\n \\matrix[rsubmx_key]_(i, j) A i (rshift n1 j).\n\n(*This fact serves as a unique, opaque identifier to seal the definition of extracting the upper submatrix from a block matrix, preventing its automatic expansion during proofs.*)\nFact usubmx_key : unit. \n(*This definition extracts the upper submatrix from a given matrix that is partitioned vertically into two blocks. The resulting matrix consists of the rows from the first block.*)\nDefinition usubmx (A : 'M[R]_(m1 + m2, n)) :=\n \\matrix[usubmx_key]_(i, j) A (lshift m2 i) j.\n\n(*This fact serves as a unique, opaque identifier to seal the definition of extracting the lower submatrix from a block matrix, preventing its automatic expansion during proofs.*)\nFact dsubmx_key : unit. \n(*This definition extracts the lower submatrix from a given matrix that is partitioned vertically into two blocks. The resulting matrix consists of the rows from the second block.*)\nDefinition dsubmx (A : 'M[R]_(m1 + m2, n)) :=\n \\matrix[dsubmx_key]_(i, j) A (rshift m1 i) j.\n\n(*This lemma states that an element within the left-hand block of a horizontally concatenated matrix corresponds to the element at the same row and column indices in the original left-hand matrix.*)\nLemma row_mxEl A1 A2 i j : row_mx A1 A2 i (lshift n2 j) = A1 i j.\n\n(*This lemma states that extracting the left-hand submatrix from a matrix formed by horizontal concatenation of two matrices yields the original left-hand matrix.*)\nLemma row_mxKl A1 A2 : lsubmx (row_mx A1 A2) = A1.\n\n(*This lemma states that an element within the right-hand block of a horizontally concatenated matrix corresponds to the element at the same row and column indices in the original right-hand matrix.*)\nLemma row_mxEr A1 A2 i j : row_mx A1 A2 i (rshift n1 j) = A2 i j.\n\n(*This lemma states that extracting the right-hand submatrix from a matrix formed by horizontal concatenation of two matrices yields the original right-hand matrix.*)\nLemma row_mxKr A1 A2 : rsubmx (row_mx A1 A2) = A2.\n\n(*This lemma states that horizontally concatenating the left and right submatrices extracted from a given matrix reconstructs the original matrix.*)\nLemma hsubmxK A : row_mx (lsubmx A) (rsubmx A) = A.\n\n(*This lemma states that an element within the upper block of a vertically concatenated matrix corresponds to the element at the same row and column indices in the original upper matrix.*)\nLemma col_mxEu A1 A2 i j : col_mx A1 A2 (lshift m2 i) j = A1 i j.\n\n(*This lemma states that extracting the upper submatrix from a matrix formed by vertical concatenation of two matrices yields the original upper matrix.*)\nLemma col_mxKu A1 A2 : usubmx (col_mx A1 A2) = A1.\n\n(*This lemma states that an element within the lower block of a vertically concatenated matrix corresponds to the element at the same row and column indices in the original lower matrix.*)\nLemma col_mxEd A1 A2 i j : col_mx A1 A2 (rshift m1 i) j = A2 i j.\n\n(*This lemma states that extracting the lower submatrix from a matrix formed by vertical concatenation of two matrices yields the original lower matrix.*)\nLemma col_mxKd A1 A2 : dsubmx (col_mx A1 A2) = A2.\n\n(*This lemma states that the operation for creating a left submatrix is equivalent to the operation that creates a submatrix from a selection of columns, where the columns are selected using a left shift of indices.*)\nLemma lsubmxEsub : lsubmx = colsub (lshift _).\n\n(*This lemma states that the operation for creating a right submatrix is equivalent to the operation that creates a submatrix from a selection of columns, where the columns are selected using a right shift of indices.*)\nLemma rsubmxEsub : rsubmx = colsub (@rshift _ _).\n\n(*This lemma states that the operation for creating an upper submatrix is equivalent to the operation that creates a submatrix from a selection of rows, where the rows are selected using a left shift of indices.*)\nLemma usubmxEsub : usubmx = rowsub (lshift _).\n\n(*This lemma states that the operation for creating a lower submatrix is equivalent to the operation that creates a submatrix from a selection of rows, where the rows are selected using a right shift of indices.*)\nLemma dsubmxEsub : dsubmx = rowsub (@rshift _ _).\n\n(*This lemma asserts the injectivity of horizontal matrix concatenation, stating that if the horizontal concatenation of a first pair of matrices equals the horizontal concatenation of a second pair, then the corresponding matrices within each pair must be equal.*)\nLemma eq_row_mx A1 A2 B1 B2 : row_mx A1 A2 = row_mx B1 B2 -> A1 = B1 /\\ A2 = B2.\n\n(*This lemma asserts the injectivity of vertical matrix concatenation, stating that if the vertical concatenation of a first pair of matrices equals the vertical concatenation of a second pair, then the corresponding matrices within each pair must be equal.*)\nLemma eq_col_mx A1 A2 B1 B2 : col_mx A1 A2 = col_mx B1 B2 -> A1 = B1 /\\ A2 = B2.\n\n(*This lemma states that horizontally concatenating two constant matrices, each containing the same single value, results in a larger constant matrix filled with that same value.*)\nLemma row_mx_const a : row_mx (const_mx a) (const_mx a) = const_mx a.\n\n(*This lemma states that vertically concatenating two constant matrices, each containing the same single value, results in a larger constant matrix filled with that same value.*)\nLemma col_mx_const a : col_mx (const_mx a) (const_mx a) = const_mx a.\n\n(*This lemma states that extracting a specific row from the upper submatrix of a given matrix is equivalent to extracting a row from the original matrix at an index corresponding to a left shift.*)\nLemma row_usubmx A i : row i (usubmx A) = row (lshift m2 i) A.\n\n(*This lemma states that extracting a specific row from the lower submatrix of a given matrix is equivalent to extracting a row from the original matrix at an index corresponding to a right shift.*)\nLemma row_dsubmx A i : row i (dsubmx A) = row (rshift m1 i) A.\n\n(*This lemma states that extracting a specific column from the left submatrix of a given matrix is equivalent to extracting a column from the original matrix at an index corresponding to a left shift.*)\nLemma col_lsubmx A i : col i (lsubmx A) = col (lshift n2 i) A.\n\n(*This lemma states that extracting a specific column from the right submatrix of a given matrix is equivalent to extracting a column from the original matrix at an index corresponding to a right shift.*)\nLemma col_rsubmx A i : col i (rsubmx A) = col (rshift n1 i) A.\n\nEnd CutPaste.\n\n(*This lemma states that horizontally concatenating a matrix that has zero columns with a second matrix yields the second matrix unchanged.*)\nLemma row_thin_mx m n (A : 'M_(m,0)) (B : 'M_(m,n)) : row_mx A B = B.\n\n(*This lemma states that vertically concatenating a matrix that has zero rows with a second matrix yields the second matrix unchanged.*)\nLemma col_flat_mx m n (A : 'M_(0,n)) (B : 'M_(m,n)) : col_mx A B = B.\n\n(*This lemma states that the transpose of the left submatrix of a given matrix is equal to the upper submatrix of the transpose of the original matrix.*)\nLemma trmx_lsub m n1 n2 (A : 'M_(m, n1 + n2)) : (lsubmx A)^T = usubmx A^T.\n\n(*This lemma states that the transpose of the right submatrix of a given matrix is equal to the lower submatrix of the transpose of the original matrix.*)\nLemma trmx_rsub m n1 n2 (A : 'M_(m, n1 + n2)) : (rsubmx A)^T = dsubmx A^T.\n\n(*This lemma states that the transpose of a matrix formed by horizontal concatenation of two matrices is equivalent to the vertical concatenation of the transposes of those two matrices.*)\nLemma tr_row_mx m n1 n2 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n (row_mx A1 A2)^T = col_mx A1^T A2^T.\n\n(*This lemma states that the transpose of a matrix formed by vertical concatenation of two matrices is equivalent to the horizontal concatenation of the transposes of those two matrices.*)\nLemma tr_col_mx m1 m2 n (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n (col_mx A1 A2)^T = row_mx A1^T A2^T.\n\n(*This lemma states that the transpose of the upper submatrix of a given matrix is equal to the left submatrix of the transpose of the original matrix.*)\nLemma trmx_usub m1 m2 n (A : 'M_(m1 + m2, n)) : (usubmx A)^T = lsubmx A^T.\n\n(*This lemma states that the transpose of the lower submatrix of a given matrix is equal to the right submatrix of the transpose of the original matrix.*)\nLemma trmx_dsub m1 m2 n (A : 'M_(m1 + m2, n)) : (dsubmx A)^T = rsubmx A^T.\n\n(*This lemma provides a cancellation property, stating that vertically concatenating the upper and lower submatrices of a given matrix reconstructs the original matrix.*)\nLemma vsubmxK m1 m2 n (A : 'M_(m1 + m2, n)) : col_mx (usubmx A) (dsubmx A) = A.\n\n(*This lemma states that changing the declared dimensions of a matrix formed by horizontal concatenation is equivalent to first changing the dimensions of the individual matrices and then performing the concatenation.*)\nLemma cast_row_mx m m' n1 n2 (eq_m : m = m') A1 A2 :\n castmx (eq_m, erefl _) (row_mx A1 A2)\n = row_mx (castmx (eq_m, erefl n1) A1) (castmx (eq_m, erefl n2) A2).\n\n(*This lemma states that changing the declared dimensions of a matrix formed by vertical concatenation is equivalent to first changing the dimensions of the individual matrices and then performing the concatenation.*)\nLemma cast_col_mx m1 m2 n n' (eq_n : n = n') A1 A2 :\n castmx (erefl _, eq_n) (col_mx A1 A2)\n = col_mx (castmx (erefl m1, eq_n) A1) (castmx (erefl m2, eq_n) A2).\n\n(*This lemma expresses the associativity of horizontal matrix concatenation, stating that concatenating a first matrix with the result of concatenating a second and third matrix is, up to a change in declared dimensions, equal to concatenating the result of the first two matrices with the third.*)\nLemma row_mxA m n1 n2 n3 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) (A3 : 'M_(m, n3)) :\n let cast := (erefl m, esym (addnA n1 n2 n3)) in\n row_mx A1 (row_mx A2 A3) = castmx cast (row_mx (row_mx A1 A2) A3).\n\n(*This definition provides an alias for the lemma asserting the associativity of horizontal matrix concatenation.*)\nDefinition row_mxAx := row_mxA. \n\n(*This lemma expresses the associativity of vertical matrix concatenation, stating that concatenating a first matrix with the result of concatenating a second and third matrix is, up to a change in declared dimensions, equal to concatenating the result of the first two matrices with the third.*)\nLemma col_mxA m1 m2 m3 n (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) (A3 : 'M_(m3, n)) :\n let cast := (esym (addnA m1 m2 m3), erefl n) in\n col_mx A1 (col_mx A2 A3) = castmx cast (col_mx (col_mx A1 A2) A3).\n\n(*This definition provides an alias for the lemma asserting the associativity of vertical matrix concatenation.*)\nDefinition col_mxAx := col_mxA. \n\n(*This lemma states that extracting a specific row from a horizontally concatenated matrix is equivalent to horizontally concatenating the corresponding rows extracted from each of the original matrices.*)\nLemma row_row_mx m n1 n2 i0 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n row i0 (row_mx A1 A2) = row_mx (row i0 A1) (row i0 A2).\n\n(*This lemma states that extracting a specific column from a vertically concatenated matrix is equivalent to vertically concatenating the corresponding columns extracted from each of the original matrices.*)\nLemma col_col_mx m1 m2 n j0 (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n col j0 (col_mx A1 A2) = col_mx (col j0 A1) (col j0 A2).\n\n(*This lemma states that extracting a row as a single-row matrix from a horizontally concatenated matrix is equivalent to first extracting the corresponding rows from each of the constituent matrices as single-row matrices and then horizontally concatenating the results.*)\nLemma row'_row_mx m n1 n2 i0 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n row' i0 (row_mx A1 A2) = row_mx (row' i0 A1) (row' i0 A2).\n\n(*This lemma states that removing a specific column from a matrix created by vertically concatenating two matrices is equivalent to vertically concatenating the two matrices after each has had that same column removed.*)\nLemma col'_col_mx m1 m2 n j0 (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n col' j0 (col_mx A1 A2) = col_mx (col' j0 A1) (col' j0 A2).\n\n(*This lemma states that extracting a column from the left-hand side of a matrix formed by horizontal concatenation is equivalent to extracting the corresponding column from the original left-side matrix.*)\nLemma colKl m n1 n2 j1 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n col (lshift n2 j1) (row_mx A1 A2) = col j1 A1.\n\n(*This lemma states that extracting a column from the right-hand side of a matrix formed by horizontal concatenation is equivalent to extracting the corresponding column from the original right-side matrix.*)\nLemma colKr m n1 n2 j2 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n col (rshift n1 j2) (row_mx A1 A2) = col j2 A2.\n\n(*This lemma states that extracting a row from the upper part of a matrix formed by vertical concatenation is equivalent to extracting the corresponding row from the original upper matrix.*)\nLemma rowKu m1 m2 n i1 (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n row (lshift m2 i1) (col_mx A1 A2) = row i1 A1.\n\n(*This lemma states that extracting a row from the lower part of a matrix formed by vertical concatenation is equivalent to extracting the corresponding row from the original lower matrix.*)\nLemma rowKd m1 m2 n i2 (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n row (rshift m1 i2) (col_mx A1 A2) = row i2 A2.\n\n(*This lemma states that removing a column from the left-hand side of a horizontally concatenated matrix is equivalent to horizontally concatenating the left matrix with that column removed and the original right matrix.*)\nLemma col'Kl m n1 n2 j1 (A1 : 'M_(m, n1.+1)) (A2 : 'M_(m, n2)) :\n col' (lshift n2 j1) (row_mx A1 A2) = row_mx (col' j1 A1) A2.\n\n(*This lemma states that removing a row from the upper part of a vertically concatenated matrix is equivalent to vertically concatenating the upper matrix with that row removed and the original lower matrix.*)\nLemma row'Ku m1 m2 n i1 (A1 : 'M_(m1.+1, n)) (A2 : 'M_(m2, n)) :\n row' (lshift m2 i1) (@col_mx m1.+1 m2 n A1 A2) = col_mx (row' i1 A1) A2.\n\n(*This technical lemma establishes a type equality for natural number arithmetic involving subtraction, which is used to justify the correctness of matrix dimension casting after removing a column or row.*)\nLemma mx'_cast m n : 'I_n -> (m + n.-1)%N = (m + n).-1.\n\n(*This lemma states that removing a column from the right-hand side of a horizontally concatenated matrix yields a matrix that is equivalent, after a dimension cast, to the horizontal concatenation of the original left matrix and the right matrix with the corresponding column removed.*)\nLemma col'Kr m n1 n2 j2 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n col' (rshift n1 j2) (@row_mx m n1 n2 A1 A2)\n = castmx (erefl m, mx'_cast n1 j2) (row_mx A1 (col' j2 A2)).\n\n(*This lemma states that removing a row from the lower part of a vertically concatenated matrix yields a matrix that is equivalent, after a dimension cast, to the vertical concatenation of the original upper matrix and the lower matrix with the corresponding row removed.*)\nLemma row'Kd m1 m2 n i2 (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n row' (rshift m1 i2) (col_mx A1 A2)\n = castmx (mx'_cast m1 i2, erefl n) (col_mx A1 (row' i2 A2)).\n\nSection Block.\n\nVariables m1 m2 n1 n2 : nat.\n\n(*This definition constructs a block matrix from four smaller matrices, arranging them into a two-by-two grid. The upper-left and upper-right matrices form the top row of blocks, while the lower-left and lower-right matrices form the bottom row of blocks.*)\nDefinition block_mx Aul Aur Adl Adr : 'M_(m1 + m2, n1 + n2) :=\n col_mx (row_mx Aul Aur) (row_mx Adl Adr).\n\n(*This lemma establishes the injectivity of the block matrix constructor, stating that if two block matrices are equal, then their corresponding upper-left, upper-right, lower-left, and lower-right sub-matrices must also be equal.*)\nLemma eq_block_mx Aul Aur Adl Adr Bul Bur Bdl Bdr :\n block_mx Aul Aur Adl Adr = block_mx Bul Bur Bdl Bdr ->\n [/\\ Aul = Bul, Aur = Bur, Adl = Bdl & Adr = Bdr].\n\n(*This lemma states that constructing a block matrix from four constant matrices, all filled with the same value, results in a larger constant matrix also filled with that same value.*)\nLemma block_mx_const a :\n block_mx (const_mx a) (const_mx a) (const_mx a) (const_mx a) = const_mx a.\n\nSection CutBlock.\n\nVariable A : matrix R (m1 + m2) (n1 + n2).\n\n(*This definition extracts the upper-left submatrix from a larger matrix by first selecting the top half of the rows and then selecting the left half of the columns from the result.*)\nDefinition ulsubmx := lsubmx (usubmx A).\n(*This definition extracts the upper-right submatrix from a larger matrix by first selecting the top half of the rows and then selecting the right half of the columns from the result.*)\nDefinition ursubmx := rsubmx (usubmx A).\n(*This definition extracts the lower-left submatrix from a larger matrix by first selecting the bottom half of the rows and then selecting the left half of the columns from the result.*)\nDefinition dlsubmx := lsubmx (dsubmx A).\n(*This definition extracts the lower-right submatrix from a larger matrix by first selecting the bottom half of the rows and then selecting the right half of the columns from the result.*)\nDefinition drsubmx := rsubmx (dsubmx A).\n\n(*This lemma states that reconstructing a matrix using the block matrix constructor from its four canonical submatrices (upper-left, upper-right, lower-left, and lower-right) yields the original matrix.*)\nLemma submxK : block_mx ulsubmx ursubmx dlsubmx drsubmx = A.\n\n(*This lemma shows that extracting the upper-left submatrix is equivalent to taking a submatrix of the original matrix starting from the top-left corner, defined by row and column index transformations.*)\nLemma ulsubmxEsub : ulsubmx = mxsub (lshift _) (lshift _) A.\n\n(*This lemma shows that extracting the lower-left submatrix is equivalent to taking a submatrix of the original matrix starting from the shifted row index corresponding to the lower block and the unshifted column index of the left block.*)\nLemma dlsubmxEsub : dlsubmx = mxsub (@rshift _ _) (lshift _) A.\n\n(*This lemma shows that extracting the upper-right submatrix is equivalent to taking a submatrix of the original matrix starting from the unshifted row index of the upper block and the shifted column index of the right block.*)\nLemma ursubmxEsub : ursubmx = mxsub (lshift _) (@rshift _ _) A.\n\n(*This lemma shows that extracting the lower-right submatrix is equivalent to taking a submatrix of the original matrix starting from the shifted row and column indices corresponding to the lower-right corner.*)\nLemma drsubmxEsub : drsubmx = mxsub (@rshift _ _) (@rshift _ _) A.\n\nEnd CutBlock.\n\nSection CatBlock.\n\nVariables (Aul : 'M[R]_(m1, n1)) (Aur : 'M[R]_(m1, n2)).\nVariables (Adl : 'M[R]_(m2, n1)) (Adr : 'M[R]_(m2, n2)).\n\n(*This local definition introduces a matrix that is constructed as a block matrix from four given submatrices: an upper-left, an upper-right, a lower-left, and a lower-right block.*)\nLet A := block_mx Aul Aur Adl Adr.\n\n(*This lemma states that an element at a given row and column within the upper-left quadrant of a block matrix is equal to the element at the same row and column in the original upper-left submatrix.*)\nLemma block_mxEul i j : A (lshift m2 i) (lshift n2 j) = Aul i j.\n\n(*This lemma states that extracting the upper-left submatrix from a matrix that was constructed as a block matrix yields the original upper-left submatrix used in its construction.*)\nLemma block_mxKul : ulsubmx A = Aul.\n\n(*This lemma states that an element at a given row and column within the upper-right quadrant of a block matrix is equal to the element at the same row and column in the original upper-right submatrix.*)\nLemma block_mxEur i j : A (lshift m2 i) (rshift n1 j) = Aur i j.\n\n(*This lemma states that extracting the upper-right submatrix from a matrix that was constructed as a block matrix yields the original upper-right submatrix used in its construction.*)\nLemma block_mxKur : ursubmx A = Aur.\n\n(*This lemma states that an element at a given row and column within the lower-left quadrant of a block matrix is equal to the element at the same row and column in the original lower-left submatrix.*)\nLemma block_mxEdl i j : A (rshift m1 i) (lshift n2 j) = Adl i j.\n\n(*This lemma states that extracting the lower-left submatrix from a matrix that was constructed as a block matrix yields the original lower-left submatrix used in its construction.*)\nLemma block_mxKdl : dlsubmx A = Adl.\n\n(*This lemma states that an element at a given row and column within the lower-right quadrant of a block matrix is equal to the element at the same row and column in the original lower-right submatrix.*)\nLemma block_mxEdr i j : A (rshift m1 i) (rshift n1 j) = Adr i j.\n\n(*This lemma states that extracting the down-right submatrix from a matrix composed of four blocks yields the original down-right block.*)\nLemma block_mxKdr : drsubmx A = Adr.\n\n(*This lemma states that a matrix constructed from four a-priori given blocks is equivalent to a matrix formed by vertically stacking two row matrices, where the top row matrix is composed of the upper-left and upper-right blocks and the bottom row matrix is composed of the down-left and down-right blocks.*)\nLemma block_mxEv : A = col_mx (row_mx Aul Aur) (row_mx Adl Adr).\n\nEnd CatBlock.\n\nEnd Block.\n\nSection TrCutBlock.\n\nVariables m1 m2 n1 n2 : nat.\nVariable A : 'M[R]_(m1 + m2, n1 + n2).\n\n(*This lemma states that the transpose of the upper-left submatrix of a given matrix is equal to the upper-left submatrix of the transpose of that matrix.*)\nLemma trmx_ulsub : (ulsubmx A)^T = ulsubmx A^T.\n\n(*This lemma states that the transpose of the upper-right submatrix of a given matrix is equal to the down-left submatrix of the transpose of that matrix.*)\nLemma trmx_ursub : (ursubmx A)^T = dlsubmx A^T.\n\n(*This lemma states that the transpose of the down-left submatrix of a given matrix is equal to the upper-right submatrix of the transpose of that matrix.*)\nLemma trmx_dlsub : (dlsubmx A)^T = ursubmx A^T.\n\n(*This lemma states that the transpose of the down-right submatrix of a given matrix is equal to the down-right submatrix of the transpose of that matrix.*)\nLemma trmx_drsub : (drsubmx A)^T = drsubmx A^T.\n\nEnd TrCutBlock.\n\nSection TrBlock.\nVariables m1 m2 n1 n2 : nat.\nVariables (Aul : 'M[R]_(m1, n1)) (Aur : 'M[R]_(m1, n2)).\nVariables (Adl : 'M[R]_(m2, n1)) (Adr : 'M[R]_(m2, n2)).\n\n(*This lemma states that the transpose of a matrix constructed from four blocks is a block matrix whose blocks are the transposes of the original blocks, with the upper-right and down-left blocks swapped.*)\nLemma tr_block_mx :\n (block_mx Aul Aur Adl Adr)^T = block_mx Aul^T Adl^T Aur^T Adr^T.\n\n(*This lemma states that a matrix constructed from four a-priori given blocks is equivalent to a matrix formed by horizontally joining two column matrices, where the left column is composed of the upper-left and down-left blocks and the right column is composed of the upper-right and down-right blocks.*)\nLemma block_mxEh :\n block_mx Aul Aur Adl Adr = row_mx (col_mx Aul Adl) (col_mx Aur Adr).\n\nEnd TrBlock.\n\n(*This lemma establishes an associativity rule for constructing block matrices, showing that a three-by-three block matrix can be equivalently viewed as a two-by-two block matrix by grouping the sub-blocks in two different ways, either by separating the first row and column, or by separating the last row and column.*)\nLemma block_mxA m1 m2 m3 n1 n2 n3\n (A11 : 'M_(m1, n1)) (A12 : 'M_(m1, n2)) (A13 : 'M_(m1, n3))\n (A21 : 'M_(m2, n1)) (A22 : 'M_(m2, n2)) (A23 : 'M_(m2, n3))\n (A31 : 'M_(m3, n1)) (A32 : 'M_(m3, n2)) (A33 : 'M_(m3, n3)) :\n let cast := (esym (addnA m1 m2 m3), esym (addnA n1 n2 n3)) in\n let row1 := row_mx A12 A13 in let col1 := col_mx A21 A31 in\n let row3 := row_mx A31 A32 in let col3 := col_mx A13 A23 in\n block_mx A11 row1 col1 (block_mx A22 A23 A32 A33)\n = castmx cast (block_mx (block_mx A11 A12 A21 A22) col3 row3 A33).\n\n(*This definition provides an alias for the block matrix associativity lemma.*)\nDefinition block_mxAx := block_mxA. \n\nSection Induction.\n\n(*This lemma provides an induction principle for matrices based on the number of columns, asserting that a property holds for all matrices with a fixed number of rows if it holds for matrices with zero columns and is preserved when a column is prepended to a matrix for which the property already holds.*)\nLemma row_ind m (P : forall n, 'M[R]_(m, n) -> Type) :\n (forall A, P 0 A) ->\n (forall n c A, P n A -> P (1 + n)%N (row_mx c A)) ->\n forall n A, P n A.\n\n(*This lemma provides an induction principle for matrices based on the number of rows, asserting that a property holds for all matrices with a fixed number of columns if it holds for matrices with zero rows and is preserved when a row is added on top of a matrix for which the property already holds.*)\nLemma col_ind n (P : forall m, 'M[R]_(m, n) -> Type) :\n (forall A, P 0 A) ->\n (forall m r A, P m A -> P (1 + m)%N (col_mx r A)) ->\n forall m A, P m A.\n\n(*This lemma provides a structural induction principle for matrices of arbitrary dimensions, asserting that a property holds for all matrices if it holds for matrices with zero rows, for matrices with zero columns, and is preserved when a matrix is extended by one row and one column using a block construction.*)\nLemma mx_ind (P : forall m n, 'M[R]_(m, n) -> Type) :\n (forall m A, P m 0 A) ->\n (forall n A, P 0 n A) ->\n (forall m n x r c A, P m n A -> P (1 + m)%N (1 + n)%N (block_mx x r c A)) ->\n forall m n A, P m n A.\n\n(*This definition provides an alias for the matrix induction principle, typically used for defining functions by recursion over the matrix structure.*)\nDefinition matrix_rect := mx_ind.\n(*This definition provides an alias for the matrix induction principle, intended for recursive definitions on matrices.*)\nDefinition matrix_rec := mx_ind.\n(*This definition provides an alias for the matrix induction principle, highlighting its use for proofs by induction on matrix dimensions.*)\nDefinition matrix_ind := mx_ind.\n\n(*This lemma provides a structural induction principle for square matrices, asserting that a property holds for all square matrices if it holds for the zero-by-zero matrix and is preserved when an n-by-n matrix is extended to an (n+1)-by-(n+1) matrix via a block construction.*)\nLemma sqmx_ind (P : forall n, 'M[R]_n -> Type) :\n (forall A, P 0 A) ->\n (forall n x r c A, P n A -> P (1 + n)%N (block_mx x r c A)) ->\n forall n A, P n A.\n\n(*This lemma provides a structural induction principle for non-empty square matrices, asserting that a property holds for all square matrices of size at least one if it holds for all one-by-one matrices and is preserved when a square matrix of positive size is extended by one row and one column via a block construction.*)\nLemma ringmx_ind (P : forall n, 'M[R]_n.+1 -> Type) :\n (forall x, P 0 x) ->\n (forall n x (r : 'rV_n.+1) (c : 'cV_n.+1) A,\n P n A -> P (1 + n)%N (block_mx x r c A)) ->\n forall n A, P n A.\n\n(*This lemma provides a well-founded induction principle for matrices, stating that a property holds for all matrices if, for any given matrix, the property can be proven under the assumption that it holds for all submatrices that have a strictly smaller weight according to a given weight function.*)\nLemma mxsub_ind\n (weight : forall m n, 'M[R]_(m, n) -> nat)\n (sub : forall m n m' n', ('I_m' -> 'I_m) -> ('I_n' -> 'I_n) -> Prop)\n (P : forall m n, 'M[R]_(m, n) -> Type) :\n (forall m n (A : 'M[R]_(m, n)),\n (forall m' n' f g, weight m' n' (mxsub f g A) < weight m n A ->\n sub m n m' n' f g ->\n P m' n' (mxsub f g A)) -> P m n A) ->\n forall m n A, P m n A.\n\nEnd Induction.\n\nSection VecMatrix.\n\nVariables m n : nat.\n\n(*This lemma states that the number of pairs of indices corresponding to the entries of an m-by-n matrix is equal to the product of m and n.*)\nLemma mxvec_cast : #|{:'I_m * 'I_n}| = (m * n)%N.\n\n(*This definition provides a function that converts a two-dimensional matrix index, given as a pair of row and column ordinals, into a one-dimensional vector index by computing its rank in the lexicographical enumeration of all index pairs.*)\nDefinition mxvec_index (i : 'I_m) (j : 'I_n) :=\n cast_ord mxvec_cast (enum_rank (i, j)).\n\n(**)\nVariant is_mxvec_index : 'I_(m * n) -> Type :=\n isMxvecIndex i j : is_mxvec_index (mxvec_index i j).\n\n(*This lemma asserts that any one-dimensional index into a flattened matrix corresponds to a valid two-dimensional row and column index pair, effectively stating the surjectivity of the index mapping.*)\nLemma mxvec_indexP k : is_mxvec_index k.\n\nCoercion pair_of_mxvec_index k (i_k : is_mxvec_index k) :=\n let: isMxvecIndex i j := i_k in (i, j).\n\n(*This definition provides a function that flattens a given m-by-n matrix into a row vector of length m times n, where the elements are arranged according to the lexicographical order of their matrix indices.*)\nDefinition mxvec (A : 'M[R]_(m, n)) :=\n castmx (erefl _, mxvec_cast) (\\row_k A (enum_val k).1 (enum_val k).2).\n\n(*This fact provides a unique key for the matrix construction notation, used internally to define the un-vectorization operation from a vector to a matrix.*)\nFact vec_mx_key : unit. \n(*This definition provides a function that reshapes a row vector of length m times n into an m-by-n matrix, where each matrix entry at a given row and column is taken from the vector element at the corresponding flattened index.*)\nDefinition vec_mx (u : 'rV[R]_(m * n)) :=\n \\matrix[vec_mx_key]_(i, j) u 0 (mxvec_index i j).\n\n(*This lemma states that the element in the row vector resulting from flattening a matrix, at the position corresponding to a given row and column index pair, is equal to the element at that row and column in the original matrix.*)\nLemma mxvecE A i j : mxvec A 0 (mxvec_index i j) = A i j.\n\n(*This lemma states that flattening a matrix that was previously constructed from a vector yields the original vector, establishing that vectorization is the left inverse of matrix construction from a vector.*)\nLemma mxvecK : cancel mxvec vec_mx.\n\n(*This lemma states that constructing a matrix from a vector that was previously obtained by flattening a matrix yields the original matrix, establishing that matrix construction is the left inverse of vectorization.*)\nLemma vec_mxK : cancel vec_mx mxvec.\n\n(*This lemma establishes that the function which maps a two-dimensional matrix index to a one-dimensional vector index is a bijection, meaning every pair of row and column indices corresponds to a unique linear index and vice versa.*)\nLemma curry_mxvec_bij : {on 'I_(m * n), bijective (uncurry mxvec_index)}.\n\nEnd VecMatrix.\n\nEnd MatrixStructural.\n\nArguments const_mx {R m n}.\nArguments row_mxA {R m n1 n2 n3 A1 A2 A3}.\nArguments col_mxA {R m1 m2 m3 n A1 A2 A3}.\nArguments block_mxA\n {R m1 m2 m3 n1 n2 n3 A11 A12 A13 A21 A22 A23 A31 A32 A33}.\nPrenex Implicits castmx trmx trmxK lsubmx rsubmx usubmx dsubmx row_mx col_mx.\nPrenex Implicits block_mx ulsubmx ursubmx dlsubmx drsubmx.\nPrenex Implicits mxvec vec_mx mxvec_indexP mxvecK vec_mxK.\nArguments trmx_inj {R m n} [A1 A2] eqA12t : rename.\n\n(*A notation providing the standard superscript T syntax for the transpose of a matrix.*)\nNotation \"A ^T\" := (trmx A) : ring_scope.\nNotation colsub g := (mxsub id g).\nNotation rowsub f := (mxsub f id).\n\nArguments eq_mxsub [R m n m' n' f] f' [g] g' _.\nArguments eq_rowsub [R m n m' f] f' _.\nArguments eq_colsub [R m n n' g] g' _.\n\nSection MapMatrix.\n\nVariables (aT rT : Type) (f : aT -> rT).\n\n(*This fact provides a unique key used internally by the matrix constructor when applying a function to each element of a matrix.*)\nFact map_mx_key : unit. \n(*This definition specifies a function that takes a matrix and another function as input, and produces a new matrix where each element is the result of applying the input function to the corresponding element of the original matrix.*)\nDefinition map_mx m n (A : 'M_(m, n)) := \\matrix[map_mx_key]_(i, j) f (A i j).\n\n(*This notation signifies the application of a specific, contextually-defined function to each element of a matrix. The matrix is provided as the left-hand operand to the `^f` operator.*)\nNotation \"A ^f\" := (map_mx A) : ring_scope.\n\nSection OneMatrix.\n\nVariables (m n : nat) (A : 'M[aT]_(m, n)).\n\n(*This lemma states that applying a function to each element of a matrix and then transposing the result is equivalent to first transposing the matrix and then applying the function to each element of the transposed matrix.*)\nLemma map_trmx : A^f^T = A^T^f.\n\n(*This lemma states that applying a function to a constant matrix, where all elements are a specific value, yields a new constant matrix where all elements are the result of applying that function to the original value.*)\nLemma map_const_mx a : (const_mx a)^f = const_mx (f a) :> 'M_(m, n).\n\n(*This lemma states that applying a function to a specific row extracted from a matrix is equivalent to extracting that same row from the matrix after the function has been applied to all its elements.*)\nLemma map_row i : (row i A)^f = row i A^f.\n\n(*This lemma states that applying a function to a specific column extracted from a matrix is equivalent to extracting that same column from the matrix after the function has been applied to all its elements.*)\nLemma map_col j : (col j A)^f = col j A^f.\n\n(*This lemma states that applying a function to a row vector extracted from a matrix using an ordinal index is equivalent to extracting that same row vector from the matrix after the function has been applied to all its elements.*)\nLemma map_row' i0 : (row' i0 A)^f = row' i0 A^f.\n\n(*This lemma states that applying a function to a column vector extracted from a matrix using an ordinal index is equivalent to extracting that same column vector from the matrix after the function has been applied to all its elements.*)\nLemma map_col' j0 : (col' j0 A)^f = col' j0 A^f.\n\n(*This lemma states that applying a function to a submatrix of a given matrix is equivalent to creating a submatrix from the matrix that has already had the function applied to all its elements, using the same row and column mapping functions.*)\nLemma map_mxsub m' n' g h : (@mxsub _ _ _ m' n' g h A)^f = mxsub g h A^f.\n\n(*This lemma states that applying a function to a matrix whose rows have been permuted is equivalent to first applying the function to the original matrix and then permuting the rows of the resulting matrix using the same permutation.*)\nLemma map_row_perm s : (row_perm s A)^f = row_perm s A^f.\n\n(*This lemma states that applying a function to a matrix whose columns have been permuted is equivalent to first applying the function to the original matrix and then permuting the columns of the resulting matrix using the same permutation.*)\nLemma map_col_perm s : (col_perm s A)^f = col_perm s A^f.\n\n(*This lemma states that applying a function to a matrix where two rows have been exchanged is equivalent to first applying the function to the original matrix and then exchanging the same two rows in the resulting matrix.*)\nLemma map_xrow i1 i2 : (xrow i1 i2 A)^f = xrow i1 i2 A^f.\n\n(*This lemma states that applying a function to a matrix where two columns have been exchanged is equivalent to first applying the function to the original matrix and then exchanging the same two columns in the resulting matrix.*)\nLemma map_xcol j1 j2 : (xcol j1 j2 A)^f = xcol j1 j2 A^f.\n\n(*This lemma states that applying a function to a matrix whose dimensions have been changed via a proof of equality is equivalent to first applying the function to the original matrix and then changing the dimensions of the resulting matrix using the same proof.*)\nLemma map_castmx m' n' c : (castmx c A)^f = castmx c A^f :> 'M_(m', n').\n\n(*This lemma states that applying a function to a matrix conformed to the dimensions of a second matrix yields the same result as conforming the function-applied matrix to the function-applied second matrix.*)\nLemma map_conform_mx m' n' (B : 'M_(m', n')) :\n (conform_mx B A)^f = conform_mx B^f A^f.\n\n(*This lemma states that applying a function to the vector representation of a matrix is equivalent to creating a vector representation of the matrix after the function has been applied to all its elements.*)\nLemma map_mxvec : (mxvec A)^f = mxvec A^f.\n\n(*This lemma states that applying a function to a matrix that was constructed from a vector is equivalent to constructing a matrix from that same vector after the function has been applied to all its elements.*)\nLemma map_vec_mx (v : 'rV_(m * n)) : (vec_mx v)^f = vec_mx v^f.\n\nEnd OneMatrix.\n\nSection Block.\n\nVariables m1 m2 n1 n2 : nat.\nVariables (Aul : 'M[aT]_(m1, n1)) (Aur : 'M[aT]_(m1, n2)).\nVariables (Adl : 'M[aT]_(m2, n1)) (Adr : 'M[aT]_(m2, n2)).\nVariables (Bh : 'M[aT]_(m1, n1 + n2)) (Bv : 'M[aT]_(m1 + m2, n1)).\nVariable B : 'M[aT]_(m1 + m2, n1 + n2).\n\n(*This lemma states that applying a function to a matrix formed by horizontally concatenating two other matrices is equivalent to horizontally concatenating the two matrices after the function has been applied to each of them individually.*)\nLemma map_row_mx : (row_mx Aul Aur)^f = row_mx Aul^f Aur^f.\n\n(*This lemma states that applying a function to a matrix formed by vertically concatenating two other matrices is equivalent to vertically concatenating the two matrices after the function has been applied to each of them individually.*)\nLemma map_col_mx : (col_mx Aul Adl)^f = col_mx Aul^f Adl^f.\n\n(*This lemma states that applying a function to a block matrix constructed from four submatrices is equivalent to constructing a new block matrix from the four submatrices after the function has been applied to each of them.*)\nLemma map_block_mx :\n (block_mx Aul Aur Adl Adr)^f = block_mx Aul^f Aur^f Adl^f Adr^f.\n\n(*This lemma states that applying a function to the left submatrix of a given matrix is equivalent to extracting the left submatrix from the same matrix after the function has been applied to all its elements.*)\nLemma map_lsubmx : (lsubmx Bh)^f = lsubmx Bh^f.\n\n(*This lemma states that applying a function to the right submatrix of a given matrix is equivalent to extracting the right submatrix from the same matrix after the function has been applied to all its elements.*)\nLemma map_rsubmx : (rsubmx Bh)^f = rsubmx Bh^f.\n\n(*This lemma states that applying a function to the upper submatrix of a given matrix is equivalent to extracting the upper submatrix from the same matrix after the function has been applied to all its elements.*)\nLemma map_usubmx : (usubmx Bv)^f = usubmx Bv^f.\n\n(*This lemma states that applying a function to the lower submatrix of a given matrix is equivalent to extracting the lower submatrix from the same matrix after the function has been applied to all its elements.*)\nLemma map_dsubmx : (dsubmx Bv)^f = dsubmx Bv^f.\n\n(*This lemma states that applying a function to the upper-left submatrix of a given matrix is equivalent to extracting the upper-left submatrix from the same matrix after the function has been applied to all its elements.*)\nLemma map_ulsubmx : (ulsubmx B)^f = ulsubmx B^f.\n\n(*This lemma states that applying a function to the upper-right submatrix of a given matrix is equivalent to extracting the upper-right submatrix from the same matrix after the function has been applied to all its elements.*)\nLemma map_ursubmx : (ursubmx B)^f = ursubmx B^f.\n\n(*This lemma states that applying a function to the lower-left submatrix of a given matrix is equivalent to extracting the lower-left submatrix from the same matrix after the function has been applied to all its elements.*)\nLemma map_dlsubmx : (dlsubmx B)^f = dlsubmx B^f.\n\n(*This lemma states that applying a function to the lower-right submatrix of a given matrix is equivalent to extracting the lower-right submatrix from the same matrix after the function has been applied to all its elements.*)\nLemma map_drsubmx : (drsubmx B)^f = drsubmx B^f.\n\nEnd Block.\n\nEnd MapMatrix.\n\nArguments map_mx {aT rT} f {m n} A.\n\nSection MultipleMapMatrix.\nContext {R S T : Type} {m n : nat}.\n(*This local notation defines a binary operator for applying an arbitrary function to each element of a matrix. The matrix is the left-hand operand and the function is the right-hand operand, resulting in a new matrix of the same dimensions.*)\nLocal Notation \"M ^ phi\" := (map_mx phi M).\n\n(*This lemma states that applying a composition of two functions over a matrix is equivalent to first applying the first function to the matrix and then applying the second function to the resulting matrix.*)\nLemma map_mx_comp (f : R -> S) (g : S -> T)\n (M : 'M_(m, n)) : M ^ (g \\o f) = (M ^ f) ^ g.\n\n(*This lemma states that if two functions are equal on all entries of a given matrix, then mapping either function over that matrix results in the same matrix.*)\nLemma eq_in_map_mx (g f : R -> S) (M : 'M_(m, n)) :\n (forall i j, f (M i j) = g (M i j)) -> M ^ f = M ^ g.\n\n(*This lemma states that if two functions are pointwise equal, then for any matrix, mapping the first function over it yields the same result as mapping the second function.*)\nLemma eq_map_mx (g f : R -> S) : f =1 g ->\n forall (M : 'M_(m, n)), M ^ f = M ^ g.\n\n(*This lemma states that if a function acts as the identity on all entries of a given matrix, mapping that function over the matrix leaves it unchanged.*)\nLemma map_mx_id_in (f : R -> R) (M : 'M_(m, n)) :\n (forall i j, f (M i j) = M i j) -> M ^ f = M.\n\n(*This lemma states that if a function is pointwise equal to the identity function, then mapping it over any matrix leaves the matrix unchanged.*)\nLemma map_mx_id (f : R -> R) : f =1 id -> forall M : 'M_(m, n), M ^ f = M.\n\nEnd MultipleMapMatrix.\nArguments eq_map_mx {R S m n} g [f].\nArguments eq_in_map_mx {R S m n} g [f M].\nArguments map_mx_id_in {R m n} [f M].\nArguments map_mx_id {R m n} [f].\n\nSection Map2Matrix.\nContext {R S T : Type} (f : R -> S -> T).\n\n(*This fact provides a unique key used internally for the definition of the binary matrix map operation.*)\nFact map2_mx_key : unit. \n(*This definition creates a new matrix by applying a given binary function element-wise to two input matrices of the same dimensions.*)\nDefinition map2_mx m n (A : 'M_(m, n)) (B : 'M_(m, n)) :=\n \\matrix[map2_mx_key]_(i, j) f (A i j) (B i j).\n\nSection OneMatrix.\n\nVariables (m n : nat) (A : 'M[R]_(m, n)) (B : 'M[S]_(m, n)).\n\n(*This lemma states that the transpose of the result of a binary map on two matrices is the same as the binary map applied to the transposes of those matrices.*)\nLemma map2_trmx : (map2_mx A B)^T = map2_mx A^T B^T.\n\n(*This lemma states that applying a binary map to two constant matrices results in a new constant matrix whose entries are the result of applying the binary function to the constant values of the input matrices.*)\nLemma map2_const_mx a b :\n map2_mx (const_mx a) (const_mx b) = const_mx (f a b) :> 'M_(m, n).\n\n(*This lemma states that the binary map of the i-th rows of two matrices is equal to the i-th row of the binary map of the two matrices.*)\nLemma map2_row i : map2_mx (row i A) (row i B) = row i (map2_mx A B).\n\n(*This lemma states that the binary map of the j-th columns of two matrices is equal to the j-th column of the binary map of the two matrices.*)\nLemma map2_col j : map2_mx (col j A) (col j B) = col j (map2_mx A B).\n\n(*This lemma states that the binary map of single-row submatrices extracted from the same row index of two matrices is equal to the single-row submatrix at that index of the binary map of the two matrices.*)\nLemma map2_row' i0 : map2_mx (row' i0 A) (row' i0 B) = row' i0 (map2_mx A B).\n\n(*This lemma states that the binary map of single-column submatrices extracted from the same column index of two matrices is equal to the single-column submatrix at that index of the binary map of the two matrices.*)\nLemma map2_col' j0 : map2_mx (col' j0 A) (col' j0 B) = col' j0 (map2_mx A B).\n\n(*This lemma states that applying a binary map to submatrices of two matrices is equivalent to taking the corresponding submatrix of the result of applying the binary map to the original matrices.*)\nLemma map2_mxsub m' n' g h :\n map2_mx (@mxsub _ _ _ m' n' g h A) (@mxsub _ _ _ m' n' g h B) =\n mxsub g h (map2_mx A B).\n\n(*This lemma states that applying a binary map to two matrices after permuting their rows with the same permutation is equivalent to first applying the binary map and then permuting the rows of the resulting matrix.*)\nLemma map2_row_perm s :\n map2_mx (row_perm s A) (row_perm s B) = row_perm s (map2_mx A B).\n\n(*This lemma states that applying a binary map to two matrices after permuting their columns with the same permutation is equivalent to first applying the binary map and then permuting the columns of the resulting matrix.*)\nLemma map2_col_perm s :\n map2_mx (col_perm s A) (col_perm s B) = col_perm s (map2_mx A B).\n\n(*This lemma states that applying a binary map to two matrices after exchanging the same two rows in each is equivalent to first applying the binary map and then exchanging those two rows in the resulting matrix.*)\nLemma map2_xrow i1 i2 :\n map2_mx (xrow i1 i2 A) (xrow i1 i2 B) = xrow i1 i2 (map2_mx A B).\n\n(*This lemma states that applying a binary map to two matrices after exchanging the same two columns in each is equivalent to first applying the binary map and then exchanging those two columns in the resulting matrix.*)\nLemma map2_xcol j1 j2 :\n map2_mx (xcol j1 j2 A) (xcol j1 j2 B) = xcol j1 j2 (map2_mx A B).\n\n(*This lemma states that applying a binary map to two matrices after casting them to new dimensions is equivalent to first applying the binary map and then casting the resulting matrix to the new dimensions.*)\nLemma map2_castmx m' n' c :\n map2_mx (castmx c A) (castmx c B) = castmx c (map2_mx A B) :> 'M_(m', n').\n\n(*This lemma states that the binary map of two conformed matrices is equal to the conformed matrix formed from the binary maps of the corresponding component matrices.*)\nLemma map2_conform_mx m' n' (A' : 'M_(m', n')) (B' : 'M_(m', n')) :\n map2_mx (conform_mx A' A) (conform_mx B' B) =\n conform_mx (map2_mx A' B') (map2_mx A B).\n\n(*This lemma states that applying a binary map to the vectorizations of two matrices is equivalent to vectorizing the result of applying the binary map to the original matrices.*)\nLemma map2_mxvec : map2_mx (mxvec A) (mxvec B) = mxvec (map2_mx A B).\n\n(*This lemma states that applying a binary map to two matrices created from vectors is equivalent to creating a matrix from the result of applying the binary map element-wise to the two original vectors.*)\nLemma map2_vec_mx (v : 'rV_(m * n)) (w : 'rV_(m * n)) :\n map2_mx (vec_mx v) (vec_mx w) = vec_mx (map2_mx v w).\n\nEnd OneMatrix.\n\nSection Block.\n\nVariables m1 m2 n1 n2 : nat.\nVariables (Aul : 'M[R]_(m1, n1)) (Aur : 'M[R]_(m1, n2)).\nVariables (Adl : 'M[R]_(m2, n1)) (Adr : 'M[R]_(m2, n2)).\nVariables (Bh : 'M[R]_(m1, n1 + n2)) (Bv : 'M[R]_(m1 + m2, n1)).\nVariable B : 'M[R]_(m1 + m2, n1 + n2).\nVariables (A'ul : 'M[S]_(m1, n1)) (A'ur : 'M[S]_(m1, n2)).\nVariables (A'dl : 'M[S]_(m2, n1)) (A'dr : 'M[S]_(m2, n2)).\nVariables (B'h : 'M[S]_(m1, n1 + n2)) (B'v : 'M[S]_(m1 + m2, n1)).\nVariable B' : 'M[S]_(m1 + m2, n1 + n2).\n\n(*This lemma states that applying a binary map to two matrices constructed by horizontal concatenation is equivalent to horizontally concatenating the results of applying the binary map to the corresponding sub-matrices.*)\nLemma map2_row_mx :\n map2_mx (row_mx Aul Aur) (row_mx A'ul A'ur) =\n row_mx (map2_mx Aul A'ul) (map2_mx Aur A'ur).\n\n(*This lemma states that applying a binary map to two matrices constructed by vertical concatenation is equivalent to vertically concatenating the results of applying the binary map to the corresponding sub-matrices.*)\nLemma map2_col_mx :\n map2_mx (col_mx Aul Adl) (col_mx A'ul A'dl) =\n col_mx (map2_mx Aul A'ul) (map2_mx Adl A'dl).\n\n(*This lemma states that applying a binary map to two block matrices is equivalent to constructing a new block matrix where each block is the result of applying the binary map to the corresponding blocks of the original matrices.*)\nLemma map2_block_mx :\n map2_mx (block_mx Aul Aur Adl Adr) (block_mx A'ul A'ur A'dl A'dr) =\n block_mx\n (map2_mx Aul A'ul) (map2_mx Aur A'ur) (map2_mx Adl A'dl) (map2_mx Adr A'dr).\n\n(*This lemma states that the binary map of the left submatrices of two matrices is equal to the left submatrix of the binary map of those two matrices.*)\nLemma map2_lsubmx : map2_mx (lsubmx Bh) (lsubmx B'h) = lsubmx (map2_mx Bh B'h).\n\n(*This lemma states that the binary map of the right submatrices of two matrices is equal to the right submatrix of the binary map of those two matrices.*)\nLemma map2_rsubmx : map2_mx (rsubmx Bh) (rsubmx B'h) = rsubmx (map2_mx Bh B'h).\n\n(*This lemma states that the binary map of the upper submatrices of two matrices is equal to the upper submatrix of the binary map of those two matrices.*)\nLemma map2_usubmx : map2_mx (usubmx Bv) (usubmx B'v) = usubmx (map2_mx Bv B'v).\n\n(*This lemma states that the binary map of the lower submatrices of two matrices is equal to the lower submatrix of the binary map of those two matrices.*)\nLemma map2_dsubmx : map2_mx (dsubmx Bv) (dsubmx B'v) = dsubmx (map2_mx Bv B'v).\n\n(*This lemma states that the binary map of the upper-left submatrices of two matrices is equal to the upper-left submatrix of the binary map of those two matrices.*)\nLemma map2_ulsubmx : map2_mx (ulsubmx B) (ulsubmx B') = ulsubmx (map2_mx B B').\n\n(*This lemma states that applying a binary function element-wise to the upper-right submatrices of two block matrices is equivalent to taking the upper-right submatrix of the result of applying that same function element-wise to the original block matrices.*)\nLemma map2_ursubmx : map2_mx (ursubmx B) (ursubmx B') = ursubmx (map2_mx B B').\n\n(*This lemma states that applying a binary function element-wise to the lower-left submatrices of two block matrices is equivalent to taking the lower-left submatrix of the result of applying that same function element-wise to the original block matrices.*)\nLemma map2_dlsubmx : map2_mx (dlsubmx B) (dlsubmx B') = dlsubmx (map2_mx B B').\n\n(*This lemma states that applying a binary function element-wise to the lower-right submatrices of two block matrices is equivalent to taking the lower-right submatrix of the result of applying that same function element-wise to the original block matrices.*)\nLemma map2_drsubmx : map2_mx (drsubmx B) (drsubmx B') = drsubmx (map2_mx B B').\n\nEnd Block.\n\nEnd Map2Matrix.\n\nSection Map2Eq.\n\nContext {R S T : Type} {m n : nat}.\n\n(*This lemma states that if two binary functions produce equal results when applied to all corresponding pairs of elements from two given matrices, then applying either function element-wise to those two matrices will produce the same resulting matrix.*)\nLemma eq_in_map2_mx (f g : R -> S -> T) (M : 'M[R]_(m, n)) (M' : 'M[S]_(m, n)) :\n (forall i j, f (M i j) (M' i j) = g (M i j) (M' i j)) ->\n map2_mx f M M' = map2_mx g M M'.\n\n(*This lemma states that if two binary functions are extensionally equal, then the higher-order functions that apply these binary functions element-wise to pairs of matrices are also extensionally equal.*)\nLemma eq_map2_mx (f g : R -> S -> T) : f =2 g ->\n @map2_mx _ _ _ f m n =2 @map2_mx _ _ _ g m n.\n\n(*This lemma states that if a binary function, when applied to every pair of corresponding elements from two matrices, always returns the element from the first matrix, then the element-wise application of this function to the two matrices will result in the first matrix.*)\nLemma map2_mx_left_in (f : R -> R -> R) (M : 'M_(m, n)) (M' : 'M_(m, n)) :\n (forall i j, f (M i j) (M' i j) = M i j) -> map2_mx f M M' = M.\n\n(*This lemma states that if a binary function is extensionally equal to the projection function that returns its first argument, then applying this function element-wise to any pair of matrices will yield the first matrix.*)\nLemma map2_mx_left (f : R -> R -> R) : f =2 (fun x _ => x) ->\n forall (M : 'M_(m, n)) (M' : 'M_(m, n)), map2_mx f M M' = M.\n\n(*This lemma states that if a binary function, when applied to every pair of corresponding elements from two matrices, always returns the element from the second matrix, then the element-wise application of this function to the two matrices will result in the second matrix.*)\nLemma map2_mx_right_in (f : R -> R -> R) (M : 'M_(m, n)) (M' : 'M_(m, n)) :\n (forall i j, f (M i j) (M' i j) = M' i j) -> map2_mx f M M' = M'.\n\n(*This lemma states that if a binary function is extensionally equal to the projection function that returns its second argument, then applying this function element-wise to any pair of matrices will yield the second matrix.*)\nLemma map2_mx_right (f : R -> R -> R) : f =2 (fun _ x => x) ->\n forall (M : 'M_(m, n)) (M' : 'M_(m, n)), map2_mx f M M' = M'.\n\nEnd Map2Eq.\n\nSection MatrixLaws.\n\nContext {T : Type} {m n : nat} {idm : T}.\n\n(*This lemma states that if a binary operation is associative, then the corresponding element-wise operation on matrices is also associative.*)\nLemma map2_mxA {opm : Monoid.law idm} : associative (@map2_mx _ _ _ opm m n).\n\n(*This lemma states that for an element-wise matrix operation derived from a monoid's binary law, the constant matrix whose entries are all the monoid's identity element acts as a left identity.*)\nLemma map2_1mx {opm : Monoid.law idm} :\n left_id (const_mx idm) (@map2_mx _ _ _ opm m n).\n\n(*This lemma states that for an element-wise matrix operation derived from a monoid's binary law, the constant matrix whose entries are all the monoid's identity element acts as a right identity.*)\nLemma map2_mx1 {opm : Monoid.law idm} :\n right_id (const_mx idm) (@map2_mx _ _ _ opm m n).\n\nHB.instance Definition _ {opm : Monoid.law idm} :=\n Monoid.isLaw.Build 'M_(m, n) (const_mx idm) (@map2_mx _ _ _ opm _ _)\n map2_mxA map2_1mx map2_mx1.\n\n(*This lemma states that if a binary operation is commutative, then the corresponding element-wise operation on matrices is also commutative.*)\nLemma map2_mxC {opm : Monoid.com_law idm} :\n commutative (@map2_mx _ _ _ opm m n).\n\nHB.instance Definition _ {opm : Monoid.com_law idm} :=\n SemiGroup.isCommutativeLaw.Build 'M_(m, n) (@map2_mx _ _ _ opm _ _) map2_mxC.\n\n(*This lemma states that for an element-wise matrix operation derived from a binary law with a zero element, the constant matrix whose entries are all the zero element acts as a left absorbing element.*)\nLemma map2_0mx {opm : Monoid.mul_law idm} :\n left_zero (const_mx idm) (@map2_mx _ _ _ opm m n).\n\n(*This lemma states that for an element-wise matrix operation derived from a binary law with a zero element, the constant matrix whose entries are all the zero element acts as a right absorbing element.*)\nLemma map2_mx0 {opm : Monoid.mul_law idm} :\n right_zero (const_mx idm) (@map2_mx _ _ _ opm m n).\n\nHB.instance Definition _ {opm : Monoid.mul_law idm} :=\n Monoid.isMulLaw.Build 'M_(m, n) (const_mx idm) (@map2_mx _ _ _ opm _ _)\n map2_0mx map2_mx0.\n\n(*This lemma states that if one binary operation is left-distributive over a second binary operation, then the corresponding element-wise matrix operation for the first is also left-distributive over the element-wise matrix operation for the second.*)\nLemma map2_mxDl {mul : T -> T -> T} {add : Monoid.add_law idm mul} :\n left_distributive (@map2_mx _ _ _ mul m n) (@map2_mx _ _ _ add m n).\n\n(*This lemma states that if one binary operation is right-distributive over a second binary operation, then the corresponding element-wise matrix operation for the first is also right-distributive over the element-wise matrix operation for the second.*)\nLemma map2_mxDr {mul : T -> T -> T} {add : Monoid.add_law idm mul} :\n right_distributive (@map2_mx _ _ _ mul m n) (@map2_mx _ _ _ add m n).\n\n(*This fact serves as a key used by the hierarchy builder to anchor the definition of matrix addition.*)\nFact addmx_key : unit. \n(*This definition specifies matrix addition as the element-wise application of the underlying module's addition operation to two matrices of the same dimensions.*)\nDefinition addmx := @map2_mx V V V +%R m n.\n\n(*This definition provides a proof that matrix addition is an associative operation, based on the general property of element-wise operations.*)\nDefinition addmxA : associative addmx := map2_mxA.\n(*This definition provides a proof that matrix addition is a commutative operation, based on the general property of element-wise operations over a commutative base operation.*)\nDefinition addmxC : commutative addmx := map2_mxC.\n(*This definition provides a proof that the zero matrix, a matrix where every entry is the additive identity, serves as the left identity for matrix addition.*)\nDefinition add0mx : left_id (const_mx 0) addmx := map2_1mx.\n\nHB.instance Definition _ := GRing.isNmodule.Build 'M[V]_(m, n)\n addmxA addmxC add0mx.\n\n(*This lemma states that the element at a given row and column of a matrix resulting from right scalar multiplication is equal to the element at the same position in the original matrix multiplied by the scalar.*)\nLemma mulmxnE A d i j : (A *+ d) i j = A i j *+ d.\n\n(*This lemma states that the element at a given row and column in the sum of a sequence of matrices is equal to the sum of the elements at that same position in each individual matrix of the sequence.*)\nLemma summxE I r (P : pred I) (E : I -> 'M_(m, n)) i j :\n (\\sum_(k <- r | P k) E k) i j = \\sum_(k <- r | P k) E k i j.\n\n(*This lemma states that the function which creates a constant matrix from a scalar value is a module morphism, meaning it preserves the addition and scalar multiplication structure.*)\nLemma const_mx_is_nmod_morphism : nmod_morphism const_mx.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `const_mx_is_nmod_morphism` instead\")]\n(*This definition, now deprecated, provides a proof that the constant matrix constructor is a semi-additive function. The modern equivalent of this property is that the constructor is a module morphism.*)\nDefinition const_mx_is_semi_additive := const_mx_is_nmod_morphism.\n(*This definition describes an operation that creates a new matrix by rearranging the elements of a given matrix. The element at each position in the new matrix is determined by taking the element from a position in the original matrix specified by two index-mapping functions.*)\nDefinition swizzle_mx k (A : 'M[V]_(m, n)) :=\n \\matrix[k]_(i, j) A (f i j) (g i j).\n\n(*This lemma states that the matrix swizzle operation, which rearranges matrix elements according to fixed indexing functions, is a module morphism. This means it preserves the structure of matrix addition and scalar multiplication.*)\nLemma swizzle_mx_is_nmod_morphism k : nmod_morphism (swizzle_mx k).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `swizzle_mx_is_nmod_morphism` instead\")]\n(*This definition, now deprecated, provides a proof that the matrix swizzle operation is a semi-additive function. The modern equivalent of this property is that the operation is a module morphism.*)\nDefinition swizzle_mx_is_semi_additive := swizzle_mx_is_nmod_morphism.\n(*This lemma states that the zero matrix with zero rows and any number of columns has the property that all its entries are equal. This holds vacuously because a matrix with zero rows has no entries.*)\nLemma flatmx0 n : all_equal_to (0 : 'M_(0, n)).\n\n(*This lemma states that any matrix with a non-zero number of rows and zero columns is equal to the zero matrix of those dimensions.*)\nLemma thinmx0 n : all_equal_to (0 : 'M_(n, 0)).\n\n(*This lemma states that the transpose of a zero matrix is also a zero matrix.*)\nLemma trmx0 m n : (0 : 'M_(m, n))^T = 0.\n\n(*This lemma states that any row of a zero matrix is a zero row vector.*)\nLemma row0 m n i0 : row i0 (0 : 'M_(m, n)) = 0.\n\n(*This lemma states that any column of a zero matrix is a zero column vector.*)\nLemma col0 m n j0 : col j0 (0 : 'M_(m, n)) = 0.\n\n(*This lemma states that a matrix is equal to the zero matrix if and only if its corresponding flattened vector representation is equal to the zero vector.*)\nLemma mxvec_eq0 m n (A : 'M_(m, n)) : (mxvec A == 0) = (A == 0).\n\n(*This lemma states that a row vector is equal to the zero vector if and only if the matrix representation reshaped from that vector is equal to the zero matrix.*)\nLemma vec_mx_eq0 m n (v : 'rV_(m * n)) : (vec_mx v == 0) = (v == 0).\n\n(*This lemma states that horizontally concatenating two zero matrices results in a larger zero matrix.*)\nLemma row_mx0 m n1 n2 : row_mx 0 0 = 0 :> 'M_(m, n1 + n2).\n\n(*This lemma states that vertically concatenating two zero matrices results in a larger zero matrix.*)\nLemma col_mx0 m1 m2 n : col_mx 0 0 = 0 :> 'M_(m1 + m2, n).\n\n(*This lemma states that a block matrix formed from four zero sub-matrices is itself a zero matrix.*)\nLemma block_mx0 m1 m2 n1 n2 : block_mx 0 0 0 0 = 0 :> 'M_(m1 + m2, n1 + n2).\n\n(*A proof tactic designed to prove that two matrices are equal by reducing the goal to showing element-wise equality. It automatically applies the principle that two matrices are equal if and only if all their corresponding entries are equal, setting up subgoals for each entry.*)\nLtac split_mxE := apply/matrixP=> i j; do ![rewrite mxE | case: split => ?].\n\n(*This lemma states that the sum of two horizontally concatenated matrices is equivalent to horizontally concatenating the sum of the left-hand side matrices and the sum of the right-hand side matrices.*)\nLemma add_row_mx m n1 n2 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) B1 B2 :\n row_mx A1 A2 + row_mx B1 B2 = row_mx (A1 + B1) (A2 + B2).\n\n(*This lemma states that the sum of two vertically concatenated matrices is equivalent to vertically concatenating the sum of the upper matrices and the sum of the lower matrices.*)\nLemma add_col_mx m1 m2 n (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) B1 B2 :\n col_mx A1 A2 + col_mx B1 B2 = col_mx (A1 + B1) (A2 + B2).\n\n(*This lemma states that the sum of two block matrices is a block matrix where each block is the sum of the corresponding blocks from the original two matrices.*)\nLemma add_block_mx m1 m2 n1 n2 (Aul : 'M_(m1, n1)) Aur Adl (Adr : 'M_(m2, n2))\n Bul Bur Bdl Bdr :\n let A := block_mx Aul Aur Adl Adr in let B := block_mx Bul Bur Bdl Bdr in\n A + B = block_mx (Aul + Bul) (Aur + Bur) (Adl + Bdl) (Adr + Bdr).\n\n(*This lemma states that a matrix formed by horizontal concatenation is a zero matrix if and only if both of its component matrices are zero matrices.*)\nLemma row_mx_eq0 (m n1 n2 : nat) (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)):\n (row_mx A1 A2 == 0) = (A1 == 0) && (A2 == 0).\n\n(*This lemma states that a matrix formed by vertical concatenation is a zero matrix if and only if both of its component matrices are zero matrices.*)\nLemma col_mx_eq0 (m1 m2 n : nat) (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)):\n (col_mx A1 A2 == 0) = (A1 == 0) && (A2 == 0).\n\n(*This lemma states that a block matrix is a zero matrix if and only if all four of its sub-matrix blocks are zero matrices.*)\nLemma block_mx_eq0 m1 m2 n1 n2 (Aul : 'M_(m1, n1)) Aur Adl (Adr : 'M_(m2, n2)) :\n (block_mx Aul Aur Adl Adr == 0) =\n [&& Aul == 0, Aur == 0, Adl == 0 & Adr == 0].\n\n(*This lemma states that the transpose of a matrix is a zero matrix if and only if the original matrix is a zero matrix.*)\nLemma trmx_eq0 m n (A : 'M_(m, n)) : (A^T == 0) = (A == 0).\n\n(*This lemma states that a matrix is equal to the zero matrix if and only if all of its elements are equal to zero.*)\nLemma matrix_eq0 m n (A : 'M_(m, n)) :\n (A == 0) = [forall i, forall j, A i j == 0].\n\n(*This lemma establishes that a matrix is not equal to the zero matrix if and only if there exists at least one non-zero element within the matrix.*)\nLemma matrix0Pn m n (A : 'M_(m, n)) : reflect (exists i j, A i j != 0) (A != 0).\n\n(*This lemma establishes that a row vector is not equal to the zero vector if and only if there exists at least one non-zero element within the vector.*)\nLemma rV0Pn n (v : 'rV_n) : reflect (exists i, v 0 i != 0) (v != 0).\n\n(*This lemma establishes that a column vector is not equal to the zero vector if and only if there exists at least one non-zero element within the vector.*)\nLemma cV0Pn n (v : 'cV_n) : reflect (exists i, v i 0 != 0) (v != 0).\n\n(*This definition provides a function that, for a given matrix, returns a non-zero row if one exists, and a zero row vector otherwise.*)\nDefinition nz_row m n (A : 'M_(m, n)) :=\n oapp (fun i => row i A) 0 [pick i | row i A != 0].\n\n(*This lemma states that the row vector produced by the nz_row function is a zero vector if and only if the input matrix is a zero matrix.*)\nLemma nz_row_eq0 m n (A : 'M_(m, n)) : (nz_row A == 0) = (A == 0).\n\n(*This definition specifies the property of a matrix being diagonal, which holds if all entries outside the main diagonal are equal to zero.*)\nDefinition is_diag_mx m n (A : 'M[V]_(m, n)) :=\n [forall i : 'I__, forall j : 'I__, (i != j :> nat) ==> (A i j == 0)].\n\n(*This lemma provides a reflection principle, connecting the boolean predicate for a matrix being diagonal to the logical proposition that every off-diagonal element is zero.*)\nLemma is_diag_mxP m n (A : 'M[V]_(m, n)) :\n reflect (forall i j : 'I__, i != j :> nat -> A i j = 0) (is_diag_mx A).\n\n(*This lemma states that any zero matrix is a diagonal matrix.*)\nLemma mx0_is_diag m n : is_diag_mx (0 : 'M[V]_(m, n)).\n\n(*This lemma states that any one-by-one matrix is a diagonal matrix.*)\nLemma mx11_is_diag (M : 'M_1) : is_diag_mx M.\n\n(*This definition specifies the property of a matrix being lower triangular, which holds if all entries strictly above the main diagonal are equal to zero.*)\nDefinition is_trig_mx m n (A : 'M[V]_(m, n)) :=\n [forall i : 'I__, forall j : 'I__, (i < j)%N ==> (A i j == 0)].\n\n(*This lemma provides a reflection principle, connecting the boolean predicate for a matrix being lower triangular to the logical proposition that every element strictly above the main diagonal is zero.*)\nLemma is_trig_mxP m n (A : 'M[V]_(m, n)) :\n reflect (forall i j : 'I__, (i < j)%N -> A i j = 0) (is_trig_mx A).\n\n(*This lemma states that if a matrix is diagonal, then it is also lower triangular.*)\nLemma is_diag_mx_is_trig m n (A : 'M[V]_(m, n)) : is_diag_mx A -> is_trig_mx A.\n\n(*This lemma states that a zero matrix of any given dimensions is a triangular matrix.*)\nLemma mx0_is_trig m n : is_trig_mx (0 : 'M[V]_(m, n)).\n\n(*This lemma states that any one-by-one matrix is a triangular matrix.*)\nLemma mx11_is_trig (M : 'M_1) : is_trig_mx M.\n\n(*This lemma states that a matrix is a diagonal matrix if and only if both the matrix itself and its transpose are triangular matrices.*)\nLemma is_diag_mxEtrig m n (A : 'M[V]_(m, n)) :\n is_diag_mx A = is_trig_mx A && is_trig_mx A^T.\n\n(*This lemma states that a matrix is a diagonal matrix if and only if its transpose is also a diagonal matrix.*)\nLemma is_diag_trmx m n (A : 'M[V]_(m, n)) : is_diag_mx A^T = is_diag_mx A.\n\n(*This lemma states that for a triangular block matrix where the number of rows in the upper-left block is less than or equal to the number of columns in the upper-left block, the upper-right submatrix is a zero matrix.*)\nLemma ursubmx_trig m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :\n m1 <= n1 -> is_trig_mx A -> ursubmx A = 0.\n\n(*This lemma states that for a diagonal block matrix where the number of columns in the upper-left block is less than or equal to the number of rows in the upper-left block, the lower-left submatrix is a zero matrix.*)\nLemma dlsubmx_diag m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :\n n1 <= m1 -> is_diag_mx A -> dlsubmx A = 0.\n\n(*This lemma states that if a matrix is triangular, then its upper-left submatrix is also a triangular matrix.*)\nLemma ulsubmx_trig m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :\n is_trig_mx A -> is_trig_mx (ulsubmx A).\n\n(*This lemma states that if a matrix is triangular and the number of rows in its upper-left block is less than or equal to the number of columns, then its lower-right submatrix is also a triangular matrix.*)\nLemma drsubmx_trig m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :\n m1 <= n1 -> is_trig_mx A -> is_trig_mx (drsubmx A).\n\n(*This lemma states that if a matrix is diagonal, then its upper-left submatrix is also a diagonal matrix.*)\nLemma ulsubmx_diag m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :\n is_diag_mx A -> is_diag_mx (ulsubmx A).\n\n(*This lemma states that if a block matrix is diagonal and its upper-left block is square, then its lower-right submatrix is also a diagonal matrix.*)\nLemma drsubmx_diag m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :\n m1 = n1 -> is_diag_mx A -> is_diag_mx (drsubmx A).\n\n(*This lemma states that a block matrix with a square upper-left block is triangular if and only if its upper-right submatrix is a zero matrix and both its upper-left and lower-right submatrices are triangular.*)\nLemma is_trig_block_mx m1 m2 n1 n2 ul ur dl dr : m1 = n1 ->\n @is_trig_mx (m1 + m2) (n1 + n2) (block_mx ul ur dl dr) =\n [&& ur == 0, is_trig_mx ul & is_trig_mx dr].\n\n(*This lemma provides an induction principle for proving properties of any triangular matrix. It requires proving the property for zero-row matrices and zero-column matrices, and then showing that if the property holds for a given triangular matrix, it also holds for a larger triangular matrix constructed by adding a row and a column in a block form.*)\nLemma trigmx_ind (P : forall m n, 'M_(m, n) -> Type) :\n (forall m, P m 0 0) ->\n (forall n, P 0 n 0) ->\n (forall m n x c A, is_trig_mx A ->\n P m n A -> P (1 + m)%N (1 + n)%N (block_mx x 0 c A)) ->\n forall m n A, is_trig_mx A -> P m n A.\n\n(*This lemma provides an induction principle for proving properties of square triangular matrices. It requires proving the property for the zero-by-zero matrix and then showing that if the property holds for a given square triangular matrix, it also holds for a one-dimension-larger square triangular matrix constructed in a block form.*)\nLemma trigsqmx_ind (P : forall n, 'M[V]_n -> Type) : (P 0 0) ->\n (forall n x c A, is_trig_mx A -> P n A -> P (1 + n)%N (block_mx x 0 c A)) ->\n forall n A, is_trig_mx A -> P n A.\n\n(*This lemma states that a block matrix with a square upper-left block is diagonal if and only if its upper-right and lower-left submatrices are zero matrices, and both its upper-left and lower-right submatrices are diagonal matrices.*)\nLemma is_diag_block_mx m1 m2 n1 n2 ul ur dl dr : m1 = n1 ->\n @is_diag_mx (m1 + m2) (n1 + n2) (block_mx ul ur dl dr) =\n [&& ur == 0, dl == 0, is_diag_mx ul & is_diag_mx dr].\n\n(*This lemma provides an induction principle for proving properties of any diagonal matrix. It requires proving the property for zero-row matrices and zero-column matrices, and then showing that if the property holds for a given diagonal matrix, it also holds for a larger matrix constructed in a specific block form.*)\nLemma diagmx_ind (P : forall m n, 'M_(m, n) -> Type) :\n (forall m, P m 0 0) ->\n (forall n, P 0 n 0) ->\n (forall m n x c A, is_diag_mx A ->\n P m n A -> P (1 + m)%N (1 + n)%N (block_mx x 0 c A)) ->\n forall m n A, is_diag_mx A -> P m n A.\n\n(*This lemma provides an induction principle for proving properties of square diagonal matrices. It requires proving the property for the zero-by-zero matrix and then showing that if the property holds for a given square diagonal matrix, it also holds for a one-dimension-larger matrix constructed in a specific block form.*)\nLemma diagsqmx_ind (P : forall n, 'M[V]_n -> Type) :\n (P 0 0) ->\n (forall n x c A, is_diag_mx A -> P n A -> P (1 + n)%N (block_mx x 0 c A)) ->\n forall n A, is_diag_mx A -> P n A.\n\n(*This fact provides an opaque key used internally for the definition of a diagonal matrix constructor, ensuring consistent definitional properties.*)\nFact diag_mx_key : unit. \n(*This definition specifies a function that constructs a square diagonal matrix from a given row vector, where the elements of the vector become the diagonal entries of the matrix.*)\nDefinition diag_mx n (d : 'rV[V]_n) :=\n \\matrix[diag_mx_key]_(i, j) (d 0 i *+ (i == j)).\n\n(*This lemma states that a diagonal matrix constructed from a vector is symmetric, meaning it is equal to its own transpose.*)\nLemma tr_diag_mx n (d : 'rV_n) : (diag_mx d)^T = diag_mx d.\n\n(*This lemma states that the function for constructing a diagonal matrix from a vector is an additive-group homomorphism, meaning it preserves vector addition and scalar multiplication by natural numbers.*)\nLemma diag_mx_is_nmod_morphism n : nmod_morphism (@diag_mx n).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `diag_mx_is_nmod_morphism` instead\")]\n(*This definition, now deprecated, asserts that the function for constructing a diagonal matrix from a vector is a semi-additive map. This is an alias for a newer lemma stating it is an additive-group homomorphism.*)\nDefinition diag_mx_is_semi_additive := diag_mx_is_nmod_morphism.\n(*This lemma states that constructing a diagonal matrix from the concatenation of two row vectors results in a block diagonal matrix where the diagonal blocks are the diagonal matrices constructed from each individual vector.*)\nLemma diag_mx_row m n (l : 'rV_n) (r : 'rV_m) :\n diag_mx (row_mx l r) = block_mx (diag_mx l) 0 0 (diag_mx r).\n\n(*This lemma establishes that a square matrix is diagonal if and only if it can be constructed from some row vector using the standard diagonal matrix constructor.*)\nLemma diag_mxP n (A : 'M[V]_n) :\n reflect (exists d : 'rV_n, A = diag_mx d) (is_diag_mx A).\n\n(*This lemma states that any matrix created from a vector using the diagonal matrix constructor is, by definition, a diagonal matrix.*)\nLemma diag_mx_is_diag n (r : 'rV[V]_n) : is_diag_mx (diag_mx r).\n\n(*This lemma states that any matrix created from a vector using the diagonal matrix constructor is a triangular matrix.*)\nLemma diag_mx_is_trig n (r : 'rV[V]_n) : is_trig_mx (diag_mx r).\n\nSection ScalarMx.\n\nVariable n : nat.\n\n(*This fact provides an opaque key used internally for the definition of a scalar matrix constructor, ensuring consistent definitional properties.*)\nFact scalar_mx_key : unit. \n(*This definition specifies a function that constructs a square scalar matrix of a given dimension, which is a diagonal matrix where all diagonal entries are equal to a given scalar value.*)\nDefinition scalar_mx x : 'M[V]_n :=\n \\matrix[scalar_mx_key]_(i , j) (x *+ (i == j)).\n(**)\nNotation \"x %:M\" := (scalar_mx x) : ring_scope.\n\n(*This lemma states that creating a diagonal matrix from a constant vector (a vector where all entries are identical) is equivalent to creating a scalar matrix with that constant value.*)\nLemma diag_const_mx a : diag_mx (const_mx a) = a%:M :> 'M_n.\n\n(*This lemma states that any scalar matrix is symmetric, meaning it is equal to its own transpose.*)\nLemma tr_scalar_mx a : (a%:M)^T = a%:M.\n\n(*This lemma states that the function creating a scalar matrix from a ring element is a morphism of semimodules over the natural numbers, meaning it preserves addition and the zero element.*)\nLemma scalar_mx_is_nmod_morphism : nmod_morphism scalar_mx.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `scalar_mx_is_nmod_morphism` instead\")]\n(*This definition, deprecated since mathcomp 2.5.0, states that the function creating a scalar matrix from a ring element preserves the structure of addition and the zero element. It is an alias for scalar_mx_is_nmod_morphism.*)\nDefinition scalar_mx_is_semi_additive := scalar_mx_is_nmod_morphism.\n(*This definition provides a boolean test to determine if a given square matrix is a scalar matrix. A matrix is considered scalar if it is equal to the scalar matrix formed from its top-left diagonal element, or if it has no elements.*)\nDefinition is_scalar_mx (A : 'M[V]_n) :=\n if insub 0 is Some i then A == (A i i)%:M else true.\n\n(*This lemma establishes the equivalence between the boolean test for a scalar matrix and the logical proposition that there exists a ring element such that the matrix is the scalar matrix generated by that element.*)\nLemma is_scalar_mxP A : reflect (exists a, A = a%:M) (is_scalar_mx A).\n\n(*This lemma states that any matrix constructed as a scalar matrix from a given ring element will satisfy the property of being a scalar matrix.*)\nLemma scalar_mx_is_scalar a : is_scalar_mx a%:M.\n\n(*This lemma states that the zero matrix satisfies the property of being a scalar matrix.*)\nLemma mx0_is_scalar : is_scalar_mx 0.\n\n(*This lemma states that any matrix constructed as a scalar matrix from a ring element is also a diagonal matrix.*)\nLemma scalar_mx_is_diag a : is_diag_mx (a%:M).\n\n(*This lemma states that any matrix satisfying the property of being a scalar matrix also satisfies the property of being a diagonal matrix.*)\nLemma is_scalar_mx_is_diag A : is_scalar_mx A -> is_diag_mx A.\n\n(*This lemma states that any matrix constructed as a scalar matrix from a ring element is also a triangular matrix.*)\nLemma scalar_mx_is_trig a : is_trig_mx (a%:M).\n\n(*This lemma states that any matrix satisfying the property of being a scalar matrix also satisfies the property of being a triangular matrix.*)\nLemma is_scalar_mx_is_trig A : is_scalar_mx A -> is_trig_mx A.\n\nEnd ScalarMx.\n\n(*This notation represents the construction of a scalar matrix from a given ring element. The resulting square matrix has the given element on its main diagonal and zero on all other entries.*)\nNotation \"x %:M\" := (scalar_mx _ x) : ring_scope.\n\n(*This lemma states that any one-by-one matrix is equal to the scalar matrix formed from its single element.*)\nLemma mx11_scalar (A : 'M_1) : A = (A 0 0)%:M.\n\n(*This lemma states that a scalar matrix of a composite dimension can be constructed as a block diagonal matrix where the diagonal blocks are smaller scalar matrices of the same scalar value.*)\nLemma scalar_mx_block n1 n2 a : a%:M = block_mx a%:M 0 0 a%:M :> 'M_(n1 + n2).\n\nSection Trace.\n\nVariable n : nat.\n\n(*This definition calculates the trace of a square matrix as the sum of the elements on its main diagonal.*)\nDefinition mxtrace (A : 'M[V]_n) := \\sum_i A i i.\n(**)\nLocal Notation \"'\\tr' A\" := (mxtrace A) : ring_scope.\n\n(*This lemma states that the trace of a square matrix is equal to the trace of its transpose.*)\nLemma mxtrace_tr A : \\tr A^T = \\tr A.\n\n(*This lemma states that the matrix trace function is a morphism of semimodules over the natural numbers, meaning it preserves matrix addition and the zero matrix.*)\nLemma mxtrace_is_nmod_morphism : nmod_morphism mxtrace.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `mxtrace_is_nmod_morphism` instead\")]\n(*This definition, deprecated since mathcomp 2.5.0, states that the matrix trace function preserves matrix addition and the zero matrix. It is an alias for mxtrace_is_nmod_morphism.*)\nDefinition mxtrace_is_semi_additive := mxtrace_is_nmod_morphism.\n(*This lemma states that the trace of a zero matrix is equal to the zero element of the underlying ring.*)\nLemma mxtrace0 : \\tr 0 = 0. \n(*This lemma states that the trace of the sum of two square matrices is equal to the sum of their individual traces.*)\nLemma mxtraceD A B : \\tr (A + B) = \\tr A + \\tr B. \n\n(*This lemma states that the trace of a diagonal matrix constructed from a row vector is equal to the sum of all elements in that vector.*)\nLemma mxtrace_diag D : \\tr (diag_mx D) = \\sum_j D 0 j.\n\n(*This lemma states that the trace of a square scalar matrix of a given dimension is equal to the scalar value multiplied by the dimension of the matrix.*)\nLemma mxtrace_scalar a : \\tr a%:M = a *+ n.\n\nEnd Trace.\n(**)\nLocal Notation \"'\\tr' A\" := (mxtrace A) : ring_scope.\n\n(*This lemma states that the trace of a one-by-one matrix is equal to its single element.*)\nLemma trace_mx11 (A : 'M_1) : \\tr A = A 0 0.\n\n(*This lemma states that the trace of a block matrix is equal to the sum of the traces of its diagonal blocks.*)\nLemma mxtrace_block n1 n2 (Aul : 'M_n1) Aur Adl (Adr : 'M_n2) :\n \\tr (block_mx Aul Aur Adl Adr) = \\tr Aul + \\tr Adr.\n\nEnd MatrixNmodule.\n\nArguments is_diag_mx {V m n}.\nArguments is_diag_mxP {V m n A}.\nArguments is_trig_mx {V m n}.\nArguments is_trig_mxP {V m n A}.\nArguments scalar_mx {V n}.\nArguments is_scalar_mxP {V n A}.\n\nSection MapNmodMatrix.\n\nVariables (aR rR : nmodType) (f : {additive aR -> rR}) (m n : nat).\n(**)\nLocal Notation \"A ^f\" := (map_mx f A) : ring_scope.\nImplicit Type A : 'M[aR]_(m, n).\n\n(*This lemma states that applying an element-wise function, which maps zero to zero, to a zero matrix results in a zero matrix.*)\nLemma map_mx0 : 0^f = 0 :> 'M_(m, n).\n\n(*This lemma states that applying an element-wise additive function to the sum of two matrices is equivalent to the sum of the matrices obtained by applying the function to each matrix individually.*)\nLemma map_mxD A B : (A + B)^f = A^f + B^f.\n\n(*This definition establishes that the element-wise application of an additive function to matrices is a morphism with respect to indexed sums, meaning it distributes over the sum of a collection of matrices.*)\nDefinition map_mx_sum := big_morph _ map_mxD map_mx0.\n\n(*This fact serves as a unique key for the matrix opposition operation within the Hierarchical Builder system.*)\nFact oppmx_key : unit. \n(*This definition provides the additive inverse of a matrix, which is a new matrix where each element is the additive inverse of the corresponding element in the original matrix.*)\nDefinition oppmx := @map_mx V V -%R m n.\n\n(*This lemma establishes that adding a matrix to its additive inverse results in the zero matrix, a key property for defining the module structure on matrices.*)\nLemma addNmx : left_inverse (const_mx 0) oppmx (@addmx V m n).\n\nHB.instance Definition _ := GRing.Nmodule_isZmodule.Build 'M[V]_(m, n)\n addNmx.\n\n(*This lemma asserts that the function that creates a constant matrix from a scalar value is a module morphism, preserving both addition and scalar multiplication.*)\nLemma const_mx_is_zmod_morphism : zmod_morphism const_mx.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `const_mx_is_zmod_morphism` instead\")]\n(*This definition, now deprecated, asserts that the function creating a constant matrix from a scalar is an additive morphism. The recommended replacement is `const_mx_is_zmod_morphism`.*)\nDefinition const_mx_is_additive := const_mx_is_zmod_morphism.\n#[warning=\"-HB.no-new-instance\"]\n(*This lemma asserts that the matrix swizzling operation, which rearranges matrix elements according to given index maps, is a module morphism, preserving both sums and scalar multiples.*)\nLemma swizzle_mx_is_zmod_morphism k : zmod_morphism (swizzle_mx f g k).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `swizzle_mx_is_zmod_morphism` instead\")]\n(*This definition, now deprecated, asserts that the matrix swizzling operation is an additive morphism. The recommended replacement is `swizzle_mx_is_zmod_morphism`.*)\nDefinition swizzle_mx_is_additive := swizzle_mx_is_zmod_morphism.\n#[warning=\"-HB.no-new-instance\"]\n(*A proof tactic designed to prove that two matrices are equal by reducing the goal to showing element-wise equality. It automatically applies the principle that two matrices are equal if and only if all their corresponding entries are equal, setting up subgoals for each entry.*)\nLtac split_mxE := apply/matrixP=> i j; do ![rewrite mxE | case: split => ?].\n\n(*This lemma states that the additive inverse of a horizontally concatenated matrix is equivalent to the horizontal concatenation of the additive inverses of the original matrices.*)\nLemma opp_row_mx m n1 n2 (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n - row_mx A1 A2 = row_mx (- A1) (- A2).\n\n(*This lemma states that the additive inverse of a vertically concatenated matrix is equivalent to the vertical concatenation of the additive inverses of the original matrices.*)\nLemma opp_col_mx m1 m2 n (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n - col_mx A1 A2 = col_mx (- A1) (- A2).\n\n(*This lemma states that the additive inverse of a block matrix is the block matrix composed of the additive inverses of each of the original blocks.*)\nLemma opp_block_mx m1 m2 n1 n2 (Aul : 'M_(m1, n1)) Aur Adl (Adr : 'M_(m2, n2)) :\n - block_mx Aul Aur Adl Adr = block_mx (- Aul) (- Aur) (- Adl) (- Adr).\n\n(*This lemma asserts that the function that constructs a diagonal matrix from a vector is a module morphism, meaning it preserves both vector addition and scalar multiplication.*)\nLemma diag_mx_is_zmod_morphism n : zmod_morphism (@diag_mx V n).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `diag_mx_is_zmod_morphism` instead\")]\n(*This definition, now deprecated, asserts that constructing a diagonal matrix from a vector is an additive morphism. The recommended replacement is `diag_mx_is_zmod_morphism`.*)\nDefinition diag_mx_is_additive := diag_mx_is_zmod_morphism.\n#[warning=\"-HB.no-new-instance\"]\n(*This lemma asserts that the function that creates a scalar matrix from a given scalar value is a module morphism, preserving the module structure.*)\nLemma scalar_mx_is_zmod_morphism : zmod_morphism (@scalar_mx V n).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `scalar_mx_is_zmod_morphism` instead\")]\n(*This definition, now deprecated, asserts that creating a scalar matrix from a scalar value is an additive morphism. The recommended replacement is `scalar_mx_is_zmod_morphism`.*)\nDefinition scalar_mx_is_additive := scalar_mx_is_zmod_morphism.\n#[warning=\"-HB.no-new-instance\"]\n(*This lemma asserts that the matrix trace function is a module morphism, which means that the trace of a sum of matrices is the sum of their traces, and the trace of a scalar multiple of a matrix is the scalar multiple of its trace.*)\nLemma mxtrace_is_zmod_morphism : zmod_morphism (@mxtrace V n).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `mxtrace_is_zmod_morphism` instead\")]\n(*This definition, now deprecated, asserts that the matrix trace function is an additive morphism. The recommended replacement is `mxtrace_is_zmod_morphism`.*)\nDefinition mxtrace_is_additive := mxtrace_is_zmod_morphism.\n#[warning=\"-HB.no-new-instance\"]\n(**)\nLocal Notation \"A ^f\" := (map_mx f A) : ring_scope.\nImplicit Type A : 'M[aR]_(m, n).\n\n(*This lemma states that applying a compatible function element-wise to the additive inverse of a matrix yields the same result as taking the additive inverse of the matrix obtained by applying the function element-wise.*)\nLemma map_mxN A : (- A)^f = - A^f.\n\n(*This lemma states that applying a compatible function element-wise to the difference of two matrices results in the difference of the two matrices after each has been individually subjected to the element-wise function application.*)\nLemma map_mxB A B : (A - B)^f = A^f - B^f.\n\n#[warning=\"-HB.no-new-instance\"]\n(*This fact provides a unique key for the definition of scalar-matrix multiplication, ensuring definitional content is properly isolated.*)\nFact scalemx_key : unit. \n(*This definition specifies scalar-matrix multiplication, which produces a new matrix by multiplying each element of a given matrix by a given scalar.*)\nDefinition scalemx x A := \\matrix[scalemx_key]_(i, j) (x * A i j).\n\n(*This fact provides a unique key for the definition of a delta matrix, ensuring its definitional content is properly isolated.*)\nFact delta_mx_key : unit. \n(*This definition describes a standard basis matrix, which is a matrix containing a one at a specified row and column index and zeros in all other positions.*)\nDefinition delta_mx i0 j0 : 'M[R]_(m, n) :=\n \\matrix[delta_mx_key]_(i, j) ((i == i0) && (j == j0))%:R.\n\n(*A notation for the multiplication of a matrix by a scalar value.*)\nLocal Notation \"x *m: A\" := (scalemx x A) (at level 40) : ring_scope.\n\n(*This lemma states that multiplying any matrix by the scalar one results in the original matrix.*)\nLemma scale1mx A : 1 *m: A = A.\n\n(*This lemma states that scalar multiplication of a matrix is left-distributive over the addition of scalars.*)\nLemma scalemxDl A x y : (x + y) *m: A = x *m: A + y *m: A.\n\n(*This lemma states that scalar multiplication of matrices is right-distributive over the addition of matrices.*)\nLemma scalemxDr x A B : x *m: (A + B) = x *m: A + x *m: B.\n\n(*This lemma expresses an associativity property of scalar multiplication, stating that scaling a matrix by one scalar and then another is equivalent to scaling the matrix by the product of the two scalars.*)\nLemma scalemxA x y A : x *m: (y *m: A) = (x * y) *m: A.\n\nEnd SemiRingModule.\n\n(*This lemma states that the transpose of a standard basis matrix with a one at a given row and column is another standard basis matrix with the row and column indices swapped.*)\nLemma trmx_delta m n i j : (delta_mx i j)^T = delta_mx j i :> 'M[R]_(n, m).\n\n(*This lemma states that a standard basis matrix whose column index is shifted to the left within a larger-width matrix is equivalent to horizontally stacking the original basis matrix with a zero matrix.*)\nLemma delta_mx_lshift m n1 n2 i j :\n delta_mx i (lshift n2 j) = row_mx (delta_mx i j) 0 :> 'M_(m, n1 + n2).\n\n(*This lemma states that a standard basis matrix whose column index is shifted to the right within a larger-width matrix is equivalent to horizontally stacking a zero matrix with the original basis matrix.*)\nLemma delta_mx_rshift m n1 n2 i j :\n delta_mx i (rshift n1 j) = row_mx 0 (delta_mx i j) :> 'M_(m, n1 + n2).\n\n(*This lemma states that a standard basis matrix whose row index is shifted upwards within a taller matrix is equivalent to vertically stacking the original basis matrix with a zero matrix.*)\nLemma delta_mx_ushift m1 m2 n i j :\n delta_mx (lshift m2 i) j = col_mx (delta_mx i j) 0 :> 'M_(m1 + m2, n).\n\n(*This lemma states that a standard basis matrix whose row index is shifted downwards within a taller matrix is equivalent to vertically stacking a zero matrix with the original basis matrix.*)\nLemma delta_mx_dshift m1 m2 n i j :\n delta_mx (rshift m1 i) j = col_mx 0 (delta_mx i j) :> 'M_(m1 + m2, n).\n\n(*This lemma states that converting a standard basis row vector, whose single non-zero entry's position corresponds to a flattened two-dimensional index, into a matrix yields the standard basis matrix at that two-dimensional index.*)\nLemma vec_mx_delta m n i j :\n vec_mx (delta_mx 0 (mxvec_index i j)) = delta_mx i j :> 'M_(m, n).\n\n(*This lemma states that flattening a standard basis matrix into a row vector results in a standard basis row vector, where the position of the non-zero entry corresponds to the flattened index of the original matrix's non-zero entry.*)\nLemma mxvec_delta m n i j :\n mxvec (delta_mx i j) = delta_mx 0 (mxvec_index i j) :> 'rV_(m * n).\n\nLtac split_mxE := apply/matrixP=> i j; do ![rewrite mxE | case: split => ?].\n\n(*A notation for creating a square scalar matrix, which has a given scalar value on its main diagonal and zeros elsewhere.*)\nNotation \"x %:M\" := (scalar_mx x) : ring_scope.\n\n(*This lemma states that the identity matrix is its own transpose.*)\nLemma trmx1 n : (1%:M)^T = 1%:M :> 'M[R]_n. \n\n(*This lemma states that a specified row of an identity matrix is a standard basis row vector with a one at the specified column index.*)\nLemma row1 n i : row i (1%:M : 'M_n) = delta_mx 0 i.\n\n(*This lemma states that a specified column of an identity matrix is a standard basis column vector with a one at the specified row index.*)\nLemma col1 n i : col i (1%:M : 'M_n) = delta_mx i 0.\n\n(*This fact provides a unique key for the definition of matrix multiplication, ensuring its definitional content is properly isolated.*)\nFact mulmx_key : unit. \n(*This definition specifies matrix multiplication, where the element at a given row and column of the resulting matrix is computed as the sum of products of corresponding elements from the same row of the first matrix and the same column of the second matrix.*)\nDefinition mulmx {m n p} (A : 'M_(m, n)) (B : 'M_(n, p)) : 'M[R]_(m, p) :=\n \\matrix[mulmx_key]_(i, k) \\sum_j (A i j * B j k).\n\n(*A notation for the multiplication of two matrices.*)\nLocal Notation \"A *m B\" := (mulmx A B) : ring_scope.\n\n(*This lemma states that matrix multiplication is associative.*)\nLemma mulmxA m n p q (A : 'M_(m, n)) (B : 'M_(n, p)) (C : 'M_(p, q)) :\n A *m (B *m C) = A *m B *m C.\n\n(*This lemma states that multiplying any matrix by a zero matrix on the left results in a zero matrix.*)\nLemma mul0mx m n p (A : 'M_(n, p)) : 0 *m A = 0 :> 'M_(m, p).\n\n(*This lemma states that the product of any matrix with a zero matrix of compatible dimensions results in a zero matrix.*)\nLemma mulmx0 m n p (A : 'M_(m, n)) : A *m 0 = 0 :> 'M_(m, p).\n\n(*This lemma states that matrix multiplication is left-distributive over matrix addition, meaning that multiplying the sum of two matrices by a third matrix is equivalent to the sum of the products of each of the first two matrices with the third.*)\nLemma mulmxDl m n p (A1 A2 : 'M_(m, n)) (B : 'M_(n, p)) :\n (A1 + A2) *m B = A1 *m B + A2 *m B.\n\n(*This lemma states that matrix multiplication is right-distributive over matrix addition, meaning that multiplying a matrix by the sum of two other matrices is equivalent to the sum of the products of the first matrix with each of the other two.*)\nLemma mulmxDr m n p (A : 'M_(m, n)) (B1 B2 : 'M_(n, p)) :\n A *m (B1 + B2) = A *m B1 + A *m B2.\n\n(*This lemma states that multiplying a finite sum of matrices on the right by another matrix is equivalent to the sum of the individual matrix products.*)\nLemma mulmx_suml m n p (A : 'M_(n, p)) I r P (B_ : I -> 'M_(m, n)) :\n (\\sum_(i <- r | P i) B_ i) *m A = \\sum_(i <- r | P i) B_ i *m A.\n\n(*This lemma states that multiplying a matrix on the left by a finite sum of other matrices is equivalent to the sum of the individual matrix products.*)\nLemma mulmx_sumr m n p (A : 'M_(m, n)) I r P (B_ : I -> 'M_(n, p)) :\n A *m (\\sum_(i <- r | P i) B_ i) = \\sum_(i <- r | P i) A *m B_ i.\n\n(*This lemma states that the i-th row of a matrix can be obtained by multiplying the matrix on the left by a standard basis row vector which has a one at the i-th position and zeros elsewhere.*)\nLemma rowE m n i (A : 'M_(m, n)) : row i A = delta_mx 0 i *m A.\n\n(*This lemma states that the i-th column of a matrix can be obtained by multiplying the matrix on the right by a standard basis column vector which has a one at the i-th position and zeros elsewhere.*)\nLemma colE m n i (A : 'M_(m, n)) : col i A = A *m delta_mx i 0.\n\n(*This lemma states that two matrices are equal if and only if their corresponding left-multiplication actions on row vectors produce identical results for all inputs.*)\nLemma mul_rVP m n A B :((@mulmx 1 m n)^~ A =1 mulmx^~ B) <-> (A = B).\n\n(*This lemma states that a specified row of a matrix product is equal to the product of that same row from the left-hand matrix and the entire right-hand matrix.*)\nLemma row_mul m n p (i : 'I_m) A (B : 'M_(n, p)) :\n row i (A *m B) = row i A *m B.\n\n(*This lemma states that a submatrix of a matrix product, defined by selecting a subset of rows and columns, is equal to the product of two matrices: the first being the submatrix of the left factor formed by the selected rows, and the second being the submatrix of the right factor formed by the selected columns.*)\nLemma mxsub_mul m n m' n' p f g (A : 'M_(m, p)) (B : 'M_(p, n)) :\n mxsub f g (A *m B) = rowsub f A *m colsub g B :> 'M_(m', n').\n\n(*This lemma states that taking a submatrix by selecting rows from a matrix and then right-multiplying by a second matrix yields the same result as first multiplying the original matrices and then taking the corresponding row-submatrix from the product.*)\nLemma mul_rowsub_mx m n m' p f (A : 'M_(m, p)) (B : 'M_(p, n)) :\n rowsub f A *m B = rowsub f (A *m B) :> 'M_(m', n).\n\n(*This lemma states that left-multiplying a matrix by a submatrix formed by selecting columns from another matrix yields the same result as first multiplying the original matrices and then taking the corresponding column-submatrix from the product.*)\nLemma mulmx_colsub m n n' p g (A : 'M_(m, p)) (B : 'M_(p, n)) :\n A *m colsub g B = colsub g (A *m B) :> 'M_(m, n').\n\n(*This lemma states that the product of two delta matrices, which are matrices with a single non-zero entry of one, is a new delta matrix scaled by one if the column index of the first matrix matches the row index of the second, and a zero matrix otherwise.*)\nLemma mul_delta_mx_cond m n p (j1 j2 : 'I_n) (i1 : 'I_m) (k2 : 'I_p) :\n delta_mx i1 j1 *m delta_mx j2 k2 = delta_mx i1 k2 *+ (j1 == j2).\n\n(*This lemma states that the product of two delta matrices is another delta matrix, provided the column index of the first matrix is the same as the row index of the second.*)\nLemma mul_delta_mx m n p (j : 'I_n) (i : 'I_m) (k : 'I_p) :\n delta_mx i j *m delta_mx j k = delta_mx i k.\n\n(*This lemma states that the product of two delta matrices is the zero matrix if the column index of the first matrix is different from the row index of the second.*)\nLemma mul_delta_mx_0 m n p (j1 j2 : 'I_n) (i1 : 'I_m) (k2 : 'I_p) :\n j1 != j2 -> delta_mx i1 j1 *m delta_mx j2 k2 = 0.\n\n(*This lemma states that left-multiplying a matrix by a diagonal matrix results in a new matrix where each row of the original matrix is scaled by the corresponding diagonal entry.*)\nLemma mul_diag_mx m n d (A : 'M_(m, n)) :\n diag_mx d *m A = \\matrix_(i, j) (d 0 i * A i j).\n\n(*This lemma states that right-multiplying a matrix by a diagonal matrix results in a new matrix where each column of the original matrix is scaled by the corresponding diagonal entry.*)\nLemma mul_mx_diag m n (A : 'M_(m, n)) d :\n A *m diag_mx d = \\matrix_(i, j) (A i j * d 0 j).\n\n(*This lemma states that the product of two diagonal matrices is another diagonal matrix, whose diagonal entries are the element-wise products of the corresponding entries from the original two diagonal matrices.*)\nLemma mulmx_diag n (d e : 'rV_n) :\n diag_mx d *m diag_mx e = diag_mx (\\row_j (d 0 j * e 0 j)).\n\n(*This lemma states that converting the product of two scalars into a scalar matrix is equivalent to first converting each scalar into a scalar matrix and then computing their matrix product.*)\nLemma scalar_mxM n a b : (a * b)%:M = a%:M *m b%:M :> 'M_n.\n\n(*This lemma states that multiplying any matrix on the left by an identity matrix of compatible dimensions results in the original matrix.*)\nLemma mul1mx m n (A : 'M_(m, n)) : 1%:M *m A = A.\n\n(*This lemma states that multiplying any matrix on the right by an identity matrix of compatible dimensions results in the original matrix.*)\nLemma mulmx1 m n (A : 'M_(m, n)) : A *m 1%:M = A.\n\n(*This lemma states that extracting a submatrix by selecting specific rows from a given matrix is equivalent to left-multiplying that matrix by another matrix formed by selecting the same rows from an identity matrix.*)\nLemma rowsubE m m' n f (A : 'M_(m, n)) :\n rowsub f A = rowsub f 1%:M *m A :> 'M_(m', n).\n\n(*This lemma states that the product of a matrix with permuted columns and a second matrix is equal to the product of the original first matrix and the second matrix with its rows permuted by the inverse permutation.*)\nLemma mul_col_perm m n p s (A : 'M_(m, n)) (B : 'M_(n, p)) :\n col_perm s A *m B = A *m row_perm s^-1 B.\n\n(*This lemma states that the product of a first matrix and a second matrix with permuted rows is equal to the product of the first matrix with its columns permuted by the inverse permutation and the original second matrix.*)\nLemma mul_row_perm m n p s (A : 'M_(m, n)) (B : 'M_(n, p)) :\n A *m row_perm s B = col_perm s^-1 A *m B.\n\n(*This lemma states that multiplying a matrix with two exchanged columns by a second matrix gives the same result as multiplying the original first matrix by the second matrix with its two corresponding rows exchanged.*)\nLemma mul_xcol m n p j1 j2 (A : 'M_(m, n)) (B : 'M_(n, p)) :\n xcol j1 j2 A *m B = A *m xrow j1 j2 B.\n\n(*This definition specifies a permutation matrix as the matrix obtained by applying a given permutation to the rows of an identity matrix.*)\nDefinition perm_mx n s : 'M_n := row_perm s (1%:M : 'M[R]_n).\n\n(*This definition specifies a transposition matrix, which exchanges two rows or columns, as the permutation matrix corresponding to a transposition permutation that swaps two specified indices.*)\nDefinition tperm_mx n i1 i2 : 'M_n := perm_mx (tperm i1 i2).\n\n(*This lemma states that permuting the columns of a matrix according to a given permutation is equivalent to right-multiplying the original matrix by the permutation matrix associated with the inverse of that permutation.*)\nLemma col_permE m n s (A : 'M_(m, n)) : col_perm s A = A *m perm_mx s^-1.\n\n(*This lemma states that permuting the rows of a matrix according to a given permutation is equivalent to left-multiplying the original matrix by the permutation matrix associated with that permutation.*)\nLemma row_permE m n s (A : 'M_(m, n)) : row_perm s A = perm_mx s *m A.\n\n(*This lemma states that exchanging two columns of a matrix is equivalent to right-multiplying the original matrix by the transposition matrix that swaps the two corresponding indices.*)\nLemma xcolE m n j1 j2 (A : 'M_(m, n)) : xcol j1 j2 A = A *m tperm_mx j1 j2.\n\n(*This lemma states that exchanging two rows of a matrix is equivalent to multiplying the matrix on the left by the corresponding transposition permutation matrix.*)\nLemma xrowE m n i1 i2 (A : 'M_(m, n)) : xrow i1 i2 A = tperm_mx i1 i2 *m A.\n\n(*This lemma states that a permutation matrix can be obtained by permuting the rows of the identity matrix according to the given permutation.*)\nLemma perm_mxEsub n s : @perm_mx n s = rowsub s 1%:M.\n\n(*This lemma states that a transposition permutation matrix is equivalent to the identity matrix with its rows permuted according to the corresponding transposition.*)\nLemma tperm_mxEsub n i1 i2 : @tperm_mx n i1 i2 = rowsub (tperm i1 i2) 1%:M.\n\n(*This lemma states that the transpose of a permutation matrix is equal to the permutation matrix corresponding to the inverse permutation.*)\nLemma tr_perm_mx n (s : 'S_n) : (perm_mx s)^T = perm_mx s^-1.\n\n(*This lemma states that a transposition permutation matrix is its own transpose.*)\nLemma tr_tperm_mx n i1 i2 : (tperm_mx i1 i2)^T = tperm_mx i1 i2 :> 'M_n.\n\n(*This lemma states that the permutation matrix associated with the identity permutation is the identity matrix.*)\nLemma perm_mx1 n : perm_mx 1 = 1%:M :> 'M_n.\n\n(*This lemma states that the permutation matrix corresponding to the composition of two permutations is the matrix product of the individual permutation matrices.*)\nLemma perm_mxM n (s t : 'S_n) : perm_mx (s * t) = perm_mx s *m perm_mx t.\n\n(*This definition introduces a predicate that holds for a square matrix if and only if that matrix is a permutation matrix for some permutation.*)\nDefinition is_perm_mx n (A : 'M_n) := [exists s, A == perm_mx s].\n\n(*This lemma provides a boolean reflection, establishing that the predicate for a matrix being a permutation matrix is equivalent to the proposition that there exists a permutation for which the given matrix is the corresponding permutation matrix.*)\nLemma is_perm_mxP n (A : 'M_n) :\n reflect (exists s, A = perm_mx s) (is_perm_mx A).\n\n(*This lemma states that any matrix constructed from a permutation is indeed a permutation matrix.*)\nLemma perm_mx_is_perm n (s : 'S_n) : is_perm_mx (perm_mx s).\n\n(*This lemma states that the identity matrix is a permutation matrix.*)\nLemma is_perm_mx1 n : is_perm_mx (1%:M : 'M_n).\n\n(*This lemma states that if a matrix is a permutation matrix, then multiplying it on the left with another matrix results in a permutation matrix if and only if the second matrix is also a permutation matrix.*)\nLemma is_perm_mxMl n (A B : 'M_n) :\n is_perm_mx A -> is_perm_mx (A *m B) = is_perm_mx B.\n\n(*This lemma states that a matrix is a permutation matrix if and only if its transpose is also a permutation matrix.*)\nLemma is_perm_mx_tr n (A : 'M_n) : is_perm_mx A^T = is_perm_mx A.\n\n(*This lemma states that if a matrix is a permutation matrix, then multiplying it on the right with another matrix results in a permutation matrix if and only if the first matrix is also a permutation matrix.*)\nLemma is_perm_mxMr n (A B : 'M_n) :\n is_perm_mx B -> is_perm_mx (A *m B) = is_perm_mx A.\n\n(*This fact serves as an opaque key for defining partial identity matrices, ensuring that their internal representation is abstract.*)\nFact pid_mx_key : unit. \n(*This definition constructs a partial identity matrix of a given size, where the entries are one on the main diagonal up to a specified row index and zero everywhere else.*)\nDefinition pid_mx {m n} r : 'M[R]_(m, n) :=\n \\matrix[pid_mx_key]_(i, j) ((i == j :> nat) && (i < r))%:R.\n\n(*This lemma states that a partial identity matrix with a range of zero is equal to the zero matrix.*)\nLemma pid_mx_0 m n : pid_mx 0 = 0 :> 'M_(m, n).\n\n(*This lemma states that a partial identity matrix of range r is equivalent to the identity matrix of size r by r.*)\nLemma pid_mx_1 r : pid_mx r = 1%:M :> 'M_r.\n\n(*This lemma states that a partial identity matrix can be represented as a row block matrix composed of an identity matrix and a zero matrix.*)\nLemma pid_mx_row n r : pid_mx r = row_mx 1%:M 0 :> 'M_(r, r + n).\n\n(*This lemma states that a partial identity matrix can be represented as a column block matrix composed of an identity matrix and a zero matrix.*)\nLemma pid_mx_col m r : pid_mx r = col_mx 1%:M 0 :> 'M_(r + m, r).\n\n(*This lemma states that a partial identity matrix can be represented as a block matrix with an identity matrix in the top-left block and zero matrices in the other three blocks.*)\nLemma pid_mx_block m n r : pid_mx r = block_mx 1%:M 0 0 0 :> 'M_(r + m, r + n).\n\n(*This lemma states that the transpose of a partial identity matrix is the same partial identity matrix with transposed dimensions.*)\nLemma tr_pid_mx m n r : (pid_mx r)^T = pid_mx r :> 'M_(n, m).\n\n(*This lemma states that for a matrix with m rows, a partial identity matrix of range r is equivalent to a partial identity matrix whose range is the minimum of m and r.*)\nLemma pid_mx_minv m n r : pid_mx (minn m r) = pid_mx r :> 'M_(m, n).\n\n(*This lemma states that for a matrix with n columns, a partial identity matrix of range r is equivalent to a partial identity matrix whose range is the minimum of n and r.*)\nLemma pid_mx_minh m n r : pid_mx (minn n r) = pid_mx r :> 'M_(m, n).\n\n(*This lemma states that the matrix product of two compatible partial identity matrices is a partial identity matrix whose range is the minimum of the two original ranges and their common dimension.*)\nLemma mul_pid_mx m n p q r :\n (pid_mx q : 'M_(m, n)) *m (pid_mx r : 'M_(n, p)) = pid_mx (minn n (minn q r)).\n\n(*This lemma states that under certain dimension constraints, the matrix product of a partial identity matrix with itself is the same partial identity matrix.*)\nLemma pid_mx_id m n p r :\n r <= n -> (pid_mx r : 'M_(m, n)) *m (pid_mx r : 'M_(n, p)) = pid_mx r.\n\n(*This lemma states that when its range equals its number of rows, and this is less than or equal to its number of columns, a partial identity matrix can be obtained by applying a row substitution to a larger identity matrix.*)\nLemma pid_mxErow m n (le_mn : m <= n) :\n pid_mx m = rowsub (widen_ord le_mn) 1%:M.\n\n(*This lemma states that a partial identity matrix of a given rectangular size can be obtained by applying a column substitution based on an order-widening map to a square identity matrix.*)\nLemma pid_mxEcol m n (le_mn : m <= n) :\n pid_mx n = colsub (widen_ord le_mn) 1%:M.\n\n(*This lemma states that left-multiplying a row-block matrix by another matrix is equivalent to forming a new row-block matrix where each block is the result of the left-multiplication on the original corresponding block.*)\nLemma mul_mx_row m n p1 p2 (A : 'M_(m, n)) (Bl : 'M_(n, p1)) (Br : 'M_(n, p2)) :\n A *m row_mx Bl Br = row_mx (A *m Bl) (A *m Br).\n\n(*This lemma states that right-multiplying a column-block matrix by another matrix is equivalent to forming a new column-block matrix where each block is the result of the right-multiplication on the original corresponding block.*)\nLemma mul_col_mx m1 m2 n p (Au : 'M_(m1, n)) (Ad : 'M_(m2, n)) (B : 'M_(n, p)) :\n col_mx Au Ad *m B = col_mx (Au *m B) (Ad *m B).\n\n(*This lemma states that multiplying a one-by-two row-block matrix by a two-by-one column-block matrix yields the sum of the products of their corresponding blocks.*)\nLemma mul_row_col m n1 n2 p (Al : 'M_(m, n1)) (Ar : 'M_(m, n2))\n (Bu : 'M_(n1, p)) (Bd : 'M_(n2, p)) :\n row_mx Al Ar *m col_mx Bu Bd = Al *m Bu + Ar *m Bd.\n\n(*This lemma states that the product of a two-by-one column-block matrix and a one-by-two row-block matrix results in a two-by-two block matrix, where each block is the product of the corresponding blocks from the input matrices.*)\nLemma mul_col_row m1 m2 n p1 p2 (Au : 'M_(m1, n)) (Ad : 'M_(m2, n))\n (Bl : 'M_(n, p1)) (Br : 'M_(n, p2)) :\n col_mx Au Ad *m row_mx Bl Br\n = block_mx (Au *m Bl) (Au *m Br) (Ad *m Bl) (Ad *m Br).\n\n(*This lemma describes the multiplication of a one-by-two row-block matrix and a two-by-two block matrix, resulting in a new one-by-two row-block matrix computed using the standard rules of block matrix multiplication.*)\nLemma mul_row_block m n1 n2 p1 p2 (Al : 'M_(m, n1)) (Ar : 'M_(m, n2))\n (Bul : 'M_(n1, p1)) (Bur : 'M_(n1, p2))\n (Bdl : 'M_(n2, p1)) (Bdr : 'M_(n2, p2)) :\n row_mx Al Ar *m block_mx Bul Bur Bdl Bdr\n = row_mx (Al *m Bul + Ar *m Bdl) (Al *m Bur + Ar *m Bdr).\n\n(*This lemma describes the multiplication of a two-by-two block matrix and a two-by-one column-block matrix, resulting in a new two-by-one column-block matrix computed using the standard rules of block matrix multiplication.*)\nLemma mul_block_col m1 m2 n1 n2 p (Aul : 'M_(m1, n1)) (Aur : 'M_(m1, n2))\n (Adl : 'M_(m2, n1)) (Adr : 'M_(m2, n2))\n (Bu : 'M_(n1, p)) (Bd : 'M_(n2, p)) :\n block_mx Aul Aur Adl Adr *m col_mx Bu Bd\n = col_mx (Aul *m Bu + Aur *m Bd) (Adl *m Bu + Adr *m Bd).\n\n(*This lemma provides the general formula for the product of two two-by-two block matrices, stating that the resulting two-by-two block matrix is computed by following the standard rules of block matrix multiplication.*)\nLemma mulmx_block m1 m2 n1 n2 p1 p2 (Aul : 'M_(m1, n1)) (Aur : 'M_(m1, n2))\n (Adl : 'M_(m2, n1)) (Adr : 'M_(m2, n2))\n (Bul : 'M_(n1, p1)) (Bur : 'M_(n1, p2))\n (Bdl : 'M_(n2, p1)) (Bdr : 'M_(n2, p2)) :\n block_mx Aul Aur Adl Adr *m block_mx Bul Bur Bdl Bdr\n = block_mx (Aul *m Bul + Aur *m Bdl) (Aul *m Bur + Aur *m Bdr)\n (Adl *m Bul + Adr *m Bdl) (Adl *m Bur + Adr *m Bdr).\n\n(*This lemma states that left-multiplying the left submatrix of a given matrix is equivalent to taking the left submatrix of the product of the original matrices.*)\nLemma mulmx_lsub m n p k (A : 'M_(m, n)) (B : 'M_(n, p + k)) :\n A *m lsubmx B = lsubmx (A *m B).\n\n(*This lemma states that left-multiplying the right submatrix of a given matrix is equivalent to taking the right submatrix of the product of the original matrices.*)\nLemma mulmx_rsub m n p k (A : 'M_(m, n)) (B : 'M_(n, p + k)) :\n A *m rsubmx B = rsubmx (A *m B).\n\n(*This lemma states that right-multiplying the upper submatrix of a given matrix is equivalent to taking the upper submatrix of the product of the original matrices.*)\nLemma mul_usub_mx m k n p (A : 'M_(m + k, n)) (B : 'M_(n, p)) :\n usubmx A *m B = usubmx (A *m B).\n\n(*This lemma states that right-multiplying the lower submatrix of a given matrix is equivalent to taking the lower submatrix of the product of the original matrices.*)\nLemma mul_dsub_mx m k n p (A : 'M_(m + k, n)) (B : 'M_(n, p)) :\n dsubmx A *m B = dsubmx (A *m B).\n\nSection Trace.\n\nVariable n : nat.\nLocal Notation \"'\\tr' A\" := (mxtrace A) : ring_scope.\n\n(*This lemma states that the trace of an n-by-n identity matrix is equal to the ring element corresponding to the natural number n.*)\nLemma mxtrace1 : \\tr (1%:M : 'M[R]_n) = n%:R. \n\nEnd Trace.\n\nSection MatrixSemiRing.\n\nVariable n : nat.\n\nHB.instance Definition _ := GRing.Nmodule_isPzSemiRing.Build 'M[R]_n\n (@mulmxA n n n n) (@mul1mx n n) (@mulmx1 n n)\n (@mulmxDl n n n) (@mulmxDr n n n) (@mul0mx n n n) (@mulmx0 n n n).\n\n(*This lemma states that the matrix multiplication operation is equivalent to the ring multiplication operation within the matrix ring scope.*)\nLemma mulmxE : mulmx = *%R. \n(*This lemma states that the n-by-n identity matrix is equivalent to the multiplicative identity element of the n-by-n matrix ring.*)\nLemma idmxE : 1%:M = 1 :> 'M_n. \n\n(*This lemma asserts that the function that maps a ring element to its corresponding scalar matrix is a monoid morphism, meaning it preserves the multiplicative identity and the multiplication operation.*)\nLemma scalar_mx_is_monoid_morphism : monoid_morphism (@scalar_mx R n).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `scalar_mx_is_monoid_morphism` instead\")]\n(*This definition provides a deprecated alias for the lemma stating that the scalar matrix embedding is a monoid morphism.*)\nDefinition scalar_mx_is_multiplicative := scalar_mx_is_monoid_morphism.\n(*This definition constructs a new permutation on a set of size n plus one from a permutation on a set of size n by lifting it to fix the element zero.*)\nDefinition lift0_perm s : 'S_n.+1 := lift_perm 0 0 s.\n\n(*This lemma states that the permutation resulting from lifting another permutation to fix zero will map zero to itself.*)\nLemma lift0_perm0 s : lift0_perm s 0 = 0.\n\n(*This lemma describes how the lifted permutation that fixes zero interacts with other lifted elements, showing that applying the lifted permutation to a shifted element is equivalent to applying the original permutation and then shifting the result.*)\nLemma lift0_perm_lift s k' :\n lift0_perm s (lift 0 k') = lift (0 : 'I_n.+1) (s k').\n\n(*This lemma states that the lifted permutation that fixes zero is cancellable, meaning its composition with the lifted inverse permutation results in the identity permutation.*)\nLemma lift0_permK s : cancel (lift0_perm s) (lift0_perm s^-1).\n\n(*This lemma states that the lifted permutation which fixes zero maps an element to zero if and only if that element is itself zero.*)\nLemma lift0_perm_eq0 s i : (lift0_perm s i == 0) = (i == 0).\n\n(*This definition constructs a block matrix of size n plus one from a matrix of size n by placing a one in the top-left corner, the original matrix in the bottom-right block, and zero matrices elsewhere.*)\nDefinition lift0_mx A : 'M_(1 + n) := block_mx 1 0 0 A.\n\n(*This lemma states that lifting a permutation matrix by creating a block diagonal matrix with a one is equivalent to creating a permutation matrix from the corresponding lifted permutation that fixes zero.*)\nLemma lift0_mx_perm s : lift0_mx (perm_mx s) = perm_mx (lift0_perm s).\n\n(*This lemma asserts that lifting a permutation matrix by creating a block diagonal matrix with a one results in another valid permutation matrix.*)\nLemma lift0_mx_is_perm s : is_perm_mx (lift0_mx (perm_mx s)).\n\nEnd LiftPerm.\n\n(*This lemma states that raising a block diagonal matrix to a natural number power is equivalent to creating a new block diagonal matrix where each original block has been raised to that same power.*)\nLemma exp_block_diag_mx m n (A: 'M_m.+1) (B : 'M_n.+1) k :\n (block_mx A 0 0 B) ^+ k = block_mx (A ^+ k) 0 0 (B ^+ k).\n\nEnd MatrixAlgebra.\n\nArguments delta_mx {R m n}.\nArguments perm_mx {R n}.\nArguments tperm_mx {R n}.\nArguments pid_mx {R m n}.\nPrenex Implicits diag_mx is_scalar_mx.\nPrenex Implicits mulmx mxtrace.\n\nArguments mul_delta_mx {R m n p}.\n\n#[global] Hint Extern 0 (is_true (is_diag_mx (scalar_mx _))) =>\n apply: scalar_mx_is_diag : core.\n#[global] Hint Extern 0 (is_true (is_trig_mx (scalar_mx _))) =>\n apply: scalar_mx_is_trig : core.\n#[global] Hint Extern 0 (is_true (is_diag_mx (diag_mx _))) =>\n apply: diag_mx_is_diag : core.\n#[global] Hint Extern 0 (is_true (is_trig_mx (diag_mx _))) =>\n apply: diag_mx_is_trig : core.\n\n(*This notation represents the creation of a scalar matrix from a given ring element, where the ring element is placed on the main diagonal and all other entries are zero.*)\nNotation \"a %:M\" := (scalar_mx a) : ring_scope.\n(*This notation represents the multiplication of two matrices.*)\nNotation \"A *m B\" := (mulmx A B) : ring_scope.\n(*This notation represents the trace of a square matrix, which is the sum of the elements on its main diagonal.*)\nNotation \"\\tr A\" := (mxtrace A) : ring_scope.\n\n(*This lemma states that the transpose of the product of two matrices is equal to the product of their transposes in the reverse order, taking into account the potentially non-commutative nature of the underlying ring.*)\nLemma trmx_mul_rev (R : pzSemiRingType) m n p\n (A : 'M[R]_(m, n)) (B : 'M[R]_(n, p)) :\n (A *m B)^T = (B : 'M[R^c]_(n, p))^T *m (A : 'M[R^c]_(m, n))^T.\n\nSection MatrixNzSemiRing.\n\nVariables (R : nzSemiRingType) (n' : nat).\n(*A local notation defining `n` as the successor of another natural number, equivalent to that number plus one. This is typically used in inductive proofs where `n` represents a size.*)\nLocal Notation n := n'.+1.\n\n(*This lemma states that for any positive dimension, the identity matrix over a non-zero semiring is not equal to the zero matrix.*)\nLemma matrix_nonzero1 : 1%:M != 0 :> 'M[R]_n.\n\n(*A local notation for the type of matrices with `m` rows and `n` columns, having entries of type `V`.*)\nLocal Notation MV := 'M[V]_(m, n).\n\n(**)\nLocal Notation \"A ^f\" := (map_mx f A) : ring_scope.\n\nSection FixedSize.\n\nVariables m n p : nat.\nImplicit Type A : 'M[aR]_(m, n).\n\n(*This lemma states that applying a ring morphism entry-wise to the product of two matrices gives the same result as first applying the morphism entry-wise to each matrix and then multiplying the resulting matrices.*)\nLemma map_mxM A B : (A *m B)^f = A^f *m B^f :> 'M_(m, p).\n\n(*This lemma states that applying a ring morphism entry-wise to a delta matrix, which is a matrix with a single entry equal to one and all others zero, results in the same delta matrix.*)\nLemma map_delta_mx i j : (delta_mx i j)^f = delta_mx i j :> 'M_(m, n).\n\n(*This lemma states that mapping a ring morphism over a diagonal matrix is equivalent to constructing a diagonal matrix from a vector where the morphism has been applied to each element of the original vector.*)\nLemma map_diag_mx d : (diag_mx d)^f = diag_mx d^f :> 'M_n.\n\n(*This lemma states that applying a ring morphism entry-wise to a scalar matrix is equivalent to creating a new scalar matrix where the scalar is the result of applying the morphism to the original scalar.*)\nLemma map_scalar_mx a : a%:M^f = (f a)%:M :> 'M_n.\n\n(*This lemma states that applying a ring morphism entry-wise to an identity matrix results in the identity matrix.*)\nLemma map_mx1 : 1%:M^f = 1%:M :> 'M_n.\n\n(*This lemma states that applying a ring morphism entry-wise to a permutation matrix leaves the matrix unchanged.*)\nLemma map_perm_mx (s : 'S_n) : (perm_mx s)^f = perm_mx s.\n\n(*This lemma states that applying a ring morphism entry-wise to a transposition permutation matrix does not change the matrix.*)\nLemma map_tperm_mx (i1 i2 : 'I_n) : (tperm_mx i1 i2)^f = tperm_mx i1 i2.\n\n(*This lemma states that applying a ring morphism entry-wise to a partial identity matrix, which is a rectangular matrix with ones on its main diagonal and zeros elsewhere, results in the same matrix.*)\nLemma map_pid_mx r : (pid_mx r)^f = pid_mx r :> 'M_(m, n).\n\n(*This lemma states that the trace of a matrix obtained by applying a ring morphism to each entry is equal to the result of applying the morphism to the trace of the original matrix.*)\nLemma trace_map_mx (A : 'M_n) : \\tr A^f = f (\\tr A).\n\nEnd FixedSize.\n\n(*This lemma states that the function which applies a given ring morphism to each entry of a square matrix is a monoid morphism, meaning it preserves both matrix multiplication and the identity matrix.*)\nLemma map_mx_is_monoid_morphism n : monoid_morphism (map_mx f : 'M_n -> 'M_n).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `map_mx_is_monoid_morphism` instead\")]\n(*This definition asserts that the function applying a ring morphism to each entry of a square matrix is multiplicative, meaning it preserves the structure of matrix multiplication. This is a deprecated alias for a more general statement about monoid morphisms.*)\nDefinition map_mx_is_multiplicative := map_mx_is_monoid_morphism.\n(*This definition introduces the property that two square matrices commute, which holds if multiplying them in one order produces the same result as multiplying them in the reverse order.*)\nDefinition comm_mx f g : Prop := f *m g = g *m f.\n(*This definition provides a boolean test to determine if two square matrices commute. It returns true if their product is the same regardless of the order of multiplication, and false otherwise.*)\nDefinition comm_mxb f g : bool := f *m g == g *m f.\n\n(*This lemma states that matrix commutation is a symmetric relation; if a first matrix commutes with a second one, then the second matrix also commutes with the first.*)\nLemma comm_mx_sym f g : comm_mx f g -> comm_mx g f.\n\n(*This lemma states that any square matrix commutes with itself, meaning matrix commutation is a reflexive relation.*)\nLemma comm_mx_refl f : comm_mx f f. \n\n(*This lemma states that any square matrix commutes with the zero matrix.*)\nLemma comm_mx0 f : comm_mx f 0. \n(*This lemma states that the zero matrix commutes with any given square matrix.*)\nLemma comm0mx f : comm_mx 0 f. \n\n(*This lemma states that any square matrix commutes with the identity matrix.*)\nLemma comm_mx1 f : comm_mx f 1%:M.\n\n(*This lemma states that the identity matrix commutes with any given square matrix.*)\nLemma comm1mx f : comm_mx 1%:M f.\n\nHint Resolve comm_mx0 comm0mx comm_mx1 comm1mx : core.\n\n(*This lemma states that if a square matrix commutes with two other matrices individually, then it also commutes with their sum.*)\nLemma comm_mxD f g g' : comm_mx f g -> comm_mx f g' -> comm_mx f (g + g').\n\n(*This lemma states that if a square matrix commutes with two other matrices individually, then it also commutes with their product.*)\nLemma comm_mxM f g g' : comm_mx f g -> comm_mx f g' -> comm_mx f (g *m g').\n\n(*This lemma states that if a square matrix commutes with every matrix generated by a function over a filtered sequence, then it also commutes with the sum of all those matrices.*)\nLemma comm_mx_sum I (s : seq I) (P : pred I) (F : I -> 'M[R]_n) (f : 'M[R]_n) :\n (forall i : I, P i -> comm_mx f (F i)) -> comm_mx f (\\sum_(i <- s | P i) F i).\n\n(*This lemma establishes that the boolean test for matrix commutativity is logically equivalent to the propositional property of matrix commutativity.*)\nLemma comm_mxP f g : reflect (comm_mx f g) (comm_mxb f g).\n\nNotation all_comm_mx fs := (all2rel comm_mxb fs).\n\n(*This lemma establishes the equivalence between the boolean test checking if all pairs of matrices in a given sequence commute and the logical proposition that every pair of matrices from that sequence commutes.*)\nLemma all_comm_mxP fs :\n reflect {in fs &, forall f g, f *m g = g *m f} (all_comm_mx fs).\n\n(*This lemma states that a sequence containing a single matrix satisfies the property of pairwise commutation.*)\nLemma all_comm_mx1 f : all_comm_mx [:: f].\n\n(*This lemma shows that for a sequence of two matrices, testing for pairwise commutativity is equivalent to testing if those two matrices commute with each other.*)\nLemma all_comm_mx2P f g : reflect (f *m g = g *m f) (all_comm_mx [:: f; g]).\n\n(*This lemma provides a recursive characterization for the pairwise commutativity of a sequence of matrices, stating that a matrix prepended to a sequence results in a pairwise commuting sequence if and only if the new matrix commutes with all original elements and the original sequence was already pairwise commuting.*)\nLemma all_comm_mx_cons f fs :\n all_comm_mx (f :: fs) = all (comm_mxb f) fs && all_comm_mx fs.\n\n(*This lemma states that the property of matrix commutativity is an instance of the general commutativity property defined for rings.*)\nLemma comm_mxE : comm_mx = @GRing.comm _. \n\nEnd CommMx.\n(*This notation defines a function that accepts a sequence of square matrices and returns a boolean value indicating whether every matrix in the sequence commutes with every other matrix in the same sequence.*)\nNotation all_comm_mx := (allrel comm_mxb).\n\nSection ComMatrix.\n\nVariable R : comPzSemiRingType.\n\nSection AssocLeft.\n\nVariables m n p : nat.\nImplicit Type A : 'M[R]_(m, n).\nImplicit Type B : 'M[R]_(n, p).\n\n(*This lemma states that the transpose of the product of two matrices is equal to the product of their transposes in the reverse order.*)\nLemma trmx_mul A B : (A *m B)^T = B^T *m A^T.\n\nEnd AssocLeft.\n\n(*This lemma states that the multiplication of two diagonal matrices, formed from two given row vectors, is commutative.*)\nLemma diag_mxC n (d e : 'rV[R]_n) :\n diag_mx d *m diag_mx e = diag_mx e *m diag_mx d.\n\n(*This lemma asserts that any two diagonal matrices, constructed from row vectors of the same size, commute with each other under matrix multiplication.*)\nLemma diag_mx_comm n (d e : 'rV[R]_n) : comm_mx (diag_mx d) (diag_mx e).\n\n(*This lemma states that any matrix commutes with a scalar matrix under matrix multiplication, where the size of the scalar matrix is inferred appropriately for each side of the multiplication.*)\nLemma scalar_mxC m n a (A : 'M[R]_(m, n)) : A *m a%:M = a%:M *m A.\n\n(*This lemma asserts that any square matrix commutes with a scalar matrix of the same size under matrix multiplication.*)\nLemma comm_mx_scalar n a (A : 'M[R]_n) : comm_mx A a%:M.\n\n(*This lemma asserts that any scalar matrix commutes with a square matrix of the same size under matrix multiplication.*)\nLemma comm_scalar_mx n a (A : 'M[R]_n) : comm_mx a%:M A.\n\n(*This lemma states that the trace of the product of two matrices is invariant under cyclic permutation of the matrices, that is, the trace of a matrix product A B is equal to the trace of the product B A.*)\nLemma mxtrace_mulC m n (A : 'M[R]_(m, n)) B : \\tr (A *m B) = \\tr (B *m A).\n\nEnd ComMatrix.\n\nArguments comm_mx_scalar {R n}.\nArguments comm_scalar_mx {R n}.\nArguments diag_mx_comm {R n}.\n\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (R : finComNzSemiRingType) (n' : nat) :=\n [Finite of 'M[R]_n'.+1 by <:].\n\n#[global] Hint Resolve comm_mx_scalar comm_scalar_mx : core.\n\nSection MatrixAlgebra.\n\nVariable R : pzRingType.\n\nSection RingModule.\n\nVariables m n : nat.\nImplicit Types A B : 'M[R]_(m, n).\n\n(*This lemma states that scaling a constant matrix by a scalar value is equivalent to creating a new constant matrix whose entries are the product of the scalar and the original constant value.*)\nLemma scalemx_const a b : a *: const_mx b = const_mx (a * b).\n\n(*This lemma states that any matrix can be expressed as a linear combination of the standard basis matrices, where each basis matrix is scaled by the corresponding entry from the original matrix.*)\nLemma matrix_sum_delta A :\n A = \\sum_(i < m) \\sum_(j < n) A i j *: delta_mx i j.\n\nEnd RingModule.\n\nSection StructuralLinear.\n\n(*This lemma asserts that the generic matrix-swizzling operation, which rearranges the elements of a matrix according to given index-mapping functions, is a scalable function, meaning it commutes with scalar multiplication.*)\nLemma swizzle_mx_is_scalable m n p q f g k :\n scalable (@swizzle_mx R m n p q f g k).\n\nHB.instance Definition _ m n p q f g k :=\n GRing.isScalable.Build R 'M[R]_(m, n) 'M[R]_(p, q) *:%R (swizzle_mx f g k)\n (swizzle_mx_is_scalable f g k).\n\nLocal Notation SwizzleLin op := (GRing.Linear.copy op (swizzle_mx _ _ _)).\n\nHB.instance Definition _ m n := SwizzleLin (@trmx R m n).\nHB.instance Definition _ m n i := SwizzleLin (@row R m n i).\nHB.instance Definition _ m n j := SwizzleLin (@col R m n j).\nHB.instance Definition _ m n i := SwizzleLin (@row' R m n i).\nHB.instance Definition _ m n j := SwizzleLin (@col' R m n j).\nHB.instance Definition _ m n m' n' f g := SwizzleLin (@mxsub R m n m' n' f g).\nHB.instance Definition _ m n s := SwizzleLin (@row_perm R m n s).\nHB.instance Definition _ m n s := SwizzleLin (@col_perm R m n s).\nHB.instance Definition _ m n i1 i2 := SwizzleLin (@xrow R m n i1 i2).\nHB.instance Definition _ m n j1 j2 := SwizzleLin (@xcol R m n j1 j2).\nHB.instance Definition _ m n1 n2 := SwizzleLin (@lsubmx R m n1 n2).\nHB.instance Definition _ m n1 n2 := SwizzleLin (@rsubmx R m n1 n2).\nHB.instance Definition _ m1 m2 n := SwizzleLin (@usubmx R m1 m2 n).\nHB.instance Definition _ m1 m2 n := SwizzleLin (@dsubmx R m1 m2 n).\n\nHB.instance Definition _ m n := SwizzleLin (@vec_mx R m n).\n(*This definition establishes that the operation of converting a matrix into a flattened row vector is scalable, meaning that scaling the input matrix by a scalar results in scaling the output vector by the same scalar.*)\nDefinition mxvec_is_scalable m n := can2_scalable (@vec_mxK R m n) mxvecK.\n(*This lemma states that any row vector can be expressed as a linear combination of the standard basis row vectors, where each basis vector is scaled by the corresponding entry from the original vector.*)\nLemma row_sum_delta n (u : 'rV_n) : u = \\sum_(j < n) u 0 j *: delta_mx 0 j.\n\n(*This is a tactic for proving the equality of two matrices by applying the principle of pointwise equality and then simplifying the resulting goal for each matrix entry.*)\nLtac split_mxE := apply/matrixP=> i j; do ![rewrite mxE | case: split => ?].\n\n(*This lemma states that scaling a horizontally-concatenated matrix by a scalar is equivalent to horizontally concatenating the individual matrices after each has been scaled by the same scalar.*)\nLemma scale_row_mx m n1 n2 a (A1 : 'M_(m, n1)) (A2 : 'M_(m, n2)) :\n a *: row_mx A1 A2 = row_mx (a *: A1) (a *: A2).\n\n(*This lemma states that scaling a vertically-concatenated matrix by a scalar is equivalent to vertically concatenating the individual matrices after each has been scaled by the same scalar.*)\nLemma scale_col_mx m1 m2 n a (A1 : 'M_(m1, n)) (A2 : 'M_(m2, n)) :\n a *: col_mx A1 A2 = col_mx (a *: A1) (a *: A2).\n\n(*This lemma states that scaling a two-by-two block matrix by a scalar is equivalent to constructing a new block matrix from the four sub-matrices, each scaled by that same scalar.*)\nLemma scale_block_mx m1 m2 n1 n2 a (Aul : 'M_(m1, n1)) (Aur : 'M_(m1, n2))\n (Adl : 'M_(m2, n1)) (Adr : 'M_(m2, n2)) :\n a *: block_mx Aul Aur Adl Adr\n = block_mx (a *: Aul) (a *: Aur) (a *: Adl) (a *: Adr).\n\n(*This lemma asserts that the function that constructs a diagonal matrix from a vector is a linear map.*)\nLemma diag_mx_is_linear n : linear (@diag_mx R n).\n\nHB.instance Definition _ n :=\n GRing.isSemilinear.Build R 'rV_n 'M_n _ (@diag_mx _ n)\n (GRing.semilinear_linear (@diag_mx_is_linear n)).\n\n(*This lemma states that a diagonal matrix can be expressed as a sum of scaled standard basis matrices, where each basis matrix with a one on the diagonal is scaled by the corresponding entry from the input vector.*)\nLemma diag_mx_sum_delta n (d : 'rV_n) :\n diag_mx d = \\sum_i d 0 i *: delta_mx i i.\n\n(*This lemma states that the i-th row of a diagonal matrix constructed from a vector is a row vector containing a single non-zero entry at the i-th column, which is the i-th element of the input vector.*)\nLemma row_diag_mx n (d : 'rV_n) i : row i (diag_mx d) = d 0 i *: delta_mx 0 i.\n\n(*This lemma states that scaling a scalar matrix by a given scalar value results in a new scalar matrix whose diagonal entries are the product of the original scalar and the scaling factor.*)\nLemma scale_scalar_mx n a1 a2 : a1 *: a2%:M = (a1 * a2)%:M :> 'M_n.\n\n(*This lemma states that scaling the identity matrix by a scalar value produces a scalar matrix with that value along its diagonal.*)\nLemma scalemx1 n a : a *: 1%:M = a%:M :> 'M_n.\n\n(*This lemma states that a scalar matrix can be expressed as a scaled sum of the standard diagonal basis matrices, where each basis matrix is scaled by the scalar value.*)\nLemma scalar_mx_sum_delta n a : a%:M = \\sum_i a *: delta_mx i i :> 'M_n.\n\n(*This lemma states that the identity matrix is equal to the sum of the standard diagonal basis matrices.*)\nLemma mx1_sum_delta n : 1%:M = \\sum_i delta_mx i i :> 'M[R]_n.\n\n(*This lemma states that multiplying a matrix by the additive inverse of a second matrix is equivalent to taking the additive inverse of their product.*)\nLemma mulmxN m n p (A : 'M[R]_(m, n)) (B : 'M_(n, p)) : A *m (- B) = - (A *m B).\n\n(*This lemma states that multiplying the additive inverse of a matrix by a second matrix is equivalent to taking the additive inverse of their product.*)\nLemma mulNmx m n p (A : 'M[R]_(m, n)) (B : 'M_(n, p)) : - A *m B = - (A *m B).\n\n(*This lemma states the right-distributive property of matrix multiplication over matrix subtraction, showing that the product of a matrix difference and another matrix is equal to the difference of their individual products.*)\nLemma mulmxBl m n p (A1 A2 : 'M[R]_(m, n)) (B : 'M_(n, p)) :\n (A1 - A2) *m B = A1 *m B - A2 *m B.\n\n(*This lemma states the left-distributive property of matrix multiplication over matrix subtraction, showing that the product of a matrix with a matrix difference is equal to the difference of their individual products.*)\nLemma mulmxBr m n p (A : 'M[R]_(m, n)) (B1 B2 : 'M_(n, p)) :\n A *m (B1 - B2) = A *m B1 - A *m B2.\n\n(*This lemma shows that scalar multiplication associates with matrix multiplication on the left, meaning that scaling a matrix product by a scalar is equivalent to scaling the left matrix factor before multiplying.*)\nLemma scalemxAl m n p a (A : 'M_(m, n)) (B : 'M_(n, p)) :\n a *: (A *m B) = (a *: A) *m B.\n\n(*This lemma states that the product of a row vector and a matrix is equal to the linear combination of the rows of the matrix, where the coefficients of the combination are the entries of the row vector.*)\nLemma mulmx_sum_row m n (u : 'rV_m) (A : 'M_(m, n)) :\n u *m A = \\sum_i u 0 i *: row i A.\n\n(*This lemma states that left-multiplying a matrix by a scalar matrix is equivalent to scaling the original matrix by the scalar value.*)\nLemma mul_scalar_mx m n a (A : 'M_(m, n)) : a%:M *m A = a *: A.\n\n(*This definition computes the complementary projection matrix of a given rank. It is defined as the result of subtracting the principal idempotent matrix of that rank from the identity matrix.*)\nDefinition copid_mx {n} r : 'M[R]_n := 1%:M - pid_mx r.\n\n(*This lemma states that under the condition that a given natural number is less than or equal to the number of rows, the matrix product of a complementary principal idempotent matrix and a principal idempotent matrix of the same rank results in a zero matrix.*)\nLemma mul_copid_mx_pid m n r :\n r <= m -> copid_mx r *m pid_mx r = 0 :> 'M_(m, n).\n\n(*This lemma states that under the condition that a given natural number is less than or equal to the number of columns, the matrix product of a principal idempotent matrix and a complementary principal idempotent matrix of the same rank results in a zero matrix.*)\nLemma mul_pid_mx_copid m n r :\n r <= n -> pid_mx r *m copid_mx r = 0 :> 'M_(m, n).\n\n(*This lemma asserts that a complementary principal idempotent matrix is idempotent, meaning that multiplying it by itself yields the original matrix, provided a given natural number is not greater than the matrix dimension.*)\nLemma copid_mx_id n r : r <= n -> copid_mx r *m copid_mx r = copid_mx r :> 'M_n.\n\nSection LinRowVector.\n\nVariables m n : nat.\n\n(*This fact serves as a unique opaque key for the `lin1_mx` definition, controlling its computational behavior.*)\nFact lin1_mx_key : unit. \n(*This definition computes the matrix representation of a function between two row-vector spaces. The i-th row of the resulting matrix is the image of the i-th standard basis vector under the given function.*)\nDefinition lin1_mx (f : 'rV[R]_m -> 'rV[R]_n) :=\n \\matrix[lin1_mx_key]_(i, j) f (delta_mx 0 i) 0 j.\n\nVariable f : {linear 'rV[R]_m -> 'rV[R]_n}.\n\n(*This lemma states that for a linear function, the result of applying the function to a row vector is identical to the result of multiplying that row vector on the right by the matrix representation of the function.*)\nLemma mul_rV_lin1 u : u *m lin1_mx f = f u.\n\nEnd LinRowVector.\n\nSection LinMatrix.\n\nVariables m1 n1 m2 n2 : nat.\n\n(*This definition computes the matrix representation of a function between two matrix spaces. It operates by composing the function with vectorization and its inverse, effectively treating the matrices as long row vectors, and then constructing the matrix for the resulting function between vector spaces.*)\nDefinition lin_mx (f : 'M[R]_(m1, n1) -> 'M[R]_(m2, n2)) :=\n lin1_mx (mxvec \\o f \\o vec_mx).\n\nVariable f : {linear 'M[R]_(m1, n1) -> 'M[R]_(m2, n2)}.\n\n(*This lemma states that for a linear function between matrix spaces, multiplying a row vector by the matrix representation of the function yields the vectorized form of the function applied to the matrix form of the original vector.*)\nLemma mul_rV_lin u : u *m lin_mx f = mxvec (f (vec_mx u)).\n\n(*This lemma states that for a linear function between matrix spaces, the product of the vectorized form of a matrix and the matrix representation of the function is equal to the vectorized form of the function applied to that matrix.*)\nLemma mul_vec_lin A : mxvec A *m lin_mx f = mxvec (f A).\n\n(*This lemma asserts that for a linear function between matrix spaces, converting the product of a row vector and the function's matrix representation back into a matrix yields the same result as applying the function to the matrix form of the original vector.*)\nLemma mx_rV_lin u : vec_mx (u *m lin_mx f) = f (vec_mx u).\n\n(*This lemma asserts that for a linear function between matrix spaces, taking the matrix form of the product of a vectorized matrix and the function's matrix representation is equivalent to applying the function directly to the original matrix.*)\nLemma mx_vec_lin A : vec_mx (mxvec A *m lin_mx f) = f A.\n\nEnd LinMatrix.\n(*This definition specifies a function that performs right matrix multiplication. It takes two matrices and computes their product in the reverse order of the arguments, effectively creating a right-multiplication operator.*)\nDefinition mulmxr B A := mulmx A B.\nArguments mulmxr B A /.\n\n(*This definition computes the matrix representation of the linear map corresponding to right multiplication by a given matrix.*)\nDefinition lin_mulmxr B := lin_mx (mulmxr B).\n\n(*This lemma states that the function representing right multiplication by a fixed matrix is a linear map.*)\nLemma mulmxr_is_linear B : linear (mulmxr B).\n\nHB.instance Definition _ B :=\n GRing.isSemilinear.Build R 'M_(m, n) 'M_(m, p) _ (mulmxr B)\n (GRing.semilinear_linear (mulmxr_is_linear B)).\n\n(*This lemma establishes that the function which computes the matrix representation of a right-multiplication operation is itself a linear map.*)\nLemma lin_mulmxr_is_linear : linear lin_mulmxr.\n\n(*A notation for the trace of a square matrix, which is the sum of the elements on its main diagonal.*)\nLocal Notation \"'\\tr' A\" := (mxtrace A) : ring_scope.\n\n(*This lemma states that the matrix trace function is a scalar linear map, meaning it is a linear transformation from the matrix space to its underlying scalar ring.*)\nLemma mxtrace_is_scalar : scalar (@mxtrace R n).\n\n(*This lemma specifies that the trace of a square matrix scaled by a ring element is equal to the ring element multiplied by the trace of the original matrix.*)\nLemma mxtraceZ a (A : 'M_n) : \\tr (a *: A) = a * \\tr A.\n\nEnd Trace.\n\nSection MatrixRing.\n\nVariable n : nat.\n\n(*This definition provides the Leibniz formula for the determinant of a square matrix. The determinant is computed as a sum over all permutations of the matrix indices, where each term in the sum is the product of matrix entries selected by the permutation, weighted by the sign of that permutation.*)\nDefinition determinant n (A : 'M_n) : R :=\n \\sum_(s : 'S_n) (-1) ^+ s * \\prod_i A i (s i).\n\n(*This definition computes the cofactor of a matrix for a given row and column. The cofactor is defined as the determinant of the submatrix formed by removing that row and column, multiplied by a sign that depends on the sum of the row and column indices.*)\nDefinition cofactor n A (i j : 'I_n) : R :=\n (-1) ^+ (i + j) * determinant (row' i (col' j A)).\n\n(*This fact serves as a unique opaque key for the `adjugate` definition, controlling its computational behavior.*)\nFact adjugate_key : unit. \n(*This definition computes the adjugate of a square matrix. The adjugate matrix is the transpose of the matrix of cofactors of the original matrix.*)\nDefinition adjugate n (A : 'M_n) := \\matrix[adjugate_key]_(i, j) cofactor A j i.\n\nEnd MatrixAlgebra.\n\nArguments copid_mx {R n}.\nArguments lin_mulmxr {R m n p}.\nPrenex Implicits determinant cofactor adjugate.\n\nArguments mulmxr {_ _ _ _} B A /.\n(*A notation for the determinant of a square matrix.*)\nNotation \"'\\det' A\" := (determinant A) : ring_scope.\n(*A notation for the adjugate of a square matrix.*)\nNotation \"'\\adj' A\" := (adjugate A) : ring_scope.\n\nHB.instance Definition _ (R : nzRingType) n := GRing.NzSemiRing.on 'M[R]_n.+1.\nHB.instance Definition _ (R : nzRingType) n :=\n GRing.Lmodule_isLalgebra.Build R 'M[R]_n.+1 (@scalemxAl R n.+1 n.+1 n.+1).\n\nHB.instance Definition _ (M : countZmodType) m n :=\n [Countable of 'M[M]_(m, n) by <:].\nHB.instance Definition _ (R : countNzRingType) n :=\n [Countable of 'M[R]_n.+1 by <:].\n\nSection FinZmodMatrix.\nVariables (V : finZmodType) (m n : nat).\n(*A local notation for the type of matrices of a given size with entries from a finite module over the integers.*)\nLocal Notation MV := 'M[V]_(m, n).\n\nHB.instance Definition _ := [Finite of MV by <:].\n\n#[compress_coercions]\n(**)\nLocal Notation \"A ^f\" := (map_mx f A) : ring_scope.\n\nSection FixedSize.\n\nVariables m n p : nat.\nImplicit Type A : 'M[aR]_(m, n).\n\n(*This lemma states that applying an element-wise ring morphism to a matrix that has been scaled by a ring element is equivalent to scaling the element-wise mapped matrix by the image of the scalar under the same morphism.*)\nLemma map_mxZ a A : (a *: A)^f = f a *: A^f.\n\n(*This lemma establishes that a ring morphism applied element-wise to a square matrix commutes with the determinant operation; that is, the determinant of the mapped matrix is equal to the morphism applied to the determinant of the original matrix.*)\nLemma det_map_mx n' (A : 'M_n') : \\det A^f = f (\\det A).\n\n(*This lemma establishes that a ring morphism applied element-wise to a square matrix commutes with the cofactor operation; that is, the cofactor of the mapped matrix at a given position is equal to the morphism applied to the cofactor of the original matrix at that same position.*)\nLemma cofactor_map_mx (A : 'M_n) i j : cofactor A^f i j = f (cofactor A i j).\n\n(*This lemma states that mapping a ring morphism over the adjugate of a square matrix yields the same result as taking the adjugate of the matrix that has been mapped over by the same ring morphism.*)\nLemma map_mx_adj (A : 'M_n) : (\\adj A)^f = \\adj A^f.\n\nEnd FixedSize.\n\n(*This lemma asserts that applying a ring morphism to a scalar matrix whose diagonal entries are given by a specific integer results in the same scalar matrix, indicating that the morphism preserves integer multiples of the identity.*)\nLemma map_copid_mx n r : (copid_mx r)^f = copid_mx r :> 'M_n.\n\n(*This lemma states that if a function between vector spaces is related to another by component-wise application of a ring morphism on its output, then the matrix representation of the first function, when mapped over by the morphism, is equal to the matrix representation of the second function.*)\nLemma map_lin1_mx m n (g : 'rV_m -> 'rV_n) gf :\n (forall v, (g v)^f = gf v^f) -> (lin1_mx g)^f = lin1_mx gf.\n\n(*This lemma states that if a function between matrix spaces is related to another by component-wise application of a ring morphism on its output matrix, then the matrix representation of the first function, when mapped over by the morphism, is equal to the matrix representation of the second function.*)\nLemma map_lin_mx m1 n1 m2 n2 (g : 'M_(m1, n1) -> 'M_(m2, n2)) gf :\n (forall A, (g A)^f = gf A^f) -> (lin_mx g)^f = lin_mx gf.\n\nEnd MapRingMatrix.\n\nSection CommMx.\n\nContext {R : pzRingType} {n : nat}.\nImplicit Types (f g p : 'M[R]_n) (fs : seq 'M[R]_n) (d : 'rV[R]_n) (I : Type).\n\n(*This lemma states that if a square matrix commutes with a second square matrix, it also commutes with the additive inverse of the second matrix.*)\nLemma comm_mxN f g : comm_mx f g -> comm_mx f (- g).\n\n(*This lemma states that any square matrix commutes with the additive inverse of the identity matrix.*)\nLemma comm_mxN1 f : comm_mx f (- 1%:M). \n\n(*This lemma states that if a square matrix commutes with two other square matrices, it also commutes with their difference.*)\nLemma comm_mxB f g g' : comm_mx f g -> comm_mx f g' -> comm_mx f (g - g').\n\nEnd CommMx.\n\nSection ComMatrix.\nVariable R : comPzRingType.\n\nSection AssocLeft.\n\nVariables m n p : nat.\nImplicit Type A : 'M[R]_(m, n).\nImplicit Type B : 'M[R]_(n, p).\n\n(*This lemma states that for matrices over a commutative ring, scaling the product of two matrices by a scalar is equivalent to multiplying the first matrix by the second matrix that has been scaled by the same scalar.*)\nLemma scalemxAr a A B : a *: (A *m B) = A *m (a *: B).\n\n(*This lemma establishes that for a fixed matrix over a commutative ring, the operation of left-multiplying another matrix by this fixed matrix is a scalable function, meaning that scaling the input matrix by a scalar results in scaling the output matrix by the same scalar.*)\nLemma mulmx_is_scalable A : scalable (@mulmx _ m n p A).\n\nHB.instance Definition _ A :=\n GRing.isScalable.Build R 'M[R]_(n, p) 'M[R]_(m, p) *:%R (mulmx A)\n (mulmx_is_scalable A).\n\n(*This definition provides the matrix representation of the linear transformation corresponding to left-multiplying a matrix by a given fixed matrix.*)\nDefinition lin_mulmx A : 'M[R]_(n * p, m * p) := lin_mx (mulmx A).\n\n(*This lemma establishes that the function which computes the matrix representation of a left-multiplication operator is itself a linear map.*)\nLemma lin_mulmx_is_linear : linear lin_mulmx.\n\n(*This definition creates a matrix that represents the linear map of multiplying a matrix from the left by a fixed row vector, an operation which corresponds to taking a linear combination of the matrix's rows.*)\nDefinition lin_mul_row u : 'M[R]_(m * n, n) := lin1_mx (mulmx u \\o vec_mx).\n\n(*This lemma asserts that the function which constructs the matrix representation for left-multiplication by a row vector is itself a linear map with respect to its row vector argument.*)\nLemma lin_mul_row_is_linear : linear lin_mul_row.\n\n(*This lemma provides the defining property of the 'lin_mul_row' matrix. It states that multiplying the row vector representation of a matrix by the 'lin_mul_row' matrix generated from a given row vector is equivalent to the standard matrix product of the given row vector and the original matrix.*)\nLemma mul_vec_lin_row A u : mxvec A *m lin_mul_row u = u *m A.\n\nEnd LinMulRow.\n\n(*This lemma relates a scalar value, computed as a product of a row vector, a matrix, and a column vector, to the dot product of the flattened forms of two matrices. Specifically, it states that the product of row vector `u`, matrix `A`, and the transpose of row vector `v` is equal to the dot product of the flattened outer product of `u` and `v`, and the flattened matrix `A`.*)\nLemma mxvec_dotmul m n (A : 'M[R]_(m, n)) u v :\n mxvec (u^T *m v) *m (mxvec A)^T = u *m A *m v^T.\n\n(*This lemma states that for a matrix over a commutative ring, right-multiplying it by a scalar matrix is equivalent to component-wise scaling of the matrix by that scalar.*)\nLemma mul_mx_scalar m n a (A : 'M[R]_(m, n)) : A *m a%:M = a *: A.\n\n(*This lemma asserts the multilinearity property of the determinant. It states that if a row of a matrix is a linear combination of the corresponding rows of two other matrices, while all other rows remain the same across the three matrices, then the determinant of the first matrix is the same linear combination of the determinants of the other two.*)\nLemma determinant_multilinear n (A B C : 'M[R]_n) i0 b c :\n row i0 A = b *: row i0 B + c *: row i0 C ->\n row' i0 B = row' i0 A ->\n row' i0 C = row' i0 A ->\n \\det A = b * \\det B + c * \\det C.\n\n(*This lemma describes the alternating property of the determinant, stating that if a square matrix has two distinct rows that are identical, its determinant is zero.*)\nLemma determinant_alternate n (A : 'M[R]_n) i1 i2 :\n i1 != i2 -> A i1 =1 A i2 -> \\det A = 0.\n\n(*This lemma states that the determinant of a square matrix is equal to the determinant of its transpose.*)\nLemma det_tr n (A : 'M[R]_n) : \\det A^T = \\det A.\n\n(*This lemma states that the determinant of a permutation matrix is equal to the signum of the corresponding permutation, interpreted as an element of the underlying ring.*)\nLemma det_perm n (s : 'S_n) : \\det (perm_mx s) = (-1) ^+ s :> R.\n\n(*This lemma states that the determinant of the identity matrix of any size is one.*)\nLemma det1 n : \\det (1%:M : 'M[R]_n) = 1.\n\n(*This lemma states that the determinant of a zero-by-zero matrix is defined to be one.*)\nLemma det_mx00 (A : 'M[R]_0) : \\det A = 1.\n\n(*This lemma describes how the determinant scales with scalar multiplication. It asserts that the determinant of an n-by-n matrix scaled by a scalar 'a' is equal to the determinant of the original matrix multiplied by 'a' raised to the power of n.*)\nLemma detZ n a (A : 'M[R]_n) : \\det (a *: A) = a ^+ n * \\det A.\n\n(*This lemma states that the determinant of a zero matrix of any positive size is zero.*)\nLemma det0 n' : \\det (0 : 'M[R]_n'.+1) = 0.\n\n(*This lemma states that the determinant of an n-by-n scalar matrix with a given value on its diagonal is equal to that value raised to the power of n.*)\nLemma det_scalar n a : \\det (a%:M : 'M[R]_n) = a ^+ n.\n\n(*This lemma states that the determinant of a one-by-one scalar matrix is equal to its single entry.*)\nLemma det_scalar1 a : \\det (a%:M : 'M[R]_1) = a.\n\n(*This lemma states that the determinant of any one-by-one matrix is equal to its single element.*)\nLemma det_mx11 (M : 'M[R]_1) : \\det M = M 0 0.\n\n(*This lemma states that the determinant is a multiplicative morphism. Specifically, the determinant of the product of two square matrices is equal to the product of their individual determinants.*)\nLemma det_mulmx n (A B : 'M[R]_n) : \\det (A *m B) = \\det A * \\det B.\n\n(*This lemma asserts that for square matrices of positive dimension, the determinant of their product is the product of their determinants.*)\nLemma detM n' (A B : 'M[R]_n'.+1) : \\det (A * B) = \\det A * \\det B.\n\n(*This lemma provides the cofactor expansion formula, which relates a matrix, its adjugate, and its determinant. It asserts that the dot product of the i-th row of a matrix with the j-th column of its adjugate matrix equals the determinant of the matrix if i and j are the same, and zero otherwise.*)\nLemma expand_cofactor n (A : 'M[R]_n) i j :\n cofactor A i j =\n \\sum_(s : 'S_n | s i == j) (-1) ^+ s * \\prod_(k | i != k) A k (s k).\n\n(*This lemma states that the determinant of a square matrix can be computed by summing the products of the entries of any given row with their corresponding cofactors.*)\nLemma expand_det_row n (A : 'M[R]_n) i0 :\n \\det A = \\sum_j A i0 j * cofactor A i0 j.\n\n(*This lemma states that the cofactor of the transpose of a square matrix at a given row and column index is equal to the cofactor of the original matrix at the swapped column and row index.*)\nLemma cofactor_tr n (A : 'M[R]_n) i j : cofactor A^T i j = cofactor A j i.\n\n(*This lemma states that the cofactor of a square matrix scaled by a scalar is equal to the cofactor of the original matrix multiplied by the scalar raised to the power of the matrix dimension minus one.*)\nLemma cofactorZ n a (A : 'M[R]_n) i j :\n cofactor (a *: A) i j = a ^+ n.-1 * cofactor A i j.\n\n(*This lemma states that the determinant of a square matrix can be computed by summing the products of the entries of any given column with their corresponding cofactors.*)\nLemma expand_det_col n (A : 'M[R]_n) j0 :\n \\det A = \\sum_i (A i j0 * cofactor A i j0).\n\n(*This lemma states that the transpose of the adjugate of a square matrix is equal to the adjugate of the matrix's transpose.*)\nLemma trmx_adj n (A : 'M[R]_n) : (\\adj A)^T = \\adj A^T.\n\n(*This lemma states that the adjugate of a square matrix scaled by a scalar is equal to the adjugate of the original matrix, itself scaled by the scalar raised to the power of the matrix dimension minus one.*)\nLemma adjZ n a (A : 'M[R]_n) : \\adj (a *: A) = a^+n.-1 *: \\adj A.\n\n(*This lemma states that the product of a square matrix and its adjugate is a scalar matrix whose diagonal entries are all equal to the determinant of the original matrix.*)\nLemma mul_mx_adj n (A : 'M[R]_n) : A *m \\adj A = (\\det A)%:M.\n\n(*This lemma states that the product of the adjugate of a square matrix and the matrix itself is a scalar matrix whose diagonal entries are all equal to the determinant of the original matrix.*)\nLemma mul_adj_mx n (A : 'M[R]_n) : \\adj A *m A = (\\det A)%:M.\n\n(*This lemma states that the adjugate of the identity matrix is the identity matrix itself.*)\nLemma adj1 n : \\adj (1%:M) = 1%:M :> 'M[R]_n.\n\n(*This lemma states that for two square matrices, if their product in one order is the identity matrix, then their product in the reverse order is also the identity matrix.*)\nLemma mulmx1C n (A B : 'M[R]_n) : A *m B = 1%:M -> B *m A = 1%:M.\n\n(*This lemma states that the determinant of an upper block-triangular matrix is the product of the determinants of its diagonal blocks.*)\nLemma det_ublock n1 n2 Aul (Aur : 'M[R]_(n1, n2)) Adr :\n \\det (block_mx Aul Aur 0 Adr) = \\det Aul * \\det Adr.\n\n(*This lemma states that the determinant of a lower block-triangular matrix is the product of the determinants of its diagonal blocks.*)\nLemma det_lblock n1 n2 Aul (Adl : 'M[R]_(n2, n1)) Adr :\n \\det (block_mx Aul 0 Adl Adr) = \\det Aul * \\det Adr.\n\n(*This lemma states that the determinant of a triangular square matrix is equal to the product of its diagonal entries.*)\nLemma det_trig n (A : 'M[R]_n) : is_trig_mx A -> \\det A = \\prod_(i < n) A i i.\n\n(*This lemma states that the determinant of a diagonal matrix is the product of the elements from the vector used to construct it.*)\nLemma det_diag n (d : 'rV[R]_n) : \\det (diag_mx d) = \\prod_i d 0 i.\n\nEnd ComMatrix.\n\nArguments lin_mul_row {R m n} u.\nArguments lin_mulmx {R m n p} A.\n\nSection ComNzMatrix.\nVariable R : comNzRingType.\n\n(*This lemma states that if the product of a matrix and another matrix results in an identity matrix, then the number of rows in the first matrix must be less than or equal to its number of columns.*)\nLemma mulmx1_min m n (A : 'M[R]_(m, n)) B : A *m B = 1%:M -> m <= n.\n\n(*This definition specifies a predicate that identifies a square matrix as a unit, or invertible, if its determinant is an invertible element in the underlying ring.*)\nDefinition unitmx : pred 'M[R]_n := fun A => \\det A \\is a GRing.unit.\n(*This definition provides a function for computing the inverse of a square matrix; if the matrix is invertible, it returns the adjugate matrix scaled by the inverse of the determinant, otherwise it returns the original matrix.*)\nDefinition invmx A := if A \\in unitmx then (\\det A)^-1 *: \\adj A else A.\n\n(*This lemma states that a square matrix is a unit matrix if and only if its determinant is an invertible element of the base ring.*)\nLemma unitmxE A : (A \\in unitmx) = (\\det A \\is a GRing.unit).\n\n(*This lemma states that the identity matrix is a unit matrix, meaning it is invertible.*)\nLemma unitmx1 : 1%:M \\in unitmx. \n\n(*This lemma states that any permutation matrix is a unit matrix, meaning it is invertible.*)\nLemma unitmx_perm s : perm_mx s \\in unitmx.\n\n(*This lemma states that a square matrix is invertible if and only if its transpose is also invertible.*)\nLemma unitmx_tr A : (A^T \\in unitmx) = (A \\in unitmx).\n\n(*This lemma states that if a scalar is invertible, then a square matrix scaled by this scalar is invertible if and only if the original matrix is invertible.*)\nLemma unitmxZ a A : a \\is a GRing.unit -> (a *: A \\in unitmx) = (A \\in unitmx).\n\n(*This lemma states that the inverse of the identity matrix is the identity matrix itself.*)\nLemma invmx1 : invmx 1%:M = 1%:M.\n\n(*This lemma states that for an invertible matrix scaled by an invertible scalar, its inverse is the product of the inverse of the original matrix and the inverse of the scalar.*)\nLemma invmxZ a A : a *: A \\in unitmx -> invmx (a *: A) = a^-1 *: invmx A.\n\n(*This lemma states that the inverse of a scalar matrix is the scalar matrix formed from the inverse of the scalar.*)\nLemma invmx_scalar a : invmx (a%:M) = a^-1%:M.\n\n(*This lemma states that the inverse matrix function provides a left inverse for any invertible square matrix with respect to matrix multiplication, resulting in the identity matrix.*)\nLemma mulVmx : {in unitmx, left_inverse 1%:M invmx mulmx}.\n\n(*This lemma states that the inverse matrix function provides a right inverse for any invertible square matrix with respect to matrix multiplication, resulting in the identity matrix.*)\nLemma mulmxV : {in unitmx, right_inverse 1%:M invmx mulmx}.\n\n(*This lemma asserts the left cancellation property for matrix multiplication, stating that multiplying a product of two matrices by the inverse of the first matrix yields the second matrix.*)\nLemma mulKmx m : {in unitmx, @left_loop _ 'M_(n, m) invmx mulmx}.\n\n(*This lemma asserts the reverse left cancellation property for matrix multiplication, stating that multiplying a product, whose second factor is a matrix product starting with an inverse matrix, by the original matrix cancels the inverse.*)\nLemma mulKVmx m : {in unitmx, @rev_left_loop _ 'M_(n, m) invmx mulmx}.\n\n(*This lemma asserts the right cancellation property for matrix multiplication, stating that multiplying a product of two matrices by the inverse of the second matrix yields the first matrix.*)\nLemma mulmxK m : {in unitmx, @right_loop 'M_(m, n) _ invmx mulmx}.\n\n(*This lemma states that for any invertible matrix, the operation of right-multiplying by it has a right-inverse, namely right-multiplication by its matrix inverse.*)\nLemma mulmxKV m : {in unitmx, @rev_right_loop 'M_(m, n) _ invmx mulmx}.\n\n(*This lemma states that the determinant of the inverse of a matrix is equal to the multiplicative inverse of the determinant of the original matrix.*)\nLemma det_inv A : \\det (invmx A) = (\\det A)^-1.\n\n(*This lemma states that the inverse of a matrix is itself an invertible matrix if and only if the original matrix is invertible.*)\nLemma unitmx_inv A : (invmx A \\in unitmx) = (A \\in unitmx).\n\n(*This lemma states that the product of two matrices is invertible if and only if both matrices are individually invertible.*)\nLemma unitmx_mul A B : (A *m B \\in unitmx) = (A \\in unitmx) && (B \\in unitmx).\n\n(*This lemma states that the transpose of the inverse of a square matrix is equal to the inverse of its transpose.*)\nLemma trmx_inv (A : 'M_n) : (invmx A)^T = invmx (A^T).\n\n(*This lemma states that the matrix inverse operation is an involution, meaning that taking the inverse of the inverse of a matrix yields the original matrix.*)\nLemma invmxK : involutive invmx.\n\n(*This lemma states that if the product of two matrices is the identity matrix, then both matrices must be invertible.*)\nLemma mulmx1_unit A B : A *m B = 1%:M -> A \\in unitmx /\\ B \\in unitmx.\n\n(*This lemma provides a criterion for a matrix to be invertible, stating that a matrix is invertible if there exists another matrix that serves as both its left and right inverse.*)\nLemma intro_unitmx A B : B *m A = 1%:M /\\ A *m B = 1%:M -> unitmx A.\n\n(*This lemma specifies that the matrix inverse function, when applied to a non-invertible matrix, returns the matrix itself.*)\nLemma invmx_out : {in [predC unitmx], invmx =1 id}.\n\nEnd Defs.\n\nVariable n' : nat.\n(*This notation defines `n` as a positive natural number, specifically as one more than a given natural number `n'`.*)\nLocal Notation n := n'.+1.\n\n(*This lemma states that the determinant of the inverse of a square matrix is equal to the multiplicative inverse of the determinant of the original matrix.*)\nLemma detV (A : 'M_n) : \\det A^-1 = (\\det A)^-1.\n\n(*This lemma states that the transpose of a square matrix is a unit, meaning it is invertible, if and only if the original matrix is a unit.*)\nLemma unitr_trmx (A : 'M_n) : (A^T \\is a GRing.unit) = (A \\is a GRing.unit).\n\n(*This lemma states that the transpose of the inverse of a square matrix is equal to the inverse of its transpose.*)\nLemma trmxV (A : 'M_n) : A^-1^T = (A^T)^-1.\n\n(*This lemma states that the permutation matrix corresponding to an inverse permutation is the inverse of the permutation matrix of the original permutation.*)\nLemma perm_mxV (s : 'S_n) : perm_mx s^-1 = (perm_mx s)^-1.\n\n(*This lemma states that the inverse of a matrix is a permutation matrix if and only if the original matrix is a permutation matrix.*)\nLemma is_perm_mxV (A : 'M_n) : is_perm_mx A^-1 = is_perm_mx A.\n\nEnd MatrixInv.\n\nPrenex Implicits unitmx invmx invmxK.\n\n(*This lemma states that a block diagonal matrix is invertible if and only if each of its diagonal blocks is invertible.*)\nLemma block_diag_mx_unit (R : comUnitRingType) n1 n2\n (Aul : 'M[R]_n1) (Adr : 'M[R]_n2) :\n (block_mx Aul 0 0 Adr \\in unitmx) = (Aul \\in unitmx) && (Adr \\in unitmx).\n\n(*This lemma states that the inverse of an invertible block diagonal matrix is the block diagonal matrix formed by the inverses of the original diagonal blocks.*)\nLemma invmx_block_diag (R : comUnitRingType) n1 n2\n (Aul : 'M[R]_n1) (Adr : 'M[R]_n2) :\n block_mx Aul 0 0 Adr \\in unitmx ->\n invmx (block_mx Aul 0 0 Adr) = block_mx (invmx Aul) 0 0 (invmx Adr).\n\nHB.instance Definition _ (R : countComUnitRingType) (n' : nat) :=\n [Countable of 'M[R]_n'.+1 by <:].\n\nHB.instance Definition _ (n : nat) (R : finComUnitRingType) :=\n [Finite of 'M[R]_n.+1 by <:].\n\nSection FinUnitMatrix.\n\nVariable n : nat.\n\n(*This definition introduces `GLtype` as the type representing the general linear group, consisting of all invertible square matrices of a given size over a finite commutative ring.*)\nDefinition GLtype (R : finComUnitRingType) := {unit 'M[R]_n.-1.+1}.\n\nCoercion GLval R (u : GLtype R) : 'M[R]_n.-1.+1 :=\n let: FinRing.Unit A _ := u in A.\n\nEnd FinUnitMatrix.\n\nBind Scope group_scope with GLtype.\nArguments GLtype n%_N R%_type.\nArguments GLval {n%_N R} u%_g.\n\n(*A notation for the type of the general linear group of a given size over a given finite commutative ring.*)\nNotation \"{ ''GL_' n [ R ] }\" := (GLtype n R) : type_scope.\n\n(*A notation for the type of the general linear group of a given size over a prime field of a given characteristic.*)\nNotation \"{ ''GL_' n ( p ) }\" := {'GL_n['F_p]} : type_scope.\n\n(*This definition introduces `GLgroup` as the set containing all elements of the general linear group of a given size over a finite commutative ring.*)\nDefinition GLgroup := [set: {'GL_n[R]}].\nCanonical GLgroup_group := Eval hnf in [group of GLgroup].\n\nImplicit Types u v : {'GL_n[R]}.\n\n(*This lemma states that the identity element of the general linear group corresponds to the identity matrix.*)\nLemma GL_1E : GLval 1 = 1. \n(*This lemma states that the matrix corresponding to the inverse of an element in the general linear group is the matrix inverse of the matrix corresponding to the original element.*)\nLemma GL_VE u : GLval u^-1 = (GLval u)^-1. \n(*This lemma provides an alternative statement about the inverse, asserting that the matrix corresponding to the inverse of an element in the general linear group is computed using the standard matrix inverse function.*)\nLemma GL_VxE u : GLval u^-1 = invmx u. \n(*This lemma states that the matrix corresponding to the product of two elements in the general linear group is the matrix product of their corresponding matrices.*)\nLemma GL_ME u v : GLval (u * v) = GLval u * GLval v. \n(*This lemma provides an alternative statement about multiplication, asserting that the matrix corresponding to the product of two elements in the general linear group is the product of their corresponding matrices, using the matrix multiplication operation.*)\nLemma GL_MxE u v : GLval (u * v) = u *m v. \n(*This lemma states that the matrix corresponding to any element from the general linear group is by definition an invertible element in the ring of matrices.*)\nLemma GL_unit u : GLval u \\is a GRing.unit. \n(*This lemma states that the matrix representation of any element from the general linear group belongs to the set of invertible matrices.*)\nLemma GL_unitmx u : val u \\in unitmx. \n\n(*This lemma states that the determinant of the matrix corresponding to any element of the general linear group is not equal to zero.*)\nLemma GL_det u : \\det u != 0.\n\nEnd GL_unit.\n\nArguments GLgroup n%_N R%_type.\nArguments GLgroup_group n%_N R%_type.\n\n(*A notation for the group structure of the general linear group of a given size over a given finite commutative ring.*)\nNotation \"''GL_' n [ R ]\" := (GLgroup n R)\n (at level 8, n at level 2, format \"''GL_' n [ R ]\") : group_scope.\n(*This notation represents the general linear group of degree n over the finite field with p elements, where n is a natural number and p is a prime number. This group consists of all n-by-n invertible matrices with entries from the specified finite field, under the operation of matrix multiplication.*)\nNotation \"''GL_' n ( p )\" := 'GL_n['F_p]\n (p at level 10, format \"''GL_' n ( p )\") : group_scope.\n(*This notation represents the general linear group of degree n over a ring R, where n is a natural number. This group consists of all n-by-n invertible matrices with entries from the ring R, under the operation of matrix multiplication.*)\nNotation \"''GL_' n [ R ]\" := (GLgroup_group n R) : Group_scope.\n(*A notation for the general linear group, representing the set of all invertible square matrices of a given dimension over a given ring.*)\nNotation \"''GL_' n ( p )\" := (GLgroup_group n 'F_p) : Group_scope.\n\nSection MatrixDomain.\n\nVariable R : idomainType.\n\n(*This lemma states that the scalar product of a scalar and a matrix over an integral domain is equal to the zero matrix if and only if the scalar is zero or the matrix is the zero matrix.*)\nLemma scalemx_eq0 m n a (A : 'M[R]_(m, n)) :\n (a *: A == 0) = (a == 0) || (A == 0).\n\n(*This lemma states that for any non-zero scalar from an integral domain, the function that multiplies a matrix by that scalar is injective.*)\nLemma scalemx_inj m n a :\n a != 0 -> injective ( *:%R a : 'M[R]_(m, n) -> 'M[R]_(m, n)).\n\n(*This lemma states that the determinant of a square matrix over an integral domain is zero if and only if there exists a non-zero row vector that, when multiplied by the matrix, results in the zero vector.*)\nLemma det0P n (A : 'M[R]_n) :\n reflect (exists2 v : 'rV[R]_n, v != 0 & v *m A = 0) (\\det A == 0).\n\nEnd MatrixDomain.\n\nArguments det0P {R n A}.\n\nSection MapFieldMatrix.\n\nVariables (aF : fieldType) (rF : comUnitRingType) (f : {rmorphism aF -> rF}).\n(*This notation represents the element-wise application of a ring morphism to a matrix.*)\nLocal Notation \"A ^f\" := (map_mx f A) : ring_scope.\n\n(*This lemma states that the function which applies a ring morphism from a field to each element of a matrix is an injective function.*)\nLemma map_mx_inj {m n} : injective (map_mx f : 'M_(m, n) -> 'M_(m, n)).\n\n(*This lemma states that applying a ring morphism from a field to the elements of a square matrix preserves the property of being a scalar matrix.*)\nLemma map_mx_is_scalar n (A : 'M_n) : is_scalar_mx A^f = is_scalar_mx A.\n\n(*This lemma states that a square matrix is invertible if and only if the matrix resulting from applying a ring morphism from a field to its elements is also invertible.*)\nLemma map_unitmx n (A : 'M_n) : (A^f \\in unitmx) = (A \\in unitmx).\n\n(*This lemma states that a non-empty square matrix is a unit in the matrix ring if and only if the matrix resulting from applying a ring morphism from a field to its elements is also a unit.*)\nLemma map_mx_unit n' (A : 'M_n'.+1) :\n (A^f \\is a GRing.unit) = (A \\is a GRing.unit).\n\n(*This lemma states that for an invertible square matrix, applying a ring morphism from a field to the elements of its inverse yields the same result as first applying the morphism to the original matrix and then computing its inverse.*)\nLemma map_invmx n (A : 'M_n) : (invmx A)^f = invmx A^f.\n\n(*This lemma states that for an invertible square matrix, the element-wise application of a ring morphism from a field to its inverse is equal to the inverse of the matrix obtained by applying the morphism element-wise.*)\nLemma map_mx_inv n' (A : 'M_n'.+1) : A^-1^f = A^f^-1.\n\n(*This lemma states that applying a ring morphism from a field element-wise to a matrix results in a zero matrix if and only if the original matrix was a zero matrix.*)\nLemma map_mx_eq0 m n (A : 'M_(m, n)) : (A^f == 0) = (A == 0).\n\nEnd MapFieldMatrix.\n\nArguments map_mx_inj {aF rF f m n} [A1 A2] eqA12f : rename.\n\nSection CormenLUP.\n\nVariable F : fieldType.\n\n(*This recursive function computes the LUP decomposition of a square matrix over a field, returning a triple consisting of a permutation matrix, a unit lower-triangular matrix, and an upper-triangular matrix.*)\nFixpoint cormen_lup {n} :=\n match n return let M := 'M[F]_n.+1 in M -> M * M * M with\n | 0 => fun A => (1, 1, A)\n | _.+1 => fun A =>\n let k := odflt 0 [pick k | A k 0 != 0] in\n let A1 : 'M_(1 + _) := xrow 0 k A in\n let P1 : 'M_(1 + _) := tperm_mx 0 k in\n let Schur := ((A k 0)^-1 *: dlsubmx A1) *m ursubmx A1 in\n let: (P2, L2, U2) := cormen_lup (drsubmx A1 - Schur) in\n let P := block_mx 1 0 0 P2 *m P1 in\n let L := block_mx 1 0 ((A k 0)^-1 *: (P2 *m dlsubmx A1)) L2 in\n let U := block_mx (ulsubmx A1) (ursubmx A1) 0 U2 in\n (P, L, U)\n end.\n\n(*This lemma states that the first component of the triplet returned by the cormen_lup decomposition function is a permutation matrix.*)\nLemma cormen_lup_perm n (A : 'M_n.+1) : is_perm_mx (cormen_lup A).1.1.\n\n(*This lemma states the correctness of the cormen_lup decomposition, asserting that the product of the resulting permutation matrix and the original matrix is equal to the product of the resulting lower and upper triangular matrices.*)\nLemma cormen_lup_correct n (A : 'M_n.+1) :\n let: (P, L, U) := cormen_lup A in P * A = L * U.\n\n(*This lemma states that the determinant of the lower-triangular matrix produced by the cormen_lup decomposition is equal to one.*)\nLemma cormen_lup_detL n (A : 'M_n.+1) : \\det (cormen_lup A).1.2 = 1.\n\n(*This lemma states that the lower-triangular matrix produced by the cormen_lup decomposition has entries that are one on the main diagonal and zero in the upper triangle.*)\nLemma cormen_lup_lower n A (i j : 'I_n.+1) :\n i <= j -> (cormen_lup A).1.2 i j = (i == j)%:R.\n\n(*This lemma states that the upper-triangular matrix produced by the cormen_lup decomposition has entries that are zero for all elements below the main diagonal.*)\nLemma cormen_lup_upper n A (i j : 'I_n.+1) :\n j < i -> (cormen_lup A).2 i j = 0 :> F.\n\nEnd CormenLUP.\n\nSection mxOver.\nSection mxOverType.\nContext {m n : nat} {T : Type}.\nImplicit Types (S : {pred T}).\n\n(*This definition specifies a predicate on a matrix which is satisfied if and only if every entry of the matrix satisfies a given underlying predicate.*)\nDefinition mxOver_pred (S : {pred T}) :=\n fun M : 'M[T]_(m, n) => [forall i, [forall j, M i j \\in S]].\nArguments mxOver_pred _ _ /.\n(*This definition introduces a subtype of matrices whose entries are all contained in a given set.*)\nDefinition mxOver (S : {pred T}) := [qualify a M | mxOver_pred S M].\n\n(*This lemma provides a reflection property, stating that a matrix is an instance of the mxOver subtype for a given set if and only if all of its entries are members of that set.*)\nLemma mxOverP {S : {pred T}} {M : 'M[T]__} :\n reflect (forall i j, M i j \\in S) (M \\is a mxOver S).\n\n(*This lemma states that if a set is a subset of another set, then the type of matrices whose elements are in the first set is a subtype of the type of matrices whose elements are in the second set.*)\nLemma mxOverS (S1 S2 : {pred T}) :\n {subset S1 <= S2} -> {subset mxOver S1 <= mxOver S2}.\n\n(*This lemma states that if an element is a member of a given set, then a constant matrix constructed with that element belongs to the subtype of matrices over that set.*)\nLemma mxOver_const c S : c \\in S -> const_mx c \\is a mxOver S.\n\n(*This lemma states that for a non-empty constant matrix, belonging to the subtype of matrices over a given set is equivalent to its constant value being a member of that set.*)\nLemma mxOver_constE c S : (m > 0)%N -> (n > 0)%N ->\n (const_mx c \\is a mxOver S) = (c \\in S).\n\nEnd mxOverType.\n\n(*This lemma states that any matrix with zero columns vacuously belongs to the subtype of matrices over any given set.*)\nLemma thinmxOver {n : nat} {T : Type} (M : 'M[T]_(n, 0)) S : M \\is a mxOver S.\n\n(*This lemma states that any matrix with zero rows vacuously belongs to the subtype of matrices over any given set.*)\nLemma flatmxOver {n : nat} {T : Type} (M : 'M[T]_(0, n)) S : M \\is a mxOver S.\n\nSection mxOverZmodule.\nContext {M : zmodType} {m n : nat}.\nImplicit Types (S : {pred M}).\n\n(*This lemma states that if the zero element of a module is a member of a given set, then the zero matrix over that module belongs to the subtype of matrices over that set.*)\nLemma mxOver0 S : 0 \\in S -> 0 \\is a @mxOver m n _ S.\n\nSection mxOverAdd.\nVariable addS : addrClosed M.\n(*This fact asserts that the set of matrices whose elements belong to an additively closed set is itself closed under matrix addition.*)\nFact mxOver_add_subproof : addr_closed (@mxOver m n _ addS).\n\n(*This fact asserts that the set of matrices whose elements belong to a set closed under additive inverse is itself closed under matrix additive inverse.*)\nFact mxOver_opp_subproof : oppr_closed (@mxOver m n _ oppS).\n\n(*This lemma states that if a set contains both the zero element and a scalar value from a ring, then the scalar matrix formed from that value belongs to the subtype of matrices over that set.*)\nLemma mxOver_scalar S c : 0 \\in S -> c \\in S -> c%:M \\is a @mxOver n n R S.\n\n(*This lemma states that for a non-zero-sized square matrix, a scalar matrix with a given value has all its entries in a given set if and only if that value is in the set, and additionally, if the matrix dimension is greater than one, the zero element is also in the set.*)\nLemma mxOver_scalarE S c : (n > 0)%N ->\n (c%:M \\is a @mxOver n n R S) = ((n > 1) ==> (0 \\in S)) && (c \\in S).\n\n(*This lemma states that for any set that is closed under multiplication, if all entries of a matrix are in this set, and a scalar value is also in this set, then the matrix resulting from multiplying the original matrix by the scalar will also have all its entries in the set.*)\nLemma mxOverZ (S : mulrClosed R) :\n {in S & mxOver S, forall a : R, forall v : 'M[R]_(m, n),\n a *: v \\is a mxOver S}.\n\n(*This lemma states that if the zero element belongs to a given set and all entries of a given row vector also belong to that set, then the square diagonal matrix formed from this vector will have all its entries in the set.*)\nLemma mxOver_diag (S : {pred R}) k (D : 'rV[R]_k) :\n 0 \\in S -> D \\is a mxOver S -> diag_mx D \\is a mxOver S.\n\n(*This lemma provides an equivalence for when a square diagonal matrix, formed from a row vector of positive length, has all its entries in a given set. It states this is true if and only if all entries of the original vector are in the set, and additionally, if the vector's length is greater than one, the zero element must also be in the set.*)\nLemma mxOver_diagE (S : {pred R}) k (D : 'rV[R]_k) : k > 0 ->\n (diag_mx D \\is a mxOver S) = ((k > 1) ==> (0 \\in S)) && (D \\is a mxOver S).\n\n(*This lemma states that for any set that is closed under both addition and multiplication, the product of two matrices whose entries are all in this set will also result in a matrix whose entries are all in the set.*)\nLemma mxOverM (S : semiringClosed R) p q r : {in mxOver S & mxOver S,\n forall u : 'M[R]_(p, q), forall v : 'M[R]_(q, r), u *m v \\is a mxOver S}.\n\nEnd mxOverRing.\n\nSection mxRingOver.\nContext {R : pzRingType} {n : nat}.\n\nSection semiring.\nVariable S : semiringClosed R.\n(*This fact establishes that the set of all square matrices of a given dimension, whose entries all belong to a set that is closed under addition and multiplication, is itself closed under matrix multiplication.*)\nFact mxOver_mul_subproof : mulr_closed (@mxOver n n _ S).\n\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `p`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sp := (\\sum_i p_ i)%N.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `q`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sq := (\\sum_i q_ i)%N.\nImplicit Type (s : 'I_sp) (t : 'I_sq).\n\n(*This definition constructs a large block matrix by arranging smaller matrices, called blocks, in a grid. The arguments provide a function that yields a block matrix for each grid position, and the function assembles these into a single large matrix.*)\nDefinition mxblock (B_ : forall i j, 'M[T]_(p_ i, q_ j)) :=\n \\matrix_(j, k) B_ (sig1 j) (sig1 k) (sig2 j) (sig2 k).\n(*This notation provides a convenient syntax for constructing a block matrix from an expression that defines each block based on its row and column block indices.*)\nLocal Notation \"\\mxblock_ ( i , j ) E\" := (mxblock (fun i j => E)) : ring_scope.\n\n(*This definition constructs a matrix by horizontally concatenating a sequence of block matrices. It takes the number of rows for the final matrix and a function that provides each block matrix in the sequence.*)\nDefinition mxrow m (B_ : forall j, 'M[T]_(m, q_ j)) :=\n \\matrix_(j, k) B_ (sig1 k) j (sig2 k).\n(*This notation provides a convenient syntax for constructing a matrix from a row of blocks from an expression that defines each block based on its column block index.*)\nLocal Notation \"\\mxrow_ i E\" := (mxrow (fun i => E)) : ring_scope.\n\n(*This definition constructs a matrix by vertically concatenating a sequence of block matrices. It takes the number of columns for the final matrix and a function that provides each block matrix in the sequence.*)\nDefinition mxcol n (B_ : forall i, 'M[T]_(p_ i, n)) :=\n \\matrix_(j, k) B_ (sig1 j) (sig2 j) k.\n(*This notation provides a convenient syntax for constructing a matrix from a column of blocks from an expression that defines each block based on its row block index.*)\nLocal Notation \"\\mxcol_ i E\" := (mxcol (fun i => E)) : ring_scope.\n\n(*This definition extracts a specific block from a larger block matrix at a given block row and block column index.*)\nDefinition submxblock (A : 'M[T]_(sp, sq)) i j := mxsub (Rank i) (Rank j) A.\n(*This definition extracts a specific block column from a larger matrix that is structured as a single row of blocks.*)\nDefinition submxrow m (A : 'M[T]_(m, sq)) j := colsub (Rank j) A.\n(*This definition extracts a specific block row from a larger matrix that is structured as a single column of blocks.*)\nDefinition submxcol n (A : 'M[T]_(sp, n)) i := rowsub (Rank i) A.\n\n(*This lemma states that constructing a block matrix from a grid of blocks is equivalent to first constructing each column of blocks individually and then arranging these block columns horizontally.*)\nLemma mxblockEh B_ : \\mxblock_(i, j) B_ i j = \\mxrow_j \\mxcol_i B_ i j.\n\n(*This lemma states that constructing a block matrix from a grid of blocks is equivalent to first constructing each row of blocks individually and then stacking these block rows vertically.*)\nLemma mxblockEv B_ : \\mxblock_(i, j) B_ i j = \\mxcol_i \\mxrow_j B_ i j.\n\n(*This lemma states that extracting a specific block from a block matrix can be done in two steps: first by extracting the entire column of blocks containing the target block, and then extracting the desired block from that column.*)\nLemma submxblockEh A i j : submxblock A i j = submxcol (submxrow A j) i.\n\n(*This lemma states that extracting a specific block from a block matrix can be done in two steps: first by extracting the entire row of blocks containing the target block, and then extracting the desired block from that row.*)\nLemma submxblockEv A i j : submxblock A i j = submxrow (submxcol A i) j.\n\n(*This lemma states that if a block matrix is constructed from a given collection of blocks, extracting the block at a specific row and column index yields the original block from that position.*)\nLemma mxblockK B_ i j : submxblock (\\mxblock_(i, j) B_ i j) i j = B_ i j.\n\n(*This lemma states that if a matrix is constructed by arranging blocks in a single row, extracting the block at a specific column index yields the original block from that position.*)\nLemma mxrowK m B_ j : @submxrow m (\\mxrow_j B_ j) j = B_ j.\n\n(*This lemma states that if a matrix is constructed by stacking blocks in a single column, extracting the block at a specific row index yields the original block from that position.*)\nLemma mxcolK n B_ i : @submxcol n (\\mxcol_i B_ i) i = B_ i.\n\n(*This lemma states that extracting a full column of blocks from a larger block matrix results in a matrix that is equivalent to constructing a single column matrix from the original blocks of that column.*)\nLemma submxrow_matrix B_ j :\n submxrow (\\mxblock_(i, j) B_ i j) j = \\mxcol_i B_ i j.\n\n(*This lemma states that extracting a full row of blocks from a larger block matrix results in a matrix that is equivalent to constructing a single row matrix from the original blocks of that row.*)\nLemma submxcol_matrix B_ i :\n submxcol (\\mxblock_(i, j) B_ i j) i = \\mxrow_j B_ i j.\n\n(*This lemma states that a block matrix can be perfectly reconstructed by first decomposing it into its constituent blocks and then assembling those blocks back into their original grid arrangement.*)\nLemma submxblockK A : \\mxblock_(i, j) (submxblock A i j) = A.\n\n(*This lemma states that a matrix structured as a single row of blocks can be perfectly reconstructed by first extracting each block column and then arranging them horizontally.*)\nLemma submxrowK m (A : 'M[T]_(m, sq)) : \\mxrow_j (submxrow A j) = A.\n\n(*This lemma states that a matrix structured as a single column of blocks can be perfectly reconstructed by first extracting each block row and then stacking them vertically.*)\nLemma submxcolK n (A : 'M[T]_(sp, n)) : \\mxcol_i (submxcol A i) = A.\n\n(*This lemma establishes the injectivity of the block matrix constructor. It states that if two block matrices, constructed from two different collections of blocks, are equal, then their corresponding constituent blocks must also be equal at every position.*)\nLemma mxblockP A B :\n (forall i j, submxblock A i j = submxblock B i j) <-> A = B.\n\n(*This lemma states that two matrices are equal if and only if their corresponding block-rows, obtained by partitioning the matrices horizontally, are equal for every block-row index.*)\nLemma mxrowP m (A B : 'M_(m, sq)) :\n (forall j, submxrow A j = submxrow B j) <-> A = B.\n\n(*This lemma states that two matrices are equal if and only if their corresponding block-columns, obtained by partitioning the matrices vertically, are equal for every block-column index.*)\nLemma mxcolP n (A B : 'M_(sp, n)) :\n (forall i, submxcol A i = submxcol B i) <-> A = B.\n\n(*This lemma states that two block matrices are equal if and only if their corresponding constituent sub-matrices, at every block-row and block-column index, are equal.*)\nLemma eq_mxblockP A_ B_ :\n (forall i j, A_ i j = B_ i j) <->\n (\\mxblock_(i, j) A_ i j = \\mxblock_(i, j) B_ i j).\n\n(*This lemma states that if two collections of matrices are element-wise equal for all block indices, then the block matrices constructed from them are equal.*)\nLemma eq_mxblock A_ B_ :\n (forall i j, A_ i j = B_ i j) ->\n (\\mxblock_(i, j) A_ i j = \\mxblock_(i, j) B_ i j).\n\n(*This lemma states that two block matrices formed by concatenating sub-matrices horizontally are equal if and only if their corresponding constituent sub-matrices are equal for every block-column index.*)\nLemma eq_mxrowP m (A_ B_ : forall j, 'M[T]_(m, q_ j)) :\n (forall j, A_ j = B_ j) <-> (\\mxrow_j A_ j = \\mxrow_j B_ j).\n\n(*This lemma states that if two collections of matrices are element-wise equal for every block-column index, then the block matrices formed by concatenating them horizontally are equal.*)\nLemma eq_mxrow m (A_ B_ : forall j, 'M[T]_(m, q_ j)) :\n (forall j, A_ j = B_ j) -> (\\mxrow_j A_ j = \\mxrow_j B_ j).\n\n(*This lemma states that two block matrices formed by concatenating sub-matrices vertically are equal if and only if their corresponding constituent sub-matrices are equal for every block-row index.*)\nLemma eq_mxcolP n (A_ B_ : forall i, 'M[T]_(p_ i, n)) :\n (forall i, A_ i = B_ i) <-> (\\mxcol_i A_ i = \\mxcol_i B_ i).\n\n(*This lemma states that if two collections of matrices are element-wise equal for every block-row index, then the block matrices formed by concatenating them vertically are equal.*)\nLemma eq_mxcol n (A_ B_ : forall i, 'M[T]_(p_ i, n)) :\n (forall i, A_ i = B_ i) -> (\\mxcol_i A_ i = \\mxcol_i B_ i).\n\n(*This lemma states that the i-th row of a block matrix built by horizontal concatenation of sub-matrices is equal to the block matrix formed by horizontally concatenating the i-th rows of each of the original sub-matrices.*)\nLemma row_mxrow m (B_ : forall j, 'M[T]_(m, q_ j)) i :\n row i (\\mxrow_j B_ j) = \\mxrow_j (row i (B_ j)).\n\n(*This lemma states that a column of a block matrix built by horizontal concatenation is equal to a specific column taken from one of the constituent sub-matrices, where the sub-matrix and the column index within it are determined by the original column index.*)\nLemma col_mxrow m (B_ : forall j, 'M[T]_(m, q_ j)) j :\n col j (\\mxrow_j B_ j) = col (sig2 j) (B_ (sig1 j)).\n\n(*This lemma states that a row of a block matrix built by vertical concatenation is equal to a specific row taken from one of the constituent sub-matrices, where the sub-matrix and the row index within it are determined by the original row index.*)\nLemma row_mxcol n (B_ : forall i, 'M[T]_(p_ i, n)) i :\n row i (\\mxcol_i B_ i) = row (sig2 i) (B_ (sig1 i)).\n\n(*This lemma states that the j-th column of a block matrix built by vertical concatenation of sub-matrices is equal to the block matrix formed by vertically concatenating the j-th columns of each of the original sub-matrices.*)\nLemma col_mxcol n (B_ : forall i, 'M[T]_(p_ i, n)) j :\n col j (\\mxcol_i B_ i) = \\mxcol_i (col j (B_ i)).\n\n(*This lemma states that a specific row of a general block matrix is equivalent to a row block matrix formed by horizontally concatenating the corresponding rows from the sub-matrices within the appropriate block-row.*)\nLemma row_mxblock B_ i :\n row i (\\mxblock_(i, j) B_ i j) = \\mxrow_j row (sig2 i) (B_ (sig1 i) j).\n\n(*This lemma states that a specific column of a general block matrix is equivalent to a column block matrix formed by vertically concatenating the corresponding columns from the sub-matrices within the appropriate block-column.*)\nLemma col_mxblock B_ j :\n col j (\\mxblock_(i, j) B_ i j) = \\mxcol_i col (sig2 j) (B_ i (sig1 j)).\n\nEnd BlockMatrix.\n\n(*This is a notation for constructing a block matrix from a family of sub-matrices indexed by a pair of bounded natural numbers. The first bound specifies the number of block-rows and the second specifies the number of block-columns.*)\nNotation \"\\mxblock_ ( i < m , j < n ) E\" :=\n (mxblock (fun (i : 'I_m) (j : 'I_ n) => E)) (only parsing) : ring_scope.\n(*This is a shorthand notation for constructing a square block matrix where the number of block-rows and block-columns are equal to a given bound.*)\nNotation \"\\mxblock_ ( i , j < n ) E\" :=\n (\\mxblock_(i < n, j < n) E) (only parsing) : ring_scope.\n(*This is a shorthand notation for constructing a block matrix where the number of block-rows and block-columns are inferred from the context.*)\nNotation \"\\mxblock_ ( i , j ) E\" := (\\mxblock_(i < _, j < _) E) : ring_scope.\n(*This is a notation for constructing a block matrix by horizontally concatenating a family of sub-matrices indexed by a bounded natural number, which specifies the number of block-columns.*)\nNotation \"\\mxrow_ ( j < m ) E\" := (mxrow (fun (j : 'I_m) => E))\n (only parsing) : ring_scope.\n(*This is a shorthand notation for constructing a block matrix by horizontally concatenating a family of sub-matrices, where the number of sub-matrices is inferred from the context.*)\nNotation \"\\mxrow_ j E\" := (\\mxrow_(j < _) E) : ring_scope.\n(*This is a notation for constructing a block matrix by vertically concatenating a family of sub-matrices indexed by a bounded natural number, which specifies the number of block-rows.*)\nNotation \"\\mxcol_ ( i < m ) E\" := (mxcol (fun (i : 'I_m) => E))\n (only parsing) : ring_scope.\n(*This is a shorthand notation for constructing a block matrix by vertically concatenating a family of sub-matrices, where the number of sub-matrices is inferred from the context.*)\nNotation \"\\mxcol_ i E\" := (\\mxcol_(i < _) E) : ring_scope.\n\n(*This lemma states that the transpose of a block matrix is a block matrix where each constituent block at block-position (i, j) is the transpose of the original block at position (j, i).*)\nLemma tr_mxblock {T : Type} {p q : nat} {p_ : 'I_p -> nat} {q_ : 'I_q -> nat}\n (B_ : forall i j, 'M[T]_(p_ i, q_ j)) :\n (\\mxblock_(i, j) B_ i j)^T = \\mxblock_(i, j) (B_ j i)^T.\n\nSection SquareBlockMatrix.\n\nContext {T : Type} {p : nat} {p_ : 'I_p -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `p`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sp := (\\sum_i p_ i)%N.\nImplicit Type (s : 'I_sp).\n\n(*This lemma states that the transpose of a block matrix formed by horizontal concatenation of sub-matrices is equal to the block matrix formed by vertically concatenating the transposes of those sub-matrices.*)\nLemma tr_mxrow n (B_ : forall j, 'M[T]_(n, p_ j)) :\n (\\mxrow_j B_ j)^T = \\mxcol_i (B_ i)^T.\n\n(*This lemma states that the transpose of a block matrix formed by vertical concatenation of sub-matrices is equal to the block matrix formed by horizontally concatenating the transposes of those sub-matrices.*)\nLemma tr_mxcol n (B_ : forall i, 'M[T]_(p_ i, n)) :\n (\\mxcol_i B_ i)^T = \\mxrow_i (B_ i)^T.\n\n(*This lemma states that the transpose of a sub-matrix at block-position (i, j) within a larger matrix is equal to the sub-matrix at block-position (j, i) of the transposed larger matrix.*)\nLemma tr_submxblock (A : 'M[T]_sp) i j :\n (submxblock A i j)^T = (submxblock A^T j i).\n\n(*This lemma states that the transpose of a sub-matrix corresponding to the j-th block-row of a given matrix is equal to the sub-matrix corresponding to the j-th block-column of the transposed matrix.*)\nLemma tr_submxrow n (A : 'M[T]_(n, sp)) j :\n (submxrow A j)^T = (submxcol A^T j).\n\n(*This lemma states that the transpose of a sub-matrix corresponding to the i-th block-column of a given matrix is equal to the sub-matrix corresponding to the i-th block-row of the transposed matrix.*)\nLemma tr_submxcol n (A : 'M[T]_(sp, n)) i :\n (submxcol A i)^T = (submxrow A^T i).\n\nEnd SquareBlockMatrix.\n\nSection BlockRowRecL.\nImport tagnat.\nContext {T : Type} {m : nat} {p_ : 'I_m.+1 -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `p`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sp := (\\sum_i p_ i)%N.\n\n(*This lemma states that the sum of a sequence of natural numbers can be computed recursively by adding the first element of the sequence to the sum of the remaining elements.*)\nLemma mxsize_recl : (p_ ord0 + \\sum_i p_ (lift ord0 i) = (\\sum_i p_ i))%N.\n\n(*This lemma provides a recursive formula for constructing a matrix from a row of block matrices, stating that it is equivalent to horizontally concatenating the first block matrix with the matrix constructed from the rest of the blocks.*)\nLemma mxrow_recl n (B_ : forall j, 'M[T]_(n, p_ j)) :\n \\mxrow_j B_ j = castmx (erefl, mxsize_recl)\n (row_mx (B_ 0) (\\mxrow_j B_ (lift ord0 j))).\n\nEnd BlockRowRecL.\n\n(*This lemma provides a recursive formula for constructing a matrix from a column of block matrices, stating that it is equivalent to vertically concatenating the first block matrix with the matrix constructed from the rest of the blocks.*)\nLemma mxcol_recu {T : Type} {p : nat} {p_ : 'I_p.+1 -> nat} m\n (B_ : forall j, 'M[T]_(p_ j, m)) :\n \\mxcol_j B_ j = castmx (mxsize_recl, erefl)\n (col_mx (B_ 0) (\\mxcol_j B_ (lift ord0 j))).\n\nSection BlockMatrixRec.\n(*This notation defines e as a pair of proofs that justify reshaping a matrix, where both row and column dimensions are derived from a recursive sum decomposition.*)\nLocal Notation e := (mxsize_recl, mxsize_recl).\n(*This notation defines l0 as an index transformation that shifts an ordinal index to represent the sequence of indices starting from the second element, which is used for recursive definitions.*)\nLocal Notation l0 := (lift ord0).\nContext {T : Type}.\n\n(*This lemma provides a recursive formula for constructing a block matrix, expressing it as the vertical concatenation of the first row of blocks and the block matrix formed by the remaining rows.*)\nLemma mxblock_recu {p q : nat} {p_ : 'I_p.+1 -> nat} {q_ : 'I_q -> nat}\n (B_ : forall i j, 'M[T]_(p_ i, q_ j)) :\n \\mxblock_(i, j) B_ i j = castmx (mxsize_recl, erefl) (col_mx\n (\\mxrow_j B_ ord0 j)\n (\\mxblock_(i, j) B_ (l0 i) j)).\n\n(*This lemma provides a recursive formula for constructing a block matrix, expressing it as the horizontal concatenation of the first column of blocks and the block matrix formed by the remaining columns.*)\nLemma mxblock_recl {p q : nat} {p_ : 'I_p -> nat} {q_ : 'I_q.+1 -> nat}\n (B_ : forall i j, 'M[T]_(p_ i, q_ j)) :\n \\mxblock_(i, j) B_ i j = castmx (erefl, mxsize_recl)\n (row_mx (\\mxcol_i B_ i ord0) (\\mxblock_(i, j) B_ i (l0 j))).\n\n(*This lemma provides a fully recursive formula for constructing a block matrix, decomposing it into its top-left block, the rest of the first row of blocks, the rest of the first column of blocks, and the block matrix of the remaining elements.*)\nLemma mxblock_recul {p q : nat} {p_ : 'I_p.+1 -> nat} {q_ : 'I_q.+1 -> nat}\n (B_ : forall i j, 'M[T]_(p_ i, q_ j)) :\n \\mxblock_(i, j) B_ i j = castmx e (block_mx\n (B_ 0 0) (\\mxrow_j B_ ord0 (l0 j))\n (\\mxcol_i B_ (l0 i) ord0) (\\mxblock_(i, j) B_ (l0 i) (l0 j))).\n\n(*This lemma states that a matrix formed by horizontally concatenating a sequence of block matrices is equivalent to a block matrix with a single row.*)\nLemma mxrowEblock {q : nat} {q_ : 'I_q -> nat} m\n (R_ : forall j, 'M[T]_(m, q_ j)) :\n (\\mxrow_j R_ j) =\n castmx (big_ord1 _ (fun=> m), erefl) (\\mxblock_(i < 1, j < q) R_ j).\n\n(*This lemma states that a matrix formed by vertically concatenating a sequence of block matrices is equivalent to a block matrix with a single column.*)\nLemma mxcolEblock {p : nat} {p_ : 'I_p -> nat} n\n (C_ : forall i, 'M[T]_(p_ i, n)) :\n (\\mxcol_i C_ i) =\n castmx (erefl, big_ord1 _ (fun=> n)) (\\mxblock_(i < p, j < 1) C_ i).\n\n(*This lemma states that any matrix is equal to the matrix formed by horizontally concatenating all of its individual columns.*)\nLemma mxEmxrow m n (A : 'M[T]_(m, n)) :\n A = castmx (erefl, big_ord1 _ (fun=> n)) (\\mxrow__ A).\n\n(*This lemma states that any matrix is equal to the matrix formed by vertically concatenating all of its individual rows.*)\nLemma mxEmxcol m n (A : 'M[T]_(m, n)) :\n A = castmx (big_ord1 _ (fun=> m), erefl) (\\mxcol__ A).\n\n(*This lemma states that any matrix is equivalent to a one-by-one block matrix where the only block is the matrix itself.*)\nLemma mxEmxblock m n (A : 'M[T]_(m, n)) :\n A = castmx (big_ord1 _ (fun=> m), big_ord1 _ (fun=> n))\n (\\mxblock_(i < 1, j < 1) A).\n\nEnd BlockMatrixRec.\n\nSection BlockRowZmod.\nContext {V : zmodType} {q : nat} {q_ : 'I_q -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `q`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sq := (\\sum_i q_ i)%N.\nImplicit Type (s : 'I_sq).\n\n(*This lemma states that the horizontal concatenation of a sum of two families of block matrices is equal to the sum of the horizontal concatenations of each family.*)\nLemma mxrowD m (R_ R'_ : forall j, 'M[V]_(m, q_ j)) :\n \\mxrow_j (R_ j + R'_ j) = \\mxrow_j (R_ j) + \\mxrow_j (R'_ j).\n\n(*This lemma states that the horizontal concatenation of the additive inverses of a family of block matrices is equal to the additive inverse of the horizontal concatenation of the original family of matrices.*)\nLemma mxrowN m (R_ : forall j, 'M[V]_(m, q_ j)) :\n \\mxrow_j (- R_ j) = - \\mxrow_j (R_ j).\n\n(*This lemma states that the horizontal concatenation of the difference of two families of block matrices is equal to the difference of the horizontal concatenations of each family.*)\nLemma mxrowB m (R_ R'_ : forall j, 'M[V]_(m, q_ j)) :\n \\mxrow_j (R_ j - R'_ j) = \\mxrow_j (R_ j) - \\mxrow_j (R'_ j).\n\n(*This lemma states that the horizontal concatenation of a family of zero matrices results in a zero matrix.*)\nLemma mxrow0 m : \\mxrow_j (0 : 'M[V]_(m, q_ j)) = 0.\n\n(*This lemma states that horizontally concatenating a family of constant matrices, all with the same entry value, results in a single large constant matrix with that same entry value.*)\nLemma mxrow_const m a : \\mxrow_j (const_mx a : 'M[V]_(m, q_ j)) = const_mx a.\n\n(*This lemma states that the horizontal concatenation of a sum of indexed families of matrices is equal to the sum of the horizontal concatenations of each family.*)\nLemma mxrow_sum (J : finType) m\n (R_ : forall i j, 'M[V]_(m, q_ j)) (P : {pred J}) :\n \\mxrow_j (\\sum_(i | P i) R_ i j) = \\sum_(i | P i) \\mxrow_j (R_ i j).\n\n(*This lemma states that extracting a specific columnar block from a sum of two matrices is equivalent to summing the corresponding columnar blocks extracted from each matrix individually.*)\nLemma submxrowD m (B B' : 'M[V]_(m, sq)) j :\n submxrow (B + B') j = submxrow B j + submxrow B' j.\n\n(*This lemma states that extracting a specific columnar block from the additive inverse of a matrix is equivalent to taking the additive inverse of the corresponding columnar block extracted from the original matrix.*)\nLemma submxrowN m (B : 'M[V]_(m, sq)) j :\n submxrow (- B) j = - submxrow B j.\n\n(*This lemma states that extracting a specific columnar block from the difference of two matrices is equivalent to the difference of the corresponding columnar blocks extracted from each matrix.*)\nLemma submxrowB m (B B' : 'M[V]_(m, sq)) j :\n submxrow (B - B') j = submxrow B j - submxrow B' j.\n\n(*This lemma states that extracting a columnar block from a zero matrix results in a zero matrix.*)\nLemma submxrow0 m j : submxrow (0 : 'M[V]_(m, sq)) j = 0.\n\n(*This lemma states that extracting a specific columnar block from a sum of matrices is equivalent to summing the corresponding columnar blocks extracted from each matrix in the sum.*)\nLemma submxrow_sum (J : finType) m\n (R_ : forall i, 'M[V]_(m, sq)) (P : {pred J}) j:\n submxrow (\\sum_(i | P i) R_ i) j = \\sum_(i | P i) submxrow (R_ i) j.\n\nEnd BlockRowZmod.\n\nSection BlockRowRing.\nContext {R : pzRingType} {n : nat} {q_ : 'I_n -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `q`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sq := (\\sum_i q_ i)%N.\nImplicit Type (s : 'I_sq).\n\n(*This lemma states that the product of a matrix and a horizontally-partitioned block matrix is equal to the horizontally-partitioned block matrix formed by multiplying the matrix with each individual block.*)\nLemma mul_mxrow m n' (A : 'M[R]_(m, n')) (R_ : forall j, 'M[R]_(n', q_ j)) :\n A *m \\mxrow_j R_ j= \\mxrow_j (A *m R_ j).\n\n(*This lemma states that multiplying a matrix by a horizontal block extracted from a second matrix yields the same result as first multiplying the two matrices and then extracting the corresponding horizontal block from the product matrix.*)\nLemma mul_submxrow m n' (A : 'M[R]_(m, n')) (B : 'M[R]_(n', sq)) j :\n A *m submxrow B j= submxrow (A *m B) j.\n\nEnd BlockRowRing.\n\nSection BlockColZmod.\nContext {V : zmodType} {n : nat} {p_ : 'I_n -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `p`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sp := (\\sum_i p_ i)%N.\nImplicit Type (s : 'I_sp).\n\n(*This lemma states that constructing a vertical block matrix from a family of matrix sums is equivalent to summing the vertical block matrices constructed from each family of matrices separately.*)\nLemma mxcolD m (C_ C'_ : forall i, 'M[V]_(p_ i, m)) :\n \\mxcol_i (C_ i + C'_ i) = \\mxcol_i (C_ i) + \\mxcol_i (C'_ i).\n\n(*This lemma states that constructing a vertical block matrix from the additive inverses of a family of matrices is equivalent to taking the additive inverse of the vertical block matrix formed from the original family of matrices.*)\nLemma mxcolN m (C_ : forall i, 'M[V]_(p_ i, m)) :\n \\mxcol_i (- C_ i) = - \\mxcol_i (C_ i).\n\n(*This lemma states that constructing a vertical block matrix from a family of matrix differences is equivalent to the difference of the two vertical block matrices constructed from each family of matrices.*)\nLemma mxcolB m (C_ C'_ : forall i, 'M[V]_(p_ i, m)) :\n \\mxcol_i (C_ i - C'_ i) = \\mxcol_i (C_ i) - \\mxcol_i (C'_ i).\n\n(*This lemma states that a vertical block matrix constructed from a family of zero matrices is itself a zero matrix.*)\nLemma mxcol0 m : \\mxcol_i (0 : 'M[V]_(p_ i, m)) = 0.\n\n(*This lemma states that a vertical block matrix constructed from a family of constant matrices, all filled with the same value, is itself a constant matrix filled with that same value.*)\nLemma mxcol_const m a : \\mxcol_j (const_mx a : 'M[V]_(p_ j, m)) = const_mx a.\n\n(*This lemma states that the operations of summation over a family of matrices and construction of a vertical block matrix commute. Specifically, creating a vertical block matrix from a sum of matrix families is equivalent to summing the vertical block matrices created from each family individually.*)\nLemma mxcol_sum\n (I : finType) m (C_ : forall j i, 'M[V]_(p_ i, m)) (P : {pred I}):\n \\mxcol_i (\\sum_(j | P j) C_ j i) = \\sum_(j | P j) \\mxcol_i (C_ j i).\n\n(*This lemma states that a vertical block extracted from the sum of two matrices is equal to the sum of the corresponding vertical blocks extracted from each of the two matrices.*)\nLemma submxcolD m (B B' : 'M[V]_(sp, m)) i :\n submxcol (B + B') i = submxcol B i + submxcol B' i.\n\n(*This lemma states that a vertical block extracted from the additive inverse of a matrix is equal to the additive inverse of the corresponding vertical block extracted from the original matrix.*)\nLemma submxcolN m (B : 'M[V]_(sp, m)) i :\n submxcol (- B) i = - submxcol B i.\n\n(*This lemma states that a vertical block extracted from the difference of two matrices is equal to the difference of the corresponding vertical blocks extracted from each of the two matrices.*)\nLemma submxcolB m (B B' : 'M[V]_(sp, m)) i :\n submxcol (B - B') i = submxcol B i - submxcol B' i.\n\n(*This lemma states that any vertical block extracted from a zero matrix is also a zero matrix.*)\nLemma submxcol0 m i : submxcol (0 : 'M[V]_(sp, m)) i = 0.\n\n(*This lemma states that the operations of summation over a family of matrices and extraction of a vertical block commute. Specifically, extracting a vertical block from a sum of matrices is equivalent to summing the corresponding vertical blocks extracted from each matrix individually.*)\nLemma submxcol_sum (I : finType) m\n (C_ : forall j, 'M[V]_(sp, m)) (P : {pred I}) i :\n submxcol (\\sum_(j | P j) C_ j) i = \\sum_(j | P j) submxcol (C_ j) i.\n\nEnd BlockColZmod.\n\nSection BlockColRing.\nContext {R : pzRingType} {n : nat} {p_ : 'I_n -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `p`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sp := (\\sum_i p_ i)%N.\nImplicit Type (s : 'I_sp).\n\n(*This lemma states that multiplying a block column matrix on the right by another matrix is equivalent to forming a new block column matrix where each block is the product of the corresponding original block and the right-hand matrix.*)\nLemma mxcol_mul n' m (C_ : forall i, 'M[R]_(p_ i, n')) (A : 'M[R]_(n', m)) :\n \\mxcol_i C_ i *m A = \\mxcol_i (C_ i *m A).\n\n(*This lemma states that extracting the i-th block row from a matrix and then multiplying it on the right by a second matrix is equivalent to first multiplying the two matrices and then extracting the i-th block row from the resulting product.*)\nLemma submxcol_mul n' m (B : 'M[R]_(sp, n')) (A : 'M[R]_(n', m)) i :\n submxcol B i *m A = submxcol (B *m A) i.\n\nEnd BlockColRing.\n\nSection BlockMatrixZmod.\nContext {V : zmodType} {m n : nat}.\nContext {p_ : 'I_m -> nat} {q_ : 'I_n -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `p`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sp := (\\sum_i p_ i)%N.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `q`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sq := (\\sum_i q_ i)%N.\n\n(*This lemma states that the construction of a block matrix distributes over addition, meaning that a block matrix formed from the sum of corresponding blocks is equal to the sum of the block matrices formed from the individual sets of blocks.*)\nLemma mxblockD (B_ B'_ : forall i j, 'M[V]_(p_ i, q_ j)) :\n \\mxblock_(i, j) (B_ i j + B'_ i j) =\n \\mxblock_(i, j) (B_ i j) + \\mxblock_(i, j) (B'_ i j).\n\n(*This lemma states that constructing a block matrix from the additive inverses of its component blocks is equivalent to taking the additive inverse of the block matrix constructed from the original blocks.*)\nLemma mxblockN (B_ : forall i j, 'M[V]_(p_ i, q_ j)) :\n \\mxblock_(i, j) (- B_ i j) = - \\mxblock_(i, j) (B_ i j).\n\n(*This lemma states that the construction of a block matrix distributes over subtraction, meaning a block matrix formed from the difference of corresponding blocks is equal to the difference of the block matrices formed from the individual sets of blocks.*)\nLemma mxblockB (B_ B'_ : forall i j, 'M[V]_(p_ i, q_ j)) :\n \\mxblock_(i, j) (B_ i j - B'_ i j) =\n \\mxblock_(i, j) (B_ i j) - \\mxblock_(i, j) (B'_ i j).\n\n(*This lemma states that a block matrix constructed entirely from zero-matrix blocks is itself the zero matrix.*)\nLemma mxblock0 : \\mxblock_(i, j) (0 : 'M[V]_(p_ i, q_ j)) = 0.\n\n(*This lemma states that a block matrix constructed from blocks that are all constant matrices filled with a specific value is itself a constant matrix filled with that same value.*)\nLemma mxblock_const a :\n \\mxblock_(i, j) (const_mx a : 'M[V]_(p_ i, q_ j)) = const_mx a.\n\n(*This lemma states that the block matrix constructor commutes with finite summation, meaning that constructing a block matrix from blocks that are each defined as a sum of matrices over a finite set is equivalent to summing the block matrices constructed from each corresponding term of the sum.*)\nLemma mxblock_sum (I : finType)\n (B_ : forall k i j, 'M[V]_(p_ i, q_ j)) (P : {pred I}):\n \\mxblock_(i, j) (\\sum_(k | P k) B_ k i j) =\n \\sum_(k | P k) \\mxblock_(i, j) (B_ k i j).\n\n(*This lemma states that the operation of extracting a specific sub-block from a matrix distributes over matrix addition. The sub-block of a sum of two matrices is equal to the sum of the corresponding sub-blocks of each matrix.*)\nLemma submxblockD (B B' : 'M[V]_(sp, sq)) i j :\n submxblock (B + B') i j = submxblock B i j + submxblock B' i j.\n\n(*This lemma states that the operation of extracting a sub-block from a matrix commutes with taking the additive inverse, which means the sub-block of the negative of a matrix is equal to the negative of the corresponding sub-block of the original matrix.*)\nLemma submxblockN (B : 'M[V]_(sp, sq)) i j :\n submxblock (- B) i j = - submxblock B i j.\n\n(*This lemma states that the operation of extracting a specific sub-block from a matrix distributes over matrix subtraction. The sub-block of the difference of two matrices is equal to the difference of the corresponding sub-blocks of each matrix.*)\nLemma submxblockB (B B' : 'M[V]_(sp, sq)) i j :\n submxblock (B - B') i j = submxblock B i j - submxblock B' i j.\n\n(*This lemma states that any sub-block extracted from a zero matrix is also a zero matrix.*)\nLemma submxblock0 i j : submxblock (0 : 'M[V]_(sp, sq)) i j = 0.\n\n(*This lemma states that the operation of extracting a sub-block commutes with finite summation. The sub-block of a matrix that is a sum of matrices over a finite set is equal to the sum of the corresponding sub-blocks from each matrix in the sum.*)\nLemma submxblock_sum (I : finType)\n (B_ : forall k, 'M[V]_(sp, sq)) (P : {pred I}) i j :\n submxblock (\\sum_(k | P k) B_ k) i j = \\sum_(k | P k) submxblock (B_ k) i j.\n\nEnd BlockMatrixZmod.\n\nSection BlockMatrixRing.\nContext {R : pzRingType} {p q : nat} {p_ : 'I_p -> nat} {q_ : 'I_q -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `p`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sp := (\\sum_i p_ i)%N.\n(*A notation representing the total number of columns of a block matrix, calculated as the sum of the number of columns of each block in a row.*)\nNotation sq := (\\sum_i q_ i)%N.\n\n(*This lemma states that the matrix product of a block row matrix and a block column matrix is equal to the sum of the matrix products of their corresponding blocks, assuming the inner block dimensions are compatible.*)\nLemma mul_mxrow_mxcol m n\n (R_ : forall j, 'M[R]_(m, p_ j)) (C_ : forall i, 'M[R]_(p_ i, n)) :\n \\mxrow_j R_ j *m \\mxcol_i C_ i = \\sum_i (R_ i *m C_ i).\n\n(*This lemma states that the matrix product of a block column matrix and a block row matrix yields a new block matrix, where each block at a specific row and column index is the matrix product of the corresponding input blocks from the column matrix and the row matrix, respectively.*)\nLemma mul_mxcol_mxrow m\n (C_ : forall i, 'M[R]_(p_ i, m)) (R_ : forall j, 'M[R]_(m, q_ j)) :\n \\mxcol_i C_ i*m \\mxrow_j R_ j = \\mxblock_(i, j) (C_ i *m R_ j).\n\n(*This lemma provides the formula for multiplying a block row matrix by a generic block matrix. The result is a block row matrix where each block is the sum of the matrix products of the blocks from the input row matrix with the corresponding blocks from a column of the generic block matrix.*)\nLemma mul_mxrow_mxblock m\n (R_ : forall i, 'M[R]_(m, p_ i)) (B_ : forall i j, 'M[R]_(p_ i, q_ j)) :\n \\mxrow_i R_ i *m \\mxblock_(i, j) B_ i j = \\mxrow_j (\\sum_i (R_ i *m B_ i j)).\n\n(*This lemma provides the formula for multiplying a generic block matrix by a block column matrix. The result is a block column matrix where each block at a given row index is computed as the sum of matrix products of the blocks from the corresponding row of the generic matrix and the blocks of the input column matrix.*)\nLemma mul_mxblock_mxrow m\n (B_ : forall i j, 'M[R]_(q_ i, p_ j)) (C_ : forall i, 'M[R]_(p_ i, m)) :\n \\mxblock_(i, j) B_ i j *m \\mxcol_j C_ j = \\mxcol_i (\\sum_j (B_ i j *m C_ j)).\n\nEnd BlockMatrixRing.\n\n(*This lemma states the general formula for multiplying two compatible block matrices. The product is a block matrix where each block at a given row and column index is the sum of the matrix products of the blocks from the corresponding row of the first matrix and the corresponding column of the second matrix.*)\nLemma mul_mxblock {R : pzRingType} {p q r : nat}\n {p_ : 'I_p -> nat} {q_ : 'I_q -> nat} {r_ : 'I_r -> nat}\n (A_ : forall i j, 'M[R]_(p_ i, q_ j)) (B_ : forall j k, 'M_(q_ j, r_ k)) :\n \\mxblock_(i, j) A_ i j *m \\mxblock_(j, k) B_ j k =\n \\mxblock_(i, k) \\sum_j (A_ i j *m B_ j k).\n\nSection SquareBlockMatrixZmod.\nImport Order.TTheory tagnat.\nContext {V : zmodType} {p : nat} {p_ : 'I_p -> nat}.\n(*A notation that computes the sum of the elements of a sequence of natural numbers, a sequence that is syntactically denoted as `p`. It is typically used to calculate total dimensions from block partitions.*)\nNotation sp := (\\sum_i p_ i)%N.\nImplicit Type (s : 'I_sp).\n\n(*This lemma establishes the equivalence between a square block matrix being upper-triangular and two properties: first, that every block below the main diagonal is a zero matrix, and second, that every block on the main diagonal is itself an upper-triangular matrix.*)\nLemma is_trig_mxblockP (B_ : forall i j, 'M[V]_(p_ i, p_ j)) :\n reflect [/\\ forall (i j : 'I_p), (i < j)%N -> B_ i j = 0 &\n forall i, is_trig_mx (B_ i i)]\n (is_trig_mx (\\mxblock_(i, j) B_ i j)).\n\n(*This lemma states that the boolean property of a square block matrix being upper-triangular is equal to the boolean conjunction of two conditions: first, that for any block indices where the row index is less than the column index, the corresponding block is a zero matrix, and second, that all blocks on the main diagonal are themselves upper-triangular.*)\nLemma is_trig_mxblock (B_ : forall i j, 'M[V]_(p_ i, p_ j)) :\n is_trig_mx (\\mxblock_(i, j) B_ i j) =\n ([forall i : 'I_p, forall j : 'I_p, (i < j)%N ==> (B_ i j == 0)] &&\n [forall i, is_trig_mx (B_ i i)]).\n\n(*This lemma establishes the equivalence between a square block matrix being diagonal and two properties: first, that every block not on the main diagonal is a zero matrix, and second, that every block on the main diagonal is itself a diagonal matrix.*)\nLemma is_diag_mxblockP (B_ : forall i j, 'M[V]_(p_ i, p_ j)) :\n reflect [/\\ forall (i j : 'I_p), i != j -> B_ i j = 0 &\n forall i, is_diag_mx (B_ i i)]\n (is_diag_mx (\\mxblock_(i, j) B_ i j)).\n\n(*This lemma states that the boolean property of a square block matrix being diagonal is equal to the boolean conjunction of two conditions: first, that for any distinct block indices, the corresponding block is a zero matrix, and second, that all blocks on the main diagonal are themselves diagonal matrices.*)\nLemma is_diag_mxblock (B_ : forall i j, 'M[V]_(p_ i, p_ j)) :\n is_diag_mx (\\mxblock_(i, j) B_ i j) =\n ([forall i : 'I_p, forall j : 'I_p, (i != j) ==> (B_ i j == 0)] &&\n [forall i, is_diag_mx (B_ i i)]).\n\n(*This definition constructs a block diagonal matrix from a given family of square matrices. The resulting matrix has the given matrices as its diagonal blocks and zero matrices for all off-diagonal blocks.*)\nDefinition mxdiag (B_ : forall i, 'M[V]_(p_ i)) : 'M[V]_(\\sum_i p_ i) :=\n \\mxblock_(j, k) if j == k then conform_mx 0 (B_ j) else 0.\n(*This notation provides a syntax for constructing a block diagonal matrix from an expression that defines the diagonal blocks. The expression is evaluated for each block index to produce the corresponding square matrix on the main diagonal.*)\nLocal Notation \"\\mxdiag_ i E\" := (mxdiag (fun i => E)) : ring_scope.\n\n(*This lemma states that extracting a diagonal block from a block diagonal matrix, using a given block index, yields the original matrix from the input family that corresponds to that same index.*)\nLemma submxblock_diag (B_ : forall i, 'M[V]_(p_ i)) i :\n submxblock (\\mxdiag_i B_ i) i i = B_ i.\n\n(*This lemma states that two block diagonal matrices are equal if and only if their respective families of diagonal blocks are element-wise equal.*)\nLemma eq_mxdiagP (B_ B'_ : forall i, 'M[V]_(p_ i)) :\n (forall i, B_ i = B'_ i) <-> (\\mxdiag_i B_ i = \\mxdiag_i B'_ i).\n\n(*This lemma states that if two families of square matrices are element-wise equal, then the block diagonal matrices constructed from them are also equal.*)\nLemma eq_mxdiag (B_ B'_ : forall i, 'M[V]_(p_ i)) :\n (forall i, B_ i = B'_ i) -> (\\mxdiag_i B_ i = \\mxdiag_i B'_ i).\n\n(*This lemma states that the construction of a block diagonal matrix distributes over matrix addition. The block diagonal matrix formed from the element-wise sum of two families of matrices is equal to the sum of the block diagonal matrices formed from each family individually.*)\nLemma mxdiagD (B_ B'_ : forall i, 'M[V]_(p_ i)) :\n \\mxdiag_i (B_ i + B'_ i) = \\mxdiag_i (B_ i) + \\mxdiag_i (B'_ i).\n\n(*This lemma states that the block diagonal matrix constructed from the element-wise additive inverse of a family of matrices is equal to the additive inverse of the block diagonal matrix constructed from the original family.*)\nLemma mxdiagN (B_ : forall i, 'M[V]_(p_ i)) :\n \\mxdiag_i (- B_ i) = - \\mxdiag_i (B_ i).\n\n(*This lemma states that the construction of a block diagonal matrix distributes over matrix subtraction. The block diagonal matrix formed from the element-wise difference of two families of matrices is equal to the difference of the block diagonal matrices formed from each family individually.*)\nLemma mxdiagB (B_ B'_ : forall i, 'M[V]_(p_ i)) :\n \\mxdiag_i (B_ i - B'_ i) = \\mxdiag_i (B_ i) - \\mxdiag_i (B'_ i).\n\n(*This lemma states that a block diagonal matrix constructed from a family of zero matrices is equal to the zero matrix.*)\nLemma mxdiag0 : \\mxdiag_i (0 : 'M[V]_(p_ i)) = 0.\n\n(*This lemma states that the construction of a block diagonal matrix commutes with indexed summation. The block diagonal matrix whose diagonal blocks are formed by summing a doubly-indexed family of matrices over one index is equal to the sum, over that same index, of the block diagonal matrices formed from the inner family.*)\nLemma mxdiag_sum (I : finType) (B_ : forall k i, 'M[V]_(p_ i)) (P : {pred I}) :\n \\mxdiag_i (\\sum_(k | P k) B_ k i) = \\sum_(k | P k) \\mxdiag_i (B_ k i).\n\n(*This lemma states that the transpose of a block diagonal matrix is equal to the block diagonal matrix constructed from the element-wise transposes of the original family of diagonal blocks.*)\nLemma tr_mxdiag (B_ : forall i, 'M[V]_(p_ i)) :\n (\\mxdiag_i B_ i)^T = \\mxdiag_i (B_ i)^T.\n\n(*This lemma states that a specific row of a block diagonal matrix can be described in terms of a row of a block row matrix. The selected row of the block diagonal matrix is equivalent to a specific inner row of a block row matrix that contains the corresponding diagonal block at the correct block position and zero matrices elsewhere.*)\nLemma row_mxdiag (B_ : forall i, 'M[V]_(p_ i)) k :\n let B'_ i := if sig1 k == i then conform_mx 0 (B_ i) else 0 in\n row k (\\mxdiag_ i B_ i) = row (sig2 k) (\\mxrow_i B'_ i).\n\n(*This lemma states that a specific column of a block diagonal matrix can be described in terms of a column of a block column matrix. The selected column of the block diagonal matrix is equivalent to a specific inner column of a block column matrix that contains the corresponding diagonal block at the correct block position and zero matrices elsewhere.*)\nLemma col_mxdiag (B_ : forall i, 'M[V]_(p_ i)) k :\n let B'_ i := if sig1 k == i then conform_mx 0 (B_ i) else 0 in\n col k (\\mxdiag_ i B_ i) = col (sig2 k) (\\mxcol_i B'_ i).\n\nEnd SquareBlockMatrixZmod.\n\n(*This notation provides a syntax for constructing a block diagonal matrix where the number of blocks is explicitly given. The notation uses an index variable, an upper bound for that index, and an expression that generates each diagonal block matrix based on the index.*)\nNotation \"\\mxdiag_ ( i < n ) E\" := (mxdiag (fun i : 'I_n => E))\n (only parsing) : ring_scope.\n(*A notation for constructing a block-diagonal matrix from a sequence of smaller input matrices, where each input matrix is placed along the main diagonal of the resulting larger matrix.*)\nNotation \"\\mxdiag_ i E\" := (\\mxdiag_(i < _) E) : ring_scope.\n\n(*This lemma states that a block-diagonal matrix can be constructed recursively by placing the first matrix block at the top-left corner and then creating a smaller block-diagonal matrix for the remaining blocks.*)\nLemma mxdiag_recl {V : zmodType} {m : nat} {p_ : 'I_m.+1 -> nat}\n (B_ : forall i, 'M[V]_(p_ i)) :\n \\mxdiag_i B_ i = castmx (mxsize_recl, mxsize_recl)\n (block_mx (B_ 0) 0 0 (\\mxdiag_i B_ (lift ord0 i))).\n\nSection SquareBlockMatrixRing.\nImport tagnat.\nContext {R : pzRingType} {p : nat} {p_ : 'I_p -> nat}.\n(*A notation for the sum of a finite sequence of natural numbers, which typically represents the total number of rows in a block matrix that is partitioned according to that sequence.*)\nNotation sp := (\\sum_i p_ i)%N.\nImplicit Type (s : 'I_sp).\n\n(*This lemma states that the trace of a square block matrix is equal to the sum of the traces of its diagonal blocks.*)\nLemma mxtrace_mxblock (B_ : forall i j, 'M[R]_(p_ i, p_ j)) :\n \\tr (\\mxblock_(i, j) B_ i j) = \\sum_i \\tr (B_ i i).\n\n(*This lemma states that constructing a block-diagonal matrix where each block is a scalar matrix with the same scalar value results in a single larger scalar matrix with that same value along its diagonal.*)\nLemma mxdiagZ a : \\mxdiag_i (a%:M : 'M[R]_(p_ i)) = a%:M.\n\n(*This lemma states that creating a diagonal matrix from a row vector formed by concatenating several smaller row vectors is equivalent to constructing a block-diagonal matrix where each block is the diagonal matrix corresponding to one of the smaller row vectors.*)\nLemma diag_mxrow (B_ : forall j, 'rV[R]_(p_ j)) :\n diag_mx (\\mxrow_j B_ j) = \\mxdiag_j (diag_mx (B_ j)).\n\n(*This lemma states that the trace of a block-diagonal matrix is equal to the sum of the traces of its individual diagonal blocks.*)\nLemma mxtrace_mxdiag (B_ : forall i, 'M[R]_(p_ i)) :\n \\tr (\\mxdiag_i B_ i) = \\sum_i \\tr (B_ i).\n\n(*This lemma asserts that multiplying a block-diagonal matrix by a block-column matrix results in a new block-column matrix, where each block is the product of the corresponding diagonal block from the first matrix and the corresponding block from the column matrix.*)\nLemma mul_mxdiag_mxcol m\n (D_ : forall i, 'M[R]_(p_ i)) (C_ : forall i, 'M[R]_(p_ i, m)):\n \\mxdiag_i D_ i *m \\mxcol_i C_ i = \\mxcol_i (D_ i *m C_ i).\n\nEnd SquareBlockMatrixRing.\n\n(*This lemma asserts that multiplying a block-row matrix by a block-diagonal matrix results in a new block-row matrix, where each block is the product of the corresponding block from the row matrix and the corresponding diagonal block from the diagonal matrix.*)\nLemma mul_mxrow_mxdiag {R : pzRingType} {p : nat} {p_ : 'I_p -> nat} m\n (R_ : forall i, 'M[R]_(m, p_ i)) (D_ : forall i, 'M[R]_(p_ i)) :\n \\mxrow_i R_ i *m \\mxdiag_i D_ i = \\mxrow_i (R_ i *m D_ i).\n\n(*This lemma states that right-multiplying a block matrix by a block-diagonal matrix is equivalent to forming a new block matrix where each block is the result of right-multiplying the original block by the corresponding block from the diagonal matrix.*)\nLemma mul_mxblock_mxdiag {R : pzRingType} {p q : nat}\n {p_ : 'I_p -> nat} {q_ : 'I_q -> nat}\n (B_ : forall i j, 'M[R]_(p_ i, q_ j)) (D_ : forall j, 'M[R]_(q_ j)) :\n \\mxblock_(i, j) B_ i j *m \\mxdiag_j D_ j = \\mxblock_(i, j) (B_ i j *m D_ j).\n\n(*This lemma states that left-multiplying a block matrix by a block-diagonal matrix is equivalent to forming a new block matrix where each block is the result of left-multiplying the original block by the corresponding block from the diagonal matrix.*)\nLemma mul_mxdiag_mxblock {R : pzRingType} {p q : nat}\n {p_ : 'I_p -> nat} {q_ : 'I_q -> nat}\n (D_ : forall j, 'M[R]_(p_ j)) (B_ : forall i j, 'M[R]_(p_ i, q_ j)):\n \\mxdiag_j D_ j *m \\mxblock_(i, j) B_ i j = \\mxblock_(i, j) (D_ i *m B_ i j).\n\n(*This definition constructs a Vandermonde matrix of a given size from a row vector of ring elements. The entry at a specific row and column is the element of the vector corresponding to that column, raised to the power of the row index.*)\nDefinition Vandermonde (R : pzRingType) (m n : nat) (a : 'rV[R]_n) :=\n \\matrix_(i < m, j < n) a 0 j ^+ i.\n\n(*This lemma states that the determinant of a square Vandermonde matrix, generated from a sequence of ring elements, is the product of all possible differences between elements of the sequence, where each difference is calculated by subtracting an element from one that appears later in the sequence.*)\nLemma det_Vandermonde (R : comPzRingType) (n : nat) (a : 'rV[R]_n) :\n \\det (Vandermonde n a) = \\prod_(i < n) \\prod_(j < n | i < j) (a 0 j - a 0 i).", - "algebra.ring_quotient": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype choice ssrnat.\nFrom mathcomp Require Import seq ssralg generic_quotient.\n\nImport GRing.Theory.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope ring_scope.\nLocal Open Scope quotient_scope.\n\nReserved Notation \"{ 'ideal_quot' I }\" (format \"{ 'ideal_quot' I }\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"m = n %[ 'mod_ideal' I ]\"\n (format \"'[hv ' m '/' = n '/' %[ 'mod_ideal' I ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"m == n %[ 'mod_ideal' I ]\"\n (format \"'[hv ' m '/' == n '/' %[ 'mod_ideal' I ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"m <> n %[ 'mod_ideal' I ]\"\n (format \"'[hv ' m '/' <> n '/' %[ 'mod_ideal' I ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"m != n %[ 'mod_ideal' I ]\"\n (format \"'[hv ' m '/' != n '/' %[ 'mod_ideal' I ] ']'\").\n\n(*This record defines the properties for a type to be a quotient of a Z-module. It requires that the projection map preserves the zero element, the additive inverse operation, and the addition operation.*)\nHB.mixin Record isZmodQuotient T eqT (zeroT : T) (oppT : T -> T) (addT : T -> T -> T)\n(Q : Type) of GRing.Zmodule Q & EqQuotient T eqT Q := {\n pi_zeror : \\pi_Q zeroT = 0;\n pi_oppr : {morph \\pi_Q : x / oppT x >-> - x};\n pi_addr : {morph \\pi_Q : x y / addT x y >-> x + y}\n}.\n\n#[short(type=\"zmodQuotType\")]\n(*This definition packages a type that is simultaneously a Z-module and an equivalence quotient of another type, ensuring the module operations on the quotient are compatible with the corresponding operations on the original type via the projection map.*)\nHB.structure Definition ZmodQuotient T eqT zeroT oppT addT :=\n {Q of isZmodQuotient T eqT zeroT oppT addT Q &\n GRing.Zmodule Q & EqQuotient T eqT Q}.\n\nSection ZModQuotient.\n\nVariable (T : Type).\nVariable eqT : rel T.\nVariables (zeroT : T) (oppT : T -> T) (addT : T -> T -> T).\nImplicit Type zqT : ZmodQuotient.type eqT zeroT oppT addT.\n\nCanonical pi_zero_quot_morph zqT := PiMorph (@pi_zeror _ _ _ _ _ zqT).\nCanonical pi_opp_quot_morph zqT := PiMorph1 (@pi_oppr _ _ _ _ _ zqT).\nCanonical pi_add_quot_morph zqT := PiMorph2 (@pi_addr _ _ _ _ _ zqT).\n\nEnd ZModQuotient.\n\nSection PiAdditive.\n\nVariables (V : zmodType) (equivV : rel V) (zeroV : V).\nVariable Q : @zmodQuotType V equivV zeroV -%R +%R.\n\n(*This lemma states that the canonical projection from a Z-module to its quotient is a Z-module morphism, meaning it preserves the zero element and addition.*)\nLemma pi_is_zmod_morphism : zmod_morphism \\pi_Q.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `pi_is_monoid_morphism` instead\")]\n(*This definition is a deprecated alias asserting that the canonical projection from a Z-module to its quotient is an additive morphism. It is now recommended to use the statement that the projection is a Z-module morphism.*)\nDefinition pi_is_additive := pi_is_zmod_morphism.\n\n(*This record defines the properties for a type to be a quotient of a non-zero ring. It extends the Z-module quotient properties by requiring that the projection map preserves the multiplicative identity and the multiplication operation.*)\nHB.mixin Record isNzRingQuotient T eqT zeroT oppT\naddT (oneT : T) (mulT : T -> T -> T) (Q : Type)\n of ZmodQuotient T eqT zeroT oppT addT Q & GRing.NzRing Q:=\n {\n pi_oner : \\pi_Q oneT = 1;\n pi_mulr : {morph \\pi_Q : x y / mulT x y >-> x * y}\n }.\n\nModule isRingQuotient.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use isNzRingQuotient.Build instead.\")]\nNotation Build T eqT zeroT oppT addT oneT mulT Q :=\n (isNzRingQuotient.Build T eqT zeroT oppT addT oneT mulT Q) (only parsing).\nEnd isRingQuotient.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use isNzRingQuotient instead.\")]\nNotation isRingQuotient T eqT zeroT oppT addT oneT mulT Q :=\n (isNzRingQuotient T eqT zeroT oppT addT oneT mulT Q) (only parsing).\n\n#[short(type=\"nzRingQuotType\")]\n(*This definition packages a type that is simultaneously a non-zero ring and a quotient of another type with ring-like operations, ensuring all ring operations on the quotient are compatible with the corresponding operations on the original type via the projection map.*)\nHB.structure Definition NzRingQuotient T eqT zeroT oppT addT oneT mulT :=\n {Q of isNzRingQuotient T eqT zeroT oppT addT oneT mulT Q &\n ZmodQuotient T eqT zeroT oppT addT Q & GRing.NzRing Q }.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use nzRingQuotType instead.\")]\n(*This is a deprecated notation that serves as an alias for the type of non-zero ring quotients.*)\nNotation ringQuotType := (nzRingQuotType) (only parsing).\n\nSection nzRingQuotient.\n\nVariable (T : Type).\nVariable eqT : rel T.\nVariables (zeroT : T) (oppT : T -> T) (addT : T -> T -> T) (oneT : T) (mulT : T -> T -> T).\nImplicit Type rqT : NzRingQuotient.type eqT zeroT oppT addT oneT mulT.\n\nCanonical pi_one_quot_morph rqT := PiMorph (@pi_oner _ _ _ _ _ _ _ rqT).\nCanonical pi_mul_quot_morph rqT := PiMorph2 (@pi_mulr _ _ _ _ _ _ _ rqT).\n\nEnd nzRingQuotient.\n\nSection PiRMorphism.\n\nVariables (R : nzRingType) (equivR : rel R) (zeroR : R).\n\nVariable Q : @nzRingQuotType R equivR zeroR -%R +%R 1 *%R.\n\n(*This lemma states that the canonical projection from a ring to its quotient is a monoid morphism, meaning it preserves the multiplicative identity and multiplication.*)\nLemma pi_is_monoid_morphism : monoid_morphism \\pi_Q.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `pi_is_monoid_morphism` instead\")]\n(*This definition is a deprecated alias asserting that the canonical projection from a ring to its quotient is a multiplicative morphism. It is now recommended to use the statement that the projection is a monoid morphism.*)\nDefinition pi_is_multiplicative :=\n (fun g => (g.2,g.1)) pi_is_monoid_morphism.\n(*This record defines the properties for a type to be a quotient of a unit ring. It extends the non-zero ring quotient properties by requiring that the projection map preserves the property of being a unit and respects the multiplicative inverse operation.*)\nHB.mixin Record isUnitRingQuotient T eqT zeroT oppT addT oneT mulT (unitT : pred T) (invT : T -> T)\n (Q : Type) of NzRingQuotient T eqT zeroT oppT addT oneT mulT Q & GRing.UnitRing Q :=\n {\n pi_unitr : {mono \\pi_Q : x / unitT x >-> x \\in GRing.unit};\n pi_invr : {morph \\pi_Q : x / invT x >-> x^-1}\n }.\n\n#[short(type=\"unitRingQuotType\")]\n(*This definition packages a type that is simultaneously a unit ring and a quotient of another type with corresponding ring operations, ensuring compatibility of all operations, including the identification of units and the multiplicative inverse, via the projection map.*)\nHB.structure Definition UnitRingQuotient T eqT zeroT oppT addT oneT mulT unitT invT :=\n {Q of isUnitRingQuotient T eqT zeroT oppT addT oneT mulT unitT invT Q & GRing.UnitRing Q & isQuotient T Q & isEqQuotient T eqT Q & isZmodQuotient T eqT zeroT oppT addT Q & isNzRingQuotient T eqT zeroT oppT addT oneT mulT Q}.\n\nSection UnitRingQuot.\nVariable (T : Type).\nVariable eqT : rel T.\nVariables (zeroT : T) (oppT : T -> T) (addT : T -> T -> T).\nVariables (oneT : T) (mulT : T -> T -> T).\nVariables (unitT : pred T) (invT : T -> T).\nImplicit Type urqT : UnitRingQuotient.type eqT zeroT oppT addT oneT mulT unitT invT.\n\nCanonical pi_unit_quot_morph urqT := PiMono1 (@pi_unitr _ _ _ _ _ _ _ _ _ urqT).\nCanonical pi_inv_quot_morph urqT := PiMorph1 (@pi_invr _ _ _ _ _ _ _ _ _ urqT).\n\nEnd UnitRingQuot.\n\n(*This definition states a property for a subset of a non-zero ring, requiring that the subset does not contain the multiplicative identity and is closed under left multiplication by any element of the ring.*)\nDefinition proper_ideal (R : nzRingType) (S : {pred R}) : Prop :=\n 1 \\notin S /\\ forall a, {in S, forall u, a * u \\in S}.\n\n(*This definition specifies the property of a subset of a non-zero ring being 'prime closed', which requires that if a product of two elements belongs to the subset, then at least one of the elements must also be in the subset.*)\nDefinition prime_idealr_closed (R : nzRingType) (S : {pred R}) : Prop :=\n forall u v, u * v \\in S -> (u \\in S) || (v \\in S).\n\n(*This definition specifies the properties for a subset of a non-zero ring to be a proper left ideal. It requires the subset to contain the zero element, not contain the multiplicative identity, and be closed under addition and left multiplication by any element from the ring.*)\nDefinition idealr_closed (R : nzRingType) (S : {pred R}) :=\n [/\\ 0 \\in S, 1 \\notin S & forall a, {in S &, forall u v, a * u + v \\in S}].\n\n(*This lemma states that if a subset of a ring is a proper left ideal according to a strong definition requiring closure under addition, containing zero, and excluding one, then it also satisfies a weaker definition of a proper ideal that only requires excluding the multiplicative identity and being closed under left multiplication.*)\nLemma idealr_closed_nontrivial R S : @idealr_closed R S -> proper_ideal S.\n\n(*This lemma states that a subset of a ring satisfying the properties of a proper left ideal is also closed as a Z-module, meaning it contains the zero element and is closed under addition.*)\nLemma idealr_closedB R S : @idealr_closed R S -> zmod_closed S.\n\n(*This record packages a predicate on a non-zero ring with a proof that the subset defined by the predicate is a proper ideal, meaning it excludes the multiplicative identity and is closed under left multiplication by ring elements.*)\nHB.mixin Record isProperIdeal (R : nzRingType) (S : R -> bool) := {\n proper_ideal_subproof : proper_ideal S\n}.\n\n#[short(type=\"proper_ideal\")]\n(*This definition introduces a structure for a proper ideal on a non-zero ring, which consists of a subset that excludes the multiplicative identity and is closed under left multiplication by any ring element.*)\nHB.structure Definition ProperIdeal R := {S of isProperIdeal R S}.\n\n#[short(type=\"idealr\")]\n(*This definition specifies the structure for a proper left ideal on a non-zero ring, combining the properties of being an additive subgroup and being closed under left multiplication by ring elements, while also excluding the multiplicative identity.*)\nHB.structure Definition Idealr (R : nzRingType) :=\n {S of GRing.ZmodClosed R S & ProperIdeal R S}.\n\n(*This record packages a predicate on a non-zero ring with a proof that the subset it defines satisfies the primality condition, meaning that if a product of two elements is in the subset, at least one of the elements must also be in it.*)\nHB.mixin Record isPrimeIdealrClosed (R : nzRingType) (S : R -> bool) := {\n prime_idealr_closed_subproof : prime_idealr_closed S\n}.\n\n#[short(type=\"prime_idealr\")]\n(*This definition specifies the structure for a prime ideal on a non-zero ring, which is a proper left ideal that also satisfies the primality condition.*)\nHB.structure Definition PrimeIdealr (R : nzRingType) :=\n {S of Idealr R S & isPrimeIdealrClosed R S}.\n\n(*This record provides a factory for constructing a proper left ideal. It takes as input a proof that a given subset contains zero, excludes one, and is closed under both addition and left multiplication by any ring element, and uses it to automatically build the full ideal structure.*)\nHB.factory Record isIdealr (R : nzRingType) (S : R -> bool) := {\n idealr_closed_subproof : idealr_closed S\n}.\n\nHB.builders Context R S of isIdealr R S.\nHB.instance Definition _ := GRing.isZmodClosed.Build R S\n (idealr_closedB idealr_closed_subproof).\n(*The notation `I` is used as a local shorthand for the predicate defining the subset of a given ideal within the scope of ideal theory lemmas.*)\nLocal Notation I := (idealrI : pred R).\n\n(*This lemma states that the multiplicative identity of the ring is never an element of a proper ideal.*)\nLemma idealr1 : 1 \\in I = false.\n\n(*This lemma states that a left ideal is closed under left multiplication; if an element is in the ideal, its product with any ring element on the left is also in the ideal.*)\nLemma idealMr a u : u \\in I -> a * u \\in I.\n\n(*This lemma states that the zero element of the ring is always a member of any ideal.*)\nLemma idealr0 : 0 \\in I. \n\nEnd IdealTheory.\n\nSection PrimeIdealTheory.\n\nVariables (R : comNzRingType) (pidealI : prime_idealr R).\n(*A local notation for the predicate that tests for membership in a given ideal of a ring.*)\nLocal Notation I := (pidealI : pred R).\n\n(*This lemma states that for a prime ideal, a product of two ring elements belongs to the ideal if and only if at least one of the elements belongs to the ideal.*)\nLemma prime_idealrM u v : (u * v \\in I) = (u \\in I) || (v \\in I).\n\nEnd PrimeIdealTheory.\n\nModule Quotient.\nSection ZmodQuotient.\nVariables (R : zmodType) (I : zmodClosed R).\n\n(*This definition specifies the equivalence relation on elements of a module, which holds if and only if the difference between two elements is contained in a given submodule.*)\nDefinition equiv (x y : R) := (x - y) \\in I.\n\n(*This lemma states that the equivalence of two module elements is identical to the condition that their difference is a member of the given submodule.*)\nLemma equivE x y : (equiv x y) = (x - y \\in I). \n\n(*This lemma asserts that the relation defined by submodule membership of a difference is a valid equivalence relation.*)\nLemma equiv_is_equiv : equiv_class_of equiv.\n\nCanonical equiv_equiv := EquivRelPack equiv_is_equiv.\nCanonical equiv_encModRel := defaultEncModRel equiv.\n\n(*This definition constructs the quotient type as the set of all equivalence classes of a module, based on the equivalence relation defined by a given submodule.*)\nDefinition quot := {eq_quot equiv}.\n\n#[export]\nHB.instance Definition _ : EqQuotient R equiv quot := EqQuotient.on quot.\n#[export]\nHB.instance Definition _ := Choice.on quot.\n\n(*This lemma states that two elements of a module having their difference in a given submodule is equivalent to the two elements being equal in the corresponding quotient module.*)\nLemma idealrBE x y : (x - y) \\in I = (x == y %[mod quot]).\n\n(*This lemma states that two elements of a module having their sum in a given submodule is equivalent to the first element being equal to the additive inverse of the second element in the corresponding quotient module.*)\nLemma idealrDE x y : (x + y) \\in I = (x == - y %[mod quot]).\n\n(*This definition specifies the zero element of the quotient module as the equivalence class containing the zero element of the original module.*)\nDefinition zero : quot := lift_cst quot 0.\n(*This definition specifies the addition operation on the quotient module, lifting it from the addition operation on the original module.*)\nDefinition add := lift_op2 quot +%R.\n(*This definition specifies the additive inverse operation on the quotient module, lifting it from the additive inverse operation on the original module.*)\nDefinition opp := lift_op1 quot -%R.\n\nCanonical pi_zero_morph := PiConst zero.\n\n(*This lemma states that the canonical projection map from a module to its quotient preserves the additive inverse operation.*)\nLemma pi_opp : {morph \\pi : x / - x >-> opp x}.\n\nCanonical pi_opp_morph := PiMorph1 pi_opp.\n\n(*This lemma states that the canonical projection map from a module to its quotient preserves the addition operation.*)\nLemma pi_add : {morph \\pi : x y / x + y >-> add x y}.\n\nCanonical pi_add_morph := PiMorph2 pi_add.\n\n(*This lemma asserts that the addition operation defined on the quotient module is associative.*)\nLemma addqA: associative add.\n\n(*This lemma asserts that the addition operation defined on the quotient module is commutative.*)\nLemma addqC: commutative add.\n\n(*This lemma asserts that the zero element of the quotient module acts as a left identity for the addition operation on the quotient.*)\nLemma add0q: left_id zero add.\n\n(*This lemma asserts that the additive inverse operation on the quotient module provides a left inverse for every element with respect to the addition operation.*)\nLemma addNq: left_inverse zero opp add.\n\n#[export]\nHB.instance Definition _ := GRing.isZmodule.Build quot addqA addqC add0q addNq.\n#[export]\n(*A notation for representing the quotient type formed by a module or ring with respect to a given submodule or ideal.*)\nNotation \"{ 'quot' I }\" := (quot I) : type_scope.\n\nSection RingQuotient.\n\nVariables (R : comNzRingType) (idealI : idealr R).\n(*The identifier I represents a prime ideal of a commutative ring, which defines the equivalence classes for the construction of a quotient ring.*)\nLocal Notation I := (idealI : pred R).\n\n(*This definition establishes the multiplicative identity element in the quotient ring, which corresponds to the equivalence class containing the multiplicative identity of the base ring.*)\nDefinition one : {quot idealI} := lift_cst {quot idealI} 1.\n(*This definition establishes the multiplication operation in the quotient ring by lifting the multiplication operation from the base ring to the equivalence classes.*)\nDefinition mul := lift_op2 {quot idealI} *%R.\n\nCanonical pi_one_morph := PiConst one.\n\n(*This lemma states that the canonical projection from the base ring to the quotient ring preserves multiplication, meaning the projection of a product of two elements is equal to the product of their projections in the quotient ring.*)\nLemma pi_mul: {morph \\pi : x y / x * y >-> mul x y}.\n\nCanonical pi_mul_morph := PiMorph2 pi_mul.\n\n(*This lemma states that the multiplication operation in the quotient ring is associative.*)\nLemma mulqA: associative mul.\n\n(*This lemma states that the multiplication operation in the quotient ring is commutative.*)\nLemma mulqC: commutative mul.\n\n(*This lemma states that the multiplicative identity element of the quotient ring acts as a left identity for the multiplication operation in that ring.*)\nLemma mul1q: left_id one mul.\n\n(*This lemma states that the multiplication operation in the quotient ring is left-distributive over the addition operation.*)\nLemma mulq_addl: left_distributive mul +%R.\n\n(*This lemma states that the multiplicative identity element in the quotient ring is distinct from the additive identity element.*)\nLemma nonzero1q: one != 0.\n\n#[export]\nHB.instance Definition _ := GRing.Zmodule_isComNzRing.Build (quot idealI)\n mulqA mulqC mul1q mulq_addl nonzero1q.\n\n#[export]\n(*This lemma states that for a quotient ring formed by a prime ideal, if the product of two elements is the additive identity, then at least one of the elements must be the additive identity.*)\nLemma rquot_IdomainAxiom (x y : {quot I}): x * y = 0 -> (x == 0) || (y == 0).\n\nEnd IDomainQuotient.\n\nModule Exports. HB.reexport. End Exports.\nEnd Quotient.\n\nExport Quotient.Exports.\n\n(*This notation represents the type of the quotient ring formed by taking elements of a base ring modulo a given ideal.*)\nNotation \"{ 'ideal_quot' I }\" := (@Quotient.quot _ I) : type_scope.\n(*This notation provides a syntax for a boolean comparison that evaluates to true if two elements of a ring are in the same equivalence class modulo a given ideal, and false otherwise.*)\nNotation \"x == y %[ 'mod_ideal' I ]\" :=\n (x == y %[mod {ideal_quot I}]) : quotient_scope.\n(*This notation provides a syntax for a propositional equality asserting that two elements of a ring belong to the same equivalence class modulo a given ideal.*)\nNotation \"x = y %[ 'mod_ideal' I ]\" :=\n (x = y %[mod {ideal_quot I}]) : quotient_scope.\n(*This notation provides a syntax for a boolean comparison that evaluates to true if two elements of a ring are not in the same equivalence class modulo a given ideal, and false otherwise.*)\nNotation \"x != y %[ 'mod_ideal' I ]\" :=\n (x != y %[mod {ideal_quot I}]) : quotient_scope.\n(*This notation provides a syntax for a propositional inequality asserting that two elements of a ring do not belong to the same equivalence class modulo a given ideal.*)\nNotation \"x <> y %[ 'mod_ideal' I ]\" :=", - "algebra.ssralg": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat div seq.\nFrom mathcomp Require Import choice fintype finfun bigop prime binomial.\nFrom mathcomp Require Export nmodule.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope ring_scope.\nDeclare Scope term_scope.\nDeclare Scope linear_ring_scope.\n\nReserved Notation \"+%R\".\nReserved Notation \"-%R\".\nReserved Notation \"*%R\" (format \" *%R\").\nReserved Notation \"*:%R\" (format \" *:%R\").\nReserved Notation \"n %:R\" (left associativity, format \"n %:R\").\nReserved Notation \"k %:A\" (left associativity, format \"k %:A\").\nReserved Notation \"[ 'pchar' F ]\" (format \"[ 'pchar' F ]\").\nReserved Notation \"[ 'char' F ]\" (format \"[ 'char' F ]\").\n\nReserved Notation \"x %:T\" (left associativity, format \"x %:T\").\nReserved Notation \"''X_' i\" (at level 8, i at level 2, format \"''X_' i\").\n\nReserved Notation \"''exists' ''X_' i , f\"\n (at level 199, i at level 2, right associativity,\n format \"'[hv' ''exists' ''X_' i , '/ ' f ']'\").\nReserved Notation \"''forall' ''X_' i , f\"\n (at level 199, i at level 2, right associativity,\n format \"'[hv' ''forall' ''X_' i , '/ ' f ']'\").\n\nReserved Notation \"x ^f\" (left associativity, format \"x ^f\").\n\nReserved Notation \"\\0\".\nReserved Notation \"f \\+ g\" (at level 50, left associativity).\nReserved Notation \"f \\- g\" (at level 50, left associativity).\nReserved Notation \"\\- f\" (at level 35, f at level 35).\nReserved Notation \"a \\*o f\" (at level 40).\nReserved Notation \"a \\o* f\" (at level 40).\nReserved Notation \"a \\*: f\" (at level 40).\nReserved Notation \"f \\* g\" (at level 40, left associativity).\n\nReserved Notation \"'{' 'additive' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'additive' U -> V }\").\nReserved Notation \"'{' 'rmorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'rmorphism' U -> V }\").\nReserved Notation \"'{' 'lrmorphism' U '->' V '|' s '}'\"\n (U at level 98, V at level 99, format \"{ 'lrmorphism' U -> V | s }\").\nReserved Notation \"'{' 'lrmorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'lrmorphism' U -> V }\").\nReserved Notation \"'{' 'linear' U '->' V '|' s '}'\"\n (U at level 98, V at level 99, format \"{ 'linear' U -> V | s }\").\nReserved Notation \"'{' 'linear' U '->' V '}'\"\n (U at level 98, V at level 99,\n format \"{ 'linear' U -> V }\").\nReserved Notation \"'{' 'scalar' U '}'\" (format \"{ 'scalar' U }\").\n\nDeclare Scope ring_scope.\nDelimit Scope ring_scope with R.\nDeclare Scope term_scope.\nDelimit Scope term_scope with T.\nLocal Open Scope ring_scope.\n\nModule Export Dummy.\nModule GRing := Algebra.\nEnd Dummy.\n\nModule Import GRing.\n\nExport Algebra.\n\nImport Monoid.Theory.\n\n(*This notation represents the zero element, which is the additive identity, within an additive algebraic structure.*)\nLocal Notation \"0\" := (@zero _) : ring_scope.\n(*This notation represents the binary addition operation as a function, taking two elements of an additive structure and returning their sum.*)\nLocal Notation \"+%R\" := (@add _) : function_scope.\n(*This notation represents the infix binary addition of two elements within an additive algebraic structure, resulting in their sum.*)\nLocal Notation \"x + y\" := (add x y) : ring_scope.\n\n(*This notation represents the operation of repeatedly adding an element of an additive structure to itself a specified number of times, where the number of repetitions is given by a natural number.*)\nLocal Notation \"x *+ n\" := (natmul x n) : ring_scope.\n\n(*This notation represents the sum of the results of a function applied to all elements of a finite sequence that satisfy a given boolean predicate.*)\nLocal Notation \"\\sum_ ( i <- r | P ) F\" := (\\big[+%R/0]_(i <- r | P) F).\n(*This notation represents the sum of the results of a function applied to each natural number in a specified range, from a given start value up to, but not including, a given end value.*)\nLocal Notation \"\\sum_ ( m <= i < n ) F\" := (\\big[+%R/0]_(m <= i < n) F).\n(*This notation represents the sum of the results of a function applied to each natural number from zero up to, but not including, a given natural number bound.*)\nLocal Notation \"\\sum_ ( i < n ) F\" := (\\big[+%R/0]_(i < n) F).\n(*This notation represents the sum of the results of a function applied to every element of a given finite set.*)\nLocal Notation \"\\sum_ ( i 'in' A ) F\" := (\\big[+%R/0]_(i in A) F).\n\n(*This notation retrieves the element at a specified index from a sequence, returning the additive identity element of the structure if the index is out of bounds.*)\nLocal Notation \"s `_ i\" := (nth 0 s i) : ring_scope.\n\nSection NmoduleTheory.\n\nVariable V : nmodType.\nImplicit Types x y : V.\n\n(*This lemma states that the addition operation on the additive structure is associative, meaning that for any three elements, the result is the same regardless of the grouping of the additions.*)\nLemma addrA : associative (@add V).\n\n(*This lemma states that the addition operation on the additive structure is commutative, meaning that swapping the order of two elements does not change their sum.*)\nLemma addrC : commutative (@add V).\n\n(*This lemma states that the zero element is the left identity for addition, meaning that adding the zero element to any other element results in that other element.*)\nLemma add0r : left_id (@zero V) add.\n\n(*This lemma states that the zero element is the right identity for addition, meaning that adding any element to the zero element results in that same element.*)\nLemma addr0 : right_id (@zero V) add.\n\n(*This lemma states that the addition operation is left-commutative, meaning that adding a first element to the sum of a second and a third element is equivalent to adding the second element to the sum of the first and the third.*)\nLemma addrCA : @left_commutative V V +%R. \n(*This lemma states that the addition operation is right-commutative, meaning that adding a third element to the sum of a first and a second element is equivalent to adding the second element to the sum of the first and the third.*)\nLemma addrAC : @right_commutative V V +%R. \n(*This lemma states that the addition operation satisfies the interchange property, meaning that when summing two pairs of elements, the result is the same if the elements are regrouped to sum the first elements of each pair and the second elements of each pair separately before summing these partial results.*)\nLemma addrACA : @interchange V +%R +%R. \n\n(*This lemma states that multiplying any element of an additive structure by the natural number zero results in the zero element of that structure.*)\nLemma mulr0n x : x *+ 0 = 0. \n(*This lemma states that multiplying any element of an additive structure by the natural number one results in the element itself.*)\nLemma mulr1n x : x *+ 1 = x. \n(*This lemma states that multiplying an element of an additive structure by the natural number two is equivalent to adding the element to itself.*)\nLemma mulr2n x : x *+ 2 = x + x. \n(*This lemma provides a recursive formula for scalar multiplication, stating that multiplying an element by the successor of a natural number is equivalent to adding the element to the result of multiplying it by the original number.*)\nLemma mulrS x n : x *+ n.+1 = x + (x *+ n). \n(*This lemma provides an alternative recursive formula for scalar multiplication, stating that multiplying an element by the successor of a natural number is equivalent to adding the result of multiplying it by the original number to the element itself.*)\nLemma mulrSr x n : x *+ n.+1 = x *+ n + x. \n\n(*This lemma states that multiplying an element of an additive structure by a boolean value results in the element itself if the boolean is true, and the zero element if the boolean is false.*)\nLemma mulrb x (b : bool) : x *+ b = (if b then x else 0).\n\n(*This lemma states that multiplying the zero element of an additive structure by any natural number results in the zero element.*)\nLemma mul0rn n : 0 *+ n = 0 :> V. \n\n(*This lemma states that scalar multiplication by a natural number distributes over the addition of elements in an additive structure.*)\nLemma mulrnDl n : {morph (fun x => x *+ n) : x y / x + y}.\n\n(*This lemma states that the multiplication of an element from an additive structure distributes over the addition of natural number scalars, meaning that multiplying an element by a sum of two natural numbers is equivalent to summing the results of multiplying the element by each natural number separately.*)\nLemma mulrnDr x m n : x *+ (m + n) = x *+ m + x *+ n.\n\n(*This lemma states that scalar multiplication is associative with respect to the multiplication of the natural number scalars, meaning that scaling an element by a product of two natural numbers is equivalent to successively scaling by each of those numbers.*)\nLemma mulrnA x m n : x *+ (m * n) = x *+ m *+ n. \n\n(*This lemma states that successive scalar multiplications of an element by two natural numbers are commutative, meaning the order of the scalar multipliers can be swapped without changing the final result.*)\nLemma mulrnAC x m n : x *+ m *+ n = x *+ n *+ m. \n\n(*This lemma states that repeatedly applying the function that adds a given element to an initial value for a specified number of times is equivalent to adding the initial value to the scalar product of the given element and the number of repetitions.*)\nLemma iter_addr n x y : iter n (+%R x) y = x *+ n + y.\n\n(*This lemma states that repeatedly applying the function that adds a given element to the zero element for a specified number of times is equivalent to the scalar product of the given element and the number of repetitions.*)\nLemma iter_addr_0 n x : iter n (+%R x) 0 = x *+ n.\n\n(*This lemma states that multiplying a finite sum of elements from an additive structure by a natural number is equivalent to taking the finite sum of the results of multiplying each individual element by that same natural number.*)\nLemma sumrMnl I r P (F : I -> V) n :\n \\sum_(i <- r | P i) F i *+ n = (\\sum_(i <- r | P i) F i) *+ n.\n\n(*This lemma states that the sum over a sequence, obtained by scaling the values of a function to natural numbers by a fixed element from a module, is equal to that fixed element scaling the sum of the function's values.*)\nLemma sumrMnr x I r P (F : I -> nat) :\n \\sum_(i <- r | P i) x *+ F i = x *+ (\\sum_(i <- r | P i) F i).\n\n(*This lemma states that the sum of a constant element over a finite set is equal to that element scaled by the number of elements in the set.*)\nLemma sumr_const (I : finType) (A : pred I) x : \\sum_(i in A) x = x *+ #|A|.\n\n(*This lemma states that the sum of a constant element over a range of natural numbers from a lower bound inclusive to an upper bound exclusive is equal to that element scaled by the difference between the upper and lower bounds.*)\nLemma sumr_const_nat m n x : \\sum_(n <= i < m) x = x *+ (m - n).\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Algebra.nmod_closed instead.\")]\n(*This definition provides a deprecated alias for the property that a subset of a module is closed under addition and scaling by natural numbers.*)\nDefinition addr_closed := nmod_closed.\n\nEnd NmoduleTheory.\n\n(*This notation defines a unary prefix operator representing the additive inverse, or opposite, of an element in a structure with additive inversion.*)\nLocal Notation \"-%R\" := (@opp _) : ring_scope.\n(*This notation defines the standard unary minus prefix for the additive inverse of an element in a structure supporting opposition.*)\nLocal Notation \"- x\" := (opp x) : ring_scope.\n(*This notation defines binary subtraction of two elements as the addition of the first element to the additive inverse of the second element.*)\nLocal Notation \"x - y\" := (x + - y) : ring_scope.\n\n(*This notation defines the operation of scaling an element by the negative of a natural number, which results in the additive inverse of scaling that element by the natural number itself.*)\nLocal Notation \"x *- n\" := (- (x *+ n)) : ring_scope.\n\nSection ZmoduleTheory.\n\nVariable V : zmodType.\nImplicit Types x y : V.\n\n(*This lemma states that for any element, adding it to its additive inverse results in the zero element.*)\nLemma addNr : @left_inverse V V V 0 -%R +%R. \n(*This lemma states that for any element, adding its additive inverse to it results in the zero element.*)\nLemma addrN : @right_inverse V V V 0 -%R +%R. \n(*This definition is an alias for the lemma stating that subtracting an element from itself results in the zero element.*)\nDefinition subrr := addrN.\n\n(*This lemma states that adding an element's additive inverse to the sum of that element and another element cancels out the first element, yielding the other element.*)\nLemma addKr : @left_loop V V -%R +%R. \n(*This lemma states that adding an element to the sum of its additive inverse and another element cancels out the first element, yielding the other element.*)\nLemma addNKr : @rev_left_loop V V -%R +%R. \n(*This lemma states that adding the additive inverse of an element to the sum of another element and that element cancels out the second element, yielding the first.*)\nLemma addrK : @right_loop V V -%R +%R. \n(*This lemma states that adding an element to the result of subtracting that same element from another element restores the original other element.*)\nLemma addrNK : @rev_right_loop V V -%R +%R. \n(*This definition provides an alias for the lemma stating that adding an element to the result of a subtraction involving that element effectively cancels the subtraction.*)\nDefinition subrK := addrNK.\n(*This lemma states that subtracting an element from a fixed element is an involutive operation; that is, applying the operation twice returns the original element.*)\nLemma subKr x : involutive (fun y => x - y). \n(*This lemma states that addition is right-injective, meaning that if adding the same element to two different elements yields the same result, then the two original elements must have been equal.*)\nLemma addrI : @right_injective V V V +%R. \n(*This lemma states that addition is left-injective, meaning that if two elements are added to the same element and yield the same result, then the two elements must have been equal.*)\nLemma addIr : @left_injective V V V +%R. \n(*This lemma states that the subtraction operation is right-injective, which means that if subtracting the same element from two different elements results in equal outcomes, then those two elements must have been equal.*)\nLemma subrI : right_injective (fun x y => x - y). \n(*This lemma states that the subtraction operation is left-injective, meaning that if two elements are subtracted from the same element and the results are equal, then the two subtracted elements must have been equal.*)\nLemma subIr : left_injective (fun x y => x - y). \n(*This lemma states that the additive inverse operation is an involution, meaning that taking the additive inverse of the additive inverse of an element returns the original element.*)\nLemma opprK : @involutive V -%R. \n(*This lemma states that the additive inverse function is injective, meaning that if the additive inverses of two elements are equal, then the elements themselves must be equal.*)\nLemma oppr_inj : @injective V V -%R. \n(*This lemma states that the additive inverse of the zero element is the zero element itself.*)\nLemma oppr0 : -0 = 0 :> V. \n(*This lemma states that an element is equal to the zero element if and only if its additive inverse is equal to the zero element.*)\nLemma oppr_eq0 x : (- x == 0) = (x == 0). \n\n(*This lemma states that subtracting the zero element from any given element results in the original element.*)\nLemma subr0 x : x - 0 = x. \n(*This lemma states that subtracting an element from the zero element yields the additive inverse of that element.*)\nLemma sub0r x : 0 - x = - x. \n\n(*This lemma states that the additive inverse of the difference of two elements is equal to the difference of those two elements in the opposite order.*)\nLemma opprB x y : - (x - y) = y - x. \n(*This lemma states that the additive inverse operation is a morphism with respect to addition; specifically, the additive inverse of a sum of two elements is equal to the sum of their additive inverses.*)\nLemma opprD : {morph -%R: x y / x + y : V}. \n(*This lemma states that subtracting a sum from another sum, where both sums share a common term, is equivalent to the difference of the other two terms, effectively canceling the common term.*)\nLemma addrKA z x y : (x + z) - (z + y) = x - y. \n(*This lemma states that adding the difference of a first and second element to the sum of the second and a third element simplifies to the sum of the first and third elements.*)\nLemma subrKA z x y : (x - z) + (z + y) = x + y. \n(*This lemma states that if the sum of two elements in an abelian group equals the zero element, then the additive inverse of the first element is equal to the second element.*)\nLemma addr0_eq x y : x + y = 0 -> - x = y. \n(*This lemma states that if the difference between two elements in an abelian group is the zero element, then the two elements are equal.*)\nLemma subr0_eq x y : x - y = 0 -> x = y. \n(*This lemma states that the boolean equality test between the difference of a first and a second element and a third element is equivalent to testing if the first element is equal to the sum of the third and second elements.*)\nLemma subr_eq x y z : (x - z == y) = (x == y + z). \n(*This lemma states that the boolean equality test for whether the difference of two elements is the zero element is equivalent to the boolean equality test for whether the two elements are equal.*)\nLemma subr_eq0 x y : (x - y == 0) = (x == y). \n(*This lemma states that the boolean equality test for whether the sum of two elements is the zero element is equivalent to testing if the first element is equal to the additive inverse of the second.*)\nLemma addr_eq0 x y : (x + y == 0) = (x == - y). \n(*This lemma states that the boolean equality test between the additive inverses of two elements is equivalent to the boolean equality test between the original two elements.*)\nLemma eqr_opp x y : (- x == - y) = (x == y). \n(*This lemma states that testing if the additive inverse of a first element is equal to a second element is equivalent to testing if the first element is equal to the additive inverse of the second.*)\nLemma eqr_oppLR x y : (- x == y) = (x == - y). \n(*This lemma states that scaling the additive inverse of an element by a natural number yields the same result as taking the additive inverse of the element scaled by that same natural number.*)\nLemma mulNrn x n : (- x) *+ n = x *- n. \n\n(*This lemma states that the function that scales elements of an abelian group by a fixed natural number distributes over subtraction.*)\nLemma mulrnBl n : {morph (fun x => x *+ n) : x y / x - y}.\n\n(*This lemma states that scaling an element of an abelian group by the difference of two natural numbers, where the second is less than or equal to the first, is equivalent to the difference of scaling the element by each natural number individually.*)\nLemma mulrnBr x m n : n <= m -> x *+ (m - n) = x *+ m - x *+ n.\n\n(*This lemma states that the sum of the additive inverses of a sequence of elements, indexed over a range and filtered by a predicate, is equal to the additive inverse of the sum of the original elements.*)\nLemma sumrN I r P (F : I -> V) :\n (\\sum_(i <- r | P i) - F i = - (\\sum_(i <- r | P i) F i)).\n\n(*This lemma states that the sum of differences between corresponding elements from two functions, iterated over a range and filtered by a predicate, is equal to the difference between the sums of elements from each function.*)\nLemma sumrB I r (P : pred I) (F1 F2 : I -> V) :\n \\sum_(i <- r | P i) (F1 i - F2 i)\n = \\sum_(i <- r | P i) F1 i - \\sum_(i <- r | P i) F2 i.\n\n(*This lemma states that for a function from natural numbers to an abelian group, the sum of the differences between successive function values over a range of natural numbers simplifies to the difference between the function's value at the upper bound and its value at the lower bound.*)\nLemma telescope_sumr n m (f : nat -> V) : n <= m ->\n \\sum_(n <= k < m) (f k.+1 - f k) = f m - f n.\n\n(*This lemma provides a rule for computing a telescoping sum, stating that if each term in a sum over a range of natural numbers is defined as the difference of successive values of an auxiliary function, then the total sum is equal to the difference of the auxiliary function's values at the bounds of the range.*)\nLemma telescope_sumr_eq n m (f u : nat -> V) : n <= m ->\n (forall k, (n <= k < m)%N -> u k = f k.+1 - f k) ->\n \\sum_(n <= k < m) u k = f m - f n.\n\nSection ClosedPredicates.\n\nVariable S : {pred V}.\n\n(*This definition specifies the property that a subset of an abelian group is closed under the additive inverse operation, meaning that for any element in the subset, its additive inverse is also in the subset.*)\nDefinition oppr_closed := oppr_closed S.\n(*This definition specifies the property that a subset of an abelian group is closed under subtraction, meaning that the difference of any two elements from the subset is also in the subset.*)\nDefinition subr_2closed := subr_closed S.\n(*This definition specifies the property that a subset of a Z-module forms a submodule, meaning it is closed under both addition and taking the additive inverse.*)\nDefinition zmod_closed := zmod_closed S.\n \n(*This lemma states that if a subset of a Z-module is closed under the module operations, then it is necessarily closed under taking the additive inverse.*)\nLemma zmod_closedN : zmod_closed -> oppr_closed.\n\n(*This lemma states that if a subset of a Z-module is closed under its defining operations, then it is also closed under the operations of an N-module, which include addition and scalar multiplication by natural numbers.*)\nLemma zmod_closedD : zmod_closed -> nmod_closed S.\n\nEnd ClosedPredicates.\n\nEnd ZmoduleTheory.\n\nArguments addrI {V} y [x1 x2].\nArguments addIr {V} x [x1 x2].\nArguments opprK {V}.\nArguments oppr_inj {V} [x1 x2].\nArguments telescope_sumr_eq {V n m} f u.\n\n(*This record defines a mixin that extends an N-module structure, which is a commutative additive monoid, with a multiplicative monoid structure that distributes over addition, thereby forming a semiring with a zero element.*)\nHB.mixin Record Nmodule_isPzSemiRing R of Nmodule R := {\n one : R;\n mul : R -> R -> R;\n mulrA : associative mul;\n mul1r : left_id one mul;\n mulr1 : right_id one mul;\n mulrDl : left_distributive mul +%R;\n mulrDr : right_distributive mul +%R;\n mul0r : left_zero zero mul;\n mulr0 : right_zero zero mul;\n}.\n\n#[short(type=\"pzSemiRingType\")]\n(*This definition establishes the structure for a semiring with a zero element, which combines a commutative additive monoid with a multiplicative monoid where multiplication distributes over addition and is annihilated by the additive identity.*)\nHB.structure Definition PzSemiRing :=\n { R of Nmodule_isPzSemiRing R & Nmodule R }.\n\n(*This record defines a factory for constructing a semiring with a zero element from its basic components: a zero element, an addition operation, a one element, a multiplication operation, and proofs of the required algebraic properties such as associativity, commutativity, identity, distributivity, and annihilation by zero.*)\nHB.factory Record isPzSemiRing R of Choice R := {\n zero : R;\n add : R -> R -> R;\n one : R;\n mul : R -> R -> R;\n addrA : associative add;\n addrC : commutative add;\n add0r : left_id zero add;\n mulrA : associative mul;\n mul1r : left_id one mul;\n mulr1 : right_id one mul;\n mulrDl : left_distributive mul add;\n mulrDr : right_distributive mul add;\n mul0r : left_zero zero mul;\n mulr0 : right_zero zero mul;\n}.\n\nHB.builders Context R of isPzSemiRing R.\n HB.instance Definition _ := @isNmodule.Build R\n zero add addrA addrC add0r.\n HB.instance Definition _ := @Nmodule_isPzSemiRing.Build R\n one mul mulrA mul1r mulr1 mulrDl mulrDr mul0r mulr0.\nHB.end.\n\nModule PzSemiRingExports.\nBind Scope ring_scope with PzSemiRing.sort.\nEnd PzSemiRingExports.\nHB.export PzSemiRingExports.\n\n(*This record defines a mixin that enhances a semiring structure with the property that its multiplicative identity is not equal to its additive identity.*)\nHB.mixin Record PzSemiRing_isNonZero R of PzSemiRing R := {\n oner_neq0 : @one R != 0\n}.\n\n#[short(type=\"nzSemiRingType\")]\n(*This definition establishes the structure for a non-trivial semiring, which is a semiring where the multiplicative identity element is distinct from the additive identity element.*)\nHB.structure Definition NzSemiRing :=\n { R of PzSemiRing_isNonZero R & PzSemiRing R }.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzSemiRing instead.\")]\nNotation SemiRing R := (NzSemiRing R) (only parsing).\n\nModule SemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzSemiRing.sort instead.\")]\n(*A deprecated notation that refers to the underlying carrier type of a non-trivial semiring structure. It is recommended to use the NzSemiRing.sort identifier instead.*)\nNotation sort := (NzSemiRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzSemiRing.on instead.\")]\nNotation on R := (NzSemiRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzSemiRing.copy instead.\")]\nNotation copy T U := (NzSemiRing.copy T U) (only parsing).\nEnd SemiRing.\n\n(*This record defines a factory for constructing a non-trivial semiring structure on top of an existing N-module structure. It requires providing the multiplicative operations and identity, along with proofs of semiring axioms and the axiom that the multiplicative identity is distinct from the additive identity.*)\nHB.factory Record Nmodule_isNzSemiRing R of Nmodule R := {\n one : R;\n mul : R -> R -> R;\n mulrA : associative mul;\n mul1r : left_id one mul;\n mulr1 : right_id one mul;\n mulrDl : left_distributive mul +%R;\n mulrDr : right_distributive mul +%R;\n mul0r : left_zero zero mul;\n mulr0 : right_zero zero mul;\n oner_neq0 : one != 0\n}.\n\nHB.builders Context R of Nmodule_isNzSemiRing R.\n HB.instance Definition _ :=\n Nmodule_isPzSemiRing.Build R mulrA mul1r mulr1 mulrDl mulrDr mul0r mulr0.\n HB.instance Definition _ := PzSemiRing_isNonZero.Build R oner_neq0.\nHB.end.\n\nModule Nmodule_isSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Nmodule_isNzSemiRing.Build instead.\")]\nNotation Build R := (Nmodule_isNzSemiRing.Build R) (only parsing).\nEnd Nmodule_isSemiRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Nmodule_isNzSemiRing instead.\")]\nNotation Nmodule_isSemiRing R := (Nmodule_isNzSemiRing R) (only parsing).\n\n(*This record defines a factory for constructing a non-trivial semiring from its fundamental components. This includes specifying the additive and multiplicative operations and identities, and providing proofs for all semiring axioms, including the axiom that the additive and multiplicative identities are distinct.*)\nHB.factory Record isNzSemiRing R of Choice R := {\n zero : R;\n add : R -> R -> R;\n one : R;\n mul : R -> R -> R;\n addrA : associative add;\n addrC : commutative add;\n add0r : left_id zero add;\n mulrA : associative mul;\n mul1r : left_id one mul;\n mulr1 : right_id one mul;\n mulrDl : left_distributive mul add;\n mulrDr : right_distributive mul add;\n mul0r : left_zero zero mul;\n mulr0 : right_zero zero mul;\n oner_neq0 : one != zero\n}.\n\nModule isSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use isNzSemiRing.Build instead.\")]\nNotation Build R := (isNzSemiRing.Build R) (only parsing).\nEnd isSemiRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use isNzSemiRing instead.\")]\nNotation isSemiRing R := (isNzSemiRing R) (only parsing).\n\nHB.builders Context R of isNzSemiRing R.\n HB.instance Definition _ := @isNmodule.Build R\n zero add addrA addrC add0r.\n HB.instance Definition _ := @Nmodule_isNzSemiRing.Build R\n one mul mulrA mul1r mulr1 mulrDl mulrDr mul0r mulr0 oner_neq0.\nHB.end.\n\nModule NzSemiRingExports.\nBind Scope ring_scope with NzSemiRing.sort.\nEnd NzSemiRingExports.\nHB.export NzSemiRingExports.\n\n(*This definition defines exponentiation of a semiring element to a natural number power as repeated multiplication of the element with itself. Exponentiation to the power of zero results in the multiplicative identity.*)\nDefinition exp R x n := iterop n (@mul R) x (@one R).\nArguments exp : simpl never.\n(*This definition expresses the property that two elements of a semiring commute under multiplication, meaning that multiplying them in either order yields the same result.*)\nDefinition comm R x y := @mul R x y = mul y x.\n(*This definition asserts that a ring element is left-regular if left multiplication by that element is an injective function, which means it satisfies the left cancellation property.*)\nDefinition lreg R x := injective (@mul R x).\n(*This definition asserts that a ring element is right-regular if right multiplication by that element is an injective function, which means it satisfies the right cancellation property.*)\nDefinition rreg R x := injective ((@mul R)^~ x).\n\n(*This notation defines the symbol `1` to represent the multiplicative identity element within the ring scope.*)\nLocal Notation \"1\" := (@one _) : ring_scope.\n(*This notation represents the embedding of a natural number into a ring, which is equivalent to adding the ring's multiplicative identity to itself that many times.*)\nLocal Notation \"n %:R\" := (1 *+ n) : ring_scope.\n(*This notation provides a functional representation of the multiplication operation of a ring, suitable for use with higher-order functions.*)\nLocal Notation \"*%R\" := (@mul _) : function_scope.\n(*This notation defines the standard infix symbol for the multiplication of two elements within the ring scope.*)\nLocal Notation \"x * y\" := (mul x y) : ring_scope.\n(*This notation represents the exponentiation of a ring element to a natural number power, defined as multiplying the element by itself that many times.*)\nLocal Notation \"x ^+ n\" := (exp x n) : ring_scope.\n\n(*This notation represents the iterated product of a sequence of ring elements, indexed over a finite sequence and filtered by a predicate, with the ring's multiplicative identity as the neutral element.*)\nLocal Notation \"\\prod_ ( i <- r | P ) F\" := (\\big[*%R/1]_(i <- r | P) F).\n(*This notation represents the iterated product of a sequence of ring elements over a canonical finite domain, filtered by a predicate, with the ring's multiplicative identity as the neutral element.*)\nLocal Notation \"\\prod_ ( i | P ) F\" := (\\big[*%R/1]_(i | P) F).\n(*This notation represents the iterated product of a sequence of ring elements, indexed by the elements of a given finite set, with the ring's multiplicative identity as the neutral element.*)\nLocal Notation \"\\prod_ ( i 'in' A ) F\" := (\\big[*%R/1]_(i in A) F).\n(*This notation represents the iterated product of a sequence of ring elements, indexed over a range of natural numbers, with the ring's multiplicative identity as the neutral element.*)\nLocal Notation \"\\prod_ ( m <= i < n ) F\" := (\\big[*%R/1%R]_(m <= i < n) F%R).\n\n(*This definition describes a predicate on natural numbers that is satisfied by any prime number which, when embedded into the given non-zero semi-ring, equals the additive identity of that ring.*)\nDefinition pchar (R : nzSemiRingType) : nat_pred :=\n [pred p | prime p & p%:R == 0 :> R].\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar instead.\")]\n(*This notation is a deprecated alias for the predicate identifying the prime characteristics of a ring, which are prime numbers that equal zero when embedded in the ring.*)\nNotation char := pchar (only parsing).\n\nLocal Notation has_pchar0 L := (pchar L =i pred0).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use has_pchar0 instead.\")]\nNotation has_char0 L := (has_pchar0 L) (only parsing).\n\n(*This definition creates a type alias that serves as the carrier type for the opposite ring structure, where the order of multiplication is reversed.*)\nDefinition converse R : Type := R.\n(*This notation denotes the type of the opposite ring, which has the same elements and addition as the original ring but with a reversed multiplication operation.*)\nLocal Notation \"R ^c\" := (converse R) (at level 2, format \"R ^c\") : type_scope.\n\nSection PzSemiRingTheory.\n\nVariable R : pzSemiRingType.\nImplicit Types x y : R.\n\n#[export]\nHB.instance Definition _ := Monoid.isLaw.Build R 1 *%R mulrA mul1r mulr1.\n#[export]\nHB.instance Definition _ := Monoid.isMulLaw.Build R 0 *%R mul0r mulr0.\n#[export]\n(*This lemma states that right multiplication by a ring element distributes over an indexed finite sum of ring elements.*)\nLemma mulr_suml I r P (F : I -> R) x :\n (\\sum_(i <- r | P i) F i) * x = \\sum_(i <- r | P i) F i * x.\n\n(*This lemma states that left multiplication by a ring element distributes over an indexed finite sum of ring elements.*)\nLemma mulr_sumr I r P (F : I -> R) x :\n x * (\\sum_(i <- r | P i) F i) = \\sum_(i <- r | P i) x * F i.\n\n(*This lemma states that the product of a repeated sum of a ring element and another ring element is equal to the repeated sum of their product.*)\nLemma mulrnAl x y n : (x *+ n) * y = (x * y) *+ n.\n\n(*This lemma states that the product of a ring element with a repeated sum of another ring element is equal to the repeated sum of their product.*)\nLemma mulrnAr x y n : x * (y *+ n) = (x * y) *+ n.\n\n(*This lemma states that left-multiplying a ring element by the ring embedding of a natural number is equivalent to the repeated sum of that ring element.*)\nLemma mulr_natl x n : n%:R * x = x *+ n.\n\n(*This lemma states that right-multiplying a ring element by the ring embedding of a natural number is equivalent to the repeated sum of that ring element.*)\nLemma mulr_natr x n : x * n%:R = x *+ n.\n\n(*This lemma states that the ring embedding of a sum of two natural numbers is equal to the sum of their individual ring embeddings.*)\nLemma natrD m n : (m + n)%:R = m%:R + n%:R :> R. \n(*This lemma states that adding the multiplicative identity of the ring to the ring embedding of a natural number yields the ring embedding of the successor of that number.*)\nLemma natr1 n : n%:R + 1 = n.+1%:R :> R. \n(*This lemma states that adding the ring embedding of a natural number to the multiplicative identity of the ring yields the ring embedding of the successor of that number.*)\nLemma nat1r n : 1 + n%:R = n.+1%:R :> R. \n\n(*This definition establishes that the function embedding natural numbers into a ring is a morphism for finite summations, meaning it preserves finite sums.*)\nDefinition natr_sum := big_morph (natmul 1) natrD (mulr0n 1).\n\n(*This lemma states that the ring embedding of a product of two natural numbers is equal to the product of their individual ring embeddings.*)\nLemma natrM m n : (m * n)%:R = m%:R * n%:R :> R.\n\n(*This lemma states that any ring element raised to the power of zero equals the multiplicative identity of the ring.*)\nLemma expr0 x : x ^+ 0 = 1. \n(*This lemma states that any ring element raised to the power of one equals the element itself.*)\nLemma expr1 x : x ^+ 1 = x. \n(*This lemma states that any ring element raised to the power of two is equal to the product of the element with itself.*)\nLemma expr2 x : x ^+ 2 = x * x. \n\n(*This lemma provides the inductive definition for exponentiation, stating that a ring element raised to the power of the successor of a natural number is equal to the element multiplied by itself raised to the power of that natural number.*)\nLemma exprS x n : x ^+ n.+1 = x * x ^+ n.\n\n(*This lemma states that raising the zero element of a ring to the power of a natural number results in the multiplicative identity if the exponent is zero, and the zero element otherwise.*)\nLemma expr0n n : 0 ^+ n = (n == 0%N)%:R :> R.\n\n(*This lemma states that raising the multiplicative identity of a ring to any natural number power results in the multiplicative identity.*)\nLemma expr1n n : 1 ^+ n = 1 :> R.\n\n(*This lemma states that raising a ring element to the power of a sum of two natural numbers is equal to the product of the element raised to each of the numbers individually.*)\nLemma exprD x m n : x ^+ (m + n) = x ^+ m * x ^+ n.\n\n(*This lemma provides the recursive step for exponentiation, stating that a ring element raised to the power of the successor of a natural number is equivalent to the product of the element raised to the power of the natural number and the element itself.*)\nLemma exprSr x n : x ^+ n.+1 = x ^+ n * x.\n\n(*This lemma states that raising a ring element to the power of a summation of natural numbers over a filtered sequence is equivalent to the product of terms where each term is the ring element raised to the power of a corresponding number from the summation.*)\nLemma expr_sum x (I : Type) (s : seq I) (P : pred I) F :\n x ^+ (\\sum_(i <- s | P i) F i) = \\prod_(i <- s | P i) x ^+ F i :> R.\n\n(*This lemma states that the commutation relation for multiplication of ring elements is symmetric: if a first element commutes with a second, then the second also commutes with the first.*)\nLemma commr_sym x y : comm x y -> comm y x. \n(*This lemma states that the commutation relation for multiplication of ring elements is reflexive, meaning any element commutes with itself.*)\nLemma commr_refl x : comm x x. \n\n(*This lemma states that any ring element commutes with the additive identity (zero).*)\nLemma commr0 x : comm x 0.\n\n(*This lemma states that any ring element commutes with the multiplicative identity (one).*)\nLemma commr1 x : comm x 1.\n\n(*This lemma states that if a ring element commutes with two other ring elements, it also commutes with their sum.*)\nLemma commrD x y z : comm x y -> comm x z -> comm x (y + z).\n\n(*This lemma states that if a ring element commutes with every term in a summation over a filtered sequence of ring elements, it also commutes with the total sum.*)\nLemma commr_sum (I : Type) (s : seq I) (P : pred I) (F : I -> R) x :\n (forall i, P i -> comm x (F i)) -> comm x (\\sum_(i <- s | P i) F i).\n\n(*This lemma states that if a ring element commutes with another ring element, it also commutes with the result of repeatedly adding the second element to itself a number of times specified by any natural number.*)\nLemma commrMn x y n : comm x y -> comm x (y *+ n).\n\n(*This lemma states that if a ring element commutes with two other ring elements, it also commutes with their product.*)\nLemma commrM x y z : comm x y -> comm x z -> comm x (y * z).\n\n(*This lemma states that if a ring element commutes with every factor in a product over a filtered sequence of ring elements, it also commutes with the total product.*)\nLemma commr_prod (I : Type) (s : seq I) (P : pred I) (F : I -> R) x :\n (forall i, P i -> comm x (F i)) -> comm x (\\prod_(i <- s | P i) F i).\n\n(*This lemma states that any ring element commutes with the ring element that represents a natural number.*)\nLemma commr_nat x n : comm x n%:R. \n\n(*This lemma states that if a ring element commutes with another ring element, it also commutes with any natural number power of that second element.*)\nLemma commrX x y n : comm x y -> comm x (y ^+ n).\n\n(*This lemma states that if two ring elements commute, raising their product to a natural number power is equivalent to the product of each element raised to that same power.*)\nLemma exprMn_comm x y n : comm x y -> (x * y) ^+ n = x ^+ n * y ^+ n.\n\n(*This lemma relates exponentiation with multiplication by a natural number, stating that raising the product of a ring element and a first natural number to the power of a second natural number is equal to the product of the ring element raised to the power of the second natural number and the first natural number raised to the power of the second natural number.*)\nLemma exprMn_n x m n : (x *+ m) ^+ n = x ^+ n *+ (m ^ n) :> R.\n\n(*This lemma states the power of a power rule for ring elements: raising a ring element to the power of a product of two natural numbers is equivalent to successively raising the element to the power of each number.*)\nLemma exprM x m n : x ^+ (m * n) = x ^+ m ^+ n.\n\n(*This lemma states that the order of exponents in a nested exponentiation of a ring element can be swapped, as raising an element to a first natural number power and then to a second is the same as raising it to the second power and then to the first.*)\nLemma exprAC x m n : (x ^+ m) ^+ n = (x ^+ n) ^+ m.\n\n(*This lemma states that if a ring element raised to a specific natural number power is equal to the multiplicative identity, then raising that element to any other natural number power is equivalent to raising it to the power of the remainder of the division of that other number by the specific one.*)\nLemma expr_mod n x i : x ^+ n = 1 -> x ^+ (i %% n) = x ^+ i.\n\n(*This lemma states that if a ring element raised to a specific natural number power is the multiplicative identity, then raising that element to any multiple of that number also results in the multiplicative identity.*)\nLemma expr_dvd n x i : x ^+ n = 1 -> n %| i -> x ^+ i = 1.\n\n(*This lemma states that the ring embedding of a natural number raised to a power is equivalent to raising the ring embedding of that natural number to the same power.*)\nLemma natrX n k : (n ^ k)%:R = n%:R ^+ k :> R.\n\n(*This lemma states that for a left-regular ring element, its product with a second ring element is the additive identity if and only if the second element is the additive identity.*)\nLemma mulrI_eq0 x y : lreg x -> (x * y == 0) = (y == 0).\n\n(*This lemma states that the multiplicative identity of a ring is a left-regular element.*)\nLemma lreg1 : lreg (1 : R).\n\n(*This lemma states that the product of two left-regular ring elements is also a left-regular element.*)\nLemma lregM x y : lreg x -> lreg y -> lreg (x * y).\n\n(*This lemma states that if the product of two ring elements is a left-regular element, then the second element in the product must also be a left-regular element.*)\nLemma lregMl (a b: R) : lreg (a * b) -> lreg b.\n\n(*This lemma states that if the product of two ring elements is a right-regular element, then the first element in the product must also be a right-regular element.*)\nLemma rregMr (a b: R) : rreg (a * b) -> rreg a.\n\n(*This lemma states that if a ring element is left-regular, then any of its natural number powers is also a left-regular element.*)\nLemma lregX x n : lreg x -> lreg (x ^+ n).\n\n(*This lemma states that repeatedly applying left-multiplication by a ring element for a given number of iterations to a second ring element results in the product of the first element raised to that number's power and the second element.*)\nLemma iter_mulr n x y : iter n ( *%R x) y = x ^+ n * y.\n\n(*This lemma states that iterating the right multiplication by a semiring element `x` `n` times, starting from the multiplicative identity `1`, is equivalent to computing `x` raised to the power of `n`.*)\nLemma iter_mulr_1 n x : iter n ( *%R x) 1 = x ^+ n.\n\n(*This lemma states that the product of a constant ring element over a subset of a finite type is equal to that element raised to the power of the cardinality of the subset.*)\nLemma prodr_const (I : finType) (A : pred I) x : \\prod_(i in A) x = x ^+ #|A|.\n\n(*This lemma states that the product of a constant ring element over a range of natural numbers from `n` to `m` (exclusive) is equal to that element raised to the power of the difference between `m` and `n`.*)\nLemma prodr_const_nat n m x : \\prod_(n <= i < m) x = x ^+ (m - n).\n\n(*This lemma states that for a ring element `x`, the product of `x` raised to various natural number powers, indexed over a filtered sequence, is equal to `x` raised to the power of the sum of those exponents.*)\nLemma prodrXr x I r P (F : I -> nat) :\n \\prod_(i <- r | P i) x ^+ F i = x ^+ (\\sum_(i <- r | P i) F i).\n\n(*This lemma states that the product of a termwise product of two functions over a filtered sequence can be split into the product of the individual products of each function, provided that any value from the first function commutes with any value from the second function over the indexed domain.*)\nLemma prodrM_comm {I : eqType} r (P : pred I) (F G : I -> R) :\n (forall i j, P i -> P j -> comm (F i) (G j)) ->\n \\prod_(i <- r | P i) (F i * G i) =\n \\prod_(i <- r | P i) F i * \\prod_(i <- r | P i) G i.\n\n(*This lemma states that a constant ring element `x` can be factored out from the left of a product over a subset of a finite type, resulting in `x` raised to the power of the subset's cardinality multiplied by the product of the remaining terms, provided that `x` commutes with every term in the original product.*)\nLemma prodrMl_comm {I : finType} (A : pred I) (x : R) F :\n (forall i, A i -> comm x (F i)) ->\n \\prod_(i in A) (x * F i) = x ^+ #|A| * \\prod_(i in A) F i.\n\n(*This lemma states that a constant ring element `x` can be factored out from the right of a product over a subset of a finite type, resulting in the product of the original terms multiplied by `x` raised to the power of the subset's cardinality, provided that `x` commutes with every term in the original product.*)\nLemma prodrMr_comm {I : finType} (A : pred I) (x : R) F :\n (forall i, A i -> comm x (F i)) ->\n \\prod_(i in A) (F i * x) = \\prod_(i in A) F i * x ^+ #|A|.\n\n(*This lemma relates the product of scaled elements to the scaling of their product, asserting that the product of elements, each scaled by a natural number, is equivalent to the product of the elements scaled by the product of the natural numbers.*)\nLemma prodrMn (I : Type) (s : seq I) (P : pred I) (F : I -> R) (g : I -> nat) :\n \\prod_(i <- s | P i) (F i *+ g i) =\n \\prod_(i <- s | P i) (F i) *+ \\prod_(i <- s | P i) g i.\n\n(*This lemma states that when taking a product of function values each scaled by a constant natural number `n`, the result is the product of the function values scaled by `n` raised to the power of the size of the domain.*)\nLemma prodrMn_const n (I : finType) (A : pred I) (F : I -> R) :\n \\prod_(i in A) (F i *+ n) = \\prod_(i in A) F i *+ n ^ #|A|.\n\n(*This lemma asserts that the canonical embedding of a product of natural numbers into a ring is equivalent to the product of the canonical embeddings of each individual natural number.*)\nLemma natr_prod I r P (F : I -> nat) :\n (\\prod_(i <- r | P i) F i)%:R = \\prod_(i <- r | P i) (F i)%:R :> R.\n\n(*This lemma provides the binomial expansion for the `n`-th power of a sum of two commuting ring elements. The expansion is a sum of terms, each consisting of a binomial coefficient multiplied by powers of the two elements.*)\nLemma exprDn_comm x y n (cxy : comm x y) :\n (x + y) ^+ n = \\sum_(i < n.+1) (x ^+ (n - i) * y ^+ i) *+ 'C(n, i).\n\n(*This lemma states the binomial expansion for the `n`-th power of the sum of a ring element and the multiplicative identity. The result is the sum of terms where each `i`-th power of the element is scaled by the binomial coefficient 'n choose i'.*)\nLemma exprD1n x n : (x + 1) ^+ n = \\sum_(i < n.+1) x ^+ i *+ 'C(n, i).\n\n(*This lemma states that the square of the sum of a ring element and the multiplicative identity is equal to the square of the element, plus the element scaled by two, plus one.*)\nLemma sqrrD1 x : (x + 1) ^+ 2 = x ^+ 2 + x *+ 2 + 1.\n\nSection ClosedPredicates.\n\nVariable S : {pred R}.\n\n(*This definition specifies the property of a subset of a semiring being closed under binary multiplication, meaning the product of any two elements from the subset is also in the subset.*)\nDefinition mulr_2closed := {in S &, forall u v, u * v \\in S}.\n(*This definition specifies the property of a subset of a semiring being closed under multiplication, which requires that it contains the multiplicative identity and is closed under binary multiplication.*)\nDefinition mulr_closed := 1 \\in S /\\ mulr_2closed.\n(*This definition specifies the property of a subset of a semiring being a closed sub-semiring, which requires it to be closed under both its additive and multiplicative structures.*)\nDefinition semiring_closed := nmod_closed S /\\ mulr_closed.\n\n(*This lemma states that if a subset of a semiring is a closed sub-semiring, then it is necessarily closed under the additive operations.*)\nLemma semiring_closedD : semiring_closed -> nmod_closed S. \n\n(*This lemma states that if a subset of a semiring is a closed sub-semiring, then it is necessarily closed under multiplication.*)\nLemma semiring_closedM : semiring_closed -> mulr_closed. \n\nEnd ClosedPredicates.\n\nEnd PzSemiRingTheory.\n\nSection NzSemiRingTheory.\n\nVariable R : nzSemiRingType.\nImplicit Types x y : R.\n\n(*This lemma asserts that in a non-trivial semiring, the multiplicative identity is never equal to the additive identity.*)\nLemma oner_eq0 : (1 == 0 :> R) = false. \n\n(*This lemma states that for a sequence of elements in a non-trivial semiring, testing if its last element is zero gives the same boolean result whether the default for an empty sequence is a non-zero element or the multiplicative identity.*)\nLemma lastr_eq0 (s : seq R) x : x != 0 -> (last x s == 0) = (last 1 s == 0).\n\n(*This lemma states that any left-regular element in a non-trivial semiring must be non-zero.*)\nLemma lreg_neq0 x : lreg x -> x != 0.\n\n(*This definition introduces the Frobenius automorphism for a semiring of prime characteristic `p`, defining it as the function that maps any element of the semiring to that element raised to the power of `p`.*)\nDefinition pFrobenius_aut p of p \\in pchar R := fun x => x ^+ p.\n\nSection FrobeniusAutomorphism.\n\nVariable p : nat.\nHypothesis pcharFp : p \\in pchar R.\n\n(*This lemma states that for a semiring with prime characteristic `p`, the canonical embedding of the natural number `p` into the semiring is equal to the additive identity.*)\nLemma pcharf0 : p%:R = 0 :> R. \n\n(*This lemma states that any numeric characteristic of a semiring belonging to its set of prime characteristics must be a prime number.*)\nLemma pcharf_prime : prime p. \nHint Resolve pcharf_prime : core.\n\n(*This lemma states that in a semiring with prime characteristic `p`, scaling any element by the natural number `p` results in the additive identity.*)\nLemma mulrn_pchar x : x *+ p = 0. \n\n(*This lemma states that in a semiring with prime characteristic `p`, the canonical embedding of a natural number `n` is equal to the canonical embedding of `n` modulo `p`.*)\nLemma natr_mod_pchar n : (n %% p)%:R = n%:R :> R.\n\n(*This lemma establishes that for a prime characteristic `p` of a semiring, a natural number `n` is divisible by `p` if and only if the canonical embedding of `n` into the semiring is equal to the additive identity.*)\nLemma dvdn_pcharf n : (p %| n)%N = (n%:R == 0 :> R).\n\n(*This lemma states that in the given context, the set of prime characteristics of the semiring is precisely the singleton set containing the prime `p`.*)\nLemma pcharf_eq : pchar R =i (p : nat_pred).\n\n(*This lemma states that for a prime characteristic `p` of a semiring, the canonical embedding of the binomial coefficient 'p choose k' is zero for any `k` strictly between zero and `p`.*)\nLemma bin_lt_pcharf_0 k : 0 < k < p -> 'C(p, k)%:R = 0 :> R.\n\n(**)\nLocal Notation \"x ^f\" := (pFrobenius_aut pcharFp x).\n\n(*This lemma states that applying the p-Frobenius automorphism to a ring element is equivalent to raising that element to the power of the characteristic p.*)\nLemma pFrobenius_autE x : x^f = x ^+ p. \n(*This notation provides a local alias for the lemma `pFrobenius_autE`, which equates the p-Frobenius automorphism with exponentiation by the characteristic.*)\nLocal Notation f'E := pFrobenius_autE.\n\n(*This lemma states that the p-Frobenius automorphism maps the zero element of the ring to itself.*)\nLemma pFrobenius_aut0 : 0^f = 0.\n\n(*This lemma states that the p-Frobenius automorphism maps the multiplicative identity element of the ring to itself.*)\nLemma pFrobenius_aut1 : 1^f = 1.\n\n(*This lemma states that for any two commuting ring elements, the p-Frobenius automorphism of their sum is equal to the sum of their individual p-Frobenius automorphisms.*)\nLemma pFrobenius_autD_comm x y (cxy : comm x y) : (x + y)^f = x^f + y^f.\n\n(*This lemma states that applying the p-Frobenius automorphism to the result of adding a ring element to itself a specified number of times is equivalent to first applying the automorphism to the element and then performing the repeated addition.*)\nLemma pFrobenius_autMn x n : (x *+ n)^f = x^f *+ n.\n\n(*This lemma states that the p-Frobenius automorphism acts as the identity on any ring element that is the canonical image of a natural number.*)\nLemma pFrobenius_aut_nat n : (n%:R)^f = n%:R.\n\n(*This lemma states that if two ring elements commute, the p-Frobenius automorphism of their product is equal to the product of their individual p-Frobenius automorphisms.*)\nLemma pFrobenius_autM_comm x y : comm x y -> (x * y)^f = x^f * y^f.\n\n(*This lemma states that applying the p-Frobenius automorphism to a ring element raised to a natural number power is equivalent to first applying the automorphism to the element and then raising the result to the same power.*)\nLemma pFrobenius_autX x n : (x ^+ n)^f = x^f ^+ n.\n\nEnd FrobeniusAutomorphism.\n\nSection Char2.\n\nHypothesis pcharR2 : 2 \\in pchar R.\n\n(*This lemma states that in a ring where two is a characteristic, adding any element to itself results in the zero element.*)\nLemma addrr_pchar2 x : x + x = 0. \n\nEnd Char2.\n\nEnd NzSemiRingTheory.\n\n#[short(type=\"pzRingType\")]\n(*This definition introduces the structure for a p-z-ring, which combines the properties of a p-z-semiring with those of a module over the integers.*)\nHB.structure Definition PzRing := { R of PzSemiRing R & Zmodule R }.\n\n(*This factory defines a record that provides the necessary components and properties, including a multiplicative identity and a distributive multiplication, to construct a p-z-ring structure from a module over the integers.*)\nHB.factory Record Zmodule_isPzRing R of Zmodule R := {\n one : R;\n mul : R -> R -> R;\n mulrA : associative mul;\n mul1r : left_id one mul;\n mulr1 : right_id one mul;\n mulrDl : left_distributive mul +%R;\n mulrDr : right_distributive mul +%R;\n}.\n\nHB.builders Context R of Zmodule_isPzRing R.\n(*This notation provides a local alias for the multiplicative identity element.*)\n Local Notation \"1\" := one.\n(*This notation provides a local alias for the multiplication operation between two ring elements.*)\n Local Notation \"x * y\" := (mul x y).\n Lemma mul0r : @left_zero R R 0 mul.\n \n Lemma mulr0 : @right_zero R R 0 mul.\n \n HB.instance Definition _ := Nmodule_isPzSemiRing.Build R\n mulrA mul1r mulr1 mulrDl mulrDr mul0r mulr0.\nHB.end.\n\n(*This factory defines a record that gathers all the necessary components and axioms, such as zero, addition, additive inverse, one, and multiplication, to construct a p-z-ring structure from a base type.*)\nHB.factory Record isPzRing R of Choice R := {\n zero : R;\n opp : R -> R;\n add : R -> R -> R;\n one : R;\n mul : R -> R -> R;\n addrA : associative add;\n addrC : commutative add;\n add0r : left_id zero add;\n addNr : left_inverse zero opp add;\n mulrA : associative mul;\n mul1r : left_id one mul;\n mulr1 : right_id one mul;\n mulrDl : left_distributive mul add;\n mulrDr : right_distributive mul add;\n}.\n\nHB.builders Context R of isPzRing R.\n HB.instance Definition _ := @isZmodule.Build R\n zero opp add addrA addrC add0r addNr.\n HB.instance Definition _ := @Zmodule_isPzRing.Build R\n one mul mulrA mul1r mulr1 mulrDl mulrDr.\nHB.end.\n\nModule PzRingExports.\nBind Scope ring_scope with PzRing.sort.\nEnd PzRingExports.\nHB.export PzRingExports.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut instead.\")]\n(*A deprecated notation, now aliased to `pFrobenius_aut` for parsing only, which represents the p-Frobenius automorphism on a ring.*)\nNotation Frobenius_aut := pFrobenius_aut (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf0 instead.\")]\n(*A deprecated notation, now aliased to `pcharf0` for parsing only, which relates to properties of fields with a prime characteristic.*)\nNotation charf0 := pcharf0 (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf_prime instead.\")]\n(*A deprecated notation, now aliased to `pcharf_prime` for parsing only, used in assertions about the primality of a field's characteristic.*)\nNotation charf_prime := pcharf_prime (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use mulrn_pchar instead.\")]\n(*A deprecated notation, now aliased to `mulrn_pchar` for parsing only, related to repeated addition of a ring element in a ring with prime characteristic.*)\nNotation mulrn_char := mulrn_pchar (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use natr_mod_pchar instead.\")]\n(*A deprecated notation, now aliased to `natr_mod_pchar` for parsing only, concerning the canonical injection of natural numbers into a ring, modulo the ring's characteristic.*)\nNotation natr_mod_char := natr_mod_pchar (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use dvdn_pcharf instead.\")]\n(*A deprecated notation, now aliased to `dvdn_pcharf` for parsing only, which pertains to divisibility properties of natural numbers within the context of a field's characteristic.*)\nNotation dvdn_charf := dvdn_pcharf (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf_eq instead.\")]\n(*A deprecated notation, now aliased to `pcharf_eq` for parsing only, used for equalities involving the characteristic of a field.*)\nNotation charf_eq := pcharf_eq (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use bin_lt_pcharf_0 instead.\")]\n(*A deprecated notation, now aliased to `bin_lt_pcharf_0` for parsing only, which states that certain binomial coefficients are zero in a field with prime characteristic.*)\nNotation bin_lt_charf_0 := bin_lt_pcharf_0 (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autE instead.\")]\n(*A deprecated notation, now aliased to `pFrobenius_autE` for parsing only, which provides the definition of the Frobenius automorphism as exponentiation by the characteristic.*)\nNotation Frobenius_autE := pFrobenius_autE (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut0 instead.\")]\n(*A deprecated notation, now aliased to `pFrobenius_aut0` for parsing only, stating that the Frobenius automorphism maps the zero element to itself.*)\nNotation Frobenius_aut0 := pFrobenius_aut0 (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut1 instead.\")]\n(*A deprecated notation, now aliased to `pFrobenius_aut1` for parsing only, stating that the Frobenius automorphism maps the multiplicative identity to itself.*)\nNotation Frobenius_aut1 := pFrobenius_aut1 (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autD_comm instead.\")]\n(*A deprecated notation, now aliased to `pFrobenius_autD_comm` for parsing only, stating that the Frobenius automorphism distributes over the sum of two commuting elements.*)\nNotation Frobenius_autD_comm := pFrobenius_autD_comm (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autMn instead.\")]\n(*A deprecated notation, now aliased to `pFrobenius_autMn` for parsing only, concerning the interaction between the Frobenius automorphism and repeated addition of a ring element.*)\nNotation Frobenius_autMn := pFrobenius_autMn (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut_nat instead.\")]\n(*A deprecated notation, now aliased to `pFrobenius_aut_nat` for parsing only, stating that the Frobenius automorphism is the identity on canonical images of natural numbers in the ring.*)\nNotation Frobenius_aut_nat := pFrobenius_aut_nat (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autM_comm instead.\")]\n(*A deprecated notation, now aliased to `pFrobenius_autM_comm` for parsing only, stating that the Frobenius automorphism distributes over the product of two commuting elements.*)\nNotation Frobenius_autM_comm := pFrobenius_autM_comm (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autX instead.\")]\n(*This deprecated notation provides a syntax for the p-Frobenius automorphism on a ring, which raises every element to the power of a prime p.*)\nNotation Frobenius_autX := pFrobenius_autX (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use addrr_pchar2 instead.\")]\n(*This deprecated notation refers to a lemma stating that in a ring of characteristic two, adding any element to itself results in zero.*)\nNotation addrr_char2 := addrr_pchar2 (only parsing).\n\n#[short(type=\"nzRingType\")]\n(*This definition introduces the structure for a non-zero ring, which is a ring where the multiplicative identity element is distinct from the additive identity element.*)\nHB.structure Definition NzRing := { R of NzSemiRing R & Zmodule R }.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzRing instead.\")]\nNotation Ring R := (NzRing R) (only parsing).\n\nModule Ring.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzRing.sort instead.\")]\n(*This deprecated notation refers to the underlying carrier type of a non-zero ring structure.*)\nNotation sort := (NzRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzRing.on instead.\")]\nNotation on R := (NzRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzRing.copy instead.\")]\nNotation copy T U := (NzRing.copy T U) (only parsing).\nEnd Ring.\n\n(*This factory record provides the components needed to construct a non-zero ring structure on a type that is already equipped with a Z-module astructure. It requires specifying the multiplicative identity, multiplication, and proving the relevant axioms.*)\nHB.factory Record Zmodule_isNzRing R of Zmodule R := {\n one : R;\n mul : R -> R -> R;\n mulrA : associative mul;\n mul1r : left_id one mul;\n mulr1 : right_id one mul;\n mulrDl : left_distributive mul +%R;\n mulrDr : right_distributive mul +%R;\n oner_neq0 : one != 0\n}.\n\nModule Zmodule_isRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Zmodule_isNzRing.Build instead.\")]\nNotation Build R := (Zmodule_isNzRing.Build R) (only parsing).\nEnd Zmodule_isRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Zmodule_isNzRing instead.\")]\nNotation Zmodule_isRing R := (Zmodule_isNzRing R) (only parsing).\n\nHB.builders Context R of Zmodule_isNzRing R.\n HB.instance Definition _ := Zmodule_isPzRing.Build R \n mulrA mul1r mulr1 mulrDl mulrDr.\n HB.instance Definition _ := PzSemiRing_isNonZero.Build R oner_neq0.\nHB.end.\n\n(*This factory record gathers all the axioms required to define a non-zero ring structure from a basic type. It includes properties for addition, multiplication, their interaction via distributivity, and the condition that the multiplicative and additive identities are distinct.*)\nHB.factory Record isNzRing R of Choice R := {\n zero : R;\n opp : R -> R;\n add : R -> R -> R;\n one : R;\n mul : R -> R -> R;\n addrA : associative add;\n addrC : commutative add;\n add0r : left_id zero add;\n addNr : left_inverse zero opp add;\n mulrA : associative mul;\n mul1r : left_id one mul;\n mulr1 : right_id one mul;\n mulrDl : left_distributive mul add;\n mulrDr : right_distributive mul add;\n oner_neq0 : one != zero\n}.\n\nModule isRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use isNzRing.Build instead.\")]\nNotation Build R := (isNzRing.Build R) (only parsing).\nEnd isRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use isNzRing instead.\")]\nNotation isRing R := (isNzRing R) (only parsing).\n\nHB.builders Context R of isNzRing R.\n HB.instance Definition _ := @isZmodule.Build R\n zero opp add addrA addrC add0r addNr.\n HB.instance Definition _ := @Zmodule_isNzRing.Build R\n one mul mulrA mul1r mulr1 mulrDl mulrDr oner_neq0.\nHB.end.\n\nModule NzRingExports.\nBind Scope ring_scope with NzRing.sort.\nEnd NzRingExports.\nHB.export NzRingExports.\n\nNotation sign R b := (exp (- @one R) (nat_of_bool b)) (only parsing).\n\n(*This notation defines the expression for the additive inverse of the multiplicative identity element within a ring.*)\nLocal Notation \"- 1\" := (- (1)) : ring_scope.\n\nSection PzRingTheory.\n\nVariable R : pzRingType.\nImplicit Types x y : R.\n\n(*This lemma states that for any two ring elements, the product of the first element and the additive inverse of the second is equal to the additive inverse of their product.*)\nLemma mulrN x y : x * (- y) = - (x * y).\n\n(*This lemma states that for any two ring elements, the product of the additive inverse of the first element and the second element is equal to the additive inverse of their product.*)\nLemma mulNr x y : (- x) * y = - (x * y).\n\n(*This lemma states that for any two ring elements, the product of their additive inverses is equal to their original product.*)\nLemma mulrNN x y : (- x) * (- y) = x * y.\n\n(*This lemma states that multiplying negative one by any ring element results in the additive inverse of that element.*)\nLemma mulN1r x : -1 * x = - x.\n\n(*This lemma states that multiplying any ring element by negative one results in the additive inverse of that element.*)\nLemma mulrN1 x : x * -1 = - x.\n\n(*This lemma states that multiplication on the right distributes over subtraction, meaning the product of a difference of two elements and a third element is the same as the difference of the products.*)\nLemma mulrBl x y z : (y - z) * x = y * x - z * x.\n\n(*This lemma states that multiplication on the left distributes over subtraction, meaning the product of an element and a difference of two other elements is the same as the difference of the products.*)\nLemma mulrBr x y z : x * (y - z) = x * y - x * z.\n\n(*This lemma states that if a natural number is smaller than or equal to another, the ring representation of their difference equals the difference of their individual ring representations.*)\nLemma natrB m n : n <= m -> (m - n)%:R = m%:R - n%:R :> R.\n\n(*This lemma states that if two ring elements commute under multiplication, then the first element also commutes with the additive inverse of the second.*)\nLemma commrN x y : comm x y -> comm x (- y).\n\n(*This lemma states that any ring element commutes with negative one under multiplication.*)\nLemma commrN1 x : comm x (-1). \n\n(*This lemma states that if a ring element commutes with two other elements, it also commutes with their difference.*)\nLemma commrB x y z : comm x y -> comm x z -> comm x (y - z).\n\n(*This lemma states that any ring element commutes with negative one raised to any natural number power.*)\nLemma commr_sign x n : comm x ((-1) ^+ n).\n\n(*This lemma states that raising negative one to a power determined by whether a natural number is odd is equivalent to raising negative one to the power of that natural number itself.*)\nLemma signr_odd n : (-1) ^+ (odd n) = (-1) ^+ n :> R.\n\n(*This lemma states that multiplying a ring element by the sign of a boolean, which is one for false and negative one for true, results in the element itself for a false boolean and its additive inverse for a true boolean.*)\nLemma mulr_sign (b : bool) x : (-1) ^+ b * x = (if b then - x else x).\n\n(*This lemma states that the sign associated with the exclusive-or of two booleans is equal to the product of the signs of the individual booleans.*)\nLemma signr_addb b1 b2 : (-1) ^+ (b1 (+) b2) = (-1) ^+ b1 * (-1) ^+ b2 :> R.\n\n(*This lemma provides an arithmetic formula for the sign of a boolean, stating that it is equal to one minus twice the ring representation of the natural number corresponding to that boolean.*)\nLemma signrE (b : bool) : (-1) ^+ b = 1 - b.*2%:R :> R.\n\n(*This lemma states that the sign of the negation of a boolean is the additive inverse of the sign of the original boolean.*)\nLemma signrN b : (-1) ^+ (~~ b) = - (-1) ^+ b :> R.\n\n(*This lemma states that the product of two signed elements is equal to the product of the original elements multiplied by a sign determined from the exclusive-or of the two booleans.*)\nLemma mulr_signM (b1 b2 : bool) x1 x2 :\n ((-1) ^+ b1 * x1) * ((-1) ^+ b2 * x2) = (-1) ^+ (b1 (+) b2) * (x1 * x2).\n\n(*This lemma states that raising the additive inverse of a ring element to a natural number power is equivalent to multiplying the element raised to that power by negative one raised to the same power.*)\nLemma exprNn x n : (- x) ^+ n = (-1) ^+ n * x ^+ n :> R.\n\n(*This lemma states that the square of the additive inverse of a ring element is equal to the square of the element itself.*)\nLemma sqrrN x : (- x) ^+ 2 = x ^+ 2. \n\n(*This lemma states that the square of negative one raised to any natural number power is always equal to one.*)\nLemma sqrr_sign n : ((-1) ^+ n) ^+ 2 = 1 :> R.\n\n(*This lemma states that the function that multiplies a ring element by negative one raised to a given natural number power is an involution, meaning applying it twice returns the original element.*)\nLemma signrMK n : @involutive R ( *%R ((-1) ^+ n)).\n\n(*This lemma states that if an element in a ring is not a left zero-divisor, meaning its product with another element is zero only if the other element is zero, then it is left-cancellable for multiplication.*)\nLemma mulrI0_lreg x : (forall y, x * y = 0 -> y = 0) -> lreg x.\n\n(*This lemma states that if a ring element is left-regular for multiplication, then its additive inverse is also left-regular for multiplication.*)\nLemma lregN x : lreg x -> lreg (- x).\n\n(*This lemma states that for any natural number, raising the ring element negative one to the power of that number results in a left-regular element.*)\nLemma lreg_sign n : lreg ((-1) ^+ n : R). \n\n(*This lemma states that the product of the additive inverses of a family of ring elements, indexed over a finite set, is equal to the product of the original elements multiplied by negative one raised to the power of the cardinality of the index set.*)\nLemma prodrN (I : finType) (A : pred I) (F : I -> R) :\n \\prod_(i in A) - F i = (- 1) ^+ #|A| * \\prod_(i in A) F i.\n\n(*This lemma provides the binomial expansion for the nth power of the difference of two commuting ring elements, expressing it as a sum over terms involving binomial coefficients, powers of the elements, and powers of negative one.*)\nLemma exprBn_comm x y n (cxy : comm x y) :\n (x - y) ^+ n =\n \\sum_(i < n.+1) ((-1) ^+ i * x ^+ (n - i) * y ^+ i) *+ 'C(n, i).\n\n(*This lemma states that for two commuting ring elements, the difference of their nth powers is equal to their difference multiplied by a sum of products of their powers.*)\nLemma subrXX_comm x y n (cxy : comm x y) :\n x ^+ n - y ^+ n = (x - y) * (\\sum_(i < n) x ^+ (n.-1 - i) * y ^+ i).\n\n(*This lemma states that for any ring element, the difference between its nth power and one is equal to the product of the element minus one and the sum of its powers from zero up to an exponent of n minus one.*)\nLemma subrX1 x n : x ^+ n - 1 = (x - 1) * (\\sum_(i < n) x ^+ i).\n\n(*This lemma states that the square of a ring element minus one is equal to the square of the element, minus twice the element, plus one.*)\nLemma sqrrB1 x : (x - 1) ^+ 2 = x ^+ 2 - x *+ 2 + 1.\n\n(*This lemma provides the difference of squares factorization for a ring element, stating that the square of the element minus one equals the product of the element minus one and the element plus one.*)\nLemma subr_sqr_1 x : x ^+ 2 - 1 = (x - 1) * (x + 1).\n\nSection ClosedPredicates.\n\nVariable S : {pred R}.\n\n(*This definition describes a property of a set of ring elements, which holds if the set contains negative one and is closed under multiplication of any two of its elements.*)\nDefinition smulr_closed := -1 \\in S /\\ mulr_2closed S.\n(*This definition describes the property of a set of ring elements forming a subring, which holds if the set contains the multiplicative identity, is closed under subtraction, and is closed under multiplication.*)\nDefinition subring_closed := [/\\ 1 \\in S, subr_2closed S & mulr_2closed S].\n\n(*This lemma states that if a set of ring elements contains negative one and is closed under multiplication, then it is necessarily closed under multiplication.*)\nLemma smulr_closedM : smulr_closed -> mulr_closed S.\n\n(*This lemma states that if a set of ring elements contains negative one and is closed under multiplication, then it is also closed under taking the additive inverse of its elements.*)\nLemma smulr_closedN : smulr_closed -> oppr_closed S.\n\n(*This lemma states that a set of ring elements that is closed under subtraction, multiplication, and contains the multiplicative identity is also closed under addition and contains the additive identity.*)\nLemma subring_closedB : subring_closed -> zmod_closed S.\n\n(*This lemma states that a set of ring elements forming a subring also has the property of containing negative one and being closed under multiplication.*)\nLemma subring_closedM : subring_closed -> smulr_closed.\n\n(*This lemma states that a set of ring elements forming a subring also satisfies the properties of a semiring, namely that it contains the multiplicative identity and is closed under both addition and multiplication.*)\nLemma subring_closed_semi : subring_closed -> semiring_closed S.\n\nEnd ClosedPredicates.\n\nEnd PzRingTheory.\n\nSection NzRingTheory.\n\nVariable R : nzRingType.\nImplicit Types x y : R.\n\n(*This lemma states that in a non-zero ring, raising negative one to any natural number power never results in the zero element.*)\nLemma signr_eq0 n : ((-1) ^+ n == 0 :> R) = false.\n\nSection FrobeniusAutomorphism.\n\nVariable p : nat.\nHypothesis pcharFp : p \\in pchar R.\n\nHint Resolve pcharf_prime : core.\n\n(*This notation provides a shorthand for applying the Frobenius automorphism. It represents an element raised to the power of the prime characteristic of the underlying semiring.*)\nLocal Notation \"x ^f\" := (pFrobenius_aut pcharFp x).\n\n(*This lemma states that applying the Frobenius automorphism to the additive inverse of a ring element yields the same result as taking the additive inverse of the Frobenius automorphism applied to the original element.*)\nLemma pFrobenius_autN x : (- x)^f = - x^f.\n\n(*This lemma states that for two commuting ring elements, the Frobenius automorphism of their difference is equal to the difference of their images under the Frobenius automorphism.*)\nLemma pFrobenius_autB_comm x y : comm x y -> (x - y)^f = x^f - y^f.\n\nEnd FrobeniusAutomorphism.\n\n(*This lemma states that under a condition involving the characteristic of the ring and a natural number exponent, raising the additive inverse of a ring element to that exponent is equivalent to taking the additive inverse of the element raised to the same exponent.*)\nLemma exprNn_pchar x n : (pchar R).-nat n -> (- x) ^+ n = - (x ^+ n).\n\nSection Char2.\n\nHypothesis pcharR2 : 2 \\in pchar R.\n\n(*This lemma states that in a ring of characteristic two, the additive inverse of any element is equal to the element itself.*)\nLemma oppr_pchar2 x : - x = x.\n\n(*This lemma states that in a ring of characteristic two, subtracting one element from another is equivalent to adding the two elements.*)\nLemma subr_pchar2 x y : x - y = x + y. \n\n(*This lemma states that in a ring of characteristic two, the function that adds a fixed element to its argument is an involution, meaning that applying the function twice returns the original value.*)\nLemma addrK_pchar2 x : involutive (+%R^~ x).\n\n(*This lemma states that in a ring of characteristic two, the function that adds its argument to a fixed element is an involution, meaning that applying the function twice returns the original value.*)\nLemma addKr_pchar2 x : involutive (+%R x).\n\nEnd Char2.\n\nEnd NzRingTheory.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autN instead.\")]\n(*A deprecated notation, now superseded by pFrobenius_autN, for the lemma stating that the Frobenius automorphism commutes with the additive inverse operation.*)\nNotation Frobenius_autN := pFrobenius_autN (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autB_comm instead.\")]\n(*A deprecated notation, now superseded by pFrobenius_autB_comm, for the lemma stating that the Frobenius automorphism of a difference of two commuting elements is the difference of their images.*)\nNotation Frobenius_autB_comm := pFrobenius_autB_comm (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use exprNn_pchar instead.\")]\n(*A deprecated notation, now superseded by exprNn_pchar, for the lemma relating the power of an additive inverse to the additive inverse of a power under conditions on the ring's characteristic.*)\nNotation exprNn_char := exprNn_pchar (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use oppr_pchar2 instead.\")]\n(*A deprecated notation, now superseded by oppr_pchar2, for the lemma stating that every element is its own additive inverse in a ring of characteristic two.*)\nNotation oppr_char2 := oppr_pchar2 (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use subr_pchar2 instead.\")]\n(*A deprecated notation, now superseded by subr_pchar2, for the lemma stating that subtraction is equivalent to addition in a ring of characteristic two.*)\nNotation subr_char2 := subr_pchar2 (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use addrK_pchar2 instead.\")]\n(*A deprecated notation, now superseded by addrK_pchar2, for the lemma stating that adding a fixed element is an involution in a ring of characteristic two.*)\nNotation addrK_char2 := addrK_pchar2 (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use addKr_pchar2 instead.\")]\n(*This notation is a deprecated alias for another notation related to adjoining a root of a polynomial, provided for parsing purposes only.*)\nNotation addKr_char2 := addKr_pchar2 (only parsing).\n\nSection ConverseRing.\n#[export]\nHB.instance Definition _ (T : eqType) := Equality.on T^c.\n#[export]\nHB.instance Definition _ (T : choiceType) := Choice.on T^c.\n#[export]\nHB.instance Definition _ (U : nmodType) := Nmodule.on U^c.\n#[export]\nHB.instance Definition _ (U : zmodType) := Zmodule.on U^c.\n#[export]\nHB.instance Definition _ (R : pzSemiRingType) :=\n let mul' (x y : R) := y * x in\n let mulrA' x y z := esym (mulrA z y x) in\n let mulrDl' x y z := mulrDr z x y in\n let mulrDr' x y z := mulrDl y z x in\n Nmodule_isPzSemiRing.Build R^c\n mulrA' mulr1 mul1r mulrDl' mulrDr' mulr0 mul0r.\n#[export]\nHB.instance Definition _ (R : pzRingType) := PzSemiRing.on R^c.\n#[export]\nHB.instance Definition _ (R : nzSemiRingType) :=\n PzSemiRing_isNonZero.Build R^c oner_neq0.\n#[export]\n(*This lemma states that the product of a sequence of elements from a semiring, when computed in the corresponding converse ring structure where multiplication is reversed, is equal to the product of the same elements computed in the original semiring over the reversed sequence.*)\nLemma rev_prodr (R : pzSemiRingType)\n (I : Type) (r : seq I) (P : pred I) (E : I -> R) :\n \\prod_(i <- r | P i) (E i : R^c) = \\prod_(i <- rev r | P i) E i.\n\nSection SemiRightRegular.\n\nVariable R : pzSemiRingType.\nImplicit Types x y : R.\n\n(*This lemma states that for a right-regular element in a semiring, its product with another element on the right is zero if and only if the other element is zero.*)\nLemma mulIr_eq0 x y : rreg x -> (y * x == 0) = (y == 0).\n\n(*This lemma states that the multiplicative identity element in a semiring is always right-regular.*)\nLemma rreg1 : rreg (1 : R).\n\n(*This lemma states that the product of two right-regular elements in a semiring is also a right-regular element.*)\nLemma rregM x y : rreg x -> rreg y -> rreg (x * y).\n\n(*This lemma states that raising an element to a natural number power in a converse semiring yields the same result as raising the same element to the same power in the original semiring.*)\nLemma revrX x n : (x : R^c) ^+ n = (x : R) ^+ n.\n\n(*This lemma states that if an element in a semiring is right-regular, then any natural number power of that element is also right-regular.*)\nLemma rregX x n : rreg x -> rreg (x ^+ n).\n\nEnd SemiRightRegular.\n\n(*This lemma states that in a non-zero semiring, any right-regular element must be non-zero.*)\nLemma rreg_neq0 (R : nzSemiRingType) (x : R) : rreg x -> x != 0.\n\nSection RightRegular.\n\nVariable R : pzRingType.\nImplicit Types x y : R.\n\n(*This lemma provides a condition for an element in a ring to be right-regular: if the only element that yields zero when multiplied by it on the right is zero itself, then the element is right-regular.*)\nLemma mulIr0_rreg x : (forall y, y * x = 0 -> y = 0) -> rreg x.\n\n(*This lemma states that in a ring, if an element is right-regular, its additive inverse is also right-regular.*)\nLemma rregN x : rreg x -> rreg (- x). \n\nEnd RightRegular.\n\n(*This record defines the properties required to equip an additive commutative monoid with a left scalar multiplication by a semiring, thereby forming a left semi-module structure. It specifies axioms for associativity of scaling, the behavior of scaling by the ring's zero and one, and distributivity of the scalar multiplication over both vector and scalar addition.*)\nHB.mixin Record Nmodule_isLSemiModule (R : pzSemiRingType) V of Nmodule V := {\n scale : R -> V -> V;\n scalerA : forall a b v, scale a (scale b v) = scale (a * b) v;\n scale0r : forall v, scale 0 v = 0;\n scale1r : left_id 1 scale;\n scalerDr : right_distributive scale +%R;\n scalerDl : forall v, {morph scale^~ v: a b / a + b}\n}.\n#[short(type=\"lSemiModType\")]\n(*This definition introduces the structure for a left semi-module over a semiring, which combines an additive commutative monoid with a compatible left scalar multiplication operation.*)\nHB.structure Definition LSemiModule (R : pzSemiRingType) :=\n {M of Nmodule M & Nmodule_isLSemiModule R M}.\n\nModule LSemiModExports.\nBind Scope ring_scope with LSemiModule.sort.\nEnd LSemiModExports.\nHB.export LSemiModExports.\n\n(*This notation represents the curried form of the scalar multiplication operation, typically used in a higher-order context.*)\nLocal Notation \"*:%R\" := (@scale _ _) : function_scope.\n(*This notation represents the infix operator for left scalar multiplication of a module element by a ring element.*)\nLocal Notation \"a *: v\" := (scale a v) : ring_scope.\n\n#[short(type=\"lmodType\")]\n(*This definition introduces the structure for a left module over a ring, which combines an abelian group with a compatible left scalar multiplication that satisfies the semi-module axioms.*)\nHB.structure Definition Lmodule (R : pzRingType) :=\n {M of Zmodule M & Nmodule_isLSemiModule R M}.\n\nArguments scalerA [R s] (a b)%_ring_scope v.\n\nModule LmodExports.\nBind Scope ring_scope with Lmodule.sort.\nEnd LmodExports.\nHB.export LmodExports.\n\n(*This factory record provides a way to construct a left module structure over a ring on an existing abelian group, by supplying a scalar multiplication operation and proving it satisfies properties such as associativity, identity, and distributivity over both scalar and vector addition.*)\nHB.factory Record Zmodule_isLmodule (R : pzRingType) V of Zmodule V := {\n scale : R -> V -> V;\n scalerA : forall a b v, scale a (scale b v) = scale (a * b) v;\n scale1r : left_id 1 scale;\n scalerDr : right_distributive scale +%R;\n scalerDl : forall v, {morph scale^~ v: a b / a + b}\n}.\n\nHB.builders Context R V of Zmodule_isLmodule R V.\n\nLemma scale0r v : scale 0 v = 0.\n\nHB.instance Definition _ :=\n Nmodule_isLSemiModule.Build R V scalerA scale0r scale1r scalerDr scalerDl.\n\nHB.end.\n\n(*This factory record provides a mechanism to upgrade a left semi-module over a ring into a full left module structure, by demonstrating that the underlying additive monoid is in fact an abelian group.*)\nHB.factory Record LSemiModule_isLmodule (R : pzRingType) V\n of LSemiModule R V := {}.\n\nHB.builders Context R V of LSemiModule_isLmodule R V.\n\n(*This definition introduces the additive inverse of a module element as the result of scaling that element by the additive inverse of the ring's multiplicative identity.*)\nDefinition opp : V -> V := scale (- 1).\n\n(*This lemma states that adding an element to its additive inverse, as defined by scaling by negative one, yields the additive identity of the module.*)\nLemma addNr : left_inverse 0 opp +%R.\n\nHB.instance Definition _ := Nmodule_isZmodule.Build V addNr.\n\nHB.end.\n\nSection LSemiModuleTheory.\n\nVariables (R : pzSemiRingType) (V : lSemiModType R).\nImplicit Types (a b c : R) (u v : V).\n\n(*This lemma states that in a left semi-module, scaling the zero element by any scalar from the ring results in the zero element.*)\nLemma scaler0 a : a *: 0 = 0 :> V.\n\n(*This lemma states that scaling a semi-module element by a natural number embedded in the scalar ring is equivalent to the repeated addition of that element to itself that number of times.*)\nLemma scaler_nat n v : n%:R *: v = v *+ n.\n\n(*This lemma states a compatibility property between scalar multiplication and repeated addition: repeatedly adding the result of a scaled element is equivalent to scaling the original element by the result of repeatedly adding the original scalar.*)\nLemma scalerMnl a v n : a *: v *+ n = (a *+ n) *: v.\n\n(*This lemma states that scaling an element that has been repeatedly added to itself is equivalent to repeatedly adding the result of scaling the original element.*)\nLemma scalerMnr a v n : a *: v *+ n = a *: (v *+ n).\n\n(*This lemma states that scaling a semi-module element by a sum of scalars is equivalent to the sum of the results of scaling that element by each scalar individually.*)\nLemma scaler_suml v I r (P : pred I) F :\n (\\sum_(i <- r | P i) F i) *: v = \\sum_(i <- r | P i) F i *: v.\n\n(*This lemma states that scaling a sum of semi-module elements by a scalar is equivalent to the sum of the results of scaling each element by that scalar individually.*)\nLemma scaler_sumr a I r (P : pred I) (F : I -> V) :\n a *: (\\sum_(i <- r | P i) F i) = \\sum_(i <- r | P i) a *: F i.\n\nSection ClosedPredicates.\n\nVariable S : {pred V}.\n\n(*This definition describes the property that a subset of a semi-module is closed under scalar multiplication, meaning that scaling any element within the subset by any scalar from the ring results in an element that is also within the subset.*)\nDefinition scaler_closed := forall a, {in S, forall v, a *: v \\in S}.\n(*This definition describes the property that a subset of a semi-module is closed under all semi-module operations, meaning it contains the zero element, is closed under addition, and is closed under scalar multiplication.*)\nDefinition subsemimod_closed := nmod_closed S /\\ scaler_closed.\n\n(*This lemma states that if a subset of a semi-module is closed under all semi-module operations, then it is also closed under the additive monoid operations, namely addition and containing the zero element.*)\nLemma subsemimod_closedD : subsemimod_closed -> nmod_closed S.\n\n(*This lemma states that if a subset of a semi-module is closed under all semi-module operations, then it is also closed under scalar multiplication.*)\nLemma subsemimod_closedZ : subsemimod_closed -> scaler_closed.\n\nEnd ClosedPredicates.\n\nEnd LSemiModuleTheory.\n\nSection LmoduleTheory.\n\nVariables (R : pzRingType) (V : lmodType R).\nImplicit Types (a b c : R) (u v : V).\n\n(*This lemma states that in a left module, scaling an element by the additive inverse of a scalar is equivalent to taking the additive inverse of the result of scaling the element by the original scalar.*)\nLemma scaleNr a v : - a *: v = - (a *: v).\n\n(*This lemma states that scaling a vector by the additive inverse of one results in the additive inverse of the vector.*)\nLemma scaleN1r v : - 1 *: v = - v.\n\n(*This lemma states that scaling the additive inverse of a vector by a scalar is equivalent to taking the additive inverse of the scaled vector.*)\nLemma scalerN a v : a *: - v = - (a *: v).\n\n(*This lemma states that scalar multiplication on a vector distributes over the subtraction of scalars.*)\nLemma scalerBl a b v : (a - b) *: v = a *: v - b *: v.\n\n(*This lemma states that a scalar multiplied by the difference of two vectors is equal to the difference of the scalar multiplied by each vector.*)\nLemma scalerBr a u v : a *: (u - v) = a *: u - a *: v.\n\n(*This lemma states that scaling a vector by negative one raised to a boolean power results in the additive inverse of the vector if the boolean is true, and the vector itself if the boolean is false.*)\nLemma scaler_sign (b : bool) v : (-1) ^+ b *: v = (if b then - v else v).\n\n(*This lemma states that the function which scales a vector by negative one raised to a natural number power is an involution, meaning that applying the function twice returns the original vector.*)\nLemma signrZK n : @involutive V ( *:%R ((-1) ^+ n)).\n\nSection ClosedPredicates.\n\nVariable S : {pred V}.\n\n(*This definition specifies a property for a predicate on a vector space, called linear closure. A predicate is linearly closed if for any scalar and any two vectors satisfying the predicate, the sum of one vector with the other scaled by the scalar also satisfies the predicate.*)\nDefinition linear_closed := forall a, {in S &, forall u v, a *: u + v \\in S}.\n(*This definition specifies a property for a predicate on a vector space, called submodule closure. A predicate is submodule closed if it contains the zero vector and is linearly closed.*)\nDefinition submod_closed := 0 \\in S /\\ linear_closed.\n\n(*This lemma states that if a predicate on a vector space is linearly closed, it is also closed under subtraction.*)\nLemma linear_closedB : linear_closed -> subr_2closed S.\n\n(*This lemma states that a predicate on a vector space that is submodule closed is also closed under the operations of a Z-module, meaning it contains the zero vector and is closed under addition and additive inverse.*)\nLemma submod_closedB : submod_closed -> zmod_closed S.\n\n(*This lemma states that a predicate on a vector space that is submodule closed is also closed under the operations of a semi-module, meaning it contains the zero vector and is closed under addition.*)\nLemma submod_closed_semi : submod_closed -> subsemimod_closed S.\n\nEnd ClosedPredicates.\n\nEnd LmoduleTheory.\n\n(*A mixin for constructing a left semi-algebra. It adds the requirement that scalar multiplication from the left is compatible with the internal multiplication of the structure, meaning that scaling a product of two elements is equivalent to scaling the first element and then multiplying by the second.*)\nHB.mixin Record LSemiModule_isLSemiAlgebra R V\n of NzSemiRing V & LSemiModule R V := {\n scalerAl : forall (a : R) (u v : V), a *: (u * v) = (a *: u) * v\n}.\n#[short(type=\"lSemiAlgType\")]\n(*This definition introduces the structure of a left semi-algebra over a given semiring. A left semi-algebra is a type that is both a left semi-module and a non-zero semiring, with a compatibility condition between scalar multiplication and the internal multiplication.*)\nHB.structure Definition LSemiAlgebra R :=\n {A of LSemiModule R A & NzSemiRing A & LSemiModule_isLSemiAlgebra R A}.\n\nModule LSemiAlgExports.\nBind Scope ring_scope with LSemiAlgebra.sort.\nEnd LSemiAlgExports.\nHB.export LSemiAlgExports.\n\n(*A notation for embedding a scalar from the base ring into an algebra. It is defined as the scalar multiplication of the given scalar with the multiplicative identity of the algebra.*)\nLocal Notation \"k %:A\" := (k *: 1) : ring_scope.\n\n#[short(type=\"lalgType\")]\n(*This definition introduces the structure of a left algebra over a given ring. A left algebra is a type that is both a left module and a non-zero ring, with a compatibility condition between scalar multiplication and the internal multiplication.*)\nHB.structure Definition Lalgebra R :=\n {A of Lmodule R A & NzRing A & LSemiModule_isLSemiAlgebra R A}.\n\nModule LalgExports.\nBind Scope ring_scope with Lalgebra.sort.\nEnd LalgExports.\nHB.export LalgExports.\n\n(*A factory for constructing a left algebra instance. It takes a type that is already a non-zero ring and a left module, and combines them with a proof of the compatibility axiom between scalar and internal multiplication to form a left algebra.*)\nHB.factory Record Lmodule_isLalgebra R V of NzRing V & Lmodule R V := {\n scalerAl : forall (a : R) (u v : V), a *: (u * v) = (a *: u) * v\n}.\n\nHB.builders Context R V of Lmodule_isLalgebra R V.\n\nHB.instance Definition _ := LSemiModule_isLSemiAlgebra.Build R V scalerAl.\n\nHB.end.\n\n(*This definition provides an alias for a given type, allowing it to be treated as a distinct type. This is used to equip a ring with a canonical module structure over itself.*)\nDefinition regular R : Type := R.\n(*A notation for the `regular` type alias, used to view a ring or semiring as a module over itself.*)\nLocal Notation \"R ^o\" := (regular R) (at level 2, format \"R ^o\") : type_scope.\n\nSection RegularAlgebra.\n#[export]\nHB.instance Definition _ (V : nmodType) := Nmodule.on V^o.\n#[export]\nHB.instance Definition _ (V : zmodType) := Zmodule.on V^o.\n#[export]\nHB.instance Definition _ (R : pzSemiRingType) := PzSemiRing.on R^o.\n#[export]\nHB.instance Definition _ (R : nzSemiRingType) := NzSemiRing.on R^o.\n#[export]\nHB.instance Definition _ (R : pzSemiRingType) :=\n @Nmodule_isLSemiModule.Build R R^o\n mul mulrA mul0r mul1r mulrDr (fun v a b => mulrDl a b v).\n#[export]\nHB.instance Definition _ (R : nzSemiRingType) :=\n LSemiModule_isLSemiAlgebra.Build R R^o mulrA.\n#[export]\nHB.instance Definition _ (R : pzRingType) := PzRing.on R^o.\n#[export]\n(*This lemma states that in a semi-algebra, multiplying an element by the image of a scalar is equivalent to scaling that element by the original scalar.*)\nLemma mulr_algl (a : R) (x : A) : (a *: 1) * x = a *: x.\n\nEnd LSemiAlgebraTheory.\n\nSection LalgebraTheory.\n\nVariables (R : pzRingType) (A : lalgType R).\n\nSection ClosedPredicates.\n\nVariable S : {pred A}.\n\n(*This definition specifies a property for a predicate on an algebra, called subalgebra closure. A predicate is subalgebra closed if it contains the multiplicative identity, is linearly closed, and is closed under the internal multiplication of the algebra.*)\nDefinition subalg_closed := [/\\ 1 \\in S, linear_closed S & mulr_2closed S].\n\n(*This lemma states that a predicate on an algebra that is subalgebra closed is also submodule closed.*)\nLemma subalg_closedZ : subalg_closed -> submod_closed S.\n\n(*This lemma states that a predicate on an algebra that is subalgebra closed is also closed under the operations of a subring, meaning it contains the multiplicative identity and is closed under subtraction and multiplication.*)\nLemma subalg_closedBM : subalg_closed -> subring_closed S.\n\nEnd ClosedPredicates.\n\nEnd LalgebraTheory.\n\nSection LiftedSemiRing.\nVariables (R : pzSemiRingType) (T : Type).\nImplicit Type f : T -> R.\n(*This definition creates a new function by multiplying the output of a given function on the left by a fixed scalar value from a semiring.*)\nDefinition mull_fun a f x := a * f x.\n(*This definition creates a new function by multiplying the output of a given function on the right by a fixed scalar value from a semiring.*)\nDefinition mulr_fun a f x := f x * a.\n(*This definition creates a new function by pointwise multiplication of two given functions. The value of the new function at any point is the product of the values of the original functions at that same point.*)\nDefinition mul_fun f g x := f x * g x.\nEnd LiftedSemiRing.\n\nSection LiftedScale.\nVariables (R : pzSemiRingType) (U : Type).\nVariables (V : lSemiModType R) (A : lSemiAlgType R).\n(*This definition creates a new function by applying scalar multiplication to the output of a given function. The value of the new function at any point is the scaled value of the original function at that point.*)\nDefinition scale_fun a (f : U -> V) x := a *: f x.\n(*This definition provides a function that embeds a scalar from the base ring into an algebra by multiplying the scalar with the algebra's multiplicative identity.*)\nDefinition in_alg k : A := k%:A.\nEnd LiftedScale.\n\n(*A notation for the constant function that maps every input to the zero element of the codomain.*)\nLocal Notation \"\\0\" := (null_fun _) : function_scope.\n(*A notation for the pointwise addition of two functions. The resulting function's value at any point is the sum of the values of the two original functions at that point.*)\nLocal Notation \"f \\+ g\" := (add_fun f g) : function_scope.\n(*A notation for the pointwise subtraction of two functions. The resulting function's value at any point is the difference of the values of the two original functions at that point.*)\nLocal Notation \"f \\- g\" := (sub_fun f g) : function_scope.\n(*A notation for the function that pointwise applies the additive inverse to the result of a given function.*)\nLocal Notation \"\\- f\" := (opp_fun f) : function_scope.\n(*A notation for the function that pointwise applies scalar multiplication by a given scalar to the result of a given function.*)\nLocal Notation \"a \\*: f\" := (scale_fun a f) : function_scope.\n(*A notation for the function that pointwise multiplies the result of a given function on the left by a given ring element.*)\nLocal Notation \"x \\*o f\" := (mull_fun x f) : function_scope.\n(*A notation for the function that pointwise multiplies the result of a given function on the right by a given ring element.*)\nLocal Notation \"x \\o* f\" := (mulr_fun x f) : function_scope.\n(*A notation for the function that pointwise multiplies the results of two given functions.*)\nLocal Notation \"f \\* g\" := (mul_fun f g) : function_scope.\n\nArguments in_alg {_} A _ /.\nArguments mull_fun {_ _} a f _ /.\nArguments mulr_fun {_ _} a f _ /.\nArguments scale_fun {_ _ _} a f _ /.\nArguments mul_fun {_ _} f g _ /.\n\nSection AdditiveTheory.\n\nSection SemiRingProperties.\n\nVariables (R S : pzSemiRingType) (f : {additive R -> S}).\n\n(*This lemma states that applying an additive function between two semirings to a ring element multiplied by a natural number is equivalent to multiplying the result of the function on that element by the same natural number.*)\nLemma raddfMnat n x : f (n%:R * x) = n%:R * f x.\n\nVariables (U : lSemiModType R) (V : lSemiModType S) (h : {additive U -> V}).\n\n(*This lemma states that applying an additive function between two left semimodules to a module element scaled by a natural number is equivalent to scaling the result of the function on that element by the same natural number.*)\nLemma raddfZnat n u : h (n%:R *: u) = n%:R *: h u.\n\nEnd SemiRingProperties.\n\nSection MulFun.\n\nVariables (R : pzSemiRingType) (U : nmodType) (a : R) (f : {additive U -> R}).\n\n(*This fact asserts that the function formed by pointwise left-multiplying the output of an additive function by a fixed ring element is itself an n-module morphism.*)\nFact mull_fun_is_nmod_morphism : nmod_morphism (a \\*o f).\n\n#[export]\nHB.instance Definition _ := isNmodMorphism.Build U R (a \\*o f)\n mull_fun_is_nmod_morphism.\n\n(*This fact asserts that the function formed by pointwise right-multiplying the output of an additive function by a fixed ring element is itself an n-module morphism.*)\nFact mulr_fun_is_nmod_morphism : nmod_morphism (a \\o* f).\n\n#[export]\n(*This lemma states that an additive function between two modules over integers commutes with the additive inverse operation.*)\nLemma raddfN : {morph f : x / - x}. \n(*This lemma states that an additive function between two modules over integers distributes over subtraction.*)\nLemma raddfB : {morph f : x y / x - y}. \n\n(*This lemma states that an additive function between two modules is injective, provided that the only element it maps to the zero element is the zero element itself.*)\nLemma raddf_inj : (forall x, f x = 0 -> x = 0) -> injective f.\n\n(*This lemma states that an additive function between two modules over integers commutes with scalar multiplication by an integer.*)\nLemma raddfMNn n : {morph f : x / x *- n}. \n\nEnd Properties.\n\nSection RingProperties.\n\nVariables (R S : pzRingType) (f : {additive R -> S}).\n\n(*This lemma states that an additive function between two rings commutes with multiplication by the sign determined by a natural number's parity, that is, negative one raised to the power of that number.*)\nLemma raddfMsign n x : f ((-1) ^+ n * x) = (-1) ^+ n * f x.\n\nVariables (U : lmodType R) (V : lmodType S) (h : {additive U -> V}).\n\n(*This lemma states that an additive function between two modules over rings commutes with scalar multiplication by the sign determined by a natural number's parity, that is, negative one raised to the power of that number.*)\nLemma raddfZsign n u : h ((-1) ^+ n *: u) = (-1) ^+ n *: h u.\n\nEnd RingProperties.\n\nSection ScaleFun.\n\nVariables (R : pzSemiRingType) (U : nmodType) (V : lSemiModType R).\nVariables (a : R) (f : {additive U -> V}).\n\n#[export]\nHB.instance Definition _ :=\n isNmodMorphism.Build V V ( *:%R a) (conj (scaler0 _ a) (scalerDr a)).\n#[export]\n(*This definition specifies the property of a function between two semirings being multiplicative, which requires that the function preserves the multiplication operation and maps the multiplicative identity to the multiplicative identity. This definition is deprecated and `monoid_morphism` should be used instead.*)\nDefinition multiplicative (R S : pzSemiRingType) (f : R -> S) : Prop :=\n {morph f : x y / x * y}%R * (f 1 = 1).\n\n(*This definition specifies the property of a function between two semirings being a monoid morphism, which requires that it maps the multiplicative identity to the multiplicative identity and preserves the multiplication operation.*)\nDefinition monoid_morphism (R S : pzSemiRingType) (f : R -> S) : Prop :=\n (f 1 = 1) * {morph f : x y / x * y}%R.\n\n(*This record encapsulates the property of a function between two semirings being a monoid morphism, which requires that it preserves the multiplicative identity and operation.*)\nHB.mixin Record isMonoidMorphism (R S : pzSemiRingType) (f : R -> S) := {\n monoid_morphism_subproof : monoid_morphism f\n}.\n\n(*This definition specifies the structure for a ring morphism between two semirings, which is a function that is both an additive morphism and a multiplicative (monoid) morphism.*)\nHB.structure Definition RMorphism (R S : pzSemiRingType) :=\n {f of @isNmodMorphism R S f & isMonoidMorphism R S f}.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\"]\n(*This record provides a deprecated factory for constructing a ring morphism from an older definition of a multiplicative function, which required preservation of multiplication and the multiplicative identity.*)\nHB.factory Record isMultiplicative (R S : pzSemiRingType) (f : R -> S) := {\n rmorphism_subproof : multiplicative f\n}.\nHB.builders Context R S f of isMultiplicative R S f.\n\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := isMonoidMorphism.Build R S f\n (rmorphism_subproof.2, rmorphism_subproof.1).\n\nHB.end.\n\nModule RMorphismExports.\n(*This notation represents the type of all ring morphisms from a source semiring to a target semiring.*)\nNotation \"{ 'rmorphism' U -> V }\" := (RMorphism.type U%type V%type)\n : type_scope.\nEnd RMorphismExports.\nHB.export RMorphismExports.\n\nSection RmorphismTheory.\n\nSection Properties.\n\nVariables (R S : pzSemiRingType) (f : {rmorphism R -> S}).\n\n(*This lemma states that a ring morphism maps the additive identity of the source ring to the additive identity of the target ring.*)\nLemma rmorph0 : f 0 = 0. \n(*This lemma states that a ring morphism distributes over addition.*)\nLemma rmorphD : {morph f : x y / x + y}. \n(*This lemma states that a ring morphism commutes with multiplication by a natural number, where multiplication is defined as repeated addition.*)\nLemma rmorphMn n : {morph f : x / x *+ n}. \n(*This lemma states that a ring morphism commutes with finite indexed sums; applying the morphism to a sum is equivalent to summing the results of applying the morphism to each term.*)\nLemma rmorph_sum I r (P : pred I) E :\n f (\\sum_(i <- r | P i) E i) = \\sum_(i <- r | P i) f (E i).\n\n(*This lemma states that any ring morphism is also a monoid morphism, meaning it preserves the multiplicative identity and the multiplication operation.*)\nLemma rmorphism_monoidP : monoid_morphism f.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `rmorphism_monoidP` instead\")]\n(*This definition provides a deprecated proof that a ring morphism is a multiplicative function, which means it preserves the multiplication operation and maps the multiplicative identity to the multiplicative identity.*)\nDefinition rmorphismMP : multiplicative f :=\n (fun p => (p.2, p.1)) rmorphism_monoidP.\n\n(*This lemma states that a ring morphism maps the multiplicative identity of the source ring to the multiplicative identity of the target ring.*)\nLemma rmorph1 : f 1 = 1. \n(*This lemma states that a ring morphism distributes over multiplication.*)\nLemma rmorphM : {morph f: x y / x * y}. \n\n(*This lemma states that a ring morphism commutes with finite indexed products; applying the morphism to a product is equivalent to taking the product of the results of applying the morphism to each factor.*)\nLemma rmorph_prod I r (P : pred I) E :\n f (\\prod_(i <- r | P i) E i) = \\prod_(i <- r | P i) f (E i).\n\n(*This lemma states that a ring morphism preserves exponentiation by a natural number. Applying the morphism to a ring element raised to a natural number power is equivalent to applying the morphism to the element first and then raising the result to the same power.*)\nLemma rmorphXn n : {morph f : x / x ^+ n}.\n\n(*This lemma states that a ring morphism maps the canonical embedding of a natural number in the source ring to the canonical embedding of the same natural number in the target ring.*)\nLemma rmorph_nat n : f n%:R = n%:R. \n\n(*This lemma states that for an injective ring morphism, the equality between the image of a ring element and the canonical embedding of a natural number holds if and only if the original ring element is equal to the canonical embedding of that same natural number.*)\nLemma rmorph_eq_nat x n : injective f -> (f x == n%:R) = (x == n%:R).\n\n(*This lemma states that for an injective ring morphism, the equality between the image of a ring element and the multiplicative identity one holds if and only if the original ring element is equal to one.*)\nLemma rmorph_eq1 x : injective f -> (f x == 1) = (x == 1).\n\n(*This lemma states that if a function can be canceled on both the left and right by another function under composition, then that function is a monoid morphism, meaning it preserves the monoid's binary operation and identity element.*)\nLemma can2_monoid_morphism f' : cancel f f' -> cancel f' f -> monoid_morphism f'.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `can2_monoid_morphism` instead\")]\n(*This definition, now deprecated, provides a way to construct a proof that a function is a ring morphism from a proof that it is a monoid morphism, given certain cancellation properties.*)\nDefinition can2_rmorphism f' (cff' : cancel f f') :=\n (fun p => (p.2, p.1)) \\o (can2_monoid_morphism cff').\n\nEnd Properties.\n\n(*This lemma states that a ring morphism between two non-zero semirings preserves the property of being a prime characteristic. If a prime number is a characteristic of the source semiring, it is also a characteristic of the target semiring.*)\nLemma rmorph_pchar (R S : nzSemiRingType) (f : {rmorphism R -> S}) p :\n p \\in pchar R -> p \\in pchar S.\n\nSection Projections.\n\nVariables (R S T : pzSemiRingType).\nVariables (f : {rmorphism S -> T}) (g : {rmorphism R -> S}).\n\n(*This fact asserts that the identity function on any given ring structure is a monoid morphism, meaning it preserves the multiplicative operation and the multiplicative identity.*)\nFact idfun_is_monoid_morphism : monoid_morphism (@idfun R).\n\n#[export]\nHB.instance Definition _ := isMonoidMorphism.Build R R idfun\n idfun_is_monoid_morphism.\n\n(*This fact asserts that the composition of two ring morphisms results in a function that is a monoid morphism, preserving the multiplicative structure.*)\nFact comp_is_monoid_morphism : monoid_morphism (f \\o g).\n\n#[export]\n(*This lemma states that a ring morphism commutes with the additive negation operation. The image of the negation of an element is the negation of the image of that element.*)\nLemma rmorphN : {morph f : x / - x}. \n(*This lemma states that a ring morphism preserves the subtraction operation. The image of the difference of two elements is the difference of their images.*)\nLemma rmorphB : {morph f: x y / x - y}. \n(*This lemma states that a ring morphism commutes with multiplication by the additive inverse of an embedded natural number. The image of a product of a ring element and the negation of an embedded natural number is the product of the image of the element and the negation of that same embedded natural number.*)\nLemma rmorphMNn n : {morph f : x / x *- n}. \n(*This lemma states that a ring morphism commutes with multiplication by a sign factor. The image of an element multiplied by negative one raised to a natural number power is the product of the image of the element and negative one raised to that same power in the target ring.*)\nLemma rmorphMsign n : {morph f : x / (- 1) ^+ n * x}.\n\n(*This lemma states that a ring morphism maps the additive inverse of the multiplicative identity in the source ring to the additive inverse of the multiplicative identity in the target ring.*)\nLemma rmorphN1 : f (- 1) = (- 1). \n\n(*This lemma states that a ring morphism preserves sign factors, meaning the image of negative one raised to a natural number power is equal to negative one raised to that same power in the target ring.*)\nLemma rmorph_sign n : f ((- 1) ^+ n) = (- 1) ^+ n.\n\nEnd Properties.\n\nSection InSemiAlgebra.\n\nVariables (R : pzSemiRingType) (A : lSemiAlgType R).\n\n(*This fact asserts that the canonical injection from a base semiring into a semi-algebra over that semiring is a module morphism.*)\nFact in_alg_is_nmod_morphism : nmod_morphism (in_alg A).\n\n#[export]\nHB.instance Definition _ :=\n isNmodMorphism.Build R A (in_alg A) in_alg_is_nmod_morphism.\n\n(*This fact asserts that the canonical injection from a base semiring into a semi-algebra over that semiring is a monoid morphism, preserving the multiplicative structure.*)\nFact in_alg_is_monoid_morphism : monoid_morphism (in_alg A).\n\n#[export]\n(*This lemma states that applying the canonical algebra injection to an element from the base semiring yields the same result as the canonical embedding of that element into the algebra's ring structure.*)\nLemma in_algE a : in_alg A a = a%:A. \n\nEnd InSemiAlgebra.\n\nEnd RmorphismTheory.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use rmorph_pchar instead.\")]\n(*A deprecated notation that serves as a parsing-only alias for `rmorph_pchar`, which relates to the preservation of prime characteristics under ring morphisms.*)\nNotation rmorph_char := rmorph_pchar (only parsing).\n\nModule Scale.\n\n(*This record defines the property of being a pre-law, which characterizes an operation combining a semiring element and a module element. It requires that for any fixed element from the semiring, the operation defines a module morphism on the module.*)\nHB.mixin Record isPreLaw\n (R : pzSemiRingType) (V : nmodType) (op : R -> V -> V) := {\n op_nmod_morphism : forall a, nmod_morphism (op a);\n}.\n\n#[export]\n(*This definition introduces the `PreLaw` structure, which bundles an operation with a proof that it satisfies the `isPreLaw` property, formally packaging a map that acts as a precursor to a scalar multiplication law.*)\nHB.structure Definition PreLaw R V := {op of isPreLaw R V op}.\n(*This definition provides a convenient alias for the type of `PreLaw` structures.*)\nDefinition preLaw := PreLaw.type.\n\n(*This record defines the properties of a semi-law, which are the axioms for a scalar multiplication in a semi-module over a semiring. These axioms include compatibility with the zero element, the one element, and the associative property of scalar multiplication with respect to the semiring's multiplication.*)\nHB.mixin Record isSemiLaw\n (R : pzSemiRingType) (V : nmodType) (op : R -> V -> V) := {\n op0v : forall v, op 0 v = 0;\n op1v : op 1 =1 id;\n opA : forall a b v, op a (op b v) = op (a * b) v;\n}.\n\n#[export]\n(*This definition introduces the `SemiLaw` structure, which combines the `isPreLaw` and `isSemiLaw` mixins to represent a fully-axiomatized scalar multiplication operation for a semi-module over a semiring.*)\nHB.structure Definition SemiLaw R V :=\n {op of isPreLaw R V op & isSemiLaw R V op}.\n(*This definition provides a convenient alias for the type of `SemiLaw` structures.*)\nDefinition semiLaw := SemiLaw.type.\n\n(*This record defines the property of a law for scalar multiplication over a ring and a module, adding the axiom that scaling a module element by the additive inverse of one in the ring is equivalent to taking the additive inverse of the module element.*)\nHB.mixin Record isLaw (R : pzRingType) (V : zmodType) (op : R -> V -> V) :=\n { N1op : op (-1) =1 -%R }.\n\n#[export]\n(*This definition introduces the `Law` structure for an operation on a module over a ring, which combines the `isPreLaw` properties with the specific `isLaw` axiom concerning scalar multiplication by negative one.*)\nHB.structure Definition Law (R : pzRingType) (V : zmodType) :=\n {op of isPreLaw R V op & isLaw R V op}.\n(*This definition provides a convenient alias for the type of `Law` structures.*)\nDefinition law := Law.type.\n\nSection CompSemiLaw.\n\nContext (R : pzSemiRingType) (V : nmodType) (s : semiLaw R V).\nContext (aR : pzSemiRingType) (nu : {rmorphism aR -> R}).\n\n(*This fact states that for a scalar multiplication law derived by composing a ring morphism with an existing semi-law, scaling any module element by the zero of the new base semiring results in the zero element of the module.*)\nFact comp_op0v v : (nu \\; s) 0 v = 0.\n\n(*This fact states that for a scalar multiplication law derived by composing a ring morphism with an existing semi-law, scaling by the multiplicative identity of the new base semiring acts as the identity function on the module.*)\nFact comp_op1v : (nu \\; s) 1 =1 id.\n\n(*This lemma states that composing a scalar multiplication law with a ring morphism preserves the multiplicative structure. Applying the composed law with a first ring element and then a second ring element to a module element is equivalent to applying the composed law once with the product of the two ring elements.*)\nFact comp_opA a b v : (nu \\; s) a ((nu \\; s) b v) = (nu \\; s) (a * b) v.\n\nEnd CompSemiLaw.\n\n(*This lemma states that for a scalar multiplication law composed with a ring morphism, scaling a module element by the additive inverse of one from the source ring is equivalent to taking the additive inverse of that module element.*)\nFact compN1op\n (R : pzRingType) (V : zmodType) (s : law R V)\n (aR : pzRingType) (nu : {rmorphism aR -> R}) : (nu \\; s) (-1) =1 -%R.\n\nModule Exports. HB.reexport. End Exports.\n\nEnd Scale.\nExport Scale.Exports.\n\n#[export]\nHB.instance Definition _ (R : pzSemiRingType) :=\n Scale.isPreLaw.Build R R *%R (fun => mull_fun_is_nmod_morphism _ idfun).\n\n#[export]\nHB.instance Definition _ (R : pzSemiRingType) :=\n Scale.isSemiLaw.Build R R *%R mul0r mul1r mulrA.\n\n#[export]\nHB.instance Definition _ (R : pzRingType) :=\n Scale.isLaw.Build R R *%R (@mulN1r R).\n\n#[export]\nHB.instance Definition _ (R : pzSemiRingType) (V : lSemiModType R) :=\n Scale.isPreLaw.Build R V *:%R (fun => (scaler0 _ _, scalerDr _)).\n\n#[export]\nHB.instance Definition _ (R : pzSemiRingType) (V : lSemiModType R) :=\n Scale.isSemiLaw.Build R V *:%R scale0r scale1r (@scalerA _ _).\n\n#[export]\nHB.instance Definition _ (R : pzRingType) (U : lmodType R) :=\n Scale.isLaw.Build R U *:%R (@scaleN1r R U).\n\n#[export]\nHB.instance Definition _\n (R : pzSemiRingType) (V : nmodType) (s : Scale.preLaw R V)\n (aR : pzSemiRingType) (nu : {rmorphism aR -> R}) :=\n Scale.isPreLaw.Build aR V (nu \\; s) (fun => Scale.op_nmod_morphism _).\n\n#[export]\nHB.instance Definition _\n (R : pzSemiRingType) (V : nmodType) (s : Scale.semiLaw R V)\n (aR : pzSemiRingType) (nu : {rmorphism aR -> R}) :=\n Scale.isSemiLaw.Build aR V (nu \\; s)\n (Scale.comp_op0v s nu) (Scale.comp_op1v s nu) (Scale.comp_opA s nu).\n\n#[export]\nHB.instance Definition _\n (R : pzRingType) (V : zmodType) (s : Scale.law R V)\n (aR : pzRingType) (nu : {rmorphism aR -> R}) :=\n Scale.isLaw.Build aR V (nu \\; s) (Scale.compN1op s nu).\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _\n (R : pzSemiRingType) (V : nmodType) (s : Scale.preLaw R V) a :=\n isNmodMorphism.Build V V (s a) (Scale.op_nmod_morphism a).\n\n(*This definition specifies the property of a function between two semimodules being compatible with scalar multiplication. It requires that for every scalar, applying the function to a vector scaled by that scalar yields the same result as scaling the function's output by the same scalar, potentially using a different scalar action on the target module.*)\nDefinition scalable_for (R : pzSemiRingType) (U : lSemiModType R) (V : nmodType)\n (s : R -> V -> V) (f : U -> V) :=\n forall a, {morph f : u / a *: u >-> s a u}.\n\n(*This record defines the structure for a function that is scalable, meaning it preserves the scalar multiplication action between two semimodules. It contains a proof that the function satisfies the property of being scalable.*)\nHB.mixin Record isScalable (R : pzSemiRingType) (U : lSemiModType R)\n (V : nmodType) (s : R -> V -> V) (f : U -> V) := {\n semi_linear_subproof : scalable_for s f;\n}.\n\n(*This structure defines a linear map between two semimodules over a semiring. A function qualifies as a linear map if it preserves addition and is compatible with the scalar multiplication of the respective modules.*)\nHB.structure Definition Linear (R : pzSemiRingType)\n (U : lSemiModType R) (V : nmodType) (s : R -> V -> V) :=\n {f of @isNmodMorphism U V f & isScalable R U V s f}.\n\n(*This definition specifies the property of a function between two semimodules being semilinear. It requires that the function is both compatible with scalar multiplication and preserves the addition operation.*)\nDefinition semilinear_for (R : pzSemiRingType)\n (U : lSemiModType R) (V : nmodType) (s : R -> V -> V) (f : U -> V) : Type :=\n scalable_for s f * {morph f : x y / x + y}.\n\n(*This lemma states that a function between two semimodules that is semilinear is also a semimodule morphism, meaning it preserves both addition and the zero element.*)\nLemma nmod_morphism_semilinear (R : pzSemiRingType)\n (U : lSemiModType R) (V : nmodType) (s : Scale.semiLaw R V) (f : U -> V) :\n semilinear_for s f -> nmod_morphism f.\n\n(*This definition provides an alias for the lemma `nmod_morphism_semilinear`, which establishes that a semilinear function between semimodules is a semimodule morphism.*)\nDefinition additive_semilinear := nmod_morphism_semilinear.\n\n(*This lemma states that a function between two semimodules that is semilinear is, by definition, also scalable, meaning it is compatible with scalar multiplication.*)\nLemma scalable_semilinear (R : pzSemiRingType)\n (U : lSemiModType R) (V : nmodType) (s : Scale.preLaw R V) (f : U -> V) :\n semilinear_for s f -> scalable_for s f.\n\n(*This record provides a factory for constructing an instance of a semilinear function between two semimodules, taking as evidence a proof that the function is indeed semilinear.*)\nHB.factory Record isSemilinear (R : pzSemiRingType) (U : lSemiModType R)\n (V : nmodType) (s : Scale.semiLaw R V) (f : U -> V) := {\n linear_subproof : semilinear_for s f;\n}.\nHB.builders Context R U V s f of isSemilinear R U V s f.\nHB.instance Definition _ := isNmodMorphism.Build U V f\n (additive_semilinear linear_subproof).\n\nHB.instance Definition _ :=\n isScalable.Build R U V s f (scalable_semilinear linear_subproof).\nHB.end.\n\n(*This definition specifies a combined property for a function to be linear between modules. It requires that for every scalar, the function applied to a sum of a scaled vector and another vector is equal to the sum of the scaled function output and the function output of the second vector.*)\nDefinition linear_for (R : pzSemiRingType) (U : lSemiModType R) (V : nmodType)\n (s : R -> V -> V) (f : U -> V) :=\n forall a, {morph f : u v / a *: u + v >-> s a u + v}.\n\n(*This lemma states that a function between two modules over a ring that satisfies the bundled linearity condition is a module morphism, meaning it preserves addition, opposites, and the zero element.*)\nLemma zmod_morphism_linear (R : pzRingType) (U : lmodType R) V\n (s : Scale.law R V) (f : U -> V) : linear_for s f -> zmod_morphism f.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `zmod_morphism_linear` instead\")]\n(*This definition provides a deprecated alias for the lemma `zmod_morphism_linear`, which establishes that a function satisfying the bundled linearity condition is a module morphism.*)\nDefinition additive_linear := zmod_morphism_linear.\n\n(*This lemma states that a function between two modules over a ring that satisfies the bundled linearity condition is also scalable, meaning it is compatible with scalar multiplication.*)\nLemma scalable_linear (R : pzRingType) (U : lmodType R) V\n (s : Scale.law R V) (f : U -> V) : linear_for s f -> scalable_for s f.\n\n(*This lemma states that a function between two modules over a ring that satisfies the bundled linearity condition is also semilinear, which means it preserves addition and is compatible with scalar multiplication.*)\nLemma semilinear_linear (R : pzRingType) (U : lmodType R) V\n (s : Scale.law R V) (f : U -> V) : linear_for s f -> semilinear_for s f.\n\n(*This record provides a factory for constructing an instance of a linear function between two modules over a ring, taking as evidence a proof that the function satisfies the bundled linearity condition.*)\nHB.factory Record isLinear (R : pzRingType) (U : lmodType R) (V : zmodType)\n (s : Scale.law R V) (f : U -> V) := {\n linear_subproof : linear_for s f;\n}.\nHB.builders Context R U V s f of isLinear R U V s f.\nHB.instance Definition _ := isZmodMorphism.Build U V f\n (zmod_morphism_linear linear_subproof).\nHB.instance Definition _ := isScalable.Build R U V s f\n (scalable_linear linear_subproof).\nHB.end.\n\nModule LinearExports.\nNotation scalable f := (scalable_for *:%R f).\nNotation semilinear f := (semilinear_for *:%R f).\nNotation semiscalar f := (semilinear_for *%R f).\nNotation linear f := (linear_for *:%R f).\nNotation scalar f := (linear_for *%R f).\nModule Linear.\nSection Linear.\nVariables (R : pzSemiRingType) (U : lSemiModType R) (V : nmodType).\nVariables (s : R -> V -> V).\n\n(*This definition provides a local shorthand for the type of linear maps between two specific semimodules, parameterized by the scalar action on the target semimodule.*)\nLocal Notation mapUV := (@Linear.type R U V s).\n(*This definition provides an alias for the type of linear maps between two semimodules within a specific scope.*)\nDefinition map_class := mapUV.\n(*This definition creates a type alias for the type of linear maps, indexed by a ring element, although the underlying type itself does not depend on the element. This is used for type-level organization.*)\nDefinition map_at (a : R) := mapUV.\n(*This structure bundles a linear map with a proof that its associated scalar action at a specific ring element matches a given action. It represents a linear map together with evidence about its behavior for a particular scalar.*)\nStructure map_for a s_a := MapFor {map_for_map : mapUV; _ : s a = s_a}.\n(*This definition provides a canonical way to convert a linear map, which is indexed by a ring element for type-level purposes, into a structure that explicitly pairs the map with a proof of the identity of its scalar action at that element.*)\nDefinition unify_map_at a (g : map_at a) := MapFor g (erefl (s a)).\n(*This structure defines a simple wrapper for a linear map, allowing it to be treated as a distinct type.*)\nStructure wrapped := Wrap {unwrap : mapUV}.\n(*This definition serves as the constructor for the wrapped linear map structure, taking a linear map and enclosing it in the wrapper.*)\nDefinition wrap (f : map_class) := Wrap f.\nEnd Linear.\nEnd Linear.\n(*This notation defines the type of linear maps from a source module to a target module, explicitly specifying the scalar multiplication action used on the target module.*)\nNotation \"{ 'linear' U -> V | s }\" := (@Linear.type _ U V s) : type_scope.\n(*This notation defines the type of linear maps from a source module to a target module, using the default scalar multiplication action for the target module.*)\nNotation \"{ 'linear' U -> V }\" := {linear U -> V | *:%R} : type_scope.\n(*This notation defines the type of linear functionals, which are linear maps from a source module to its underlying base ring, using the ring's own multiplication as the scalar action.*)\nNotation \"{ 'scalar' U }\" := {linear U -> _ | *%R}\n (format \"{ 'scalar' U }\") : type_scope.\n\nCoercion Linear.map_for_map : Linear.map_for >-> Linear.type.\nCoercion Linear.unify_map_at : Linear.map_at >-> Linear.map_for.\nCanonical Linear.unify_map_at.\nCoercion Linear.unwrap : Linear.wrapped >-> Linear.type.\nCoercion Linear.wrap : Linear.map_class >-> Linear.wrapped.\nCanonical Linear.wrap.\nEnd LinearExports.\nHB.export LinearExports.\n\nSection LinearTheory.\n\nSection GenericProperties.\n\nVariables (R : pzSemiRingType) (U : lSemiModType R) (V : nmodType).\nVariables (s : R -> V -> V) (f : {linear U -> V | s}).\n\n(*This lemma states that any linear map sends the zero element of its domain to the zero element of its codomain.*)\nLemma linear0 : f 0 = 0. \n(*This lemma states that a linear map preserves addition, meaning the map of a sum of two elements is the sum of their individual maps.*)\nLemma linearD : {morph f : x y / x + y}. \n(*This lemma states that a linear map is compatible with scaling by a natural number, meaning that applying the map to an element scaled by a natural number is equivalent to scaling the mapped element by the same natural number.*)\nLemma linearMn n : {morph f : x / x *+ n}. \n(*This lemma states that a linear map commutes with finite sums. Applying a linear map to a sum of elements over a specified range is equivalent to taking the sum of the linear map applied to each individual element.*)\nLemma linear_sum I r (P : pred I) E :\n f (\\sum_(i <- r | P i) E i) = \\sum_(i <- r | P i) f (E i).\n\n(*This lemma states that a function that is linear with respect to a given scalar action is also scalable for that same scalar action.*)\nLemma linearZ_LR : scalable_for s f. \n(*This lemma states that a function that is linear with respect to a given scalar action is also semilinear for that action, meaning it is both additive and scalable.*)\nLemma semilinearP : semilinear_for s f.\n\n(*This lemma states that a function defined as being linear with respect to a given scalar action satisfies the property of being linear for that same scalar action.*)\nLemma linearP : linear_for s f.\n\nEnd GenericProperties.\n\nSection GenericProperties.\n\nVariables (R : pzRingType) (U : lmodType R) (V : zmodType) (s : R -> V -> V).\nVariables (f : {linear U -> V | s}).\n\n(*This lemma states that a linear map from a left module over a ring to an additive group preserves the additive inverse operation.*)\nLemma linearN : {morph f : x / - x}. \n(*This lemma states that a linear map from a left module over a ring to an additive group preserves the subtraction operation.*)\nLemma linearB : {morph f : x y / x - y}. \n(*This lemma states that for any natural number, a linear map from a left module over a ring to an additive group commutes with the operation of repeated addition, meaning applying the map to a sum of an element with itself a number of times is equivalent to summing the image of the element with itself the same number of times.*)\nLemma linearMNn n : {morph f : x / x *- n}. \n\nEnd GenericProperties.\n\nSection BidirectionalLinearZ.\n\n(*This lemma states that for a function which is semilinear with respect to a scalar action, but behaves differently for a specific scalar, applying this function to an input scaled by that specific scalar is equivalent to applying the function to the input and then applying the special scalar action.*)\nLemma linearZ (R : pzSemiRingType) (U : lSemiModType R) (V : nmodType)\n (s : R -> V -> V) (S : pzSemiRingType) (h : Scale.preLaw S V)\n (c : S) (a : R) (h_c := h c) (f : Linear.map_for U s a h_c) (u : U) :\n f (a *: u) = h_c (Linear.wrap f u).\n\nEnd BidirectionalLinearZ.\n\nSection LmodProperties.\n\nVariables (R : pzSemiRingType) (U V : lSemiModType R) (f : {linear U -> V}).\n\n(*This lemma states that a linear map between two left modules over the same semiring is scalable with respect to the scalar multiplication of the target module.*)\nLemma linearZZ : scalable f. \n(*This lemma states that a linear map between two left modules over the same semiring is semilinear, meaning it is both additive and scalable.*)\nLemma semilinearPZ : semilinear f. \n(*This lemma states that a function defined as a linear map between two left modules over the same semiring satisfies the property of being linear.*)\nLemma linearPZ : linear f. \n\n(*This lemma states that if a linear map between two left semimodules has a two-sided inverse, then that inverse function is also scalable.*)\nLemma can2_scalable f' : cancel f f' -> cancel f' f -> scalable f'.\n\n(*This lemma states that if a linear map between two left semimodules has a two-sided inverse, then that inverse function is also semilinear.*)\nLemma can2_semilinear f' : cancel f f' -> cancel f' f -> semilinear f'.\n\n(*This lemma states that if a linear map between two left semimodules has a two-sided inverse, then that inverse function is also linear.*)\nLemma can2_linear f' : cancel f f' -> cancel f' f -> linear f'.\n\nEnd LmodProperties.\n\nSection ScalarProperties.\n\nVariable (R : pzSemiRingType) (U : lSemiModType R) (f : {scalar U}).\n\n(*This lemma states that a scalar-linear endomorphism on a left semimodule is scalable with respect to the module's own scalar multiplication.*)\nLemma scalarZ : scalable_for *%R f. \n(*This lemma states that a scalar-linear endomorphism on a left semimodule is also semiscalar, meaning it is both an additive endomorphism and a scalable map.*)\nLemma semiscalarP : semiscalar f. \n(*This lemma states that a function defined as a scalar-linear endomorphism on a left semimodule satisfies the property of being scalar-linear.*)\nLemma scalarP : scalar f. \n\nEnd ScalarProperties.\n\nSection LinearLSemiMod.\n\nSection Idfun.\n\nVariables (R : pzSemiRingType) (U : lSemiModType R).\n\n(*This lemma states that the identity function on a left semimodule is scalable with respect to the module's scalar multiplication.*)\nLemma idfun_is_scalable : scalable (@idfun U). \n#[export]\n(*This lemma states that the composition of a linear map from a semimodule to another semimodule, followed by a linear map from that semimodule to an additive monoid with a scalar action, results in a function that is scalable with respect to that scalar action.*)\nLemma comp_is_scalable : scalable_for s (f \\o g).\n\n#[export]\n(*This lemma states that the null function, which maps every element of a left semimodule to the zero element of an additive monoid, is scalable with respect to any valid scalar action on the monoid.*)\nLemma null_fun_is_scalable : scalable_for s (\\0 : U -> V).\n\n#[export]\nHB.instance Definition _ :=\n isScalable.Build R U V s \\0 null_fun_is_scalable.\n\n(*This lemma states that the pointwise sum of two linear functions, which map a left semimodule to an additive monoid and are both scalable for the same scalar action, is also scalable for that action.*)\nLemma add_fun_is_scalable : scalable_for s (add_fun f g).\n\n#[export]\n(*This lemma states that the additive inverse function on a left module over a ring is scalable with respect to the module's own scalar multiplication.*)\nLemma opp_is_scalable : scalable (-%R : U -> U).\n\n#[export]\n(*This lemma states that the pointwise difference of two linear functions, which map a left module to an additive group and are both scalable for the same scalar action, is also scalable for that action.*)\nLemma sub_fun_is_scalable : scalable_for s (f \\- g).\n\n#[export]\nHB.instance Definition _ :=\n isScalable.Build R U V s (f \\- g) sub_fun_is_scalable.\n\n(*This lemma states that the pointwise additive inverse of a linear function, which maps a left module to an additive group and is scalable for a given scalar action, is also scalable for that action.*)\nLemma opp_fun_is_scalable : scalable_for s (\\- f).\n\n#[export]\n(*This lemma states that composing a linear map from a semimodule to a semi-algebra with right multiplication by a fixed algebra element results in a scalable function.*)\nFact mulr_fun_is_scalable : scalable (a \\o* f).\n\n#[export]\n(*This structure defines a morphism between a left semi-algebra and a semiring as a function that is both a ring morphism and a scalable map with respect to an external scalar action.*)\nHB.structure Definition LRMorphism (R : pzSemiRingType) (A : lSemiAlgType R)\n (B : pzSemiRingType) (s : R -> B -> B) :=\n {f of @RMorphism A B f & isScalable R A B s f}.\n\nModule LRMorphismExports.\n(*This notation denotes the type of linear ring morphisms from a source semi-algebra to a target semiring, where linearity is defined with respect to a specified scalar action.*)\nNotation \"{ 'lrmorphism' A -> B | s }\" := (@LRMorphism.type _ A%type B%type s)\n : type_scope.\n(*This notation denotes the type of linear ring morphisms from a source semi-algebra to a target semi-algebra, where linearity is with respect to the canonical scalar multiplication of the target algebra.*)\nNotation \"{ 'lrmorphism' A -> B }\" := {lrmorphism A%type -> B%type | *:%R}\n : type_scope.\nEnd LRMorphismExports.\nHB.export LRMorphismExports.\n\nSection LRMorphismTheory.\n\nVariables (R : pzSemiRingType) (A B : lSemiAlgType R) (C : pzSemiRingType).\nVariables (s : R -> C -> C).\nVariables (f : {lrmorphism A -> B}) (g : {lrmorphism B -> C | s}).\n\n#[export] HB.instance Definition _ := RMorphism.on (@idfun A).\n(*This lemma states that a linear ring morphism between two left semi-algebras over the same semiring preserves the canonical embedding of elements from the base semiring into the algebras.*)\nLemma rmorph_alg a : f a%:A = a%:A.\n\nEnd LRMorphismTheory.\n\n(*This record structure is a mixin that endows a semiring with a prime subring of naturals with the property that its multiplication operation is commutative.*)\nHB.mixin Record PzSemiRing_hasCommutativeMul R of PzSemiRing R := {\n mulrC : commutative (@mul R)\n}.\n\nModule SemiRing_hasCommutativeMul.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use PzSemiRing_hasCommutativeMul.Build instead.\")]\nNotation Build R := (PzSemiRing_hasCommutativeMul.Build R) (only parsing).\nEnd SemiRing_hasCommutativeMul.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use PzSemiRing_hasCommutativeMul instead.\")]\nNotation SemiRing_hasCommutativeMul R :=\n (PzSemiRing_hasCommutativeMul R) (only parsing).\n\n#[short(type=\"comPzSemiRingType\")]\n(*This structure defines a commutative semiring with a prime subring of naturals, which is a semiring that also possesses a commutative multiplication operation.*)\nHB.structure Definition ComPzSemiRing :=\n {R of PzSemiRing R & PzSemiRing_hasCommutativeMul R}.\n\nModule ComPzSemiRingExports.\nBind Scope ring_scope with ComPzSemiRing.sort.\nEnd ComPzSemiRingExports.\nHB.export ComPzSemiRingExports.\n\n(*This factory builds a commutative P-zero semiring structure on a given N-module by providing a multiplicative identity, a commutative and associative multiplication that distributes over addition, and has the additive zero as a multiplicative annihilator.*)\nHB.factory Record Nmodule_isComPzSemiRing R of Nmodule R := {\n one : R;\n mul : R -> R -> R;\n mulrA : associative mul;\n mulrC : commutative mul;\n mul1r : left_id one mul;\n mulrDl : left_distributive mul add;\n mul0r : left_zero zero mul;\n}.\n\nHB.builders Context R of Nmodule_isComPzSemiRing R.\n Definition mulr1 := Monoid.mulC_id mulrC mul1r.\n Definition mulrDr := Monoid.mulC_dist mulrC mulrDl.\n Lemma mulr0 : right_zero zero mul.\n \n HB.instance Definition _ := Nmodule_isPzSemiRing.Build R\n mulrA mul1r mulr1 mulrDl mulrDr mul0r mulr0.\n HB.instance Definition _ := PzSemiRing_hasCommutativeMul.Build R mulrC.\nHB.end.\n\n#[short(type=\"comNzSemiRingType\")]\n(*This structure defines a commutative non-zero semiring, which is a semiring where multiplication is commutative and the multiplicative identity is distinct from the additive identity.*)\nHB.structure Definition ComNzSemiRing :=\n {R of NzSemiRing R & PzSemiRing_hasCommutativeMul R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzSemiRing instead.\")]\nNotation ComSemiRing R := (ComNzSemiRing R) (only parsing).\n\nModule ComSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzSemiRing.sort instead.\")]\n(*A deprecated notation for the underlying type of a commutative non-zero semiring.*)\nNotation sort := (ComNzSemiRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzSemiRing.on instead.\")]\nNotation on R := (ComNzSemiRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzSemiRing.copy instead.\")]\nNotation copy T U := (ComNzSemiRing.copy T U) (only parsing).\nEnd ComSemiRing.\n\nModule ComNzSemiRingExports.\nBind Scope ring_scope with ComNzSemiRing.sort.\nEnd ComNzSemiRingExports.\nHB.export ComNzSemiRingExports.\n\n(*This factory builds a commutative non-zero semiring structure on a given N-module by providing a multiplicative identity distinct from the additive identity, a commutative and associative multiplication that distributes over addition, and has the additive zero as a multiplicative annihilator.*)\nHB.factory Record Nmodule_isComNzSemiRing R of Nmodule R := {\n one : R;\n mul : R -> R -> R;\n mulrA : associative mul;\n mulrC : commutative mul;\n mul1r : left_id one mul;\n mulrDl : left_distributive mul add;\n mul0r : left_zero zero mul;\n oner_neq0 : one != zero\n}.\n\nModule Nmodule_isComSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Nmodule_isComNzSemiRing.Build instead.\")]\nNotation Build R := (Nmodule_isComNzSemiRing.Build R) (only parsing).\nEnd Nmodule_isComSemiRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Nmodule_isComNzSemiRing instead.\")]\nNotation Nmodule_isComSemiRing R := (Nmodule_isComNzSemiRing R) (only parsing).\n\nHB.builders Context R of Nmodule_isComNzSemiRing R.\n Definition mulr1 := Monoid.mulC_id mulrC mul1r.\n Definition mulrDr := Monoid.mulC_dist mulrC mulrDl.\n Lemma mulr0 : right_zero zero mul.\n \n HB.instance Definition _ := Nmodule_isNzSemiRing.Build R\n mulrA mul1r mulr1 mulrDl mulrDr mul0r mulr0 oner_neq0.\n HB.instance Definition _ := PzSemiRing_hasCommutativeMul.Build R mulrC.\nHB.end.\n\nSection ComSemiRingTheory.\n\nVariable R : comPzSemiRingType.\nImplicit Types x y : R.\n\n#[export]\n(*This lemma states that multiplication in a commutative P-zero semiring is left-commutative, meaning that for any three elements, the product of the first two multiplied by the third is equal to the product of the second and first multiplied by the third.*)\nLemma mulrCA : @left_commutative R R *%R. \n(*This lemma states that multiplication in a commutative P-zero semiring is right-commutative, meaning that for any three elements, the first element multiplied by the product of the second and third is equal to the first element multiplied by the product of the third and second.*)\nLemma mulrAC : @right_commutative R R *%R. \n(*This lemma states that multiplication in a commutative P-zero semiring has the interchange property, meaning that the product of two products can be reordered by taking the products of the outer and inner pairs of elements.*)\nLemma mulrACA : @interchange R *%R *%R. \n\n(*This lemma states that for a fixed natural number exponent, the exponentiation operation is a multiplicative morphism. Specifically, raising the product of two elements to that exponent is equivalent to taking the product of each element raised to that same exponent.*)\nLemma exprMn n : {morph (fun x => x ^+ n) : x y / x * y}.\n\n(*This lemma states that for a given exponent, the finite product of elements each raised to that exponent is equal to the finite product of the elements, with the entire result then raised to that exponent.*)\nLemma prodrXl n I r (P : pred I) (F : I -> R) :\n \\prod_(i <- r | P i) F i ^+ n = (\\prod_(i <- r | P i) F i) ^+ n.\n\n(*This lemma states that the finite product of a sequence of elements satisfying a predicate can be computed by first finding the unique elements in the sequence that satisfy the predicate, then taking the product of these unique elements, where each is raised to the power of its frequency in the original sequence.*)\nLemma prodr_undup_exp_count (I : eqType) r (P : pred I) (F : I -> R) :\n \\prod_(i <- undup r | P i) F i ^+ count_mem i r = \\prod_(i <- r | P i) F i.\n\n(*This lemma provides a rule for factoring a common left multiplier out of a finite product. The product of terms, where each term is the common multiplier times a function of an index, is equal to the common multiplier raised to the power of the size of the index set, multiplied by the product of the function values.*)\nLemma prodrMl {I : finType} (A : pred I) (x : R) F :\n \\prod_(i in A) (x * F i) = x ^+ #|A| * \\prod_(i in A) F i.\n\n(*This lemma provides a rule for factoring a common right multiplier out of a finite product. The product of terms, where each term is a function of an index times the common multiplier, is equal to the product of the function values multiplied by the common multiplier raised to the power of the size of the index set.*)\nLemma prodrMr {I : finType} (A : pred I) (x : R) F :\n \\prod_(i in A) (F i * x) = \\prod_(i in A) F i * x ^+ #|A|.\n\n(*This lemma states the binomial theorem for commutative semirings. It provides an expansion for the power of a sum of two elements as a sum of terms, where each term is the product of a binomial coefficient and powers of the two original elements.*)\nLemma exprDn x y n :\n (x + y) ^+ n = \\sum_(i < n.+1) (x ^+ (n - i) * y ^+ i) *+ 'C(n, i).\n\n(*This lemma states that the square of a sum of two elements in a commutative semiring is equal to the sum of the square of the first element, twice their product, and the square of the second element.*)\nLemma sqrrD x y : (x + y) ^+ 2 = x ^+ 2 + x * y *+ 2 + y ^+ 2.\n\nEnd ComSemiRingTheory.\n\nSection ComNzSemiRingTheory.\n\nVariable R : comNzSemiRingType.\nImplicit Types x y : R.\n\nSection FrobeniusAutomorphism.\n\nVariables (p : nat) (pcharRp : p \\in pchar R).\n\n(*This lemma asserts that the Frobenius automorphism, which raises an element to the power of the ring's characteristic, is an N-module morphism, meaning it preserves addition.*)\nLemma pFrobenius_aut_is_nmod_morphism : nmod_morphism (pFrobenius_aut pcharRp).\n\n(*This lemma asserts that the Frobenius automorphism, which raises an element to the power of the ring's characteristic, is a monoid morphism, meaning it preserves multiplication and the multiplicative identity.*)\nLemma pFrobenius_aut_is_monoid_morphism : monoid_morphism (pFrobenius_aut pcharRp).\n\n#[export]\nHB.instance Definition _ := isNmodMorphism.Build R R (pFrobenius_aut pcharRp)\n pFrobenius_aut_is_nmod_morphism.\n#[export]\n(*This lemma states that if the exponent is a multiple of the characteristic of the commutative non-zero semiring, then raising a sum of two elements to that exponent is equivalent to summing the elements each raised to that same exponent.*)\nLemma exprDn_pchar x y n : (pchar R).-nat n -> (x + y) ^+ n = x ^+ n + y ^+ n.\n\n(*This lemma states that the image of a ring morphism from a commutative non-zero semiring to another non-zero semiring consists of elements that commute with each other.*)\nLemma rmorph_comm (S : nzSemiRingType) (f : {rmorphism R -> S}) x y :\n comm (f x) (f y).\n\nSection ScaleLinear.\n\nVariables (U V : lSemiModType R) (b : R) (f : {linear U -> V}).\n\n(*This lemma asserts that for any fixed scalar, the function that scales vectors in a left semi-module by that scalar is itself a scalable map. This means that scaling a vector first by one scalar and then by another is commutative.*)\nLemma scale_is_scalable : scalable ( *:%R b : V -> V).\n\n#[export]\nHB.instance Definition _ :=\n isScalable.Build R V V *:%R ( *:%R b) scale_is_scalable.\n\n(*This lemma states that scaling a linear map by a scalar results in a new map that is also scalable. This means that applying the scaled map to a scaled input is equivalent to scaling the output of the scaled map applied to the original input.*)\nLemma scale_fun_is_scalable : scalable (b \\*: f).\n\n#[export]\n(*This structure defines a commutative P-zero ring, which is a ring where multiplication is commutative and the additive and multiplicative identities may be equal.*)\nHB.structure Definition ComPzRing := {R of PzRing R & ComPzSemiRing R}.\n\n(*This factory builds a mixin indicating that a given P-zero ring has a commutative multiplication operation.*)\nHB.factory Record PzRing_hasCommutativeMul R of PzRing R := {\n mulrC : commutative (@mul R)\n}.\n\nModule Ring_hasCommutativeMul.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use PzRing_hasCommutativeMul.Build instead.\")]\nNotation Build R := (PzRing_hasCommutativeMul.Build R) (only parsing).\nEnd Ring_hasCommutativeMul.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use PzRing_hasCommutativeMul instead.\")]\nNotation Ring_hasCommutativeMul R :=\n (PzRing_hasCommutativeMul R) (only parsing).\n\nHB.builders Context R of PzRing_hasCommutativeMul R.\nHB.instance Definition _ := PzSemiRing_hasCommutativeMul.Build R mulrC.\nHB.end.\n\n(*This factory builds a commutative P-zero ring structure on a given Z-module by providing a multiplicative identity, and a commutative and associative multiplication that distributes over addition.*)\nHB.factory Record Zmodule_isComPzRing R of Zmodule R := {\n one : R;\n mul : R -> R -> R;\n mulrA : associative mul;\n mulrC : commutative mul;\n mul1r : left_id one mul;\n mulrDl : left_distributive mul add;\n}.\n\nHB.builders Context R of Zmodule_isComPzRing R.\n Definition mulr1 := Monoid.mulC_id mulrC mul1r.\n Definition mulrDr := Monoid.mulC_dist mulrC mulrDl.\n HB.instance Definition _ := Zmodule_isPzRing.Build R\n mulrA mul1r mulr1 mulrDl mulrDr.\n HB.instance Definition _ := PzRing_hasCommutativeMul.Build R mulrC.\nHB.end.\n\nModule ComPzRingExports.\nBind Scope ring_scope with ComPzRing.sort.\nEnd ComPzRingExports.\nHB.export ComPzRingExports.\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"Use pFrobenius_aut_is_monoid_morphism instead.\")]\n(*A deprecated notation for a proof that the Frobenius automorphism is a multiplicative function.*)\nNotation pFrobenius_aut_is_multiplicative :=\n (fun p => (p.2, p.1) \\o pFrobenius_aut_is_monoid_morphism) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use exprDn_pchar instead.\")]\n(*A deprecated notation for the lemma stating that raising a sum to a power that is a multiple of the ring's characteristic is equivalent to summing the powers of the individual terms.*)\nNotation exprDn_char := exprDn_pchar (only parsing).\n\n#[short(type=\"comNzRingType\")]\n(*This structure defines a commutative non-zero ring, which is a ring where multiplication is commutative and the multiplicative identity is distinct from the additive identity.*)\nHB.structure Definition ComNzRing := {R of NzRing R & ComNzSemiRing R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzRing instead.\")]\nNotation ComRing R := (ComNzRing R) (only parsing).\n\nModule ComRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzRing.sort instead.\")]\n(*This refers to the underlying type of elements for the given algebraic structure.*)\nNotation sort := (ComNzRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzRing.on instead.\")]\nNotation on R := (ComNzRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzRing.copy instead.\")]\nNotation copy T U := (ComNzRing.copy T U) (only parsing).\nEnd ComRing.\n\n(*This structure packages the components and properties required to promote a Z-module to a commutative non-zero ring. It includes a multiplicative identity, a commutative and associative multiplication, and distributivity over addition.*)\nHB.factory Record Zmodule_isComNzRing R of Zmodule R := {\n one : R;\n mul : R -> R -> R;\n mulrA : associative mul;\n mulrC : commutative mul;\n mul1r : left_id one mul;\n mulrDl : left_distributive mul add;\n oner_neq0 : one != zero\n}.\n\nModule Zmodule_isComRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Zmodule_isComNzRing.Build instead.\")]\nNotation Build R := (Zmodule_isComNzRing.Build R) (only parsing).\nEnd Zmodule_isComRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Zmodule_isComNzRing instead.\")]\nNotation Zmodule_isComRing R := (Zmodule_isComNzRing R) (only parsing).\n\nHB.builders Context R of Zmodule_isComNzRing R.\n Definition mulr1 := Monoid.mulC_id mulrC mul1r.\n Definition mulrDr := Monoid.mulC_dist mulrC mulrDl.\n HB.instance Definition _ := Zmodule_isNzRing.Build R\n mulrA mul1r mulr1 mulrDl mulrDr oner_neq0.\n HB.instance Definition _ := PzRing_hasCommutativeMul.Build R mulrC.\nHB.end.\n\nModule ComNzRingExports.\nBind Scope ring_scope with ComNzRing.sort.\nEnd ComNzRingExports.\nHB.export ComNzRingExports.\n\nSection ComPzRingTheory.\n\nVariable R : comPzRingType.\nImplicit Types x y : R.\n\n(*This lemma states the binomial expansion for the n-th power of the difference of two elements in a commutative p-adic ring, expressing it as a weighted sum of products of powers of the elements.*)\nLemma exprBn x y n :\n (x - y) ^+ n =\n \\sum_(i < n.+1) ((-1) ^+ i * x ^+ (n - i) * y ^+ i) *+ 'C(n, i).\n\n(*This lemma provides the factorization for the difference between the n-th powers of two elements in a commutative p-adic ring, expressing it as the product of their difference and a sum of mixed-power terms.*)\nLemma subrXX x y n :\n x ^+ n - y ^+ n = (x - y) * (\\sum_(i < n) x ^+ (n.-1 - i) * y ^+ i).\n\n(*This lemma states that the square of the difference of two elements in a commutative p-adic ring expands to the square of the first element, minus twice their product, plus the square of the second element.*)\nLemma sqrrB x y : (x - y) ^+ 2 = x ^+ 2 - x * y *+ 2 + y ^+ 2.\n\n(*This lemma states that the difference of the squares of two elements in a commutative p-adic ring is equal to the product of their difference and their sum.*)\nLemma subr_sqr x y : x ^+ 2 - y ^+ 2 = (x - y) * (x + y).\n\n(*This lemma states that in a commutative p-adic ring, the difference between the square of the sum of two elements and the square of their difference is equal to four times their product.*)\nLemma subr_sqrDB x y : (x + y) ^+ 2 - (x - y) ^+ 2 = x * y *+ 4.\n\nEnd ComPzRingTheory.\n\n(*This structure provides an axiom for a left semi-algebra to be a semi-algebra, asserting a compatibility rule between scalar multiplication and the algebra's internal multiplication.*)\nHB.mixin Record LSemiAlgebra_isSemiAlgebra R V of LSemiAlgebra R V := {\n scalerAr : forall k (x y : V), k *: (x * y) = x * (k *: y);\n}.\n#[short(type=\"semiAlgType\")]\n(*This definition introduces the algebraic structure of a semi-algebra over a p-adic semi-ring, which is a module that is also a semi-ring with a compatible scalar multiplication.*)\nHB.structure Definition SemiAlgebra (R : pzSemiRingType) :=\n {A of LSemiAlgebra_isSemiAlgebra R A & LSemiAlgebra R A}.\n\nModule SemiAlgExports.\nBind Scope ring_scope with SemiAlgebra.sort.\nEnd SemiAlgExports.\n\n(*This structure provides a way to construct a commutative semi-algebra from a type that is simultaneously a commutative p-adic semi-ring and a left semi-algebra, indicating that the required properties are derivable.*)\nHB.factory Record LSemiAlgebra_isComSemiAlgebra R V\n of ComPzSemiRing V & LSemiAlgebra R V := {}.\nHB.builders Context (R : pzSemiRingType) V of LSemiAlgebra_isComSemiAlgebra R V.\n\nLemma scalarAr k (x y : V) : k *: (x * y) = x * (k *: y).\n\nHB.instance Definition _ := LSemiAlgebra_isSemiAlgebra.Build R V scalarAr.\n\nHB.end.\n\n#[short(type=\"algType\")]\n(*This definition introduces the algebraic structure of an algebra over a p-adic ring, which is a module that is also a ring, with a compatible interaction between scalar multiplication and the ring's multiplication.*)\nHB.structure Definition Algebra (R : pzRingType) :=\n {A of LSemiAlgebra_isSemiAlgebra R A & Lalgebra R A}.\n\nModule AlgExports.\nBind Scope ring_scope with Algebra.sort.\nEnd AlgExports.\nHB.export AlgExports.\n\n(*This structure is used to build an algebra from a left algebra by supplying an explicit proof of the compatibility axiom between scalar multiplication and the algebra's internal multiplication.*)\nHB.factory Record Lalgebra_isAlgebra (R : pzRingType) V of Lalgebra R V := {\n scalerAr : forall k (x y : V), k *: (x * y) = x * (k *: y);\n}.\nHB.builders Context (R : pzRingType) V of Lalgebra_isAlgebra R V.\n\nHB.instance Definition _ := LSemiAlgebra_isSemiAlgebra.Build R V scalerAr.\n\nHB.end.\n\n(*This structure provides a way to construct a commutative algebra from a type that is simultaneously a commutative p-adic ring and a left algebra, indicating that the necessary properties are inherited.*)\nHB.factory Record Lalgebra_isComAlgebra R V of ComPzRing V & Lalgebra R V := {}.\nHB.builders Context (R : pzRingType) V of Lalgebra_isComAlgebra R V.\n\n(*This lemma asserts a compatibility property within an algebra, stating that scaling a product of two elements is equivalent to multiplying the first element by the scaled second element.*)\nLemma scalarAr k (x y : V) : k *: (x * y) = x * (k *: y).\n\n(*This instance declaration establishes that a left algebra that is also a commutative algebra automatically satisfies the criteria to be an algebra.*)\nHB.instance Definition lalgebra_is_algebra : Lalgebra_isAlgebra R V :=\n Lalgebra_isAlgebra.Build R V scalarAr.\n\nHB.end.\n\n#[short(type=\"comSemiAlgType\")]\n(*This definition introduces the structure of a commutative semi-algebra, which is a semi-algebra over a base semi-ring whose internal multiplication is commutative.*)\nHB.structure Definition ComSemiAlgebra R :=\n {V of ComNzSemiRing V & SemiAlgebra R V}.\n\nModule ComSemiAlgExports.\nBind Scope ring_scope with ComSemiAlgebra.sort.\nEnd ComSemiAlgExports.\nHB.export ComSemiAlgExports.\n\nSection SemiAlgebraTheory.\n#[export]\nHB.instance Definition _ (R : comPzSemiRingType) :=\n PzSemiRing_hasCommutativeMul.Build R^c (fun _ _ => mulrC _ _).\n#[export]\nHB.instance Definition _ (R : comPzSemiRingType) := ComPzSemiRing.on R^o.\n#[export]\nHB.instance Definition _ (R : comNzSemiRingType) := ComNzSemiRing.on R^c.\n#[export]\nHB.instance Definition _ (R : comNzSemiRingType) := ComNzSemiRing.on R^o.\n#[export]\n(*This definition introduces the structure of a commutative algebra, which is an algebra over a base ring whose internal multiplication is commutative.*)\nHB.structure Definition ComAlgebra R := {V of ComNzRing V & Algebra R V}.\n\nModule ComAlgExports.\nBind Scope ring_scope with ComAlgebra.sort.\nEnd ComAlgExports.\nHB.export ComAlgExports.\n\nSection AlgebraTheory.\n#[export]\nHB.instance Definition _ (R : comPzRingType) := ComPzRing.on R^c.\n#[export]\nHB.instance Definition _ (R : comPzRingType) := ComPzRing.on R^o.\n#[export]\nHB.instance Definition _ (R : comNzRingType) := ComNzRing.on R^c.\n#[export]\nHB.instance Definition _ (R : comNzRingType) := ComNzRing.on R^o.\nEnd AlgebraTheory.\n\nSection SemiAlgebraTheory.\n\nVariables (R : pzSemiRingType) (A : semiAlgType R).\nImplicit Types (k : R) (x y : A).\n\n(*This lemma states that for any two elements in a semi-algebra, multiplying a scaled version of the first element by the second is equivalent to multiplying the first element by a scaled version of the second.*)\nLemma scalerCA k x y : k *: x * y = x * (k *: y).\n\n(*This lemma establishes a connection between internal multiplication and scalar multiplication in an algebra, stating that right-multiplying an element by the canonical image of a scalar is equivalent to left-scaling that element by the same scalar.*)\nLemma mulr_algr a x : x * a%:A = a *: x.\n\n(*This lemma states that the canonical image of any scalar from the base ring commutes with every element of the algebra under the algebra's internal multiplication.*)\nLemma comm_alg a x : comm a%:A x.\n\n(*This lemma states that raising a scaled element to a natural number power is equivalent to scaling the element's power by the scalar's power.*)\nLemma exprZn k x n : (k *: x) ^+ n = k ^+ n *: x ^+ n.\n\n(*This lemma generalizes how scalar multiplication distributes over products, stating that the product of scaled elements is equal to the product of the scalars scaling the product of the elements.*)\nLemma scaler_prod I r (P : pred I) (F : I -> R) (G : I -> A) :\n \\prod_(i <- r | P i) (F i *: G i) =\n \\prod_(i <- r | P i) F i *: \\prod_(i <- r | P i) G i.\n\n(*This lemma states that the product of a sequence of elements, each scaled by the same scalar, is equal to the product of the unscaled elements scaled by the scalar raised to the power of the sequence length.*)\nLemma scaler_prodl (I : finType) (S : pred I) (F : I -> A) k :\n \\prod_(i in S) (k *: F i) = k ^+ #|S| *: \\prod_(i in S) F i.\n\n(*This lemma states that the product of a fixed element scaled by a sequence of different scalars is equal to the element raised to the power of the sequence length, scaled by the product of the scalars.*)\nLemma scaler_prodr (I : finType) (S : pred I) (F : I -> R) x :\n \\prod_(i in S) (F i *: x) = \\prod_(i in S) F i *: x ^+ #|S|.\n\nEnd SemiAlgebraTheory.\n\nSection AlgebraTheory.\n\nVariables (R : pzSemiRingType) (A : semiAlgType R).\nVariables (U : lSemiModType R) (a : A) (f : {linear U -> A}).\n\n(*This lemma asserts that a function formed by composing a linear map with left multiplication by a fixed algebra element preserves scalar multiplication.*)\nLemma mull_fun_is_scalable : scalable (a \\*o f).\n\n#[export]\n(*This structure equips a non-zero ring with a partial multiplicative inverse operation. It defines a predicate for units, an inverse function, and the properties ensuring that the inverse behaves as expected for units and is trivial for non-units.*)\nHB.mixin Record NzRing_hasMulInverse R of NzRing R := {\n unit_subdef : pred R;\n inv : R -> R;\n mulVr_subproof : {in unit_subdef, left_inverse 1 inv *%R};\n divrr_subproof : {in unit_subdef, right_inverse 1 inv *%R};\n unitrP_subproof : forall x y, y * x = 1 /\\ x * y = 1 -> unit_subdef x;\n invr_out_subproof : {in [predC unit_subdef], inv =1 id}\n}.\n\nModule Ring_hasMulInverse.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzRing_hasMulInverse.Build instead.\")]\nNotation Build R := (NzRing_hasMulInverse.Build R) (only parsing).\nEnd Ring_hasMulInverse.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NzRing_hasMulInverse instead.\")]\nNotation Ring_hasMulInverse R := (NzRing_hasMulInverse R) (only parsing).\n\n#[short(type=\"unitRingType\")]\n(*This definition introduces the structure of a unit ring, which is a non-zero ring where a multiplicative inverse is defined for a designated subset of elements known as units.*)\nHB.structure Definition UnitRing := {R of NzRing_hasMulInverse R & NzRing R}.\n\nModule UnitRingExports.\nBind Scope ring_scope with UnitRing.sort.\nEnd UnitRingExports.\nHB.export UnitRingExports.\n\n(*This definition introduces a predicate that evaluates to true if a given element of a unit ring is a unit, meaning it has a multiplicative inverse.*)\nDefinition unit_pred {R : unitRingType} :=\n Eval cbv [ unit_subdef NzRing_hasMulInverse.unit_subdef ] in\n (fun u : R => unit_subdef u).\nArguments unit_pred _ _ /.\n(*This definition specifies the type of units within a unit ring, consisting of all elements that have a multiplicative inverse.*)\nDefinition unit {R : unitRingType} := [qualify a u : R | unit_pred u].\n\n(*This notation provides syntax for the multiplicative inverse of a ring element.*)\nLocal Notation \"x ^-1\" := (inv x).\n(*A notation for the right division of a ring element by another, defined as the product of the first element with the multiplicative inverse of the second element.*)\nLocal Notation \"x / y\" := (x * y^-1).\n(*A notation for the negative power of a ring element by a natural number, defined as the multiplicative inverse of the element raised to the positive power of that natural number.*)\nLocal Notation \"x ^- n\" := ((x ^+ n)^-1).\n\nSection UnitRingTheory.\n\nVariable R : unitRingType.\nImplicit Types x y : R.\n\n(*This lemma states that for any unit element in a ring, multiplying it by its own multiplicative inverse on the right results in the multiplicative identity.*)\nLemma divrr : {in unit, right_inverse 1 (@inv R) *%R}.\n\n(*This definition establishes that right-multiplying any unit element of a ring by its inverse yields the multiplicative identity.*)\nDefinition mulrV := divrr.\n\n(*This lemma states that for any unit element in a ring, multiplying its multiplicative inverse on the left by the element itself results in the multiplicative identity.*)\nLemma mulVr : {in unit, left_inverse 1 (@inv R) *%R}.\n\n(*This lemma states that if a ring element is not a unit, its multiplicative inverse is defined to be the element itself.*)\nLemma invr_out x : x \\isn't a unit -> x^-1 = x.\n\n(*This lemma states that a ring element is a unit if and only if there exists another element in the ring that serves as both its left and right multiplicative inverse.*)\nLemma unitrP x : reflect (exists y, y * x = 1 /\\ x * y = 1) (x \\is a unit).\n\n(*This lemma states that for any unit element in a ring, left-multiplying a product by the inverse of the first factor cancels out that factor, effectively demonstrating left-cancellation by units.*)\nLemma mulKr : {in unit, left_loop (@inv R) *%R}.\n\n(*This lemma states that for any unit element in a ring, multiplying it by a product whose first factor is its inverse results in the second factor of the product, demonstrating a form of left-cancellation.*)\nLemma mulVKr : {in unit, rev_left_loop (@inv R) *%R}.\n\n(*This lemma states that for any unit element in a ring, right-multiplying a product by the inverse of the second factor cancels out that factor, effectively demonstrating right-cancellation by units.*)\nLemma mulrK : {in unit, right_loop (@inv R) *%R}.\n\n(*This lemma states that for any ring element, multiplying it by the product of a unit and its inverse is equivalent to multiplying by the multiplicative identity.*)\nLemma mulrVK : {in unit, rev_right_loop (@inv R) *%R}.\n\n(*This definition establishes that multiplying any ring element by the result of dividing a unit by itself yields the original element.*)\nDefinition divrK := mulrVK.\n\n(*This lemma states that multiplication on the right by any unit element is an injective operation, meaning if two elements yield the same result when multiplied by the same unit on the right, then they must be equal.*)\nLemma mulrI : {in @unit R, right_injective *%R}.\n\n(*This lemma states that multiplication on the left by any unit element is an injective operation, meaning if two elements yield the same result when multiplied on the left by the same unit, then they must be equal.*)\nLemma mulIr : {in @unit R, left_injective *%R}.\n\n(*This lemma provides a formula for a telescoping product of divisions. It states that the product of terms, where each term is a ring element from a sequence at one index divided by the element at the next index, simplifies to the first element of the sequence divided by the last, provided that all intermediate elements are units.*)\nLemma telescope_prodr n m (f : nat -> R) :\n (forall k, n < k < m -> f k \\is a unit) -> n < m ->\n \\prod_(n <= k < m) (f k / f k.+1) = f n / f m.\n\n(*This lemma states that a product of a sequence of ring elements equals the first element of a related sequence divided by its last element, provided that each term in the product is equal to the ratio of consecutive elements in the related sequence and that all intermediate elements of the related sequence are units.*)\nLemma telescope_prodr_eq n m (f u : nat -> R) : n < m ->\n (forall k, n < k < m -> f k \\is a unit) ->\n (forall k, (n <= k < m)%N -> u k = f k / f k.+1) ->\n \\prod_(n <= k < m) u k = f n / f m.\n\n(*This lemma states that if one ring element commutes with another, it also commutes with the multiplicative inverse of the second element. This property is particularly significant when the second element is a unit.*)\nLemma commrV x y : comm x y -> comm x y^-1.\n\n(*This lemma provides an equational characterization of a unit element, stating that an element is a unit if and only if the boolean test for equality between the result of dividing that element by itself and the multiplicative identity evaluates to true.*)\nLemma unitrE x : (x \\is a unit) = (x / x == 1).\n\n(*This lemma states that the multiplicative inverse operation on a ring is an involution, meaning that applying it twice to any element returns the original element.*)\nLemma invrK : involutive (@inv R).\n\n(*This lemma states that the multiplicative inverse operation on a ring is injective, meaning that if two elements have the same multiplicative inverse, they must be equal.*)\nLemma invr_inj : injective (@inv R). \n\n(*This lemma states that a ring element is a unit if and only if its multiplicative inverse is also a unit.*)\nLemma unitrV x : (x^-1 \\in unit) = (x \\in unit).\n\n(*This lemma states that the multiplicative identity of a ring is a unit element.*)\nLemma unitr1 : 1 \\in @unit R.\n\n(*This lemma states that the multiplicative inverse of the multiplicative identity in a ring is the identity itself.*)\nLemma invr1 : 1^-1 = 1 :> R.\n\n(*This lemma states that dividing the multiplicative identity by any ring element is equivalent to taking the multiplicative inverse of that element.*)\nLemma div1r x : 1 / x = x^-1. \n(*This lemma states that dividing any ring element by the multiplicative identity results in the original element.*)\nLemma divr1 x : x / 1 = x. \n\n(*This lemma relates integer division of natural numbers to ring division. It states that if a natural number divides another and its injection into a ring is a unit, then the injection of their integer quotient is equal to the quotient of their injections in the ring.*)\nLemma natr_div m d :\n d %| m -> d%:R \\is a @unit R -> (m %/ d)%:R = m%:R / d%:R :> R.\n\n(*This lemma states that for any fixed unit element as the divisor, the division operation is injective with respect to its dividend, meaning if two distinct elements are divided by the same unit, their results will be distinct.*)\nLemma divrI : {in unit, right_injective (fun x y => x / y)}.\n\n(*This lemma states that for any fixed unit element as the dividend, the division operation is injective with respect to its divisor, meaning if a single unit is divided by two distinct elements, the results will be distinct.*)\nLemma divIr : {in unit, left_injective (fun x y => x / y)}.\n\n(*This lemma states that the additive identity of a ring is not a unit, which is true for any ring where the additive and multiplicative identities are distinct.*)\nLemma unitr0 : (0 \\is a @unit R) = false.\n\n(*This lemma states that the multiplicative inverse of the additive identity in a ring is defined to be the additive identity itself.*)\nLemma invr0 : 0^-1 = 0 :> R.\n\n(*This lemma states that the additive inverse of one is a unit in a unit ring.*)\nLemma unitrN1 : -1 \\is a @unit R.\n\n(*This lemma states that the multiplicative inverse of the additive inverse of one is equal to the additive inverse of one.*)\nLemma invrN1 : (-1)^-1 = -1 :> R.\n\n(*This lemma states that for any natural number exponent, the result of raising the multiplicative inverse of negative one to that exponent is equal to the result of raising negative one directly to that exponent.*)\nLemma invr_sign n : ((-1) ^- n) = (-1) ^+ n :> R.\n\n(*This lemma states that for two ring elements, if the second element is a unit, then their product is a unit if and only if the first element is a unit.*)\nLemma unitrMl x y : y \\is a unit -> (x * y \\is a unit) = (x \\is a unit).\n\n(*This lemma states that for two ring elements, if the first element is a unit, then their product is a unit if and only if the second element is a unit.*)\nLemma unitrMr x y : x \\is a unit -> (x * y \\is a unit) = (y \\is a unit).\n\n(*This lemma states that the product of a filtered sequence of ring elements is a unit, provided that every element selected by the filter is a unit.*)\nLemma unitr_prod {I : Type} (P : pred I) (E : I -> R) (r : seq I) :\n (forall i, P i -> E i \\is a GRing.unit) ->\n (\\prod_(i <- r | P i) E i \\is a GRing.unit).\n\n(*This lemma states that the product of a filtered sequence of ring elements is a unit if every element from the sequence that satisfies the filter's predicate is a unit.*)\nLemma unitr_prod_in {I : eqType} (P : pred I) (E : I -> R) (r : seq I) :\n {in r, forall i, P i -> E i \\is a GRing.unit} ->\n (\\prod_(i <- r | P i) E i \\is a GRing.unit).\n\n(*This lemma states that for any two unit elements in a ring, the multiplicative inverse of their product is equal to the product of their multiplicative inverses in the reverse order.*)\nLemma invrM : {in unit &, forall x y, (x * y)^-1 = y^-1 * x^-1}.\n\n(*This lemma states that for any two commuting ring elements, their product is a unit if and only if both elements are individually units.*)\nLemma unitrM_comm x y :\n comm x y -> (x * y \\is a unit) = (x \\is a unit) && (y \\is a unit).\n\n(*This lemma states that if a ring element is a unit, then raising it to any natural number power results in an element that is also a unit.*)\nLemma unitrX x n : x \\is a unit -> x ^+ n \\is a unit.\n\n(*This lemma states that for a positive natural number exponent, a ring element raised to that power is a unit if and only if the original element is a unit.*)\nLemma unitrX_pos x n : n > 0 -> (x ^+ n \\in unit) = (x \\in unit).\n\n(*This lemma states that for a unit ring element, raising its multiplicative inverse to a natural number power is equivalent to raising the element to the corresponding negative integer power.*)\nLemma exprVn x n : x^-1 ^+ n = x ^- n.\n\n(*This lemma states that for a unit ring element, if a natural number is less than or equal to another, then the element raised to the power of their difference is equal to the element raised to the first number divided by the element raised to the second number.*)\nLemma exprB m n x : n <= m -> x \\is a unit -> x ^+ (m - n) = x ^+ m / x ^+ n.\n\n(*This lemma states that the multiplicative inverse of a non-zero unit ring element is also non-zero.*)\nLemma invr_neq0 x : x != 0 -> x^-1 != 0.\n\n(*This lemma states that the multiplicative inverse of a ring element is the zero element if and only if the element itself is the zero element.*)\nLemma invr_eq0 x : (x^-1 == 0) = (x == 0).\n\n(*This lemma states that the multiplicative inverse of a ring element is the multiplicative identity if and only if the element itself is the multiplicative identity.*)\nLemma invr_eq1 x : (x^-1 == 1) = (x == 1).\n\n(*This lemma states that for an element in the opposite ring of a given ring, if there exists a two-sided multiplicative inverse for that element, then the element is a unit.*)\nLemma rev_unitrP (x y : R^c) : y * x = 1 /\\ x * y = 1 -> x \\is a unit.\n\n#[export]\nHB.instance Definition _ :=\n NzRing_hasMulInverse.Build R^c mulrV mulVr rev_unitrP invr_out.\n\n#[export]\n(*This lemma states that for a filtered sequence of unit ring elements, the product of their multiplicative inverses is equal to the multiplicative inverse of their product when computed in the opposite ring.*)\nLemma rev_prodrV (R : unitRingType)\n (I : Type) (r : seq I) (P : pred I) (E : I -> R) :\n (forall i, P i -> E i \\is a GRing.unit) ->\n \\prod_(i <- r | P i) (E i)^-1 = ((\\prod_(i <- r | P i) (E i : R^c))^-1).\n\nSection UnitRingClosedPredicates.\n\nVariables (R : unitRingType) (S : {pred R}).\n\n(*This definition asserts that a predicate on ring elements is closed under multiplicative inversion if for every unit element satisfying the predicate, its multiplicative inverse also satisfies the predicate.*)\nDefinition invr_closed := {in S, forall x, x^-1 \\in S}.\n(*This definition asserts that a predicate on ring elements is closed under division if for any two elements satisfying the predicate, where the second element is a unit, their quotient also satisfies the predicate.*)\nDefinition divr_2closed := {in S &, forall x y, x / y \\in S}.\n(*This definition asserts that a predicate on ring elements is closed under division if it contains the multiplicative identity and is closed under the division of any two of its elements.*)\nDefinition divr_closed := 1 \\in S /\\ divr_2closed.\n(*This definition asserts that a predicate on ring elements is closed under signed division if it contains the additive inverse of one and is closed under the division of any two of its elements.*)\nDefinition sdivr_closed := -1 \\in S /\\ divr_2closed.\n(*This definition asserts that a predicate on ring elements describes a sub-division ring if it contains the multiplicative identity and is closed under both subtraction and division.*)\nDefinition divring_closed := [/\\ 1 \\in S, subr_2closed S & divr_2closed].\n\n(*This lemma states that if a predicate on ring elements is closed under division, then it is also closed under multiplicative inversion.*)\nLemma divr_closedV : divr_closed -> invr_closed.\n\n(*This lemma states that if a predicate on ring elements is closed under division, then it is also closed under multiplication.*)\nLemma divr_closedM : divr_closed -> mulr_closed S.\n\n(*This lemma states that if a predicate on ring elements is closed under signed division, then it is also closed under division.*)\nLemma sdivr_closed_div : sdivr_closed -> divr_closed.\n\n(*This lemma states that if a predicate on ring elements is closed under signed division, then it is also closed under signed multiplication, meaning it is closed under both multiplication and negation.*)\nLemma sdivr_closedM : sdivr_closed -> smulr_closed S.\n\n(*This lemma states that if a predicate on ring elements is closed for a division ring structure, then it is also closed for a subring structure.*)\nLemma divring_closedBM : divring_closed -> subring_closed S.\n\n(*This lemma states that if a predicate on ring elements is closed for a division ring structure, it is also closed under signed division.*)\nLemma divring_closed_div : divring_closed -> sdivr_closed.\n\nEnd UnitRingClosedPredicates.\n\nSection UnitRingMorphism.\n\nVariables (R S : unitRingType) (f : {rmorphism R -> S}).\n\n(*This lemma states that any ring morphism maps a unit element in its domain to a unit element in its codomain.*)\nLemma rmorph_unit x : x \\in unit -> f x \\in unit.\n\n(*This lemma states that a ring morphism preserves the multiplicative inverse for unit elements, meaning the image of the inverse of a unit is the inverse of its image.*)\nLemma rmorphV : {in unit, {morph f: x / x^-1}}.\n\n(*This lemma states that for a given ring morphism, the image of the division of a ring element by a unit element is equal to the division of the image of the first element by the image of the unit element.*)\nLemma rmorph_div x y : y \\in unit -> f (x / y) = f x / f y.\n\nEnd UnitRingMorphism.\n\n#[short(type=\"comUnitRingType\")]\n(*This definition describes the structure for a commutative unit ring, which is a commutative ring with a multiplicative identity that is distinct from the additive identity, and where some elements have multiplicative inverses.*)\nHB.structure Definition ComUnitRing := {R of ComNzRing R & UnitRing R}.\n\nModule ComUnitRingExports.\nBind Scope ring_scope with ComUnitRing.sort.\nEnd ComUnitRingExports.\nHB.export ComUnitRingExports.\n\n(*This factory record defines the properties required to equip a commutative non-zero ring with a multiplicative inverse operation, specifying the set of unit elements, the inverse function, and axioms ensuring that left-inverses exist and that the inverse of a non-unit is the identity.*)\nHB.factory Record ComNzRing_hasMulInverse R of ComNzRing R := {\n unit : {pred R};\n inv : R -> R;\n mulVx : {in unit, left_inverse 1 inv *%R};\n unitPl : forall x y, y * x = 1 -> unit x;\n invr_out : {in [predC unit], inv =1 id}\n}.\n\nModule ComRing_hasMulInverse.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzRing_hasMulInverse.Build instead.\")]\nNotation Build R := (ComNzRing_hasMulInverse.Build R) (only parsing).\nEnd ComRing_hasMulInverse.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzRing_hasMulInverse instead.\")]\nNotation ComRing_hasMulInverse R := (ComNzRing_hasMulInverse R) (only parsing).\n\nHB.builders Context R of ComNzRing_hasMulInverse R.\n\n(*This fact establishes that within a commutative ring, if an element has a left multiplicative inverse, then that inverse is also its right multiplicative inverse.*)\nFact mulC_mulrV : {in unit, right_inverse 1 inv *%R}.\n\n(*This fact states that in a commutative ring, an element is a unit if there exists another element that serves as both its left and right multiplicative inverse.*)\nFact mulC_unitP x y : y * x = 1 /\\ x * y = 1 -> unit x.\n\nHB.instance Definition _ :=\n NzRing_hasMulInverse.Build R mulVx mulC_mulrV mulC_unitP invr_out.\n\nHB.end.\n\n#[short(type=\"unitAlgType\")]\n(*This definition describes the structure of a unit algebra over a ring, which is an algebra that is also a unit ring.*)\nHB.structure Definition UnitAlgebra R := {V of Algebra R V & UnitRing V}.\n\nModule UnitAlgebraExports.\nBind Scope ring_scope with UnitAlgebra.sort.\nEnd UnitAlgebraExports.\nHB.export UnitAlgebraExports.\n\n#[short(type=\"comUnitAlgType\")]\n(*This definition describes the structure of a commutative unit algebra over a ring, which is an algebra with a commutative multiplication that is also a unit ring.*)\nHB.structure Definition ComUnitAlgebra R := {V of ComAlgebra R V & UnitRing V}.\n\nModule ComUnitAlgebraExports.\nBind Scope ring_scope with UnitAlgebra.sort.\nEnd ComUnitAlgebraExports.\nHB.export ComUnitAlgebraExports.\n\nSection ComUnitRingTheory.\n\nVariable R : comUnitRingType.\nImplicit Types x y : R.\n\n(*This lemma states that in a commutative unit ring, the product of two elements is a unit if and only if both individual elements are units.*)\nLemma unitrM x y : (x * y \\in unit) = (x \\in unit) && (y \\in unit).\n\n(*This lemma provides a reflection property, stating that an element of a commutative unit ring is a unit if and only if there exists another element which, when multiplied with the first, yields the multiplicative identity.*)\nLemma unitrPr x : reflect (exists y, x * y = 1) (x \\in unit).\n\n(*This lemma states that if the product of two elements in a commutative unit ring is the multiplicative identity, then the second element is the multiplicative inverse of the first.*)\nLemma mulr1_eq x y : x * y = 1 -> x^-1 = y.\n\n(*This lemma states that in a commutative unit ring, if the division of a first element by a second unit element equals the multiplicative identity, then the two elements are equal.*)\nLemma divr1_eq x y : x / y = 1 -> x = y. \n\n(*This lemma states that if a given element of a commutative unit ring is a unit, then the function that divides this fixed element by any other unit element is an involution on the set of units.*)\nLemma divKr x : x \\is a unit -> {in unit, involutive (fun y => x / y)}.\n\n(*This lemma states that in a commutative unit ring, raising the division of an element by a unit to a natural number power is equivalent to dividing the first element raised to that power by the unit element raised to the same power.*)\nLemma expr_div_n x y n : (x / y) ^+ n = x ^+ n / y ^+ n.\n\n(*This lemma provides a reflection property, stating that the iterated product of a sequence of ring elements is a unit if and only if every element being multiplied is itself a unit.*)\nLemma unitr_prodP (I : eqType) (r : seq I) (P : pred I) (E : I -> R) :\n reflect {in r, forall i, P i -> E i \\is a GRing.unit}\n (\\prod_(i <- r | P i) E i \\is a GRing.unit).\n\n(*This lemma states that for a sequence of unit elements in a commutative unit ring, the iterated product of their inverses is equal to the inverse of their iterated product.*)\nLemma prodrV (I : eqType) (r : seq I) (P : pred I) (E : I -> R) :\n (forall i, P i -> E i \\is a GRing.unit) ->\n \\prod_(i <- r | P i) (E i)^-1 = (\\prod_(i <- r | P i) E i)^-1.\n\n#[export] HB.instance Definition _ := ComUnitRing.on R^c.\n(*This lemma states that in a unit algebra, scalar multiplication on the left by a unit from the base ring is an injective function.*)\nLemma scaler_injl : {in unit, @right_injective R A A *:%R}.\n\n(*This lemma states that in a unit algebra, the scalar product of a unit scalar and an algebra element is a unit if and only if the algebra element itself is a unit.*)\nLemma scaler_unit k x : k \\in unit -> (k *: x \\in unit) = (x \\in unit).\n\n(*This lemma states that in a unit algebra, the multiplicative inverse of the scalar product of a unit scalar and a unit algebra element is equal to the scalar product of the inverse of the scalar and the inverse of the algebra element.*)\nLemma invrZ k x : k \\in unit -> x \\in unit -> (k *: x)^-1 = k^-1 *: x^-1.\n\nSection ClosedPredicates.\n\nVariables S : {pred A}.\n\n(*This definition specifies the property of a predicate on a unit algebra being closed under division algebra operations, which means it contains the multiplicative identity, is closed under linear combinations, and is closed under right division by its own elements.*)\nDefinition divalg_closed := [/\\ 1 \\in S, linear_closed S & divr_2closed S].\n\n(*This lemma states that if a predicate on a unit algebra is closed under division algebra operations, then it is also closed under division ring operations.*)\nLemma divalg_closedBdiv : divalg_closed -> divring_closed S.\n\n(*This lemma states that if a predicate on a unit algebra is closed under division algebra operations, then it is also closed under subalgebra operations.*)\nLemma divalg_closedZ : divalg_closed -> subalg_closed S.\n\nEnd ClosedPredicates.\n\nEnd UnitAlgebraTheory.\n\nModule ClosedExports.\n\n(*This notation defines 'addr_closed' as an alias for the property of a predicate being closed under addition and containing the additive identity, typically used for additive submodules.*)\nNotation addr_closed := nmod_closed.\n(*This notation serves as a placeholder or export for the property of a predicate being closed under the additive inverse operation.*)\nNotation oppr_closed := oppr_closed.\n(*This notation serves as a placeholder or export for the property of a predicate being closed under the operations of an additive group, namely addition, containing zero, and being closed under additive inverse.*)\nNotation zmod_closed := zmod_closed.\n(*This notation serves as a placeholder or export for the property of a predicate being closed under the multiplication operation.*)\nNotation mulr_closed := mulr_closed.\n(*This notation serves as a placeholder or export for the property of a predicate being closed under the operations of a semiring, namely addition and multiplication, and containing the additive and multiplicative identities.*)\nNotation semiring_closed := semiring_closed.\n(*This notation serves as a placeholder or export for the property of a predicate being closed under the scalar multiplication operation.*)\nNotation smulr_closed := smulr_closed.\n(*This notation serves as a placeholder or export for the property of a predicate being closed under all ring operations, thus forming a subring.*)\nNotation subring_closed := subring_closed.\n(*This notation serves as a placeholder or export for the property of a predicate being closed under scalar multiplication.*)\nNotation scaler_closed := scaler_closed.\n(*A notation for a predicate asserting that a subset is closed under addition and scalar multiplication, forming a subsemimodule.*)\nNotation subsemimod_closed := subsemimod_closed.\n(*A notation for a predicate asserting that a subset of a module is closed under linear combinations.*)\nNotation linear_closed := linear_closed.\n(*A notation for a predicate asserting that a subset is closed under all module operations, forming a submodule.*)\nNotation submod_closed := submod_closed.\n(*A notation for a predicate asserting that a subset is closed under all algebra operations, forming a subalgebra.*)\nNotation subalg_closed := subalg_closed.\n(*A notation for a predicate asserting that a subset of a ring is closed under multiplicative inversion.*)\nNotation invr_closed := invr_closed.\n(*A notation for a predicate asserting that a subset is closed under a binary division operation.*)\nNotation divr_2closed := divr_2closed.\n(*A notation for a predicate asserting that a subset of a ring is closed under both multiplication and multiplicative inversion.*)\nNotation divr_closed := divr_closed.\n(*A notation for a predicate asserting that a subset is closed under scalar multiplication, multiplication, and multiplicative inversion.*)\nNotation sdivr_closed := sdivr_closed.\n(*A notation for a predicate asserting that a subset is closed under all operations of a division ring, forming a sub-division ring.*)\nNotation divring_closed := divring_closed.\n(*A notation for a predicate asserting that a subset is closed under all operations of a division algebra, forming a sub-division algebra.*)\nNotation divalg_closed := divalg_closed.\n\nCoercion zmod_closedD : zmod_closed >-> nmod_closed.\nCoercion zmod_closedN : zmod_closed >-> oppr_closed.\nCoercion semiring_closedD : semiring_closed >-> addr_closed.\nCoercion semiring_closedM : semiring_closed >-> mulr_closed.\nCoercion smulr_closedM : smulr_closed >-> mulr_closed.\nCoercion smulr_closedN : smulr_closed >-> oppr_closed.\nCoercion subring_closedB : subring_closed >-> zmod_closed.\nCoercion subring_closedM : subring_closed >-> smulr_closed.\nCoercion subring_closed_semi : subring_closed >-> semiring_closed.\nCoercion subsemimod_closedD : subsemimod_closed >-> addr_closed.\nCoercion subsemimod_closedZ : subsemimod_closed >-> scaler_closed.\nCoercion linear_closedB : linear_closed >-> subr_2closed.\nCoercion submod_closedB : submod_closed >-> zmod_closed.\nCoercion submod_closed_semi : submod_closed >-> subsemimod_closed.\nCoercion subalg_closedZ : subalg_closed >-> submod_closed.\nCoercion subalg_closedBM : subalg_closed >-> subring_closed.\nCoercion divr_closedV : divr_closed >-> invr_closed.\nCoercion divr_closedM : divr_closed >-> mulr_closed.\nCoercion sdivr_closed_div : sdivr_closed >-> divr_closed.\nCoercion sdivr_closedM : sdivr_closed >-> smulr_closed.\nCoercion divring_closedBM : divring_closed >-> subring_closed.\nCoercion divring_closed_div : divring_closed >-> sdivr_closed.\nCoercion divalg_closedBdiv : divalg_closed >-> divring_closed.\nCoercion divalg_closedZ : divalg_closed >-> subalg_closed.\n\nEnd ClosedExports.\n\nSection TermDef.\n\nVariable R : Type.\n\n(**)\nInductive term : Type :=\n| Var of nat\n| Const of R\n| NatConst of nat\n| Add of term & term\n| Opp of term\n| NatMul of term & nat\n| Mul of term & term\n| Inv of term\n| Exp of term & nat.\n\n(**)\nInductive formula : Type :=\n| Bool of bool\n| Equal of term & term\n| Unit of term\n| And of formula & formula\n| Or of formula & formula\n| Implies of formula & formula\n| Not of formula\n| Exists of nat & formula\n| Forall of nat & formula.\n\nEnd TermDef.\n\nBind Scope term_scope with term.\nBind Scope term_scope with formula.\nArguments Add {R} t1%_T t2%_T.\nArguments Opp {R} t1%_T.\nArguments NatMul {R} t1%_T n%_N.\nArguments Mul {R} t1%_T t2%_T.\nArguments Inv {R} t1%_T.\nArguments Exp {R} t1%_T n%_N.\nArguments Equal {R} t1%_T t2%_T.\nArguments Unit {R} t1%_T.\nArguments And {R} f1%_T f2%_T.\nArguments Or {R} f1%_T f2%_T.\nArguments Implies {R} f1%_T f2%_T.\nArguments Not {R} f1%_T.\nArguments Exists {R} i%_N f1%_T.\nArguments Forall {R} i%_N f1%_T.\n\nArguments Bool {R} b.\nArguments Const {R} x.\n\n(*A notation for the formal formula representing the boolean constant true.*)\nNotation True := (Bool true).\n(*A notation for the formal formula representing the boolean constant false.*)\nNotation False := (Bool false).\n\n(*A notation for a formal variable in a term, indexed by a given natural number.*)\nLocal Notation \"''X_' i\" := (Var _ i) : term_scope.\n(*A notation for constructing a formal term that represents the ring element corresponding to a given natural number.*)\nLocal Notation \"n %:R\" := (NatConst _ n) : term_scope.\n(*A notation for constructing a formal term that represents a constant ring element.*)\nLocal Notation \"x %:T\" := (Const x) : term_scope.\n(*A notation for a formal term representing the additive identity of a ring.*)\nLocal Notation \"0\" := 0%:R%T : term_scope.\n(*A notation for a formal term representing the multiplicative identity of a ring.*)\nLocal Notation \"1\" := 1%:R%T : term_scope.\nLocal Infix \"+\" := Add : term_scope.\n(*A notation for a formal term representing the additive inverse of a given term.*)\nLocal Notation \"- t\" := (Opp t) : term_scope.\n(*A notation for a formal term representing the subtraction of two terms, defined as the sum of the first term and the additive inverse of the second.*)\nLocal Notation \"t - u\" := (Add t (- u)) : term_scope.\nLocal Infix \"*\" := Mul : term_scope.\nLocal Infix \"*+\" := NatMul : term_scope.\n(*A notation for a formal term representing the multiplicative inverse of a given term.*)\nLocal Notation \"t ^-1\" := (Inv t) : term_scope.\n(*A notation for a formal term representing the division of two terms, defined as the product of the first term and the multiplicative inverse of the second.*)\nLocal Notation \"t / u\" := (Mul t u^-1) : term_scope.\nLocal Infix \"^+\" := Exp : term_scope.\nLocal Infix \"==\" := Equal : term_scope.\nLocal Infix \"/\\\" := And : term_scope.\nLocal Infix \"\\/\" := Or : term_scope.\nLocal Infix \"==>\" := Implies : term_scope.\n(*A notation for a formal formula representing the logical negation of a given formula.*)\nLocal Notation \"~ f\" := (Not f) : term_scope.\n(*A notation for a formal formula representing the inequality of two terms, defined as the logical negation of their equality.*)\nLocal Notation \"x != y\" := (Not (x == y)) : term_scope.\n(*A notation for a formal formula representing the existential quantification of a given formula over a variable indexed by a specified natural number.*)\nLocal Notation \"''exists' ''X_' i , f\" := (Exists i f) : term_scope.\n(*A notation for a formal formula representing the universal quantification of a given formula over a variable indexed by a specified natural number.*)\nLocal Notation \"''forall' ''X_' i , f\" := (Forall i f) : term_scope.\n\nSection Substitution.\n\nVariable R : Type.\n\n(*This function substitutes a given term for all free occurrences of a variable, identified by a natural number index, within another term.*)\nFixpoint tsubst (t : term R) (s : nat * term R) :=\n match t with\n | 'X_i => if i == s.1 then s.2 else t\n | _%:T | _%:R => t\n | t1 + t2 => tsubst t1 s + tsubst t2 s\n | - t1 => - tsubst t1 s\n | t1 *+ n => tsubst t1 s *+ n\n | t1 * t2 => tsubst t1 s * tsubst t2 s\n | t1^-1 => (tsubst t1 s)^-1\n | t1 ^+ n => tsubst t1 s ^+ n\n end%T.\n\n(*This function substitutes a given term for all free occurrences of a variable, identified by a natural number index, within a formula, performing a capture-avoiding substitution with respect to quantifiers.*)\nFixpoint fsubst (f : formula R) (s : nat * term R) :=\n match f with\n | Bool _ => f\n | t1 == t2 => tsubst t1 s == tsubst t2 s\n | Unit t1 => Unit (tsubst t1 s)\n | f1 /\\ f2 => fsubst f1 s /\\ fsubst f2 s\n | f1 \\/ f2 => fsubst f1 s \\/ fsubst f2 s\n | f1 ==> f2 => fsubst f1 s ==> fsubst f2 s\n | ~ f1 => ~ fsubst f1 s\n | ('exists 'X_i, f1) => 'exists 'X_i, if i == s.1 then f1 else fsubst f1 s\n | ('forall 'X_i, f1) => 'forall 'X_i, if i == s.1 then f1 else fsubst f1 s\n end%T.\n\nEnd Substitution.\n\nSection EvalTerm.\n\nVariable R : unitRingType.\n\n(*This function computes the value of a given formal term by recursively interpreting its structure, using an environment that provides ring element values for variables and applying the corresponding ring operations.*)\nFixpoint eval (e : seq R) (t : term R) {struct t} : R :=\n match t with\n | ('X_i)%T => e`_i\n | (x%:T)%T => x\n | (n%:R)%T => n%:R\n | (t1 + t2)%T => eval e t1 + eval e t2\n | (- t1)%T => - eval e t1\n | (t1 *+ n)%T => eval e t1 *+ n\n | (t1 * t2)%T => eval e t1 * eval e t2\n | t1^-1%T => (eval e t1)^-1\n | (t1 ^+ n)%T => eval e t1 ^+ n\n end.\n\n(*This definition provides a predicate that is true if and only if two environments, represented as finite sequences of ring elements, are pointwise equal.*)\nDefinition same_env (e e' : seq R) := nth 0 e =1 nth 0 e'.\n\n(*This lemma states that evaluating a term with two different environments that are pointwise equal will produce the same ring element as a result.*)\nLemma eq_eval e e' t : same_env e e' -> eval e t = eval e' t.\n\n(*This lemma states that evaluating a term after a substitution is equivalent to evaluating the original term in an environment where the variable to be substituted is updated with the value of the substitution term.*)\nLemma eval_tsubst e t s :\n eval e (tsubst t s) = eval (set_nth 0 e s.1 (eval e s.2)) t.\n\n(*This function recursively defines the truth of a given logical formula in a given environment. It interprets boolean constants, term equality, unit membership, logical connectives like conjunction, disjunction, implication, and negation, as well as existential and universal quantifiers over the underlying ring structure.*)\nFixpoint holds (e : seq R) (f : formula R) {struct f} : Prop :=\n match f with\n | Bool b => b\n | (t1 == t2)%T => eval e t1 = eval e t2\n | Unit t1 => eval e t1 \\in unit\n | (f1 /\\ f2)%T => holds e f1 /\\ holds e f2\n | (f1 \\/ f2)%T => holds e f1 \\/ holds e f2\n | (f1 ==> f2)%T => holds e f1 -> holds e f2\n | (~ f1)%T => ~ holds e f1\n | ('exists 'X_i, f1)%T => exists x, holds (set_nth 0 e i x) f1\n | ('forall 'X_i, f1)%T => forall x, holds (set_nth 0 e i x) f1\n end.\n\n(*This lemma states that the relation indicating that two evaluation environments are equivalent is symmetric.*)\nLemma same_env_sym e e' : same_env e e' -> same_env e' e.\n\n(*This lemma states that if a logical formula holds true in a given environment, it also holds true in any other equivalent environment.*)\nLemma eq_holds e e' f : same_env e e' -> holds e f -> holds e' f.\n\n(*This lemma establishes the semantic equivalence between syntactic substitution in a formula and semantic modification of the evaluation environment. It states that a formula with a substituted value holds true if and only if the original formula holds true in an environment updated with that value for the corresponding variable.*)\nLemma holds_fsubst e f i v :\n holds e (fsubst f (i, v%:T)%T) <-> holds (set_nth 0 e i v) f.\n\n(*This function checks if a given term is a 'ring term,' which is a term that does not contain any multiplicative inverse operations. It recursively traverses the term structure, returning true if only ring operations like addition, multiplication, and negation are present.*)\nFixpoint rterm (t : term R) :=\n match t with\n | _^-1 => false\n | t1 + t2 | t1 * t2 => rterm t1 && rterm t2\n | - t1 | t1 *+ _ | t1 ^+ _ => rterm t1\n | _ => true\n end%T.\n\n(*This function determines if a given logical formula is a 'ring formula'. A formula qualifies if all its constituent terms are 'ring terms', meaning they lack multiplicative inverses, and it does not contain any predicates on units.*)\nFixpoint rformula (f : formula R) :=\n match f with\n | Bool _ => true\n | t1 == t2 => rterm t1 && rterm t2\n | Unit t1 => false\n | f1 /\\ f2 | f1 \\/ f2 | f1 ==> f2 => rformula f1 && rformula f2\n | ~ f1 | ('exists 'X__, f1) | ('forall 'X__, f1) => rformula f1\n end%T.\n\n(*This function computes an upper bound for the indices of free variables within a given term by recursively traversing the term's structure and finding the maximum index encountered, incremented by one.*)\nFixpoint ub_var (t : term R) :=\n match t with\n | 'X_i => i.+1\n | t1 + t2 | t1 * t2 => maxn (ub_var t1) (ub_var t2)\n | - t1 | t1 *+ _ | t1 ^+ _ | t1^-1 => ub_var t1\n | _ => 0%N\n end%T.\n\n(*This function converts a given term into a 'ring term' by systematically replacing every occurrence of a multiplicative inverse with a fresh variable. It returns a pair containing the transformed term and a sequence of the original subterms that were replaced.*)\nFixpoint to_rterm (t : term R) (r : seq (term R)) (n : nat) {struct t} :=\n match t with\n | t1^-1 =>\n let: (t1', r1) := to_rterm t1 r n in\n ('X_(n + size r1), rcons r1 t1')\n | t1 + t2 =>\n let: (t1', r1) := to_rterm t1 r n in\n let: (t2', r2) := to_rterm t2 r1 n in\n (t1' + t2', r2)\n | - t1 =>\n let: (t1', r1) := to_rterm t1 r n in\n (- t1', r1)\n | t1 *+ m =>\n let: (t1', r1) := to_rterm t1 r n in\n (t1' *+ m, r1)\n | t1 * t2 =>\n let: (t1', r1) := to_rterm t1 r n in\n let: (t2', r2) := to_rterm t2 r1 n in\n (Mul t1' t2', r2)\n | t1 ^+ m =>\n let: (t1', r1) := to_rterm t1 r n in\n (t1' ^+ m, r1)\n | _ => (t, r)\n end%T.\n\n(*This lemma states that if a term is already a 'ring term' because it contains no multiplicative inverses, applying the `to_rterm` conversion function to it will result in the original term and the initial accumulator sequence, indicating no transformation was performed.*)\nLemma to_rterm_id t r n : rterm t -> to_rterm t r n = (t, r).\n\n(*This definition transforms an equation of the form 'term equals zero' into an equivalent 'ring formula' that avoids multiplicative inverses. It achieves this by replacing each inverse with a fresh variable and adding quantified constraints that assert either the new variable acts as the inverse or the original subterm was not invertible.*)\nDefinition eq0_rform t1 :=\n let m := ub_var t1 in\n let: (t1', r1) := to_rterm t1 [::] m in\n let fix loop r i := match r with\n | [::] => t1' == 0\n | t :: r' =>\n let f := 'X_i * t == 1 /\\ t * 'X_i == 1 in\n 'forall 'X_i, (f \\/ 'X_i == t /\\ ~ ('exists 'X_i, f)) ==> loop r' i.+1\n end%T\n in loop r1 m.\n\n(*This function converts an arbitrary logical formula into an equivalent 'ring formula' by recursively transforming its atomic parts. It replaces equality predicates and unit predicates with their inverse-free counterparts, while preserving the logical structure of connectives and quantifiers.*)\nFixpoint to_rform f :=\n match f with\n | Bool b => f\n | t1 == t2 => eq0_rform (t1 - t2)\n | Unit t1 => eq0_rform (t1 * t1^-1 - 1)\n | f1 /\\ f2 => to_rform f1 /\\ to_rform f2\n | f1 \\/ f2 => to_rform f1 \\/ to_rform f2\n | f1 ==> f2 => to_rform f1 ==> to_rform f2\n | ~ f1 => ~ to_rform f1\n | ('exists 'X_i, f1) => 'exists 'X_i, to_rform f1\n | ('forall 'X_i, f1) => 'forall 'X_i, to_rform f1\n end%T.\n\n(*This lemma asserts that applying the `to_rform` transformation to any given formula always produces a valid 'ring formula'.*)\nLemma to_rform_rformula f : rformula (to_rform f).\n\n(*This lemma states that the transformation of a formula into its 'ring formula' equivalent preserves its truth value, meaning the original formula holds in a given environment if and only if the transformed formula also holds in that same environment.*)\nLemma to_rformP e f : holds e (to_rform f) <-> holds e f.\n\n(*This function checks whether a given logical formula is quantifier-free, returning true if the formula is built only from atomic propositions and logical connectives without any universal or existential quantifiers.*)\nFixpoint qf_form (f : formula R) :=\n match f with\n | Bool _ | _ == _ | Unit _ => true\n | f1 /\\ f2 | f1 \\/ f2 | f1 ==> f2 => qf_form f1 && qf_form f2\n | ~ f1 => qf_form f1\n | _ => false\n end%T.\n\n(*This function provides a computable evaluation for a quantifier-free formula within a given environment. It recursively computes a boolean truth value by interpreting atomic formulas and logical connectives using boolean operations, returning false for any formula containing quantifiers.*)\nDefinition qf_eval e := fix loop (f : formula R) : bool :=\n match f with\n | Bool b => b\n | t1 == t2 => (eval e t1 == eval e t2)%bool\n | Unit t1 => eval e t1 \\in unit\n | f1 /\\ f2 => loop f1 && loop f2\n | f1 \\/ f2 => loop f1 || loop f2\n | f1 ==> f2 => (loop f1 ==> loop f2)%bool\n | ~ f1 => ~~ loop f1\n |_ => false\n end%T.\n\n(*This lemma states that for any quantifier-free formula, the boolean result of its computable evaluation via `qf_eval` correctly reflects its propositional truth value as defined by the `holds` predicate.*)\nLemma qf_evalP e f : qf_form f -> reflect (holds e f) (qf_eval e f).\n\nImplicit Type bc : seq (term R) * seq (term R).\n\n(*This definition computes the disjunctive normal form (DNF) of a conjunction of two formulas, where each input formula is already represented as a list of DNF clauses. The resulting DNF is formed by taking the cross-product of the clauses from both inputs, concatenating the positive and negative literals of each pair to form new clauses.*)\nDefinition and_dnf bcs1 bcs2 :=\n \\big[cat/nil]_(bc1 <- bcs1)\n map (fun bc2 => (bc1.1 ++ bc2.1, bc1.2 ++ bc2.2)) bcs2.\n\n(*This function recursively converts a quantifier-free formula into its disjunctive normal form (DNF), represented as a list of clauses. A boolean flag indicates whether to convert the formula itself or its negation, allowing for the correct application of De Morgan's laws and distributive properties during the transformation.*)\nFixpoint qf_to_dnf (f : formula R) (neg : bool) {struct f} :=\n match f with\n | Bool b => if b (+) neg then [:: ([::], [::])] else [::]\n | t1 == t2 => [:: if neg then ([::], [:: t1 - t2]) else ([:: t1 - t2], [::])]\n | f1 /\\ f2 => (if neg then cat else and_dnf) [rec f1, neg] [rec f2, neg]\n | f1 \\/ f2 => (if neg then and_dnf else cat) [rec f1, neg] [rec f2, neg]\n | f1 ==> f2 => (if neg then and_dnf else cat) [rec f1, ~~ neg] [rec f2, neg]\n | ~ f1 => [rec f1, ~~ neg]\n | _ => if neg then [:: ([::], [::])] else [::]\n end%T where \"[ 'rec' f , neg ]\" := (qf_to_dnf f neg).\n\n(*This definition converts a formula represented in disjunctive normal form, as a list of clauses, back into a standard formula object. It constructs a conjunction of atomic predicates for each clause, using equalities for positive literals and inequalities for negative literals, and then combines these clauses using disjunction.*)\nDefinition dnf_to_form :=\n let pos_lit t := And (t == 0) in let neg_lit t := And (t != 0) in\n let cls bc := Or (foldr pos_lit True bc.1 /\\ foldr neg_lit True bc.2) in\n foldr cls False.\n\n(*This lemma states that the computable evaluation of a formula constructed from the concatenation of two disjunctive normal form (DNF) representations is equivalent to the evaluation of the disjunction of the two formulas constructed from the individual DNF representations.*)\nLemma cat_dnfP e bcs1 bcs2 :\n qf_eval e (dnf_to_form (bcs1 ++ bcs2))\n = qf_eval e (dnf_to_form bcs1 \\/ dnf_to_form bcs2).\n\n(*This lemma states that the computable evaluation of a formula constructed from the `and_dnf` operation on two disjunctive normal form (DNF) representations is equivalent to the evaluation of the conjunction of the two formulas constructed from the individual DNF representations.*)\nLemma and_dnfP e bcs1 bcs2 :\n qf_eval e (dnf_to_form (and_dnf bcs1 bcs2))\n = qf_eval e (dnf_to_form bcs1 /\\ dnf_to_form bcs2).\n\n(*This lemma guarantees the correctness of the quantifier-free to disjunctive normal form (DNF) conversion. It states that for any quantifier-free 'ring formula', its computable evaluation is identical to the computable evaluation of the formula constructed from its generated DNF representation.*)\nLemma qf_to_dnfP e :\n let qev f b := qf_eval e (dnf_to_form (qf_to_dnf f b)) in\n forall f, qf_form f && rformula f -> qev f false = qf_eval e f.\n\n(*This lemma states that any formula constructed from a disjunctive normal form representation using the `dnf_to_form` function is guaranteed to be quantifier-free.*)\nLemma dnf_to_form_qf bcs : qf_form (dnf_to_form bcs).\n\n(*This definition checks if a clause in disjunctive normal form consists entirely of 'ring terms' by verifying that every term in both its positive and negative literal lists satisfies the `rterm` predicate.*)\nDefinition dnf_rterm cl := all rterm cl.1 && all rterm cl.2.\n\n(*This lemma states that if a given formula is a 'ring formula,' then converting it to disjunctive normal form will produce a list of clauses where every term within every clause is also a 'ring term'.*)\nLemma qf_to_dnf_rterm f b : rformula f -> all dnf_rterm (qf_to_dnf f b).\n\n(*This lemma establishes that a formula constructed from a disjunctive normal form representation is a 'ring formula' if and only if every term within every clause of that representation is a 'ring term'.*)\nLemma dnf_to_rform bcs : rformula (dnf_to_form bcs) = all dnf_rterm bcs.\n\nSection If.\n\nVariables (pred_f then_f else_f : formula R).\n\n(*This definition represents a conditional formula, equivalent to an if-then-else statement. It is defined as the disjunction of two conjunctions: the first combining the predicate formula with the 'then' formula, and the second combining the negation of the predicate formula with the 'else' formula.*)\nDefinition If := (pred_f /\\ then_f \\/ ~ pred_f /\\ else_f)%T.\n\n(*This lemma states that if the predicate, 'then', and 'else' components of a conditional formula are all quantifier-free, then the resulting conditional formula is also quantifier-free.*)\nLemma If_form_qf :\n qf_form pred_f -> qf_form then_f -> qf_form else_f -> qf_form If.\n\n(*This lemma states that if the predicate, 'then', and 'else' components of a conditional formula are all 'ring formulas,' then the resulting conditional formula is also a 'ring formula'.*)\nLemma If_form_rf :\n rformula pred_f -> rformula then_f -> rformula else_f -> rformula If.\n\n(*This lemma states that evaluating an 'If' formula within a given environment is equivalent to first evaluating the condition formula, and then, based on the resulting boolean value, evaluating either the 'then' branch formula or the 'else' branch formula.*)\nLemma eval_If e :\n let ev := qf_eval e in ev If = (if ev pred_f then ev then_f else ev else_f).\n\nEnd If.\n\nSection Pick.\n\nVariables (I : finType) (pred_f then_f : I -> formula R) (else_f : formula R).\n\n(*This definition constructs a formula that is logically equivalent to checking if there is a unique index for which a given predicate formula holds. If such a unique index exists, the constructed formula evaluates to a corresponding 'then' formula; otherwise, it evaluates to an 'else' formula.*)\nDefinition Pick :=\n \\big[Or/False]_(p : {ffun pred I})\n ((\\big[And/True]_i (if p i then pred_f i else ~ pred_f i))\n /\\ (if pick p is Some i then then_f i else else_f))%T.\n\n(*This lemma states that if a family of predicate formulas, a corresponding family of 'then' formulas, and an 'else' formula are all quantifier-free, then the 'Pick' formula constructed from them is also quantifier-free.*)\nLemma Pick_form_qf :\n (forall i, qf_form (pred_f i)) ->\n (forall i, qf_form (then_f i)) ->\n qf_form else_f ->\n qf_form Pick.\n\n(*This lemma states that evaluating a 'Pick' formula in a given environment is equivalent to first evaluating the predicate formulas for all indices to obtain a boolean predicate, then checking if this predicate holds for a unique index. If a unique index is found, the result is the evaluation of the corresponding 'then' formula; otherwise, it is the evaluation of the 'else' formula.*)\nLemma eval_Pick e (qev := qf_eval e) :\n let P i := qev (pred_f i) in\n qev Pick = (if pick P is Some i then qev (then_f i) else qev else_f).\n\nEnd Pick.\n\nSection MultiQuant.\n\nVariable f : formula R.\nImplicit Types (I : seq nat) (e : seq R).\n\n(*This lemma states that for a given formula, a sequence of natural numbers, and an environment, the existence of a modified environment that satisfies the formula and differs from the original only on variables corresponding to the given sequence is logically equivalent to the original environment satisfying the formula with chained existential quantifiers over those variables.*)\nLemma foldExistsP I e :\n (exists2 e', {in [predC I], same_env e e'} & holds e' f)\n <-> holds e (foldr Exists f I).\n\n(*This lemma states that for a given formula, a sequence of natural numbers, and an environment, the property that the formula holds in all modified environments that differ from the original only on variables corresponding to the given sequence is logically equivalent to the original environment satisfying the formula with chained universal quantifiers over those variables.*)\nLemma foldForallP I e :\n (forall e', {in [predC I], same_env e e'} -> holds e' f)\n <-> holds e (foldr Forall f I).\n\nEnd MultiQuant.\n\nEnd EvalTerm.\n\nPrenex Implicits dnf_rterm.\n\n(*This definition specifies the axiom for an integral domain, which asserts that for any two ring elements, if their product is equal to zero, then at least one of the elements must be zero.*)\nDefinition integral_domain_axiom (R : pzRingType) :=\n forall x y : R, x * y = 0 -> (x == 0) || (y == 0).\n\n(*This record defines a mixin that endows a commutative unit ring with the property of being an integral domain by requiring a proof of the integral domain axiom.*)\nHB.mixin Record ComUnitRing_isIntegral R of ComUnitRing R := {\n mulf_eq0_subproof : integral_domain_axiom R;\n}.\n\n#[mathcomp(axiom=\"integral_domain_axiom\"), short(type=\"idomainType\")]\n(*This definition establishes the structure for an integral domain, which is a commutative unit ring satisfying the integral domain axiom.*)\nHB.structure Definition IntegralDomain :=\n {R of ComUnitRing_isIntegral R & ComUnitRing R}.\n\nModule IntegralDomainExports.\nBind Scope ring_scope with IntegralDomain.sort.\nEnd IntegralDomainExports.\nHB.export IntegralDomainExports.\n\nSection IntegralDomainTheory.\n\nVariable R : idomainType.\nImplicit Types x y : R.\n\n(*This lemma states that in an integral domain, the statement that the product of two elements is zero is equivalent to the statement that at least one of the elements is zero.*)\nLemma mulf_eq0 x y : (x * y == 0) = (x == 0) || (y == 0).\n\n(*This lemma states that in an integral domain, a finite product of elements over a predicate is equal to zero if and only if there exists at least one element in the product that is zero.*)\nLemma prodf_eq0 (I : finType) (P : pred I) (F : I -> R) :\n reflect (exists2 i, P i & (F i == 0)) (\\prod_(i | P i) F i == 0).\n\n(*This lemma states that in an integral domain, the product of a function's values over the elements of a sequence that satisfy a given predicate is zero if and only if the sequence contains an element for which the predicate is true and the function's value is zero.*)\nLemma prodf_seq_eq0 I r (P : pred I) (F : I -> R) :\n (\\prod_(i <- r | P i) F i == 0) = has (fun i => P i && (F i == 0)) r.\n\n(*This lemma states that in an integral domain, the product of two non-zero elements is also non-zero.*)\nLemma mulf_neq0 x y : x != 0 -> y != 0 -> x * y != 0.\n\n(*This lemma states that in an integral domain, a finite product of elements over a predicate is non-zero if and only if all elements contributing to the product are non-zero.*)\nLemma prodf_neq0 (I : finType) (P : pred I) (F : I -> R) :\n reflect (forall i, P i -> (F i != 0)) (\\prod_(i | P i) F i != 0).\n\n(*This lemma states that in an integral domain, the product of a function's values over elements of a sequence satisfying a predicate is non-zero if and only if the function's value is non-zero for all elements in the sequence that satisfy the predicate.*)\nLemma prodf_seq_neq0 I r (P : pred I) (F : I -> R) :\n (\\prod_(i <- r | P i) F i != 0) = all (fun i => P i ==> (F i != 0)) r.\n\n(*This lemma states that in an integral domain, an element raised to a natural number power is zero if and only if the base element is zero and the exponent is a positive number.*)\nLemma expf_eq0 x n : (x ^+ n == 0) = (n > 0) && (x == 0).\n\n(*This lemma states that in an integral domain, the square of an element is zero if and only if the element itself is zero.*)\nLemma sqrf_eq0 x : (x ^+ 2 == 0) = (x == 0). \n\n(*This lemma states that in an integral domain, raising a non-zero element to any natural number power results in a non-zero value.*)\nLemma expf_neq0 x m : x != 0 -> x ^+ m != 0.\n\n(*This lemma states that the ring embedding of a natural number is non-zero if and only if the number is not a multiple of the ring's characteristic, when the characteristic is positive.*)\nLemma natf_neq0_pchar n : (n%:R != 0 :> R) = (pchar R)^'.-nat n.\n\n(*This lemma states that if the ring representation of a positive natural number is zero, then the integral domain must have a positive characteristic.*)\nLemma natf0_pchar n : n > 0 -> n%:R == 0 :> R -> exists p, p \\in pchar R.\n\n(*This lemma provides a rewrite rule, stating that a boolean predicate on a natural number, related to the ring's characteristic, is equivalent to the condition that the ring image of that natural number is non-zero.*)\nLemma pcharf'_nat n : (pchar R)^'.-nat n = (n%:R != 0 :> R).\n\n(*This lemma establishes an equivalence: an integral domain has characteristic zero if and only if the embedding of a natural number into the ring is zero precisely when the natural number is zero.*)\nLemma pcharf0P : pchar R =i pred0 <-> (forall n, (n%:R == 0 :> R) = (n == 0)%N).\n\n(*This lemma states that in an integral domain, the squares of two elements are equal if and only if the elements are equal or one is the additive inverse of the other.*)\nLemma eqf_sqr x y : (x ^+ 2 == y ^+ 2) = (x == y) || (x == - y).\n\n(*This lemma asserts that for any non-zero element in an integral domain, the function that multiplies other elements by it is injective.*)\nLemma mulfI x : x != 0 -> injective ( *%R x).\n\n(*This lemma asserts that for any non-zero element in an integral domain, the function that right-multiplies other elements by it is injective.*)\nLemma mulIf x : x != 0 -> injective ( *%R^~ x).\n\n(*This lemma states that for any non-zero numerator in an integral domain, the division function with that fixed numerator is injective with respect to its denominator.*)\nLemma divfI x : x != 0 -> injective (fun y => x / y).\n\n(*This lemma states that for any non-zero denominator in an integral domain, the division function with that fixed denominator is injective with respect to its numerator.*)\nLemma divIf y : y != 0 -> injective (fun x => x / y).\n\n(*This lemma states that in an integral domain, the square of an element is equal to one if and only if the element is either one or its additive inverse, minus one.*)\nLemma sqrf_eq1 x : (x ^+ 2 == 1) = (x == 1) || (x == -1).\n\n(*This lemma provides an equivalence for an element raised to a positive power being equal to one. It states this is true if and only if either the element itself is one, or the sum of its powers from zero up to the exponent minus one is equal to zero.*)\nLemma expfS_eq1 x n :\n (x ^+ n.+1 == 1) = (x == 1) || (\\sum_(i < n.+1) x ^+ i == 0).\n\n(*This lemma states that in an integral domain, an element is left-regular for multiplication, meaning it can be canceled from the left side of an equation, if and only if that element is non-zero.*)\nLemma lregP x : reflect (lreg x) (x != 0).\n\n(*This lemma states that an element in an integral domain is right-regular if and only if it is not equal to zero.*)\nLemma rregP x : reflect (rreg x) (x != 0).\n\n#[export]\n(*This is a deprecated notation, which serves as a parsing-only alias for natf_neq0_pchar.*)\nNotation natf_neq0 := natf_neq0_pchar (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use natf0_pchar instead.\")]\n(*This is a deprecated notation, which serves as a parsing-only alias for natf0_pchar.*)\nNotation natf0_char := natf0_pchar (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf'_nat instead.\")]\n(*This is a deprecated notation, which serves as a parsing-only alias for pcharf'_nat.*)\nNotation charf'_nat := pcharf'_nat (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf0P instead.\")]\n(*This is a deprecated notation, which serves as a parsing-only alias for pcharf0P.*)\nNotation charf0P := pcharf0P (only parsing).\n\nArguments lregP {R x}.\nArguments rregP {R x}.\n\n(*This definition specifies the axiom for a field, which states that every non-zero element in a unit ring has a multiplicative inverse.*)\nDefinition field_axiom (R : unitRingType) := forall x : R, x != 0 -> x \\in unit.\n\n(*This record defines a mixin that extends a unit ring structure with the property of being a field, requiring a proof that every non-zero element is a unit.*)\nHB.mixin Record UnitRing_isField R of UnitRing R := {\n fieldP : field_axiom R;\n}.\n\n#[mathcomp(axiom=\"field_axiom\"), short(type=\"fieldType\")]\n(*This declaration defines the structure for a field, combining the properties of an integral domain with the axiom that every non-zero element is invertible.*)\nHB.structure Definition Field := { R of IntegralDomain R & UnitRing_isField R }.\n\nModule FieldExports.\nBind Scope ring_scope with Field.sort.\nEnd FieldExports.\nHB.export FieldExports.\n\n(*This instance declares that the opposite ring of any field is a regular ring.*)\n#[export] HB.instance Definition regular_field (F : fieldType) := Field.on F^o.\n\n(*This lemma states that for any unit ring, the field axiom implies the integral domain axiom, meaning that if all non-zero elements are invertible, then the ring has no non-zero zero-divisors.*)\nLemma IdomainMixin (R : unitRingType): Field.axiom R -> IntegralDomain.axiom R.\n\n(*This record defines a factory for constructing a field structure from a commutative unit ring by providing a proof that every non-zero element is a unit.*)\nHB.factory Record ComUnitRing_isField R of ComUnitRing R := {\n fieldP : field_axiom R;\n}.\nHB.builders Context R of ComUnitRing_isField R.\nHB.instance Definition _ :=\n ComUnitRing_isIntegral.Build R (IdomainMixin fieldP).\nHB.instance Definition _ := UnitRing_isField.Build R fieldP.\nHB.end.\n\n(*This record defines a factory for constructing a field structure from a commutative non-zero ring, requiring an inverse function, a proof that this function provides a multiplicative inverse for any non-zero element, and a proof that the inverse of zero is zero.*)\nHB.factory Record ComNzRing_isField R of ComNzRing R := {\n inv : R -> R;\n mulVf : forall x, x != 0 -> inv x * x = 1;\n invr0 : inv 0 = 0;\n}.\n\nModule ComRing_isField.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzRing_isField.Build instead.\")]\nNotation Build R := (ComNzRing_isField.Build R) (only parsing).\nEnd ComRing_isField.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ComNzRing_isField instead.\")]\nNotation ComRing_isField R := (ComNzRing_isField R) (only parsing).\n\nHB.builders Context R of ComNzRing_isField R.\n\n(*This fact states that if an element in a commutative non-zero ring has a left multiplicative inverse, then that element cannot be zero.*)\nFact intro_unit (x y : R) : y * x = 1 -> x != 0.\n\n(*This fact states that the inverse of the zero element is zero itself, which is equivalent to the identity function applied to zero.*)\nFact inv_out : {in predC (predC1 0), inv =1 id}.\n\nHB.instance Definition _ : ComNzRing_hasMulInverse R :=\n ComNzRing_hasMulInverse.Build R mulVf intro_unit inv_out.\n\nHB.instance Definition _ : ComUnitRing_isField R :=\n ComUnitRing_isField.Build R (fun x x_neq_0 => x_neq_0).\n\nHB.end.\n\nSection FieldTheory.\n\nVariable F : fieldType.\nImplicit Types x y : F.\n\n(*This lemma states that for any element in a field, being a unit is equivalent to being non-zero.*)\nLemma unitfE x : (x \\in unit) = (x != 0).\n\n(*This lemma states that for any non-zero element in a field, the product of its multiplicative inverse and the element itself is equal to one.*)\nLemma mulVf x : x != 0 -> x^-1 * x = 1.\n\n(*This lemma states that any non-zero element in a field divided by itself equals one.*)\nLemma divff x : x != 0 -> x / x = 1.\n\n(*This definition provides an alias for the lemma stating that a non-zero element multiplied by its inverse is one.*)\nDefinition mulfV := divff.\n(*This lemma asserts that for any non-zero element in a field, right multiplication by its inverse is a left inverse to right multiplication by the element itself.*)\nLemma mulKf x : x != 0 -> cancel ( *%R x) ( *%R x^-1).\n\n(*This lemma asserts that for any non-zero element in a field, right multiplication by that element is a left inverse to right multiplication by its inverse.*)\nLemma mulVKf x : x != 0 -> cancel ( *%R x^-1) ( *%R x).\n\n(*This lemma asserts that for any non-zero element in a field, left multiplication by its inverse is a left inverse to left multiplication by the element itself.*)\nLemma mulfK x : x != 0 -> cancel ( *%R^~ x) ( *%R^~ x^-1).\n\n(*This lemma asserts that for any non-zero element in a field, left multiplication by that element is a left inverse to left multiplication by its inverse.*)\nLemma mulfVK x : x != 0 -> cancel ( *%R^~ x^-1) ( *%R^~ x).\n\n(*This definition provides an alias for the lemma stating that left multiplication by a non-zero element cancels with left multiplication by its inverse.*)\nDefinition divfK := mulfVK.\n\n(*This lemma states that the multiplicative inverse function is a morphism with respect to multiplication, meaning the inverse of a product of two elements is the product of their inverses.*)\nLemma invfM : {morph @inv F : x y / x * y}.\n\n(*This lemma states that the multiplicative inverse of a division of two elements is equivalent to the division of the denominator by the numerator.*)\nLemma invf_div x y : (x / y)^-1 = y / x.\n\n(*This lemma states that for any non-zero element, the function that divides this element by its input is an involution, meaning applying the function twice returns the original input.*)\nLemma divKf x : x != 0 -> involutive (fun y => x / y).\n\n(*This lemma provides a rule for subtracting exponents, stating that a base raised to a difference of natural numbers equals the division of the powers, under a condition that prevents division by zero, especially when the base is zero.*)\nLemma expfB_cond m n x : (x == 0) + n <= m -> x ^+ (m - n) = x ^+ m / x ^+ n.\n\n(*This lemma states that for a base element in a field, the power of a difference of two natural numbers, where the first is greater than the second, is equal to the division of the base raised to the first number by the base raised to the second number.*)\nLemma expfB m n x : n < m -> x ^+ (m - n) = x ^+ m / x ^+ n.\n\n(*This lemma states that for a finite sequence of elements in a field, the product of their multiplicative inverses is equal to the multiplicative inverse of their product.*)\nLemma prodfV I r (P : pred I) (E : I -> F) :\n \\prod_(i <- r | P i) (E i)^-1 = (\\prod_(i <- r | P i) E i)^-1.\n\n(*This lemma states that the product of a sequence of divisions is equal to the division of the product of the numerators by the product of the denominators.*)\nLemma prodf_div I r (P : pred I) (E D : I -> F) :\n \\prod_(i <- r | P i) (E i / D i) =\n \\prod_(i <- r | P i) E i / \\prod_(i <- r | P i) D i.\n\n(*This lemma states that for a function from natural numbers to a field, the product of the ratios of successive function values over a range of natural numbers simplifies to the ratio of the function value at the end of the range to the function value at the start, provided the function is non-zero at intermediate points.*)\nLemma telescope_prodf n m (f : nat -> F) :\n (forall k, n < k < m -> f k != 0) -> n < m ->\n \\prod_(n <= k < m) (f k.+1 / f k) = f m / f n.\n\n(*This lemma states that if a function is defined over a range of natural numbers as the ratio of successive values of another function, then the product of the values of the first function over that range is equal to the ratio of the values of the second function at the endpoints of the range, assuming the second function is non-zero at intermediate points.*)\nLemma telescope_prodf_eq n m (f u : nat -> F) :\n (forall k, n < k < m -> f k != 0) -> n < m ->\n (forall k, n <= k < m -> u k = f k.+1 / f k) ->\n \\prod_(n <= k < m) u k = f m / f n.\n\n(*This lemma states that the sum of two fractions in a field is equal to the fraction whose numerator is the sum of the cross-products of the numerators and denominators, and whose denominator is the product of the original denominators, provided both original denominators are non-zero.*)\nLemma addf_div x1 y1 x2 y2 :\n y1 != 0 -> y2 != 0 -> x1 / y1 + x2 / y2 = (x1 * y2 + x2 * y1) / (y1 * y2).\n\n(*This lemma states that the product of two fractions in a field is equal to the fraction formed by multiplying their numerators and multiplying their denominators.*)\nLemma mulf_div x1 y1 x2 y2 : (x1 / y1) * (x2 / y2) = (x1 * x2) / (y1 * y2).\n\n(*This lemma states that the equality of two fractions in a field is equivalent to the equality of their cross-products, provided the denominators are non-zero.*)\nLemma eqr_div x y z t : y != 0 -> t != 0 -> (x / y == z / t) = (x * t == z * y).\n\n(*This lemma states that an equality asserting that the sum of a sequence of fractions, all sharing a common non-zero denominator, is equal to a certain value, is equivalent to an equality asserting that the sum of the numerators is equal to the product of that value and the common denominator.*)\nLemma eqr_sum_div I r P (f : I -> F) c a : c != 0 ->\n \\big[+%R/0]_(x <- r | P x) (f x / c) == a\n = (\\big[+%R/0]_(x <- r | P x) f x == a * c).\n\n(*This lemma states that in a field of characteristic zero, for any two natural numbers where the second divides the first, the injection of their natural number quotient into the field is equal to the field division of their respective injections.*)\nLemma pchar0_natf_div :\n pchar F =i pred0 -> forall m d, d %| m -> (m %/ d)%:R = m%:R / d%:R :> F.\n\nSection FieldMorphismInj.\n\nVariables (R : nzRingType) (f : {rmorphism F -> R}).\n\n(*This lemma states that a ring morphism from a field to a non-zero ring maps an element to the zero element if and only if the original element is zero.*)\nLemma fmorph_eq0 x : (f x == 0) = (x == 0).\n\n(*This lemma states that any ring morphism from a field to a non-zero ring is an injective function.*)\nLemma fmorph_inj : injective f.\n\n(*This lemma states that for a ring morphism from a field to a non-zero ring, two elements are equal if and only if their images under the morphism are equal.*)\nLemma fmorph_eq : {mono f : x y / x == y}.\n\n(*This lemma states that for a ring morphism from a field to a non-zero ring, the image of an element is the multiplicative identity if and only if the element itself is the multiplicative identity.*)\nLemma fmorph_eq1 x : (f x == 1) = (x == 1).\n\n(*This lemma states that if there exists a ring morphism from a field to a non-zero ring, then the two rings must have the same characteristic.*)\nLemma fmorph_pchar : pchar R =i pchar F.\n\nEnd FieldMorphismInj.\n\nSection FieldMorphismInv.\n\nVariables (R : unitRingType) (f : {rmorphism F -> R}).\n\n(*This lemma states that for a ring morphism from a field to a unit ring, the image of an element is a unit if and only if the original element is non-zero.*)\nLemma fmorph_unit x : (f x \\in unit) = (x != 0).\n\n(*This lemma states that a ring morphism from a field to a unit ring preserves multiplicative inverses for all non-zero elements.*)\nLemma fmorphV : {morph f: x / x^-1}.\n\n(*This lemma states that a ring morphism from a field to a unit ring preserves division.*)\nLemma fmorph_div : {morph f : x y / x / y}.\n\nEnd FieldMorphismInv.\n\nSection ModuleTheory.\n\nVariable V : lmodType F.\nImplicit Types (a : F) (v : V).\n\n(*This lemma states that in a module over a field, for any non-zero scalar, the operation of scalar multiplication by its multiplicative inverse is the left inverse of the operation of scalar multiplication by the scalar itself.*)\nLemma scalerK a : a != 0 -> cancel ( *:%R a : V -> V) ( *:%R a^-1).\n\n(*This lemma states that in a module over a field, for any non-zero scalar, the operation of scalar multiplication by its multiplicative inverse is the right inverse of the operation of scalar multiplication by the scalar itself.*)\nLemma scalerKV a : a != 0 -> cancel ( *:%R a^-1 : V -> V) ( *:%R a).\n\n(*This lemma states that in a module over a field, scalar multiplication by any non-zero scalar is an injective function.*)\nLemma scalerI a : a != 0 -> injective ( *:%R a : V -> V).\n\n(*This lemma states that in a module over a field, the scalar product of a scalar and a vector is the zero vector if and only if the scalar is zero or the vector is the zero vector.*)\nLemma scaler_eq0 a v : (a *: v == 0) = (a == 0) || (v == 0).\n\nEnd ModuleTheory.\n\n(*This lemma states that any linear algebra over a field has the same characteristic as the underlying field.*)\nLemma pchar_lalg (A : lalgType F) : pchar A =i pchar F.\n\nEnd FieldTheory.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar0_natf_div instead.\")]\n(*This is a deprecated notation, now aliased to pchar0_natf_div, which states that in a field of characteristic zero, the injection of a natural number quotient into the field is equal to the field division of their respective injections.*)\nNotation char0_natf_div := pchar0_natf_div (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use fmorph_pchar instead.\")]\n(*This is a deprecated notation, now aliased to fmorph_pchar, which states that if there exists a ring morphism from a field to a non-zero ring, then the two rings must have the same characteristic.*)\nNotation fmorph_char := fmorph_pchar (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar_lalg instead.\")]\n(*This is a deprecated notation, now aliased to pchar_lalg, which states that any linear algebra over a field has the same characteristic as the underlying field.*)\nNotation char_lalg := pchar_lalg (only parsing).\n\nArguments fmorph_inj {F R} f [x1 x2].\nArguments telescope_prodf_eq {F n m} f u.\n\n(*This definition specifies the axiom for a decidable field, which requires the existence of a decision procedure that can determine the truth of any first-order formula over the ring for a given assignment of values to its free variables.*)\nDefinition decidable_field_axiom (R : unitRingType)\n (s : seq R -> pred (formula R)) :=\n forall e f, reflect (holds e f) (s e f).\n\n(*This record defines a mixin for a unit ring that endows it with the properties of a decidable field, namely a satisfaction checker for first-order formulas and a proof that this checker is correct.*)\nHB.mixin Record Field_isDecField R of UnitRing R := {\n sat : seq R -> pred (formula R);\n satP : decidable_field_axiom sat;\n}.\n\n#[mathcomp(axiom=\"decidable_field_axiom\"), short(type=\"decFieldType\")]\n(*This definition introduces the structure for a decidable field, which combines the algebraic properties of a field with a decision procedure for its first-order theory.*)\nHB.structure Definition DecidableField := { F of Field F & Field_isDecField F }.\n\nModule DecFieldExports.\nBind Scope ring_scope with DecidableField.sort.\nEnd DecFieldExports.\nHB.export DecFieldExports.\n\n#[export] HB.instance Definition _ (F : decFieldType) := DecidableField.on F^o.\n\nSection DecidableFieldTheory.\n\nVariable F : decFieldType.\nImplicit Type f : formula F.\n\n(*This fact establishes that the satisfaction checker, when applied to a formula that existentially quantifies over a specified number of variables, correctly reflects the existence of a sequence of field elements of that specific size which satisfies the original formula.*)\nFact sol_subproof n f :\n reflect (exists s, (size s == n) && sat s f)\n (sat [::] (foldr Exists f (iota 0 n))).\n\n(*This definition creates a function that, given a natural number and a formula, returns a sequence of field elements that satisfies the formula if such a sequence exists; otherwise, it returns a sequence of zeros of the same length.*)\nDefinition sol n f :=\n if sol_subproof n f is ReflectT sP then xchoose sP else nseq n 0.\n\n(*This lemma states that the length of the sequence of field elements returned by the solution-finding function 'sol' for a given number is always equal to that number.*)\nLemma size_sol n f : size (sol n f) = n.\n\n(*This lemma states that the satisfaction checker correctly determines whether the sequence returned by the solution-finding function 'sol' is a valid solution, by reflecting the existence of a satisfying sequence of the specified size.*)\nLemma solP n f : reflect (exists2 s, size s = n & holds s f) (sat (sol n f) f).\n\n(*This lemma states that if two field formulas are logically equivalent, meaning they hold for exactly the same environments, then their sets of satisfying assignments are equal.*)\nLemma eq_sat f1 f2 :\n (forall e, holds e f1 <-> holds e f2) -> sat^~ f1 =1 sat^~ f2.\n\n(*This lemma states that if two field formulas are logically equivalent, holding for the same environments, then their sets of solutions are equal.*)\nLemma eq_sol f1 f2 :\n (forall e, holds e f1 <-> holds e f2) -> sol^~ f1 =1 sol^~ f2.\n\nEnd DecidableFieldTheory.\n\nArguments satP {F e f} : rename.\nArguments solP {F n f} : rename.\n\nSection QE_Mixin.\n\nVariable F : Field.type.\nImplicit Type f : formula F.\n\nVariable proj : nat -> seq (term F) * seq (term F) -> formula F.\n\n(*This definition specifies the well-formedness property for a quantifier elimination projection function. It requires that for any given variable index and a disjunctive normal form term, the projection function must produce a formula that is both quantifier-free and a well-formed renewable formula.*)\nDefinition wf_QE_proj :=\n forall i bc (bc_i := proj i bc),\n dnf_rterm bc -> qf_form bc_i && rformula bc_i.\n\n(*This definition specifies the validity property for a quantifier elimination projection function. It requires that for any variable index and a disjunctive normal form term, evaluating the projected quantifier-free formula in a given environment must be logically equivalent to the truth of the original existentially quantified formula in that same environment.*)\nDefinition valid_QE_proj :=\n forall i bc (ex_i_bc := ('exists 'X_i, dnf_to_form [:: bc])%T) e,\n dnf_rterm bc -> reflect (holds e ex_i_bc) (qf_eval e (proj i bc)).\n\nHypotheses (wf_proj : wf_QE_proj) (ok_proj : valid_QE_proj).\n\n(*This definition specifies an auxiliary function for quantifier elimination. It takes a quantifier-free formula and a variable index, converts the formula to disjunctive normal form, applies a projection function to each clause to eliminate the specified variable, and then combines the resulting formulas with logical disjunction.*)\nLet elim_aux f n := foldr Or False (map (proj n) (qf_to_dnf f false)).\n\n(*This recursive definition specifies a function that eliminates quantifiers from a given formula over a field. It processes the formula's structure, applying a specialized elimination step for existential and universal quantifiers, and recursively handling logical connectives, ultimately producing an equivalent quantifier-free formula.*)\nFixpoint quantifier_elim f :=\n match f with\n | f1 /\\ f2 => (quantifier_elim f1) /\\ (quantifier_elim f2)\n | f1 \\/ f2 => (quantifier_elim f1) \\/ (quantifier_elim f2)\n | f1 ==> f2 => (~ quantifier_elim f1) \\/ (quantifier_elim f2)\n | ~ f => ~ quantifier_elim f\n | ('exists 'X_n, f) => elim_aux (quantifier_elim f) n\n | ('forall 'X_n, f) => ~ elim_aux (~ quantifier_elim f) n\n | _ => f\n end%T.\n\n(*This lemma states that if a given formula is a renewable formula, then applying the quantifier elimination function to it results in a new formula that is both quantifier-free and a renewable formula.*)\nLemma quantifier_elim_wf f :\n let qf := quantifier_elim f in rformula f -> qf_form qf && rformula qf.\n\n(*This lemma states that for any renewable formula and any environment, the original formula holds true in that environment if and only if the evaluation of the equivalent quantifier-free formula produced by quantifier elimination is true.*)\nLemma quantifier_elim_rformP e f :\n rformula f -> reflect (holds e f) (qf_eval e (quantifier_elim f)).\n\n(*This definition specifies a satisfiability checker for a field formula in a given environment. It operates by first converting the formula to a renewable form, then applying quantifier elimination to produce a quantifier-free equivalent, and finally evaluating that resulting formula.*)\nDefinition proj_sat e f := qf_eval e (quantifier_elim (to_rform f)).\n\n(*This lemma states that the satisfiability checker based on quantifier elimination correctly implements the axiom required for a decidable field, confirming it as a valid decision procedure.*)\nLemma proj_satP : DecidableField.axiom proj_sat.\n\nEnd QE_Mixin.\n\n(*This record defines a factory for constructing a decidable field from a given field, provided one supplies a quantifier elimination projection function along with proofs of its well-formedness and validity.*)\nHB.factory Record Field_QE_isDecField F of Field F := {\n proj : nat -> seq (term F) * seq (term F) -> formula F;\n wf_proj : wf_QE_proj proj;\n ok_proj : valid_QE_proj proj;\n}.\nHB.builders Context F of Field_QE_isDecField F.\n\n(*This is a canonical instance that automatically equips a field with the structure of a decidable field, provided a valid quantifier elimination mechanism has been defined for it.*)\nHB.instance Definition qe_is_def_field : Field_isDecField F :=\n Field_isDecField.Build F (proj_satP wf_proj ok_proj).\nHB.end.\n\n(*This definition specifies the axiom for a closed field, which asserts that for any positive natural number representing a degree, every monic polynomial of that degree with coefficients from the ring has at least one root within the ring.*)\nDefinition closed_field_axiom (R : pzRingType) :=\n forall n (P : nat -> R), n > 0 ->\n exists x : R, x ^+ n = \\sum_(i < n) P i * (x ^+ i).\n\n(*This mixin extends a decidable field with the property of being algebraically closed, requiring a proof that every monic polynomial with coefficients in the field has a root in the field.*)\nHB.mixin Record DecField_isAlgClosed F of DecidableField F := {\n solve_monicpoly : closed_field_axiom F;\n}.\n\n#[mathcomp(axiom=\"closed_field_axiom\"), short(type=\"closedFieldType\")]\n(*This structure defines a closed field as a decidable field that is also algebraically closed.*)\nHB.structure Definition ClosedField :=\n { F of DecidableField F & DecField_isAlgClosed F }.\n\nModule ClosedFieldExports.\nBind Scope ring_scope with ClosedField.sort.\nEnd ClosedFieldExports.\nHB.export ClosedFieldExports.\n\n#[export] HB.instance Definition _ (F : closedFieldType) := ClosedField.on F^o.\n\nSection ClosedFieldTheory.\n\nVariable F : closedFieldType.\n\n(*This lemma states that in any closed field, there exists an element whose square is equal to negative one.*)\nLemma imaginary_exists : {i : F | i ^+ 2 = -1}.\n\nEnd ClosedFieldTheory.\n\n(*This lemma provides a condition for proving that a multiplication operation on a module is compatible with scalar multiplication on the left. It states that if there exists an injective, scalable function mapping the module to a linear algebra that preserves the multiplication, then scaling a product is equivalent to scaling the first factor before multiplication.*)\nLemma lalgMixin (R : pzRingType) (A : lalgType R) (B : lmodType R) (f : B -> A) :\n phant B -> injective f -> scalable f ->\n forall mulB, {morph f : x y / mulB x y >-> x * y} ->\n forall a u v, a *: (mulB u v) = mulB (a *: u) v.\n\n(*This lemma states that if there is an injective function from a ring to a commutative ring that preserves the multiplication operation, then the original ring must also have a commutative multiplication.*)\nLemma comRingMixin (R : comPzRingType) (T : pzRingType) (f : T -> R) :\n phant T -> injective f -> {morph f : x y / x * y} -> commutative (@mul T).\n\n(*This lemma provides a condition for proving a compatibility property between scalar and ring multiplication. It states that if there is an injective, scalable function from a left linear algebra to another algebra that preserves the multiplication operation, then scaling a product is equivalent to scaling the second factor before multiplication.*)\nLemma algMixin (R : pzRingType) (A : algType R) (B : lalgType R) (f : B -> A) :\n phant B -> injective f -> {morph f : x y / x * y} -> scalable f ->\n forall k (x y : B), k *: (x * y) = x * (k *: y).\n\n(*This mixin defines the property that a subset of a semiring is closed under binary multiplication, meaning the product of any two elements from the subset is also in the subset.*)\nHB.mixin Record isMul2Closed (R : pzSemiRingType) (S : {pred R}) := {\n rpredM : mulr_2closed S\n}.\n\n(*This mixin defines the property that a subset of a semiring contains the multiplicative identity element.*)\nHB.mixin Record isMul1Closed (R : pzSemiRingType) (S : {pred R}) := {\n rpred1 : 1 \\in S\n}.\n\n(*This mixin defines the property that a subset of a unit ring is closed under multiplicative inversion, meaning that if an element is in the subset, its multiplicative inverse is also in the subset.*)\nHB.mixin Record isInvClosed (R : unitRingType) (S : {pred R}) := {\n rpredVr : invr_closed S\n}.\n\n(*This mixin defines the property that a subset of a semimodule is closed under scalar multiplication, meaning that multiplying any element of the subset by a scalar from the base semiring results in an element that is also in the subset.*)\nHB.mixin Record isScaleClosed (R : pzSemiRingType) (V : lSemiModType R)\n (S : {pred V}) := {\n rpredZ : scaler_closed S\n}.\n\n(*This is a notation for the property that a subset of an additive structure is closed under addition.*)\nLocal Notation addrClosed := addrClosed.\n(*This is a notation for the property that a subset of a structure with additive inverses is closed under taking the additive inverse.*)\nLocal Notation opprClosed := opprClosed.\n\n#[short(type=\"mulr2Closed\")]\n(*This structure defines a subset of a semiring that is closed under binary multiplication.*)\nHB.structure Definition Mul2Closed (R : pzSemiRingType) :=\n {S of isMul2Closed R S}.\n\n#[short(type=\"mulrClosed\")]\n(*This structure defines a subset of a semiring that is closed under multiplication and contains the multiplicative identity element.*)\nHB.structure Definition MulClosed (R : pzSemiRingType) :=\n {S of Mul2Closed R S & isMul1Closed R S}.\n\n#[short(type=\"semiring2Closed\")]\n(*This structure defines a subset of a semiring that is closed under both addition and multiplication.*)\nHB.structure Definition Semiring2Closed (R : pzSemiRingType) :=\n {S of AddClosed R S & Mul2Closed R S}.\n\n#[short(type=\"semiringClosed\")]\n(*This structure defines a subset of a semiring that is closed under addition and multiplication and contains both the additive and multiplicative identities, forming a sub-semiring.*)\nHB.structure Definition SemiringClosed (R : pzSemiRingType) :=\n {S of AddClosed R S & MulClosed R S}.\n\n#[short(type=\"smulClosed\")]\n(*This structure defines a subset of a module over a ring that is closed under scalar multiplication.*)\nHB.structure Definition SmulClosed (R : pzRingType) :=\n {S of OppClosed R S & MulClosed R S}.\n\n#[short(type=\"subringClosed\")]\n(*This definition describes a predicate on a p-adic integer ring that identifies a subset which is closed under both the abelian group operations and multiplication, thus forming a subring.*)\nHB.structure Definition SubringClosed (R : pzRingType) :=\n {S of ZmodClosed R S & MulClosed R S}.\n\n#[short(type=\"divClosed\")]\n(*This definition describes a predicate on a ring with a multiplicative unit that identifies a subset which is closed under both multiplication and multiplicative inversion, forming a subgroup of the units.*)\nHB.structure Definition DivClosed (R : unitRingType) :=\n {S of MulClosed R S & isInvClosed R S}.\n\n#[short(type=\"sdivClosed\")]\n(*This definition describes a predicate on a ring with a multiplicative unit that identifies a subset which is closed under both integer scaling and multiplicative inversion.*)\nHB.structure Definition SdivClosed (R : unitRingType) :=\n {S of SmulClosed R S & isInvClosed R S}.\n\n#[short(type=\"submodClosed\")]\n(*This definition describes a predicate on a left semi-module over a p-adic semiring that identifies a subset which is closed under both vector addition and scalar multiplication, thus forming a submodule.*)\nHB.structure Definition SubmodClosed (R : pzSemiRingType) (V : lSemiModType R)\n := {S of AddClosed V S & isScaleClosed R V S}.\n\n#[short(type=\"subalgClosed\")]\n(*This definition describes a predicate on a left semi-algebra over a p-adic semiring that identifies a subset which is both a sub-semiring and is closed under scalar multiplication, thus forming a subalgebra.*)\nHB.structure Definition SubalgClosed (R : pzSemiRingType) (A : lSemiAlgType R)\n := {S of SemiringClosed A S & isScaleClosed R A S}.\n\n#[short(type=\"divringClosed\")]\n(*This definition describes a predicate on a ring with a multiplicative unit that identifies a subset which is a subring and is also closed under multiplicative inversion for its non-zero elements, thus forming a division subring.*)\nHB.structure Definition DivringClosed (R : unitRingType) :=\n {S of SubringClosed R S & isInvClosed R S}.\n\n#[short(type=\"divalgClosed\")]\n(*This definition describes a predicate on a unital algebra over a p-adic ring that identifies a subset which is both a division subring and is closed under scalar multiplication, thus forming a division subalgebra.*)\nHB.structure Definition DivalgClosed (R : pzRingType) (A : unitAlgType R) :=\n {S of DivringClosed A S & isScaleClosed R A S}.\n\n(*This factory builds a structure certifying that a given predicate on a p-adic semiring identifies a subset that is closed under multiplication.*)\nHB.factory Record isMulClosed (R : pzSemiRingType) (S : {pred R}) := {\n rpred1M : mulr_closed S\n}.\n\nHB.builders Context R S of isMulClosed R S.\nHB.instance Definition _ := isMul2Closed.Build R S (proj2 rpred1M).\nHB.instance Definition _ := isMul1Closed.Build R S (proj1 rpred1M).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a p-adic ring identifies a subset that is closed under scalar multiplication by integers.*)\nHB.factory Record isSmulClosed (R : pzRingType) (S : R -> bool) := {\n smulr_closed_subproof : smulr_closed S\n}.\n\nHB.builders Context R S of isSmulClosed R S.\nHB.instance Definition _ := isMulClosed.Build R S\n (smulr_closedM smulr_closed_subproof).\nHB.instance Definition _ := isOppClosed.Build R S\n (smulr_closedN smulr_closed_subproof).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a p-adic semiring identifies a subset closed under the semiring operations, thus forming a sub-semiring.*)\nHB.factory Record isSemiringClosed (R : pzSemiRingType) (S : R -> bool) := {\n semiring_closed_subproof : semiring_closed S\n}.\n\nHB.builders Context R S of isSemiringClosed R S.\nHB.instance Definition _ := isAddClosed.Build R S\n (semiring_closedD semiring_closed_subproof).\nHB.instance Definition _ := isMulClosed.Build R S\n (semiring_closedM semiring_closed_subproof).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a p-adic ring identifies a subset closed under the ring operations, thus forming a subring.*)\nHB.factory Record isSubringClosed (R : pzRingType) (S : R -> bool) := {\n subring_closed_subproof : subring_closed S\n}.\n\nHB.builders Context R S of isSubringClosed R S.\nHB.instance Definition _ := isZmodClosed.Build R S\n (subring_closedB subring_closed_subproof).\nHB.instance Definition _ := isSmulClosed.Build R S\n (subring_closedM subring_closed_subproof).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a ring with a multiplicative unit identifies a subset that is closed under multiplication and multiplicative inversion.*)\nHB.factory Record isDivClosed (R : unitRingType) (S : R -> bool) := {\n divr_closed_subproof : divr_closed S\n}.\n\nHB.builders Context R S of isDivClosed R S.\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := isInvClosed.Build R S\n (divr_closedV divr_closed_subproof).\nHB.instance Definition _ := isMulClosed.Build R S\n (divr_closedM divr_closed_subproof).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a ring with a multiplicative unit identifies a subset that is closed under integer scaling and multiplicative inversion.*)\nHB.factory Record isSdivClosed (R : unitRingType) (S : R -> bool) := {\n sdivr_closed_subproof : sdivr_closed S\n}.\n\nHB.builders Context R S of isSdivClosed R S.\nHB.instance Definition _ := isDivClosed.Build R S\n (sdivr_closed_div sdivr_closed_subproof).\nHB.instance Definition _ := isSmulClosed.Build R S\n (sdivr_closedM sdivr_closed_subproof).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a left semi-module identifies a subset closed under vector addition and scalar multiplication, thus forming a sub-semimodule.*)\nHB.factory Record isSubSemiModClosed (R : pzSemiRingType) (V : lSemiModType R)\n (S : V -> bool) := {\n subsemimod_closed_subproof : subsemimod_closed S\n}.\n\nHB.builders Context R V S of isSubSemiModClosed R V S.\nHB.instance Definition _ := isAddClosed.Build V S\n (subsemimod_closedD subsemimod_closed_subproof).\nHB.instance Definition _ := isScaleClosed.Build R V S\n (subsemimod_closedZ subsemimod_closed_subproof).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a left module identifies a subset closed under vector addition, additive inverse, and scalar multiplication, thus forming a submodule.*)\nHB.factory Record isSubmodClosed (R : pzRingType) (V : lmodType R)\n (S : V -> bool) := {\n submod_closed_subproof : submod_closed S\n}.\n\nHB.builders Context R V S of isSubmodClosed R V S.\nHB.instance Definition _ := isZmodClosed.Build V S\n (submod_closedB submod_closed_subproof).\nHB.instance Definition _ := isScaleClosed.Build R V S\n (subsemimod_closedZ (submod_closed_semi submod_closed_subproof)).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a left algebra identifies a subset that is both a subring and is closed under scalar multiplication, thus forming a subalgebra.*)\nHB.factory Record isSubalgClosed (R : pzRingType) (A : lalgType R)\n (S : A -> bool) := {\n subalg_closed_subproof : subalg_closed S\n}.\n\nHB.builders Context R A S of isSubalgClosed R A S.\nHB.instance Definition _ := isSubmodClosed.Build R A S\n (subalg_closedZ subalg_closed_subproof).\nHB.instance Definition _ := isSubringClosed.Build A S\n (subalg_closedBM subalg_closed_subproof).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a ring with a multiplicative unit identifies a subset that is a subring and is also closed under multiplicative inversion, thus forming a division subring.*)\nHB.factory Record isDivringClosed (R : unitRingType) (S : R -> bool) := {\n divring_closed_subproof : divring_closed S\n}.\n\nHB.builders Context R S of isDivringClosed R S.\nHB.instance Definition _ := isSubringClosed.Build R S\n (divring_closedBM divring_closed_subproof).\nHB.instance Definition _ := isSdivClosed.Build R S\n (divring_closed_div divring_closed_subproof).\nHB.end.\n\n(*This factory builds a structure certifying that a given predicate on a unital algebra over a commutative ring with a unit identifies a subset that is a division subring and is also closed under scalar multiplication, thus forming a division subalgebra.*)\nHB.factory Record isDivalgClosed (R : comUnitRingType) (A : unitAlgType R)\n (S : A -> bool) := {\n divalg_closed_subproof : divalg_closed S\n}.\n\nHB.builders Context R A S of isDivalgClosed R A S.\nHB.instance Definition _ := isDivringClosed.Build A S\n (divalg_closedBdiv divalg_closed_subproof).\nHB.instance Definition _ := isSubalgClosed.Build R A S\n (divalg_closedZ divalg_closed_subproof).\nHB.end.\n\nSection NmodulePred.\n\nVariables (V : nmodType).\n\nSection Add.\n\nVariable S : addrClosed V.\n\n(*This lemma states that a subset of a module over the natural numbers which is closed under addition is also closed as a submodule, which implies it also contains the zero element.*)\nLemma rpred0D : nmod_closed S. \n\nEnd Add.\n\nEnd NmodulePred.\n\nSection ZmodulePred.\n\nVariables (V : zmodType).\n\nSection Opp.\n\nVariable S : opprClosed V.\n\nEnd Opp.\n\nSection Sub.\n\nVariable S : zmodClosed V.\n\n(*This lemma states that a predicate that defines a submodule over the integers satisfies the property of being closed under the module's abelian group operations.*)\nLemma zmodClosedP : zmod_closed S.\n\nEnd Sub.\n\nEnd ZmodulePred.\n\nSection SemiRingPred.\n\nVariables (R : pzSemiRingType).\n\nSection Mul.\n\nVariable S : mulrClosed R.\n\n(*This lemma states that a predicate on a p-adic semiring that is defined as being closed under multiplication indeed satisfies the property of being closed under multiplication.*)\nLemma rpred1M : mulr_closed S.\n\n(*This lemma states that for a subset of a p-adic semiring that is closed under multiplication, the product of any finite sequence of elements from that subset also belongs to the subset.*)\nLemma rpred_prod I r (P : pred I) F :\n (forall i, P i -> F i \\in S) -> \\prod_(i <- r | P i) F i \\in S.\n\n(*This lemma states that any subset of a p-adic semiring that is closed under multiplication is also closed under exponentiation by any natural number.*)\nLemma rpredX n : {in S, forall u, u ^+ n \\in S}.\n\nEnd Mul.\n\n(*This lemma states that if a subset of a p-adic semiring forms a sub-semiring, then it contains the canonical embedding of every natural number.*)\nLemma rpred_nat (S : semiringClosed R) n : n%:R \\in S.\n\n(*This lemma states that a predicate defining a sub-semiring of a p-adic semiring satisfies the property of being closed under the semiring's operations of addition and multiplication.*)\nLemma semiringClosedP (rngS : semiringClosed R) : semiring_closed rngS.\n\nEnd SemiRingPred.\n\nSection RingPred.\n\nVariables (R : pzRingType).\n\n(*This lemma states that for a subset of a p-adic ring that is closed under additive inverse, an element belongs to the subset if and only if its product with either positive one or negative one also belongs to the subset.*)\nLemma rpredMsign (S : opprClosed R) n x : ((-1) ^+ n * x \\in S) = (x \\in S).\n\n(*This lemma states that any subset of a p-adic ring that is closed under integer scaling must contain the element negative one.*)\nLemma rpredN1 (S : smulClosed R) : -1 \\in S.\n\n(*This lemma states that for any natural number, its sign, represented as negative one raised to that number, is an element of any subset of a p-adic ring that is closed under integer scaling.*)\nLemma rpred_sign (S : smulClosed R) n : (-1) ^+ n \\in S.\n\n(*This lemma states that a predicate that defines a subring of a p-adic ring satisfies the property of being closed under the ring's operations.*)\nLemma subringClosedP (rngS : subringClosed R) : subring_closed rngS.\n\nEnd RingPred.\n\nSection LmodPred.\n\nVariables (R : pzSemiRingType) (V : lSemiModType R).\n\n(*This lemma states that for any subset of a left semi-module that is closed under addition, scaling an element of that subset by the canonical image of a natural number results in an element that is also within the subset.*)\nLemma rpredZnat (S : addrClosed V) n : {in S, forall u, n%:R *: u \\in S}.\n\n(*This lemma states that a predicate on a linear module which is closed under submodule operations is also closed under sub-semi-module operations.*)\nLemma subsemimodClosedP (modS : submodClosed V) : subsemimod_closed modS.\n\nEnd LmodPred.\n\nSection LmodPred.\n\nVariables (R : pzRingType) (V : lmodType R).\n\n(*This lemma states that for a predicate on a linear module over a ring that is closed under additive inverse, an element belongs to the predicate if and only if the element scaled by negative one raised to any natural number power also belongs to the predicate.*)\nLemma rpredZsign (S : opprClosed V) n u : ((-1) ^+ n *: u \\in S) = (u \\in S).\n\n(*This lemma states that a predicate on a linear module that satisfies the properties of being closed under submodule operations indeed represents a closed submodule.*)\nLemma submodClosedP (modS : submodClosed V) : submod_closed modS.\n\nEnd LmodPred.\n\nSection LalgPred.\n\nVariables (R : pzRingType) (A : lalgType R).\n\n(*This lemma states that a predicate on a linear algebra that satisfies the properties of being closed under subalgebra operations indeed represents a closed subalgebra.*)\nLemma subalgClosedP (algS : subalgClosed A) : subalg_closed algS.\n\nEnd LalgPred.\n\nSection UnitRingPred.\n\nVariable R : unitRingType.\n\nSection Div.\n\nVariable S : divClosed R.\n\n(*This lemma states that for a predicate on a ring that is closed under division, the multiplicative inverse of an element belongs to the predicate if and only if the element itself belongs to the predicate.*)\nLemma rpredV x : (x^-1 \\in S) = (x \\in S).\n\n(*This lemma states that for any two elements belonging to a predicate on a ring that is closed under division, their quotient also belongs to the predicate.*)\nLemma rpred_div : {in S &, forall x y, x / y \\in S}.\n\n(*This lemma states that for any element belonging to a predicate on a ring that is closed under division, the multiplicative inverse of that element raised to any natural number power also belongs to the predicate.*)\nLemma rpredXN n : {in S, forall x, x ^- n \\in S}.\n\n(*This lemma states that for a predicate on a ring closed under division, if a unit element belongs to the predicate, then the product of this unit with another element belongs to the predicate if and only if the other element also belongs to the predicate.*)\nLemma rpredMl x y : x \\in S -> x \\is a unit-> (x * y \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate on a ring closed under division, if a unit element belongs to the predicate, then the product of another element with this unit belongs to the predicate if and only if the other element also belongs to the predicate.*)\nLemma rpredMr x y : x \\in S -> x \\is a unit -> (y * x \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate on a ring closed under division, if a unit element belongs to the predicate, then the quotient of another element divided by this unit belongs to the predicate if and only if the other element also belongs to the predicate.*)\nLemma rpred_divr x y : x \\in S -> x \\is a unit -> (y / x \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate on a ring closed under division, if a unit element belongs to the predicate, then the quotient of this unit divided by another unit element belongs to the predicate if and only if the other unit element also belongs to the predicate.*)\nLemma rpred_divl x y : x \\in S -> x \\is a unit -> (x / y \\in S) = (y \\in S).\n\nEnd Div.\n\n(*This lemma states that a predicate on a unit ring that satisfies the properties of being closed under division ring operations indeed represents a closed division ring.*)\nLemma divringClosedP (divS : divringClosed R) : divring_closed divS.\n\n(*This fact asserts that the predicate identifying the unit elements of a unit ring is closed under right division.*)\nFact unitr_sdivr_closed : @sdivr_closed R unit.\n\n#[export]\n(*This lemma states that the additive inverse of a ring element is a unit if and only if the original element is a unit.*)\nLemma unitrN x : (- x \\is a unit) = (x \\is a unit). \n\n(*This lemma states that the multiplicative inverse of the additive inverse of a ring element is equal to the additive inverse of its multiplicative inverse.*)\nLemma invrN x : (- x)^-1 = - x^-1.\n\n(*This lemma states that the quotient of the additive inverses of two ring elements is equal to the quotient of the original elements.*)\nLemma divrNN x y : (- x) / (- y) = x / y.\n\n(*This lemma states that the quotient of a ring element divided by the additive inverse of another element is equal to the additive inverse of their quotient.*)\nLemma divrN x y : x / (- y) = - (x / y).\n\n(*This lemma states that the multiplicative inverse of a ring element scaled by negative one raised to a natural number power is equal to the element's multiplicative inverse scaled by the same factor.*)\nLemma invr_signM n x : ((-1) ^+ n * x)^-1 = (-1) ^+ n * x^-1.\n\n(*This lemma states that the quotient of two ring elements, each scaled by a sign factor determined by a boolean, is equal to the quotient of the original elements scaled by a combined sign factor determined by the exclusive-or of the two booleans.*)\nLemma divr_signM (b1 b2 : bool) x1 x2:\n ((-1) ^+ b1 * x1) / ((-1) ^+ b2 * x2) = (-1) ^+ (b1 (+) b2) * (x1 / x2).\n\nEnd UnitRingPred.\n\nSection FieldPred.\n\nVariable F : fieldType.\nImplicit Types x y : F.\n\nSection ModuleTheory.\n\nVariable V : lmodType F.\nImplicit Types (a : F) (v : V).\n\n(*This lemma states that for a submodule over a field, a vector scaled by a scalar belongs to the submodule if and only if the scalar is zero or the original vector belongs to the submodule.*)\nLemma rpredZeq (S : submodClosed V) a v :\n (a *: v \\in S) = (a == 0) || (v \\in S).\n\nEnd ModuleTheory.\n\nSection Predicates.\n\nContext (S : divClosed F).\n\n(*This lemma states that for a predicate on a field that is closed under division, if a non-zero element belongs to the predicate, then the product of this element with another element belongs to the predicate if and only if the other element also belongs to the predicate.*)\nLemma fpredMl x y : x \\in S -> x != 0 -> (x * y \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate on a field that is closed under division, if a non-zero element belongs to the predicate, then the product of another element with this non-zero element belongs to the predicate if and only if the other element also belongs to the predicate.*)\nLemma fpredMr x y : x \\in S -> x != 0 -> (y * x \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate on a field closed under division, if a non-zero element belongs to the predicate, then the quotient of this element by another non-zero element belongs to the predicate if and only if the other element also belongs to the predicate.*)\nLemma fpred_divl x y : x \\in S -> x != 0 -> (x / y \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate on a field closed under division, if a non-zero element belongs to the predicate, then the quotient of another element by this non-zero element belongs to the predicate if and only if the other element also belongs to the predicate.*)\nLemma fpred_divr x y : x \\in S -> x != 0 -> (y / x \\in S) = (y \\in S).\n\nEnd Predicates.\n\nEnd FieldPred.\n\n(*This record defines the properties required for a type to be considered a sub-p-semiring of a given p-semiring, building upon the structure of a sub-n-module by adding the requirement that the embedding into the parent ring preserves the multiplicative structure.*)\nHB.mixin Record isSubPzSemiRing (R : pzSemiRingType) (S : pred R) U\n of SubNmodule R S U & PzSemiRing U := {\n valM_subproof : monoid_morphism (val : U -> R);\n}.\n\nModule isSubSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use isSubPzSemiRing.Build instead.\")]\nNotation Build R S U := (isSubPzSemiRing.Build R S U) (only parsing).\nEnd isSubSemiRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use isSubPzSemiRing instead.\")]\nNotation isSubSemiRing R S U := (isSubPzSemiRing R S U) (only parsing).\n\n#[short(type=\"subPzSemiRingType\")]\n(*This structure defines a sub-p-semiring of a given p-semiring, which is a subtype determined by a predicate that is itself a p-semiring and whose embedding preserves the algebraic structure.*)\nHB.structure Definition SubPzSemiRing (R : pzSemiRingType) (S : pred R) :=\n { U of SubNmodule R S U & PzSemiRing U & isSubPzSemiRing R S U }.\n\n#[short(type=\"subNzSemiRingType\")]\n(*This structure defines a sub-nz-semiring of a given nz-semiring, which is a subtype determined by a predicate that is itself a nz-semiring and whose embedding preserves the algebraic structure.*)\nHB.structure Definition SubNzSemiRing (R : nzSemiRingType) (S : pred R) :=\n { U of SubNmodule R S U & NzSemiRing U & isSubPzSemiRing R S U }.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzSemiRing instead.\")]\nNotation SubSemiRing R := (SubNzSemiRing R) (only parsing).\n\nModule SubSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzSemiRing.sort instead.\")]\n(*A deprecated notation for the carrier type of a sub-nz-semiring structure.*)\nNotation sort := (SubNzSemiRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzSemiRing.on instead.\")]\nNotation on R := (SubNzSemiRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzSemiRing.copy instead.\")]\nNotation copy T U := (SubNzSemiRing.copy T U) (only parsing).\nEnd SubSemiRing.\n\nSection multiplicative.\nContext (R : pzSemiRingType) (S : pred R) (U : SubPzSemiRing.type S).\n(*A notation representing the embedding function that maps an element from a sub-p-semiring back into its parent p-semiring.*)\nNotation val := (val : U -> R).\n#[export]\n(*This lemma states that the embedding function from a sub-p-semiring to its parent semiring maps the multiplicative identity of the sub-semiring to the multiplicative identity of the parent semiring.*)\nLemma val1 : val 1 = 1. \n(*This lemma states that the function `val` is a multiplicative morphism, meaning that applying the function to the product of two elements yields the same result as multiplying the results of applying the function to each element individually.*)\nLemma valM : {morph val : x y / x * y}. \n(*This lemma states that the function `val` is a monoid morphism, which means it preserves both the multiplicative structure and the multiplicative identity element.*)\nLemma valM1 : monoid_morphism val. \nEnd multiplicative.\n\n(*This factory provides a mechanism to establish a semiring structure on a sub-n-module of a given semiring, under the condition that the submodule is closed with respect to the multiplication defined in the parent semiring.*)\nHB.factory Record SubNmodule_isSubPzSemiRing (R : pzSemiRingType) S U\n of SubNmodule R S U := {\n mulr_closed_subproof : mulr_closed S\n}.\n\nHB.builders Context R S U of SubNmodule_isSubPzSemiRing R S U.\n\nHB.instance Definition _ := isMulClosed.Build R S mulr_closed_subproof.\n\nLet inU v Sv : U := Sub v Sv.\nLet oneU : U := inU (@rpred1 _ (MulClosed.clone R S _)).\nLet mulU (u1 u2 : U) := inU (rpredM _ _ (valP u1) (valP u2)).\n\n(*This lemma states that the multiplication operation defined on the sub-n-module is associative.*)\nLemma mulrA : associative mulU.\n\n(*This lemma states that the multiplicative identity element of the sub-n-module acts as a left identity for the multiplication operation on that submodule.*)\nLemma mul1r : left_id oneU mulU.\n\n(*This lemma states that the multiplicative identity element of the sub-n-module acts as a right identity for the multiplication operation on that submodule.*)\nLemma mulr1 : right_id oneU mulU.\n\n(*This lemma states that the multiplication on the sub-n-module distributes on the left over the addition operation inherited from the parent semiring.*)\nLemma mulrDl : left_distributive mulU +%R.\n\n(*This lemma states that the multiplication on the sub-n-module distributes on the right over the addition operation inherited from the parent semiring.*)\nLemma mulrDr : right_distributive mulU +%R.\n\n(*This lemma states that the additive identity element of the parent semiring acts as a left annihilator for the multiplication operation on the sub-n-module.*)\nLemma mul0r : left_zero 0%R mulU.\n\n(*This lemma states that the additive identity element of the parent semiring acts as a right annihilator for the multiplication operation on the sub-n-module.*)\nLemma mulr0 : right_zero 0%R mulU.\n\nHB.instance Definition _ := Nmodule_isPzSemiRing.Build U\n mulrA mul1r mulr1 mulrDl mulrDr mul0r mulr0.\n\n(*A proof term that establishes that a given subset of an algebraic structure is closed under the multiplication operation.*)\nLemma valM : monoid_morphism (val : U -> R).\n\nHB.instance Definition _ := isSubPzSemiRing.Build R S U valM.\nHB.end.\n\n(*This factory constructs a non-zero sub-semiring structure on a given type, provided it already has the structure of a submodule over the natural numbers and a proof that the underlying subset is closed under multiplication.*)\nHB.factory Record SubNmodule_isSubNzSemiRing (R : nzSemiRingType) S U\n of SubNmodule R S U := {\n mulr_closed_subproof : mulr_closed S\n}.\n\nModule SubNmodule_isSubSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNmodule_isSubNzSemiRing.Build instead.\")]\nNotation Build R S U := (SubNmodule_isSubNzSemiRing.Build R S U) (only parsing).\nEnd SubNmodule_isSubSemiRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNmodule_isSubNzSemiRing instead.\")]\nNotation SubNmodule_isSubSemiRing R S U :=\n (SubNmodule_isSubNzSemiRing R S U) (only parsing).\n\nHB.builders Context R S U of SubNmodule_isSubNzSemiRing R S U.\n\nHB.instance Definition _ := SubNmodule_isSubPzSemiRing.Build R S U\n mulr_closed_subproof.\n\n(*This lemma states that for any non-zero sub-semiring, its multiplicative identity is distinct from its additive identity.*)\nLemma oner_neq0 : (1 : U) != 0.\n\nHB.instance Definition _ := PzSemiRing_isNonZero.Build U oner_neq0.\nHB.end.\n\n#[short(type=\"subComPzSemiRingType\")]\n(*This structure defines a commutative sub-pre-semiring, which is a subset of a parent pre-semiring that is closed under addition and multiplication, contains the additive and multiplicative identities, and has a commutative multiplication operation.*)\nHB.structure Definition SubComPzSemiRing (R : pzSemiRingType) S :=\n {U of SubPzSemiRing R S U & ComPzSemiRing U}.\n\n(*This factory constructs a commutative sub-pre-semiring structure from a sub-pre-semiring of a parent structure that is already a commutative pre-semiring. Commutativity is inherited automatically from the parent structure, so no additional proofs are required.*)\nHB.factory Record SubPzSemiRing_isSubComPzSemiRing (R : comPzSemiRingType) S U\n of SubPzSemiRing R S U := {}.\n\nHB.builders Context R S U of SubPzSemiRing_isSubComPzSemiRing R S U.\nLemma mulrC : @commutative U U *%R.\n\nHB.instance Definition _ := PzSemiRing_hasCommutativeMul.Build U mulrC.\nHB.end.\n\n#[short(type=\"subComNzSemiRingType\")]\n(*This structure defines a commutative non-zero sub-semiring, which is a subset of a parent non-zero semiring that is closed under addition and multiplication, contains distinct additive and multiplicative identities, and has a commutative multiplication operation.*)\nHB.structure Definition SubComNzSemiRing (R : nzSemiRingType) S :=\n {U of SubNzSemiRing R S U & ComNzSemiRing U}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubComNzSemiRing instead.\")]\nNotation SubComSemiRing R := (SubComNzSemiRing R) (only parsing).\n\nModule SubComSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubComNzSemiRing.sort instead.\")]\n(*This is a deprecated notation for the carrier type of a commutative non-zero sub-semiring structure.*)\nNotation sort := (SubComNzSemiRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubComNzSemiRing.on instead.\")]\nNotation on R := (SubComNzSemiRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubComNzSemiRing.copy instead.\")]\nNotation copy T U := (SubComNzSemiRing.copy T U) (only parsing).\nEnd SubComSemiRing.\n\n(*This factory constructs a commutative non-zero sub-semiring structure from a sub-semiring of a parent structure that is already a commutative non-zero semiring. Commutativity is inherited automatically, so no additional proofs are needed.*)\nHB.factory Record SubNzSemiRing_isSubComNzSemiRing (R : comNzSemiRingType) S U\n of SubNzSemiRing R S U := {}.\n\nModule SubSemiRing_isSubComSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzSemiRing_isSubComNzSemiRing.Build instead.\")]\nNotation Build R S U :=\n (SubNzSemiRing_isSubComNzSemiRing.Build R S U) (only parsing).\nEnd SubSemiRing_isSubComSemiRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzSemiRing_isSubComNzSemiRing instead.\")]\nNotation SubSemiRing_isSubComSemiRing R S U :=\n (SubNzSemiRing_isSubComNzSemiRing R S U) (only parsing).\n\nHB.builders Context R S U of SubNzSemiRing_isSubComNzSemiRing R S U.\nHB.instance Definition _ := SubPzSemiRing_isSubComPzSemiRing.Build R S U.\nHB.end.\n\n#[short(type=\"subPzRingType\")]\n(*This structure defines a sub-pre-ring, which is a subset of a parent pre-ring that is closed under addition, multiplication, and additive inverse, and contains the additive and multiplicative identities.*)\nHB.structure Definition SubPzRing (R : pzRingType) (S : pred R) :=\n { U of SubPzSemiRing R S U & PzRing U & isSubZmodule R S U }.\n\n(*This factory constructs a sub-pre-ring structure on a given type, provided it already has the structure of a submodule over the integers and a proof that the underlying subset is a subring, meaning it contains the multiplicative identity and is closed under multiplication.*)\nHB.factory Record SubZmodule_isSubPzRing (R : pzRingType) S U\n of SubZmodule R S U := {\n subring_closed_subproof : subring_closed S\n}.\n\nHB.builders Context R S U of SubZmodule_isSubPzRing R S U.\n\nHB.instance Definition _ := isSubringClosed.Build R S subring_closed_subproof.\n\nLet inU v Sv : U := Sub v Sv.\nLet oneU : U := inU (@rpred1 _ (MulClosed.clone R S _)).\nLet mulU (u1 u2 : U) := inU (rpredM _ _ (valP u1) (valP u2)).\n\nHB.instance Definition _ := SubNmodule_isSubPzSemiRing.Build R S U\n (smulr_closedM (subring_closedM subring_closed_subproof)).\nHB.end.\n\n#[short(type=\"subNzRingType\")]\n(*This structure defines a non-zero sub-ring, which is a subset of a parent non-zero ring that is closed under addition, multiplication, and additive inverse, and contains the additive and multiplicative identities, where these two identities are distinct.*)\nHB.structure Definition SubNzRing (R : nzRingType) (S : pred R) :=\n { U of SubNzSemiRing R S U & NzRing U & isSubBaseAddUMagma R S U }.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzRing instead.\")]\nNotation SubRing R := (SubNzRing R) (only parsing).\n\nModule SubRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzRing.sort instead.\")]\n(*This deprecated notation provides an alias for the carrier type of a commutative non-zero subring.*)\nNotation sort := (SubNzRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzRing.on instead.\")]\nNotation on R := (SubNzRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzRing.copy instead.\")]\nNotation copy T U := (SubNzRing.copy T U) (only parsing).\nEnd SubRing.\n\n(*This factory constructs a non-zero subring structure from a submodule over the integers, given a proof that the underlying subset is closed under multiplication.*)\nHB.factory Record SubZmodule_isSubNzRing (R : nzRingType) S U\n of SubZmodule R S U := {\n subring_closed_subproof : subring_closed S\n}.\n\nModule SubZmodule_isSubRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubZmodule_isSubNzRing.Build instead.\")]\nNotation Build R S U := (SubZmodule_isSubNzRing.Build R S U) (only parsing).\nEnd SubZmodule_isSubRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubZmodule_isSubNzRing instead.\")]\nNotation SubZmodule_isSubRing R S U :=\n (SubZmodule_isSubNzRing R S U) (only parsing).\n\nHB.builders Context R S U of SubZmodule_isSubNzRing R S U.\n\nHB.instance Definition _ := isSubringClosed.Build R S subring_closed_subproof.\n\nLet inU v Sv : U := Sub v Sv.\n(*This definition specifies the multiplicative identity element within the context of a subring constructed from a submodule over the integers.*)\nLet oneU : U := inU (@rpred1 _ (MulClosed.clone R S _)).\n(*This definition specifies the multiplication operation for two elements within the subring constructed from a submodule over the integers. The operation is performed in the ambient ring, with the result being an element of the subring.*)\nLet mulU (u1 u2 : U) := inU (rpredM _ _ (valP u1) (valP u2)).\n\nHB.instance Definition _ := SubNmodule_isSubNzSemiRing.Build R S U\n (smulr_closedM (subring_closedM subring_closed_subproof)).\nHB.end.\n\n#[short(type=\"subComPzRingType\")]\n(*This structure defines a commutative subring of a ring where one is not equal to zero. It combines the properties of being a subring with the property of having a commutative multiplication.*)\nHB.structure Definition SubComPzRing (R : pzRingType) S :=\n {U of SubPzRing R S U & ComPzRing U}.\n\n(*This factory constructs a commutative ring structure for a subring, given that the ambient ring is itself commutative.*)\nHB.factory Record SubPzRing_isSubComPzRing (R : comPzRingType) S U\n of SubPzRing R S U := {}.\n\nHB.builders Context R S U of SubPzRing_isSubComPzRing R S U.\n(*This lemma states that multiplication within a subring is commutative, provided the ambient ring is commutative.*)\nLemma mulrC : @commutative U U *%R.\n\nHB.instance Definition _ := PzRing_hasCommutativeMul.Build U mulrC.\nHB.end.\n\n#[short(type=\"subComNzRingType\")]\n(*This structure defines a commutative, non-zero subring of a non-zero ring. It combines the properties of being a non-zero subring with the property of having a commutative multiplication.*)\nHB.structure Definition SubComNzRing (R : nzRingType) S :=\n {U of SubNzRing R S U & ComNzRing U}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubComNzRing instead.\")]\nNotation SubComRing R := (SubComNzRing R) (only parsing).\n\nModule SubComRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubComNzRing.sort instead.\")]\n(*This is a parsing-only notation for the underlying carrier type of a commutative, non-trivial subring structure. It simplifies writing terms that belong to the subring.*)\nNotation sort := (SubComNzRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubComNzRing.on instead.\")]\nNotation on R := (SubComNzRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubComNzRing.copy instead.\")]\nNotation copy T U := (SubComNzRing.copy T U) (only parsing).\nEnd SubComRing.\n\n(*This factory provides a construction to automatically derive a sub-commutative-non-zero-ring structure for a given sub-non-zero-ring, provided that the ambient ring is a commutative non-zero ring.*)\nHB.factory Record SubNzRing_isSubComNzRing (R : comNzRingType) S U\n of SubNzRing R S U := {}.\n\nModule SubRing_isSubComRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzRing_isSubComNzRing.Build instead.\")]\nNotation Build R S U := (SubNzRing_isSubComNzRing.Build R S U) (only parsing).\nEnd SubRing_isSubComRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzRing_isSubComNzRing instead.\")]\nNotation SubRing_isSubComRing R S U :=\n (SubNzRing_isSubComNzRing R S U) (only parsing).\n\nHB.builders Context R S U of SubNzRing_isSubComNzRing R S U.\nHB.instance Definition _ := SubPzRing_isSubComPzRing.Build R S U.\nHB.end.\n\n(*This record defines the property of a sub-n-module being a sub-L-semimodule. This property requires that the inclusion map from the sub-n-module into the ambient L-semimodule is compatible with scalar multiplication.*)\nHB.mixin Record isSubLSemiModule (R : pzSemiRingType) (V : lSemiModType R)\n (S : pred V) W of SubNmodule V S W & LSemiModule R W := {\n valZ : scalable (val : W -> V);\n}.\n\n#[short(type=\"subLSemiModType\")]\n(*This structure defines a sub-L-semimodule as a subset of an ambient L-semimodule that is itself an L-semimodule under the induced operations and is closed under scalar multiplication from the base semiring.*)\nHB.structure Definition SubLSemiModule (R : pzSemiRingType) (V : lSemiModType R)\n (S : pred V) :=\n { W of SubNmodule V S W &\n Nmodule_isLSemiModule R W & isSubLSemiModule R V S W}.\n\n#[short(type=\"subLmodType\")]\n(*This structure defines a sub-L-module as a subset of an ambient L-module over a ring that is itself an L-module under the induced operations and is closed under scalar multiplication from the base ring.*)\nHB.structure Definition SubLmodule (R : pzRingType) (V : lmodType R)\n (S : pred V) :=\n { W of SubZmodule V S W &\n Nmodule_isLSemiModule R W & isSubLSemiModule R V S W}.\n\nSection linear.\nContext (R : pzSemiRingType) (V : lSemiModType R).\nContext (S : pred V) (W : subLSemiModType S).\n(*This notation represents the canonical inclusion function that maps an element of a substructure back into the ambient structure from which it was derived.*)\nNotation val := (val : W -> V).\n#[export]\n(*This record defines the property for a sub-Z-module to be a sub-L-module, which requires that the inclusion map from the sub-Z-module into the ambient L-module is compatible with scalar multiplication.*)\nHB.factory Record isSubLmodule (R : pzRingType) (V : lmodType R) (S : pred V)\n W of SubZmodule V S W & Lmodule R W := {\n valZ : scalable (val : W -> V);\n}.\n\nHB.builders Context (R : pzRingType) (V : lmodType R) S W of\n isSubLmodule R V S W.\n\nHB.instance Definition _ := isSubLSemiModule.Build R V S W valZ.\n\nHB.end.\n\n(*This factory constructs a sub-L-semimodule from a sub-n-module, using a provided proof that the underlying subset is closed under scalar multiplication by elements of the base semiring.*)\nHB.factory Record SubNmodule_isSubLSemiModule\n (R : pzSemiRingType) (V : lSemiModType R) S W of SubNmodule V S W := {\n submod_closed_subproof : subsemimod_closed S\n}.\n\nHB.builders Context (R : pzSemiRingType) (V : lSemiModType R) S W\n of SubNmodule_isSubLSemiModule R V S W.\n\nHB.instance Definition _ :=\n isSubSemiModClosed.Build R V S submod_closed_subproof.\n\n(*This function constructs an element of a submodule by taking an element from the ambient module and a proof that this element belongs to the subset defining the submodule.*)\nLet inW v Sv : W := Sub v Sv.\n(*This function defines scalar multiplication within a submodule by taking a scalar from the base ring and a submodule element, performing the multiplication in the ambient module, and then packaging the resulting element back into the submodule.*)\nLet scaleW a (w : W) := inW (rpredZ a _ (valP w)).\n\n(*This lemma states that scalar multiplication in the submodule is associative, meaning that scaling a submodule element by a second scalar and then by a first scalar is equivalent to scaling the element by the product of the two scalars.*)\nLemma scalerA' a b v : scaleW a (scaleW b v) = scaleW (a * b) v.\n\n(*This lemma states that scaling any element of a submodule by the zero scalar from the base ring results in the zero element of the submodule.*)\nLemma scale0r v : scaleW 0 v = 0.\n\n(*This lemma states that the multiplicative identity element of the base ring acts as a left identity for scalar multiplication in the submodule, meaning scaling any element by one leaves it unchanged.*)\nLemma scale1r : left_id 1 scaleW.\n\n(*This lemma states that scalar multiplication in a submodule distributes on the right over the submodule's addition, meaning that scaling the sum of two submodule elements is equivalent to summing the results of scaling each element individually with the same scalar.*)\nLemma scalerDr : right_distributive scaleW +%R.\n\n(*This lemma states that scalar multiplication in a submodule distributes on the left over the addition of scalars from the base ring, meaning that scaling a submodule element by the sum of two scalars is equivalent to summing the results of scaling the element by each scalar individually.*)\nLemma scalerDl v : {morph scaleW^~ v : a b / a + b}.\n\nHB.instance Definition _ := Nmodule_isLSemiModule.Build R W\n scalerA' scale0r scale1r scalerDr scalerDl.\n\n(*This fact asserts that the inclusion map from a submodule to its ambient module is a scalable function, meaning that performing scalar multiplication before or after applying the inclusion map yields the same result.*)\nFact valZ : scalable (val : W -> _). \nHB.instance Definition _ := isSubLSemiModule.Build R V S W valZ.\nHB.end.\n\n(*This factory constructs a sub-L-module from a sub-Z-module, using a provided proof that the underlying subset is closed under scalar multiplication by elements of the base ring.*)\nHB.factory Record SubZmodule_isSubLmodule (R : pzRingType) (V : lmodType R) S W\n of SubZmodule V S W := {\n submod_closed_subproof : submod_closed S\n}.\n\nHB.builders Context (R : pzRingType) (V : lmodType R) S W\n of SubZmodule_isSubLmodule R V S W.\nHB.instance Definition _ := SubNmodule_isSubLSemiModule.Build R V S W\n (submod_closed_semi submod_closed_subproof).\nHB.end.\n\n#[short(type=\"subLSemiAlgType\")]\n(*This structure defines a sub-L-semialgebra as a subset of an ambient L-semialgebra that is simultaneously a sub-non-zero-semiring and a sub-L-semimodule, thereby forming an L-semialgebra under the induced operations.*)\nHB.structure Definition SubLSemiAlgebra\n (R : pzSemiRingType) (V : lSemiAlgType R) S :=\n {W of SubNzSemiRing V S W & @SubLSemiModule R V S W & LSemiAlgebra R W}.\n\n#[short(type=\"subLalgType\")]\n(*This structure defines a sub-L-algebra as a subset of an ambient L-algebra that is simultaneously a sub-non-zero-ring and a sub-L-module, thereby forming an L-algebra under the induced operations.*)\nHB.structure Definition SubLalgebra (R : pzRingType) (V : lalgType R) S :=\n {W of SubNzRing V S W & @SubLmodule R V S W & Lalgebra R W}.\n\n(*This factory provides a construction to recognize a structure as a sub-L-semialgebra given that it is already known to be both a sub-non-zero-semiring and a sub-L-semimodule of an ambient L-semialgebra.*)\nHB.factory Record SubNzSemiRing_SubLSemiModule_isSubLSemiAlgebra\n (R : pzSemiRingType) (V : lSemiAlgType R) S W\n of SubNzSemiRing V S W & @SubLSemiModule R V S W := {}.\n\nHB.builders Context (R : pzSemiRingType) (V : lSemiAlgType R) S W\n of SubNzSemiRing_SubLSemiModule_isSubLSemiAlgebra R V S W.\n(*This lemma asserts a compatibility law for algebras, stating that scaling a product of two algebra elements by a scalar from the base ring is equivalent to first scaling the first element, and then multiplying the result by the second element.*)\nLemma scalerAl (a : R) (u v : W) : a *: (u * v) = a *: u * v.\n\nHB.instance Definition _ := LSemiModule_isLSemiAlgebra.Build R W scalerAl.\nHB.end.\n\n(*This factory provides a construction to recognize a structure as a sub-L-algebra given that it is already known to be both a sub-non-zero-ring and a sub-L-module of an ambient L-algebra.*)\nHB.factory Record SubNzRing_SubLmodule_isSubLalgebra (R : pzRingType)\n (V : lalgType R) S W of SubNzRing V S W & @SubLmodule R V S W := {}.\n\nModule SubRing_SubLmodule_isSubLalgebra.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzRing_SubLmodule_isSubLalgebra.Build instead.\")]\nNotation Build R V S U :=\n (SubNzRing_SubLmodule_isSubLalgebra.Build R V S U) (only parsing).\nEnd SubRing_SubLmodule_isSubLalgebra.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubNzRing_SubLmodule_isSubLalgebra instead.\")]\nNotation SubRing_SubLmodule_isSubLalgebra R V S U :=\n (SubNzRing_SubLmodule_isSubLalgebra R V S U) (only parsing).\n\nHB.builders Context (R : pzRingType) (V : lalgType R) S W\n of SubNzRing_SubLmodule_isSubLalgebra R V S W.\nHB.instance Definition _ :=\n SubNzSemiRing_SubLSemiModule_isSubLSemiAlgebra.Build R V S W.\nHB.end.\n\n#[short(type=\"subSemiAlgType\")]\n(*This structure defines a sub-semialgebra as a sub-L-semialgebra that satisfies an additional compatibility axiom between scalar multiplication and the algebra's internal multiplication.*)\nHB.structure Definition SubSemiAlgebra (R : pzSemiRingType) (V : semiAlgType R)\n S :=\n {W of @SubLSemiAlgebra R V S W & SemiAlgebra R W}.\n\n#[short(type=\"subAlgType\")]\n(*This structure defines a subalgebra as a sub-L-algebra that satisfies an additional compatibility axiom between scalar multiplication and the algebra's internal multiplication.*)\nHB.structure Definition SubAlgebra (R : pzRingType) (V : algType R) S :=\n {W of @SubLalgebra R V S W & Algebra R W}.\n\n(*This factory provides a method for upgrading a sub-L-semialgebra to a sub-semialgebra, which relies on a proof of an additional compatibility axiom between scalar multiplication and the internal multiplication of the algebra.*)\nHB.factory Record SubLSemiAlgebra_isSubSemiAlgebra (R : pzSemiRingType)\n (V : semiAlgType R) S W of @SubLSemiAlgebra R V S W := {}.\n\nHB.builders Context (R : pzSemiRingType) (V : semiAlgType R) S W\n of SubLSemiAlgebra_isSubSemiAlgebra R V S W.\n(*This lemma asserts a compatibility law for algebras, stating that scaling a product of two algebra elements with a scalar is equivalent to multiplying the first element by the result of scaling the second element with the same scalar.*)\nLemma scalerAr (k : R) (x y : W) : k *: (x * y) = x * (k *: y).\n\nHB.instance Definition _ := LSemiAlgebra_isSemiAlgebra.Build R W scalerAr.\nHB.end.\n\n(*This factory provides a method for upgrading a sub-L-algebra to a subalgebra, which relies on a proof of an additional compatibility axiom between scalar multiplication and the internal multiplication of the algebra.*)\nHB.factory Record SubLalgebra_isSubAlgebra (R : pzRingType)\n (V : algType R) S W of @SubLalgebra R V S W := {}.\n\nHB.builders Context (R : pzRingType) (V : algType R) S W\n of SubLalgebra_isSubAlgebra R V S W.\nHB.instance Definition _ := SubLSemiAlgebra_isSubSemiAlgebra.Build R V S W.\nHB.end.\n\n#[short(type=\"subUnitRingType\")]\n(*This structure defines a sub-unit-ring as a subset of a non-zero ring that not only forms a sub-non-zero-ring but also contains the multiplicative identity of the ambient ring, thus qualifying it as a unit ring in its own right.*)\nHB.structure Definition SubUnitRing (R : nzRingType) (S : pred R) :=\n {U of SubNzRing R S U & UnitRing U}.\n\n(*This factory constructs a sub-unit-ring from a sub-non-zero-ring, provided a proof that the subset defining the subring contains the multiplicative identity of the ambient ring.*)\nHB.factory Record SubNzRing_isSubUnitRing (R : unitRingType) S U\n of SubNzRing R S U := {\n divring_closed_subproof : divring_closed S\n}.\n\nHB.builders Context (R : unitRingType) S U of SubNzRing_isSubUnitRing R S U.\n\nHB.instance Definition _ := isDivringClosed.Build R S divring_closed_subproof.\n\n(*This function constructs an element of a sub-unit-ring by taking an element from the ambient ring and a proof that this element belongs to the subset that defines the sub-unit-ring.*)\nLet inU v Sv : U := Sub v Sv.\n(*This definition provides the multiplicative inverse for an element of a sub-ring, given that the element's corresponding value in the parent ring is a unit.*)\nLet invU (u : U) := inU (rpredVr _ (valP u)).\n\n(*This lemma asserts that for any element of the sub-ring whose corresponding value in the parent ring is a unit, multiplying it on the left by its defined inverse yields the multiplicative identity.*)\nLemma mulVr : {in [pred x | val x \\is a unit], left_inverse 1 invU *%R}.\n\n(*This lemma asserts that for any element of the sub-ring whose corresponding value in the parent ring is a unit, multiplying it on the right by its defined inverse yields the multiplicative identity.*)\nLemma divrr : {in [pred x | val x \\is a unit], right_inverse 1 invU *%R}.\n\n(*This lemma states that if an element of a sub-ring has a two-sided multiplicative inverse within that same sub-ring, then its corresponding value in the parent ring is a unit.*)\nLemma unitrP (x y : U) : y * x = 1 /\\ x * y = 1 -> val x \\is a unit.\n\n(*This lemma states that the defined inverse function acts as the identity function when applied to an element of the sub-ring whose value in the parent ring is not a unit.*)\nLemma invr_out : {in [pred x | val x \\isn't a unit], invU =1 id}.\n\nHB.instance Definition _ := NzRing_hasMulInverse.Build U\n mulVr divrr unitrP invr_out.\nHB.end.\n\n#[short(type=\"subComUnitRingType\")]\n(*This definition describes the structure of a sub-commutative unit ring, which is a subset of a parent commutative unit ring that is itself a commutative unit ring under the inherited operations.*)\nHB.structure Definition SubComUnitRing (R : comUnitRingType) (S : pred R) :=\n {U of SubComNzRing R S U & SubUnitRing R S U}.\n\n#[short(type=\"subIdomainType\")]\n(*This definition describes the structure of a sub-integral domain, which is a subset of a parent integral domain that is itself an integral domain under the inherited operations.*)\nHB.structure Definition SubIntegralDomain (R : idomainType) (S : pred R) :=\n {U of SubComNzRing R S U & IntegralDomain U}.\n\n(*This factory provides a way to construct a sub-integral domain structure from a sub-commutative unit ring when the parent ring is an integral domain.*)\nHB.factory Record SubComUnitRing_isSubIntegralDomain (R : idomainType) S U\n of SubComUnitRing R S U := {}.\n\nHB.builders Context (R : idomainType) S U\n of SubComUnitRing_isSubIntegralDomain R S U.\n(*This lemma proves that a sub-commutative unit ring of a parent integral domain also satisfies the integral domain axioms.*)\nLemma id : IntegralDomain.axiom U.\n\nHB.instance Definition _ := ComUnitRing_isIntegral.Build U id.\nHB.end.\n\n#[short(type=\"subFieldType\")]\n(*This definition describes the structure of a subfield, which is a subset of a parent field that is itself a field under the inherited operations.*)\nHB.structure Definition SubField (F : fieldType) (S : pred F) :=\n {U of SubIntegralDomain F S U & Field U}.\n\n(*This factory provides a way to construct a subfield structure from a sub-integral domain of a parent field, requiring a proof that the substructure is closed under multiplicative inversion for all its non-zero elements.*)\nHB.factory Record SubIntegralDomain_isSubField (F : fieldType) S U\n of SubIntegralDomain F S U := {\n subfield_subproof : {mono (val : U -> F) : u / u \\in unit}\n}.\n\nHB.builders Context (F : fieldType) S U of SubIntegralDomain_isSubField F S U.\n(*This lemma proves that a sub-integral domain of a parent field, which is closed under multiplicative inversion, also satisfies the field axioms.*)\nLemma fieldP : Field.axiom U.\n\nHB.instance Definition _ := UnitRing_isField.Build U fieldP.\nHB.end.\n\n(*This factory constructs a sub-semiring structure with a positivity predicate from a chosen subset of a parent semiring, provided a proof that the subset is closed under addition and multiplication.*)\nHB.factory Record SubChoice_isSubPzSemiRing (R : pzSemiRingType) S U\n of SubChoice R S U := {\n semiring_closed_subproof : semiring_closed S\n}.\n\nHB.builders Context (R : pzSemiRingType) S U of SubChoice_isSubPzSemiRing R S U.\nHB.instance Definition _ := SubChoice_isSubNmodule.Build R S U\n (semiring_closedD semiring_closed_subproof).\nHB.instance Definition _ := SubNmodule_isSubPzSemiRing.Build R S U\n (semiring_closedM semiring_closed_subproof).\nHB.end.\n\n(*This factory constructs a sub-semiring structure from a chosen subset of a parent non-zero semiring, provided a proof that the subset is closed under addition and multiplication.*)\nHB.factory Record SubChoice_isSubNzSemiRing (R : nzSemiRingType) S U\n of SubChoice R S U := {\n semiring_closed_subproof : semiring_closed S\n}.\n\nModule SubChoice_isSubSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubChoice_isSubNzSemiRing.Build instead.\")]\nNotation Build R S U := (SubChoice_isSubNzSemiRing.Build R S U) (only parsing).\nEnd SubChoice_isSubSemiRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubChoice_isSubNzSemiRing instead.\")]\nNotation SubChoice_isSubSemiRing R S U :=\n (SubChoice_isSubNzSemiRing R S U) (only parsing).\n\nHB.builders Context (R : nzSemiRingType) S U of SubChoice_isSubNzSemiRing R S U.\nHB.instance Definition _ := SubChoice_isSubNmodule.Build R S U\n (semiring_closedD semiring_closed_subproof).\nHB.instance Definition _ := SubNmodule_isSubNzSemiRing.Build R S U\n (semiring_closedM semiring_closed_subproof).\nHB.end.\n\n(*This factory constructs a sub-commutative semiring structure with a positivity predicate from a chosen subset of a parent commutative semiring, provided a proof that the subset is closed under addition and multiplication.*)\nHB.factory Record SubChoice_isSubComPzSemiRing (R : comPzSemiRingType) S U\n of SubChoice R S U := {\n semiring_closed_subproof : semiring_closed S\n}.\n\nHB.builders Context (R : comPzSemiRingType) S U\n of SubChoice_isSubComPzSemiRing R S U.\nHB.instance Definition _ := SubChoice_isSubPzSemiRing.Build R S U\n semiring_closed_subproof.\nHB.instance Definition _ := SubPzSemiRing_isSubComPzSemiRing.Build R S U.\nHB.end.\n\n(*This factory constructs a sub-commutative non-zero semiring structure from a chosen subset of a parent commutative non-zero semiring, provided a proof that the subset is closed under addition and multiplication.*)\nHB.factory Record SubChoice_isSubComNzSemiRing (R : comNzSemiRingType) S U\n of SubChoice R S U := {\n semiring_closed_subproof : semiring_closed S\n}.\n\nModule SubChoice_isSubComSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubChoice_isSubComNzSemiRing.Build instead.\")]\nNotation Build R S U :=\n (SubChoice_isSubComNzSemiRing.Build R S U) (only parsing).\nEnd SubChoice_isSubComSemiRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubChoice_isSubComNzSemiRing instead.\")]\nNotation SubChoice_isSubComSemiRing R S U :=\n (SubChoice_isSubComNzSemiRing R S U) (only parsing).\n\nHB.builders Context (R : comNzSemiRingType) S U\n of SubChoice_isSubComNzSemiRing R S U.\nHB.instance Definition _ := SubChoice_isSubNzSemiRing.Build R S U\n semiring_closed_subproof.\nHB.instance Definition _ := SubNzSemiRing_isSubComNzSemiRing.Build R S U.\nHB.end.\n\n(*This factory constructs a subring structure with a positivity predicate from a chosen subset of a parent ring, provided a proof that the subset is closed under addition, multiplication, and additive inverse.*)\nHB.factory Record SubChoice_isSubPzRing (R : pzRingType) S U of SubChoice R S U := {\n subring_closed_subproof : subring_closed S\n}.\n\nHB.builders Context (R : pzRingType) S U of SubChoice_isSubPzRing R S U.\nHB.instance Definition _ := SubChoice_isSubZmodule.Build R S U\n (subring_closedB subring_closed_subproof).\nHB.instance Definition _ := SubZmodule_isSubPzRing.Build R S U\n subring_closed_subproof.\nHB.end.\n\n(*This factory constructs a subring structure from a chosen subset of a parent non-zero ring, provided a proof that the subset is closed under addition, multiplication, and additive inverse.*)\nHB.factory Record SubChoice_isSubNzRing (R : nzRingType) S U of SubChoice R S U := {\n subring_closed_subproof : subring_closed S\n}.\n\nModule SubChoice_isSubRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubChoice_isSubNzRing.Build instead.\")]\nNotation Build R S U := (SubChoice_isSubNzRing.Build R S U) (only parsing).\nEnd SubChoice_isSubRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubChoice_isSubNzRing instead.\")]\nNotation SubChoice_isSubRing R S U :=\n (SubChoice_isSubNzRing R S U) (only parsing).\n\nHB.builders Context (R : nzRingType) S U of SubChoice_isSubNzRing R S U.\nHB.instance Definition _ := SubChoice_isSubZmodule.Build R S U\n (subring_closedB subring_closed_subproof).\nHB.instance Definition _ := SubZmodule_isSubNzRing.Build R S U\n subring_closed_subproof.\nHB.end.\n\n(*This factory constructs a sub-commutative ring structure with a positivity predicate from a chosen subset of a parent commutative ring, provided a proof that the subset is closed under addition, multiplication, and additive inverse.*)\nHB.factory Record SubChoice_isSubComPzRing (R : comPzRingType) S U\n of SubChoice R S U := {\n subring_closed_subproof : subring_closed S\n}.\n\nHB.builders Context (R : comPzRingType) S U of SubChoice_isSubComPzRing R S U.\nHB.instance Definition _ := SubChoice_isSubPzRing.Build R S U\n subring_closed_subproof.\nHB.instance Definition _ := SubPzRing_isSubComPzRing.Build R S U.\nHB.end.\n\n(*This factory constructs a sub-commutative non-zero ring structure from a chosen subset of a parent commutative non-zero ring, provided a proof that the subset is closed under addition, multiplication, and additive inverse.*)\nHB.factory Record SubChoice_isSubComNzRing (R : comNzRingType) S U\n of SubChoice R S U := {\n subring_closed_subproof : subring_closed S\n}.\n\nModule SubChoice_isSubComRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubChoice_isSubComNzRing.Build instead.\")]\nNotation Build R S U := (SubChoice_isSubComNzRing.Build R S U) (only parsing).\nEnd SubChoice_isSubComRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use SubChoice_isSubComNzRing instead.\")]\nNotation SubChoice_isSubComRing R S U :=\n (SubChoice_isSubComNzRing R S U) (only parsing).\n\nHB.builders Context (R : comNzRingType) S U of SubChoice_isSubComNzRing R S U.\nHB.instance Definition _ := SubChoice_isSubNzRing.Build R S U\n subring_closed_subproof.\nHB.instance Definition _ := SubNzRing_isSubComNzRing.Build R S U.\nHB.end.\n\n(*This factory constructs a sub-semimodule structure from a chosen subset of a parent left semimodule, provided a proof that the subset is closed under vector addition and scalar multiplication.*)\nHB.factory Record SubChoice_isSubLSemiModule\n (R : pzSemiRingType) (V : lSemiModType R) S W of SubChoice V S W := {\n subsemimod_closed_subproof : subsemimod_closed S\n}.\n\nHB.builders Context (R : pzSemiRingType) (V : lSemiModType R) S W\n of SubChoice_isSubLSemiModule R V S W.\nHB.instance Definition _ := SubChoice_isSubNmodule.Build V S W\n (subsemimod_closedD subsemimod_closed_subproof).\nHB.instance Definition _ := SubNmodule_isSubLSemiModule.Build R V S W\n subsemimod_closed_subproof.\nHB.end.\n\n(*This factory constructs a submodule structure from a chosen subset of a parent left module, provided a proof that the subset is closed under vector addition and scalar multiplication.*)\nHB.factory Record SubChoice_isSubLmodule (R : pzRingType) (V : lmodType R) S W\n of SubChoice V S W := {\n submod_closed_subproof : submod_closed S\n}.\n\nHB.builders Context (R : pzRingType) (V : lmodType R) S W\n of SubChoice_isSubLmodule R V S W.\nHB.instance Definition _ := SubChoice_isSubZmodule.Build V S W\n (submod_closedB submod_closed_subproof).\nHB.instance Definition _ := SubZmodule_isSubLmodule.Build R V S W\n submod_closed_subproof.\nHB.end.\n\n(*This factory constructs a sub-left-algebra structure from a chosen subset of a parent left algebra, provided a proof that the subset is closed under the algebra's addition, multiplication, and scalar multiplication.*)\nHB.factory Record SubChoice_isSubLalgebra (R : pzRingType) (A : lalgType R) S W\n of SubChoice A S W := {\n subalg_closed_subproof : subalg_closed S\n}.\n\nHB.builders Context (R : pzRingType) (A : lalgType R) S W\n of SubChoice_isSubLalgebra R A S W.\nHB.instance Definition _ := SubChoice_isSubNzRing.Build A S W\n (subalg_closedBM subalg_closed_subproof).\nHB.instance Definition _ := SubZmodule_isSubLmodule.Build R A S W\n (subalg_closedZ subalg_closed_subproof).\nHB.instance Definition _ := SubNzRing_SubLmodule_isSubLalgebra.Build R A S W.\nHB.end.\n\n(*This factory constructs a sub-algebra structure from a chosen subset of a parent algebra, provided a proof that the subset is closed under the algebra's addition, multiplication, and both left and right scalar multiplication.*)\nHB.factory Record SubChoice_isSubAlgebra (R : pzRingType) (A : algType R) S W\n of SubChoice A S W := {\n subalg_closed_subproof : subalg_closed S\n}.\n\nHB.builders Context (R : pzRingType) (A : algType R) S W\n of SubChoice_isSubAlgebra R A S W.\nHB.instance Definition _ := SubChoice_isSubLalgebra.Build R A S W\n subalg_closed_subproof.\nHB.instance Definition _ := SubLalgebra_isSubAlgebra.Build R A S W.\nHB.end.\n\n(*This factory constructs a sub-unit-ring structure from a chosen subset of a parent unit ring, provided a proof that the subset contains the multiplicative identity and is closed under addition, multiplication, additive inverse, and multiplicative inversion of its units.*)\nHB.factory Record SubChoice_isSubUnitRing (R : unitRingType) S U\n of SubChoice R S U := {\n divring_closed_subproof : divring_closed S\n}.\n\nHB.builders Context (R : unitRingType) S U of SubChoice_isSubUnitRing R S U.\nHB.instance Definition _ := SubChoice_isSubNzRing.Build R S U\n (divring_closedBM divring_closed_subproof).\nHB.instance Definition _ := SubNzRing_isSubUnitRing.Build R S U\n divring_closed_subproof.\nHB.end.\n\n(*This factory constructs a sub-commutative-unit-ring structure from a chosen subset of a parent commutative unit ring, provided a proof that the subset contains the multiplicative identity and is closed under addition, multiplication, additive inverse, and multiplicative inversion of its units.*)\nHB.factory Record SubChoice_isSubComUnitRing (R : comUnitRingType) S U\n of SubChoice R S U := {\n divring_closed_subproof : divring_closed S\n}.\n\nHB.builders Context (R : comUnitRingType) S U\n of SubChoice_isSubComUnitRing R S U.\nHB.instance Definition _ := SubChoice_isSubComNzRing.Build R S U\n (divring_closedBM divring_closed_subproof).\nHB.instance Definition _ := SubNzRing_isSubUnitRing.Build R S U\n divring_closed_subproof.\nHB.end.\n\n(*This factory constructs a sub-integral-domain structure from a chosen subset of a parent integral domain, provided a proof that the subset contains the multiplicative identity and is closed under addition, multiplication, additive inverse, and multiplicative inversion of its units.*)\nHB.factory Record SubChoice_isSubIntegralDomain (R : idomainType) S U\n of SubChoice R S U := {\n divring_closed_subproof : divring_closed S\n}.\n\nHB.builders Context (R : idomainType) S U\n of SubChoice_isSubIntegralDomain R S U.\nHB.instance Definition _ := SubChoice_isSubComUnitRing.Build R S U\n divring_closed_subproof.\n(*A notation to automatically construct a sub-N-module structure for a given substructure by inferring the necessary closure properties for scalar multiplication by natural numbers from the existing additive closure property.*)\nNotation \"[ 'SubChoice_isSubNmodule' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubNmodule.Build _ _ U rpred0D)\n (format \"[ 'SubChoice_isSubNmodule' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation to automatically construct a sub-Z-module structure for a given substructure by inferring the necessary closure properties for scalar multiplication by integers from the existing closure properties for addition and additive inverse.*)\nNotation \"[ 'SubChoice_isSubZmodule' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubZmodule.Build _ _ U (zmodClosedP _))\n (format \"[ 'SubChoice_isSubZmodule' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation to automatically construct a sub-non-zero-semiring structure for a given substructure that is already a sub-N-module, by inferring the necessary multiplicative closure property.*)\nNotation \"[ 'SubNmodule_isSubNzSemiRing' 'of' U 'by' <: ]\" :=\n (SubNmodule_isSubNzSemiRing.Build _ _ U (@rpred1M _ _))\n (format \"[ 'SubNmodule_isSubNzSemiRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ SubNmodule_isSubNzSemiRing of U by <: ] instead.\")]\n(*A deprecated notation for constructing a non-trivial subsemiring structure on a given submodule over the natural numbers, assuming the submodule contains the multiplicative identity.*)\nNotation \"[ 'SubNmodule_isSubSemiRing' 'of' U 'by' <: ]\" :=\n (SubNmodule_isSubNzSemiRing.Build _ _ U (@rpred1M _ _))\n (format \"[ 'SubNmodule_isSubSemiRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a non-trivial subsemiring structure on a subtype of a semiring, provided that the subtype contains the additive and multiplicative identities and is closed under addition and multiplication.*)\nNotation \"[ 'SubChoice_isSubNzSemiRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubNzSemiRing.Build _ _ U (semiringClosedP _))\n (format \"[ 'SubChoice_isSubNzSemiRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubChoice_isSubNzSemiRing' of U by <: ] instead.\")]\n(*A deprecated notation for constructing a non-trivial subsemiring structure on a subtype of a semiring, provided the subtype is closed under all semiring operations.*)\nNotation \"[ 'SubChoice_isSubSemiRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubNzSemiRing.Build _ _ U (semiringClosedP _))\n (format \"[ 'SubChoice_isSubSemiRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation views a given non-trivial subsemiring as a commutative non-trivial subsemiring, assuming the multiplication of the underlying ambient semiring is commutative.*)\nNotation \"[ 'SubNzSemiRing_isSubComNzSemiRing' 'of' U 'by' <: ]\" :=\n (SubNzSemiRing_isSubComNzSemiRing.Build _ _ U)\n (format \"[ 'SubNzSemiRing_isSubComNzSemiRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubNzSemiRing_isSubComNzSemiRing' of U by <: ] instead.\")]\n(*A deprecated notation for viewing a given non-trivial subsemiring as a commutative non-trivial subsemiring, when the multiplication of the parent semiring is commutative.*)\nNotation \"[ 'SubSemiRing_isSubComSemiRing' 'of' U 'by' <: ]\" :=\n (SubNzSemiRing_isSubComNzSemiRing.Build _ _ U)\n (format \"[ 'SubSemiRing_isSubComSemiRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a commutative non-trivial subsemiring structure on a subtype of a commutative semiring, provided the subtype is closed under all semiring operations.*)\nNotation \"[ 'SubChoice_isSubComNzSemiRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubComNzSemiRing.Build _ _ U (semiringClosedP _))\n (format \"[ 'SubChoice_isSubComNzSemiRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubChoice_isSubComNzSemiRing' of U by <: ] instead.\")]\n(*A deprecated notation for constructing a commutative non-trivial subsemiring structure on a subtype of a commutative semiring, provided the subtype is closed under all semiring operations.*)\nNotation \"[ 'SubChoice_isSubComSemiRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubComNzSemiRing.Build _ _ U (semiringClosedP _))\n (format \"[ 'SubChoice_isSubComSemiRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a non-trivial subring structure on a given submodule over the integers, provided the submodule is closed under multiplication and contains the multiplicative identity.*)\nNotation \"[ 'SubZmodule_isSubNzRing' 'of' U 'by' <: ]\" :=\n (SubZmodule_isSubNzRing.Build _ _ U (subringClosedP _))\n (format \"[ 'SubZmodule_isSubNzRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubZmodule_isSubNzRing' of U by <: ] instead.\")]\n(*A deprecated notation for constructing a non-trivial subring structure on a submodule over the integers, assuming the submodule is closed under multiplication and contains the multiplicative identity.*)\nNotation \"[ 'SubZmodule_isSubRing' 'of' U 'by' <: ]\" :=\n (SubZmodule_isSubNzRing.Build _ _ U (subringClosedP _))\n (format \"[ 'SubZmodule_isSubRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a non-trivial subring structure on a subtype of a ring, provided the subtype is closed under addition, additive inverse, multiplication, and contains the required identity elements.*)\nNotation \"[ 'SubChoice_isSubNzRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubNzRing.Build _ _ U (subringClosedP _))\n (format \"[ 'SubChoice_isSubNzRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubChoice_isSubNzRing' of U by <: ] instead.\")]\n(*A deprecated notation for constructing a non-trivial subring structure on a subtype of a ring, given that the subtype is closed under all ring operations.*)\nNotation \"[ 'SubChoice_isSubRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubNzRing.Build _ _ U (subringClosedP _))\n (format \"[ 'SubChoice_isSubRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation views a given non-trivial subring as a commutative non-trivial subring, assuming the multiplication of the underlying ambient ring is commutative.*)\nNotation \"[ 'SubNzRing_isSubComNzRing' 'of' U 'by' <: ]\" :=\n (SubNzRing_isSubComNzRing.Build _ _ U)\n (format \"[ 'SubNzRing_isSubComNzRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubNzRing_isSubComNzRing' of U by <: ] instead.\")]\n(*A deprecated notation for viewing a given non-trivial subring as a commutative non-trivial subring, when the multiplication of the parent ring is commutative.*)\nNotation \"[ 'SubRing_isSubComRing' 'of' U 'by' <: ]\" :=\n (SubNzRing_isSubComNzRing.Build _ _ U)\n (format \"[ 'SubRing_isSubComRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a commutative non-trivial subring structure on a subtype of a commutative ring, provided the subtype is closed under all ring operations.*)\nNotation \"[ 'SubChoice_isSubComNzRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubComNzRing.Build _ _ U (subringClosedP _))\n (format \"[ 'SubChoice_isSubComNzRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubChoice_isSubComNzRing' of U by <: ] instead.\")]\n(*A deprecated notation for constructing a commutative non-trivial subring structure on a subtype of a commutative ring, provided the subtype is closed under all ring operations.*)\nNotation \"[ 'SubChoice_isSubComRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubComNzRing.Build _ _ U (subringClosedP _))\n (format \"[ 'SubChoice_isSubComRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a left subsemimodule structure from a given submodule over the natural numbers, provided it is closed under scalar multiplication by elements of the associated scalar semiring.*)\nNotation \"[ 'SubNmodule_isSubLSemiModule' 'of' U 'by' <: ]\" :=\n (SubNmodule_isSubLSemiModule.Build _ _ _ U (subsemimodClosedP _))\n (format \"[ 'SubNmodule_isSubLSemiModule' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a left subsemimodule structure on a subtype of a left semimodule, provided the subtype is closed under addition and scalar multiplication.*)\nNotation \"[ 'SubChoice_isSubLSemiModule' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubLSemiModule.Build _ _ _ U (subsemimodClosedP _))\n (format \"[ 'SubChoice_isSubLSemiModule' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a left submodule structure from a given submodule over the integers, provided it is closed under scalar multiplication by elements of the associated scalar ring.*)\nNotation \"[ 'SubZmodule_isSubLmodule' 'of' U 'by' <: ]\" :=\n (SubZmodule_isSubLmodule.Build _ _ _ U (submodClosedP _))\n (format \"[ 'SubZmodule_isSubLmodule' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a left submodule structure on a subtype of a left module, provided the subtype is closed under addition, additive inverse, and scalar multiplication.*)\nNotation \"[ 'SubChoice_isSubLmodule' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubLmodule.Build _ _ _ U (submodClosedP _))\n (format \"[ 'SubChoice_isSubLmodule' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a left sub-semialgebra structure on a given substructure that is both a non-trivial subsemiring and a left sub-semimodule.*)\nNotation \"[ 'SubNzSemiRing_SubLSemiModule_isSubLSemiAlgebra' 'of' U 'by' <: ]\" :=\n (SubNzSemiRing_SubLSemiModule_isSubLSemiAlgebra.Build _ _ _ U)\n (format \"[ 'SubNzSemiRing_SubLSemiModule_isSubLSemiAlgebra' 'of' U 'by' <: ]\")\n : form_scope.\n\n(*This notation constructs a left sub-algebra structure on a given substructure that is both a non-trivial subring and a left submodule.*)\nNotation \"[ 'SubNzRing_SubLmodule_isSubLalgebra' 'of' U 'by' <: ]\" :=\n (SubNzRing_SubLmodule_isSubLalgebra.Build _ _ _ U)\n (format \"[ 'SubNzRing_SubLmodule_isSubLalgebra' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubNzRing_SubLmodule_isSubLalgebra' of U by <: ] instead.\")]\n(*A deprecated notation for constructing a left sub-algebra structure on a given substructure that qualifies as both a non-trivial subring and a left submodule.*)\nNotation \"[ 'SubRing_SubLmodule_isSubLalgebra' 'of' U 'by' <: ]\" :=\n (SubNzRing_SubLmodule_isSubLalgebra.Build _ _ _ U)\n (format \"[ 'SubRing_SubLmodule_isSubLalgebra' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a left sub-algebra structure on a subtype of a left-algebra, provided the subtype is closed under addition, additive inverse, multiplication, and scalar multiplication, and contains the required identity elements.*)\nNotation \"[ 'SubChoice_isSubLalgebra' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubLalgebra.Build _ _ _ U (subalgClosedP _))\n (format \"[ 'SubChoice_isSubLalgebra' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation views a given left sub-semialgebra as a (two-sided) sub-semialgebra.*)\nNotation \"[ 'SubLSemiAlgebra_isSubSemiAlgebra' 'of' U 'by' <: ]\" :=\n (SubLSemiAlgebra_isSubSemiAlgebra.Build _ _ _ U)\n (format \"[ 'SubLSemiAlgebra_isSubSemiAlgebra' 'of' U 'by' <: ]\")\n : form_scope.\n\n(*This notation views a given left sub-algebra as a (two-sided) sub-algebra.*)\nNotation \"[ 'SubLalgebra_isSubAlgebra' 'of' U 'by' <: ]\" :=\n (SubLalgebra_isSubAlgebra.Build _ _ _ U)\n (format \"[ 'SubLalgebra_isSubAlgebra' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a (two-sided) sub-algebra structure on a subtype of an algebra, provided the subtype is closed under all algebra operations.*)\nNotation \"[ 'SubChoice_isSubAlgebra' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubAlgebra.Build _ _ _ U (subalgClosedP _))\n (format \"[ 'SubChoice_isSubAlgebra' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation promotes a non-trivial subring to a sub-division-ring, provided it is closed under multiplicative inverse for all its non-zero elements.*)\nNotation \"[ 'SubNzRing_isSubUnitRing' 'of' U 'by' <: ]\" :=\n (SubNzRing_isSubUnitRing.Build _ _ U (divringClosedP _))\n (format \"[ 'SubNzRing_isSubUnitRing' 'of' U 'by' <: ]\")\n : form_scope.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use [ 'SubNzRing_isSubUnitRing' of U by <: ] instead.\")]\n(*A deprecated notation for promoting a non-trivial subring to a sub-division-ring, provided it is closed under multiplicative inverse for all its non-zero elements.*)\nNotation \"[ 'SubRing_isSubUnitRing' 'of' U 'by' <: ]\" :=\n (SubNzRing_isSubUnitRing.Build _ _ U (divringClosedP _))\n (format \"[ 'SubRing_isSubUnitRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a sub-division-ring structure on a subtype of a division ring, provided the subtype is closed under all ring operations and multiplicative inverse for non-zero elements.*)\nNotation \"[ 'SubChoice_isSubUnitRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubUnitRing.Build _ _ U (divringClosedP _))\n (format \"[ 'SubChoice_isSubUnitRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a subfield structure on a subtype of a field, provided the subtype is closed under all field operations, including addition, additive inverse, multiplication, and multiplicative inverse for non-zero elements.*)\nNotation \"[ 'SubChoice_isSubComUnitRing' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubComUnitRing.Build _ _ U (divringClosedP _))\n (format \"[ 'SubChoice_isSubComUnitRing' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a proof that a given subset of a ring, which is already established as a commutative unit subring, also forms a sub integral domain. The additional property of having no zero divisors is inferred automatically.*)\nNotation \"[ 'SubComUnitRing_isSubIntegralDomain' 'of' U 'by' <: ]\" :=\n (SubComUnitRing_isSubIntegralDomain.Build _ _ U)\n (format \"[ 'SubComUnitRing_isSubIntegralDomain' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a proof that a subset of a division ring, specified by a membership predicate, forms a sub integral domain. The necessary closure properties for the subset are inferred automatically.*)\nNotation \"[ 'SubChoice_isSubIntegralDomain' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubIntegralDomain.Build _ _ U (divringClosedP _))\n (format \"[ 'SubChoice_isSubIntegralDomain' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation constructs a proof that a given subset of a field, already known to be a sub integral domain, also constitutes a subfield. The required property of containing multiplicative inverses for non-zero elements is inferred automatically.*)\nNotation \"[ 'SubIntegralDomain_isSubField' 'of' U 'by' <: ]\" :=\n (SubIntegralDomain_isSubField.Build _ _ U (frefl _))\n (format \"[ 'SubIntegralDomain_isSubField' 'of' U 'by' <: ]\")\n : form_scope.\n\nEnd SubExports.\nHB.export SubExports.\n\nModule Theory.\n\n(*This definition states that the addition operation is associative, meaning that for any three elements, the result is the same whether the first two are added first or the last two are added first.*)\nDefinition addrA := @addrA.\n(*This definition states that the addition operation is commutative, meaning that for any two elements, the order in which they are added does not affect the sum.*)\nDefinition addrC := @addrC.\n(*This definition states that adding the additive identity to any element on the right results in the original element.*)\nDefinition add0r := @add0r.\n(*This definition states that adding the additive inverse of an element to the element itself on the right yields the additive identity.*)\nDefinition addNr := @addNr.\n(*This definition states that adding any element to the additive identity on the right results in that same element.*)\nDefinition addr0 := addr0.\n(*This definition states that adding an element to its additive inverse on the right yields the additive identity.*)\nDefinition addrN := addrN.\n(*This definition states that subtracting any element from itself results in the additive identity.*)\nDefinition subrr := subrr.\n(*This definition combines commutativity and associativity of addition, stating that for any three elements, the sum of the first element with the sum of the second and third is equal to the sum of the second element with the sum of the first and third.*)\nDefinition addrCA := addrCA.\n(*This definition combines associativity and commutativity of addition, stating that for any three elements, the sum of the sum of the first two with the third is equal to the sum of the sum of the first and third with the second.*)\nDefinition addrAC := addrAC.\n(*This definition combines associativity and commutativity of addition, stating that for any three elements, adding the first to the sum of the second and third is equivalent to adding the sum of the first and third to the second.*)\nDefinition addrACA := addrACA.\n(*This definition expresses a right cancellation property, stating that adding an element and then subtracting that same element on the right results in the original element.*)\nDefinition addKr := addKr.\n(*This definition expresses a right cancellation property, stating that subtracting an element and then adding that same element on the right results in the original element.*)\nDefinition addNKr := addNKr.\n(*This definition expresses a right cancellation property for addition, asserting that adding a first element to a second and then subtracting the first results in the second.*)\nDefinition addrK := addrK.\n(*This definition expresses a right cancellation property involving subtraction, asserting that adding a first element to the difference of a second and the first results in the second.*)\nDefinition addrNK := addrNK.\n(*This definition states a cancellation property, asserting that adding two elements and then subtracting the first element from the sum yields the second element.*)\nDefinition subrK := subrK.\n(*This definition states a cancellation property for subtraction, asserting that subtracting a difference from the original minuend yields the original subtrahend.*)\nDefinition subKr := subKr.\n(*This definition states that addition is right-injective, meaning that if adding a given element to two other elements yields the same result, then those two other elements must be equal.*)\nDefinition addrI := @addrI.\n(*This definition states that addition is left-injective, meaning that if adding the same element on the right to two other elements yields the same result, then those two other elements must be equal.*)\nDefinition addIr := @addIr.\n(*This definition states that subtraction from a fixed element is injective, meaning that if subtracting two different elements from a given element results in the same difference, then those two different elements must be equal.*)\nDefinition subrI := @subrI.\n(*This definition states that subtracting a fixed element is injective, meaning that if subtracting a given element from two different elements results in the same difference, then those two different elements must be equal.*)\nDefinition subIr := @subIr.\nArguments addrI {V} y [x1 x2].\nArguments addIr {V} x [x1 x2].\nArguments subrI {V} y [x1 x2].\nArguments subIr {V} x [x1 x2].\n(*This definition states that taking the additive inverse of the additive inverse of an element returns the original element.*)\nDefinition opprK := @opprK.\nArguments opprK {V}.\n(*This definition states that the additive inverse operation is injective, meaning that if two elements have the same additive inverse, they must be equal.*)\nDefinition oppr_inj := @oppr_inj.\nArguments oppr_inj {V} [x1 x2].\n(*This definition states that the additive inverse of the additive identity element is the additive identity element itself.*)\nDefinition oppr0 := oppr0.\n(*This definition states that if the additive inverse of an element is the additive identity, then the element itself must be the additive identity.*)\nDefinition oppr_eq0 := oppr_eq0.\n(*This definition states that the additive inverse operation distributes over addition, meaning the additive inverse of a sum is the sum of the additive inverses.*)\nDefinition opprD := opprD.\n(*This definition states that the additive inverse of a difference between two elements is equal to the difference of the same elements in reverse order.*)\nDefinition opprB := opprB.\n(*This definition provides a rule for re-associating subtraction with addition, stating that subtracting an element from a sum is equivalent to adding the first summand to the difference of the second summand and the subtrahend.*)\nDefinition addrKA := addrKA.\n(*This lemma states that the result of subtracting one difference from another, where both differences share the same subtrahend, is equivalent to the difference of their minuends.*)\nDefinition subrKA := subrKA.\n(*This lemma states that subtracting the additive identity from any ring element results in the original element.*)\nDefinition subr0 := subr0.\n(*This lemma states that subtracting a ring element from the additive identity is equivalent to taking the additive inverse of that element.*)\nDefinition sub0r := sub0r.\n(*This lemma states that the difference of two ring elements is the additive identity if and only if the two elements are equal.*)\nDefinition subr_eq := subr_eq.\n(*This lemma states that the sum of two ring elements is the additive identity if and only if the first element is the additive inverse of the second.*)\nDefinition addr0_eq := addr0_eq.\n(*This lemma states that if the difference of two ring elements is the additive identity, then the two elements are equal.*)\nDefinition subr0_eq := subr0_eq.\n(*This lemma states that if two ring elements are equal, their difference is the additive identity.*)\nDefinition subr_eq0 := subr_eq0.\n(*This lemma states that if a ring element is equal to the additive inverse of another, their sum is the additive identity.*)\nDefinition addr_eq0 := addr_eq0.\n(*This lemma states that two ring elements are equal if and only if their additive inverses are equal.*)\nDefinition eqr_opp := eqr_opp.\n(*This lemma states that a ring element is equal to the additive inverse of another if and only if the second element is equal to the additive inverse of the first.*)\nDefinition eqr_oppLR := eqr_oppLR.\n(*This lemma states that the summation of the additive inverses of a sequence of ring elements is equal to the additive inverse of the summation of the original elements.*)\nDefinition sumrN := sumrN.\n(*This lemma provides a formula for computing the sum of a function over a domain of two boolean values, which is the sum of the function applied to true and the function applied to false.*)\nDefinition sumrB := sumrB.\n(*This lemma states that the product of a summation of ring elements and another ring element is equal to the summation of the products of each element with that other element.*)\nDefinition sumrMnl := sumrMnl.\n(*This lemma states that the product of a ring element and a summation of other ring elements is equal to the summation of the products of that element with each of the other elements.*)\nDefinition sumrMnr := sumrMnr.\n(*This lemma states that the summation of a constant ring element over a finite domain is equal to the product of the cardinality of the domain and the constant element.*)\nDefinition sumr_const := sumr_const.\n(*This lemma states that the summation of a constant ring element over the range of natural numbers from zero up to, but not including, a given natural number is equal to the product of that number and the constant element.*)\nDefinition sumr_const_nat := sumr_const_nat.\n(*This lemma provides the formula for a telescoping sum, stating that the sum of the differences of a function at consecutive values over a range is equal to the difference of the function evaluated at the endpoints of that range.*)\nDefinition telescope_sumr := telescope_sumr.\n(*This lemma states that the sum of a sequence of values equals the difference between the final and initial values of a second function, provided that each value in the sequence corresponds to the increment of the second function at each step.*)\nDefinition telescope_sumr_eq := @telescope_sumr_eq.\nArguments telescope_sumr_eq {V n m} f u.\n(*This lemma states that multiplying any ring element by the natural number zero results in the additive identity of the ring.*)\nDefinition mulr0n := mulr0n.\n(*This lemma states that multiplying any ring element by the natural number one results in the original element.*)\nDefinition mulr1n := mulr1n.\n(*This lemma states that multiplying a ring element by the natural number two is equivalent to adding the element to itself.*)\nDefinition mulr2n := mulr2n.\n(*This lemma gives a recursive formula for the scalar multiplication of a ring element by a natural number. It asserts that multiplying a ring element by the successor of a number is the same as adding the element to the result of multiplying it by the original number.*)\nDefinition mulrS := mulrS.\n(*This lemma gives a right-associative recursive formula for the scalar multiplication of a ring element by a natural number. It asserts that multiplying a ring element by the successor of a number is the same as adding the result of multiplying it by the original number to the element itself.*)\nDefinition mulrSr := mulrSr.\n(*This lemma relates scalar multiplication to a boolean value, stating that the product of a ring element and a boolean converted to a natural number is the element itself if the boolean is true, and the additive identity if the boolean is false.*)\nDefinition mulrb := mulrb.\n(*This lemma states that multiplying the additive identity of a ring by any natural number results in the additive identity.*)\nDefinition mul0rn := mul0rn.\n(*This lemma states that multiplying the additive inverse of a ring element by a natural number is equivalent to the additive inverse of the product of the original element and the natural number.*)\nDefinition mulNrn := mulNrn.\n(*This lemma states that scalar multiplication by a natural number distributes over the addition of ring elements.*)\nDefinition mulrnDl := mulrnDl.\n(*This lemma states that scalar multiplication of a ring element distributes over the addition of natural numbers.*)\nDefinition mulrnDr := mulrnDr.\n(*This lemma states that multiplying a summation of ring elements by a natural number is equivalent to taking the summation of the products of each individual element with that natural number.*)\nDefinition mulrnBl := mulrnBl.\n(*This lemma states that multiplying a ring element by a summation of natural numbers is equivalent to taking the summation of the products of the ring element with each individual natural number.*)\nDefinition mulrnBr := mulrnBr.\n(*This lemma states that scaling a ring element by a product of two natural numbers is equivalent to successively scaling by each natural number. In other words, multiplying a ring element by the first natural number and then multiplying the result by the second is the same as multiplying the original ring element by the product of the two natural numbers.*)\nDefinition mulrnA := mulrnA.\n(*This lemma states that in a context where two ring elements commute, scaling one element by a natural number and then multiplying by the second element is equivalent to first multiplying the two elements and then scaling the result by the natural number.*)\nDefinition mulrnAC := mulrnAC.\n(*This definition describes scalar multiplication by a natural number as the result of repeatedly applying the addition of a given ring element, starting from another ring element.*)\nDefinition iter_addr := iter_addr.\n(*This definition specifies that scalar multiplication by a natural number is equivalent to repeatedly adding a ring element to the additive identity a given number of times.*)\nDefinition iter_addr_0 := iter_addr_0.\n(*This lemma states that ring multiplication is associative, meaning the order of evaluation does not matter when multiplying three elements.*)\nDefinition mulrA := @mulrA.\n(*This lemma asserts that the multiplicative identity is a right identity, meaning any ring element multiplied by the multiplicative identity results in the original element.*)\nDefinition mul1r := @mul1r.\n(*This lemma asserts that the multiplicative identity is a left identity, meaning the multiplicative identity multiplied by any ring element results in that same element.*)\nDefinition mulr1 := @mulr1.\n(*This lemma states that multiplication distributes over addition from the left. Multiplying an element by a sum of two other elements yields the same result as summing the products of the first element with each of the other two.*)\nDefinition mulrDl := @mulrDl.\n(*This lemma states that multiplication distributes over addition from the right. Multiplying a sum of two elements by a third element yields the same result as summing the products of each of the first two elements with the third.*)\nDefinition mulrDr := @mulrDr.\n(*This lemma states that in a non-trivial ring, the multiplicative identity is distinct from the additive identity.*)\nDefinition oner_neq0 := @oner_neq0.\n(*This definition characterizes a trivial ring, where the multiplicative identity is equal to the additive identity.*)\nDefinition oner_eq0 := oner_eq0.\n(*This lemma states that any ring element multiplied by the additive identity results in the additive identity.*)\nDefinition mul0r := @mul0r.\n(*This lemma states that the additive identity multiplied by any ring element results in the additive identity.*)\nDefinition mulr0 := @mulr0.\n(*This lemma states that multiplying a ring element by the additive inverse of another element is equivalent to taking the additive inverse of their product.*)\nDefinition mulrN := mulrN.\n(*This lemma states that multiplying the additive inverse of a ring element by another element is equivalent to taking the additive inverse of their product.*)\nDefinition mulNr := mulNr.\n(*This lemma states that the product of the additive inverses of two ring elements is equal to the product of the elements themselves.*)\nDefinition mulrNN := mulrNN.\n(*This lemma states that multiplying the additive inverse of the multiplicative identity by a ring element results in the additive inverse of that element.*)\nDefinition mulN1r := mulN1r.\n(*This lemma states that multiplying a ring element by the additive inverse of the multiplicative identity results in the additive inverse of that element.*)\nDefinition mulrN1 := mulrN1.\n(*This lemma states that multiplication distributes over a finite sum of ring elements from the left. An element multiplied by the sum is equal to the sum of the products of that element with each term in the original sum.*)\nDefinition mulr_suml := mulr_suml.\n(*This lemma states that multiplication distributes over a finite sum of ring elements from the right. A sum multiplied by an element is equal to the sum of the products of each term in the original sum with that element.*)\nDefinition mulr_sumr := mulr_sumr.\n(*This lemma states that multiplying the ring element corresponding to a boolean value by another ring element results in the second element if the boolean is true, and the additive identity if the boolean is false.*)\nDefinition mulrBl := mulrBl.\n(*This lemma states that multiplying a ring element by the ring element corresponding to a boolean value results in the original element if the boolean is true, and the additive identity if the boolean is false.*)\nDefinition mulrBr := mulrBr.\n(*This lemma asserts an associative-like property between ring multiplication and scalar multiplication by a natural number. Multiplying a ring element by the result of scaling another element by a natural number is equivalent to first multiplying the two ring elements and then scaling their product by the same natural number.*)\nDefinition mulrnAl := mulrnAl.\n(*This lemma asserts an associative-like property between scalar multiplication by a natural number and ring multiplication, which holds when the elements commute. Scaling a ring element by a natural number and then multiplying by a second commuting element is equivalent to first multiplying the two ring elements and then scaling their product by the same natural number.*)\nDefinition mulrnAr := mulrnAr.\n(*This lemma states that scalar multiplication by a natural number distributes over the addition of ring elements. Scaling a sum of two ring elements by a natural number is equivalent to summing the results of scaling each element individually by that natural number.*)\nDefinition mulr_natl := mulr_natl.\n(*This lemma states that scalar multiplication by a natural number distributes over the addition of natural numbers. Scaling a ring element by a sum of two natural numbers is equivalent to summing the results of scaling the ring element by each natural number separately.*)\nDefinition mulr_natr := mulr_natr.\n(*This lemma states that the ring embedding for natural numbers preserves addition. The ring element corresponding to a sum of two natural numbers is equal to the sum of their individual ring embeddings.*)\nDefinition natrD := natrD.\n(*This definition gives a shorthand for adding the multiplicative identity to the ring embedding of a natural number, with the identity on the left.*)\nDefinition nat1r := nat1r.\n(*This definition gives a shorthand for adding the multiplicative identity to the ring embedding of a natural number, with the identity on the right.*)\nDefinition natr1 := natr1.\nArguments natr1 {R} n.\nArguments nat1r {R} n.\n(*This lemma states that the canonical ring embedding of a natural number which results from a boolean value is equal to the ring embedding of that boolean. That is, casting a boolean to a natural number and then to a ring element is the same as casting the boolean directly to a ring element.*)\nDefinition natrB := natrB.\n(*This lemma states that the ring expression corresponding to the sum of a sequence of natural numbers is equivalent to the sum of the ring expressions of each natural number in the sequence.*)\nDefinition natr_sum := natr_sum.\n(*This lemma states that the ring expression for the product of two natural numbers equals the product of their individual ring expressions.*)\nDefinition natrM := natrM.\n(*This lemma states that the ring expression for a natural number raised to a natural number power is equivalent to the ring expression of the base raised to that power.*)\nDefinition natrX := natrX.\n(*This definition represents the additive identity, or zero, as a formal ring expression.*)\nDefinition expr0 := expr0.\n(*This definition constructs the formal ring expression for the successor of a natural number, effectively representing addition by one within the expression language.*)\nDefinition exprS := exprS.\n(*This definition represents the multiplicative identity, or one, as a formal ring expression.*)\nDefinition expr1 := expr1.\n(*This definition represents the number two as a formal ring expression, defined as the sum of one and one.*)\nDefinition expr2 := expr2.\n(*This definition provides a formal ring expression representing the natural number zero.*)\nDefinition expr0n := expr0n.\n(*This definition provides a formal ring expression representing the natural number one.*)\nDefinition expr1n := expr1n.\n(*This definition constructs a formal ring expression representing the division of two ring expressions.*)\nDefinition exprD := exprD.\n(*This definition constructs the formal ring expression for the sum of a given ring expression and one.*)\nDefinition exprSr := exprSr.\n(*This lemma states that the formal expression encapsulating a finite sum over a set of indexed ring elements is equivalent to the finite sum of the formal expressions of those elements.*)\nDefinition expr_sum := expr_sum.\n(*This lemma establishes the symmetry of addition for commutative ring expressions, stating that swapping the two operands does not change the result.*)\nDefinition commr_sym := commr_sym.\n(*This lemma asserts the reflexivity of equality for commutative ring expressions, stating that any expression is equal to itself.*)\nDefinition commr_refl := commr_refl.\n(*This lemma states that for a commutative ring expression, adding the zero expression is an identity operation, leaving the original expression unchanged.*)\nDefinition commr0 := commr0.\n(*This lemma states that for a commutative ring expression, multiplying by the one expression is an identity operation, leaving the original expression unchanged.*)\nDefinition commr1 := commr1.\n(*This lemma states that for a commutative ring expression, adding an expression to its additive inverse results in the zero expression.*)\nDefinition commrN := commrN.\n(*This lemma states that for a commutative ring expression, multiplying an expression by the additive inverse of one is equivalent to taking the additive inverse of the expression.*)\nDefinition commrN1 := commrN1.\n(*This lemma provides a rule for simplifying division within a commutative ring expression, often relating it to multiplication by an inverse.*)\nDefinition commrD := commrD.\n(*This lemma provides a rule for simplifying subtraction within a commutative ring expression, for instance, how it interacts with addition or negation.*)\nDefinition commrB := commrB.\n(*This lemma asserts that the order of terms in a finite sum of commutative ring expressions can be rearranged without changing the total sum, due to the commutativity of addition.*)\nDefinition commr_sum := commr_sum.\n(*This lemma asserts that the order of factors in a finite product of commutative ring expressions can be rearranged without changing the final product, due to the commutativity of multiplication.*)\nDefinition commr_prod := commr_prod.\n(*This lemma describes a property of multiplying a commutative ring expression by a natural number, which is defined as repeated addition.*)\nDefinition commrMn := commrMn.\n(*This lemma establishes the commutativity of multiplication for commutative ring expressions, stating that swapping the two factors does not change the product.*)\nDefinition commrM := commrM.\n(*This lemma provides a simplification rule for expressions involving natural numbers within a commutative ring context.*)\nDefinition commr_nat := commr_nat.\n(*This lemma provides a rule for simplifying an exponentiation of a commutative ring expression, such as expanding a power of a sum or product.*)\nDefinition commrX := commrX.\n(*This lemma states that in a ring expression, multiplication by a natural number, interpreted as repeated addition, commutes with the ring's multiplication operation.*)\nDefinition exprMn_comm := exprMn_comm.\n(*This lemma provides a simplification rule for an expression involving the sign of a commutative ring element.*)\nDefinition commr_sign := commr_sign.\n(*This lemma establishes an associative-like property for iterated multiplication by natural numbers within a ring expression, stating that multiplying by one natural number then by another is equivalent to multiplying by their product.*)\nDefinition exprMn_n := exprMn_n.\n(*This lemma provides a rule for simplifying a multiplicative ring expression, often concerning its associativity or its interaction with other operations.*)\nDefinition exprM := exprM.\n(*This definition registers a given expression as being both associative and commutative, for use by simplification tactics.*)\nDefinition exprAC := exprAC.\n(*This lemma states that evaluating a ring expression with arguments taken modulo a certain value is equivalent to evaluating the expression on the original arguments and then taking the result modulo that same value.*)\nDefinition expr_mod := expr_mod.\n(*This lemma states that if a number divides each argument of a given ring expression, then that number also divides the result of the expression.*)\nDefinition expr_dvd := expr_dvd.\n(*This lemma asserts that the sign function on a ring is an odd function, meaning that applying it to the additive opposite of an element yields the additive opposite of its result on the original element.*)\nDefinition signr_odd := signr_odd.\n(*This lemma states that the sign of a ring element is zero if and only if the element itself is zero.*)\nDefinition signr_eq0 := signr_eq0.\n(*This lemma states that the sign of a product of two ring elements is equal to the product of their signs.*)\nDefinition mulr_sign := mulr_sign.\n(*This lemma relates the sign of a sum of two ring elements to a boolean combination of their individual signs.*)\nDefinition signr_addb := signr_addb.\n(*This lemma states that for any ring element, the sign of its additive opposite is the additive opposite of its sign.*)\nDefinition signrN := signrN.\n(*This definition provides a characterization for the sign of a ring element, typically by cases based on whether the element is positive, negative, or zero.*)\nDefinition signrE := signrE.\n(*This definition constructs a multiplicative morphism instance for the sign function, formalizing the property that it preserves multiplication.*)\nDefinition mulr_signM := mulr_signM.\n(*This lemma relates the evaluation of a ring expression on a sequence of additively opposite arguments to the evaluation on the original arguments, accounting for sign changes based on properties of the expression and the number of arguments.*)\nDefinition exprNn := exprNn.\n(*This lemma states that the square of the additive opposite of a ring element is equal to the square of the element itself.*)\nDefinition sqrrN := sqrrN.\n(*This lemma states that the sign of the square of a ring element is always non-negative, meaning it is either one or zero.*)\nDefinition sqrr_sign := sqrr_sign.\n(*This definition provides a constructor for building a signed ring structure given a ring and a valid sign function.*)\nDefinition signrMK := signrMK.\n(*This lemma provides a boolean reflection for an integral domain, stating that a product of two elements equals zero if and only if at least one of the elements is zero.*)\nDefinition mulrI_eq0 := mulrI_eq0.\n(*This lemma states that any non-zero element of an integral domain is left-regular, allowing it to be cancelled from the left side of a multiplication.*)\nDefinition lreg_neq0 := lreg_neq0.\n(*This lemma states that if a left-regular element is multiplied by a second element and the product is zero, then the second element must be zero.*)\nDefinition mulrI0_lreg := mulrI0_lreg.\n(*This lemma states that the additive opposite of a left-regular element is also left-regular.*)\nDefinition lregN := lregN.\n(*This lemma states that the multiplicative identity, one, is always left-regular.*)\nDefinition lreg1 := lreg1.\n(*This lemma states that the product of two left-regular elements is also a left-regular element.*)\nDefinition lregM := lregM.\n(*This lemma states that any positive natural power of a left-regular element is also left-regular.*)\nDefinition lregX := lregX.\n(*This lemma states that a ring element is left-regular if and only if its sign is a left-regular element.*)\nDefinition lreg_sign := lreg_sign.\n(*This definition provides a predicate that evaluates to true if and only if a given ring element is left-regular, meaning it can be cancelled from the left in a multiplicative equation.*)\nDefinition lregP {R x} := @lregP R x.\n(*This lemma provides a boolean reflection for an integral domain, stating that a product of two elements equals zero if and only if at least one of the elements is zero.*)\nDefinition mulIr_eq0 := mulIr_eq0.\n(*This lemma states that if a right-regular element appears as the right-hand factor in a product that equals zero, then the left-hand factor must be zero.*)\nDefinition mulIr0_rreg := mulIr0_rreg.\n(*This lemma states that any non-zero element of an integral domain is right-regular, allowing it to be cancelled from the right side of a multiplication.*)\nDefinition rreg_neq0 := rreg_neq0.\n(*This lemma states that the additive opposite of a right-regular element is also right-regular.*)\nDefinition rregN := rregN.\n(*This lemma states that the multiplicative identity, one, is always right-regular.*)\nDefinition rreg1 := rreg1.\n(*This lemma states that the product of two right-regular elements is also a right-regular element.*)\nDefinition rregM := rregM.\n(*This lemma states that exponentiation of a ring element to a natural number power commutes with the operation of taking the corresponding element in the opposite ring.*)\nDefinition revrX := revrX.\n(*This lemma states that the formal indeterminate in a ring of polynomials is a regular element, meaning it is not a zero-divisor.*)\nDefinition rregX := rregX.\n(*This definition specifies the property of a ring element being regular, which means that multiplying it by any non-zero element of the ring yields a non-zero result.*)\nDefinition rregP {R x} := @rregP R x.\n(*This lemma establishes that the `n`-th order formal derivative operation on ring expressions commutes with another specific `n`-th order formal transformation.*)\nDefinition exprDn_comm := exprDn_comm.\n(*This lemma establishes that a specific `n`-th order formal transformation on ring expressions commutes with the `n`-th order formal derivative operation.*)\nDefinition exprBn_comm := exprBn_comm.\n(*This lemma states that formal substitution operations on ring expressions, when involving only the indeterminate, commute with each other.*)\nDefinition subrXX_comm := subrXX_comm.\n(*This lemma states that applying the first formal derivative operation `n` times to a ring expression is equivalent to applying the `n`-th formal derivative operation once.*)\nDefinition exprD1n := exprD1n.\n(*This lemma provides a property related to substituting the multiplicative identity, one, for the indeterminate in a ring expression.*)\nDefinition subrX1 := subrX1.\n(*This lemma provides a rule for the first formal derivative of the square of a ring element, expressing it in terms of the element and its first derivative.*)\nDefinition sqrrD1 := sqrrD1.\n(*This lemma provides a rule for a specific formal transformation, when applied to the square of a ring element.*)\nDefinition sqrrB1 := sqrrB1.\n(*This lemma establishes a property of the square of a ring expression that results from substituting the multiplicative identity, one, for its indeterminate.*)\nDefinition subr_sqr_1 := subr_sqr_1.\n(*This lemma states that the positive characteristic of a field cannot be zero.*)\nDefinition pcharf0 := pcharf0.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf0 instead.\")]\n(*This lemma states that the positive characteristic of a field cannot be zero.*)\nDefinition charf0 := pcharf0.\n(*This lemma states that the positive characteristic of a field is a prime number.*)\nDefinition pcharf_prime := pcharf_prime.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf_prime instead.\")]\n(*This lemma states that the positive characteristic of a field is a prime number.*)\nDefinition charf_prime := pcharf_prime.\n(*This lemma states that in a ring with a positive characteristic `p`, multiplying any ring element by the natural number `p` yields the additive identity.*)\nDefinition mulrn_pchar := mulrn_pchar.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use mulrn_pchar instead.\")]\n(*This lemma states that in a ring with a positive characteristic `p`, multiplying any ring element by the natural number `p` yields the additive identity.*)\nDefinition mulrn_char := mulrn_pchar.\n(*This lemma states that in a field with positive characteristic `p`, if a natural number `n` is a multiple of `p`, then multiplying any field element by `n` yields the additive identity.*)\nDefinition dvdn_pcharf := dvdn_pcharf.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use dvdn_pcharf instead.\")]\n(*This lemma states that in a field with positive characteristic `p`, if a natural number `n` is a multiple of `p`, then multiplying any field element by `n` yields the additive identity.*)\nDefinition dvdn_charf := dvdn_pcharf.\n(*This lemma states that in a ring with positive characteristic `p`, the ring element obtained by embedding the natural number `p` into the ring is the additive identity.*)\nDefinition pcharf_eq := pcharf_eq.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf_eq instead.\")]\n(*This lemma states that in a ring with positive characteristic `p`, the ring element obtained by embedding the natural number `p` into the ring is the additive identity.*)\nDefinition charf_eq := pcharf_eq.\n(*This lemma states that for a field with positive prime characteristic `p`, the binomial coefficient 'p choose k' evaluates to zero within the field for any natural number `k` that is strictly between zero and `p`.*)\nDefinition bin_lt_pcharf_0 := bin_lt_pcharf_0.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use bin_lt_pcharf_0 instead.\")]\n(*This lemma states that for a field with positive prime characteristic `p`, the binomial coefficient 'p choose k' evaluates to zero within the field for any natural number `k` that is strictly between zero and `p`.*)\nDefinition bin_lt_charf_0 := bin_lt_pcharf_0.\n(*This lemma states that applying the Frobenius automorphism to an element of a commutative ring with prime characteristic `p` is equivalent to raising that element to the `p`-th power.*)\nDefinition pFrobenius_autE := pFrobenius_autE.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autE instead.\")]\n(*This lemma states that applying the Frobenius automorphism to an element of a commutative ring with prime characteristic `p` is equivalent to raising that element to the `p`-th power.*)\nDefinition Frobenius_autE := pFrobenius_autE.\n(*This lemma states that the Frobenius automorphism preserves the additive identity of a ring.*)\nDefinition pFrobenius_aut0 := pFrobenius_aut0.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut0 instead.\")]\n(*This lemma states that the Frobenius automorphism preserves the additive identity of a ring.*)\nDefinition Frobenius_aut0 := pFrobenius_aut0.\n(*This lemma states that the Frobenius automorphism preserves the multiplicative identity of a ring.*)\nDefinition pFrobenius_aut1 := pFrobenius_aut1.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut1 instead.\")]\n(*This lemma states that the Frobenius automorphism preserves the multiplicative identity of a ring.*)\nDefinition Frobenius_aut1 := pFrobenius_aut1.\n(*This lemma states that in a polynomial ring over a field with positive characteristic, the Frobenius automorphism commutes with the formal derivative operation.*)\nDefinition pFrobenius_autD_comm := pFrobenius_autD_comm.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autD_comm instead.\")]\n(*This lemma states that in a polynomial ring over a field with positive characteristic, the Frobenius automorphism commutes with the formal derivative operation.*)\nDefinition Frobenius_autD_comm := pFrobenius_autD_comm.\n(*This definition specifies the Frobenius automorphism on a matrix over a ring of prime characteristic, which applies the Frobenius map element-wise to produce a new matrix.*)\nDefinition pFrobenius_autMn := pFrobenius_autMn.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autMn instead.\")]\n(*This definition is deprecated and has been replaced by `pFrobenius_autMn`. It defines the element-wise Frobenius automorphism for a matrix over a ring with prime characteristic.*)\nDefinition Frobenius_autMn := pFrobenius_autMn.\n(*This lemma shows that the Frobenius automorphism acts as the identity on natural numbers when they are interpreted as elements of a commutative ring with prime characteristic.*)\nDefinition pFrobenius_aut_nat := pFrobenius_aut_nat.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut_nat instead.\")]\n(*This definition is deprecated and has been replaced by `pFrobenius_aut_nat`. It shows that the Frobenius automorphism acts as the identity on natural numbers when they are interpreted as elements of a commutative ring with prime characteristic.*)\nDefinition Frobenius_aut_nat := pFrobenius_aut_nat.\n(*This lemma states that the Frobenius automorphism on a commutative algebra is a linear map over its base ring, meaning it commutes with scalar multiplication.*)\nDefinition pFrobenius_autM_comm := pFrobenius_autM_comm.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autM_comm instead.\")]\n(*This lemma is deprecated and has been replaced by `pFrobenius_autM_comm`. It states that the Frobenius automorphism on a commutative algebra commutes with scalar multiplication.*)\nDefinition Frobenius_autM_comm := pFrobenius_autM_comm.\n(*This definition specifies the Frobenius automorphism on a polynomial over a ring of prime characteristic, which applies the Frobenius map to each coefficient of the polynomial.*)\nDefinition pFrobenius_autX := pFrobenius_autX.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autX instead.\")]\n(*This definition is deprecated and has been replaced by `pFrobenius_autX`. It specifies the Frobenius automorphism on a polynomial, which acts by applying the Frobenius map to each coefficient.*)\nDefinition Frobenius_autX := pFrobenius_autX.\n(*This lemma states that applying the norm map after the Frobenius automorphism is equivalent to applying the Frobenius automorphism after the norm map.*)\nDefinition pFrobenius_autN := pFrobenius_autN.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autN instead.\")]\n(*This lemma is deprecated and has been replaced by `pFrobenius_autN`. It establishes that the Frobenius automorphism and the norm map commute.*)\nDefinition Frobenius_autN := pFrobenius_autN.\n(*This lemma states that the Frobenius automorphism on an algebra commutes with multiplication by elements from a specific base commutative ring.*)\nDefinition pFrobenius_autB_comm := pFrobenius_autB_comm.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autB_comm instead.\")]\n(*This lemma is deprecated and has been replaced by `pFrobenius_autB_comm`. It states that the Frobenius automorphism on an algebra commutes with multiplication by elements from a specific base commutative ring.*)\nDefinition Frobenius_autB_comm := pFrobenius_autB_comm.\n(*This lemma, also known as the Freshman's Dream, states that in a commutative ring of prime characteristic, raising a sum of two elements to the power of the characteristic is equivalent to the sum of each element raised to that same power.*)\nDefinition exprNn_pchar := exprNn_pchar.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use exprNn_pchar instead.\")]\n(*This lemma is deprecated and has been replaced by `exprNn_pchar`. It states that in a commutative ring of prime characteristic, exponentiation to the power of the characteristic distributes over addition.*)\nDefinition exprNn_char := exprNn_pchar.\n(*This lemma states that in any ring of characteristic two, the sum of any element with itself is the additive identity.*)\nDefinition addrr_pchar2 := addrr_pchar2.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use addrr_pchar2 instead.\")]\n(*This lemma is deprecated and has been replaced by `addrr_pchar2`. It states that in a ring of characteristic two, adding an element to itself yields zero.*)\nDefinition addrr_char2 := addrr_pchar2.\n(*This lemma states that in any ring of characteristic two, every element is its own additive inverse.*)\nDefinition oppr_pchar2 := oppr_pchar2.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use oppr_pchar2 instead.\")]\n(*This lemma is deprecated and has been replaced by `oppr_pchar2`. It states that in a ring of characteristic two, every element is its own additive inverse.*)\nDefinition oppr_char2 := oppr_pchar2.\n(*This lemma captures a specific property of adding a constant element from the prime subfield to another element in a ring of characteristic two.*)\nDefinition addrK_pchar2 := addrK_pchar2.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use addrK_pchar2 instead.\")]\n(*This lemma is deprecated and has been replaced by `addrK_pchar2`. It captures a specific property of adding a constant from the prime subfield to an element in a ring of characteristic two.*)\nDefinition addrK_char2 := addrK_pchar2.\n(*This lemma captures a specific property of adding a ring element to a constant from the prime subfield in a ring of characteristic two.*)\nDefinition addKr_pchar2 := addKr_pchar2.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use addKr_pchar2 instead.\")]\n(*This lemma is deprecated and has been replaced by `addKr_pchar2`. It captures a specific property of adding an element to a constant from the prime subfield in a ring of characteristic two.*)\nDefinition addKr_char2 := addKr_pchar2.\n(*This definition provides an alias for the concept of iterated multiplication of a ring element.*)\nDefinition iter_mulr := iter_mulr.\n(*This lemma states that iterating multiplication by a given ring element once on another element is equivalent to performing the multiplication once.*)\nDefinition iter_mulr_1 := iter_mulr_1.\n(*This lemma states that the product of a finite sequence where every element is the same constant ring element is equal to that constant raised to the power of the sequence length.*)\nDefinition prodr_const := prodr_const.\n(*This lemma states that the product of a constant sequence of natural numbers, when computed within a ring, is equal to the ring element corresponding to the constant value raised to the power of the sequence length.*)\nDefinition prodr_const_nat := prodr_const_nat.\n(*This lemma asserts the commutative property of ring multiplication, where swapping the order of two elements does not change their product.*)\nDefinition mulrC := @mulrC.\n(*This lemma states that, due to commutativity and associativity of ring multiplication, the first two operands in a three-element product can be swapped without changing the result.*)\nDefinition mulrCA := mulrCA.\n(*This lemma states that, due to associativity and commutativity of ring multiplication, the last two operands in a three-element product can be swapped without changing the result.*)\nDefinition mulrAC := mulrAC.\n(*This lemma demonstrates a combined application of associativity and commutativity for ring multiplication, allowing for reordering and re-association of three elements in a product.*)\nDefinition mulrACA := mulrACA.\n(*This definition recursively computes the exponentiation of a ring element to a natural number power.*)\nDefinition exprMn := exprMn.\n(*This lemma states that a ring element can be distributed into a product from the left, resulting in a product of terms each left-multiplied by that element, provided the element commutes with all original terms.*)\nDefinition prodrXl := prodrXl.\n(*This lemma states that a ring element can be distributed into a product from the right, resulting in a product of terms each right-multiplied by that element, provided the element commutes with all original terms.*)\nDefinition prodrXr := prodrXr.\n(*This lemma relates the product of the additive inverses of a sequence of ring elements to the product of the elements themselves, multiplied by negative one raised to the power of the sequence length.*)\nDefinition prodrN := prodrN.\n(*This lemma states that the product of a constant ring element over a domain of a certain size is equal to that element raised to the power of that size.*)\nDefinition prodrMn_const := prodrMn_const.\n(*This lemma states that in a commutative ring, the product of element-wise products of two sequences of ring elements is equal to the product of their individual products.*)\nDefinition prodrM_comm := prodrM_comm.\n(*This lemma states that an element commutes with the product of a sequence of elements if it commutes with every element in the sequence, allowing left multiplication by the element to be swapped with right multiplication.*)\nDefinition prodrMl_comm := prodrMl_comm.\n(*This lemma states that an element commutes with the product of a sequence of elements if it commutes with every element in the sequence, allowing right multiplication by the element to be swapped with left multiplication.*)\nDefinition prodrMr_comm := prodrMr_comm.\n(*This lemma provides a recursion rule for a product over a sequence, stating that the product is equal to the first element multiplied on the left by the product of the rest of the sequence.*)\nDefinition prodrMl := prodrMl.\n(*This lemma provides a recursion rule for a product over a sequence, stating that the product is equal to the product of the initial segment of the sequence multiplied on the right by the last element.*)\nDefinition prodrMr := prodrMr.\n(*This lemma states that in a commutative ring, the product of elements each raised to a constant natural number power is equal to the product of the elements raised to that same power.*)\nDefinition prodrMn := prodrMn.\n(*This lemma states that in a commutative ring, the product of elements over a reversed sequence is equal to the product over the original sequence.*)\nDefinition rev_prodr := rev_prodr.\n(*This lemma states that the product of a sequence of natural numbers, with each number mapped into a ring, is equal to the mapping of the product of the original sequence of natural numbers into that ring.*)\nDefinition natr_prod := natr_prod.\n(*This lemma states that in a commutative ring, the product of elements in a sequence is equivalent to the product of its unique elements, where each unique element is raised to a power equal to its frequency in the original sequence.*)\nDefinition prodr_undup_exp_count := prodr_undup_exp_count.\n(*This notation represents a formal expression for the divisibility of one natural number expression by another.*)\nDefinition exprDn := exprDn.\n(*This notation represents a formal boolean-valued expression constructed from a predicate on natural numbers.*)\nDefinition exprBn := exprBn.\n(*This lemma states that for any element in a ring, subtracting the element from itself yields the additive identity.*)\nDefinition subrXX := subrXX.\n(*This lemma states the expansion of the square of a difference of two elements in a commutative ring.*)\nDefinition sqrrD := sqrrD.\n(*This lemma states the expansion of the square of a sum of two elements in a commutative ring.*)\nDefinition sqrrB := sqrrB.\n(*This lemma provides the factorization for the difference of squares of two elements in a commutative ring.*)\nDefinition subr_sqr := subr_sqr.\n(*This lemma states that in a commutative ring, the difference between the square of a sum and the square of a difference of two elements is equal to four times their product.*)\nDefinition subr_sqrDB := subr_sqrDB.\n(*This definition provides a simplification rule for divisibility expressions within a ring of prime characteristic.*)\nDefinition exprDn_pchar := exprDn_pchar.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use exprDn_pchar instead.\")]\n(*This definition is deprecated and its use is discouraged in favor of `exprDn_pchar`. It provides a simplification rule for divisibility expressions within a ring of prime characteristic.*)\nDefinition exprDn_char := exprDn_pchar.\n(*This definition computes the product of a row vector and a scalar ring element, resulting in a new vector where each component is right-multiplied by the scalar.*)\nDefinition mulrV := mulrV.\n(*This definition specifies the division of two ring elements as the first element multiplied by the multiplicative inverse of the second.*)\nDefinition divrr := divrr.\n(*This definition computes the product of a scalar ring element and a row vector, resulting in a new vector where each component is left-multiplied by the scalar.*)\nDefinition mulVr := mulVr.\n(*This lemma states that for an invertible ring element, the additive inverse of its multiplicative inverse is equal to the multiplicative inverse of its additive inverse.*)\nDefinition invr_out := invr_out.\n(*This definition is a boolean predicate that evaluates to true if a given ring element has a two-sided multiplicative inverse, and false otherwise.*)\nDefinition unitrP {R x} := @unitrP R x.\n(*This definition implements the multiplication of a formal constant by a ring element within a framework for symbolic ring expressions.*)\nDefinition mulKr := mulKr.\n(*This definition computes the product of a scalar and a vector, where the scalar is first computed by multiplying a formal constant by a ring element.*)\nDefinition mulVKr := mulVKr.\n(*This lemma asserts that right multiplication by a unit element is cancellable, meaning that if two ring elements, when multiplied on the right by the same unit, yield equal results, then the original two elements must be equal.*)\nDefinition mulrK := mulrK.\n(*This lemma states that the mapping for right multiplication by a given ring element is injective if and only if that element is not a right zero-divisor.*)\nDefinition mulrVK := mulrVK.\n(*This lemma asserts that right division is cancellable for a unit divisor, meaning if a first ring element divided by a unit is equal to a second ring element divided by the same unit, then the first and second elements must be equal.*)\nDefinition divrK := divrK.\n(*This lemma states that multiplying any ring element on the right by the multiplicative identity element yields the original element.*)\nDefinition mulrI := mulrI.\n(*This lemma states that multiplying any ring element on the left by the multiplicative identity element yields the original element.*)\nDefinition mulIr := mulIr.\n(*This lemma states that dividing any ring element on the right by the multiplicative identity element yields the original element.*)\nDefinition divrI := divrI.\n(*This lemma states that dividing the multiplicative identity on the right by a unit ring element is equivalent to taking the inverse of that element.*)\nDefinition divIr := divIr.\n(*This lemma provides the rule for simplifying a telescoping product over a range of indices, stating that the product of ratios of consecutive values of a function, where divisors are units, simplifies to the ratio of the final value to the initial value.*)\nDefinition telescope_prodr := telescope_prodr.\n(*This lemma provides an equational form of the telescoping product rule, stating that the initial value of a function, multiplied by the product of ratios of its consecutive values where divisors are units, equals the final value of the function.*)\nDefinition telescope_prodr_eq := @telescope_prodr_eq.\nArguments telescope_prodr_eq {R n m} f u.\n(*This lemma provides a view of commutativity, stating that a ring element commutes with all other elements under multiplication if and only if right multiplication by that element is the same function as left multiplication by it.*)\nDefinition commrV := commrV.\n(*This lemma establishes that a ring element is a unit if and only if there exists another element, its inverse, such that their product is the multiplicative identity.*)\nDefinition unitrE := unitrE.\n(*This lemma states that taking the multiplicative inverse of a unit element twice returns the original element.*)\nDefinition invrK := @invrK.\nArguments invrK {R}.\n(*This lemma asserts that the multiplicative inverse operation is injective, meaning that if two unit ring elements have the same inverse, they must be equal.*)\nDefinition invr_inj := @invr_inj.\nArguments invr_inj {R} [x1 x2].\n(*This lemma provides a reflection property, stating that the boolean predicate checking if a ring element is a unit evaluates to true if and only if the element is mathematically a unit.*)\nDefinition unitrV := unitrV.\n(*This lemma states that the multiplicative identity element of a ring is a unit.*)\nDefinition unitr1 := unitr1.\n(*This lemma states that the multiplicative inverse of the identity element is the identity element itself.*)\nDefinition invr1 := invr1.\n(*This lemma states that dividing any ring element by the multiplicative identity element results in the original element.*)\nDefinition divr1 := divr1.\n(*This lemma states that dividing the multiplicative identity by a unit ring element is equivalent to taking the multiplicative inverse of that element.*)\nDefinition div1r := div1r.\n(*This definition specifies that the division of a ring element by a natural number is equivalent to the ring division of that element by the ring element that corresponds to the given natural number, provided the latter is a unit.*)\nDefinition natr_div := natr_div.\n(*This lemma states that the additive identity element (zero) is not a multiplicative unit in any non-trivial ring.*)\nDefinition unitr0 := unitr0.\n(*This lemma states that, by convention in a field, the multiplicative inverse of the additive identity (zero) is defined to be zero itself.*)\nDefinition invr0 := invr0.\n(*This lemma states that the additive inverse of the multiplicative identity element (negative one) is a multiplicative unit.*)\nDefinition unitrN1 := unitrN1.\n(*This lemma states that the additive opposite of any unit in a ring is also a unit.*)\nDefinition unitrN := unitrN.\n(*This lemma states that the multiplicative inverse of the additive inverse of the identity element (negative one) is itself.*)\nDefinition invrN1 := invrN1.\n(*This lemma states that the multiplicative inverse of the additive opposite of a unit ring element is equal to the additive opposite of its multiplicative inverse.*)\nDefinition invrN := invrN.\n(*This lemma states that dividing the additive opposite of a ring element by the additive opposite of a unit ring element is equivalent to dividing the first element by the second unit element.*)\nDefinition divrNN := divrNN.\n(*This lemma states that dividing a ring element by the additive opposite of a unit ring element is equivalent to taking the additive opposite of their division.*)\nDefinition divrN := divrN.\n(*This lemma states that in an ordered ring, the sign of the multiplicative inverse of a unit element is the same as the sign of the element itself.*)\nDefinition invr_sign := invr_sign.\n(*This lemma states that if a square matrix is a unit (invertible), then the function that performs left multiplication by this matrix is itself a unit in the ring of endomorphisms.*)\nDefinition unitrMl := unitrMl.\n(*This lemma states that if a square matrix is a unit (invertible), then the function that performs right multiplication by this matrix is itself a unit in the ring of endomorphisms.*)\nDefinition unitrMr := unitrMr.\n(*This lemma states that the multiplicative inverse of a product of two real numbers is equal to the product of their multiplicative inverses.*)\nDefinition invrM := invrM.\n(*This lemma states that if two real numbers are units, meaning they are equal to one or its additive inverse, then their product is also a unit.*)\nDefinition unitr_prod := unitr_prod.\n(*This lemma states that if the product of two real numbers is a unit and one of the factors is a unit, then the other factor must also be a unit.*)\nDefinition unitr_prod_in := unitr_prod_in.\n(*This lemma states that the multiplicative inverse of a real number is never equal to zero.*)\nDefinition invr_eq0 := invr_eq0.\n(*This lemma states that the multiplicative inverse of a real number is equal to one if and only if the number itself is equal to one.*)\nDefinition invr_eq1 := invr_eq1.\n(*This lemma states that the multiplicative inverse of a non-zero real number is also non-zero.*)\nDefinition invr_neq0 := invr_neq0.\n(*This lemma states that a real number is a unit if and only if its additive inverse is a unit.*)\nDefinition rev_unitrP := rev_unitrP.\n(*This lemma states that the additive inverse of a product of two real numbers is equal to the product of the additive inverse of the first number and the second number.*)\nDefinition rev_prodrV := rev_prodrV.\n(*This lemma states that the multiplication of any real number by a unit real number is commutative.*)\nDefinition unitrM_comm := unitrM_comm.\n(*This lemma states that if a real number is a unit, then any integer power of this number is also a unit.*)\nDefinition unitrX := unitrX.\n(*This lemma states that if a real number is a unit, then any non-negative integer power of this number is also a unit.*)\nDefinition unitrX_pos := unitrX_pos.\n(*This lemma states that for a non-zero real number, exponentiation by a negative integer is equivalent to the multiplicative inverse of the exponentiation by the corresponding positive integer.*)\nDefinition exprVn := exprVn.\n(*This definition returns a given real number if a given boolean is true, and returns one otherwise.*)\nDefinition exprB := exprB.\n(*This lemma states that for any non-zero real number, the sign of its multiplicative inverse is the same as the sign of the number itself.*)\nDefinition invr_signM := invr_signM.\n(*This lemma states that for any two real numbers where the divisor is non-zero, the sign of their quotient is the product of their signs.*)\nDefinition divr_signM := divr_signM.\n(*This lemma states that the constant-false predicate on real numbers evaluates to false for any real number.*)\nDefinition rpred0D := @rpred0D.\n(*This defines a predicate on real numbers that always evaluates to false.*)\nDefinition rpred0 := rpred0.\n(*This lemma states that any boolean predicate on real numbers is decidable, meaning for any given real number, the predicate is either true or false.*)\nDefinition rpredD := rpredD.\n(*This lemma states that applying the negation of a boolean predicate on a real number is equivalent to evaluating the predicate and then taking the boolean negation of the result.*)\nDefinition rpredNr := @rpredNr.\n(*This lemma states that if a predicate on real numbers holds for zero, is closed under addition, and holds for every term in a finite sequence of real numbers, then it also holds for the sum of the sequence.*)\nDefinition rpred_sum := rpred_sum.\n(*This lemma states that for a predicate on real numbers that is a cone and stable under additive inversion, if the predicate holds for a real number, it also holds for the negative part of that number.*)\nDefinition rpredMn := rpredMn.\n(*This definition constructs the negation of a given boolean predicate on real numbers, such that the new predicate is true if and only if the original is false.*)\nDefinition rpredN := rpredN.\n(*This definition creates a new predicate from a given predicate and a boolean value, where the new predicate is the original predicate if the boolean is true, and its negation if the boolean is false.*)\nDefinition rpredB := rpredB.\n(*This lemma states that applying a conditional predicate to a real number is equivalent to checking if the original predicate's evaluation on that number is equal to the conditional's boolean.*)\nDefinition rpredBC := rpredBC.\n(*This lemma states that for a predicate on real numbers that is a cone and stable under additive inversion, if the predicate holds for a real number, then it also holds for both the positive part and the negative part of that number.*)\nDefinition rpredMNn := rpredMNn.\n(*This lemma establishes a right-cancellation property for certain predicates on real numbers, stating that if such a predicate is true for a non-zero number and a product, it must also be true for the other factor.*)\nDefinition rpredDr := rpredDr.\n(*This lemma establishes a left-cancellation property for certain predicates on real numbers, stating that if such a predicate is true for a non-zero number and a product, it must also be true for the other factor.*)\nDefinition rpredDl := rpredDl.\n(*This lemma states that if a predicate on real numbers represents a cone, then for any fixed real number, the predicate formed by applying the original predicate to the product of its argument and the fixed number is also a cone.*)\nDefinition rpredBr := rpredBr.\n(*This lemma states that if a predicate on real numbers represents a cone, then for any fixed real number, the predicate formed by applying the original predicate to the product of the fixed number and its argument is also a cone.*)\nDefinition rpredBl := rpredBl.\n(*This lemma states that any Z-submodule of the real numbers constitutes a closed set with respect to the standard topology on the reals.*)\nDefinition zmodClosedP := zmodClosedP.\n(*This definition specifies a predicate on a matrix that holds if and only if every entry of the matrix satisfies a given sign predicate.*)\nDefinition rpredMsign := rpredMsign.\n(*This definition specifies a predicate on a matrix that holds if and only if every entry of the matrix is equal to one.*)\nDefinition rpred1M := @rpred1M.\n(*This definition specifies a predicate that holds for an element if and only if that element is equal to one.*)\nDefinition rpred1 := @rpred1.\n(*This definition provides a generic way to lift a predicate on elements to a predicate on matrices, which is satisfied if and only if all entries of the matrix satisfy the original predicate.*)\nDefinition rpredM := @rpredM.\n(*This definition constructs a predicate on a pair of values, which holds if and only if a given predicate for the first component holds for the first value and a given predicate for the second component holds for the second value.*)\nDefinition rpred_prod := rpred_prod.\n(*This definition lifts a predicate on ring elements to a predicate on polynomials, which holds if and only if all coefficients of the polynomial satisfy the given predicate.*)\nDefinition rpredX := rpredX.\n(*This definition specifies a predicate on elements of a ring that holds if and only if the element corresponds to a non-negative integer.*)\nDefinition rpred_nat := rpred_nat.\n(*This definition specifies a predicate for natural numbers that holds if and only if the number is equal to one.*)\nDefinition rpredN1 := rpredN1.\n(*This definition specifies a predicate on a ring element that determines its sign, typically categorizing it as positive, negative, or zero.*)\nDefinition rpred_sign := rpred_sign.\n(*This definition specifies a predicate on a set of elements from a semiring that holds if and only if the set is closed under both addition and multiplication.*)\nDefinition semiringClosedP := semiringClosedP.\n(*This definition specifies a predicate on a set of elements from a ring that holds if and only if the set contains the additive identity, the multiplicative identity, and is closed under addition, negation, and multiplication.*)\nDefinition subringClosedP := subringClosedP.\n(*This definition specifies a predicate on an integer that categorizes it as positive, negative, or zero.*)\nDefinition rpredZsign := rpredZsign.\n(*This definition specifies a predicate on an integer that holds if and only if the integer is non-negative.*)\nDefinition rpredZnat := rpredZnat.\n(*This definition specifies a predicate on a set of elements from a module that holds if and only if the set contains the zero vector and is closed under vector addition and scalar multiplication.*)\nDefinition submodClosedP := submodClosedP.\n(*This definition specifies a predicate on a set of elements from an algebra that holds if and only if the set forms a submodule and is also closed under multiplication.*)\nDefinition subalgClosedP := subalgClosedP.\n(*This definition specifies a predicate on an integer that is derived from a predicate on natural numbers by applying the natural number predicate to the absolute value of the integer.*)\nDefinition rpredZ := @rpredZ.\n(*This definition lifts a predicate on elements to a predicate on row vectors, which holds if and only if all entries of the vector satisfy the given predicate.*)\nDefinition rpredVr := @rpredVr.\n(*This definition lifts a predicate on elements to a predicate on column vectors, which holds if and only if all entries of the vector satisfy the given predicate.*)\nDefinition rpredV := rpredV.\n(*This definition specifies a predicate that holds for two elements if and only if the first element divides the second.*)\nDefinition rpred_div := rpred_div.\n(*This definition specifies a predicate on a polynomial which holds if and only if all of its coefficients are non-negative.*)\nDefinition rpredXN := rpredXN.\n(*This definition specifies a predicate on an integer that holds if and only if the integer is equal to a given, fixed integer value.*)\nDefinition rpredZeq := rpredZeq.\n(*This definition computes the characteristic polynomial of an element in a linear algebra.*)\nDefinition pchar_lalg := pchar_lalg.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar_lalg instead.\")]\n(*This definition computes the characteristic polynomial of an element in a linear algebra. This definition is deprecated and 'pchar_lalg' should be used instead.*)\nDefinition char_lalg := pchar_lalg.\n(*This definition lifts a predicate on row vectors to a predicate on matrices, which holds if and only if the predicate is satisfied by every row of the matrix.*)\nDefinition rpredMr := rpredMr.\n(*This definition lifts a predicate on column vectors to a predicate on matrices, which holds if and only if the predicate is satisfied by every column of the matrix.*)\nDefinition rpredMl := rpredMl.\n(*This definition specifies a predicate that holds for two elements if and only if the first element is a right divisor of the second.*)\nDefinition rpred_divr := rpred_divr.\n(*This definition specifies a predicate that holds for two elements if and only if the first element is a left divisor of the second.*)\nDefinition rpred_divl := rpred_divl.\n(*This definition specifies a predicate on a set of elements from a division ring that holds if and only if the set contains the additive identity and the multiplicative identity, and is closed under addition, negation, multiplication, and multiplicative inversion of non-zero elements.*)\nDefinition divringClosedP := divringClosedP.\n(*This lemma states that if two polynomials are equal, then their evaluations at any given point are also equal.*)\nDefinition eq_eval := eq_eval.\n(*This lemma states that evaluating a composite polynomial at a point gives the same result as evaluating the outer polynomial at the value of the inner polynomial evaluated at that same point.*)\nDefinition eval_tsubst := eval_tsubst.\n(*This definition re-exports a foundational axiom concerning equality, which asserts that substitution of an element along an equality path results in the element at the end of the path.*)\nDefinition eq_holds := eq_holds.\n(*This definition re-exports a lemma for reasoning about boolean functions, asserting that applying a function to a boolean is propositionally equivalent to a case analysis on that boolean.*)\nDefinition holds_fsubst := holds_fsubst.\n(*This definition describes the property that a constant function, which always returns the multiplicative identity of a ring, qualifies as a ring homomorphism.*)\nDefinition unitrM := unitrM.\n(*This lemma states an equivalence for a predicate applied to the proposition that a finite product of ring elements equals one. It asserts this is equivalent to the predicate holding for the proposition that each individual element is equal to one.*)\nDefinition unitr_prodP := unitr_prodP.\n(*This lemma provides a rule to unfold a finite product of ring elements, stating that the product is equal to the first element multiplied by the product of the remaining elements.*)\nDefinition prodrV := prodrV.\n(*This lemma states that an element of a ring with units is equal to the multiplicative identity if and only if its multiplicative inverse is also equal to the multiplicative identity.*)\nDefinition unitrPr {R x} := @unitrPr R x.\n(*This lemma states a property of exponentiation in a division ring, asserting that an element raised to the power of a difference of two natural numbers is equal to the division of the element raised to the first number by the element raised to the second number.*)\nDefinition expr_div_n := expr_div_n.\n(*This lemma states that multiplying any ring element on the right by the multiplicative identity results in the original element.*)\nDefinition mulr1_eq := mulr1_eq.\n(*This lemma states that dividing any element of a division ring by the multiplicative identity results in the original element.*)\nDefinition divr1_eq := divr1_eq.\n(*This lemma expresses the right cancellation law for division in a division ring. It states that for any non-zero element, multiplying it by the result of dividing another element by it yields that other element.*)\nDefinition divKr := divKr.\n(*This lemma states the zero-product property in a field, asserting that the product of two elements is zero if and only if at least one of the elements is zero.*)\nDefinition mulf_eq0 := mulf_eq0.\n(*This lemma generalizes the zero-product property to finite products in a field. It states that a product over a finite collection of field elements is zero if and only if there exists at least one zero element in the collection.*)\nDefinition prodf_eq0 := prodf_eq0.\n(*This lemma provides the zero-product property for sequences of field elements, stating that the product of the elements in a sequence is zero if and only if the sequence contains at least one zero element.*)\nDefinition prodf_seq_eq0 := prodf_seq_eq0.\n(*This lemma states that the product of two field elements is non-zero if and only if both elements are non-zero.*)\nDefinition mulf_neq0 := mulf_neq0.\n(*This lemma states that a finite product of field elements is non-zero if and only if every element in the product is non-zero.*)\nDefinition prodf_neq0 := prodf_neq0.\n(*This lemma states that the product of a sequence of field elements is non-zero if and only if all elements in the sequence are non-zero.*)\nDefinition prodf_seq_neq0 := prodf_seq_neq0.\n(*This lemma characterizes when a power of a field element is zero. It states that an element raised to a natural number power is zero if and only if the base element is zero and the exponent is positive.*)\nDefinition expf_eq0 := expf_eq0.\n(*This lemma states that the square of a field element is zero if and only if the element itself is zero.*)\nDefinition sqrf_eq0 := sqrf_eq0.\n(*This lemma characterizes when a power of a field element is non-zero. It states that an element raised to a natural number power is non-zero if and only if the base element is non-zero or the exponent is zero.*)\nDefinition expf_neq0 := expf_neq0.\n(*This lemma states that for a field with a non-zero characteristic, the canonical image of a natural number is non-zero if and only if the characteristic does not divide that number.*)\nDefinition natf_neq0_pchar := natf_neq0_pchar.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use natf_neq0_pchar instead.\")]\n(*This lemma states that for a field with a non-zero characteristic, the canonical image of a natural number is non-zero if and only if the characteristic does not divide that number. This definition is deprecated, and `natf_neq0_pchar` should be used instead.*)\nDefinition natf_neq0 := natf_neq0_pchar.\n(*This lemma states that the canonical image of a natural number in a field is zero if and only if the field has a non-zero characteristic that divides the number.*)\nDefinition natf0_pchar := natf0_pchar.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use natf0_pchar instead.\")]\n(*This lemma states that the canonical image of a natural number in a field is zero if and only if the field has a non-zero characteristic that divides the number. This definition is deprecated, and `natf0_pchar` should be used instead.*)\nDefinition natf0_char := natf0_pchar.\n(*This lemma states that the characteristic of a field is equal to its underlying natural number representation.*)\nDefinition pcharf'_nat := pcharf'_nat.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf'_nat instead.\")]\n(*This lemma states that the characteristic of a field is equal to its underlying natural number representation. This definition is deprecated, and `pcharf'_nat` should be used instead.*)\nDefinition charf'_nat := pcharf'_nat.\n(*This lemma provides an alternate characterization for fields of characteristic zero, stating that a field has characteristic zero if and only if the canonical image of any positive natural number is non-zero.*)\nDefinition pcharf0P := pcharf0P.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf0P instead.\")]\n(*This lemma provides an alternate characterization for fields of characteristic zero, stating that a field has characteristic zero if and only if the canonical image of any positive natural number is non-zero. This definition is deprecated, and `pcharf0P` should be used instead.*)\nDefinition charf0P := pcharf0P.\n(*This lemma states that the squares of two field elements are equal if and only if the elements themselves are equal or one is the additive inverse of the other.*)\nDefinition eqf_sqr := eqf_sqr.\n(*This lemma states the cancellation property for multiplication in a field. It asserts that for a non-zero multiplier, the equality of the products of two elements with that multiplier implies the equality of the two original elements.*)\nDefinition mulfI := mulfI.\n(*This definition is an alias for a lemma stating the cancellation property for multiplication in a field. It asserts that for a non-zero multiplier, the equality of the products of two elements with that multiplier implies the equality of the two original elements.*)\nDefinition mulIf := mulIf.\n(*This lemma states that dividing any element of a field by the multiplicative identity results in the original element.*)\nDefinition divfI := divfI.\n(*This lemma states that dividing the multiplicative identity of a field by a non-zero element is equivalent to taking the multiplicative inverse of that element.*)\nDefinition divIf := divIf.\n(*This lemma states that for a field with characteristic other than two, the square of an element is equal to one if and only if the element is either one or its additive inverse.*)\nDefinition sqrf_eq1 := sqrf_eq1.\n(*This lemma relates the equality of an element raised to a successor power with one to a property involving the element and the smaller power.*)\nDefinition expfS_eq1 := expfS_eq1.\n(*This definition provides a boolean predicate that is true if and only if a given ring structure satisfies the property of being a field, which means every non-zero element is a unit.*)\nDefinition fieldP := @fieldP.\n(*This lemma states that an element of a field is a unit if and only if it is not the additive identity.*)\nDefinition unitfE := unitfE.\n(*This definition specifies the operation of right scalar multiplication of a vector by an element from a field.*)\nDefinition mulVf := mulVf.\n(*This definition specifies the operation of left scalar multiplication of a vector by an element from a field.*)\nDefinition mulfV := mulfV.\n(*This lemma establishes a simplification rule for the division of one fraction by another within a field.*)\nDefinition divff := divff.\n(*This lemma states that the product of an element from a subfield and an element from a larger field is equivalent to their product computed entirely within the larger field.*)\nDefinition mulKf := mulKf.\n(*This lemma relates the scalar multiplication of a vector over a subfield, with the scalar originating from the larger field.*)\nDefinition mulVKf := mulVKf.\n(*This lemma states that the product of an element from a larger field and an element from a subfield is equivalent to their product computed entirely within the larger field.*)\nDefinition mulfK := mulfK.\n(*This lemma relates the scalar multiplication of a vector over a subfield, with the scalar originating from the larger field and placed on the left.*)\nDefinition mulfVK := mulfVK.\n(*This lemma states that dividing an element from a larger field by an element from a subfield is equivalent to performing the division entirely within the larger field.*)\nDefinition divfK := divfK.\n(*This lemma states that dividing an element from a subfield by an element from a larger field is equivalent to performing the division entirely within the larger field.*)\nDefinition divKf := divKf.\n(*This lemma states that the inverse of an invertible square matrix over a field is the product of the inverse of its determinant and its adjugate matrix.*)\nDefinition invfM := invfM.\n(*This lemma formally states that the multiplicative inverse of a non-zero field element is equal to the division of one by that element.*)\nDefinition invf_div := invf_div.\n(*This lemma states that exponentiating a field element by a boolean value yields the element itself if the boolean is true, and the multiplicative identity if the boolean is false.*)\nDefinition expfB_cond := expfB_cond.\n(*This definition provides an operation for raising a field element to a boolean power, resulting in the element for true and the multiplicative identity for false.*)\nDefinition expfB := expfB.\n(*This definition computes the product of the components of a given vector over a field.*)\nDefinition prodfV := prodfV.\n(*This lemma states that the product of a sequence of fractions is equal to the fraction of the products of the numerators and the products of the denominators.*)\nDefinition prodf_div := prodf_div.\n(*This lemma establishes the telescoping cancellation property for a product of fractions where each numerator is related to the subsequent denominator, simplifying the product to the ratio of the final numerator and the initial denominator.*)\nDefinition telescope_prodf := telescope_prodf.\n(*This lemma states that the product of a given sequence of field elements over a range equals the ratio of two terms from an auxiliary sequence, provided that each element of the original sequence is a ratio of consecutive terms from the auxiliary sequence.*)\nDefinition telescope_prodf_eq := @telescope_prodf_eq.\nArguments telescope_prodf_eq {F n m} f u.\n(*This lemma states that division in a field distributes on the right over addition.*)\nDefinition addf_div := addf_div.\n(*This lemma states that multiplying a field element by a fraction is equivalent to multiplying the numerator by that element and then dividing by the denominator.*)\nDefinition mulf_div := mulf_div.\n(*This lemma provides a right-cancellation rule for division, stating that if two elements divided by the same non-zero element are equal, then the original two elements are equal.*)\nDefinition eqr_div := eqr_div.\n(*This lemma extends the right-cancellation rule for division to sums, stating that if two sums of fractions with a common non-zero denominator are equal, then the sums of their numerators are also equal.*)\nDefinition eqr_sum_div := eqr_sum_div.\n(*This lemma states that in a field of characteristic zero, the division of two natural numbers embedded into the field is equal to the embedding of their rational division.*)\nDefinition pchar0_natf_div := pchar0_natf_div.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar0_natf_div instead.\")]\n(*This definition is deprecated and should be replaced by 'pchar0_natf_div'. It states that in a field of characteristic zero, the division of two natural numbers embedded into the field is equivalent to the embedding of their rational division.*)\nDefinition char0_natf_div := pchar0_natf_div.\n(*This lemma concerns the predecessor of a value associated with a matrix over a field.*)\nDefinition fpredMr := fpredMr.\n(*This definition creates a higher-order predicate that asserts an implication between two other predicates on a function, stating that for any input, if the first predicate holds for the function's output, then the second predicate must also hold.*)\nDefinition fpredMl := fpredMl.\n(*A predicate on a polynomial that is satisfied if the polynomial is the quotient resulting from the division of a given dividend polynomial by a given divisor polynomial on the right.*)\nDefinition fpred_divr := fpred_divr.\n(*A predicate on a polynomial that is satisfied if the polynomial is the quotient resulting from the division of a given dividend polynomial by a given divisor polynomial on the left.*)\nDefinition fpred_divl := fpred_divl.\n(*A predicate on a value that is satisfied if substituting the value into a given polynomial evaluates to zero.*)\nDefinition satP {F e f} := @satP F e f.\n(*This lemma states that for two non-zero polynomials, having the same set of roots is equivalent to the polynomials being equal, under appropriate conditions on the underlying ring.*)\nDefinition eq_sat := eq_sat.\n(*A definition for the set of all values that satisfy a given boolean-valued predicate.*)\nDefinition solP {F n f} := @solP F n f.\n(*This lemma states that two boolean-valued functions are equal if and only if their solution sets are identical.*)\nDefinition eq_sol := eq_sol.\n(*A definition for the number of elements in the solution set of a given boolean-valued predicate.*)\nDefinition size_sol := size_sol.\n(*A function that computes the list of all roots of a given monic polynomial over a finite type by checking every element of the type.*)\nDefinition solve_monicpoly := @solve_monicpoly.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\",\n deprecated(since=\"mathcomp 2.5.0\", note=\"use `nmod_morphism` instead\")]\n(*A deprecated predicate asserting that a function preserves addition. It has been replaced by nmod_morphism.*)\nDefinition semi_additive := semi_additive.\n(*A predicate asserting that a function between two structures with natural number scaling is a module morphism, meaning it preserves both addition and scalar multiplication by natural numbers.*)\nDefinition nmod_morphism := nmod_morphism.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\",\n deprecated(since=\"mathcomp 2.5.0\", note=\"use `zmod_morphism` instead\")]\n(*A deprecated predicate asserting that a function between two additive groups preserves the addition operation. It has been replaced by zmod_morphism.*)\nDefinition additive := additive.\n(*A predicate asserting that a function between two structures with integer scaling is a module morphism, meaning it preserves both addition and scaling by integers.*)\nDefinition zmod_morphism := zmod_morphism.\n(*This lemma states that any function that preserves addition maps the zero element of its domain to the zero element of its codomain.*)\nDefinition raddf0 := raddf0.\n(*This lemma states that an additive function is identical to the constant zero function if and only if it evaluates to zero for all inputs.*)\nDefinition raddf_eq0 := raddf_eq0.\n(*This lemma states that an additive function is injective if and only if the only element that maps to zero is the zero element itself.*)\nDefinition raddf_inj := raddf_inj.\n(*This lemma states that any function that preserves addition also preserves additive negation, mapping the negative of an element to the negative of its image.*)\nDefinition raddfN := raddfN.\n(*This lemma states that any function that preserves addition also preserves subtraction, mapping the difference of two elements to the difference of their images.*)\nDefinition raddfD := raddfD.\n(*This lemma states that an additive function commutes with the canonical injection of booleans into a ring.*)\nDefinition raddfB := raddfB.\n(*This lemma states that an additive function commutes with finite summation, meaning the image of a sum of elements is the sum of their images.*)\nDefinition raddf_sum := raddf_sum.\n(*This lemma states that if a function between rings is additive, then the function that applies it element-wise to matrices is also an additive function between matrix rings.*)\nDefinition raddfMn := raddfMn.\n(*This lemma states that an element-wise application of an additive function to a matrix preserves matrix negation.*)\nDefinition raddfMNn := raddfMNn.\n(*This lemma states that an element-wise application of an additive function to a matrix commutes with the scalar multiplication of the matrix by a natural number.*)\nDefinition raddfMnat := raddfMnat.\n(*This lemma states that an element-wise application of an additive function to a matrix commutes with the scalar multiplication of the matrix by a sign.*)\nDefinition raddfMsign := raddfMsign.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\",\n deprecated(since=\"mathcomp 2.5.0\", note=\"use `can2_nmod_morphism` instead\")]\n(*A deprecated definition asserting that if two functions are semi-additive, then the function that applies them component-wise to a pair of values is also semi-additive. It has been replaced by can2_nmod_morphism.*)\nDefinition can2_semi_additive := can2_semi_additive.\n(*This definition asserts that if two functions are N-module morphisms, then the function that applies them component-wise to a pair of values is also an N-module morphism.*)\nDefinition can2_nmod_morphism := can2_nmod_morphism.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\",\n deprecated(since=\"mathcomp 2.5.0\", note=\"use `can2_zmod_morphism` instead\")]\n(*A deprecated definition asserting that if two functions are additive group homomorphisms, then the function that applies them component-wise to a pair of values is also an additive group homomorphism. It has been replaced by can2_zmod_morphism.*)\nDefinition can2_additive := can2_additive.\n(*This definition asserts that if two functions are Z-module morphisms, then the function that applies them component-wise to a pair of values is also a Z-module morphism.*)\nDefinition can2_zmod_morphism := can2_zmod_morphism.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\",\n deprecated(since=\"mathcomp 2.5.0\", note=\"use `monoid_morphism` instead\")]\n(*A deprecated predicate asserting that a function preserves the multiplication operation. It has been replaced by monoid_morphism.*)\nDefinition multiplicative := multiplicative.\n(*A predicate asserting that a function between two monoids is a monoid morphism, meaning it preserves the multiplication operation and maps the identity element of the domain to the identity element of the codomain.*)\nDefinition monoid_morphism := monoid_morphism.\n(*This definition specifies the zero ring morphism, which is a function that maps every element from a source ring to the zero element of a destination ring.*)\nDefinition rmorph0 := rmorph0.\n(*This definition specifies the canonical ring morphism from the ring of integers into an arbitrary ring, mapping an integer to the corresponding multiple of the ring's multiplicative identity.*)\nDefinition rmorphN := rmorphN.\n(*This definition creates a ring morphism between two rings that is compatible with the division operation, mapping the result of a division in the source ring to the result of the corresponding division in the destination ring.*)\nDefinition rmorphD := rmorphD.\n(*This definition specifies the canonical ring morphism from the Boolean ring to an arbitrary ring, mapping the Boolean true to the multiplicative identity and false to the additive identity.*)\nDefinition rmorphB := rmorphB.\n(*This definition constructs a ring morphism that is the pointwise sum of a finite sequence of ring morphisms.*)\nDefinition rmorph_sum := rmorph_sum.\n(*This definition lifts a given ring morphism to a morphism between matrix rings of the same dimensions, applying the original morphism to each entry of a given matrix.*)\nDefinition rmorphMn := rmorphMn.\n(*This definition lifts a given ring morphism to a morphism between rings of square matrices of the same size, applying the original morphism to each entry of a given square matrix.*)\nDefinition rmorphMNn := rmorphMNn.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\",\n deprecated(since=\"mathcomp 2.5.0\", note=\"use `rmorphism_monoidP` instead\")]\n(*This definition is deprecated as of mathcomp 2.5.0 and has been replaced by `rmorphism_monoidP`. It provides a property asserting that a ring morphism also behaves as a monoid morphism with respect to multiplication.*)\nDefinition rmorphismMP := rmorphismMP.\n(*This definition provides a property asserting that a function satisfying the requirements of a ring morphism also fulfills the conditions of a monoid morphism for the multiplicative structure, meaning it preserves the multiplicative identity and the multiplication operation.*)\nDefinition rmorphism_monoidP := rmorphism_monoidP.\n(*This definition specifies the identity ring morphism, which is a function from a ring to itself that maps every element to itself.*)\nDefinition rmorph1 := rmorph1.\n(*This lemma asserts that a ring morphism is the identity morphism if it satisfies certain conditions, such as mapping a generator to itself.*)\nDefinition rmorph_eq1 := rmorph_eq1.\n(*This definition constructs a ring morphism from a given monoid morphism, extending the behavior of the monoid morphism to the entire ring structure.*)\nDefinition rmorphM := rmorphM.\n(*This definition specifies a ring morphism derived from a sign function on a monoid, mapping elements to ring representations of their sign, such as positive one, negative one, or zero.*)\nDefinition rmorphMsign := rmorphMsign.\n(*This definition specifies the canonical morphism from the semiring of natural numbers into an arbitrary ring, mapping a natural number to the ring element obtained by repeatedly adding the ring's multiplicative identity.*)\nDefinition rmorph_nat := rmorph_nat.\n(*This lemma states that two ring morphisms originating from the ring of integers are equal if they produce the same result for all natural number inputs.*)\nDefinition rmorph_eq_nat := rmorph_eq_nat.\n(*This definition constructs a ring morphism between two product rings from a pair of morphisms for their components. The resulting morphism applies each of the original morphisms to the corresponding component of an element in the source product ring.*)\nDefinition rmorph_prod := rmorph_prod.\n(*This definition creates a ring morphism from a ring to a product of that ring with itself a finite number of times, constructed from a sequence of morphisms where each one produces the corresponding component in the output tuple.*)\nDefinition rmorphXn := rmorphXn.\n(*This definition specifies a monoid morphism from the multiplicative monoid of positive natural numbers to the group of units of a ring, mapping a natural number to the corresponding power of a given unit element.*)\nDefinition rmorphN1 := rmorphN1.\n(*This definition specifies a ring morphism that computes the sign of an element in an ordered ring, mapping it to an integer representation such as positive one, negative one, or zero.*)\nDefinition rmorph_sign := rmorph_sign.\n(*This definition specifies the canonical ring morphism from the ring of integers modulo a prime number to any ring having that prime number as its characteristic.*)\nDefinition rmorph_pchar := rmorph_pchar.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use rmorph_pchar instead.\")]\n(*This definition is deprecated as of mathcomp 2.4.0 and has been replaced by `rmorph_pchar`. It specifies the canonical ring morphism from the ring of integers modulo a prime number to a ring of the same characteristic.*)\nDefinition rmorph_char := rmorph_pchar.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\",\n deprecated(since=\"mathcomp 2.5.0\", note=\"use `can2_monoid_morphism` instead\")]\n(*This definition is deprecated as of mathcomp 2.5.0 and has been replaced by `can2_monoid_morphism`. It refers to a canonical morphism related to the second component of a product-like structure.*)\nDefinition can2_rmorphism := can2_rmorphism.\n(*This definition specifies the canonical monoid morphism that projects an element of a product of two monoids onto its second component.*)\nDefinition can2_monoid_morphism := can2_monoid_morphism.\n(*This lemma states that the subring formed by the image of a commutative ring under a ring morphism is also commutative.*)\nDefinition rmorph_comm := rmorph_comm.\n(*This lemma asserts that a ring morphism maps a unit element in the source ring to a unit element in the destination ring.*)\nDefinition rmorph_unit := rmorph_unit.\n(*This definition lifts a ring morphism to a function between vectors, where the resulting function applies the original morphism to each coordinate of the input vector.*)\nDefinition rmorphV := rmorphV.\n(*This lemma states that a ring morphism between two rings that have a division operation preserves that division.*)\nDefinition rmorph_div := rmorph_div.\n(*This lemma states that a field morphism is the zero morphism if and only if it maps at least one non-zero element to zero.*)\nDefinition fmorph_eq0 := fmorph_eq0.\n(*This lemma states that any non-zero field morphism is injective, meaning it maps distinct elements in the source field to distinct elements in the destination field.*)\nDefinition fmorph_inj := @fmorph_inj.\nArguments fmorph_inj {F R} f [x1 x2].\n(*This lemma provides a condition for the equality of two field morphisms, asserting that they are equal if they agree on all elements of a generating set of the source field.*)\nDefinition fmorph_eq := fmorph_eq.\n(*This lemma states that for a field morphism between two fields, if a non-zero element is mapped to the multiplicative identity, then that element must be the multiplicative identity.*)\nDefinition fmorph_eq1 := fmorph_eq1.\n(*This lemma states that a field morphism preserves the prime characteristic of the domain field, effectively acting as the identity map on the prime subfield.*)\nDefinition fmorph_pchar := fmorph_pchar.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use fmorph_pchar instead.\")]\n(*This is a deprecated definition, and `fmorph_pchar` should be used instead. This lemma states that a field morphism preserves the characteristic of a field.*)\nDefinition fmorph_char := fmorph_pchar.\n(*This lemma states that a field morphism maps any non-zero element from its domain to a non-zero element in its codomain.*)\nDefinition fmorph_unit := fmorph_unit.\n(*This lemma states that applying a field morphism to a scaled value in an algebra is equivalent to scaling the morphism-applied value by the morphism-applied scalar.*)\nDefinition fmorphV := fmorphV.\n(*This lemma states that a field morphism is compatible with division, meaning that the morphism applied to a quotient of two elements is equal to the quotient of their images under the morphism.*)\nDefinition fmorph_div := fmorph_div.\n(*This lemma expresses the compatibility of scalar multiplication with vector addition, stating that scaling a sum of two vectors is equivalent to the sum of scaling each vector individually.*)\nDefinition scalerA := scalerA.\n(*This lemma states that scaling any vector by the multiplicative identity of the scalar ring yields the original vector.*)\nDefinition scale1r := @scale1r.\n(*This lemma expresses the distributivity of scalar multiplication over vector addition, asserting that scaling a sum of vectors is equivalent to the sum of the individually scaled vectors.*)\nDefinition scalerDr := @scalerDr.\n(*This lemma expresses the distributivity of scalar multiplication over scalar addition, asserting that scaling a vector by a sum of scalars is equivalent to the sum of the results of scaling the vector by each scalar.*)\nDefinition scalerDl := @scalerDl.\n(*This lemma states that scaling any vector by the zero scalar results in the zero vector.*)\nDefinition scaler0 := scaler0.\n(*This lemma states that scaling the zero vector by any scalar results in the zero vector.*)\nDefinition scale0r := @scale0r.\n(*This lemma relates scalar multiplication with the negation of the scalar, stating that scaling a vector by the additive inverse of a scalar produces the additive inverse of the scaled vector.*)\nDefinition scaleNr := scaleNr.\n(*This lemma states that scaling a vector by the additive inverse of the multiplicative identity is equivalent to taking the additive inverse of the vector.*)\nDefinition scaleN1r := scaleN1r.\n(*This lemma relates scalar multiplication with the negation of the vector, stating that scaling the additive inverse of a vector by a scalar is equivalent to the additive inverse of the result of scaling the original vector.*)\nDefinition scalerN := scalerN.\n(*This lemma describes how scalar multiplication distributes over a conditional expression for the scalar, stating that scaling a vector by a scalar chosen by a boolean condition is equivalent to choosing between the results of scaling the vector by each potential scalar.*)\nDefinition scalerBl := scalerBl.\n(*This lemma describes how scalar multiplication distributes over a conditional expression for the vector, stating that scaling a vector chosen by a boolean condition is equivalent to choosing between the two scaled vectors.*)\nDefinition scalerBr := scalerBr.\n(*This lemma connects scalar multiplication by a natural number with repeated addition, asserting that scaling a vector by a natural number is equivalent to the sum of that many copies of the vector.*)\nDefinition scaler_nat := scaler_nat.\n(*This lemma specifies a compatibility rule for algebras, stating that scaling a product of two algebra elements is equivalent to first scaling the left factor and then performing the multiplication.*)\nDefinition scalerMnl := scalerMnl.\n(*This lemma specifies a compatibility rule for algebras, stating that scaling a product of two algebra elements is equivalent to first scaling the right factor and then performing the multiplication.*)\nDefinition scalerMnr := scalerMnr.\n(*This lemma states that scalar multiplication distributes over a finite sum of scalars, where scaling a vector by the sum is equivalent to summing the results of scaling the vector by each scalar in the sum.*)\nDefinition scaler_suml := scaler_suml.\n(*This lemma states that scalar multiplication distributes over a finite sum of vectors, where scaling the sum is equivalent to summing the results of scaling each vector in the sum.*)\nDefinition scaler_sumr := scaler_sumr.\n(*This lemma states that for a module over an integral domain, a scalar product is zero if and only if either the scalar is zero or the vector is zero.*)\nDefinition scaler_eq0 := scaler_eq0.\n(*This lemma provides a left cancellation rule for scalar multiplication, stating that if two vectors scaled by the same non-zero scalar are equal, then the original vectors must be equal.*)\nDefinition scalerK := scalerK.\n(*This lemma provides a right cancellation rule for scalar multiplication over a division ring, asserting that if a non-zero vector scaled by two different scalars yields the same result, then the scalars must be equal.*)\nDefinition scalerKV := scalerKV.\n(*This lemma establishes the condition under which scaling a vector returns the vector unchanged, which holds if and only if the scalar is one or the vector is zero.*)\nDefinition scalerI := scalerI.\n(*This lemma expresses the distributivity of scalar multiplication over scalar addition, stating that scaling a vector by a sum of scalars is equivalent to summing the individually scaled vectors.*)\nDefinition scalerAl := @scalerAl.\n(*This lemma asserts that for any element in an algebra, the right multiplication map is a linear map, which means that scaling a product of two elements is equivalent to scaling the left multiplicand before the multiplication.*)\nDefinition mulr_algl := mulr_algl.\n(*This lemma describes how the sign function interacts with scalar multiplication in an ordered module over an ordered ring, stating that the sign of a scaled vector is equal to the product of the sign of the scalar and the sign of the vector.*)\nDefinition scaler_sign := scaler_sign.\n(*This lemma describes how the sign function interacts with scaling by an integer in a module, stating that the sign of a vector scaled by an integer is the product of the sign of the integer and the sign of the vector.*)\nDefinition signrZK := signrZK.\n(*This definition provides the scalar multiplication operation for an algebra over a commutative ring, where the action of a ring element on an algebra element is defined.*)\nDefinition scalerCA := scalerCA.\n(*This definition provides the scalar multiplication operation for an algebra over an arbitrary ring.*)\nDefinition scalerAr := @scalerAr.\n(*This definition specifies the ring multiplication within an algebra that is also a ring.*)\nDefinition mulr_algr := mulr_algr.\n(*This definition introduces the structure of a commutative algebra, which is an algebra where the multiplication operation is commutative.*)\nDefinition comm_alg := comm_alg.\n(*This definition computes the power of a ring element for an integer exponent, handling positive, negative, and zero exponents.*)\nDefinition exprZn := exprZn.\n(*This definition specifies the scalar multiplication on the left component of a product of two modules, applying the scalar only to the first element.*)\nDefinition scaler_prodl := scaler_prodl.\n(*This definition specifies the scalar multiplication on the right component of a product of two modules, applying the scalar only to the second element.*)\nDefinition scaler_prodr := scaler_prodr.\n(*This definition provides the component-wise scalar multiplication for a product of two modules.*)\nDefinition scaler_prod := scaler_prod.\n(*This definition provides the scalar multiplication for the left injection into a direct sum of modules.*)\nDefinition scaler_injl := scaler_injl.\n(*This definition specifies the scalar multiplication for a module structure on the unit type, where any scalar multiplication results in the unique unit value.*)\nDefinition scaler_unit := scaler_unit.\n(*This definition computes the multiplicative inverse of an integer within a ring, defined as the inverse of the corresponding ring element.*)\nDefinition invrZ := invrZ.\n(*This definition constructs a ring element from a natural number, representing it as a positive integer value within the ring.*)\nDefinition raddfZnat := raddfZnat.\n(*This definition constructs a ring element from a boolean sign and a natural number magnitude, yielding either a positive or negative integer value within the ring.*)\nDefinition raddfZsign := raddfZsign.\n(*This lemma establishes that an element belongs to the sub-algebra generated by a given set if and only if it can be expressed as a polynomial in the elements of the set with coefficients from the base ring.*)\nDefinition in_algE := in_algE.\n(*This definition specifies the property of a function between two modules being scalable, which means that applying the function to a scalar-multiplied element is equivalent to multiplying the function's result by the same scalar.*)\nDefinition scalable_for := scalable_for.\n(*This definition specifies the property of a function between two modules being semilinear, which means that the function interacts with scalar multiplication via a given ring morphism on the scalars.*)\nDefinition semilinear_for := semilinear_for.\n(*This definition specifies the property of a function between two modules being linear, which is a special case of being semilinear where the associated ring morphism is the identity.*)\nDefinition linear_for := linear_for.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `nmod_morphism_semilinear` instead\")]\n(*This deprecated definition describes a function that is both additive, meaning it preserves sums, and semilinear, meaning it respects scalar multiplication up to a ring homomorphism. The recommended replacement is nmod_morphism_semilinear.*)\nDefinition additive_semilinear := additive_semilinear.\n(*This definition describes a semilinear morphism between modules over a numerical domain, which is a function that preserves both addition and scalar multiplication twisted by a ring homomorphism.*)\nDefinition nmod_morphism_semilinear := nmod_morphism_semilinear.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `zmod_morphism_linear` instead\")]\n(*This deprecated definition describes a function that is both additive, preserving sums, and linear, preserving scalar multiplication. The recommended replacement is zmod_morphism_linear.*)\nDefinition additive_linear := additive_linear.\n(*This definition describes a linear morphism between modules over the integers, which is a function that preserves both addition and scalar multiplication.*)\nDefinition zmod_morphism_linear := zmod_morphism_linear.\n(*This lemma states that a semilinear function can be viewed as a scalable function if the scalar action on the target module is redefined to incorporate the ring morphism associated with the semilinear map.*)\nDefinition scalable_semilinear := scalable_semilinear.\n(*This lemma asserts that any linear function is, by definition, a scalable function.*)\nDefinition scalable_linear := scalable_linear.\n(*This lemma states that a linear function maps the zero element of its domain to the zero element of its codomain.*)\nDefinition linear0 := linear0.\n(*This lemma states that a linear function commutes with negation, meaning the function applied to the negative of an element is the negative of the function applied to that element.*)\nDefinition linearN := linearN.\n(*This lemma states that a linear function distributes over subtraction, meaning the function applied to the difference of two elements is the difference of the function applied to each element.*)\nDefinition linearD := linearD.\n(*This lemma states that a linear function commutes with a conditional expression, meaning applying the function to the result of a conditional is the same as applying the conditional to the results of the function on both branches.*)\nDefinition linearB := linearB.\n(*This lemma states that a linear function distributes over a finite sum of elements, meaning the function applied to the sum is equal to the sum of the function applied to each element.*)\nDefinition linear_sum := linear_sum.\n(*This lemma states that a linear function commutes with scalar multiplication by a natural number, meaning applying the function to an element multiplied by a natural number is equivalent to multiplying the result of the function by that same natural number.*)\nDefinition linearMn := linearMn.\n(*This lemma states that a linear function commutes with scalar multiplication by a negative integer, meaning applying the function to an element multiplied by a negative integer is equivalent to multiplying the result of the function by that same negative integer.*)\nDefinition linearMNn := linearMNn.\n(*This definition specifies the property of a function between two modules being semilinear. A function is semilinear if it distributes over addition and if scaling its input by a ring element corresponds to scaling its output by the image of that element under a given ring morphism.*)\nDefinition semilinearP := semilinearP.\n(*This definition specifies the property of a function between two modules over the same ring being linear. A function is linear if it distributes over addition and commutes with scalar multiplication.*)\nDefinition linearP := linearP.\n(*This definition specifies the property of a binary function being linear with respect to integer scaling in each of its arguments. This means scaling the first input by an integer scales the output by the same integer, and similarly for the second input.*)\nDefinition linearZ_LR := linearZ_LR.\n(*This definition specifies the property of a function between two additive groups being linear with respect to integer scaling. This means that scaling the input by an integer results in scaling the output by the same integer.*)\nDefinition linearZ := linearZ.\n(*This definition specifies the property of a function being simultaneously semilinear with respect to a semiring's scalar multiplication and linear with respect to integer scalar multiplication.*)\nDefinition semilinearPZ := semilinearPZ.\n(*This definition specifies the property of a function being simultaneously linear with respect to a semiring's scalar multiplication and linear with respect to integer scalar multiplication.*)\nDefinition linearPZ := linearPZ.\n(*This definition specifies the property of a function with respect to integer scaling, typically for multilinear maps. For a bilinear map, it would mean that scaling each of the two inputs by integers results in the output being scaled by the product of those integers.*)\nDefinition linearZZ := linearZZ.\n(*This definition specifies the multiplicative component of the semilinearity property. It asserts that scaling the input of a function by a ring element is equivalent to scaling the output by the image of that element under a given ring morphism.*)\nDefinition semiscalarP := semiscalarP.\n(*This definition specifies the property that a function commutes with scalar multiplication from a semiring. It asserts that scaling the input of the function by a semiring element is equivalent to scaling the output by the same element.*)\nDefinition scalarP := scalarP.\n(*This definition specifies that a function commutes with integer scaling. It asserts that scaling the input of the function by an integer is equivalent to scaling the output by the same integer.*)\nDefinition scalarZ := scalarZ.\n(*This definition provides a cancellation law for scalable functions, allowing for the cancellation of a common non-zero scalar factor from an equation involving the function application.*)\nDefinition can2_scalable := can2_scalable.\n(*This definition provides a cancellation law for linear functions, allowing for the cancellation of a common non-zero scalar factor from an equation involving the function application.*)\nDefinition can2_linear := can2_linear.\n(*This definition provides a cancellation law for semilinear functions, allowing for the cancellation of a common non-zero scalar factor from an equation involving the function application, taking into account the associated ring morphism.*)\nDefinition can2_semilinear := can2_semilinear.\n(*This definition specifies the property of a function being an algebra morphism. An algebra morphism is a ring morphism that also commutes with the scalar multiplication of the algebra.*)\nDefinition rmorph_alg := rmorph_alg.\n(*This definition asserts the existence of an element in a ring, referred to as an imaginary unit, whose square is equal to the additive inverse of the multiplicative identity.*)\nDefinition imaginary_exists := imaginary_exists.\n\n(*This definition is a collection of simplification lemmas for ring addition. It includes rules for addition with zero, additive inverses, and the interaction between addition and subtraction.*)\nDefinition raddf := (raddf0, raddfN, raddfD, raddfMn).\n\n(*This definition is a collection of equational lemmas for ring morphisms. It provides simplification rules for how a ring morphism interacts with ring operations such as addition, multiplication, zero, one, negation, and exponentiation.*)\nDefinition rmorphE :=\n (rmorphD, rmorph0, rmorphB, rmorphN, rmorphMNn, rmorphMn, rmorph1, rmorphXn).\n\n(*This definition is a collection of equational lemmas for linear maps. It provides simplification rules for how a linear map interacts with addition, zero, negation, subtraction, and scalar multiplication.*)\nDefinition linearE :=\n (linearD, linear0, linearB, linearMNn, linearMn, linearZ).\n\nNotation null_fun V := (null_fun V) (only parsing).\nNotation in_alg A := (in_alg A) (only parsing).\n\nEnd Theory.\n\nModule AllExports. HB.reexport. End AllExports.\n\nEnd GRing.\n\nExport AllExports.\nExport Scale.Exports.\nExport ClosedExports.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Try pzSemiRingType (the potentially-zero counterpart) first, or use nzSemiRingType instead.\")]\n(*A deprecated notation for a non-zero semiring type, a structure with associative addition and multiplication, a zero and a one, where addition is commutative and multiplication distributes over addition. It is recommended to use the potentially-zero counterpart or the explicit non-zero version instead.*)\nNotation semiRingType := (nzSemiRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Try pzRingType (the potentially-zero counterpart) first, or use nzRingType instead.\")]\n(*A deprecated notation for a non-zero ring type, which is a non-zero semiring with an additive inverse operation. It is recommended to use the potentially-zero counterpart or the explicit non-zero version instead.*)\nNotation ringType := (nzRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Try comPzSemiRingType (the potentially-zero counterpart) first, or use comNzSemiRingType instead.\")]\n(*A deprecated notation for a commutative non-zero semiring type. It is recommended to use the potentially-zero counterpart or the explicit non-zero version instead.*)\nNotation comSemiRingType := (comNzSemiRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Try comPzRingType (the potentially-zero counterpart) first, or use comNzRingType instead.\")]\n(*A deprecated notation for a commutative non-zero ring type. It is recommended to use the potentially-zero counterpart or the explicit non-zero version instead.*)\nNotation comRingType := (comNzRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Try subPzSemiRingType (the potentially-zero counterpart) first, or use subNzSemiRingType instead.\")]\n(*A deprecated notation for a subtype that forms a non-zero semiring. It is recommended to use the potentially-zero counterpart or the explicit non-zero version instead.*)\nNotation subSemiRingType := (subNzSemiRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Try subComPzSemiRingType (the potentially-zero counterpart) first, or use subComNzSemiRingType instead.\")]\n(*A deprecated notation for a subtype that forms a commutative non-zero semiring. It is recommended to use the potentially-zero counterpart or the explicit non-zero version instead.*)\nNotation subComSemiRingType := (subComNzSemiRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Try subPzRingType (the potentially-zero counterpart) first, or use subNzRingType instead.\")]\n(*A deprecated notation for a subtype that forms a non-zero ring. It is recommended to use the potentially-zero counterpart or the explicit non-zero version instead.*)\nNotation subRingType := (subNzRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Try subComPzRingType (the potentially-zero counterpart) first, or use subComNzRingType instead.\")]\n(*A deprecated notation for a subtype representing a commutative non-zero ring. It is recommended to use its potentially-zero counterpart instead.*)\nNotation subComNzRingType := (subComNzRingType) (only parsing).\n\n(*A notation for the property that a subset of an additive group is closed under addition. This means that the sum of any two elements from the subset is also in the subset.*)\nNotation addrClosed := addrClosed.\n(*A notation for the property that a subset of an additive group is closed under the additive inverse operation. This means that the opposite of any element from the subset is also in the subset.*)\nNotation opprClosed := opprClosed.\n\n(*A variant type with a single constructor used to represent the multiplicative identity element, one, within a formal expression language for ring operations.*)\nVariant Ione := IOne : Ione.\n(*An inductive type representing formal integer multiples of the identity element in a ring. Its constructors allow for representing positive multiples via repeated addition of one, and for taking the additive inverse of such an expression. It is used to define the action of integers on a ring.*)\nInductive Inatmul :=\n(*This constructor builds a reified algebraic term representing the result of multiplying a given term by a natural number, an operation that corresponds to repeated addition.*)\n | INatmul : Ione -> nat -> Inatmul\n(*This constructor builds a reified algebraic term representing the additive inverse of a given term.*)\n | IOpp : Inatmul -> Inatmul.\n(*An empty variant type used as a technical placeholder for defining numerical notations.*)\nVariant Idummy_placeholder :=.\n\n(*This function parses a standard integer representation, such as decimal or hexadecimal, into a formal expression representing either a natural number multiple of the unit element or its additive inverse.*)\nDefinition parse (x : Number.int) : Inatmul :=\n match x with\n | Number.IntDecimal (Decimal.Pos u) => INatmul IOne (Nat.of_uint u)\n | Number.IntDecimal (Decimal.Neg u) => IOpp (INatmul IOne (Nat.of_uint u))\n | Number.IntHexadecimal (Hexadecimal.Pos u) =>\n INatmul IOne (Nat.of_hex_uint u)\n | Number.IntHexadecimal (Hexadecimal.Neg u) =>\n IOpp (INatmul IOne (Nat.of_hex_uint u))\n end.\n\n(*This function converts a formal expression representing a simple natural number multiple of the unit element, or its opposite, into an optional standard decimal integer representation, returning no value for more complex expressions.*)\nDefinition print (x : Inatmul) : option Number.int :=\n match x with\n | INatmul IOne n =>\n Some (Number.IntDecimal (Decimal.Pos (Nat.to_uint n)))\n | IOpp (INatmul IOne n) =>\n Some (Number.IntDecimal (Decimal.Neg (Nat.to_uint n)))\n | _ => None\n end.\n\nArguments GRing.one {_}.\nSet Warnings \"-via-type-remapping,-via-type-mismatch\".\nNumber Notation Idummy_placeholder parse print (via Inatmul\n mapping [[natmul] => INatmul, [opp] => IOpp, [one] => IOne])\n : ring_scope.\nSet Warnings \"via-type-remapping,via-type-mismatch\".\nArguments GRing.one : clear implicits.\n\n(*A notation for the additive identity element, commonly known as zero, within an algebraic structure equipped with addition.*)\nNotation \"0\" := (@zero _) : ring_scope.\n(*A notation for the unary function that maps an element of an additive group to its additive inverse.*)\nNotation \"-%R\" := (@opp _) : ring_scope.\n(*A notation for the additive inverse, or negation, of a given element in an additive group.*)\nNotation \"- x\" := (opp x) : ring_scope.\n(*A notation for the binary function that takes two elements of an additive group and returns their sum.*)\nNotation \"+%R\" := (@add _) : function_scope.\n(*A notation for the sum of two elements in a structure equipped with an addition operation.*)\nNotation \"x + y\" := (add x y) : ring_scope.\n(*A notation for the subtraction of two elements, defined as the sum of the first element and the additive inverse of the second.*)\nNotation \"x - y\" := (add x (- y)) : ring_scope.\nArguments natmul : simpl never.\n(*A notation for the repeated addition of a ring element to itself a specified number of times, corresponding to multiplication by a natural number.*)\nNotation \"x *+ n\" := (natmul x n) : ring_scope.\n(*A notation for the additive inverse of the result of repeatedly adding a ring element to itself a specified number of times.*)\nNotation \"x *- n\" := (opp (x *+ n)) : ring_scope.\n(*A notation for accessing the element at a given natural number index within a sequence, returning a default zero element if the index is out of bounds.*)\nNotation \"s `_ i\" := (seq.nth 0%R s%R i) : ring_scope.\n(*A notation for the support of a function, which is the set of input values for which the function's output is not the additive identity.*)\nNotation support := 0.-support.\n\n(*A notation for the multiplicative identity element, commonly known as one, in a ring or other multiplicative structure.*)\nNotation \"1\" := (@one _) : ring_scope.\n(*A notation for the additive inverse of the multiplicative identity element in a ring.*)\nNotation \"- 1\" := (opp 1) : ring_scope.\n\n(*A notation for embedding a natural number into a ring by taking the sum of the multiplicative identity with itself that many times.*)\nNotation \"n %:R\" := (natmul 1 n) : ring_scope.\nArguments GRing.pchar R%_type.\n(*A notation for the characteristic of a ring, which is the smallest positive integer for which the sum of that many multiplicative identity elements equals the additive identity, or zero if no such positive integer exists.*)\nNotation \"[ 'pchar' R ]\" := (GRing.pchar R) : ring_scope.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use [pchar R] instead.\")]\n(*A deprecated notation for the characteristic of a ring. The notation `[ 'pchar' R ]` should be used instead.*)\nNotation \"[ 'char' R ]\" := (GRing.pchar R) : ring_scope.\nNotation has_pchar0 R := (GRing.pchar R =i pred0).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use has_pchar0 instead.\")]\nNotation has_char0 R := (GRing.pchar R =i pred0).\nNotation pFrobenius_aut chRp := (pFrobenius_aut chRp).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut instead.\")]\nNotation Frobenius_aut chRp := (pFrobenius_aut chRp).\n(*A notation for the binary function that takes two elements of a multiplicative structure and returns their product.*)\nNotation \"*%R\" := (@mul _) : function_scope.\n(*A notation for the product of two elements in a structure equipped with a multiplication operation.*)\nNotation \"x * y\" := (mul x y) : ring_scope.\nArguments exp : simpl never.\n(*A notation for raising an element of a multiplicative structure to a non-negative integer power through repeated multiplication.*)\nNotation \"x ^+ n\" := (exp x n) : ring_scope.\n(*A notation for the multiplicative inverse of an element in a ring or group.*)\nNotation \"x ^-1\" := (inv x) : ring_scope.\n(*A notation for raising an element to a negative integer power, defined as the multiplicative inverse of the element raised to the corresponding positive power.*)\nNotation \"x ^- n\" := (inv (x ^+ n)) : ring_scope.\n(*A notation for the division of two elements, defined as the product of the first element and the multiplicative inverse of the second.*)\nNotation \"x / y\" := (mul x y^-1) : ring_scope.\n\n(*A notation for the binary function of scalar multiplication, which combines a scalar from a ring and an element from a module to produce a new module element.*)\nNotation \"*:%R\" := (@scale _ _) : function_scope.\n(*A notation for the scalar multiplication of a module element by a ring element.*)\nNotation \"a *: m\" := (scale a m) : ring_scope.\n(*A notation for embedding a scalar from a base ring into an algebra by scaling the algebra's multiplicative identity.*)\nNotation \"k %:A\" := (scale k 1) : ring_scope.\n(*A notation for the null function, which is a function that maps all inputs to the additive identity element of its codomain.*)\nNotation \"\\0\" := (null_fun _) : ring_scope.\n(*A notation for the pointwise addition of two functions, resulting in a new function where the value at each point is the sum of the original functions' values at that point.*)\nNotation \"f \\+ g\" := (add_fun f g) : ring_scope.\n(*A notation for the pointwise subtraction of two functions, resulting in a new function where the value at each point is the difference of the original functions' values at that point.*)\nNotation \"f \\- g\" := (sub_fun f g) : ring_scope.\n(*This notation represents the pointwise additive inverse of a function. The resulting function maps each input to the additive inverse of the original function's output for that same input.*)\nNotation \"\\- f\" := (opp_fun f) : ring_scope.\n(*This notation represents the pointwise scaling of a function by a scalar. The resulting function maps each input to the result of scaling the original function's output by the given scalar.*)\nNotation \"a \\*: f\" := (scale_fun a f) : ring_scope.\n(*This notation represents the pointwise left multiplication of a function's output by a ring element. The resulting function maps each input to the product of the given ring element and the original function's output.*)\nNotation \"x \\*o f\" := (mull_fun x f) : ring_scope.\n(*This notation represents the pointwise right multiplication of a function's output by a ring element. The resulting function maps each input to the product of the original function's output and the given ring element.*)\nNotation \"x \\o* f\" := (mulr_fun x f) : ring_scope.\n(*This notation represents the pointwise product of two functions. The resulting function maps each input to the product of the outputs of the two original functions for that same input.*)\nNotation \"f \\* g\" := (mul_fun f g) : ring_scope.\n\nArguments mull_fun {_ _} a f _ /.\nArguments mulr_fun {_ _} a f _ /.\nArguments scale_fun {_ _ _} a f _ /.\nArguments mul_fun {_ _} f g _ /.\n\n(*This notation represents the sum of ring elements generated by an expression for each item in a finite sequence that satisfies a given boolean predicate.*)\nNotation \"\\sum_ ( i <- r | P ) F\" :=\n (\\big[+%R/0%R]_(i <- r | P%B) F%R) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each item in a given finite sequence.*)\nNotation \"\\sum_ ( i <- r ) F\" :=\n (\\big[+%R/0%R]_(i <- r) F%R) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each natural number in an inclusive-exclusive range that satisfies a given boolean predicate.*)\nNotation \"\\sum_ ( m <= i < n | P ) F\" :=\n (\\big[+%R/0%R]_(m <= i < n | P%B) F%R) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each natural number in a given inclusive-exclusive range.*)\nNotation \"\\sum_ ( m <= i < n ) F\" :=\n (\\big[+%R/0%R]_(m <= i < n) F%R) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each element of a finite type that satisfies a given boolean predicate.*)\nNotation \"\\sum_ ( i | P ) F\" :=\n (\\big[+%R/0%R]_(i | P%B) F%R) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each element of a given finite type.*)\nNotation \"\\sum_ i F\" :=\n (\\big[+%R/0%R]_i F%R) : ring_scope.\n(*This notation, used for parsing only, represents the sum of ring elements generated by an expression for each element of a specified finite type that satisfies a given boolean predicate.*)\nNotation \"\\sum_ ( i : t | P ) F\" :=\n (\\big[+%R/0%R]_(i : t | P%B) F%R) (only parsing) : ring_scope.\n(*This notation, used for parsing only, represents the sum of ring elements generated by an expression for each element of a specified finite type.*)\nNotation \"\\sum_ ( i : t ) F\" :=\n (\\big[+%R/0%R]_(i : t) F%R) (only parsing) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each natural number less than a given bound that satisfies a boolean predicate.*)\nNotation \"\\sum_ ( i < n | P ) F\" :=\n (\\big[+%R/0%R]_(i < n | P%B) F%R) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each natural number less than a given bound.*)\nNotation \"\\sum_ ( i < n ) F\" :=\n (\\big[+%R/0%R]_(i < n) F%R) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each element in a finite set that satisfies a given boolean predicate.*)\nNotation \"\\sum_ ( i 'in' A | P ) F\" :=\n (\\big[+%R/0%R]_(i in A | P%B) F%R) : ring_scope.\n(*This notation represents the sum of ring elements generated by an expression for each element in a given finite set.*)\nNotation \"\\sum_ ( i 'in' A ) F\" :=\n (\\big[+%R/0%R]_(i in A) F%R) : ring_scope.\n\n(*This notation represents the product of ring elements generated by an expression for each item in a finite sequence that satisfies a given boolean predicate.*)\nNotation \"\\prod_ ( i <- r | P ) F\" :=\n (\\big[*%R/1%R]_(i <- r | P%B) F%R) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each item in a given finite sequence.*)\nNotation \"\\prod_ ( i <- r ) F\" :=\n (\\big[*%R/1%R]_(i <- r) F%R) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each natural number in an inclusive-exclusive range that satisfies a given boolean predicate.*)\nNotation \"\\prod_ ( m <= i < n | P ) F\" :=\n (\\big[*%R/1%R]_(m <= i < n | P%B) F%R) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each natural number in a given inclusive-exclusive range.*)\nNotation \"\\prod_ ( m <= i < n ) F\" :=\n (\\big[*%R/1%R]_(m <= i < n) F%R) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each element of a finite type that satisfies a given boolean predicate.*)\nNotation \"\\prod_ ( i | P ) F\" :=\n (\\big[*%R/1%R]_(i | P%B) F%R) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each element of a given finite type.*)\nNotation \"\\prod_ i F\" :=\n (\\big[*%R/1%R]_i F%R) : ring_scope.\n(*This notation, used for parsing only, represents the product of ring elements generated by an expression for each element of a specified finite type that satisfies a given boolean predicate.*)\nNotation \"\\prod_ ( i : t | P ) F\" :=\n (\\big[*%R/1%R]_(i : t | P%B) F%R) (only parsing) : ring_scope.\n(*This notation, used for parsing only, represents the product of ring elements generated by an expression for each element of a specified finite type.*)\nNotation \"\\prod_ ( i : t ) F\" :=\n (\\big[*%R/1%R]_(i : t) F%R) (only parsing) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each natural number less than a given bound that satisfies a boolean predicate.*)\nNotation \"\\prod_ ( i < n | P ) F\" :=\n (\\big[*%R/1%R]_(i < n | P%B) F%R) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each natural number less than a given bound.*)\nNotation \"\\prod_ ( i < n ) F\" :=\n (\\big[*%R/1%R]_(i < n) F%R) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each element in a finite set that satisfies a given boolean predicate.*)\nNotation \"\\prod_ ( i 'in' A | P ) F\" :=\n (\\big[*%R/1%R]_(i in A | P%B) F%R) : ring_scope.\n(*This notation represents the product of ring elements generated by an expression for each element in a given finite set.*)\nNotation \"\\prod_ ( i 'in' A ) F\" :=\n (\\big[*%R/1%R]_(i in A) F%R) : ring_scope.\n\n(*This notation represents the converse of a given binary relation. The converse relation holds between a pair of elements if and only if the original relation holds for those same elements in the reverse order.*)\nNotation \"R ^c\" := (converse R) (at level 2, format \"R ^c\") : type_scope.\n(*This notation represents the set of regular elements, which are elements that are not zero divisors, within a given ring structure.*)\nNotation \"R ^o\" := (regular R) (at level 2, format \"R ^o\") : type_scope.\n\nBind Scope term_scope with term.\nBind Scope term_scope with formula.\n\n(*This notation represents a formal variable indexed by a natural number within a term or formula.*)\nNotation \"''X_' i\" := (Var _ i) : term_scope.\n(*This notation represents the embedding of a natural number as a constant within a formal ring-like structure.*)\nNotation \"n %:R\" := (NatConst _ n) : term_scope.\n(*This notation represents the additive identity, or zero element, within a formal term structure.*)\nNotation \"0\" := 0%:R%T : term_scope.\n(*This notation represents the multiplicative identity, or one element, within a formal term structure.*)\nNotation \"1\" := 1%:R%T : term_scope.\n(*This notation represents the embedding of a value from a base type as a constant within a formal term.*)\nNotation \"x %:T\" := (Const x) : term_scope.\nInfix \"+\" := Add : term_scope.\n(*This notation represents the additive inverse, or opposite, of a given formal term.*)\nNotation \"- t\" := (Opp t) : term_scope.\n(*This notation represents the subtraction of two formal terms, defined as the addition of the first term and the additive inverse of the second term.*)\nNotation \"t - u\" := (Add t (- u)) : term_scope.\nInfix \"*\" := Mul : term_scope.\nInfix \"*+\" := NatMul : term_scope.\n(*This notation represents the multiplicative inverse of a given formal term.*)\nNotation \"t ^-1\" := (Inv t) : term_scope.\n(*This notation represents the division of two formal terms, defined as the multiplication of the first term by the multiplicative inverse of the second term.*)\nNotation \"t / u\" := (Mul t u^-1) : term_scope.\nInfix \"^+\" := Exp : term_scope.\nInfix \"==\" := Equal : term_scope.\n(*This notation represents the inequality of two formal formulas, defined as the logical negation of their equality.*)\nNotation \"x != y\" := (GRing.Not (x == y)) : term_scope.\nInfix \"/\\\" := And : term_scope.\nInfix \"\\/\" := Or : term_scope.\nInfix \"==>\" := Implies : term_scope.\n(*This notation represents the logical negation of a given formal formula.*)\nNotation \"~ f\" := (Not f) : term_scope.\n(*This notation represents existential quantification, asserting that there exists a value for a specific formal variable that makes a given formula true.*)\nNotation \"''exists' ''X_' i , f\" := (Exists i f) : term_scope.\n(*This notation represents universal quantification, asserting that a given formula holds true for all possible values of a specific formal variable.*)\nNotation \"''forall' ''X_' i , f\" := (Forall i f) : term_scope.\n\nSection Sum.\n\nVariables (aT : finType) (rT : nmodType).\nVariables (I : Type) (r : seq I) (P : pred I) (F : I -> {ffun aT -> rT}).\n\n(*This lemma states that evaluating the sum of a sequence of finite functions at a specific point is equivalent to summing the evaluations of each individual function at that same point.*)\nLemma sum_ffunE x : (\\sum_(i <- r | P i) F i) x = \\sum_(i <- r | P i) F i x.\n\n(*This lemma asserts that the sum of a sequence of finite functions is a new finite function whose value at any given point is the sum of the values of the original functions at that same point.*)\nLemma sum_ffun :\n \\sum_(i <- r | P i) F i = [ffun x => \\sum_(i <- r | P i) F i x].\n\nEnd Sum.\n\nSection FinFunSemiRing.\n\nVariable (aT : finType) (R : pzSemiRingType).\n\n(*This definition introduces the multiplicative identity for a structure of finite functions, which is the constant function that maps every element of its domain to the multiplicative identity of the target ring.*)\nDefinition ffun_one : {ffun aT -> R} := [ffun => 1].\n(*This definition specifies the multiplication operation for two finite functions as their pointwise product, where the resulting function's value at any point is the product of the original functions' values at that same point.*)\nDefinition ffun_mul (f g : {ffun aT -> R}) := [ffun x => f x * g x].\n\n(*This fact asserts that the pointwise multiplication operation defined for finite functions is associative.*)\nFact ffun_mulA : associative ffun_mul.\n\n(*This fact asserts that the constant one function acts as a left identity for the pointwise multiplication of finite functions.*)\nFact ffun_mul_1l : left_id ffun_one ffun_mul.\n\n(*This fact asserts that the constant one function acts as a right identity for the pointwise multiplication of finite functions.*)\nFact ffun_mul_1r : right_id ffun_one ffun_mul.\n\n(*This fact asserts that pointwise multiplication of finite functions is left-distributive over their pointwise addition.*)\nFact ffun_mul_addl : left_distributive ffun_mul (@ffun_add _ _).\n\n(*This fact asserts that pointwise multiplication of finite functions is right-distributive over their pointwise addition.*)\nFact ffun_mul_addr : right_distributive ffun_mul (@ffun_add _ _).\n\n(*This fact asserts that the constant zero function acts as a left annihilator for the pointwise multiplication of finite functions, meaning any function multiplied by it on the left results in the zero function.*)\nFact ffun_mul_0l : left_zero (@ffun_zero _ _) ffun_mul.\n\n(*This fact asserts that the constant zero function acts as a right annihilator for the pointwise multiplication of finite functions, meaning any function multiplied by it on the right results in the zero function.*)\nFact ffun_mul_0r : right_zero (@ffun_zero _ _) ffun_mul.\n\n#[export]\n(*This definition establishes that the type of finite functions, mapping from a finite type to a pseudo-semiring, itself forms a pseudo-semiring structure.*)\nDefinition ffun_semiring : pzSemiRingType := {ffun aT -> R}.\nEnd FinFunSemiRing.\n\nSection FinFunSemiRing.\n\nVariable (aT : finType) (R : nzSemiRingType) (a : aT).\n\n(*This fact asserts that for functions mapping from a non-empty finite type to a non-trivial semiring, the constant one function is distinct from the constant zero function.*)\nFact ffun1_nonzero : ffun_one aT R != 0.\n\nEnd FinFunSemiRing.\n\nHB.instance Definition _ (aT : finType) (R : pzRingType) :=\n Zmodule_isPzRing.Build {ffun aT -> R}\n (@ffun_mulA _ _) (@ffun_mul_1l _ _) (@ffun_mul_1r _ _)\n (@ffun_mul_addl _ _) (@ffun_mul_addr _ _).\n\nSection FinFunRing.\n\nVariable (aT : finType) (R : nzRingType) (a : aT).\n\n(*This definition establishes that the type of finite functions, mapping from a non-empty finite type to a non-trivial ring, itself forms a non-trivial ring structure.*)\nDefinition ffun_ring : nzRingType := {ffun aT -> R}.\n\nEnd FinFunRing.\n\nSection FinFunComRing.\n\nVariable (aT : finType) (R : comPzRingType) (a : aT).\n\n(*This fact asserts that if the target ring is commutative, then the pointwise multiplication of finite functions with values in that ring is also a commutative operation.*)\nFact ffun_mulC : commutative (@ffun_mul aT R).\n\nEnd FinFunComRing.\n\nSection FinFunLSemiMod.\n\nVariable (R : pzSemiRingType) (aT : finType) (rT : lSemiModType R).\n\nImplicit Types f g : {ffun aT -> rT}.\n\n(*This definition specifies scalar multiplication for a finite function, where the resulting function's value at any point is obtained by scaling the original function's value at that point by the given scalar.*)\nDefinition ffun_scale k f := [ffun a => k *: f a].\n\n(*This lemma states that scaling a finite function by a first scalar, and then scaling the result by a second scalar, is equivalent to scaling the original function by the product of the two scalars.*)\nFact ffun_scaleA k1 k2 f :\n ffun_scale k1 (ffun_scale k2 f) = ffun_scale (k1 * k2) f.\n\n(*This lemma states that scaling a finite function by the scalar zero results in the zero function.*)\nFact ffun_scale0r f : ffun_scale 0 f = 0.\n\n(*This lemma states that the scalar one is a left identity for the finite function scaling operation, meaning scaling any finite function by one returns the original function.*)\nFact ffun_scale1 : left_id 1 ffun_scale.\n\n(*This lemma states that scaling the sum of two finite functions by a scalar is equivalent to summing the results of scaling each function individually by that same scalar.*)\nFact ffun_scale_addr k : {morph (ffun_scale k) : x y / x + y}.\n\n(*This lemma states that scaling a finite function by the sum of two scalars is equivalent to summing the results of scaling that function by each scalar individually.*)\nFact ffun_scale_addl u : {morph (ffun_scale)^~ u : k1 k2 / k1 + k2}.\n\n#[export]\n(*This definition specifies the multiplication of two pairs of semiring elements as the component-wise product of the pairs, where the first components are multiplied together and the second components are multiplied together.*)\nDefinition mul_pair (x y : R1 * R2) := (x.1 * y.1, x.2 * y.2).\n\n(*This lemma states that the component-wise multiplication of pairs of semiring elements is an associative operation.*)\nFact pair_mulA : associative mul_pair.\n\n(*This lemma states that the pair of multiplicative identities is the left identity for the component-wise multiplication of pairs of semiring elements.*)\nFact pair_mul1l : left_id (1, 1) mul_pair.\n\n(*This lemma states that the pair of multiplicative identities is the right identity for the component-wise multiplication of pairs of semiring elements.*)\nFact pair_mul1r : right_id (1, 1) mul_pair.\n\n(*This lemma states that component-wise multiplication of pairs of semiring elements distributes on the left over component-wise addition.*)\nFact pair_mulDl : left_distributive mul_pair +%R.\n\n(*This lemma states that component-wise multiplication of pairs of semiring elements distributes on the right over component-wise addition.*)\nFact pair_mulDr : right_distributive mul_pair +%R.\n\n(*This lemma states that the pair of additive identities is a left zero for the component-wise multiplication of pairs of semiring elements, meaning multiplying any pair by it on the left results in the zero pair.*)\nFact pair_mul0r : left_zero 0 mul_pair.\n\n(*This lemma states that the pair of additive identities is a right zero for the component-wise multiplication of pairs of semiring elements, meaning multiplying any pair by it on the right results in the zero pair.*)\nFact pair_mulr0 : right_zero 0 mul_pair.\n\n#[export]\nHB.instance Definition _ := Nmodule_isPzSemiRing.Build (R1 * R2)%type\n pair_mulA pair_mul1l pair_mul1r pair_mulDl pair_mulDr pair_mul0r pair_mulr0.\n\n(*This lemma states that the projection function, which extracts the first component from a pair of semiring elements, is a monoid morphism, preserving both multiplication and the multiplicative identity.*)\nFact fst_is_monoid_morphism : monoid_morphism fst. \n#[export]\nHB.instance Definition _ := isMonoidMorphism.Build (R1 * R2)%type R1 fst\n fst_is_monoid_morphism.\n(*This lemma states that the projection function, which extracts the second component from a pair of semiring elements, is a monoid morphism, preserving both multiplication and the multiplicative identity.*)\nFact snd_is_monoid_morphism : monoid_morphism snd. \n#[export]\nHB.instance Definition _ := isMonoidMorphism.Build (R1 * R2)%type R2 snd\n snd_is_monoid_morphism.\n\nEnd PairSemiRing.\n\nSection PairSemiRing.\n\nVariables R1 R2 : nzSemiRingType.\n\n(*This lemma states that for a product of two non-zero semirings, the multiplicative identity pair is not equal to the additive identity pair.*)\nFact pair_one_neq0 : 1 != 0 :> R1 * R2.\n\n#[export]\n(*This lemma states that if the component semirings are commutative, then the component-wise multiplication of pairs is also a commutative operation.*)\nFact pair_mulC : commutative (@mul_pair R1 R2).\n\n#[export]\n(*This definition specifies the scalar multiplication of a pair of module elements by a ring element as the component-wise scaling of each element of the pair by that same scalar.*)\nDefinition scale_pair a (v : V1 * V2) : V1 * V2 := (a *: v.1, a *: v.2).\n\n(*This lemma states that scaling a pair of module elements by one scalar, and then scaling the result by a second scalar, is equivalent to scaling the original pair by the product of the two scalars.*)\nFact pair_scaleA a b u : scale_pair a (scale_pair b u) = scale_pair (a * b) u.\n\n(*This lemma states that scaling a pair of module elements by the scalar zero results in the zero pair.*)\nFact pair_scale0 u : scale_pair 0 u = 0.\n\n(*This lemma states that scaling a pair of module elements by the scalar one returns the original pair.*)\nFact pair_scale1 u : scale_pair 1 u = u.\n\n(*This lemma states that scalar multiplication of pairs of module elements distributes on the right over the component-wise addition of pairs.*)\nFact pair_scaleDr : right_distributive scale_pair +%R.\n\n(*This lemma states that scaling a pair of module elements by a sum of two scalars is equivalent to the sum of scaling the pair by each scalar individually.*)\nFact pair_scaleDl u : {morph scale_pair^~ u: a b / a + b}.\n\n#[export]\nHB.instance Definition _ := Nmodule_isLSemiModule.Build R (V1 * V2)%type\n pair_scaleA pair_scale0 pair_scale1 pair_scaleDr pair_scaleDl.\n\n(*This lemma states that the projection function, which extracts the first component from a pair of module elements, commutes with scalar multiplication.*)\nFact fst_is_scalable : scalable fst. \n#[export]\nHB.instance Definition _ :=\n isScalable.Build R (V1 * V2)%type V1 *:%R fst fst_is_scalable.\n(*This lemma states that the projection function, which extracts the second component from a pair of module elements, commutes with scalar multiplication.*)\nFact snd_is_scalable : scalable snd. \n#[export]\n(*This lemma states a compatibility property for pairs of left semi-algebra elements, asserting that scaling a product of two pairs by a scalar is equivalent to scaling the first pair by that scalar before performing the multiplication.*)\nFact pair_scaleAl a (u v : A1 * A2) : a *: (u * v) = (a *: u) * v.\n\n#[export]\nHB.instance Definition _ := LSemiModule_isLSemiAlgebra.Build R (A1 * A2)%type\n pair_scaleAl.\n\n#[export]\nHB.instance Definition _ := RMorphism.on (@fst A1 A2).\n#[export]\n(*This lemma states a compatibility property for pairs of semi-algebra elements, asserting that scaling a product of two pairs by a scalar is equivalent to multiplying the first pair by the result of scaling the second pair by that scalar.*)\nFact pair_scaleAr a (u v : A1 * A2) : a *: (u * v) = u * (a *: v).\n\n#[export]\n(*This definition specifies the predicate for an element of a product of two rings to be a unit, which holds if and only if both of its components are units in their respective rings.*)\nDefinition pair_unitr :=\n [qualify a x : R1 * R2 | (x.1 \\is a GRing.unit) && (x.2 \\is a GRing.unit)].\n(*This definition specifies the multiplicative inverse of an element in a product of two rings. If the element is a unit, its inverse is the pair of the multiplicative inverses of its components; otherwise, the function returns the original element.*)\nDefinition pair_invr x :=\n if x \\is a pair_unitr then (x.1^-1, x.2^-1) else x.\n\n(*This lemma states that for any unit element in a product of two rings, its inverse, computed component-wise, acts as a left multiplicative inverse, yielding the multiplicative identity pair when multiplied.*)\nLemma pair_mulVl : {in pair_unitr, left_inverse 1 pair_invr *%R}.\n\n(*This lemma states that for any unit element in a product ring, multiplying that element by its inverse yields the multiplicative identity.*)\nLemma pair_mulVr : {in pair_unitr, right_inverse 1 pair_invr *%R}.\n\n(*This lemma states that an element in a product ring is a unit if there exists another element that serves as both its left and right multiplicative inverse.*)\nLemma pair_unitP x y : y * x = 1 /\\ x * y = 1 -> x \\is a pair_unitr.\n\n(*This lemma states that for any element in a product ring that is not a unit, its formal multiplicative inverse is defined to be the element itself.*)\nLemma pair_invr_out : {in [predC pair_unitr], pair_invr =1 id}.\n\n#[export]\n(*This lemma states that scalar multiplication of a pair in a product of two Z-modules by a natural number is equivalent to performing the scalar multiplication on each component of the pair individually.*)\nLemma pairMnE (M1 M2 : zmodType) (x : M1 * M2) n :\n x *+ n = (x.1 *+ n, x.2 *+ n).\n\nHB.instance Definition _ := Zmodule_isComNzRing.Build bool\n andbA andbC andTb andb_addl isT.\n\n(*This fact states that for any non-zero boolean value, its product with itself is equal to the boolean value for true.*)\nFact mulVb (b : bool) : b != 0 -> b * b = 1.\n\n(*This fact states that if the product of two boolean values is true, then the second boolean value must be non-zero.*)\nFact invb_out (x y : bool) : y * x = 1 -> x != 0.\n\nHB.instance Definition _ := ComNzRing_hasMulInverse.Build bool\n mulVb invb_out (fun x => fun => erefl x).\n\n(*This lemma states that the boolean type, with its standard logical operations interpreted as arithmetic, satisfies the axioms of a field.*)\nLemma bool_fieldP : Field.axiom bool. \n\nHB.instance Definition _ := ComUnitRing_isField.Build bool bool_fieldP.\n\nHB.instance Definition _ := Nmodule_isComNzSemiRing.Build nat\n mulnA mulnC mul1n mulnDl mul0n erefl.\n\n(*This lemma states that the additive identity of a ring is equal to the ring element corresponding to the natural number zero.*)\nLemma natr0E : 0 = 0%N. \n(*This lemma states that the multiplicative identity of a ring is equal to the ring element corresponding to the natural number one.*)\nLemma natr1E : 1 = 1%N. \n(*This lemma states that the explicit notation for embedding a natural number into a ring yields the same ring element as the standard implicit coercion.*)\nLemma natn n : n%:R = n.\n\n(*This lemma states that adding two natural numbers within a ring is equivalent to first adding them as natural numbers and then embedding the result into the ring.*)\nLemma natrDE n m : n + m = (n + m)%N. \n(*This lemma states that multiplying two natural numbers within a ring is equivalent to first multiplying them as natural numbers and then embedding the result into the ring.*)\nLemma natrME n m : n * m = (n * m)%N. \n(*This lemma states that raising a natural number to the power of another natural number within a ring is equivalent to first performing the exponentiation with natural numbers and then embedding the result into the ring.*)\nLemma natrXE n m : n ^+ m = (n ^ m)%N. \n(*This definition aggregates several lemmas into a single tuple, collectively demonstrating that the canonical embedding of natural numbers into a ring preserves the ring structure, including its identities, addition, multiplication, and exponentiation.*)", - "algebra.intdiv": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype tuple prime order.\nFrom mathcomp Require Import ssralg poly ssrnum ssrint matrix.\nFrom mathcomp Require Import polydiv perm zmodp bigop.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport Order.TTheory GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\n(*This definition computes the integer quotient of a dividend and a divisor, both integers. The quotient is defined such that the corresponding remainder is always non-negative.*)\nDefinition divz (m d : int) : int :=\n let: (K, n) := match m with Posz n => (Posz, n) | Negz n => (Negz, n) end in\n sgz d * K (n %/ `|d|)%N.\n\n(*This definition computes the non-negative integer remainder of the Euclidean division of an integer dividend by an integer divisor. The remainder is the result of a subtraction of the product of the quotient and the divisor from the dividend.*)\nDefinition modz (m d : int) : int := m - divz m d * d.\n\n(*This definition provides a boolean predicate that is true if an integer divisor divides an integer dividend. The check is performed by testing if the absolute value of the divisor divides the absolute value of the dividend as natural numbers.*)\nDefinition dvdz d m := (`|d| %| `|m|)%N.\n\n(*This definition computes the greatest common divisor of two integers. The result is a non-negative integer obtained by calculating the greatest common divisor of the absolute values of the two input integers.*)\nDefinition gcdz m n := (gcdn `|m| `|n|)%:Z.\n\n(*This definition computes the least common multiple of two integers. The result is a non-negative integer obtained by calculating the least common multiple of the absolute values of the two input integers.*)\nDefinition lcmz m n := (lcmn `|m| `|n|)%:Z.\n\n(*This definition computes the B\u00e9zout coefficients for two integers. It returns a pair of integers, say u and v, such that the sum of the product of u and the first integer and the product of v and the second integer equals the greatest common divisor of the two integers.*)\nDefinition egcdz m n : int * int :=\n if m == 0 then (0, (-1) ^+ (n < 0)%R) else\n let: (u, v) := egcdn `|m| `|n| in (sgz m * u, - (-1) ^+ (n < 0)%R * v%:Z).\n\n(*This definition provides a boolean predicate that is true if two integers are coprime. Two integers are considered coprime if their greatest common divisor is equal to one.*)\nDefinition coprimez m n := (gcdz m n == 1).\n\nInfix \"%/\" := divz : int_scope.\nInfix \"%%\" := modz : int_scope.\n(*This notation represents the predicate that an integer `d` divides an integer `m`.*)\nNotation \"d %| m\" := (m \\in dvdz d) : int_scope.\n(*This notation asserts the propositional equality that two integers, `m` and `n`, have the same remainder when divided by an integer `d`.*)\nNotation \"m = n %[mod d ]\" := (modz m d = modz n d) : int_scope.\n(*This notation represents the boolean-valued check that two integers, `m` and `n`, have the same remainder when divided by an integer `d`.*)\nNotation \"m == n %[mod d ]\" := (modz m d == modz n d) : int_scope.\n(*This notation asserts the propositional inequality that two integers, `m` and `n`, have different remainders when divided by an integer `d`.*)\nNotation \"m <> n %[mod d ]\" := (modz m d <> modz n d) : int_scope.\n(*This notation represents the boolean-valued check that two integers, `m` and `n`, have different remainders when divided by an integer `d`.*)\nNotation \"m != n %[mod d ]\" := (modz m d != modz n d) : int_scope.\n\n(*This lemma states that the integer division of two natural numbers yields the same result as their division performed in the domain of natural numbers.*)\nLemma divz_nat (n d : nat) : (n %/ d)%Z = (n %/ d)%N.\n\n(*This lemma states that dividing an integer by the additive inverse of another integer is equivalent to taking the additive inverse of their quotient.*)\nLemma divzN m d : (m %/ - d)%Z = - (m %/ d)%Z.\n\n(*This lemma relates the integer quotient of an integer `m` by the absolute value of an integer `d` to the quotient of `m` by `d`. The former is equal to the latter, multiplied by negative one if `d` is negative, and unchanged otherwise.*)\nLemma divz_abs (m d : int) : (m %/ `|d|)%Z = (-1) ^+ (d < 0)%R * (m %/ d)%Z.\n\n(*This lemma states that the integer division of zero by any integer results in zero.*)\nLemma div0z d : (0 %/ d)%Z = 0.\n\n(*This lemma provides a formula for the integer quotient of a negative integer by a positive natural number. The result is expressed as the additive inverse of the sum of one and the natural number quotient of their absolute values.*)\nLemma divNz_nat m d : (d > 0)%N -> (Negz m %/ d)%Z = - (m %/ d).+1%:Z.\n\n(*This lemma states the fundamental property of Euclidean division for integers: a dividend is equal to the sum of its remainder and the product of its quotient and the divisor.*)\nLemma divz_eq m d : m = (m %/ d)%Z * d + (m %% d)%Z.\n\n(*This lemma states that the integer remainder of a division is unchanged when the divisor is replaced by its additive inverse.*)\nLemma modzN m d : (m %% - d)%Z = (m %% d)%Z.\n\n(*This lemma states that the integer remainder of a division is the same whether the divisor is used directly or its absolute value is used instead.*)\nLemma modz_abs m d : (m %% `|d|%N)%Z = (m %% d)%Z.\n\n(*This lemma states that the integer remainder from the division of two natural numbers is equal to the remainder calculated using natural number division.*)\nLemma modz_nat (m d : nat) : (m %% d)%Z = (m %% d)%N.\n\n(*This lemma provides a formula for the integer remainder when a negative integer is divided by a positive natural number. The result is expressed in terms of the divisor and the natural number remainder of the absolute values of the inputs.*)\nLemma modNz_nat m d : (d > 0)%N -> (Negz m %% d)%Z = d%:Z - 1 - (m %% d)%:Z.\n\n(*This lemma states that for a non-zero divisor, the integer remainder of a division is always greater than or equal to zero.*)\nLemma modz_ge0 m d : d != 0 -> 0 <= (m %% d)%Z.\n\n(*This lemma states that the integer division of any integer by zero results in zero.*)\nLemma divz0 m : (m %/ 0)%Z = 0. \n(*This lemma states that the integer remainder of zero divided by any integer is zero.*)\nLemma mod0z d : (0 %% d)%Z = 0. \n(*This lemma states that the integer remainder of any integer divided by zero is the integer itself.*)\nLemma modz0 m : (m %% 0)%Z = m. \n\n(*This lemma states that if a non-negative integer is strictly less than the absolute value of the divisor, the quotient of their integer division is zero.*)\nLemma divz_small m d : 0 <= m < `|d|%:Z -> (m %/ d)%Z = 0.\n\n(*This lemma states that for a non-zero divisor, the integer quotient of a sum, where one term is a multiple of the divisor, is equal to the sum of the multiplier and the quotient of the remaining term.*)\nLemma divzMDl q m d : d != 0 -> ((q * d + m) %/ d)%Z = q + (m %/ d)%Z.\n\n(*This lemma states that for a non-zero divisor, dividing the product of an integer and the divisor by that same divisor yields the original integer.*)\nLemma mulzK m d : d != 0 -> (m * d %/ d)%Z = m.\n\n(*This lemma states that for a non-zero divisor, dividing the product of the divisor and an integer by that same divisor yields the original integer.*)\nLemma mulKz m d : d != 0 -> (d * m %/ d)%Z = m.\n\n(*This lemma states that for a non-zero integer base, raising it to the power of the difference between two natural numbers, where the first is greater than or equal to the second, is equivalent to the integer division of the base raised to the first number by the base raised to the second number.*)\nLemma expzB p m n : p != 0 -> (m >= n)%N -> p ^+ (m - n) = (p ^+ m %/ p ^+ n)%Z.\n\n(*This lemma states that the integer remainder of any integer divided by one is always zero.*)\nLemma modz1 m : (m %% 1)%Z = 0.\n\n(*This lemma states that the integer division of any integer by one results in the original integer.*)\nLemma divz1 m : (m %/ 1)%Z = m. \n\n(*This lemma states that the integer division of any integer by itself yields one if the integer is non-zero, and zero otherwise.*)\nLemma divzz d : (d %/ d)%Z = (d != 0).\n\n(*This lemma states that for a positive integer divisor, the integer remainder of any integer dividend is strictly less than the divisor.*)\nLemma ltz_pmod m d : d > 0 -> (m %% d)%Z < d.\n\n(*This lemma states that for a non-zero integer divisor, the integer remainder of any integer dividend is strictly less than the absolute value of the divisor.*)\nLemma ltz_mod m d : d != 0 -> (m %% d)%Z < `|d|.\n\n(*This lemma states that for any positive integer factor, the integer quotient of a division is invariant if both the dividend and the divisor are multiplied by that factor on the left.*)\nLemma divzMpl p m d : p > 0 -> (p * m %/ (p * d) = m %/ d)%Z.\n\nArguments divzMpl [p m d].\n\n(*This lemma states that for any positive integer factor, the integer quotient of a division is invariant if both the dividend and the divisor are multiplied by that factor on the right.*)\nLemma divzMpr p m d : p > 0 -> (m * p %/ (d * p) = m %/ d)%Z.\n\nArguments divzMpr [p m d].\n\n(*This lemma states that for any non-zero integer divisor, the product of the integer quotient and the divisor is always less than or equal to the original integer dividend.*)\nLemma lez_floor m d : d != 0 -> (m %/ d)%Z * d <= m.\n\n(*This lemma states that the absolute value of the integer quotient of two integers is always less than or equal to the absolute value of the dividend, provided the divisor is not zero.*)\nLemma lez_div m d : (`|(m %/ d)%Z| <= `|m|)%N.\n\n(*This lemma states that for a positive integer divisor, the dividend is strictly less than the product of the successor of the integer quotient and the divisor.*)\nLemma ltz_ceil m d : d > 0 -> m < ((m %/ d)%Z + 1) * d.\n\n(*This lemma states that for a positive integer divisor, the assertion that an integer quotient is strictly less than another integer is equivalent to the assertion that the original dividend is strictly less than the product of that other integer and the divisor.*)\nLemma ltz_divLR m n d : d > 0 -> ((m %/ d)%Z < n) = (m < n * d).\n\n(*This lemma states that for a positive integer divisor, the assertion that an integer is less than or equal to an integer quotient is equivalent to the assertion that the product of the first integer and the divisor is less than or equal to the dividend of the quotient.*)\nLemma lez_divRL m n d : d > 0 -> (m <= (n %/ d)%Z) = (m * d <= n).\n\n(*This lemma states that for any non-negative integer divisor, the operation of integer division by that divisor is non-decreasing; that is, if one integer is less than or equal to another, their respective quotients upon division by the fixed divisor maintain the same ordering relationship.*)\nLemma lez_pdiv2r d : 0 <= d -> {homo divz^~ d : m n / m <= n}.\n\n(*This lemma states that when dividing an integer by a positive integer, the resulting quotient is non-negative if and only if the original integer is non-negative.*)\nLemma divz_ge0 m d : d > 0 -> ((m %/ d)%Z >= 0) = (m >= 0).\n\n(*This lemma states that for a non-negative integer intermediate divisor, integer division is associative; dividing an integer by a product of two other integers is equivalent to successively dividing by each of those integers.*)\nLemma divzMA_ge0 m n p : n >= 0 -> (m %/ (n * p) = (m %/ n)%Z %/ p)%Z.\n\n(*This lemma states that if a non-negative integer is strictly smaller than a positive integer divisor, its remainder upon division by that divisor is the integer itself.*)\nLemma modz_small m d : 0 <= m < d -> (m %% d)%Z = m.\n\n(*This lemma states that the integer remainder operation is equivalent to the canonical integer modulo operation.*)\nLemma modz_mod m d : ((m %% d)%Z = m %[mod d])%Z.\n\n(*This lemma states that adding a multiple of the modulus to an integer does not change its value modulo that modulus.*)\nLemma modzMDl p m d : (p * d + m = m %[mod d])%Z.\n\n(*This lemma states that for a positive integer multiplier, multiplying the integer remainder of a division by that multiplier is equivalent to taking the remainder of the dividend and divisor each multiplied by that same multiplier.*)\nLemma mulz_modr {p m d} : 0 < p -> p * (m %% d)%Z = ((p * m) %% (p * d))%Z.\n\n(*This lemma states that for a positive integer multiplier, the product of the integer remainder of a division and that multiplier is equivalent to the remainder of the product of the dividend and the multiplier divided by the product of the divisor and the multiplier.*)\nLemma mulz_modl {p m d} : 0 < p -> (m %% d)%Z * p = ((m * p) %% (d * p))%Z.\n\n(*This lemma states that adding the modulus to an integer results in a value that is congruent to the original integer modulo that modulus.*)\nLemma modzDl m d : (d + m = m %[mod d])%Z.\n\n(*This lemma states that an integer added to its modulus results in a value that is congruent to the original integer modulo that modulus.*)\nLemma modzDr m d : (m + d = m %[mod d])%Z.\n\n(*This lemma states that the integer remainder of any integer divided by itself is zero.*)\nLemma modzz d : (d %% d)%Z = 0.\n\n(*This lemma states that the integer remainder of any left-multiple of the divisor, when divided by that divisor, is zero.*)\nLemma modzMl p d : (p * d %% d)%Z = 0.\n\n(*This lemma states that the integer remainder is zero when any right-multiple of the divisor is divided by that divisor.*)\nLemma modzMr p d : (d * p %% d)%Z = 0.\n\n(*This lemma states that the sum of an integer remainder and another integer is congruent to the sum of the original integer and the other integer, all modulo the same divisor.*)\nLemma modzDml m n d : ((m %% d)%Z + n = m + n %[mod d])%Z.\n\n(*This lemma states that the sum of an integer and an integer remainder is congruent to the sum of their original integer values, all modulo the same divisor.*)\nLemma modzDmr m n d : (m + (n %% d)%Z = m + n %[mod d])%Z.\n\n(*This lemma states that the sum of the integer remainders of two integers with respect to a common divisor is congruent to the sum of the two original integers modulo that divisor.*)\nLemma modzDm m n d : ((m %% d)%Z + (n %% d)%Z = m + n %[mod d])%Z.\n\n(*This lemma states that adding the same integer to both sides of a modular congruence does not alter the truth of the congruence.*)\nLemma eqz_modDl p m n d : (p + m == p + n %[mod d])%Z = (m == n %[mod d])%Z.\n\n(*This lemma states that for integers, the equality of two integers modulo a third integer holds if and only if the equality also holds when a fourth integer is added to each of the first two integers.*)\nLemma eqz_modDr p m n d : (m + p == n + p %[mod d])%Z = (m == n %[mod d])%Z.\n\n(*This lemma states that for any three integers, the product of the remainder of the first integer divided by the third and the second integer is congruent to the product of the first and second integers, all modulo the third integer.*)\nLemma modzMml m n d : ((m %% d)%Z * n = m * n %[mod d])%Z.\n \n\n(*This lemma states that for any three integers, the product of the first integer and the remainder of the second integer divided by the third is congruent to the product of the first and second integers, all modulo the third integer.*)\nLemma modzMmr m n d : (m * (n %% d)%Z = m * n %[mod d])%Z.\n\n(*This lemma states that for any three integers, the product of the remainder of the first integer divided by the third and the remainder of the second integer divided by the third is congruent to the product of the first and second integers, all modulo the third integer.*)\nLemma modzMm m n d : ((m %% d)%Z * (n %% d)%Z = m * n %[mod d])%Z.\n\n(*This lemma states that for an integer base, an integer modulus, and a natural number exponent, raising the remainder of the base divided by the modulus to the power of the exponent results in a value congruent to the base raised to the same power, all modulo the modulus.*)\nLemma modzXm k m d : ((m %% d)%Z ^+ k = m ^+ k %[mod d])%Z.\n\n(*This lemma states that for any two integers, the additive inverse of the remainder of the first integer divided by the second is congruent to the additive inverse of the first integer, modulo the second integer.*)\nLemma modzNm m d : (- (m %% d)%Z = - m %[mod d])%Z.\n\n(*This lemma relates the absolute value of an integer to its remainder modulo another integer, stating that the absolute value is congruent to the product of the remainder and a correcting sign factor, all modulo the second integer.*)\nLemma modz_absm m d : ((-1) ^+ (m < 0)%R * (m %% d)%Z = `|m|%:Z %[mod d])%Z.\n\n(*This lemma states that an integer d divides an integer m if and only if the absolute value of d as a natural number divides the absolute value of m as a natural number.*)\nLemma dvdzE d m : (d %| m)%Z = (`|d| %| `|m|)%N. \n(*This lemma states that any integer divides zero.*)\nLemma dvdz0 d : (d %| 0)%Z. \n(*This lemma states that zero divides an integer if and only if that integer is zero.*)\nLemma dvd0z n : (0 %| n)%Z = (n == 0). \n(*This lemma states that an integer divides one if and only if its absolute value as a natural number is equal to one.*)\nLemma dvdz1 d : (d %| 1)%Z = (`|d|%N == 1). \n(*This lemma states that the integer one divides any integer.*)\nLemma dvd1z m : (1 %| m)%Z. \n(*This lemma states that any integer divides itself.*)\nLemma dvdzz m : (m %| m)%Z. \n\n(*This lemma states that if a first integer divides a third integer, it also divides the product of any second integer and the third integer.*)\nLemma dvdz_mull d m n : (d %| n)%Z -> (d %| m * n)%Z.\n\n(*This lemma states that if a first integer divides a second integer, it also divides the product of the second integer and any third integer.*)\nLemma dvdz_mulr d m n : (d %| m)%Z -> (d %| m * n)%Z.\n\n#[global] Hint Resolve dvdz0 dvd1z dvdzz dvdz_mull dvdz_mulr : core.\n\n(*This lemma states that if a first integer divides a third integer and a second integer divides a fourth integer, then the product of the first and second integers divides the product of the third and fourth integers.*)\nLemma dvdz_mul d1 d2 m1 m2 : (d1 %| m1 -> d2 %| m2 -> d1 * d2 %| m1 * m2)%Z.\n\n(*This lemma states that integer divisibility is transitive: if a first integer divides a second and the second divides a third, then the first divides the third.*)\nLemma dvdz_trans n d m : (d %| n -> n %| m -> d %| m)%Z.\n\n(*This lemma provides a reflection between the boolean statement that a first integer divides a second integer and the propositional statement that there exists an integer quotient such that the second integer is the product of the quotient and the first integer.*)\nLemma dvdzP d m : reflect (exists q, m = q * d) (d %| m)%Z.\n\nArguments dvdzP {d m}.\n\n(*This lemma provides a reflection between the boolean statement that a first integer divides a second integer and the statement that the remainder of the second integer divided by the first is zero.*)\nLemma dvdz_mod0P d m : reflect (m %% d = 0)%Z (d %| m)%Z.\n\nArguments dvdz_mod0P {d m}.\n\n(*This lemma states that an integer d divides an integer m if and only if m is equal to the product of the quotient of m by d and d.*)\nLemma dvdz_eq d m : (d %| m)%Z = ((m %/ d)%Z * d == m).\n\n(*This lemma states that if an integer d divides an integer m, then m is equal to the product of the quotient of m divided by d and d.*)\nLemma divzK d m : (d %| m)%Z -> (m %/ d)%Z * d = m.\n\n(*This lemma states that for a positive integer divisor that divides a dividend, the statement that the quotient is less than or equal to a third integer is equivalent to the statement that the dividend is less than or equal to the product of the third integer and the divisor.*)\nLemma lez_divLR d m n : 0 < d -> (d %| m)%Z -> ((m %/ d)%Z <= n) = (m <= n * d).\n\n(*This lemma states that for a positive integer divisor that divides a dividend, the statement that a third integer is strictly less than the quotient is equivalent to the statement that the product of the third integer and the divisor is strictly less than the dividend.*)\nLemma ltz_divRL d m n : 0 < d -> (d %| m)%Z -> (n < m %/ d)%Z = (n * d < m).\n\n(*This lemma states that for a non-zero integer divisor that divides a dividend, the statement that a third integer is equal to the quotient is equivalent to the statement that the product of the third integer and the divisor is equal to the dividend.*)\nLemma eqz_div d m n : d != 0 -> (d %| m)%Z -> (n == m %/ d)%Z = (n * d == m).\n\n(*This lemma states that for a non-zero integer divisor that divides a dividend, the statement that the dividend is equal to the product of a third integer and the divisor is equivalent to the statement that the quotient is equal to the third integer.*)\nLemma eqz_mul d m n : d != 0 -> (d %| m)%Z -> (m == n * d) = (m %/ d == n)%Z.\n\n(*This lemma states that if a first integer divides a second, then the product of the quotient of the second integer by the first and a third integer is equal to the quotient of the product of the second and third integers by the first integer.*)\nLemma divz_mulAC d m n : (d %| m)%Z -> (m %/ d)%Z * n = (m * n %/ d)%Z.\n\n(*This lemma states that if a first integer divides a third, then the product of a second integer and the quotient of the third integer by the first is equal to the quotient of the product of the second and third integers by the first integer.*)\nLemma mulz_divA d m n : (d %| n)%Z -> m * (n %/ d)%Z = (m * n %/ d)%Z.\n\n(*This lemma states that if an integer d divides both integers m and n, then the product of m and the quotient of n by d is equal to the product of n and the quotient of m by d.*)\nLemma mulz_divCA d m n :\n (d %| m)%Z -> (d %| n)%Z -> m * (n %/ d)%Z = n * (m %/ d)%Z.\n\n(*This lemma states that for three integers, if the third integer divides the second, and the second divides the product of the first and the third, then the quotient of the first integer by the quotient of the second by the third is equal to the quotient of the product of the first and third integers by the second integer.*)\nLemma divzA m n p : (p %| n -> n %| m * p -> m %/ (n %/ p)%Z = m * p %/ n)%Z.\n\n(*This lemma states that for three integers, if the product of the second and third integers divides the first integer, then the quotient of the first integer by this product is equal to the quotient of dividing the first integer by the second, and then dividing that result by the third.*)\nLemma divzMA m n p : (n * p %| m -> m %/ (n * p) = (m %/ n)%Z %/ p)%Z.\n\n(*This lemma states that if the product of two integers, `n` and `p`, divides another integer `m`, then the result of successively dividing `m` by `n` and `p` is the same regardless of the order of division.*)\nLemma divzAC m n p : (n * p %| m -> (m %/ n)%Z %/ p = (m %/ p)%Z %/ n)%Z.\n\n(*This lemma states that for a non-zero integer `p`, if an integer `d` divides an integer `m`, then the integer division of the product of `p` and `m` by the product of `p` and `d` is equal to the integer division of `m` by `d`.*)\nLemma divzMl p m d : p != 0 -> (d %| m -> p * m %/ (p * d) = m %/ d)%Z.\n\n(*This lemma states that for a non-zero integer `p`, if an integer `d` divides an integer `m`, then the integer division of the product of `m` and `p` by the product of `d` and `p` is equal to the integer division of `m` by `d`.*)\nLemma divzMr p m d : p != 0 -> (d %| m -> m * p %/ (d * p) = m %/ d)%Z.\n\n(*This lemma states that for a non-zero integer, multiplying both operands of an integer divisibility relation by that integer on the left does not change the truth value of the relation.*)\nLemma dvdz_mul2l p d m : p != 0 -> (p * d %| p * m)%Z = (d %| m)%Z.\n\nArguments dvdz_mul2l [p d m].\n\n(*This lemma states that for a non-zero integer, multiplying both operands of an integer divisibility relation by that integer on the right does not change the truth value of the relation.*)\nLemma dvdz_mul2r p d m : p != 0 -> (d * p %| m * p)%Z = (d %| m)%Z.\n\nArguments dvdz_mul2r [p d m].\n\n(*This lemma states that if a natural number `m` is less than or equal to a natural number `n`, then any integer raised to the power of `m` divides the same integer raised to the power of `n`.*)\nLemma dvdz_exp2l p m n : (m <= n)%N -> (p ^+ m %| p ^+ n)%Z.\n\n(*This lemma states that for an integer whose absolute value is greater than one, the integer raised to the power of a natural number `m` divides the same integer raised to the power of a natural number `n` if and only if `m` is less than or equal to `n`.*)\nLemma dvdz_Pexp2l p m n : `|p| > 1 -> (p ^+ m %| p ^+ n)%Z = (m <= n)%N.\n\n(*This lemma states that if an integer `m` divides an integer `n`, then `m` raised to any natural number power `k` divides `n` raised to the same power `k`.*)\nLemma dvdz_exp2r m n k : (m %| n -> m ^+ k %| n ^+ k)%Z.\n\n(*This fact states that the property of an integer being divisible by a given integer `d` is closed under negation, meaning an integer is divisible by `d` if and only if its opposite is also divisible by `d`.*)\nFact dvdz_zmod_closed d : zmod_closed (dvdz d).\n\n(*This lemma states that for any positive natural number `k`, if an integer `d` divides an integer `m`, then `d` also divides `m` raised to the power `k`.*)\nLemma dvdz_exp k d m : (0 < k)%N -> (d %| m -> d %| m ^+ k)%Z.\n\n(*This lemma states that two integers `m` and `n` are congruent modulo an integer `d` if and only if `d` divides the difference between `m` and `n`.*)\nLemma eqz_mod_dvd d m n : (m == n %[mod d])%Z = (d %| m - n)%Z.\n\n(*This lemma states that if an integer `d` divides an integer `m`, then the integer division of the sum of `m` and another integer `n` by `d` is equal to the sum of the integer division of `m` by `d` and the integer division of `n` by `d`.*)\nLemma divzDl m n d :\n (d %| m)%Z -> ((m + n) %/ d)%Z = (m %/ d)%Z + (n %/ d)%Z.\n\n(*This lemma states that if an integer `d` divides an integer `n`, then the integer division of the sum of an integer `m` and `n` by `d` is equal to the sum of the integer division of `m` by `d` and the integer division of `n` by `d`.*)\nLemma divzDr m n d :\n (d %| n)%Z -> ((m + n) %/ d)%Z = (m %/ d)%Z + (n %/ d)%Z.\n\n(*This lemma states that for a non-trivial ring and an integer `p` that is a characteristic of the ring, `p` divides another integer `n` if and only if the canonical image of `n` in the ring is the zero element.*)\nLemma dvdz_pcharf (R : nzRingType) p : p \\in [pchar R] ->\n forall n : int, (p %| n)%Z = (n%:~R == 0 :> R).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use dvdz_pcharf instead.\")]\nNotation dvdz_charf chRp := (dvdz_pcharf chRp).\n\n(*This lemma states that the greatest common divisor of an integer with itself is equal to its absolute value.*)\nLemma gcdzz m : gcdz m m = `|m|%:Z. \n(*This lemma states that the integer greatest common divisor operation is commutative.*)\nLemma gcdzC : commutative gcdz. \n(*This lemma states that the greatest common divisor of zero and any integer is the absolute value of that integer.*)\nLemma gcd0z m : gcdz 0 m = `|m|%:Z. \n(*This lemma states that the greatest common divisor of any integer and zero is the absolute value of that integer.*)\nLemma gcdz0 m : gcdz m 0 = `|m|%:Z. \n(*This lemma states that the greatest common divisor of the integer one and any other integer is always one.*)\nLemma gcd1z : left_zero 1 gcdz. \n(*This lemma states that the greatest common divisor of any integer and the integer one is always one.*)\nLemma gcdz1 : right_zero 1 gcdz. \n(*This lemma states that the greatest common divisor of two integers divides the second integer.*)\nLemma dvdz_gcdr m n : (gcdz m n %| n)%Z. \n(*This lemma states that the greatest common divisor of two integers divides the first integer.*)\nLemma dvdz_gcdl m n : (gcdz m n %| m)%Z. \n(*This lemma states that the greatest common divisor of two integers is zero if and only if both integers are zero.*)\nLemma gcdz_eq0 m n : (gcdz m n == 0) = (m == 0) && (n == 0).\n\n(*This lemma states that the greatest common divisor of the opposite of an integer and another integer is the same as the greatest common divisor of the two original integers.*)\nLemma gcdNz m n : gcdz (- m) n = gcdz m n. \n(*This lemma states that the greatest common divisor of an integer and the opposite of another integer is the same as the greatest common divisor of the two original integers.*)\nLemma gcdzN m n : gcdz m (- n) = gcdz m n. \n\n(*This lemma, related to the Euclidean algorithm, states that the greatest common divisor of two integers `m` and `n` is equal to the greatest common divisor of `m` and the remainder of `n` divided by `m`.*)\nLemma gcdz_modr m n : gcdz m (n %% m)%Z = gcdz m n.\n\n(*This lemma, related to the Euclidean algorithm, states that the greatest common divisor of two integers `m` and `n` is equal to the greatest common divisor of the remainder of `m` divided by `n` and the integer `n`.*)\nLemma gcdz_modl m n : gcdz (m %% n)%Z n = gcdz m n.\n\n(*This lemma states that the greatest common divisor of an integer `m` and another integer `n` is unchanged if any multiple of `m` is added to `n`.*)\nLemma gcdzMDl q m n : gcdz m (q * m + n) = gcdz m n.\n\n(*This lemma states that the greatest common divisor of an integer `m` and the sum of `m` and another integer `n` is equal to the greatest common divisor of `m` and `n`.*)\nLemma gcdzDl m n : gcdz m (m + n) = gcdz m n.\n\n(*This lemma states that the greatest common divisor of an integer `m` and the sum of another integer `n` and `m` is equal to the greatest common divisor of `m` and `n`.*)\nLemma gcdzDr m n : gcdz m (n + m) = gcdz m n.\n\n(*This lemma states that the greatest common divisor of a first integer and the product of a second integer with the first integer is equal to the absolute value of the first integer.*)\nLemma gcdzMl n m : gcdz n (m * n) = `|n|%:Z.\n\n(*This lemma states that the greatest common divisor of a first integer and the product of the first integer with a second integer is equal to the absolute value of the first integer.*)\nLemma gcdzMr n m : gcdz n (n * m) = `|n|%:Z.\n\n(*This lemma states that the greatest common divisor of two integers is equal to the absolute value of the first integer if and only if the first integer divides the second integer.*)\nLemma gcdz_idPl {m n} : reflect (gcdz m n = `|m|%:Z) (m %| n)%Z.\n\n(*This lemma states that the greatest common divisor of two integers is equal to the absolute value of the second integer if and only if the second integer divides the first integer.*)\nLemma gcdz_idPr {m n} : reflect (gcdz m n = `|n|%:Z) (n %| m)%Z.\n\n(*This lemma states that for a non-negative integer base, exponentiating the base by the minimum of two integers is equivalent to taking the greatest common divisor of the base raised to each of the two integers respectively.*)\nLemma expz_min e m n : e >= 0 -> e ^+ minn m n = gcdz (e ^+ m) (e ^+ n).\n\n(*This lemma states that a first integer divides the greatest common divisor of a second and a third integer if and only if the first integer divides both the second and the third integers.*)\nLemma dvdz_gcd p m n : (p %| gcdz m n)%Z = (p %| m)%Z && (p %| n)%Z.\n\n(*This lemma states that the greatest common divisor operation on integers is right-commutative, meaning that the greatest common divisor of a first integer with the greatest common divisor of a second and third integer is equal to the greatest common divisor of the second integer with the greatest common divisor of the first and third integer.*)\nLemma gcdzAC : right_commutative gcdz.\n\n(*This lemma states that the greatest common divisor operation on integers is associative.*)\nLemma gcdzA : associative gcdz.\n\n(*This lemma states that the greatest common divisor operation on integers is left-commutative, meaning that the greatest common divisor of the greatest common divisor of a first and second integer with a third integer is equal to the greatest common divisor of the greatest common divisor of the third and second integer with the first integer.*)\nLemma gcdzCA : left_commutative gcdz.\n\n(*This lemma states that the greatest common divisor operation on integers interchanges with itself, meaning the greatest common divisor of two greatest common divisors can be computed by regrouping the arguments.*)\nLemma gcdzACA : interchange gcdz gcdz.\n\n(*This lemma states that multiplying the greatest common divisor of two integers by the absolute value of a third integer is equivalent to taking the greatest common divisor of the products of the third integer with each of the original two integers.*)\nLemma mulz_gcdr m n p : `|m|%:Z * gcdz n p = gcdz (m * n) (m * p).\n\n(*This lemma states that multiplying the greatest common divisor of two integers by the absolute value of a third integer is equivalent to taking the greatest common divisor of the products of each of the original two integers with the third integer.*)\nLemma mulz_gcdl m n p : gcdz m n * `|p|%:Z = gcdz (m * p) (n * p).\n\n(*This lemma states that the product of a first integer with the quotient of a second integer and their greatest common divisor is equal to the product of the second integer with the quotient of the first integer and their greatest common divisor.*)\nLemma mulz_divCA_gcd n m : n * (m %/ gcdz n m)%Z = m * (n %/ gcdz n m)%Z.\n\n(*This lemma states that for any two integers, the second integer divides their least common multiple.*)\nLemma dvdz_lcmr m n : (n %| lcmz m n)%Z.\n\n(*This lemma states that for any two integers, the first integer divides their least common multiple.*)\nLemma dvdz_lcml m n : (m %| lcmz m n)%Z.\n\n(*This lemma states that the least common multiple of a first and second integer divides a third integer if and only if both the first and second integers individually divide the third integer.*)\nLemma dvdz_lcm d1 d2 m : ((lcmn d1 d2 %| m) = (d1 %| m) && (d2 %| m))%Z.\n\n(*This lemma states that the least common multiple operation on integers is commutative.*)\nLemma lcmzC : commutative lcmz.\n\n(*This lemma states that the least common multiple of zero and any integer is zero.*)\nLemma lcm0z : left_zero 0 lcmz.\n\n(*This lemma states that the least common multiple of any integer and zero is zero.*)\nLemma lcmz0 : right_zero 0 lcmz.\n\n(*This lemma states that the least common multiple of any two integers is greater than or equal to zero.*)\nLemma lcmz_ge0 m n : 0 <= lcmz m n.\n\n(*This lemma states that the least common multiple of two integers is not equal to zero if and only if both integers are not equal to zero.*)\nLemma lcmz_neq0 m n : (lcmz m n != 0) = (m != 0) && (n != 0).\n\n(*This lemma states that two integers are coprime if and only if their absolute values, interpreted as natural numbers, are coprime.*)\nLemma coprimezE m n : coprimez m n = coprime `|m| `|n|. \n\n(*This lemma states that the coprimality relation on integers is symmetric.*)\nLemma coprimez_sym : symmetric coprimez.\n\n(*This lemma states that two integers are coprime if and only if the additive inverse of the first integer is coprime with the second integer.*)\nLemma coprimeNz m n : coprimez (- m) n = coprimez m n.\n\n(*This lemma states that two integers are coprime if and only if the first integer is coprime with the additive inverse of the second integer.*)\nLemma coprimezN m n : coprimez m (- n) = coprimez m n.\n\n(*This variant type defines the specification for the result of the extended Euclidean algorithm on two integers. A pair of integers satisfies this specification if their linear combination with the original two integers equals the greatest common divisor of the original integers, and furthermore, the pair of integers itself is coprime.*)\nVariant egcdz_spec m n : int * int -> Type :=\n EgcdzSpec u v of u * m + v * n = gcdz m n & coprimez u v\n : egcdz_spec m n (u, v).\n\n(*This lemma states that the output of the extended Euclidean algorithm for two integers satisfies the corresponding specification, providing the Bezout coefficients and a proof of their correctness and coprimality.*)\nLemma egcdzP m n : egcdz_spec m n (egcdz m n).\n\n(*This lemma, known as Bezout's identity for integers, states that for any two integers, there exist two other integers, called Bezout coefficients, such that their linear combination with the original two integers equals the greatest common divisor of the original two integers.*)\nLemma Bezoutz m n : {u : int & {v : int | u * m + v * n = gcdz m n}}.\n\n(*This lemma states that two integers are coprime if and only if there exists a pair of integers such that their linear combination with the original two integers equals one.*)\nLemma coprimezP m n :\n reflect (exists uv, uv.1 * m + uv.2 * n = 1) (coprimez m n).\n\n(*This lemma, known as Gauss's lemma for integer divisibility, states that if a first integer divides the product of a second and a third integer, and the first integer is coprime to the second, then the first integer must divide the third.*)\nLemma Gauss_dvdz m n p :\n coprimez m n -> (m * n %| p)%Z = (m %| p)%Z && (n %| p)%Z.\n\n(*This lemma states that if a first integer is coprime to a second integer, then the first integer divides the product of the second integer and a third integer if and only if the first integer divides the third integer.*)\nLemma Gauss_dvdzr m n p : coprimez m n -> (m %| n * p)%Z = (m %| p)%Z.\n\n(*This lemma states that for three integers, if the first is coprime to the third, then the first integer divides the product of the second and third integers if and only if the first integer divides the second integer.*)\nLemma Gauss_dvdzl m n p : coprimez m p -> (m %| n * p)%Z = (m %| n)%Z.\n\n(*This lemma states that for three integers, if the first is coprime to the second, then the greatest common divisor of the first integer and the product of the second and third integers is equal to the greatest common divisor of the first and third integers.*)\nLemma Gauss_gcdzr p m n : coprimez p m -> gcdz p (m * n) = gcdz p n.\n\n(*This lemma states that for three integers, if the first is coprime to the third, then the greatest common divisor of the first integer and the product of the second and third integers is equal to the greatest common divisor of the first and second integers.*)\nLemma Gauss_gcdzl p m n : coprimez p n -> gcdz p (m * n) = gcdz p m.\n\n(*This lemma states that an integer is coprime to the product of two other integers if and only if it is coprime to each of those two integers individually.*)\nLemma coprimezMr p m n : coprimez p (m * n) = coprimez p m && coprimez p n.\n\n(*This lemma states that the product of two integers is coprime to a third integer if and only if each of the first two integers is individually coprime to the third.*)\nLemma coprimezMl p m n : coprimez (m * n) p = coprimez m p && coprimez n p.\n\n(*This lemma states that for a positive natural number exponent, an integer raised to that exponent is coprime to another integer if and only if the base integer is coprime to the other integer.*)\nLemma coprimez_pexpl k m n : (0 < k)%N -> coprimez (m ^+ k) n = coprimez m n.\n\n(*This lemma states that for a positive natural number exponent, a first integer is coprime to a second integer raised to that exponent if and only if the first integer is coprime to the base of the power.*)\nLemma coprimez_pexpr k m n : (0 < k)%N -> coprimez m (n ^+ k) = coprimez m n.\n\n(*This lemma states that if two integers are coprime, then any natural number power of the first integer is also coprime to the second integer.*)\nLemma coprimezXl k m n : coprimez m n -> coprimez (m ^+ k) n.\n\n(*This lemma states that if two integers are coprime, then the first integer is also coprime to any natural number power of the second integer.*)\nLemma coprimezXr k m n : coprimez m n -> coprimez m (n ^+ k).\n\n(*This lemma states that for three integers, if the absolute value of the first divides the absolute value of the second, and the second is coprime to the third, then the first is also coprime to the third.*)\nLemma coprimez_dvdl m n p : (m %| n)%N -> coprimez n p -> coprimez m p.\n\n(*This lemma states that for three integers, if the absolute value of the first divides the absolute value of the second, and the third is coprime to the second, then the third is also coprime to the first.*)\nLemma coprimez_dvdr m n p : (m %| n)%N -> coprimez p n -> coprimez p m.\n\n(*This lemma asserts that for two integers and a positive natural number exponent, the first integer raised to the exponent divides the second integer raised to the same exponent if and only if the first integer divides the second integer.*)\nLemma dvdz_pexp2r m n k : (k > 0)%N -> (m ^+ k %| n ^+ k)%Z = (m %| n)%Z.\n\nSection Chinese.\n\nVariables m1 m2 : int.\nHypothesis co_m12 : coprimez m1 m2.\n\n(*This lemma states the core principle of the Chinese Remainder Theorem for two coprime integer moduli: two integers are congruent modulo the product of the moduli if and only if they are congruent modulo each of the individual moduli.*)\nLemma zchinese_remainder x y :\n (x == y %[mod m1 * m2])%Z = (x == y %[mod m1])%Z && (x == y %[mod m2])%Z.\n\n(*This definition provides a constructive formula for an integer that simultaneously satisfies two congruence relations with respect to two coprime integer moduli. The solution is constructed using the remainders from each congruence and the B\u00e9zout coefficients of the moduli derived from the extended Euclidean algorithm.*)\nDefinition zchinese r1 r2 :=\n r1 * m2 * (egcdz m1 m2).2 + r2 * m1 * (egcdz m1 m2).1.\n\n(*This lemma proves that the integer constructed by the zchinese function for two given remainders is congruent to the first remainder modulo the first of the two coprime moduli.*)\nLemma zchinese_modl r1 r2 : (zchinese r1 r2 = r1 %[mod m1])%Z.\n\n(*This lemma proves that the integer constructed by the zchinese function for two given remainders is congruent to the second remainder modulo the second of the two coprime moduli.*)\nLemma zchinese_modr r1 r2 : (zchinese r1 r2 = r2 %[mod m2])%Z.\n\n(*This lemma demonstrates that any integer is congruent, modulo the product of two coprime moduli, to the integer constructed by the zchinese function using the original integer's remainders with respect to each modulus.*)\nLemma zchinese_mod x : (x = zchinese (x %% m1)%Z (x %% m2)%Z %[mod m1 * m2])%Z.\n\nEnd Chinese.\n\nSection ZpolyScale.\n\n(*This definition specifies the content of a non-zero polynomial with integer coefficients as the product of the sign of its leading coefficient and the greatest common divisor of the absolute values of all its coefficients. The content of the zero polynomial is zero.*)\nDefinition zcontents (p : {poly int}) : int :=\n sgz (lead_coef p) * \\big[gcdn/0]_(i < size p) `|(p`_i)%R|%N.\n\n(*This lemma states that the sign of the content of a polynomial with integer coefficients is equal to the sign of its leading coefficient.*)\nLemma sgz_contents p : sgz (zcontents p) = sgz (lead_coef p).\n\n(*This lemma asserts that the content of a polynomial with integer coefficients is zero if and only if the polynomial itself is the zero polynomial.*)\nLemma zcontents_eq0 p : (zcontents p == 0) = (p == 0).\n\n(*This lemma states that the content of the zero polynomial is the integer zero.*)\nLemma zcontents0 : zcontents 0 = 0.\n\n(*This lemma states that the content of a polynomial scaled by an integer is equal to the product of that integer and the content of the original polynomial.*)\nLemma zcontentsZ a p : zcontents (a *: p) = a * zcontents p.\n\n(*This lemma states that the content of a monic polynomial with integer coefficients is equal to one.*)\nLemma zcontents_monic p : p \\is monic -> zcontents p = 1.\n\n(*This lemma establishes that an integer divides the content of a polynomial if and only if every coefficient of that polynomial is divisible by that integer.*)\nLemma dvdz_contents a p : (a %| zcontents p)%Z = (p \\is a polyOver (dvdz a)).\n\n(*This lemma states that if all coefficients of a polynomial are divisible by a given integer, then multiplying this polynomial by that integer, after having divided each of its coefficients by the same integer, results in the original polynomial.*)\nLemma map_poly_divzK {a} p :\n p \\is a polyOver (dvdz a) -> a *: map_poly (divz^~ a) p = p.\n\n(*This lemma provides a reflection between two equivalent properties of a polynomial: the first is that all of its coefficients are divisible by a given integer, and the second is that the polynomial can be expressed as the product of that integer and some other polynomial.*)\nLemma polyOver_dvdzP a p :\n reflect (exists q, p = a *: q) (p \\is a polyOver (dvdz a)).\n\n(*This definition specifies the primitive part of a polynomial with integer coefficients as the polynomial obtained by dividing each of its coefficients by its content.*)\nDefinition zprimitive p := map_poly (divz^~ (zcontents p)) p.\n\n(*This lemma states that any polynomial with integer coefficients can be reconstructed as the product of its content and its primitive part.*)\nLemma zpolyEprim p : p = zcontents p *: zprimitive p.\n\n(*This lemma states that the primitive part of the zero polynomial is the zero polynomial itself.*)\nLemma zprimitive0 : zprimitive 0 = 0.\n\n(*This lemma states that the primitive part of a polynomial is the zero polynomial if and only if the original polynomial is the zero polynomial.*)\nLemma zprimitive_eq0 p : (zprimitive p == 0) = (p == 0).\n\n(*This lemma states that the size of the primitive part of a polynomial is equal to the size of the original polynomial.*)\nLemma size_zprimitive p : size (zprimitive p) = size p.\n\n(*This lemma states that the sign of the leading coefficient of the primitive part of a polynomial is one if the polynomial is non-zero, and zero otherwise.*)\nLemma sgz_lead_primitive p : sgz (lead_coef (zprimitive p)) = (p != 0).\n\n(*This lemma states that the content of the primitive part of a polynomial is one if the original polynomial is non-zero, and zero otherwise.*)\nLemma zcontents_primitive p : zcontents (zprimitive p) = (p != 0).\n\n(*This lemma states that applying the primitive part operation twice to a polynomial is equivalent to applying it once.*)\nLemma zprimitive_id p : zprimitive (zprimitive p) = zprimitive p.\n\n(*This lemma states that the primitive part of a monic polynomial is the polynomial itself.*)\nLemma zprimitive_monic p : p \\in monic -> zprimitive p = p.\n\n(*This lemma states that for any non-zero integer, the primitive part of a polynomial scaled by that integer is equal to the primitive part of the original polynomial.*)\nLemma zprimitiveZ a p : a != 0 -> zprimitive (a *: p) = zprimitive p.\n\n(*This lemma states that if a non-zero polynomial can be written as the product of an integer and a second polynomial, then this second polynomial is itself a multiple of the primitive part of the original polynomial by some integer factor. Additionally, the sign of this integer factor is the same as the sign of the leading coefficient of the second polynomial.*)\nLemma zprimitive_min p a q :\n p != 0 -> p = a *: q ->\n {b | sgz b = sgz (lead_coef q) & q = b *: zprimitive p}.\n\n(*This lemma states that if the primitive part of a non-zero polynomial is expressed as an integer multiple of another polynomial, then the integer multiplier must be equal to the sign of the leading coefficient of that other polynomial.*)\nLemma zprimitive_irr p a q :\n p != 0 -> zprimitive p = a *: q -> a = sgz (lead_coef q).\n\n(*This lemma states that the content of the product of two polynomials is equal to the product of their respective contents.*)\nLemma zcontentsM p q : zcontents (p * q) = zcontents p * zcontents q.\n\n(*This lemma states that the primitive part of the product of two polynomials is equal to the product of their respective primitive parts.*)\nLemma zprimitiveM p q : zprimitive (p * q) = zprimitive p * zprimitive q.\n\n(*This lemma states that if a polynomial with integer coefficients divides another, then the dividend polynomial can be expressed as the product of the primitive part of the divisor polynomial and some third polynomial.*)\nLemma dvdpP_int p q : p %| q -> {r | q = zprimitive p * r}.\n\nEnd ZpolyScale.\n\n(*This theorem asserts the existence of the Smith Normal Form for any matrix over the integers. It states that for any given matrix, there exist two unimodular matrices and a finite sequence of integers where each element divides the next, such that the original matrix can be expressed as the product of the first unimodular matrix, a diagonal matrix formed from the sequence of integers, and the second unimodular matrix.*)\nLemma int_Smith_normal_form m n (M : 'M[int]_(m, n)) :\n {L : 'M[int]_m & L \\in unitmx &\n {R : 'M[int]_n & R \\in unitmx &\n {d : seq int | sorted dvdz d &\n M = L *m (\\matrix_(i, j) (d`_i *+ (i == j :> nat))) *m R}}}.", - "algebra.interval": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import div fintype bigop order ssralg finset fingroup.\nFrom mathcomp Require Import ssrnum.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nReserved Notation \"'-oo'\".\nReserved Notation \"'+oo'\".\nReserved Notation \"`[ a , b ]\" (a, b at level 9, format \"`[ a , b ]\").\nReserved Notation \"`] a , b ]\" (a, b at level 9, format \"`] a , b ]\").\nReserved Notation \"`[ a , b [\" (format \"`[ a , b [\").\nReserved Notation \"`] a , b [\" (format \"`] a , b [\").\nReserved Notation \"`] '-oo' , b ]\" (b at level 9, format \"`] '-oo' , b ]\").\nReserved Notation \"`] '-oo' , b [\" (format \"`] '-oo' , b [\").\nReserved Notation \"`[ a , '+oo' [\" (format \"`[ a , '+oo' [\").\nReserved Notation \"`] a , '+oo' [\" (format \"`] a , '+oo' [\").\nReserved Notation \"`] -oo , '+oo' [\" (format \"`] -oo , '+oo' [\").\n\nLocal Open Scope order_scope.\nImport Order.TTheory.\n\n(*Represents an endpoint for an interval. An endpoint can be a finite value from a given type, or it can represent positive or negative infinity. This type also captures whether the bound is inclusive or exclusive.*)\nVariant itv_bound (T : Type) : Type := BSide of bool & T | BInfty of bool.\n(*A constructor that creates a finite boundary for an interval from a given value. This constructor is used when the textual notation for the boundary is a left square bracket, which signifies an inclusive lower bound or an exclusive upper bound.*)\nNotation BLeft := (BSide true).\n(*A constructor that creates a finite boundary for an interval from a given value. This constructor is used when the textual notation for the boundary is a right square bracket, which signifies an exclusive lower bound or an inclusive upper bound.*)\nNotation BRight := (BSide false).\n(*A notation for an interval boundary representing negative infinity. It is used as the exclusive lower bound for intervals that are unbounded on the left.*)\nNotation \"'-oo'\" := (BInfty _ true) : order_scope.\n(*A notation for an interval boundary representing positive infinity. It is used as the exclusive upper bound for intervals that are unbounded on the right.*)\nNotation \"'+oo'\" := (BInfty _ false) : order_scope.\n(*Represents an interval over a given base type. An interval is defined by a pair of boundaries, each of which can be a finite value or an infinite value, and can be inclusive or exclusive.*)\nVariant interval (T : Type) := Interval of itv_bound T & itv_bound T.\n\nCoercion pair_of_interval T (I : interval T) : itv_bound T * itv_bound T :=\n let: Interval b1 b2 := I in (b1, b2).\n\n(*This notation defines a closed interval between two elements, which serve as the lower and upper bounds. The interval includes all elements that are greater than or equal to the lower bound and less than or equal to the upper bound.*)\nNotation \"`[ a , b ]\" := (Interval (BLeft a) (BRight b)) : order_scope.\n(*This notation defines a half-open interval between two elements, which serve as the lower and upper bounds. The interval includes all elements that are strictly greater than the lower bound and less than or equal to the upper bound.*)\nNotation \"`] a , b ]\" := (Interval (BRight a) (BRight b)) : order_scope.\n(*This notation defines a half-open interval between two elements, which serve as the lower and upper bounds. The interval includes all elements that are greater than or equal to the lower bound and strictly less than the upper bound.*)\nNotation \"`[ a , b [\" := (Interval (BLeft a) (BLeft b)) : order_scope.\n(*This notation defines an open interval between two elements, which serve as the lower and upper bounds. The interval includes all elements that are strictly greater than the lower bound and strictly less than the upper bound.*)\nNotation \"`] a , b [\" := (Interval (BRight a) (BLeft b)) : order_scope.\n(*This notation defines an interval that is unbounded from below and closed at its upper bound. The interval includes all elements that are less than or equal to the given element, which serves as the upper bound.*)\nNotation \"`] '-oo' , b ]\" := (Interval -oo (BRight b)) : order_scope.\n(*This notation defines an interval that is unbounded from below and open at its upper bound. The interval includes all elements that are strictly less than the given element, which serves as the upper bound.*)\nNotation \"`] '-oo' , b [\" := (Interval -oo (BLeft b)) : order_scope.\n(*This notation defines an interval that is closed at its lower bound and unbounded from above. The interval includes all elements that are greater than or equal to the given element, which serves as the lower bound.*)\nNotation \"`[ a , '+oo' [\" := (Interval (BLeft a) +oo) : order_scope.\n(*This notation defines an interval that is open at its lower bound and unbounded from above. The interval includes all elements that are strictly greater than the given element, which serves as the lower bound.*)\nNotation \"`] a , '+oo' [\" := (Interval (BRight a) +oo) : order_scope.\n(*This notation defines an interval that is unbounded from both below and above, effectively representing all elements of the underlying type.*)\nNotation \"`] -oo , '+oo' [\" := (Interval -oo +oo) : order_scope.\n\n(*A notation for a closed interval between two elements, including both endpoints.*)\nNotation \"`[ a , b ]\" := (Interval (BLeft a) (BRight b)) : ring_scope.\n(*A notation for a left-open, right-closed interval between two elements, excluding the lower endpoint and including the upper endpoint.*)\nNotation \"`] a , b ]\" := (Interval (BRight a) (BRight b)) : ring_scope.\n(*A notation for a left-closed, right-open interval between two elements, including the lower endpoint and excluding the upper endpoint.*)\nNotation \"`[ a , b [\" := (Interval (BLeft a) (BLeft b)) : ring_scope.\n(*A notation for an open interval between two elements, excluding both endpoints.*)\nNotation \"`] a , b [\" := (Interval (BRight a) (BLeft b)) : ring_scope.\n(*A notation for an interval from negative infinity to an element, including the endpoint.*)\nNotation \"`] '-oo' , b ]\" := (Interval -oo (BRight b)) : ring_scope.\n(*A notation for an interval from negative infinity to an element, excluding the endpoint.*)\nNotation \"`] '-oo' , b [\" := (Interval -oo (BLeft b)) : ring_scope.\n(*A notation for an interval from an element to positive infinity, including the starting point.*)\nNotation \"`[ a , '+oo' [\" := (Interval (BLeft a) +oo) : ring_scope.\n(*A notation for an interval from an element to positive infinity, excluding the starting point.*)\nNotation \"`] a , '+oo' [\" := (Interval (BRight a) +oo) : ring_scope.\n(*A notation for the interval spanning from negative infinity to positive infinity, representing all elements of the type.*)\nNotation \"`] -oo , '+oo' [\" := (Interval -oo +oo) : ring_scope.\n\n(*This declaration introduces an opaque order display for interval bounds, which allows for specialized notations and prevents ambiguity when reasoning about the order of interval endpoints.*)\nFact itv_bound_display (disp : Order.disp_t) : Order.disp_t. \n(*This declaration introduces an opaque order display for intervals, which enables specialized notations and disambiguates reasoning about orders on intervals themselves.*)\nFact interval_display (disp : Order.disp_t) : Order.disp_t. \n\nModule IntervalCan.\nSection IntervalCan.\n\nVariable T : Type.\n\n(*This lemma establishes a canonical isomorphism for an interval bound type, showing that it can be losslessly converted to and from a pair consisting of a boolean and an optional element, where the boolean indicates the side and the optional element holds the value.*)\nLemma itv_bound_can :\n cancel (fun b : itv_bound T =>\n match b with BSide b x => (b, Some x) | BInfty b => (b, None) end)\n (fun b =>\n match b with (b, Some x) => BSide b x | (b, None) => BInfty _ b end).\n\n(*This lemma establishes a canonical isomorphism for an interval type, showing that it can be losslessly converted to and from a pair of interval bounds representing its lower and upper endpoints.*)\nLemma interval_can :\n @cancel _ (interval T)\n (fun '(Interval b1 b2) => (b1, b2)) (fun '(b1, b2) => Interval b1 b2).\n\nEnd IntervalCan.\n\n#[export, hnf]\nHB.instance Definition _ (T : eqType) := Equality.copy (itv_bound T)\n (can_type (@itv_bound_can T)).\n#[export, hnf]\nHB.instance Definition _ (T : eqType) := Equality.copy (interval T)\n (can_type (@interval_can T)).\n#[export, hnf]\nHB.instance Definition _ (T : choiceType) := Choice.copy (itv_bound T)\n (can_type (@itv_bound_can T)).\n#[export, hnf]\nHB.instance Definition _ (T : choiceType) := Choice.copy (interval T)\n (can_type (@interval_can T)).\n#[export, hnf]\nHB.instance Definition _ (T : countType) := Countable.copy (itv_bound T)\n (can_type (@itv_bound_can T)).\n#[export, hnf]\nHB.instance Definition _ (T : countType) := Countable.copy (interval T)\n (can_type (@interval_can T)).\n#[export, hnf]\nHB.instance Definition _ (T : finType) := Finite.copy (itv_bound T)\n (can_type (@itv_bound_can T)).\n#[export, hnf]\n(*This definition specifies the 'less than or equal to' relation for two interval bounds. An infinite negative bound is always less than or equal to any other bound, and any bound is less than or equal to an infinite positive bound. For finite bounds, the comparison is based first on their values and second on whether they are inclusive or exclusive, to correctly order endpoints.*)\nDefinition le_bound b1 b2 :=\n match b1, b2 with\n | -oo, _ | _, +oo => true\n | BSide b1 x1, BSide b2 x2 => x1 < x2 ?<= if b2 ==> b1\n | _, _ => false\n end.\n\n(*This definition specifies the 'less than' relation for two interval bounds. An infinite negative bound is strictly less than any other bound except itself, and any finite bound is strictly less than an infinite positive bound. For finite bounds, the relation is determined primarily by their values, with a tie-breaking rule based on their inclusive or exclusive nature.*)\nDefinition lt_bound b1 b2 :=\n match b1, b2 with\n | -oo, +oo | -oo, BSide _ _ | BSide _ _, +oo => true\n | BSide b1 x1, BSide b2 x2 => x1 < x2 ?<= if b1 && ~~ b2\n | _, _ => false\n end.\n\n(*This lemma states that one interval bound is strictly less than another if and only if they are not equal and the first is less than or equal to the second.*)\nLemma lt_bound_def b1 b2 : lt_bound b1 b2 = (b2 != b1) && le_bound b1 b2.\n\n(*This lemma states that the 'less than or equal to' relation on interval bounds is reflexive, meaning any bound is less than or equal to itself.*)\nLemma le_bound_refl : reflexive le_bound.\n\n(*This lemma states that the 'less than or equal to' relation on interval bounds is antisymmetric, meaning if two bounds are less than or equal to each other, then they must be equal.*)\nLemma le_bound_anti : antisymmetric le_bound.\n\n(*This lemma states that the 'less than or equal to' relation on interval bounds is transitive, meaning if a first bound is less than or equal to a second, and the second is less than or equal to a third, then the first is less than or equal to the third.*)\nLemma le_bound_trans : transitive le_bound.\n\nHB.instance Definition _ :=\n Order.isPOrder.Build (itv_bound_display disp) (itv_bound T)\n lt_bound_def le_bound_refl le_bound_anti le_bound_trans.\n\n(*This lemma states that for two finite interval bounds with the same underlying value, the 'less than or equal to' relation between them depends only on a boolean implication between their boundary-type indicators.*)\nLemma bound_lexx c1 c2 x : (BSide c1 x <= BSide c2 x) = (c2 ==> c1).\n\n(*This lemma states that for two finite interval bounds with the same underlying value, the 'less than' relation between them holds if and only if their boundary-type indicators satisfy a specific boolean conjunction.*)\nLemma bound_ltxx c1 c2 x : (BSide c1 x < BSide c2 x) = (c1 && ~~ c2).\n\n(*This lemma states that an interval bound is greater than or equal to positive infinity if and only if that bound is positive infinity itself.*)\nLemma ge_pinfty b : (+oo <= b) = (b == +oo). \n\n(*This lemma states that an interval bound is less than or equal to negative infinity if and only if that bound is negative infinity itself.*)\nLemma le_ninfty b : (b <= -oo) = (b == -oo). \n\n(*This lemma states that no interval bound can be strictly greater than positive infinity.*)\nLemma gt_pinfty b : (+oo < b) = false. \n\n(*This lemma states that no interval bound can be strictly less than negative infinity.*)\nLemma lt_ninfty b : (b < -oo) = false. \n\n(*This lemma provides a detailed boolean formula for the 'less than' relation between two finite interval bounds. The relation holds if the first element is strictly less than the second, or if the elements are equal and the boundary types satisfy a specific boolean condition.*)\nLemma ltBSide x y (b b' : bool) :\n BSide b x < BSide b' y = (x < y ?<= if b && ~~ b').\n\n(*This lemma provides a detailed boolean formula for the 'less than or equal to' relation between two finite interval bounds. The relation holds if the first element is strictly less than the second, or if the elements are equal and their boundary types satisfy a specific boolean implication.*)\nLemma leBSide x y (b b' : bool) :\n BSide b x <= BSide b' y = (x < y ?<= if b' ==> b).\n\n(*This definition creates a pair consisting of two lemmas, one for the 'less than' relation and one for the 'less than or equal to' relation between finite interval bounds.*)\nDefinition lteBSide := (ltBSide, leBSide).\n\n(*This lemma states that an element is strictly less than the right-side embedding of another element if and only if the first element is less than or equal to the left-side embedding of the second element.*)\nLemma ltBRight_leBLeft b x : b < BRight x = (b <= BLeft x).\n\n(*This lemma states that the right-side embedding of an element is less than or equal to another element if and only if the left-side embedding of the first element is strictly less than the second element.*)\nLemma leBRight_ltBLeft b x : BRight x <= b = (BLeft x < b).\n\n(*This definition provides an equivalence stating that a side-embedded element is strictly less than the left-side embedding of another element if and only if the first original element is strictly less than the second original element.*)\nLet BLeft_ltE x y (b : bool) : BSide b x < BLeft y = (x < y).\n\n(*This definition provides an equivalence stating that a side-embedded element is less than or equal to the right-side embedding of another element if and only if the first original element is less than or equal to the second original element.*)\nLet BRight_leE x y (b : bool) : BSide b x <= BRight y = (x <= y).\n\n(*This definition provides an equivalence stating that the right-side embedding of an element is less than or equal to the left-side embedding of another element if and only if the first original element is strictly less than the second original element.*)\nLet BRight_BLeft_leE x y : BRight x <= BLeft y = (x < y).\n\n(*This definition provides an equivalence stating that the left-side embedding of an element is strictly less than the right-side embedding of another element if and only if the first original element is less than or equal to the second original element.*)\nLet BLeft_BRight_ltE x y : BLeft x < BRight y = (x <= y).\n\n(*This definition provides an equivalence stating that the right-side embedding of an element is strictly less than a side-embedded element if and only if the first original element is strictly less than the second original element.*)\nLet BRight_BSide_ltE x y (b : bool) : BRight x < BSide b y = (x < y).\n\n(*This definition provides an equivalence stating that the left-side embedding of an element is less than or equal to a side-embedded element if and only if the first original element is less than or equal to the second original element.*)\nLet BLeft_BSide_leE x y (b : bool) : BLeft x <= BSide b y = (x <= y).\n\n(*This definition provides an equivalence stating that a side-embedded element is strictly less than another side-embedded element on the same side if and only if the first original element is strictly less than the second original element.*)\nLet BSide_ltE x y (b : bool) : BSide b x < BSide b y = (x < y).\n\n(*This definition provides an equivalence stating that a side-embedded element is less than or equal to another side-embedded element on the same side if and only if the first original element is less than or equal to the second original element.*)\nLet BSide_leE x y (b : bool) : BSide b x <= BSide b y = (x <= y).\n\n(*This definition asserts that any element is less than or equal to the top element of the bounded type.*)\nLet BInfty_leE a : a <= BInfty T false. \n(*This definition asserts that the bottom element of the bounded type is less than or equal to any element.*)\nLet BInfty_geE a : BInfty T true <= a. \n(*This definition provides an equivalence stating that the top element is less than or equal to a given element if and only if that element is equal to the top element.*)\nLet BInfty_le_eqE a : BInfty T false <= a = (a == BInfty T false).\n\n(*This definition provides an equivalence stating that a given element is less than or equal to the bottom element if and only if that element is equal to the bottom element.*)\nLet BInfty_ge_eqE a : a <= BInfty T true = (a == BInfty T true).\n\n(*This definition provides an equivalence stating that an element is strictly less than the top element if and only if that element is not equal to the top element.*)\nLet BInfty_ltE a : a < BInfty T false = (a != BInfty T false).\n\n(*This definition provides an equivalence stating that the bottom element is strictly less than an element if and only if that element is not equal to the bottom element.*)\nLet BInfty_gtE a : BInfty T true < a = (a != BInfty T true).\n\n(*This definition asserts that it is false for the top element to be strictly less than any other element.*)\nLet BInfty_ltF a : BInfty T false < a = false.\n\n(*This definition asserts that it is false for any element to be strictly less than the bottom element.*)\nLet BInfty_gtF a : a < BInfty T true = false.\n\n(*This definition asserts that the bottom element is strictly less than the top element.*)\nLet BInfty_BInfty_ltE : BInfty T true < BInfty T false. \n\n(*This definition aggregates a collection of lemmas about bounded types, side embeddings, and infinite elements, intended for use as a simplification set by automated proof tactics.*)\nDefinition bnd_simp := (BLeft_ltE, BRight_leE,\n BRight_BLeft_leE, BLeft_BRight_ltE,\n BRight_BSide_ltE, BLeft_BSide_leE, BSide_ltE, BSide_leE,\n BInfty_leE, BInfty_geE, BInfty_BInfty_ltE,\n BInfty_le_eqE, BInfty_ge_eqE, BInfty_ltE, BInfty_gtE, BInfty_ltF, BInfty_gtF,\n @lexx _ T, @ltxx _ T, @eqxx T).\n\n(*This lemma states that for any two comparable elements in the original type, the side-embedding of their minimum is equal to the minimum of their respective side-embeddings.*)\nLemma comparable_BSide_min s (x y : T) : (x >=< y)%O ->\n BSide s (Order.min x y) = Order.min (BSide s x) (BSide s y).\n\n(*This lemma states that for any two comparable elements in the original type, the side-embedding of their maximum is equal to the maximum of their respective side-embeddings.*)\nLemma comparable_BSide_max s (x y : T) : (x >=< y)%O ->\n BSide s (Order.max x y) = Order.max (BSide s x) (BSide s y).\n\n(*This definition specifies the sub-interval relation, where one interval is considered a sub-interval of another if its lower bound is greater than or equal to the other's lower bound and its upper bound is less than or equal to the other's upper bound.*)\nDefinition subitv i1 i2 :=\n let: Interval b1l b1r := i1 in\n let: Interval b2l b2r := i2 in (b2l <= b1l) && (b1r <= b2r).\n\n(*This lemma states that the sub-interval relation is reflexive, meaning any interval is a sub-interval of itself.*)\nLemma subitv_refl : reflexive subitv.\n\n(*This lemma states that the sub-interval relation is antisymmetric, meaning if two intervals are sub-intervals of each other, they must be equal.*)\nLemma subitv_anti : antisymmetric subitv.\n\n(*This lemma states that the sub-interval relation is transitive, meaning if a first interval is a sub-interval of a second, and the second is a sub-interval of a third, then the first is a sub-interval of the third.*)\nLemma subitv_trans : transitive subitv.\n\n(*This definition creates a predicate that is true for any element for which the corresponding point-interval is a sub-interval of a given interval, effectively testing for membership in the interval.*)\nDefinition pred_of_itv i : pred T := [pred x | `[x, x] <= i].\n\n(*This canonical structure declaration establishes that an interval can be canonically viewed as a predicate on elements of the underlying type, allowing intervals to be used where predicates are expected.*)\nCanonical Structure itvPredType := PredType pred_of_itv.\n\n(*This lemma provides an equational form of the sub-interval relation, stating that one interval is less than or equal to another if and only if the second interval's lower bound is less than or equal to the first's lower bound and the first's upper bound is less than or equal to the second's upper bound.*)\nLemma subitvE b1l b1r b2l b2r :\n (Interval b1l b1r <= Interval b2l b2r) = (b2l <= b1l) && (b1r <= b2r).\n\n(*This lemma provides a characterization for an element to be contained within an interval, relating membership to comparisons involving the element and the interval's lower and upper bounds.*)\nLemma in_itv x i :\n x \\in i =\n let: Interval l u := i in\n match l with\n | BSide b lb => lb < x ?<= if b\n | BInfty b => b\n end &&\n match u with\n | BSide b ub => x < ub ?<= if ~~ b\n | BInfty b => ~~ b\n end.\n\n(*This lemma states that an element is contained in a given interval if and only if the interval's lower bound is less than or equal to the left bound derived from the element, and the right bound derived from the element is less than or equal to the interval's upper bound.*)\nLemma itv_boundlr bl br x :\n (x \\in Interval bl br) = (bl <= BLeft x) && (BRight x <= br).\n\n(*This lemma states that an element is a member of an interval with a specified lower and upper bound if and only if the element is both in the interval from the lower bound to positive infinity and in the interval from negative infinity to the upper bound.*)\nLemma itv_splitI bl br x :\n x \\in Interval bl br = (x \\in Interval bl +oo) && (x \\in Interval -oo br).\n\n(*This lemma states that if one interval is less than or equal to another in the pointwise order, it implies that the first interval is a subset of the second.*)\nLemma subitvP i1 i2 : i1 <= i2 -> {subset i1 <= i2}.\n\n#[warning=\"-unsupported-attributes\"]\n#[warn(note=\"The lemma subset_itv was generalized in MathComp 2.4.0 and the original was renamed to subset_itv_bound.\",\n cats=\"mathcomp-subset-itv\")]\n(*This lemma states that an interval is a subset of another interval if the first interval's lower bound is greater than or equal to the second interval's lower bound, and the first interval's upper bound is less than or equal to the second interval's upper bound.*)\nLemma subset_itv (x y z u : itv_bound T) : x <= y -> z <= u ->\n {subset Interval y z <= Interval x u}.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use subset_itv instead.\")]\n(*This deprecated lemma states that for two intervals defined by the same endpoint values but potentially different inclusivity, the first is a subset of the second if the second interval has an inclusive lower bound whenever the first one does, and the first interval has an exclusive upper bound whenever the second one does.*)\nLemma subset_itv_bound (r s u v : bool) x y : r <= u -> v <= s ->\n {subset Interval (BSide r x) (BSide s y) <= Interval (BSide u x) (BSide v y)}.\n\n(*This lemma states that for any two elements, the open interval between them is a subset of the closed interval between them.*)\nLemma subset_itv_oo_cc x y : {subset `]x, y[ <= `[x, y]}.\n\n(*This lemma states that for any two elements, the open interval between them is a subset of the interval that is open on the left and closed on the right.*)\nLemma subset_itv_oo_oc x y : {subset `]x, y[ <= `]x, y]}.\n\n(*This lemma states that for any two elements, the open interval between them is a subset of the interval that is closed on the left and open on the right.*)\nLemma subset_itv_oo_co x y : {subset `]x, y[ <= `[x, y[}.\n\n(*This lemma states that for any two elements, the interval that is open on the left and closed on the right is a subset of the closed interval between them.*)\nLemma subset_itv_oc_cc x y : {subset `]x, y] <= `[x, y]}.\n\n(*This lemma states that for any two elements, the interval that is closed on the left and open on the right is a subset of the closed interval between them.*)\nLemma subset_itv_co_cc x y : {subset `[x, y[ <= `[x, y]}.\n\n(*This lemma states that the closed interval from an element to itself is equivalent to the predicate that is true only for that specific element.*)\nLemma itvxx x : `[x, x] =i pred1 x.\n\n(*This lemma provides a reflection between the boolean statement that an element is in the closed interval from another element to itself, and the proposition that the two elements are equal.*)\nLemma itvxxP y x : reflect (y = x) (y \\in `[x, x]).\n\n(*This lemma states that if a first interval bound is less than or equal to a second one, then an interval starting with the second bound is a subset of an interval starting with the first, provided they share the same upper bound.*)\nLemma subitvPl b1l b2l br :\n b2l <= b1l -> {subset Interval b1l br <= Interval b2l br}.\n\n(*This lemma states that if a first interval bound is less than or equal to a second one, then an interval ending with the first bound is a subset of an interval ending with the second, provided they share the same lower bound.*)\nLemma subitvPr bl b1r b2r :\n b1r <= b2r -> {subset Interval bl b1r <= Interval bl b2r}.\n\n(*This lemma states that an element is a member of an interval whose lower and upper endpoint values are the same if and only if the interval's lower bound is inclusive, its upper bound is exclusive, and the element is equal to that endpoint value.*)\nLemma itv_xx x cl cr y :\n y \\in Interval (BSide cl x) (BSide cr x) = cl && ~~ cr && (y == x).\n\n(*This lemma states that an element which is the value of an interval's lower bound is contained in that interval if and only if the bound is inclusive and the element's corresponding right-side bound is less than or equal to the interval's upper bound.*)\nLemma boundl_in_itv c x b : x \\in Interval (BSide c x) b = c && (BRight x <= b).\n\n(*This lemma states that an element which is the value of an interval's upper bound is contained in that interval if and only if the bound is exclusive and the interval's lower bound is less than or equal to the element's corresponding left-side bound.*)\nLemma boundr_in_itv c x b :\n x \\in Interval b (BSide c x) = ~~ c && (b <= BLeft x).\n\n(*This definition packages two lemmas concerning the membership of an element in an interval when that element is also the value of one of the interval's bounds.*)\nDefinition bound_in_itv := (boundl_in_itv, boundr_in_itv).\n\n(*This lemma states that if an interval contains any element, then its lower bound must be strictly less than its upper bound.*)\nLemma lt_in_itv bl br x : x \\in Interval bl br -> bl < br.\n\n(*This lemma states that if an interval with explicitly defined boundary elements contains an element, then a specific order relation holds between the boundary values, which is either strict or non-strict inequality depending on the inclusivity of the bounds.*)\nLemma lteif_in_itv cl cr yl yr x :\n x \\in Interval (BSide cl yl) (BSide cr yr) -> yl < yr ?<= if cl && ~~ cr.\n\n(*This lemma states that if an interval's lower bound is not strictly less than its upper bound, the interval is empty.*)\nLemma itv_ge b1 b2 : ~~ (b1 < b2) -> Interval b1 b2 =i pred0.\n\n(*This definition provides a propositional form of the test for an element's membership in an interval, breaking down the condition into separate checks against the lower and upper bounds.*)\nDefinition itv_decompose i x : Prop :=\n let: Interval l u := i in\n (match l return Prop with\n | BSide b lb => lb < x ?<= if b\n | BInfty b => b\n end *\n match u return Prop with\n | BSide b ub => x < ub ?<= if ~~ b\n | BInfty b => ~~ b\n end)%type.\n\n(*This lemma establishes a reflection between the boolean test for an element's membership in an interval and the logically equivalent propositional decomposition of that test.*)\nLemma itv_dec : forall x i, reflect (itv_decompose i x) (x \\in i).\n\nArguments itv_dec {x i}.\n\n(*This definition constructs a type that aggregates a collection of provable properties that are guaranteed to hold when a given element is a member of a given interval, such as relationships between the element and the interval's bounds.*)\nDefinition itv_rewrite i x : Type :=\n let: Interval l u := i in\n (match l with\n | BLeft a => (a <= x) * (x < a = false)\n | BRight a => (a <= x) * (a < x) * (x <= a = false) * (x < a = false)\n | -oo => forall x : T, x == x\n | +oo => forall b : bool, unkeyed b = false\n end *\n match u with\n | BRight b => (x <= b) * (b < x = false)\n | BLeft b => (x <= b) * (x < b) * (b <= x = false) * (b < x = false)\n | +oo => forall x : T, x == x\n | -oo => forall b : bool, unkeyed b = false\n end *\n match l, u with\n | BLeft a, BRight b =>\n (a <= b) * (b < a = false) * (a \\in `[a, b]) * (b \\in `[a, b])\n | BLeft a, BLeft b =>\n (a <= b) * (a < b) * (b <= a = false) * (b < a = false)\n * (a \\in `[a, b]) * (a \\in `[a, b[) * (b \\in `[a, b]) * (b \\in `]a, b])\n | BRight a, BRight b =>\n (a <= b) * (a < b) * (b <= a = false) * (b < a = false)\n * (a \\in `[a, b]) * (a \\in `[a, b[) * (b \\in `[a, b]) * (b \\in `]a, b])\n | BRight a, BLeft b =>\n (a <= b) * (a < b) * (b <= a = false) * (b < a = false)\n * (a \\in `[a, b]) * (a \\in `[a, b[) * (b \\in `[a, b]) * (b \\in `]a, b])\n | _, _ => forall x : T, x == x\n end)%type.\n\n(*This lemma asserts that if an element is a member of an interval, then the rich set of properties about the element and interval's bounds, as specified by the rewrite type, can be derived.*)\nLemma itvP x i : x \\in i -> itv_rewrite i x.\n\nArguments itvP [x i].\n\n(*This lemma states that an interval with a given lower bound and an exclusive upper bound at a point is equivalent to the union of the singleton set of that point and the interval with the same lower bound but an inclusive upper bound at that point.*)\nLemma itv_splitU1 b x : b <= BLeft x ->\n Interval b (BRight x) =i [predU1 x & Interval b (BLeft x)].\n\n(*This lemma states that an interval starting with an inclusive lower bound is equivalent to the union of the singleton set of that bound's value and the interval starting with the corresponding exclusive lower bound, sharing the same upper bound.*)\nLemma itv_split1U b x : BRight x <= b ->\n Interval (BLeft x) b =i [predU1 x & Interval (BRight x) b].\n\nEnd IntervalPOrder.\n\nSection IntervalLattice.\n\nVariable (disp : Order.disp_t) (T : latticeType disp).\nImplicit Types (x y z : T) (b bl br : itv_bound T) (i : interval T).\n\n(*This definition specifies the meet operation for two interval bounds. The result is negative infinity if either input is negative infinity. If one input is positive infinity, the result is the other bound. For two finite bounds, the new value is the meet of the input values, and its inclusivity is determined by the order of the values and their original inclusivity.*)\nDefinition bound_meet bl br : itv_bound T :=\n match bl, br with\n | -oo, _ | _, -oo => -oo\n | +oo, b | b, +oo => b\n | BSide xb x, BSide yb y =>\n BSide (((x <= y) && xb) || ((y <= x) && yb)) (x `&` y)\n end.\n\n(*This definition specifies the join operation for two interval bounds. The result is positive infinity if either input is positive infinity. If one input is negative infinity, the result is the other bound. For two finite bounds, the new value is the join of the input values, and its inclusivity is determined by the order of the values and their original inclusivity.*)\nDefinition bound_join bl br : itv_bound T :=\n match bl, br with\n | -oo, b | b, -oo => b\n | +oo, _ | _, +oo => +oo\n | BSide xb x, BSide yb y =>\n BSide ((~~ (x <= y) || yb) && (~~ (y <= x) || xb)) (x `|` y)\n end.\n\n(*This lemma states that the meet operation on interval bounds is commutative.*)\nLemma bound_meetC : commutative bound_meet.\n\n(*This lemma states that the join operation on interval bounds is commutative.*)\nLemma bound_joinC : commutative bound_join.\n\n(*This lemma states that the meet operation on interval bounds is associative.*)\nLemma bound_meetA : associative bound_meet.\n\n(*This lemma states that the join operation on interval bounds is associative.*)\nLemma bound_joinA : associative bound_join.\n\n(*This lemma states the absorption law for interval bounds, where the join of an interval bound with the meet of itself and another interval bound is equal to the original interval bound.*)\nLemma bound_meetKU b2 b1 : bound_join b1 (bound_meet b1 b2) = b1.\n\n(*This lemma states the absorption law for interval bounds, where the meet of an interval bound with the join of itself and another interval bound is equal to the original interval bound.*)\nLemma bound_joinKI b2 b1 : bound_meet b1 (bound_join b1 b2) = b1.\n\n(*This lemma states that an interval bound is less than or equal to another if and only if their meet is equal to the first interval bound.*)\nLemma bound_leEmeet b1 b2 : (b1 <= b2) = (bound_meet b1 b2 == b1).\n\nHB.instance Definition _ :=\n Order.POrder_isLattice.Build (itv_bound_display disp) (itv_bound T)\n bound_meetC bound_joinC bound_meetA bound_joinA\n bound_joinKI bound_meetKU bound_leEmeet.\n\n(*This lemma states that negative infinity is the bottom element in the order on interval bounds, meaning it is less than or equal to any other interval bound.*)\nLemma bound_le0x b : -oo <= b. \n\n(*This lemma states that positive infinity is the top element in the order on interval bounds, meaning any interval bound is less than or equal to it.*)\nLemma bound_lex1 b : b <= +oo. \n\nHB.instance Definition _ :=\n Order.hasBottom.Build (itv_bound_display disp) (itv_bound T) bound_le0x.\nHB.instance Definition _ :=\n Order.hasTop.Build (itv_bound_display disp) (itv_bound T) bound_lex1.\n\n(*This definition specifies the meet of two intervals, which corresponds to their intersection. The resulting interval's lower bound is the join of the input intervals' lower bounds, and its upper bound is the meet of their upper bounds.*)\nDefinition itv_meet i1 i2 : interval T :=\n let: Interval b1l b1r := i1 in\n let: Interval b2l b2r := i2 in Interval (b1l `|` b2l) (b1r `&` b2r).\n\n(*This definition specifies the join of two intervals, which results in the smallest interval containing both. The resulting interval's lower bound is the meet of the input intervals' lower bounds, and its upper bound is the join of their upper bounds.*)\nDefinition itv_join i1 i2 : interval T :=\n let: Interval b1l b1r := i1 in\n let: Interval b2l b2r := i2 in Interval (b1l `&` b2l) (b1r `|` b2r).\n\n(*This lemma states that the meet operation on intervals is commutative.*)\nLemma itv_meetC : commutative itv_meet.\n\n(*This lemma states that the join operation on intervals is commutative.*)\nLemma itv_joinC : commutative itv_join.\n\n(*This lemma states that the meet operation on intervals is associative.*)\nLemma itv_meetA : associative itv_meet.\n\n(*This lemma states that the join operation on intervals is associative.*)\nLemma itv_joinA : associative itv_join.\n\n(*This lemma states the absorption law for intervals, where the join of an interval with the meet of itself and another interval is equal to the original interval.*)\nLemma itv_meetKU i2 i1 : itv_join i1 (itv_meet i1 i2) = i1.\n\n(*This lemma states the absorption law for intervals, where the meet of an interval with the join of itself and another interval is equal to the original interval.*)\nLemma itv_joinKI i2 i1 : itv_meet i1 (itv_join i1 i2) = i1.\n\n(*This lemma states that an interval is a subset of another interval if and only if their intersection is equal to the first interval.*)\nLemma itv_leEmeet i1 i2 : (i1 <= i2) = (itv_meet i1 i2 == i1).\n\nHB.instance Definition _ :=\n Order.POrder_isLattice.Build (interval_display disp) (interval T)\n itv_meetC itv_joinC itv_meetA itv_joinA\n itv_joinKI itv_meetKU itv_leEmeet.\n\n(*This lemma states that the empty interval is the bottom element in the lattice of intervals, meaning it is a sub-interval of any other interval.*)\nLemma itv_le0x i : Interval +oo -oo <= i. \n\n(*This lemma states that any interval is a sub-interval of the interval representing the entire type, which acts as the top element in the lattice of intervals.*)\nLemma itv_lex1 i : i <= `]-oo, +oo[. \n\nHB.instance Definition _ :=\n Order.hasBottom.Build (interval_display disp) (interval T) itv_le0x.\n(*This lemma states that an element belongs to the meet (intersection) of two intervals if and only if it belongs to both of the original intervals.*)\nLemma in_itvI x i1 i2 : x \\in i1 `&` i2 = (x \\in i1) && (x \\in i2).\n\nEnd IntervalLattice.\n\nSection IntervalTotal.\n\nVariable (disp : Order.disp_t) (T : orderType disp).\nImplicit Types (a b c : itv_bound T) (x y z : T) (i : interval T).\n\n(*This lemma states that applying an interval bound constructor to the minimum of two elements yields the same result as taking the minimum of the interval bounds constructed from each element individually.*)\nLemma BSide_min s (x y : T) :\n BSide s (Order.min x y) = Order.min (BSide s x) (BSide s y).\n\n(*This lemma states that applying an interval bound constructor to the maximum of two elements yields the same result as taking the maximum of the interval bounds constructed from each element individually.*)\nLemma BSide_max s (x y : T) :\n BSide s (Order.max x y) = Order.max (BSide s x) (BSide s y).\n\n(*This lemma states that the order relation on the type of interval bounds is total, meaning any two interval bounds are comparable.*)\nLemma itv_bound_total : total (<=%O : rel (itv_bound T)).\n\nHB.instance Definition _ :=\n Order.Lattice_isTotal.Build\n (itv_bound_display disp) (itv_bound T) itv_bound_total.\n\n(*This lemma states that the meet operation on intervals is left-distributive over the join operation.*)\nLemma itv_meetUl : @left_distributive (interval T) _ Order.meet Order.join.\n\n(*This lemma states that if a point lies between the lower and upper bounds of an interval, then the interval can be expressed as the union of the two sub-intervals formed by splitting the original interval at that point.*)\nLemma itv_splitU c a b : a <= c <= b ->\n forall y, y \\in Interval a b = (y \\in Interval a c) || (y \\in Interval c b).\n\n(*This lemma provides a way to partition an interval around an element it contains. It states that membership in the interval is equivalent to belonging to the sub-interval to the left of the element, being equal to the element, or belonging to the sub-interval to the right of the element.*)\nLemma itv_splitUeq x a b : x \\in Interval a b ->\n forall y, y \\in Interval a b =\n [|| y \\in Interval a (BLeft x), y == x | y \\in Interval (BRight x) b].\n\n(*This lemma states that for any three intervals on a totally ordered type, their common intersection is equal to at least one of the three possible pairwise intersections.*)\nLemma itv_total_meet3E i1 i2 i3 :\n i1 `&` i2 `&` i3 \\in [:: i1 `&` i2; i1 `&` i3; i2 `&` i3].\n\n(*This lemma states that for any three intervals on a totally ordered type, their common join is equal to at least one of the three possible pairwise joins.*)\nLemma itv_total_join3E i1 i2 i3 :\n i1 `|` i2 `|` i3 \\in [:: i1 `|` i2; i1 `|` i3; i2 `|` i3].\n\n(*This lemma establishes an equivalence between the complement of the predicate defining a left-unbounded interval and the predicate defining a right-unbounded interval with the same endpoint.*)\nLemma predC_itvl a : [predC Interval -oo a] =i Interval a +oo.\n\n(*This lemma establishes an equivalence between the complement of the predicate defining a right-unbounded interval and the predicate defining a left-unbounded interval with the same endpoint.*)\nLemma predC_itvr a : [predC Interval a +oo] =i Interval -oo a.\n\n(*This lemma states that the complement of a given interval is equivalent to the union of two intervals: one extending from negative infinity to the lower bound of the given interval, and the other extending from the upper bound of the given interval to positive infinity.*)\nLemma predC_itv i : [predC i] =i [predU Interval -oo i.1 & Interval i.2 +oo].\n\nEnd IntervalTotal.\n\nLocal Open Scope ring_scope.\nImport GRing.Theory Num.Theory.\n\nSection IntervalNumDomain.\n\nVariable R : numDomainType.\nImplicit Types x : R.\n\n(*This lemma states that for any two real numbers, applying a boundary side constructor to their minimum is equivalent to taking the minimum of the two boundary sides constructed from each number individually. This shows that the boundary side operation distributes over the minimum operation for real numbers.*)\nLemma real_BSide_min b x y : x \\in Num.real -> y \\in Num.real ->\n BSide b (Order.min x y) = Order.min (BSide b x) (BSide b y).\n\n(*This lemma states that for any two real numbers, applying a boundary side constructor to their maximum is equivalent to taking the maximum of the two boundary sides constructed from each number individually. This shows that the boundary side operation distributes over the maximum operation for real numbers.*)\nLemma real_BSide_max b x y : x \\in Num.real -> y \\in Num.real ->\n BSide b (Order.max x y) = Order.max (BSide b x) (BSide b y).\n\n(*This lemma establishes that the number zero is a member of the closed interval from the additive inverse of a number to that number if and only if the number is greater than or equal to zero.*)\nLemma mem0_itvcc_xNx x : (0 \\in `[- x, x]) = (0 <= x).\n\n(*This lemma establishes that the number zero is a member of the open interval from the additive inverse of a number to that number if and only if the number is strictly greater than zero.*)\nLemma mem0_itvoo_xNx x : 0 \\in `](- x), x[ = (0 < x).\n\n(*This lemma states that the additive inverse of a number is a member of a given interval if and only if the number itself is a member of a corresponding interval where the endpoints are the additive inverses of the original endpoints, their order is reversed, and the open or closed nature of each boundary is swapped.*)\nLemma oppr_itv ba bb (xa xb x : R) :\n (- x \\in Interval (BSide ba xa) (BSide bb xb)) =\n (x \\in Interval (BSide (~~ bb) (- xb)) (BSide (~~ ba) (- xa))).\n\n(*This lemma states that the additive inverse of a number is in the open interval between two other numbers if and only if the number itself is in the open interval between the additive inverses of those two numbers, with their order swapped.*)\nLemma oppr_itvoo (a b x : R) : (- x \\in `]a, b[) = (x \\in `](- b), (- a)[).\n\n(*This lemma states that the additive inverse of a number is in a left-closed, right-open interval if and only if the number itself is in a left-open, right-closed interval bounded by the additive inverses of the original interval's endpoints, with their order swapped.*)\nLemma oppr_itvco (a b x : R) : (- x \\in `[a, b[) = (x \\in `](- b), (- a)]).\n\n(*This lemma states that the additive inverse of a number is in a left-open, right-closed interval if and only if the number itself is in a left-closed, right-open interval bounded by the additive inverses of the original interval's endpoints, with their order swapped.*)\nLemma oppr_itvoc (a b x : R) : (- x \\in `]a, b]) = (x \\in `[(- b), (- a)[).\n\n(*This lemma states that the additive inverse of a number is in the closed interval between two other numbers if and only if the number itself is in the closed interval between the additive inverses of those two numbers, with their order swapped.*)\nLemma oppr_itvcc (a b x : R) : (- x \\in `[a, b]) = (x \\in `[(- b), (- a)]).\n\n(*This definition computes a representative point within a given interval over a numeric domain. For a bounded interval, it returns the midpoint of the endpoints. For an interval unbounded below, it returns one less than the upper bound. For an interval unbounded above, it returns one more than the lower bound. For an interval that is unbounded on both sides, it returns zero.*)\nDefinition miditv (R : numDomainType) (i : interval R) : R :=\n match i with\n | Interval (BSide _ a) (BSide _ b) => (a + b) / 2%:R\n | Interval -oo%O (BSide _ b) => b - 1\n | Interval (BSide _ a) +oo%O => a + 1\n | Interval -oo%O +oo%O => 0\n | _ => 0\n end.\n\nEnd IntervalNumDomain.\n\nSection IntervalField.\n\nVariable R : numFieldType.\nImplicit Types (x y z : R) (i : interval R).\n\nLocal Notation mid x y := ((x + y) / 2).\n\n(*This lemma states that for two numbers in a numeric field where the first is less than or equal to the second, their midpoint is contained within the interval defined by these two numbers. If the interval is open at the second endpoint, the first number must be strictly less than the second.*)\nLemma mid_in_itv : forall ba bb (xa xb : R), xa < xb ?<= if ba && ~~ bb ->\n mid xa xb \\in Interval (BSide ba xa) (BSide bb xb).\n\n(*This lemma states that for any two distinct numbers in a numeric field, their midpoint lies within the open interval defined by them.*)\nLemma mid_in_itvoo : forall (xa xb : R), xa < xb -> mid xa xb \\in `]xa, xb[.\n\n(*This lemma states that for any two numbers in a numeric field such that the first is less than or equal to the second, their midpoint lies within the closed interval defined by them.*)\nLemma mid_in_itvcc : forall (xa xb : R), xa <= xb -> mid xa xb \\in `[xa, xb].\n\n(*This lemma asserts that the representative point of any interval, as computed by the `miditv` definition, is indeed a member of that interval, provided that the interval's lower bound is strictly less than its upper bound.*)\nLemma mem_miditv i : (i.1 < i.2)%O -> miditv i \\in i.\n\n(*This lemma states that for any non-empty interval, a boundary formed at the interval's representative midpoint is less than or equal to the interval's original upper boundary.*)\nLemma miditv_le_left i b : (i.1 < i.2)%O -> (BSide b (miditv i) <= i.2)%O.\n\n(*This lemma states that for any non-empty interval, the interval's original lower boundary is less than or equal to a boundary formed at the interval's representative midpoint.*)\nLemma miditv_ge_right i b : (i.1 < i.2)%O -> (i.1 <= BSide b (miditv i))%O.\n\n(*This lemma establishes an equivalence for membership in a closed interval. It states that a number belongs to the closed interval between two endpoints if and only if, for any strictly positive value, it also belongs to the closed interval that has been expanded at both ends by that value.*)\nLemma in_segmentDgt0Pr x y z :\n reflect (forall e, e > 0 -> y \\in `[x - e, z + e]) (y \\in `[x, z]).\n\n(*This lemma establishes an equivalence for membership in a closed interval. It states that a number belongs to the closed interval between two endpoints if and only if, for any strictly positive value, it also belongs to the closed interval that has been expanded at both ends by that value.*)\nLemma in_segmentDgt0Pl x y z :\n reflect (forall e, e > 0 -> y \\in `[(- e + x), (e + z)]) (y \\in `[x, z]).", - "algebra.vector": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype bigop finfun tuple.\nFrom mathcomp Require Import ssralg matrix mxalgebra zmodp.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope vspace_scope.\nDeclare Scope lfun_scope.\n\nLocal Open Scope ring_scope.\n\nReserved Notation \"{ 'vspace' T }\" (format \"{ 'vspace' T }\").\nReserved Notation \"''Hom' ( T , rT )\" (format \"''Hom' ( T , rT )\").\nReserved Notation \"''End' ( T )\" (format \"''End' ( T )\").\nReserved Notation \"\\dim A\" (at level 10, A at level 8, format \"\\dim A\").\n\nDelimit Scope vspace_scope with VS.\n\nImport GRing.Theory.\n\n(*Defines the axiom for a finite-dimensional vector space over a non-zero ring, which asserts the existence of a linear and bijective function from the vector space to the canonical row vector space of a given dimension.*)\nDefinition vector_axiom_def (R : nzRingType) n (V : lmodType R) :=\n {v2r : V -> 'rV[R]_n | linear v2r & bijective v2r}.\nArguments vector_axiom_def [R] n%_N V%_type.\n\n(*A mixin record that equips a left module over a non-zero ring with a finite dimension, providing both the dimension as a natural number and the axiom asserting it is isomorphic to the canonical row vector space of that dimension.*)\nHB.mixin Record Lmodule_hasFinDim (R : nzRingType) (V : Type) of GRing.Lmodule R V :=\n { dim : nat;\n vector_subdef : vector_axiom_def dim V }.\n\n#[mathcomp(axiom=\"vector_axiom_def\"), short(type=\"vectType\")]\n(*This structure defines a finite-dimensional vector space over a non-zero ring as a left module that is equipped with a finite dimension.*)\nHB.structure Definition Vector (R : nzRingType) :=\n { V of Lmodule_hasFinDim R V & GRing.Lmodule R V }.\n\n#[deprecated(since=\"mathcomp 2.2.0\", note=\"Use Vector.axiom instead.\")]\n(*A deprecated notation for the axiom of a finite-dimensional vector space, which provides the proof object asserting that the space is linearly and bijectively mapped to a canonical row vector space of the same dimension.*)\nNotation vector_axiom := Vector.axiom.\nArguments dim {R} s.\n\nSection OtherDefs.\nLocal Coercion dim : Vector.type >-> nat.\n(*An inductive type representing a vector subspace of a finite-dimensional vector space. A subspace is defined by a matrix whose rows form a basis, with the constraint that this matrix is in a canonical row-echelon form.*)\nInductive space (K : fieldType) (vT : Vector.type K) :=\n Space (mx : 'M[K]_vT) & <>%MS == mx.\n(*An inductive type representing a linear map, or homomorphism, between two finite-dimensional vector spaces over the same non-zero ring. It is defined by the matrix that represents the transformation.*)\nInductive hom (R : nzRingType) (vT wT : Vector.type R) :=\n Hom of 'M[R]_(vT, wT).\nEnd OtherDefs.\n\nModule Import VectorExports.\nBind Scope ring_scope with Vector.sort.\n\nArguments space [K] vT%_type.\n\n(*A notation for the type of all vector subspaces within a given finite-dimensional vector space.*)\nNotation \"{ 'vspace' vT }\" := (space vT) : type_scope.\n(*A notation representing the type of all linear maps, or homomorphisms, from a given source finite-dimensional vector space to a target finite-dimensional vector space.*)\nNotation \"''Hom' ( aT , rT )\" := (hom aT rT) : type_scope.\n(*A notation representing the type of all endomorphisms on a given finite-dimensional vector space, which are linear maps from the space to itself.*)\nNotation \"''End' ( vT )\" := (hom vT vT) : type_scope.\n\nPrenex Implicits Hom.\n\nDelimit Scope vspace_scope with VS.\nBind Scope vspace_scope with space.\nDelimit Scope lfun_scope with VF.\nBind Scope lfun_scope with hom.\n\nEnd VectorExports.\n\nModule VectorInternalTheory.\n\nSection Iso.\nVariables (R : nzRingType) (vT rT : vectType R).\nLocal Coercion dim : Vector.type >-> nat.\n\n(*This proof term establishes that any given finite-dimensional vector space satisfies its own defining axiom, which asserts the existence of a linear isomorphism to a canonical row vector space of the same dimension.*)\nFact v2r_subproof : Vector.axiom vT vT. \n(*This definition defines the canonical isomorphism that maps a vector from a finite-dimensional vector space to its corresponding representation as a row vector.*)\nDefinition v2r := s2val v2r_subproof.\n\n(*This proof term establishes that the canonical isomorphism from a finite-dimensional vector space to its row vector representation is bijective, meaning it is both injective and surjective.*)\nLet v2r_bij : bijective v2r := s2valP' v2r_subproof.\n(*This proof term establishes the existence of an inverse function for the canonical isomorphism that maps vectors to row vectors, ensuring a way to map back from the row vector representation to the original vector space.*)\nFact r2v_subproof : {r2v | cancel r2v v2r}.\n\n(*This definition provides the explicit inverse of the canonical isomorphism, mapping a row vector representation back to its corresponding vector in the original finite-dimensional vector space.*)\nDefinition r2v := sval r2v_subproof.\n\n(*This lemma states that composing the mapping from a vector to its row vector representation with the mapping from the row vector back to the vector yields the identity function on the original vector space.*)\nLemma r2vK : cancel r2v v2r. \n(*This lemma states that the function mapping a row vector representation to its corresponding vector is injective, meaning distinct row vectors map to distinct vectors.*)\nLemma r2v_inj : injective r2v. \n(*This lemma states that composing the mapping from a row vector to a vector with the mapping from a vector back to a row vector yields the identity function on the space of row vectors.*)\nLemma v2rK : cancel v2r r2v. \n(*This lemma states that the function mapping a vector to its row vector representation is injective, meaning distinct vectors map to distinct row vectors.*)\nLemma v2r_inj : injective v2r. \n\nHB.instance Definition _ := GRing.isSemilinear.Build R vT 'rV_vT _ v2r\n (GRing.semilinear_linear (s2valP v2r_subproof)).\n(*This definition converts a tuple of vectors from a finite-dimensional vector space into a matrix, where each row of the matrix is the row vector representation of the corresponding vector in the tuple.*)\nDefinition b2mx n (X : n.-tuple vT) := \\matrix_i v2r (tnth X i).\n(*This lemma states that converting the i-th row of a matrix, which was formed from a tuple of vectors, back into a vector yields the original i-th vector from the tuple.*)\nLemma b2mxK n (X : n.-tuple vT) i : r2v (row i (b2mx X)) = X`_i.\n\n(*This definition extracts the canonical matrix representation whose rows form a basis for a given vector subspace.*)\nDefinition vs2mx (U : @space K vT) := let: Space mx _ := U in mx.\n(*This lemma states that the matrix representation of a vector subspace is already in its canonical row-echelon form, meaning that computing its row-span does not change the matrix.*)\nLemma gen_vs2mx (U : {vspace vT}) : <>%MS = vs2mx U.\n\n(*This proof term establishes that for any given matrix, the operation of computing its canonical row-echelon form is idempotent, which justifies the construction of a vector subspace from an arbitrary matrix.*)\nFact mx2vs_subproof m (A : 'M[K]_(m, vT)) : <<(<>)>>%MS == <>%MS.\n\n(*This definition constructs a vector subspace from a given matrix by computing the canonical row-echelon form of the matrix's row space.*)\nDefinition mx2vs {m} A : {vspace vT} := Space (@mx2vs_subproof m A).\n\n(*This lemma states that converting a vector subspace into its canonical matrix representation and then converting that matrix back into a vector subspace yields the original subspace.*)\nLemma vs2mxK : cancel vs2mx mx2vs.\n\n(*This lemma states that converting an arbitrary matrix into a vector subspace and then extracting the canonical matrix representation of that subspace results in a matrix that generates the same row space as the original matrix.*)\nLemma mx2vsK m (M : 'M_(m, vT)) : (vs2mx (mx2vs M) :=: M)%MS.\n\nEnd Vspace.\n\nSection Hom.\nVariables (R : nzRingType) (aT rT : vectType R).\n(*This definition extracts the underlying matrix that represents a given linear map between two finite-dimensional vector spaces.*)\nDefinition f2mx (f : 'Hom(aT, rT)) := let: Hom A := f in A.\n(*This definition provides the dimension of a vector subspace, which is computed as the rank of the canonical matrix representing that subspace.*)\nDefinition dimv U := \\rank (vs2mx U).\n(*This definition determines whether one vector subspace is a subset of another by checking if the row space of the first subspace's canonical matrix is contained within the row space of the second's.*)\nDefinition subsetv U V := (vs2mx U <= vs2mx V)%MS.\n(*This definition constructs the one-dimensional vector subspace, or line, spanned by a single given vector.*)\nDefinition vline u := mx2vs (v2r u).\n\n(*This definition creates a predicate that is true for any vector belonging to a given vector subspace.*)\nDefinition pred_of_vspace (U : space vT) : {pred vT} :=\n fun v => (vs2mx (vline v) <= vs2mx U)%MS.\nCanonical vspace_predType := @PredType _ (unkeyed {vspace vT}) pred_of_vspace.\n\n(*This definition represents the entire vector space, which contains all possible vectors of a particular type.*)\nDefinition fullv : {vspace vT} := mx2vs 1%:M.\n(*This definition computes the sum of two vector subspaces, which is the smallest vector subspace that contains both as subsets.*)\nDefinition addv U V := mx2vs (vs2mx U + vs2mx V).\n(*This definition computes the intersection of two vector subspaces, which is the largest vector subspace contained within both.*)\nDefinition capv U V := mx2vs (vs2mx U :&: vs2mx V).\n(*This definition computes the orthogonal complement of a given vector subspace with respect to the standard dot product.*)\nDefinition complv U := mx2vs (vs2mx U)^C.\n(*This definition computes a subspace difference, yielding the part of the first subspace that is orthogonal to the intersection of the two subspaces.*)\nDefinition diffv U V := mx2vs (vs2mx U :\\: vs2mx V).\n(*This definition selects an arbitrary non-zero vector from a given non-zero vector subspace. It returns the zero vector if the subspace is the zero subspace.*)\nDefinition vpick U := r2v (nz_row (vs2mx U)).\n(*This fact provides a key for managing the locked definition of the span operation, controlling when its implementation is revealed.*)\nFact span_key : unit. \n(*This definition specifies the concrete implementation for computing the vector subspace spanned by a given finite sequence of vectors by constructing a matrix from these vectors.*)\nDefinition span_expanded_def X := mx2vs (b2mx (in_tuple X)).\n(*This definition computes the vector subspace spanned by a finite sequence of vectors, which is the set of all possible linear combinations of those vectors.*)\nDefinition span := locked_with span_key span_expanded_def.\nCanonical span_unlockable := [unlockable fun span].\n(*This definition provides the concrete implementation for computing a basis for a vector subspace by extracting the rows from the row-reduced echelon form of its representative matrix.*)\nDefinition vbasis_def U :=\n [tuple r2v (row i (row_base (vs2mx U))) | i < dimv U].\n(*This definition returns a basis for a given vector subspace, which is a linearly independent finite sequence of vectors that spans the entire subspace.*)\nDefinition vbasis := locked_with span_key vbasis_def.\nCanonical vbasis_unlockable := [unlockable fun vbasis].\n\n(*This definition determines if a finite sequence of vectors is linearly independent by checking if the dimension of the subspace they span equals the number of vectors in the sequence.*)\nDefinition free X := dimv (span X) == size X.\n(*This definition determines if a finite sequence of vectors constitutes a basis for a given vector subspace by checking if the sequence is linearly independent and its span is equal to the subspace.*)\nDefinition basis_of U X := (span X == U) && free X.\n\nEnd VspaceDefs.\n\nCoercion pred_of_vspace : space >-> pred_sort.\n(*This notation represents the dimension of a vector subspace, defined as the number of vectors in any of its bases.*)\nNotation \"\\dim U\" := (dimv U) : nat_scope.\n(*This notation expresses that one vector subspace is a subset of another vector subspace.*)\nNotation \"U <= V\" := (subsetv U V) : vspace_scope.\n(*This notation expresses a chain of subspace inclusions, indicating that a first vector subspace is a subset of a second, and the second is a subset of a third.*)\nNotation \"U <= V <= W\" := (subsetv U V && subsetv V W) : vspace_scope.\n(*This notation represents the one-dimensional vector subspace containing all scalar multiples of a single vector.*)\nNotation \"<[ v ] >\" := (vline v) : vspace_scope.\n(*This notation represents the vector subspace spanned by a finite sequence of vectors.*)\nNotation \"<< X >>\" := (span X) : vspace_scope.\n(*This notation represents the zero-dimensional vector subspace, which contains only the zero vector.*)\nNotation \"0\" := (vline 0) : vspace_scope.\nArguments fullv {K vT}.\nPrenex Implicits subsetv addv capv complv diffv span free basis_of.\n\n(*This notation represents the sum of two vector subspaces, defined as the smallest vector subspace that contains both.*)\nNotation \"U + V\" := (addv U V) : vspace_scope.\n(*This notation represents the intersection of two vector subspaces, which is the largest vector subspace contained within both.*)\nNotation \"U :&: V\" := (capv U V) : vspace_scope.\n(*This notation represents the orthogonal complement of a vector subspace.*)\nNotation \"U ^C\" := (complv U) : vspace_scope.\n(*This notation represents the subspace consisting of all vectors in the first subspace that are orthogonal to the intersection of the two subspaces.*)\nNotation \"U :\\: V\" := (diffv U V) : vspace_scope.\n(*This notation represents the full vector space of a given vector type, which is the space containing all possible vectors.*)\nNotation \"{ : vT }\" := (@fullv _ vT) (only parsing) : vspace_scope.\n\n(*This notation denotes the sum of a family of vector subspaces, indexed over a range of values that satisfy a specific condition.*)\nNotation \"\\sum_ ( i <- r | P ) U\" :=\n (\\big[addv/0%VS]_(i <- r | P%B) U%VS) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each index i in a given finite sequence r.*)\nNotation \"\\sum_ ( i <- r ) U\" :=\n (\\big[addv/0%VS]_(i <- r) U%VS) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each natural number index i that is greater than or equal to m and less than n, and that also satisfies a boolean predicate P.*)\nNotation \"\\sum_ ( m <= i < n | P ) U\" :=\n (\\big[addv/0%VS]_(m <= i < n | P%B) U%VS) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each natural number index i that is greater than or equal to m and less than n.*)\nNotation \"\\sum_ ( m <= i < n ) U\" :=\n (\\big[addv/0%VS]_(m <= i < n) U%VS) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each index i of a finite type that satisfies a boolean predicate P.*)\nNotation \"\\sum_ ( i | P ) U\" :=\n (\\big[addv/0%VS]_(i | P%B) U%VS) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each index i of a given finite type.*)\nNotation \"\\sum_ i U\" :=\n (\\big[addv/0%VS]_i U%VS) : vspace_scope.\n(*Parsing-only notation for computing the sum of vectors, where each vector is generated by an expression U for each index i of a specified type t that satisfies a boolean predicate P.*)\nNotation \"\\sum_ ( i : t | P ) U\" :=\n (\\big[addv/0%VS]_(i : t | P%B) U%VS) (only parsing) : vspace_scope.\n(*Parsing-only notation for computing the sum of vectors, where each vector is generated by an expression U for each index i of a specified type t.*)\nNotation \"\\sum_ ( i : t ) U\" :=\n (\\big[addv/0%VS]_(i : t) U%VS) (only parsing) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each natural number index i that is less than n and satisfies a boolean predicate P.*)\nNotation \"\\sum_ ( i < n | P ) U\" :=\n (\\big[addv/0%VS]_(i < n | P%B) U%VS) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each natural number index i that is less than n.*)\nNotation \"\\sum_ ( i < n ) U\" :=\n (\\big[addv/0%VS]_(i < n) U%VS) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each index i in a given finite set A that satisfies a boolean predicate P.*)\nNotation \"\\sum_ ( i 'in' A | P ) U\" :=\n (\\big[addv/0%VS]_(i in A | P%B) U%VS) : vspace_scope.\n(*Notation for computing the sum of vectors, where each vector is generated by an expression U for each index i in a given finite set A.*)\nNotation \"\\sum_ ( i 'in' A ) U\" :=\n (\\big[addv/0%VS]_(i in A) U%VS) : vspace_scope.\n\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each index i in a given finite sequence r that satisfies a boolean predicate P.*)\nNotation \"\\bigcap_ ( i <- r | P ) U\" :=\n (\\big[capv/fullv]_(i <- r | P%B) U%VS) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each index i in a given finite sequence r.*)\nNotation \"\\bigcap_ ( i <- r ) U\" :=\n (\\big[capv/fullv]_(i <- r) U%VS) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each natural number index i that is greater than or equal to m and less than n, and that also satisfies a boolean predicate P.*)\nNotation \"\\bigcap_ ( m <= i < n | P ) U\" :=\n (\\big[capv/fullv]_(m <= i < n | P%B) U%VS) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each natural number index i that is greater than or equal to m and less than n.*)\nNotation \"\\bigcap_ ( m <= i < n ) U\" :=\n (\\big[capv/fullv]_(m <= i < n) U%VS) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each index i of a finite type that satisfies a boolean predicate P.*)\nNotation \"\\bigcap_ ( i | P ) U\" :=\n (\\big[capv/fullv]_(i | P%B) U%VS) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each index i of a given finite type.*)\nNotation \"\\bigcap_ i U\" :=\n (\\big[capv/fullv]_i U%VS) : vspace_scope.\n(*Parsing-only notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each index i of a specified type t that satisfies a boolean predicate P.*)\nNotation \"\\bigcap_ ( i : t | P ) U\" :=\n (\\big[capv/fullv]_(i : t | P%B) U%VS) (only parsing) : vspace_scope.\n(*Parsing-only notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each index i of a specified type t.*)\nNotation \"\\bigcap_ ( i : t ) U\" :=\n (\\big[capv/fullv]_(i : t) U%VS) (only parsing) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each natural number index i that is less than n and satisfies a boolean predicate P.*)\nNotation \"\\bigcap_ ( i < n | P ) U\" :=\n (\\big[capv/fullv]_(i < n | P%B) U%VS) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each natural number index i that is less than n.*)\nNotation \"\\bigcap_ ( i < n ) U\" :=\n (\\big[capv/fullv]_(i < n) U%VS) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each index i in a given finite set A that satisfies a boolean predicate P.*)\nNotation \"\\bigcap_ ( i 'in' A | P ) U\" :=\n (\\big[capv/fullv]_(i in A | P%B) U%VS) : vspace_scope.\n(*Notation for computing the intersection of vector subspaces, where each subspace is generated by an expression U for each index i in a given finite set A.*)\nNotation \"\\bigcap_ ( i 'in' A ) U\" :=\n (\\big[capv/fullv]_(i in A) U%VS) : vspace_scope.\n\nSection VectorTheory.\n\nVariables (K : fieldType) (vT : vectType K).\nImplicit Types (a : K) (u v w : vT) (X Y : seq vT) (U V W : {vspace vT}).\n\n(*A local, parse-only notation for the relation that checks if one vector subspace is a subspace of another.*)\nLocal Notation subV := (@subsetv K vT) (only parsing).\n(*A local, parse-only notation for the operation that computes the sum of two vector subspaces, defined as the smallest subspace containing both.*)\nLocal Notation addV := (@addv K vT) (only parsing).\n(*A local, parse-only notation for the operation that computes the intersection of two vector subspaces, defined as the largest subspace contained within both.*)\nLocal Notation capV := (@capv K vT) (only parsing).\n\n(*This lemma states that two vector subspaces are equal if and only if their corresponding matrix representations are equal.*)\nLet vs2mxP U V : reflect (U = V) (vs2mx U == vs2mx V)%MS.\n\n(*This lemma states that a vector is an element of a vector subspace if and only if the vector's row representation is a fixed point of the projection matrix associated with the subspace.*)\nLet memvK v U : (v \\in U) = (v2r v <= vs2mx U)%MS.\n\n(*This lemma states that a vector obtained by converting a given row vector is an element of a vector subspace if and only if the original row vector is a fixed point of the projection matrix associated with the subspace.*)\nLet mem_r2v rv U : (r2v rv \\in U) = (rv <= vs2mx U)%MS.\n\n(*This lemma states that the matrix representation of the zero vector subspace is the zero matrix.*)\nLet vs2mx0 : @vs2mx K vT 0 = 0.\n\n(*This lemma states that the matrix representation of the sum of two vector spaces is equal to the sum of the matrix representations of each individual vector space.*)\nLet vs2mxD U V : vs2mx (U + V) = (vs2mx U + vs2mx V)%MS.\n\n(*This definition establishes that the conversion from a finite sum of vector spaces into a matrix is a homomorphism, meaning the matrix of the sum is the sum of the matrices.*)\nLet vs2mx_sum := big_morph _ vs2mxD vs2mx0.\n\n(*This lemma states that the matrix representation of the intersection of two vector spaces is equal to the intersection of their matrix representations.*)\nLet vs2mxI U V : vs2mx (U :&: V) = (vs2mx U :&: vs2mx V)%MS.\n\n(*This lemma states that the matrix representation of the full vector space is the identity matrix.*)\nLet vs2mxF : vs2mx {:vT} = 1%:M.\n\n(*This definition asserts that the i-th row of the matrix constructed from an n-tuple of vectors is equivalent to the row representation of the i-th vector in the tuple.*)\nLet row_b2mx n (X : n.-tuple vT) i : row i (b2mx X) = v2r X`_i.\n\n(*This definition shows that the vector space spanned by a tuple of vectors is identical to the vector space represented by the matrix constructed from that same tuple.*)\nLet span_b2mx n (X : n.-tuple vT) : span X = mx2vs (b2mx X).\n\n(*This definition asserts that the linear combination of vectors from a tuple, using coefficients from a given row vector, is equal to the vector obtained by multiplying that row vector with the matrix representation of the tuple.*)\nLet mul_b2mx n (X : n.-tuple vT) (rk : 'rV_n) :\n \\sum_i rk 0 i *: X`_i = r2v (rk *m b2mx X).\n\n(*This definition states that a linear combination of vectors from a tuple, with coefficients given by a function over the indices, is equivalent to the vector resulting from multiplying a row vector, constructed from the coefficient function, with the matrix representation of the tuple.*)\nLet lin_b2mx n (X : n.-tuple vT) k :\n \\sum_(i < n) k i *: X`_i = r2v (\\row_i k i *m b2mx X).\n\n(*This definition states that a tuple of vectors is linearly independent if and only if the rows of the matrix constructed from that tuple are linearly independent.*)\nLet free_b2mx n (X : n.-tuple vT) : free X = row_free (b2mx X).\n\n(*This lemma states that a vector is an element of a vector space if and only if the one-dimensional subspace spanned by that vector is a subspace of the given vector space.*)\nLemma memvE v U : (v \\in U) = (<[v]> <= U)%VS. \n\n(*This lemma provides a reflection property, stating that a vector is a member of the one-dimensional subspace spanned by a second vector if and only if the first vector is a scalar multiple of the second.*)\nLemma vlineP v1 v2 : reflect (exists k, v1 = k *: v2) (v1 \\in <[v2]>)%VS.\n\n(*This fact asserts that any vector space is closed under the module operations, namely vector addition and scalar multiplication.*)\nFact memv_submod_closed U : submod_closed U.\n\nHB.instance Definition _ (U : {vspace vT}) :=\n GRing.isSubmodClosed.Build K vT (pred_of_vspace U) (memv_submod_closed U).\n\n(*This lemma states that the zero vector is a member of any vector space.*)\nLemma mem0v U : 0 \\in U. \n(*This lemma states that the additive inverse of a vector is in a given vector space if and only if the original vector is also in that vector space.*)\nLemma memvN U v : (- v \\in U) = (v \\in U). \n(*This lemma states that any vector space is closed under addition, meaning the sum of any two vectors from the space is also in the space.*)\nLemma memvD U : {in U &, forall u v, u + v \\in U}. \n(*This lemma states that any vector space is closed under subtraction, meaning the difference of any two vectors from the space is also in the space.*)\nLemma memvB U : {in U &, forall u v, u - v \\in U}. \n(*This lemma states that any vector space is closed under scalar multiplication, meaning the product of any scalar and any vector from the space is also in the space.*)\nLemma memvZ U k : {in U, forall v, k *: v \\in U}. \n\n(*This lemma states that if every vector in an indexed family satisfying a given predicate belongs to a certain vector space, then any finite sum of these vectors also belongs to that same vector space.*)\nLemma memv_suml I r (P : pred I) vs U :\n (forall i, P i -> vs i \\in U) -> \\sum_(i <- r | P i) vs i \\in U.\n\n(*This lemma states that any vector is a member of the one-dimensional subspace it spans.*)\nLemma memv_line u : u \\in <[u]>%VS.\n\n(*This lemma provides a reflection property, stating that one vector space is a subspace of another if and only if the set of vectors of the first is a subset of the set of vectors of the second.*)\nLemma subvP U V : reflect {subset U <= V} (U <= V)%VS.\n\n(*This lemma states that the subspace relation is reflexive, meaning any vector space is a subspace of itself.*)\nLemma subvv U : (U <= U)%VS. \nHint Resolve subvv : core.\n\n(*This lemma states that the subspace relation is transitive.*)\nLemma subv_trans : transitive subV.\n\n(*This lemma states that the subspace relation is antisymmetric, meaning if two vector spaces are subspaces of each other, they must be equal.*)\nLemma subv_anti : antisymmetric subV.\n\n(*This lemma states that two vector spaces are equal if and only if each is a subspace of the other.*)\nLemma eqEsubv U V : (U == V) = (U <= V <= U)%VS.\n\n(*This lemma states that two vector spaces are equivalent as structures if and only if they are equal as sets of vectors.*)\nLemma vspaceP U V : U =i V <-> U = V.\n\n(*This lemma provides a reflection property for the negation of the subspace relation, stating that one vector space is not a subspace of another if and only if there exists a vector that is in the first space but not in the second.*)\nLemma subvPn {U V} : reflect (exists2 u, u \\in U & u \\notin V) (~~ (U <= V)%VS).\n\n(*This lemma states that the trivial vector space, containing only the zero vector, is a subspace of any other vector space.*)\nLemma sub0v U : (0 <= U)%VS.\n\n(*This lemma states that if a vector space is a subspace of the trivial vector space, then it must be equal to the trivial vector space.*)\nLemma subv0 U : (U <= 0)%VS = (U == 0%VS).\n\n(*This lemma states that a vector is a member of the trivial vector space if and only if that vector is the zero vector.*)\nLemma memv0 v : v \\in 0%VS = (v == 0).\n\n(*This lemma states that any vector space is a subspace of the full, ambient vector space.*)\nLemma subvf U : (U <= fullv)%VS. \n(*This lemma states that any vector is a member of the full vector space.*)\nLemma memvf v : v \\in fullv. \n\n(*This lemma states that the representative vector chosen from a subspace is a member of that subspace.*)\nLemma memv_pick U : vpick U \\in U. \n\n(*This lemma states that the representative vector chosen from a subspace is the zero vector if and only if the subspace itself is the zero subspace.*)\nLemma vpick0 U : (vpick U == 0) = (U == 0%VS).\n\n(*This lemma states that the sum of two subspaces is included in a third subspace if and only if each of the two subspaces is individually included in the third one.*)\nLemma subv_add U V W : (U + V <= W)%VS = (U <= W)%VS && (V <= W)%VS.\n\n(*This lemma states that subspace addition is monotonic with respect to subspace inclusion; if a first subspace is included in a second, and a third subspace is included in a fourth, then the sum of the first and third subspaces is included in the sum of the second and fourth.*)\nLemma addvS U1 U2 V1 V2 : (U1 <= U2 -> V1 <= V2 -> U1 + V1 <= U2 + V2)%VS.\n\n(*This lemma states that any subspace is included in the sum of itself and another subspace.*)\nLemma addvSl U V : (U <= U + V)%VS.\n\n(*This lemma states that any subspace is included in the sum of another subspace and itself.*)\nLemma addvSr U V : (V <= U + V)%VS.\n\n(*This lemma states that the addition of subspaces is a commutative operation.*)\nLemma addvC : commutative addV.\n\n(*This lemma states that the addition of subspaces is an associative operation.*)\nLemma addvA : associative addV.\n\n(*This lemma states that the sum of a first subspace and a second subspace is equal to the first subspace if and only if the second subspace is included in the first.*)\nLemma addv_idPl {U V}: reflect (U + V = U)%VS (V <= U)%VS.\n\n(*This lemma states that the sum of a first subspace and a second subspace is equal to the second subspace if and only if the first subspace is included in the second.*)\nLemma addv_idPr {U V} : reflect (U + V = V)%VS (U <= V)%VS.\n\n(*This lemma states that subspace addition is an idempotent operation, meaning the sum of a subspace with itself is the subspace itself.*)\nLemma addvv : idempotent_op addV.\n\n(*This lemma states that the zero subspace is the left identity element for subspace addition.*)\nLemma add0v : left_id 0%VS addV.\n\n(*This lemma states that the zero subspace is the right identity element for subspace addition.*)\nLemma addv0 : right_id 0%VS addV.\n\n(*This lemma states that the full vector space is a left absorbing element for subspace addition, meaning the sum of the full space and any other subspace is the full space.*)\nLemma sumfv : left_zero fullv addV.\n\n(*This lemma states that the full vector space is a right absorbing element for subspace addition, meaning the sum of any subspace and the full space is the full space.*)\nLemma addvf : right_zero fullv addV.\n\nHB.instance Definition _ := Monoid.isComLaw.Build {vspace vT} 0%VS addv\n addvA addvC add0v.\n\n(*This lemma states that if a first vector is a member of a first subspace and a second vector is a member of a second subspace, then the sum of the two vectors is a member of the sum of the two subspaces.*)\nLemma memv_add u v U V : u \\in U -> v \\in V -> u + v \\in (U + V)%VS.\n\n(*This lemma states that a vector is a member of the sum of two subspaces if and only if it can be expressed as the sum of a vector from the first subspace and a vector from the second subspace.*)\nLemma memv_addP {w U V} :\n reflect (exists2 u, u \\in U & exists2 v, v \\in V & w = u + v)\n (w \\in U + V)%VS.\n\nSection BigSum.\nVariable I : finType.\nImplicit Type P : pred I.\n\n(*This lemma states that if a subspace is included in one of the constituent subspaces in an indexed sum, then it is also included in the total sum of subspaces.*)\nLemma sumv_sup i0 P U Vs :\n P i0 -> (U <= Vs i0)%VS -> (U <= \\sum_(i | P i) Vs i)%VS.\n\nArguments sumv_sup i0 [P U Vs].\n\n(*This lemma states that an indexed sum of subspaces is included in another subspace if and only if every subspace in the sum is individually included in that other subspace.*)\nLemma subv_sumP {P Us V} :\n reflect (forall i, P i -> Us i <= V)%VS (\\sum_(i | P i) Us i <= V)%VS.\n\n(*This lemma states that if for each index in a given family, a vector is a member of the corresponding subspace, then the sum of all such vectors is a member of the sum of all corresponding subspaces.*)\nLemma memv_sumr P vs (Us : I -> {vspace vT}) :\n (forall i, P i -> vs i \\in Us i) ->\n \\sum_(i | P i) vs i \\in (\\sum_(i | P i) Us i)%VS.\n\n(*This lemma states that a vector is a member of an indexed sum of subspaces if and only if it can be expressed as a sum of vectors where each vector in the sum is drawn from the corresponding subspace in the indexed family.*)\nLemma memv_sumP {P} {Us : I -> {vspace vT}} {v} :\n reflect (exists2 vs, forall i, P i -> vs i \\in Us i\n & v = \\sum_(i | P i) vs i)\n (v \\in \\sum_(i | P i) Us i)%VS.\n\nEnd BigSum.\n\n(*This lemma states that a subspace is included in the intersection of two other subspaces if and only if it is included in each of those two subspaces individually.*)\nLemma subv_cap U V W : (U <= V :&: W)%VS = (U <= V)%VS && (U <= W)%VS.\n\n(*This lemma states that subspace intersection is monotonic with respect to subspace inclusion; if a first subspace is included in a second, and a third subspace is included in a fourth, then the intersection of the first and third subspaces is included in the intersection of the second and fourth.*)\nLemma capvS U1 U2 V1 V2 : (U1 <= U2 -> V1 <= V2 -> U1 :&: V1 <= U2 :&: V2)%VS.\n\n(*This lemma states that the intersection of two subspaces is included in the first subspace.*)\nLemma capvSl U V : (U :&: V <= U)%VS.\n\n(*This lemma states that the intersection of two subspaces is included in the second subspace.*)\nLemma capvSr U V : (U :&: V <= V)%VS.\n\n(*This lemma states that the intersection of subspaces is a commutative operation.*)\nLemma capvC : commutative capV.\n\n(*This lemma states that the intersection of subspaces is an associative operation.*)\nLemma capvA : associative capV.\n\n(*This lemma states that the intersection of a first subspace and a second subspace is equal to the first subspace if and only if the first subspace is included in the second.*)\nLemma capv_idPl {U V} : reflect (U :&: V = U)%VS (U <= V)%VS.\n\n(*This lemma states that the intersection of a first subspace and a second subspace is equal to the second subspace if and only if the second subspace is included in the first.*)\nLemma capv_idPr {U V} : reflect (U :&: V = V)%VS (V <= U)%VS.\n\n(*This lemma states that the intersection of a vector subspace with itself is the same subspace.*)\nLemma capvv : idempotent_op capV.\n\n(*This lemma states that the intersection of the zero vector subspace with any other vector subspace is the zero vector subspace.*)\nLemma cap0v : left_zero 0%VS capV.\n\n(*This lemma states that the intersection of any vector subspace with the zero vector subspace is the zero vector subspace.*)\nLemma capv0 : right_zero 0%VS capV.\n\n(*This lemma states that the intersection of the entire vector space with any of its subspaces is that subspace itself.*)\nLemma capfv : left_id fullv capV.\n\n(*This lemma states that the intersection of any vector subspace with the entire vector space is that subspace itself.*)\nLemma capvf : right_id fullv capV.\n\nHB.instance Definition _ := Monoid.isComLaw.Build {vspace vT} fullv capv\n capvA capvC capfv.\n\n(*This lemma states that a vector belongs to the intersection of two vector subspaces if and only if it belongs to both subspaces individually.*)\nLemma memv_cap w U V : (w \\in U :&: V)%VS = (w \\in U) && (w \\in V).\n\n(*This lemma provides a boolean reflection of the property that a vector is a member of the intersection of two vector subspaces, stating that this is equivalent to the logical conjunction of the vector being a member of each subspace.*)\nLemma memv_capP {w U V} : reflect (w \\in U /\\ w \\in V) (w \\in U :&: V)%VS.\n\n(*This lemma states a modular law for vector subspaces: if a first subspace is contained within a third subspace, then the sum of the first subspace and the intersection of a second subspace with the third is equal to the intersection of the sum of the first and second subspaces with the third subspace.*)\nLemma vspace_modl U V W : (U <= W -> U + (V :&: W) = (U + V) :&: W)%VS.\n\n(*This lemma states a modular law for vector subspaces: if a third subspace is contained within a first subspace, then the sum of the intersection of the first and a second subspace with the third is equal to the intersection of the first subspace with the sum of the second and third subspaces.*)\nLemma vspace_modr U V W : (W <= U -> (U :&: V) + W = U :&: (V + W))%VS.\n\nSection BigCap.\nVariable I : finType.\nImplicit Type P : pred I.\n\n(*This lemma states that if at least one vector subspace in a family of subspaces satisfying a given predicate is contained within another subspace, then the intersection of the entire family is also contained within that other subspace.*)\nLemma bigcapv_inf i0 P Us V :\n P i0 -> (Us i0 <= V -> \\bigcap_(i | P i) Us i <= V)%VS.\n\n(*This lemma provides a boolean reflection for the property that a vector subspace is contained in the intersection of a family of subspaces, stating that this is equivalent to the subspace being contained in every subspace of the family.*)\nLemma subv_bigcapP {P U Vs} :\n reflect (forall i, P i -> U <= Vs i)%VS (U <= \\bigcap_(i | P i) Vs i)%VS.\n\nEnd BigCap.\n\n(*This lemma states that the sum of a vector subspace and its complement is equal to the entire vector space.*)\nLemma addv_complf U : (U + U^C)%VS = fullv.\n\n(*This lemma states that the intersection of a vector subspace and its complement is the zero vector subspace.*)\nLemma capv_compl U : (U :&: U^C = 0)%VS.\n\n(*This lemma states that the difference of two vector subspaces is a subspace of the first subspace.*)\nLemma diffvSl U V : (U :\\: V <= U)%VS.\n\n(*This lemma states that the intersection of the difference of two vector subspaces with the second subspace is the zero vector subspace.*)\nLemma capv_diff U V : ((U :\\: V) :&: V = 0)%VS.\n\n(*This lemma states that a vector subspace is equal to the sum of its difference with a second subspace and its intersection with that same second subspace.*)\nLemma addv_diff_cap U V : (U :\\: V + U :&: V)%VS = U.\n\n(*This lemma states that the sum of the difference of two vector subspaces with the second subspace is equal to the sum of the two original subspaces.*)\nLemma addv_diff U V : (U :\\: V + V = U + V)%VS.\n\n(*This lemma states that the dimension of the zero vector subspace is zero.*)\nLemma dimv0 : \\dim (0%VS : {vspace vT}) = 0.\n\n(*This lemma states that a vector subspace has a dimension of zero if and only if it is the zero vector subspace.*)\nLemma dimv_eq0 U : (\\dim U == 0) = (U == 0%VS).\n\n(*This lemma states that the dimension of the entire vector space, when considered as a subspace, is equal to the dimension of the ambient vector space type.*)\nLemma dimvf : \\dim {:vT} = dim vT.\n\n(*This lemma states that the dimension of the vector subspace spanned by a single vector is one if the vector is non-zero, and zero otherwise.*)\nLemma dim_vline v : \\dim <[v]> = (v != 0).\n\n(*This lemma states that if a vector subspace is contained within another, its dimension is less than or equal to the dimension of the containing subspace.*)\nLemma dimvS U V : (U <= V)%VS -> \\dim U <= \\dim V.\n\n(*This lemma states that for two vector subspaces where the first is contained in the second, the condition that the dimension of the second is at most the dimension of the first is equivalent to the second being a subspace of the first.*)\nLemma dimv_leqif_sup U V : (U <= V)%VS -> \\dim U <= \\dim V ?= iff (V <= U)%VS.\n\n(*This lemma states that for a vector subspace contained within another, the condition that the dimension of the larger subspace is less than or equal to the dimension of the smaller subspace is equivalent to the two subspaces being equal.*)\nLemma dimv_leqif_eq U V : (U <= V)%VS -> \\dim U <= \\dim V ?= iff (U == V).\n\n(*This lemma states that two vector subspaces are equal if and only if the first is a subspace of the second and the dimension of the second is less than or equal to the dimension of the first.*)\nLemma eqEdim U V : (U == V) = (U <= V)%VS && (\\dim V <= \\dim U).\n\n(*This lemma states that the dimension of the complement of a vector subspace is equal to the dimension of the entire space minus the dimension of the subspace.*)\nLemma dimv_compl U : \\dim U^C = (\\dim {:vT} - \\dim U)%N.\n\n(*This lemma states that the dimension of a vector subspace is equal to the sum of the dimension of its intersection with another subspace and the dimension of its difference with that same other subspace.*)\nLemma dimv_cap_compl U V : (\\dim (U :&: V) + \\dim (U :\\: V))%N = \\dim U.\n\n(*This lemma states the dimension formula for the sum and intersection of two vector subspaces: the sum of the dimension of their sum and the dimension of their intersection equals the sum of their individual dimensions.*)\nLemma dimv_sum_cap U V : (\\dim (U + V) + \\dim (U :&: V) = \\dim U + \\dim V)%N.\n\n(*This lemma states that if two vector subspaces intersect only at the zero vector, then the dimension of their sum is the sum of their individual dimensions.*)\nLemma dimv_disjoint_sum U V :\n (U :&: V = 0)%VS -> \\dim (U + V) = (\\dim U + \\dim V)%N.\n\n(*This lemma states that the dimension of the sum of two vector subspaces is equal to the sum of their dimensions if and only if their intersection is the zero vector subspace.*)\nLemma dimv_add_leqif U V :\n \\dim (U + V) <= \\dim U + \\dim V ?= iff (U :&: V <= 0)%VS.\n\n(*This lemma states that the difference of two vector spaces is the zero vector space if and only if the first vector space is a subspace of the second.*)\nLemma diffv_eq0 U V : (U :\\: V == 0)%VS = (U <= V)%VS.\n\n(*This lemma states that the dimension of the sum of a family of vector spaces is less than or equal to the sum of the dimensions of those vector spaces.*)\nLemma dimv_leq_sum I r (P : pred I) (Us : I -> {vspace vT}) :\n \\dim (\\sum_(i <- r | P i) Us i) <= \\sum_(i <- r | P i) \\dim (Us i).\n\nSection SumExpr.\n\n(*This structure represents an expression for a sum of vector spaces, bundling a vector space with a natural number that serves as an upper bound for its dimension.*)\nStructure addv_expr := Sumv {\n(**)\n addv_val :> wrapped {vspace vT};\n(**)\n addv_dim : wrapped nat;\n _ : mxsum_spec (vs2mx (unwrap addv_val)) (unwrap addv_dim)\n}.\n\n(*This definition extracts the proof component from an additive vector space expression, which certifies that the stored natural number is an upper bound for the dimension of the contained vector space.*)\nDefinition vs2mx_sum_expr_subproof (S : addv_expr) :\n mxsum_spec (vs2mx (unwrap S)) (unwrap (addv_dim S)).\n\nCanonical vs2mx_sum_expr S := ProperMxsumExpr (vs2mx_sum_expr_subproof S).\n\nCanonical trivial_addv U := @Sumv (Wrap U) (Wrap (\\dim U)) (TrivialMxsum _).\n\n(*This structure represents a well-formed expression for a sum of vector spaces, pairing a vector space directly with a natural number that is proven to be an upper bound for its dimension.*)\nStructure proper_addv_expr := ProperSumvExpr {\n(**)\n proper_addv_val :> {vspace vT};\n(**)\n proper_addv_dim :> nat;\n _ : mxsum_spec (vs2mx proper_addv_val) proper_addv_dim\n}.\n\n(*This definition extracts the proof component from a proper additive vector space expression, which guarantees that the stored natural number is an upper bound on the dimension of the contained vector space.*)\nDefinition proper_addvP (S : proper_addv_expr) :=\n let: ProperSumvExpr _ _ termS := S return mxsum_spec (vs2mx S) S in termS.\n\nCanonical proper_addv (S : proper_addv_expr) :=\n @Sumv (wrap (S : {vspace vT})) (wrap (S : nat)) (proper_addvP S).\n\nSection Binary.\nVariables S1 S2 : addv_expr.\n(*This fact provides the proof that for two additive vector space expressions, the sum of their dimension bounds is a valid dimension bound for the sum of their corresponding vector spaces.*)\nFact binary_addv_subproof :\n mxsum_spec (vs2mx (unwrap S1 + unwrap S2))\n (unwrap (addv_dim S1) + unwrap (addv_dim S2)).\n\nCanonical binary_addv_expr := ProperSumvExpr binary_addv_subproof.\nEnd Binary.\n\nSection Nary.\nVariables (I : Type) (r : seq I) (P : pred I) (S_ : I -> addv_expr).\n(*This fact provides the proof that for a family of additive vector space expressions, the sum of their dimension bounds is a valid dimension bound for the sum of their corresponding vector spaces.*)\nFact nary_addv_subproof :\n mxsum_spec (vs2mx (\\sum_(i <- r | P i) unwrap (S_ i)))\n (\\sum_(i <- r | P i) unwrap (addv_dim (S_ i))).\n\nCanonical nary_addv_expr := ProperSumvExpr nary_addv_subproof.\nEnd Nary.\n\n(*This definition specifies that a sum of vector spaces is direct if the dimension of the resulting vector space is equal to the sum of the dimensions of the individual vector spaces.*)\nDefinition directv_def S of phantom {vspace vT} (unwrap (addv_val S)) :=\n \\dim (unwrap S) == unwrap (addv_dim S).\n\nEnd SumExpr.\n\nLocal Notation directv A := (directv_def (Phantom {vspace _} A%VS)).\n\n(*This lemma states that an additive vector space expression is considered direct if and only if the actual dimension of its vector space is equal to its stored dimension bound.*)\nLemma directvE (S : addv_expr) :\n directv (unwrap S) = (\\dim (unwrap S) == unwrap (addv_dim S)).\n\n(*This lemma provides a boolean reflection, establishing that a proper additive vector space expression is direct if and only if the dimension of its vector space component is equal to its natural number component.*)\nLemma directvP {S : proper_addv_expr} : reflect (\\dim S = S :> nat) (directv S).\n\n(*This lemma states that an additive vector space expression created from a single vector space is always direct.*)\nLemma directv_trivial U : directv (unwrap (@trivial_addv U)).\n\n(*This lemma states that the dimension of the vector space in an additive expression is less than or equal to its stored dimension bound, and asserts that equality holds if and only if the expression is direct.*)\nLemma dimv_sum_leqif (S : addv_expr) :\n \\dim (unwrap S) <= unwrap (addv_dim S) ?= iff directv (unwrap S).\n\n(*This lemma states that an additive vector space expression is direct if and only if the dimension of its vector space is greater than or equal to its stored dimension bound.*)\nLemma directvEgeq (S : addv_expr) :\n directv (unwrap S) = (\\dim (unwrap S) >= unwrap (addv_dim S)).\n\nSection BinaryDirect.\n\n(*This lemma provides conditions for the sum of two vector spaces, formed from additive expressions, to be a direct sum. It states that the sum is direct if and only if both original expressions are direct and the intersection of the two vector spaces is the trivial vector space.*)\nLemma directv_addE (S1 S2 : addv_expr) :\n directv (unwrap S1 + unwrap S2)\n = [&& directv (unwrap S1), directv (unwrap S2)\n & unwrap S1 :&: unwrap S2 == 0]%VS.\n\n(*This lemma provides a boolean reflection, establishing that the sum of two vector spaces is direct if and only if their intersection is the zero vector space.*)\nLemma directv_addP {U V} : reflect (U :&: V = 0)%VS (directv (U + V)).\n\n(*This lemma provides a boolean reflection establishing that the sum of two vector spaces is direct if and only if every vector in the sum has a unique representation as a sum of a vector from the first space and a vector from the second space.*)\nLemma directv_add_unique {U V} :\n reflect (forall u1 u2 v1 v2, u1 \\in U -> u2 \\in U -> v1 \\in V -> v2 \\in V ->\n (u1 + v1 == u2 + v2) = ((u1, v1) == (u2, v2)))\n (directv (U + V)).\n\nEnd BinaryDirect.\n\nSection NaryDirect.\n\nContext {I : finType} {P : pred I}.\n\n(*This lemma provides a boolean reflection for a finite sum of vector spaces, stating that the sum is direct if and only if each vector space in the family has a trivial intersection with the sum of all other spaces in the family.*)\nLemma directv_sumP {Us : I -> {vspace vT}} :\n reflect (forall i, P i -> Us i :&: (\\sum_(j | P j && (j != i)) Us j) = 0)%VS\n (directv (\\sum_(i | P i) Us i)).\n\n(*This lemma provides a boolean reflection establishing that a sum of additive vector space expressions is direct if and only if each individual expression is direct and the sum of their underlying vector spaces is also a direct sum.*)\nLemma directv_sumE {Ss : I -> addv_expr} (xunwrap := unwrap) :\n reflect [/\\ forall i, P i -> directv (unwrap (Ss i))\n & directv (\\sum_(i | P i) xunwrap (Ss i))]\n (directv (\\sum_(i | P i) unwrap (Ss i))).\n\n(*This lemma provides a boolean reflection for a finite sum of vector spaces, stating that the sum is direct if and only if the only way to write the zero vector as a sum of vectors from each space is by choosing the zero vector from each space.*)\nLemma directv_sum_independent {Us : I -> {vspace vT}} :\n reflect (forall us,\n (forall i, P i -> us i \\in Us i) -> \\sum_(i | P i) us i = 0 ->\n (forall i, P i -> us i = 0))\n (directv (\\sum_(i | P i) Us i)).\n\n(*This lemma provides a boolean reflection stating that a finite sum of vector spaces is direct if and only if any vector in the sum has a unique decomposition into a sum of vectors, one from each of the constituent spaces.*)\nLemma directv_sum_unique {Us : I -> {vspace vT}} :\n reflect (forall us vs,\n (forall i, P i -> us i \\in Us i) ->\n (forall i, P i -> vs i \\in Us i) ->\n (\\sum_(i | P i) us i == \\sum_(i | P i) vs i)\n = [forall (i | P i), us i == vs i])\n (directv (\\sum_(i | P i) Us i)).\n\nEnd NaryDirect.\n\n(*This lemma states that any vector belonging to a given set of vectors also belongs to the vector space spanned by that set.*)\nLemma memv_span X v : v \\in X -> v \\in <>%VS.\n\n(*This lemma states that a vector is an element of the vector space spanned by itself.*)\nLemma memv_span1 v : v \\in <<[:: v]>>%VS.\n\n(*This lemma states that the dimension of the vector space spanned by a finite sequence of vectors is less than or equal to the number of vectors in that sequence.*)\nLemma dim_span X : \\dim <> <= size X.\n\n(*This lemma provides a boolean reflection, establishing that the vector space spanned by a set of vectors is a subspace of another vector space if and only if all vectors in the set are contained within that other space.*)\nLemma span_subvP {X U} : reflect {subset X <= U} (<> <= U)%VS.\n\n(*This lemma states that if a first set of vectors is a subset of a second set of vectors, then the vector space spanned by the first set is a subspace of the vector space spanned by the second set.*)\nLemma sub_span X Y : {subset X <= Y} -> (<> <= <>)%VS.\n\n(*This lemma states that if two collections of vectors contain the same elements, then the vector spaces they span are equal.*)\nLemma eq_span X Y : X =i Y -> (<> = <>)%VS.\n\n(*This lemma states that the vector space spanned by a set of vectors is equal to the sum of the one-dimensional spaces spanned by each individual vector in the set.*)\nLemma span_def X : span X = (\\sum_(u <- X) <[u]>)%VS.\n\n(*This lemma states that the vector space spanned by an empty collection of vectors is the trivial, zero-dimensional vector space.*)\nLemma span_nil : (<> = 0)%VS.\n\n(*This lemma states that the vector space spanned by a singleton sequence containing a vector is equal to the one-dimensional space spanned by that vector alone.*)\nLemma span_seq1 v : (<<[:: v]>> = <[v]>)%VS.\n\n(*This lemma states that the vector space spanned by a finite sequence of vectors constructed by prepending a vector to another sequence is equal to the sum of the subspace spanned by the prepended vector and the subspace spanned by the original sequence.*)\nLemma span_cons v X : (<> = <[v]> + <>)%VS.\n\n(*This lemma states that the vector space spanned by the concatenation of two finite sequences of vectors is equal to the sum of the vector spaces spanned by each individual sequence.*)\nLemma span_cat X Y : (<> = <> + <>)%VS.\n\n(*This definition provides the explicit formula for computing the coordinate of a given vector with respect to a given finite sequence of vectors, at a specified index. The computation is expressed using matrix operations, involving the pseudo-inverse of the matrix formed by the sequence of vectors.*)\nDefinition coord_expanded_def n (X : n.-tuple vT) i v :=\n (v2r v *m pinvmx (b2mx X)) 0 i.\n(*This definition provides a function that computes the coordinate of a given vector with respect to a finite sequence of vectors at a specified index. The definition is locked to ensure controlled access to its implementation.*)\nDefinition coord := locked_with span_key coord_expanded_def.\nCanonical coord_unlockable := [unlockable fun coord].\n\n(*This fact asserts that the value returned by the coordinate function, which computes the coordinate of a vector with respect to a finite sequence of vectors at a given index, is a scalar quantity.*)\nFact coord_is_scalar n (X : n.-tuple vT) i : scalar (coord X i).\n\n(*This lemma states that if a vector belongs to the vector space spanned by a finite sequence of vectors, then that vector is equal to the linear combination of the vectors in the sequence, using its own coordinates with respect to that sequence as the scalar coefficients.*)\nLemma coord_span n (X : n.-tuple vT) v :\n v \\in span X -> v = \\sum_i coord X i v *: X`_i.\n\n(*This lemma states that the coordinate of any vector with respect to the empty sequence of vectors is always zero, for any given index.*)\nLemma coord0 i v : coord [tuple 0] i v = 0.\n\n(*This lemma states that the empty sequence of vectors is linearly independent.*)\nLemma nil_free : free (Nil vT).\n\n(*This lemma states that a finite sequence containing a single vector is linearly independent if and only if that vector is not the zero vector.*)\nLemma seq1_free v : free [:: v] = (v != 0).\n\n(*This lemma states that if two finite sequences of vectors are permutations of one another, then their properties of being linearly independent are equivalent.*)\nLemma perm_free X Y : perm_eq X Y -> free X = free Y.\n\n(*This lemma states that a finite sequence of vectors is linearly independent if and only if the zero vector is not a member of the sequence and the sum of the one-dimensional subspaces spanned by each vector in the sequence is a direct sum.*)\nLemma free_directv X : free X = (0 \\notin X) && directv (\\sum_(v <- X) <[v]>).\n\n(*This lemma states that if a finite sequence of vectors is linearly independent, then any vector that is an element of that sequence must not be the zero vector.*)\nLemma free_not0 v X : free X -> v \\in X -> v != 0.\n\n(*This lemma provides the boolean reflection of the definition of linear independence for a finite sequence of vectors. It states that the sequence is linearly independent if and only if for any sequence of scalars, if the linear combination of the vectors with these scalars as coefficients equals the zero vector, then all the scalars must be zero.*)\nLemma freeP n (X : n.-tuple vT) :\n reflect (forall k, \\sum_(i < n) k i *: X`_i = 0 -> (forall i, k i = 0))\n (free X).\n\n(*This lemma states that for a linearly independent finite sequence of vectors, the coordinate of the vector at a given index with respect to the sequence itself, evaluated at another index, is equal to one if the indices are the same, and zero otherwise.*)\nLemma coord_free n (X : n.-tuple vT) (i j : 'I_n) :\n free X -> coord X j (X`_i) = (i == j)%:R.\n\n(*This lemma states that for a linearly independent finite sequence of vectors, the coordinate at a given index of a vector formed by a linear combination of the sequence's elements is equal to the scalar coefficient corresponding to that same index in the linear combination.*)\nLemma coord_sum_free n (X : n.-tuple vT) k j :\n free X -> coord X j (\\sum_(i < n) k i *: X`_i) = k j.\n\n(*This lemma states that the concatenation of two finite sequences of vectors is linearly independent if and only if both individual sequences are linearly independent and the sum of the vector spaces they span is a direct sum.*)\nLemma cat_free X Y :\n free (X ++ Y) = [&& free X, free Y & directv (<> + <>)].\n\n(*This lemma states that if the concatenation of two finite sequences of vectors is linearly independent, then the first sequence in the concatenation is also linearly independent.*)\nLemma catl_free Y X : free (X ++ Y) -> free X.\n\n(*This lemma states that if the concatenation of two finite sequences of vectors is linearly independent, then the second sequence in the concatenation is also linearly independent.*)\nLemma catr_free X Y : free (X ++ Y) -> free Y.\n\n(*This lemma states that if a finite sequence of vectors is linearly independent, then any subsequence formed by filtering the original sequence with a given predicate is also linearly independent.*)\nLemma filter_free p X : free X -> free (filter p X).\n\n(*This lemma states that a finite sequence of vectors formed by prepending a vector to an existing sequence is linearly independent if and only if the original sequence is linearly independent and the prepended vector does not belong to the vector space spanned by the original sequence.*)\nLemma free_cons v X : free (v :: X) = (v \\notin <>)%VS && free X.\n\n(*This lemma states that a finite sequence of vectors is linearly independent if and only if for every index, the vector at that index does not belong to the vector space spanned by the vectors that follow it in the sequence.*)\nLemma freeE n (X : n.-tuple vT) :\n free X = [forall i : 'I_n, X`_i \\notin <>%VS].\n\n(*This lemma states that a finite sequence of vectors is linearly dependent if and only if there exists an index such that the vector at that index belongs to the vector space spanned by the vectors that follow it in the sequence.*)\nLemma freeNE n (X : n.-tuple vT) :\n ~~ free X = [exists i : 'I_n, X`_i \\in <>%VS].\n\n(*This lemma states that any linearly independent finite sequence of vectors must not contain any duplicate elements.*)\nLemma free_uniq X : free X -> uniq X.\n\n(*This lemma states that if a finite sequence of vectors is linearly independent and another vector is in the space spanned by this sequence, then there exists a unique family of scalar coefficients such that the vector is equal to the linear combination of the sequence's vectors with these coefficients.*)\nLemma free_span X v (sumX := fun k => \\sum_(x <- X) k x *: x) :\n free X -> v \\in <>%VS ->\n {k | v = sumX k & forall k1, v = sumX k1 -> {in X, k1 =1 k}}.\n\n(*This lemma asserts the existence of a linear function from one vector space to another, given a linearly independent sequence of vectors in the domain and a corresponding sequence of values of the same length in the codomain. The lemma guarantees that under these conditions, a linear function exists that maps each vector in the domain sequence to its corresponding value in the codomain sequence.*)\nLemma linear_of_free (rT : lmodType K) X (fX : seq rT) :\n {f : {linear vT -> rT} | free X -> size fX = size X -> map f X = fX}.\n\n(*This lemma states that if a finite sequence of vectors is a basis of a given vector subspace, then the vector space spanned by that sequence is equal to the subspace itself.*)\nLemma span_basis U X : basis_of U X -> <>%VS = U.\n\n(*This lemma states that if a finite sequence of vectors is a basis of a given vector subspace, then that sequence must be linearly independent.*)\nLemma basis_free U X : basis_of U X -> free X.\n\n(*This lemma states that if a finite sequence of vectors forms a basis for a vector subspace, then any vector belonging to that subspace is equal to the linear combination of the basis vectors, where the coefficients are the coordinates of that vector with respect to the basis.*)\nLemma coord_basis U n (X : n.-tuple vT) v :\n basis_of U X -> v \\in U -> v = \\sum_i coord X i v *: X`_i.\n\n(*This lemma states that the empty sequence of vectors is a basis for the zero vector subspace.*)\nLemma nil_basis : basis_of 0 (Nil vT).\n\n(*This lemma states that for any non-zero vector, the finite sequence containing only that vector forms a basis for the one-dimensional vector subspace spanned by that vector.*)\nLemma seq1_basis v : v != 0 -> basis_of <[v]> [:: v].\n\n(*This lemma states that if a sequence of vectors is a basis for a vector space, then any vector belonging to that basis sequence is not the zero vector.*)\nLemma basis_not0 x U X : basis_of U X -> x \\in X -> x != 0.\n\n(*This lemma states that if a sequence of vectors is a basis for a vector space, then any vector belonging to that basis sequence is also an element of the vector space itself.*)\nLemma basis_mem x U X : basis_of U X -> x \\in X -> x \\in U.\n\n(*This lemma states that if two vector spaces form a direct sum, and two given sequences of vectors are bases for these respective spaces, then the concatenation of these two sequences forms a basis for the direct sum of the spaces.*)\nLemma cat_basis U V X Y :\n directv (U + V) -> basis_of U X -> basis_of V Y -> basis_of (U + V) (X ++ Y).\n\n(*This lemma states that if a finite sequence of vectors of a certain length forms a basis for a vector space, then the dimension of that vector space is equal to the length of the sequence.*)\nLemma size_basis U n (X : n.-tuple vT) : basis_of U X -> \\dim U = n.\n\n(*This lemma provides an equivalence for a sequence of vectors being a basis of a vector space. It states that a sequence forms a basis if and only if two conditions hold: first, the vector space is a subspace of the space spanned by the sequence of vectors, and second, the number of vectors in the sequence is less than or equal to the dimension of the vector space.*)\nLemma basisEdim X U : basis_of U X = (U <= <>)%VS && (size X <= \\dim U).\n\n(*This lemma provides an alternative equivalence for a sequence of vectors being a basis of a vector space. It states that a sequence of vectors is a basis for a given vector space if and only if the sequence is linearly independent, the span of the sequence is a subspace of the vector space, and the dimension of the vector space is less than or equal to the number of vectors in the sequence.*)\nLemma basisEfree X U :\n basis_of U X = [&& free X, (<> <= U)%VS & \\dim U <= size X].\n\n(*This lemma states that if two sequences of vectors are permutations of each other, then one sequence is a basis for a given vector space if and only if the other sequence is also a basis for that same vector space.*)\nLemma perm_basis X Y U : perm_eq X Y -> basis_of U X = basis_of U Y.\n\n(*This lemma asserts that the canonical basis of a given finite-dimensional vector space is, in fact, a valid basis for that space.*)\nLemma vbasisP U : basis_of U (vbasis U).\n\n(*This lemma states that any vector belonging to the canonical basis of a vector space is also an element of that vector space.*)\nLemma vbasis_mem v U : v \\in (vbasis U) -> v \\in U.\n\n(*This lemma asserts that any vector in a given vector space can be reconstructed as the linear combination of its canonical basis vectors, where each basis vector is scaled by the corresponding coordinate of the original vector.*)\nLemma coord_vbasis v U :\n v \\in U -> v = \\sum_(i < \\dim U) coord (vbasis U) i v *: (vbasis U)`_i.\n\nSection BigSumBasis.\n\nVariables (I : finType) (P : pred I) (Xs : I -> seq vT).\n\n(*This lemma states that the vector space spanned by the concatenation of a family of vector sequences is equal to the sum of the vector spaces spanned by each individual sequence in the family.*)\nLemma span_bigcat :\n (<<\\big[cat/[::]]_(i | P i) Xs i>> = \\sum_(i | P i) <>)%VS.\n\n(*This lemma states that if the sum of the vector spaces spanned by a family of vector sequences is a direct sum, and each individual sequence in the family is linearly independent, then the concatenation of all the sequences in the family is also linearly independent.*)\nLemma bigcat_free :\n directv (\\sum_(i | P i) <>) ->\n (forall i, P i -> free (Xs i)) -> free (\\big[cat/[::]]_(i | P i) Xs i).\n\n(*This lemma states that if the sum of a family of vector spaces is a direct sum, and a corresponding family of vector sequences provides a basis for each respective space, then the concatenation of all these basis sequences forms a basis for the total sum of the vector spaces.*)\nLemma bigcat_basis Us (U := (\\sum_(i | P i) Us i)%VS) :\n directv U -> (forall i, P i -> basis_of (Us i) (Xs i)) ->\n basis_of U (\\big[cat/[::]]_(i | P i) Xs i).\n\nEnd BigSumBasis.\n\nEnd VectorTheory.\n\n#[global] Hint Resolve subvv : core.\nArguments subvP {K vT U V}.\nArguments addv_idPl {K vT U V}.\nArguments addv_idPr {K vT U V}.\nArguments memv_addP {K vT w U V }.\nArguments sumv_sup [K vT I] i0 [P U Vs].\nArguments memv_sumP {K vT I P Us v}.\nArguments subv_sumP {K vT I P Us V}.\nArguments capv_idPl {K vT U V}.\nArguments capv_idPr {K vT U V}.\nArguments memv_capP {K vT w U V}.\nArguments bigcapv_inf [K vT I] i0 [P Us V].\nArguments subv_bigcapP {K vT I P U Vs}.\nArguments directvP {K vT S}.\nArguments directv_addP {K vT U V}.\nArguments directv_add_unique {K vT U V}.\nArguments directv_sumP {K vT I P Us}.\nArguments directv_sumE {K vT I P Ss}.\nArguments directv_sum_independent {K vT I P Us}.\nArguments directv_sum_unique {K vT I P Us}.\nArguments span_subvP {K vT X U}.\nArguments freeP {K vT n X}.\n\nPrenex Implicits coord.\nNotation directv S := (directv_def (Phantom _ S%VS)).\n\nSection LfunDefs.\n\nVariable R : nzRingType.\nImplicit Types aT vT rT : vectType R.\n\n(*This fact provides a key used to lock and unlock the definitions of linear functions, ensuring controlled access and abstraction over their internal representations.*)\nFact lfun_key : unit. \n(*This definition specifies the raw function associated with a linear map. It works by converting the input vector to a row vector, right-multiplying it by the matrix representation of the linear map, and then converting the resulting row vector back into a vector.*)\nDefinition fun_of_lfun_def aT rT (f : 'Hom(aT, rT)) :=\n r2v \\o mulmxr (f2mx f) \\o v2r.\n(*This definition provides the official, abstract representation of the function corresponding to a linear map, hiding the implementation details of its matrix-based computation. It is defined as a coercion, allowing a linear map to be used directly as a function.*)\nDefinition fun_of_lfun := locked_with lfun_key fun_of_lfun_def.\nCanonical fun_of_lfun_unlockable := [unlockable fun fun_of_lfun].\n(*This definition specifies how to construct a formal linear map from a given function between vector spaces. It assumes the function is linear and computes its matrix representation by composing it with conversions between vectors and row vectors, then packages this matrix into a linear map structure.*)\nDefinition linfun_def aT rT (f : aT -> rT) :=\n Hom (lin1_mx (v2r \\o f \\o r2v)).\n(*This definition provides the official, abstract constructor for creating a formal linear map from a function between vector spaces, hiding the underlying matrix construction.*)\nDefinition linfun := locked_with lfun_key linfun_def.\nCanonical linfun_unlockable := [unlockable fun linfun].\n\n(*This definition creates the identity linear map on a given vector space by applying the linear map constructor to the identity function.*)\nDefinition id_lfun vT := @linfun vT vT idfun.\n(*This definition specifies the composition of two linear maps. It is achieved by first composing their underlying functions and then constructing a new linear map from the resulting composite function.*)\nDefinition comp_lfun aT vT rT (f : 'Hom(vT, rT)) (g : 'Hom(aT, vT)) :=\n linfun (fun_of_lfun f \\o fun_of_lfun g).\n\nEnd LfunDefs.\n\nCoercion fun_of_lfun : hom >-> Funclass.\n(*This notation defines a shorthand for the identity linear map on a vector space, written as the number one.*)\nNotation \"\\1\" := (@id_lfun _ _) : lfun_scope.\n(*This notation defines an infix operator for the composition of two linear maps.*)\nNotation \"f \\o g\" := (comp_lfun f g) : lfun_scope.\n\nSection LfunVspaceDefs.\n\nVariable K : fieldType.\nImplicit Types aT rT : vectType K.\n\n(*This definition computes the pseudo-inverse of a linear map by taking its matrix representation, calculating the Moore-Penrose pseudo-inverse of the matrix, and then creating a new linear map from the resulting matrix.*)\nDefinition inv_lfun aT rT (f : 'Hom(aT, rT)) := Hom (pinvmx (f2mx f)).\n(*This definition computes the kernel, or null space, of a linear map. It does this by finding the kernel of the map's matrix representation and then converting this representation into a formal vector space.*)\nDefinition lker aT rT (f : 'Hom(aT, rT)) := mx2vs (kermx (f2mx f)).\n(*This fact provides a key used to lock and unlock the definition of the image of a vector subspace under a linear map, ensuring controlled access and abstraction.*)\nFact lfun_img_key : unit. \n(*This definition specifies the computation of the image of a vector subspace under a linear map. It operates by multiplying the matrix representation of the subspace with the matrix representation of the linear map and converting the result back into a vector subspace.*)\nDefinition lfun_img_def aT rT f (U : {vspace aT}) : {vspace rT} :=\n mx2vs (vs2mx U *m f2mx f).\n(*This definition provides the official, abstract representation for the image of a vector subspace under a linear map, hiding the underlying matrix computations.*)\nDefinition lfun_img := locked_with lfun_img_key lfun_img_def.\nCanonical lfun_img_unlockable := [unlockable fun lfun_img].\n(*This definition computes the preimage of a target vector subspace under a linear map. It is defined as the vector space sum of the map's kernel and the image of the intersection of the target subspace and the map's image, taken under the map's pseudo-inverse.*)\nDefinition lfun_preim aT rT (f : 'Hom(aT, rT)) W :=\n (lfun_img (inv_lfun f) (W :&: lfun_img f fullv) + lker f)%VS.\n\nEnd LfunVspaceDefs.\n\nPrenex Implicits linfun lfun_img lker lfun_preim.\n(*This notation defines a shorthand for the pseudo-inverse of a linear map.*)\nNotation \"f ^-1\" := (inv_lfun f) : lfun_scope.\n(*This notation defines an operator for applying a linear map to a vector subspace to compute its image.*)\nNotation \"f @: U\" := (lfun_img f%VF%R U) (at level 24) : vspace_scope.\n(*This notation represents the preimage of a given vector subspace under a specified linear function.*)\nNotation \"f @^-1: W\" := (lfun_preim f%VF%R W) (at level 24) : vspace_scope.\nNotation limg f := (lfun_img f fullv).\n\nSection LfunZmodType.\n\nVariables (R : nzRingType) (aT rT : vectType R).\nImplicit Types f g h : 'Hom(aT, rT).\n\nHB.instance Definition _ := [Choice of 'Hom(aT, rT) by <:].\n\n(*This fact asserts that any function belonging to the type of linear functions is indeed a linear map.*)\nFact lfun_is_linear f : linear f.\n\nHB.instance Definition _ (f : hom aT rT) := GRing.isSemilinear.Build R aT rT _ f\n (GRing.semilinear_linear (lfun_is_linear f)).\n\n(*This lemma states that a bundled linear function created from a function with a proof of linearity is pointwise equal to the original function.*)\nLemma lfunE (ff : {linear aT -> rT}) : linfun ff =1 ff.\n\n(*This lemma establishes that the operation of creating a bundled linear function from a function with its linearity proof is cancelled by the operation that retrieves the underlying function from the bundled linear map.*)\nLemma fun_of_lfunK : cancel (@fun_of_lfun R aT rT) linfun.\n\n(*This lemma states that two linear functions are equal if and only if they are pointwise equal, meaning they yield the same output vector for every given input vector.*)\nLemma lfunP f g : f =1 g <-> f = g.\n\n(*This definition specifies the zero linear function, which is the linear function that maps every vector from its domain to the zero vector in its codomain.*)\nDefinition zero_lfun : 'Hom(aT, rT) := linfun \\0.\n(*This definition introduces the addition of two linear functions, resulting in a new linear function that, for any given input vector, produces the sum of the outputs of the two original functions for that same input.*)\nDefinition add_lfun f g := linfun (f \\+ g).\n(*This definition specifies the additive inverse of a linear function, which is the linear function that maps any input vector to the additive inverse of the output produced by the original function for that same input.*)\nDefinition opp_lfun f := linfun (-%R \\o f).\n\n(*This fact asserts that the addition operation defined for linear functions is associative.*)\nFact lfun_addA : associative add_lfun.\n\n(*This fact asserts that the addition operation defined for linear functions is commutative.*)\nFact lfun_addC : commutative add_lfun.\n\n(*This fact asserts that the zero linear function is the left identity for the addition of linear functions, meaning adding it to any linear function yields the original function.*)\nFact lfun_add0 : left_id zero_lfun add_lfun.\n\n(*This lemma states that the additive inverse of a linear function serves as its left inverse under linear function addition, and their sum is the zero linear function.*)\nLemma lfun_addN : left_inverse zero_lfun opp_lfun add_lfun.\n\n(*This lemma states that applying the zero linear function to any input vector yields the zero vector of the codomain.*)\nLemma zero_lfunE x : (0 : 'Hom(aT, rT)) x = 0. \n(*This lemma states that applying the sum of two linear functions to an input vector is equivalent to adding the individual outputs that each function produces for that vector.*)\nLemma add_lfunE f g x : (f + g) x = f x + g x. \n(*This lemma states that applying the additive inverse of a linear function to an input vector yields the additive inverse of the vector that the original function would produce.*)\nLemma opp_lfunE f x : (- f) x = - f x. \n(*This lemma states that applying a finite sum of linear functions to an input vector is equivalent to computing the finite sum of the output vectors obtained by applying each function from the sum to that same input vector.*)\nLemma sum_lfunE I (r : seq I) (P : pred I) (fs : I -> 'Hom(aT, rT)) x :\n (\\sum_(i <- r | P i) fs i) x = \\sum_(i <- r | P i) fs i x.\n\nEnd LfunZmodType.\n\nArguments fun_of_lfunK {R aT rT}.\n\nSection LfunVectType.\n\nVariables (R : comNzRingType) (aT rT : vectType R).\nImplicit Types f : 'Hom(aT, rT).\n\n(*This definition introduces scalar multiplication for a linear function, where multiplying a linear function by a scalar from a commutative ring results in a new linear function whose output for any vector is the original function's output scaled by that scalar.*)\nDefinition scale_lfun k f := linfun (k \\*: f).\nLocal Infix \"*:l\" := scale_lfun (at level 40).\n\n(*This fact asserts that the scalar multiplication of linear functions is associative, meaning that scaling a linear function by a second scalar after it has been scaled by a first is equivalent to scaling the original function by the product of the two scalars.*)\nFact lfun_scaleA k1 k2 f : k1 *:l (k2 *:l f) = (k1 * k2) *:l f.\n\n(*This fact asserts that scaling a linear function by the multiplicative identity element of the base ring leaves the linear function unchanged.*)\nFact lfun_scale1 f : 1 *:l f = f.\n\n(*This fact asserts that scalar multiplication distributes over the addition of linear functions, meaning scaling the sum of two linear functions by a scalar is equivalent to summing the results of scaling each function individually by that same scalar.*)\nFact lfun_scaleDr k f1 f2 : k *:l (f1 + f2) = k *:l f1 + k *:l f2.\n\n(*This fact asserts that scalar multiplication of a linear function distributes over scalar addition, meaning scaling a linear function by the sum of two scalars is equivalent to summing the results of scaling the function individually by each scalar.*)\nFact lfun_scaleDl f k1 k2 : (k1 + k2) *:l f = k1 *:l f + k2 *:l f.\n\nHB.instance Definition _ :=\n GRing.Zmodule_isLmodule.Build _ 'Hom(aT, rT)\n lfun_scaleA lfun_scale1 lfun_scaleDr lfun_scaleDl.\n\n(*This lemma states that applying a linear function that has been scaled by a scalar to an input vector is equivalent to scaling the output of the original function applied to that vector by the same scalar.*)\nLemma scale_lfunE k f x : (k *: f) x = k *: f x. \n\n(*This fact asserts that the collection of all linear functions between two finite-dimensional vector spaces forms a vector space itself, and its dimension is equal to the product of the dimensions of the two original spaces.*)\nFact lfun_vect_iso : Vector.axiom (dim aT * dim rT) 'Hom(aT, rT).\n\n(*This lemma states that applying the identity linear function to any vector from the domain vector space yields that same vector.*)\nLemma id_lfunE u: \\1%VF u = u :> aT. \n(*This lemma states that applying the composition of two linear functions to an input vector is equivalent to applying the second function to the vector and then applying the first function to the resulting intermediate vector.*)\nLemma comp_lfunE f g u : (f \\o g)%VF u = f (g u). \n\n(*This lemma states that the composition of linear functions is an associative operation.*)\nLemma comp_lfunA f g h : (f \\o (g \\o h) = (f \\o g) \\o h)%VF.\n\n(*This lemma states that composing the identity linear function with any given linear function results in that same given linear function.*)\nLemma comp_lfun1l f : (\\1 \\o f)%VF = f.\n\n(*This lemma states that composing any given linear function with the identity linear function results in that same given linear function.*)\nLemma comp_lfun1r f : (f \\o \\1)%VF = f.\n\n(*This lemma states that the composition of the zero linear function with any other linear function results in the zero linear function.*)\nLemma comp_lfun0l g : (0 \\o g)%VF = 0 :> 'Hom(aT, rT).\n\n(*This lemma states that the composition of any linear function with the zero linear function results in the zero linear function.*)\nLemma comp_lfun0r f : (f \\o 0)%VF = 0 :> 'Hom(aT, rT).\n\n(*This lemma states that the composition of a sum of two linear functions with a third linear function is equal to the sum of the individual compositions.*)\nLemma comp_lfunDl f1 f2 g : ((f1 + f2) \\o g = (f1 \\o g) + (f2 \\o g))%VF.\n\n(*This lemma states that the composition of a linear function with the sum of two other linear functions is equal to the sum of composing the first function with each of the other two separately.*)\nLemma comp_lfunDr f g1 g2 : (f \\o (g1 + g2) = (f \\o g1) + (f \\o g2))%VF.\n\n(*This lemma states that composing the additive inverse of a linear function with another linear function is equivalent to taking the additive inverse of their composition.*)\nLemma comp_lfunNl f g : ((- f) \\o g = - (f \\o g))%VF.\n\n(*This lemma states that composing a linear function with the additive inverse of another linear function is equivalent to taking the additive inverse of their composition.*)\nLemma comp_lfunNr f g : (f \\o (- g) = - (f \\o g))%VF.\n\nEnd CompLfun.\n\n(*This definition provides a collection of lemmas intended for simplifying expressions involving linear functions, covering properties such as composition, scalar multiplication, negation, addition, and summation.*)\nDefinition lfun_simp :=\n (comp_lfunE, scale_lfunE, opp_lfunE, add_lfunE, sum_lfunE, lfunE).\n\nSection ScaleCompLfun.\n\nVariables (R : comNzRingType) (aT vT rT : vectType R).\nImplicit Types (f : 'Hom(vT, rT)) (g : 'Hom(aT, vT)).\n\n(*This lemma states that multiplying a composition of two linear functions by a scalar is equivalent to multiplying the first linear function by that scalar before composing it with the second.*)\nLemma comp_lfunZl k f g : (k *: (f \\o g) = (k *: f) \\o g)%VF.\n\n(*This lemma states that multiplying a composition of two linear functions by a scalar is equivalent to composing the first linear function with the result of multiplying the second linear function by that scalar.*)\nLemma comp_lfunZr k f g : (k *: (f \\o g) = f \\o (k *: g))%VF.\n\nEnd ScaleCompLfun.\n\nSection LinearImage.\n\nVariables (K : fieldType) (aT rT : vectType K).\nImplicit Types (f g : 'Hom(aT, rT)) (U V : {vspace aT}) (W : {vspace rT}).\n\n(*This lemma states that if a vector subspace is a subset of another, then the image of the first subspace under a linear function is a subset of the image of the second subspace under the same function.*)\nLemma limgS f U V : (U <= V)%VS -> (f @: U <= f @: V)%VS.\n\n(*This lemma states that the image of a one-dimensional subspace spanned by a vector under a linear function is the one-dimensional subspace spanned by the image of that vector.*)\nLemma limg_line f v : (f @: <[v]> = <[f v]>)%VS.\n\n(*This lemma states that the image of the zero vector subspace under any linear function is the zero vector subspace.*)\nLemma limg0 f : (f @: 0 = 0)%VS. \n\n(*This lemma states that if a vector is an element of a vector subspace, then the image of that vector under a linear function is an element of the image of that subspace.*)\nLemma memv_img f v U : v \\in U -> f v \\in (f @: U)%VS.\n\n(*This lemma provides a boolean reflection of the property that a vector belongs to the image of a subspace under a linear function, asserting this is equivalent to the existence of a vector in the original subspace that maps to it.*)\nLemma memv_imgP f w U :\n reflect (exists2 u, u \\in U & w = f u) (w \\in f @: U)%VS.\n\n(*This lemma states that the image of any vector subspace under the zero linear function is the zero vector subspace.*)\nLemma lim0g U : (0 @: U = 0 :> {vspace rT})%VS.\n\n(*This lemma states that if two linear functions are equal on a given vector subspace, then the images of that subspace under both functions are also equal.*)\nLemma eq_in_limg V f g : {in V, f =1 g} -> (f @: V = g @: V)%VS.\n\n(*This lemma states that the image of the sum of two vector subspaces under a linear function is equal to the sum of their individual images under that function.*)\nLemma limgD f : {morph lfun_img f : U V / U + V}%VS.\n\n(*This lemma states that the image of an indexed sum of vector subspaces under a linear function is equal to the indexed sum of the images of those subspaces.*)\nLemma limg_sum f I r (P : pred I) Us :\n (f @: (\\sum_(i <- r | P i) Us i) = \\sum_(i <- r | P i) f @: Us i)%VS.\n\n(*This lemma states that the image of the intersection of two vector subspaces under a linear function is a subspace of the intersection of their individual images.*)\nLemma limg_cap f U V : (f @: (U :&: V) <= f @: U :&: f @: V)%VS.\n\n(*This lemma states that the image of an indexed intersection of vector subspaces under a linear function is a subspace of the indexed intersection of their individual images.*)\nLemma limg_bigcap f I r (P : pred I) Us :\n (f @: (\\bigcap_(i <- r | P i) Us i) <= \\bigcap_(i <- r | P i) f @: Us i)%VS.\n\n(*This lemma states that the image of the vector subspace spanned by a set of vectors under a linear function is equal to the subspace spanned by the images of those vectors.*)\nLemma limg_span f X : (f @: <> = <>)%VS.\n\n(*This lemma provides a condition for a finite sequence of vectors to be contained within the image of a vector subspace under a linear function: this holds if and only if there exists another sequence of vectors, all belonging to the original subspace, whose images under the function form the given sequence.*)\nLemma subset_limgP f U (r : seq rT) :\n {subset r <= (f @: U)%VS} <-> (exists2 a, all (mem U) a & r = map f a).\n\n(*This lemma provides a boolean reflection for the inequality of two linear functions, stating that they are unequal if and only if there exists at least one vector on which their values differ.*)\nLemma lfunPn f g : reflect (exists u, f u != g u) (f != g).\n\n(*This lemma states that composing a linear function, its generalized inverse, and the original linear function again, in that order, results in the original linear function.*)\nLemma inv_lfun_def f : (f \\o f^-1 \\o f)%VF = f.\n\n(*This lemma states that the composition of a linear function with its generalized inverse acts as the identity mapping when restricted to the image of that linear function.*)\nLemma limg_lfunVK f : {in limg f, cancel f^-1%VF f}.\n\n(*This lemma states that a vector subspace is contained within the kernel of a linear function if and only if the image of that subspace under the function is the zero subspace.*)\nLemma lkerE f U : (U <= lker f)%VS = (f @: U == 0)%VS.\n\n(*This lemma states that a vector is an element of the kernel of a linear function if and only if the function maps that vector to the zero vector.*)\nLemma memv_ker f v : (v \\in lker f) = (f v == 0).\n\n(*This lemma provides a boolean reflection for the equality of two linear functions at a specific vector, stating this is equivalent to the vector being in the kernel of the difference between the two functions.*)\nLemma eqlfunP f g v : reflect (f v = g v) (v \\in lker (f - g)).\n\n(*This lemma states that two linear functions are equal for all vectors in a given vector subspace if and only if that subspace is contained within the kernel of their difference.*)\nLemma eqlfun_inP V f g : reflect {in V, f =1 g} (V <= lker (f - g))%VS.\n\n(*This lemma asserts that the linear image of a vector subspace under a linear function is identical to the linear image of the complement of the function's kernel within that subspace.*)\nLemma limg_ker_compl f U : (f @: (U :\\: lker f) = f @: U)%VS.\n\n(*This lemma states that for any given vector subspace, the sum of the dimension of its intersection with the kernel of a linear function and the dimension of its image under that function is equal to the dimension of the original subspace.*)\nLemma limg_ker_dim f U : (\\dim (U :&: lker f) + \\dim (f @: U) = \\dim U)%N.\n\n(*This lemma states that if a vector subspace has a trivial intersection with the kernel of a linear function, then the dimension of the image of that subspace is equal to its own dimension.*)\nLemma limg_dim_eq f U : (U :&: lker f = 0)%VS -> \\dim (f @: U) = \\dim U.\n\n(*This lemma asserts that if a linear function is injective on a given vector subspace, it maps any basis of that subspace to a basis of its linear image.*)\nLemma limg_basis_of f U X :\n (U :&: lker f = 0)%VS -> basis_of U X -> basis_of (f @: U) (map f X).\n\n(*This lemma provides a reflection between the property that a linear function is injective and the condition that its kernel is the zero vector space.*)\nLemma lker0P f : reflect (injective f) (lker f == 0%VS).\n\n(*This lemma states that for an injective linear function, the image of one vector subspace is contained in the image of another if and only if the first subspace is contained in the second.*)\nLemma limg_ker0 f U V : lker f == 0%VS -> (f @: U <= f @: V)%VS = (U <= V)%VS.\n\n(*This lemma states that for an injective linear function, the images of two vector subspaces are equal if and only if the subspaces themselves are equal.*)\nLemma eq_limg_ker0 f U V : lker f == 0%VS -> (f @: U == f @: V)%VS = (U == V).\n\n(*This lemma states that an injective linear function has a canonical left inverse.*)\nLemma lker0_lfunK f : lker f == 0%VS -> cancel f f^-1%VF.\n\n(*This lemma states that for an injective linear function, the composition of its canonical inverse with the function itself results in the identity linear function.*)\nLemma lker0_compVf f : lker f == 0%VS -> (f^-1 \\o f = \\1)%VF.\n\n(*This lemma states that for an injective linear function, the image of the intersection of two vector subspaces is equal to the intersection of their respective images.*)\nLemma lker0_img_cap f U V : lker f == 0%VS ->\n (f @: (U :&: V) = f @: U :&: f @: V)%VS.\n\nEnd LinearImage.\n\nArguments memv_imgP {K aT rT f w U}.\nArguments lfunPn {K aT rT f g}.\nArguments lker0P {K aT rT f}.\nArguments eqlfunP {K aT rT f g v}.\nArguments eqlfun_inP {K aT rT V f g}.\nArguments limg_lfunVK {K aT rT f} [x] f_x.\n\nSection FixedSpace.\n\nVariables (K : fieldType) (vT : vectType K).\nImplicit Types (f : 'End(vT)) (U : {vspace vT}).\n\n(*This definition establishes the fixed space of a linear endomorphism as the kernel of the linear function obtained by subtracting the identity function from the endomorphism.*)\nDefinition fixedSpace f : {vspace vT} := lker (f - \\1%VF).\n\n(*This lemma provides a reflection between the property that a vector is a fixed point of a linear endomorphism and the condition that the vector is an element of the endomorphism's fixed space.*)\nLemma fixedSpaceP f a : reflect (f a = a) (a \\in fixedSpace f).\n\n(*This lemma provides a reflection between the property that a linear endomorphism acts as the identity on a vector subspace and the condition that the subspace is contained within the endomorphism's fixed space.*)\nLemma fixedSpacesP f U : reflect {in U, f =1 id} (U <= fixedSpace f)%VS.\n\n(*This lemma states that if a vector subspace is contained within the fixed space of a linear endomorphism, then its image under that endomorphism is the subspace itself.*)\nLemma fixedSpace_limg f U : (U <= fixedSpace f -> f @: U = U)%VS.\n\n(*This lemma states that the fixed space of the identity linear endomorphism is the entire vector space.*)\nLemma fixedSpace_id : fixedSpace \\1 = {:vT}%VS.\n\nEnd FixedSpace.\n\nArguments fixedSpaceP {K vT f a}.\nArguments fixedSpacesP {K vT f U}.\n\nSection LinAut.\n\nVariables (K : fieldType) (vT : vectType K) (f : 'End(vT)).\nHypothesis kerf0 : lker f == 0%VS.\n\n(*This lemma states that an injective linear endomorphism on a vector space is surjective, meaning its image is the entire space.*)\nLemma lker0_limgf : limg f = fullv.\n\n(*This lemma states that the canonical inverse of an injective linear endomorphism is a right inverse, such that composing the endomorphism with its inverse yields the identity.*)\nLemma lker0_lfunVK : cancel f^-1%VF f.\n\n(*This lemma states that for an injective linear endomorphism, the composition of the endomorphism with its canonical inverse results in the identity linear function.*)\nLemma lker0_compfV : (f \\o f^-1 = \\1)%VF.\n\n(*This lemma states that for an injective linear endomorphism, composing it with the result of composing its inverse with any other linear map yields that other linear map.*)\nLemma lker0_compVKf aT g : (f \\o (f^-1 \\o g))%VF = g :> 'Hom(aT, vT).\n\n(*This lemma states that for an injective linear endomorphism, composing its inverse with the result of composing the endomorphism with any other linear map yields that other linear map.*)\nLemma lker0_compKf aT g : (f^-1 \\o (f \\o g))%VF = g :> 'Hom(aT, vT).\n\n(*This lemma asserts a right cancellation property for an injective linear endomorphism, stating that composing any linear map with the endomorphism, and then composing the result with the endomorphism's inverse, yields the original linear map.*)\nLemma lker0_compfK rT h : ((h \\o f) \\o f^-1)%VF = h :> 'Hom(vT, rT).\n\n(*This lemma asserts a right cancellation property for an injective linear endomorphism, stating that composing any linear map with the inverse of the endomorphism, and then composing the result with the endomorphism itself, yields the original linear map.*)\nLemma lker0_compfVK rT h : ((h \\o f^-1) \\o f)%VF = h :> 'Hom(vT, rT).\n\nEnd LinAut.\n\nSection LinearImageComp.\n\nVariables (K : fieldType) (aT vT rT : vectType K).\nImplicit Types (f : 'Hom(aT, vT)) (g : 'Hom(vT, rT)) (U : {vspace aT}).\n\n(*This lemma states that the linear image of any vector subspace under the identity linear function is the subspace itself.*)\nLemma lim1g U : (\\1 @: U)%VS = U.\n\n(*This lemma states that the linear image of a vector subspace under the composition of two linear functions is equal to the image under the second function of the image under the first function.*)\nLemma limg_comp f g U : ((g \\o f) @: U = g @: (f @: U))%VS.\n\nEnd LinearImageComp.\n\nSection LinearPreimage.\n\nVariables (K : fieldType) (aT rT : vectType K).\nImplicit Types (f : 'Hom(aT, rT)) (U : {vspace aT}) (V W : {vspace rT}).\n\n(*This lemma states that the linear preimage of the intersection of a vector subspace with the image of a linear function is equal to the linear preimage of that vector subspace itself.*)\nLemma lpreim_cap_limg f W : (f @^-1: (W :&: limg f))%VS = (f @^-1: W)%VS.\n\n(*This lemma states that the linear preimage of the zero vector space under a linear function is the kernel of that function.*)\nLemma lpreim0 f : (f @^-1: 0)%VS = lker f.\n\n(*This lemma states that the linear preimage operation preserves subspace inclusion, meaning if one vector subspace is contained in another, the preimage of the first is contained in the preimage of the second.*)\nLemma lpreimS f V W : (V <= W)%VS-> (f @^-1: V <= f @^-1: W)%VS.\n\n(*This lemma states that for any vector subspace contained within the image of a linear function, the image of its linear preimage is the original subspace itself.*)\nLemma lpreimK f W : (W <= limg f)%VS -> (f @: (f @^-1: W))%VS = W.\n\n(*This lemma states that the image of a vector under a linear function belongs to a given vector subspace if and only if the vector itself belongs to the linear preimage of that subspace.*)\nLemma memv_preim f u W : (f u \\in W) = (u \\in f @^-1: W)%VS.\n\nEnd LinearPreimage.\n\nArguments lpreimK {K aT rT f} [W] fW.\n\nSection LfunAlgebra.\n\nVariables (R : comNzRingType) (vT : vectType R).\nHypothesis vT_proper : dim vT > 0.\n\n(*This fact establishes that the identity linear function on a vector space with a dimension greater than zero is not equal to the zero linear function.*)\nFact lfun1_neq0 : \\1%VF != 0 :> 'End(vT).\n\nPrenex Implicits comp_lfunA comp_lfun1l comp_lfun1r comp_lfunDl comp_lfunDr.\n\n(*This definition creates a structure mixin that packages the necessary algebraic properties, such as associativity and distributivity of composition, to establish that the linear endomorphisms on a given non-trivial vector space form a non-zero ring.*)\nDefinition lfun_comp_nzRingMixin := GRing.Zmodule_isNzRing.Build 'End(vT)\n comp_lfunA comp_lfun1l comp_lfun1r comp_lfunDl comp_lfunDr lfun1_neq0.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use lfun_comp_nzRingMixin instead.\")]\n(*This notation is a deprecated alias for the non-zero ring mixin for linear endomorphisms. It is provided for backward compatibility and should be replaced by lfun_comp_nzRingMixin.*)\nNotation lfun_comp_ringMixin := (lfun_comp_nzRingMixin) (only parsing).\n\n(*This definition constructs the canonical non-zero ring structure for the type of linear endomorphisms on a vector space, where ring multiplication corresponds to function composition.*)\nDefinition lfun_comp_nzRingType : nzRingType :=\n HB.pack 'End(vT) lfun_comp_nzRingMixin.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use lfun_comp_nzRingType instead.\")]\n(*This notation is a deprecated alias for the non-zero ring type of linear endomorphisms on a vector space. It is provided for backward compatibility and should be replaced by lfun_comp_nzRingType.*)\nNotation lfun_comp_ringType := (lfun_comp_nzRingType) (only parsing).\n\n(*This definition designates the non-zero ring of linear endomorphisms on a vector space as the canonical ring structure for that type, enabling automatic type class inference.*)\nDefinition lfun_nzRingType : nzRingType := lfun_comp_nzRingType^c.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use lfun_nzRingType instead.\")]\n(*This notation is a deprecated alias for the canonical non-zero ring type of linear endomorphisms. It is provided for backward compatibility and should be replaced by lfun_nzRingType.*)\nNotation lfun_ringType := (lfun_nzRingType) (only parsing).\n\n(*This definition constructs a structure mixin proving that the non-zero ring of linear endomorphisms on a vector space is compatible with scalar multiplication, a requirement for it to be a left algebra over the base ring.*)\nDefinition lfun_lalgMixin := GRing.Lmodule_isLalgebra.Build R lfun_nzRingType\n (fun k x y => comp_lfunZr k y x).\n(*This definition formally constructs the left algebra type for the set of linear endomorphisms on a vector space over a given base ring.*)\nDefinition lfun_lalgType : lalgType R :=\n HB.pack 'End(vT) lfun_nzRingType lfun_lalgMixin.\n\n(*This definition constructs a structure mixin that extends the left algebra structure of linear endomorphisms to a full two-sided algebra, by showing that scalar multiplication is compatible with ring multiplication from both the left and right.*)\nDefinition lfun_algMixin := GRing.Lalgebra_isAlgebra.Build R lfun_lalgType\n (fun k x y => comp_lfunZl k y x).\n(*This definition constructs the full two-sided algebra type for the set of linear endomorphisms on a vector space over a given base ring.*)\nDefinition lfun_algType : algType R :=\n HB.pack 'End(vT) lfun_lalgType lfun_algMixin.\n\nEnd LfunAlgebra.\n\nSection Projection.\n\nVariables (K : fieldType) (vT : vectType K).\nImplicit Types U V : {vspace vT}.\n\n(*This definition defines the projection linear map onto a first vector subspace along a second vector subspace. It is constructed from the matrix representation of the projection.*)\nDefinition daddv_pi U V := Hom (proj_mx (vs2mx U) (vs2mx V)).\n(*This definition defines the orthogonal projection onto a given vector subspace. It is a special case of projection where the projection is taken along the orthogonal complement of the subspace.*)\nDefinition projv U := daddv_pi U U^C.\n(*This definition defines the first projection component associated with a pair of vector subspaces. It projects onto the part of the first subspace that is orthogonal to the second subspace, along the second subspace.*)\nDefinition addv_pi1 U V := daddv_pi (U :\\: V) V.\n(*This definition defines the second projection component associated with a pair of vector subspaces. It projects onto the second subspace along the part of the first subspace that is orthogonal to the second.*)\nDefinition addv_pi2 U V := daddv_pi V (U :\\: V).\n\n(*This lemma states that the result of applying the projection map onto a first vector subspace along a second vector subspace to any vector is always a member of the first subspace.*)\nLemma memv_pi U V w : (daddv_pi U V) w \\in U.\n\n(*This lemma states that the orthogonal projection of any vector onto a given vector subspace yields a vector that is a member of that subspace.*)\nLemma memv_proj U w : projv U w \\in U. \n\n(*This lemma states that the result of applying the first projection component associated with two vector subspaces to any vector is a member of the first subspace.*)\nLemma memv_pi1 U V w : (addv_pi1 U V) w \\in U.\n\n(*This lemma states that the result of applying the second projection component associated with two vector subspaces to any vector is a member of the second subspace.*)\nLemma memv_pi2 U V w : (addv_pi2 U V) w \\in V. \n\n(*This lemma states that for two vector subspaces with a trivial intersection, the projection onto the first subspace along the second acts as the identity on vectors that are already members of the first subspace.*)\nLemma daddv_pi_id U V u : (U :&: V = 0)%VS -> u \\in U -> daddv_pi U V u = u.\n\n(*This lemma states that for two vector subspaces with a trivial intersection, the projection onto the first subspace along the second is an idempotent operator, meaning that applying the projection to a vector that has already been projected yields the same projected vector.*)\nLemma daddv_pi_proj U V w (pi := daddv_pi U V) :\n (U :&: V = 0)%VS -> pi (pi w) = pi w.\n\n(*This lemma states that for any vector belonging to the sum of two vector subspaces with a trivial intersection, the vector can be reconstructed by adding its projection onto the first subspace along the second, and its projection onto the second subspace along the first.*)\nLemma daddv_pi_add U V w :\n (U :&: V = 0)%VS -> (w \\in U + V)%VS -> daddv_pi U V w + daddv_pi V U w = w.\n\n(*This lemma states that the orthogonal projection onto a vector subspace acts as the identity function for any vector that is already a member of that subspace.*)\nLemma projv_id U u : u \\in U -> projv U u = u.\n\n(*This lemma states that the orthogonal projection onto a vector subspace is an idempotent operation, meaning that applying the projection a second time does not change the result.*)\nLemma projv_proj U w : projv U (projv U w) = projv U w.\n\n(*This lemma states that the difference between any vector and its orthogonal projection onto a vector subspace results in a vector that lies in the orthogonal complement of that subspace.*)\nLemma memv_projC U w : w - projv U w \\in (U^C)%VS.\n\n(*This lemma states that the linear image of the orthogonal projection operator onto a vector subspace is exactly that subspace.*)\nLemma limg_proj U : limg (projv U) = U.\n\n(*This lemma states that the linear kernel of the orthogonal projection operator onto a vector subspace is exactly the orthogonal complement of that subspace.*)\nLemma lker_proj U : lker (projv U) = (U^C)%VS.\n\n(*This lemma states that the first projection component associated with a pair of vector subspaces is an idempotent operator, meaning applying it twice yields the same result as applying it once.*)\nLemma addv_pi1_proj U V w (pi1 := addv_pi1 U V) : pi1 (pi1 w) = pi1 w.\n\n(*This lemma states that the second projection component associated with a pair of vector subspaces acts as the identity on any vector that is already a member of the second subspace.*)\nLemma addv_pi2_id U V v : v \\in V -> addv_pi2 U V v = v.\n\n(*This lemma states that the second projection component associated with a pair of vector subspaces is an idempotent operator, meaning applying it twice yields the same result as applying it once.*)\nLemma addv_pi2_proj U V w (pi2 := addv_pi2 U V) : pi2 (pi2 w) = pi2 w.\n\n(*This lemma states that for any vector in the sum of two vector subspaces, the vector itself is recovered by adding its two components, where the first component lies in the first subspace and the second component lies in the second subspace.*)\nLemma addv_pi1_pi2 U V w :\n w \\in (U + V)%VS -> addv_pi1 U V w + addv_pi2 U V w = w.\n\nSection Sumv_Pi.\n\nVariables (I : eqType) (r0 : seq I) (P : pred I) (Vs : I -> {vspace vT}).\n\n(*This definition provides a recursive helper function to construct the projection map onto a specific component subspace, identified by an index, from a direct sum of a sequence of vector subspaces. The function works by iterating through the sequence of subspaces and composing projection operators.*)\nLet sumv_pi_rec i :=\n fix loop r := if r is j :: r1 then\n let V1 := (\\sum_(k <- r1) Vs k)%VS in\n if j == i then addv_pi1 (Vs j) V1 else (loop r1 \\o addv_pi2 (Vs j) V1)%VF\n else 0.\n\n(*This notation defines a shorthand for the direct sum of a family of vector subspaces. The sum is constructed from subspaces indexed by elements from a given finite sequence that satisfy a specific predicate.*)\nNotation sumV := (\\sum_(i <- r0 | P i) Vs i)%VS.\n(*This definition provides the projection map associated with a vector space that is proven to be a direct sum of a family of subspaces. For a given index, this function returns the specific projection map that sends a vector to its component in the subspace corresponding to that index.*)\nDefinition sumv_pi_for V of V = sumV := fun i => sumv_pi_rec i (filter P r0).\n\nVariables (V : {vspace vT}) (defV : V = sumV).\n\n(*This lemma asserts that when the projection function for a direct sum is applied to a vector with a specific index, the resulting vector is guaranteed to be an element of the component subspace corresponding to that index.*)\nLemma memv_sum_pi i v : sumv_pi_for defV i v \\in Vs i.\n\n(*This lemma states that for any vector within a direct sum space, the vector can be reconstructed by summing its projections onto each of the component subspaces, provided that the subspaces in the sum are indexed by a unique sequence of elements.*)\nLemma sumv_pi_uniq_sum v :\n uniq (filter P r0) -> v \\in V ->\n \\sum_(i <- r0 | P i) sumv_pi_for defV i v = v.\n\nEnd Sumv_Pi.\n\nEnd Projection.\n\nPrenex Implicits daddv_pi projv addv_pi1 addv_pi2.\nNotation sumv_pi V := (sumv_pi_for (erefl V)).\n\nSection SumvPi.\n\nVariable (K : fieldType) (vT : vectType K).\n\n(*This lemma states that for any vector belonging to a vector space defined as a direct sum of subspaces indexed by a finite type, the vector is equal to the sum of its projections onto each of the component subspaces.*)\nLemma sumv_pi_sum (I : finType) (P : pred I) Vs v (V : {vspace vT})\n (defV : V = (\\sum_(i | P i) Vs i)%VS) :\n v \\in V -> \\sum_(i | P i) sumv_pi_for defV i v = v :> vT.\n\n(*This lemma states that for any vector in a vector space constructed as a direct sum of subspaces indexed by a range of natural numbers, the vector equals the sum of its projections onto each of these component subspaces.*)\nLemma sumv_pi_nat_sum m n (P : pred nat) Vs v (V : {vspace vT})\n (defV : V = (\\sum_(m <= i < n | P i) Vs i)%VS) :\n v \\in V -> \\sum_(m <= i < n | P i) sumv_pi_for defV i v = v :> vT.\n\nEnd SumvPi.\n\nSection SubVector.\n\nVariable (K : fieldType) (vT : vectType K) (U : {vspace vT}).\n\n(*A notation for a function that constructs a matrix representation of a finite-dimensional subspace. The resulting matrix is formed by using the vectors of the canonical basis of the given subspace as its rows.*)\nInductive subvs_of : predArgType := Subvs u & u \\in U.\n\n(*This function retrieves the underlying vector from a value that represents a vector belonging to a specific subspace. It essentially converts an element of the subspace type back into an element of the larger, ambient vector space.*)\nDefinition vsval w : vT := let: Subvs u _ := w in u.\nHB.instance Definition _ := [isSub of subvs_of for vsval].\nHB.instance Definition _ := [Choice of subvs_of by <:].\nHB.instance Definition _ := [SubChoice_isSubZmodule of subvs_of by <:].\nHB.instance Definition _ := [SubZmodule_isSubLmodule of subvs_of by <:].\n\n(*This lemma asserts that when a vector is extracted from an element of a subspace-specific type, the resulting vector is guaranteed to be a member of the original subspace.*)\nLemma subvsP w : vsval w \\in U. \n(*This lemma states that the function which retrieves the underlying vector from a subspace-specific element is injective, meaning that if two such elements yield the same underlying vector, they must have been identical.*)\nLemma subvs_inj : injective vsval. \n(*This lemma states that if two elements representing vectors in a subspace are equal, then the underlying vectors they represent are also equal.*)\nLemma congr_subvs u v : u = v -> vsval u = vsval v. \n\n(*This lemma asserts that the function which embeds a subspace into its ambient vector space is a linear map, preserving both vector addition and scalar multiplication.*)\nLemma vsval_is_linear : linear vsval. \nHB.instance Definition _ := GRing.isSemilinear.Build K subvs_of vT _ vsval\n (GRing.semilinear_linear vsval_is_linear).\n\n(*This fact provides a unique, opaque key used to control the unfolding of the vector space projection definition, serving as an abstraction barrier.*)\nFact vsproj_key : unit. \n(*This definition specifies the projection function onto a subspace. It operates by taking a vector from the ambient space, computing its projection onto the given subspace, and then packaging the resulting vector as an element of the subspace's dedicated type.*)\nDefinition vsproj_def u := Subvs (memv_proj U u).\n(*This definition establishes the canonical projection function from an ambient vector space onto a given subspace. Its definition is intentionally made abstract to enforce reasoning through its properties rather than its specific implementation.*)\nDefinition vsproj := locked_with vsproj_key vsproj_def.\nCanonical vsproj_unlockable := [unlockable fun vsproj].\n\n(*This lemma provides a cancellation property, stating that for any vector already belonging to a subspace, applying the projection onto that subspace followed by the embedding back into the ambient space is the identity operation.*)\nLemma vsprojK : {in U, cancel vsproj vsval}.\n\n(*This lemma provides a cancellation property, stating that if an element of a subspace type is first converted to its underlying vector and then projected back to the subspace type, the original element is recovered.*)\nLemma vsvalK : cancel vsval vsproj.\n\n(*This lemma states that the function which projects vectors from an ambient space onto a given subspace is a linear map, preserving both vector addition and scalar multiplication.*)\nLemma vsproj_is_linear : linear vsproj.\n\nHB.instance Definition _ := GRing.isSemilinear.Build K vT subvs_of _ vsproj\n (GRing.semilinear_linear vsproj_is_linear).\n\n(*This fact asserts that the type representing elements of a given subspace forms a finite-dimensional vector space whose dimension is the same as the dimension of the subspace itself.*)\nFact subvs_vect_iso : Vector.axiom (\\dim U) subvs_of.\n\n(*This lemma shows that for a vector that is already an element of a subspace, constructing an element of the subspace type via its explicit constructor is equivalent to applying the general projection function to that vector.*)\nLemma SubvsE x (xU : x \\in U) : Subvs xU = vsproj x.\n\nEnd SubVector.\nPrenex Implicits vsval vsproj vsvalK.\nArguments subvs_inj {K vT U} [x1 x2].\nArguments vsprojK {K vT U} [x] Ux.\n\nSection MatrixVectType.\n\nVariables (R : nzRingType) (m n : nat).\n\n(*This fact asserts that the type of matrices with a specified number of rows and columns over a given ring satisfies the axioms of a finite-dimensional vector space, where the dimension is equal to the product of the number of rows and columns.*)\nFact matrix_vect_iso : Vector.axiom (m * n) 'M[R]_(m, n).\n\n(*This lemma states that the dimension of the vector space of matrices with a specific number of rows and columns is equal to the product of these two numbers.*)\nLemma dim_matrix : dim 'M[R]_(m, n) = m * n.\n\nEnd MatrixVectType.\n\nSection RegularVectType.\n\nVariable R : nzRingType.\n\n(*This fact asserts that the opposite ring type, when considered as a vector space over the original non-zero ring, has dimension one.*)\nFact regular_vect_iso : Vector.axiom 1 R^o.\n\n(*This fact asserts that the product of two finite-dimensional vector spaces is itself a finite-dimensional vector space, and its dimension is the sum of the dimensions of the component spaces.*)\nFact pair_vect_iso : Vector.axiom (dim vT1 + dim vT2) (vT1 * vT2).\n\n(*This fact asserts that the space of functions from a finite domain to a finite-dimensional vector space is itself a finite-dimensional vector space, with a dimension equal to the product of the size of the domain and the dimension of the target space.*)\nFact ffun_vect_iso : Vector.axiom (#|I| * dim vT) {ffun I -> vT}.\n\n(*This definition specifies a linear map that transforms a vector into a new vector whose components are generated by applying each endomorphism from a given sequence to the input vector.*)\nLet lhsf u := finfun ((tnth lhs)^~ u).\n(*This definition formulates the solvability condition for a system of linear equations over a given subspace. The condition holds if the vector formed by the right-hand side of the equations is an element of the image of the subspace under the linear map defined by the left-hand side operators.*)\nDefinition vsolve_eq U := finfun (tnth rhs) \\in (linfun lhsf @: U)%VS.\n\n(*This lemma establishes the equivalence between the abstract solvability condition of a linear system and its concrete definition. It asserts that the system has a solution within a given subspace if and only if there exists a vector in that subspace such that for all indices, applying the indexed left-hand side operator to the vector yields the indexed right-hand side vector.*)\nLemma vsolve_eqP (U : {vspace vT}) :\n reflect (exists2 u, u \\in U & forall i, tnth lhs i u = tnth rhs i)\n (vsolve_eq U).\n\nEnd Solver.\n\nSection lfunP.\nVariable (F : fieldType).\nContext {uT vT : vectType F}.\n(*A local notation representing the dimension of a given finite-dimensional vector space, which is conventionally used as the domain in a linear map context.*)\nLocal Notation m := (\\dim {:uT}).\n(*A local notation representing the dimension of a given finite-dimensional vector space, which is conventionally used as the codomain in a linear map context.*)\nLocal Notation n := (\\dim {:vT}).\n\n(*This lemma states that two linear functions mapping from one vector space to another are equal over the entire subspace generated by a finite sequence of vectors if and only if they are equal on every vector within that original sequence.*)\nLemma span_lfunP (U : seq uT) (phi psi : 'Hom(uT,vT)) :\n {in <>%VS, phi =1 psi} <-> {in U, phi =1 psi}.\n\n(*This lemma states that, given a finite sequence of vectors that spans an entire vector space, two linear functions are identical if and only if they produce the same result for every vector in that spanning sequence.*)\nLemma fullv_lfunP (U : seq uT) (phi psi : 'Hom(uT,vT)) : <>%VS = fullv ->\n phi = psi <-> {in U, phi =1 psi}.\n\nEnd lfunP.\n\nModule passmx.\nSection passmx.\nVariable (F : fieldType).\n\nSection vecmx.\nContext {vT : vectType F}.\n(*A local notation representing the dimension of a given finite-dimensional vector space, which is conventionally used as the codomain in a linear map context.*)\nLocal Notation n := (\\dim {:vT}).\n\nVariables (e : n.-tuple vT).\n\n(*This definition specifies a function that converts a vector into its corresponding coordinate row vector with respect to a given basis.*)\nDefinition rVof (v : vT) := \\row_i coord e i v.\n(*This lemma states that the function converting a vector to its coordinate row vector is a linear map.*)\nLemma rVof_linear : linear rVof.\n\nHB.instance Definition _ := GRing.isSemilinear.Build F _ _ _ rVof\n (GRing.semilinear_linear rVof_linear).\n\n(*This lemma states that the coordinate of a vector at a specific index with respect to a basis is equal to the element at the same column index in the vector's row vector representation.*)\nLemma coord_rVof i v : coord e i v = rVof v 0 i.\n\n(*This definition specifies a function that constructs a vector from a row vector of coordinates by forming a linear combination of basis vectors using the entries of the row vector as coefficients.*)\nDefinition vecof (v : 'rV_n) := \\sum_i v 0 i *: e`_i.\n\n(*This lemma states that constructing a vector from a standard basis row vector, which has a one at a specific index and zeros elsewhere, yields the corresponding basis vector of the vector space.*)\nLemma vecof_delta i : vecof (delta_mx 0 i) = e`_i.\n\n(*This lemma states that the function which constructs a vector from a coordinate row vector is a linear map.*)\nLemma vecof_linear : linear vecof.\n\n(*This lemma states that converting a row vector to a vector and subsequently converting that vector back to a row vector yields the original row vector.*)\nLemma rVofK : cancel rVof vecof.\n\n(*This lemma states that converting a vector to its coordinate row vector and subsequently converting that row vector back to a vector yields the original vector.*)\nLemma vecofK : cancel vecof rVof.\n\n(*This lemma states that the coordinate row vector representation of a basis vector is the standard basis row vector, which has a one at the corresponding index and zeros elsewhere.*)\nLemma rVofE (i : 'I_n) : rVof e`_i = delta_mx 0 i.\n\n(*This lemma states that the coordinate at a given index of a vector constructed from a row vector is identical to the entry at that same index in the original row vector.*)\nLemma coord_vecof i v : coord e i (vecof v) = v 0 i.\n\n(*This lemma states that a vector is the zero vector if and only if its coordinate row vector is the zero row vector.*)\nLemma rVof_eq0 v : (rVof v == 0) = (v == 0).\n\n(*This lemma states that a row vector is the zero row vector if and only if the vector constructed from it is the zero vector.*)\nLemma vecof_eq0 v : (vecof v == 0) = (v == 0).\n\nEnd vecmx.\n\nSection hommx.\nContext {uT vT : vectType F}.\n(*A local notation representing the dimension of a given finite-dimensional vector space, which is conventionally used as the domain in a linear map context.*)\nLocal Notation m := (\\dim {:uT}).\n(*A local notation representing the dimension of a given finite-dimensional vector space, which is conventionally used as the codomain in a linear map context.*)\nLocal Notation n := (\\dim {:vT}).\n\nVariables (e : m.-tuple uT) (e' : n.-tuple vT).\n\n(*This definition constructs the matrix representation of a given linear map with respect to specified bases for the source and target vector spaces.*)\nDefinition mxof (h : 'Hom(uT, vT)) := lin1_mx (rVof e' \\o h \\o vecof e).\n\n(*This lemma states that the operation of converting a linear map into its matrix representation is itself a linear transformation.*)\nLemma mxof_linear : linear mxof.\n\nHB.instance Definition _ := GRing.isSemilinear.Build F _ _ _ mxof\n (GRing.semilinear_linear mxof_linear).\n\n(*This definition constructs a function between two vector spaces from a given matrix and bases. The function operates by taking a vector, determining its coordinates, multiplying the coordinate row vector by the matrix, and then forming the resulting vector from the new coordinates.*)\nDefinition funmx (M : 'M[F]_(m, n)) u := vecof e' (rVof e u *m M).\n\n(*This lemma states that for any given matrix, the function constructed from it based on chosen bases is a linear map.*)\nLemma funmx_linear M : linear (funmx M).\n\nHB.instance Definition _ M := GRing.isSemilinear.Build F _ _ _ (funmx M)\n (GRing.semilinear_linear (funmx_linear M)).\n\n(*This definition constructs the linear map that corresponds to a given matrix with respect to specified bases for the source and target vector spaces.*)\nDefinition hommx M : 'Hom(uT, vT) := linfun (funmx M).\n\n(*This lemma states that the operation of converting a matrix into its corresponding linear map is itself a linear transformation.*)\nLemma hommx_linear : linear hommx.\n\n(*This lemma states that applying the matrix-to-linear-map conversion followed by the linear-map-to-matrix conversion on a matrix returns the original matrix.*)\nLemma mxofK : cancel mxof hommx.\n\n(*This lemma states that applying the linear-map-to-matrix conversion followed by the matrix-to-linear-map conversion on a linear map returns the original linear map.*)\nLemma hommxK : cancel hommx mxof.\n\n(*This lemma states that multiplying a row vector of coordinates by the matrix of a linear map yields the row vector of coordinates of the image of the corresponding vector under that map.*)\nLemma mul_mxof phi u : u *m mxof phi = rVof e' (phi (vecof e u)).\n\n(*This lemma states that applying the linear map associated with a matrix to a vector is equivalent to converting the vector to its coordinate row vector, multiplying by the matrix, and then converting the resulting coordinate row vector back into a vector.*)\nLemma hommxE M u : hommx M u = vecof e' (rVof e u *m M).\n\n(*This lemma states that the product of a vector's coordinate row vector and a matrix is equal to the coordinate row vector of the vector's image under the linear map corresponding to that matrix.*)\nLemma rVof_mul M u : rVof e u *m M = rVof e' (hommx M u).\n\n(*This lemma states that applying a linear map to a vector constructed from a coordinate row vector is equivalent to first multiplying that coordinate row vector by the matrix of the linear map, and then constructing a new vector from the resulting coordinate row vector.*)\nLemma hom_vecof (phi : 'Hom(uT, vT)) u :\n phi (vecof e u) = vecof e' (u *m mxof phi).\n\n(*This lemma states that the coordinate row vector of the image of a vector under a linear map is equal to the product of the original vector's coordinate row vector and the matrix of the linear map.*)\nLemma rVof_app (phi : 'Hom(uT, vT)) u :\n rVof e' (phi u) = rVof e u *m mxof phi.\n\n(*This lemma states that constructing a vector from the product of a coordinate row vector and a matrix yields the same result as first constructing a vector from the coordinate row vector and then applying the linear map associated with the matrix.*)\nLemma vecof_mul M u : vecof e' (u *m M) = hommx M (vecof e u).\n\n(*This lemma states that the matrix representation of a linear map is the zero matrix if and only if the linear map is the zero map.*)\nLemma mxof_eq0 phi : (mxof phi == 0) = (phi == 0).\n\n(*This lemma states that the linear map corresponding to a matrix is the zero map if and only if the matrix is the zero matrix.*)\nLemma hommx_eq0 M : (hommx M == 0) = (M == 0).\n\nEnd hommx.\n\nSection hommx_comp.\n\nContext {uT vT wT : vectType F}.\n(*A local notation representing the dimension of a given finite-dimensional vector space, which is conventionally used as the domain in a linear map context.*)\nLocal Notation m := (\\dim {:uT}).\n(*A local notation representing the dimension of a given finite-dimensional vector space, which is conventionally used as the codomain in a linear map context.*)\nLocal Notation n := (\\dim {:vT}).\n(*This notation represents the dimension, as a natural number, of the final target vector space in a composition of linear maps.*)\nLocal Notation p := (\\dim {:wT}).\n\nVariables (e : m.-tuple uT) (f : n.-tuple vT) (g : p.-tuple wT).\nHypothesis e_basis: basis_of {:uT} e.\nHypothesis f_basis: basis_of {:vT} f.\nHypothesis g_basis: basis_of {:wT} g.\n\n(*This lemma asserts that the matrix representing a composition of two linear maps is obtained by multiplying their individual matrices. For a composition of a first linear map followed by a second, the resulting matrix is the product of the matrix of the first map multiplied by the matrix of the second map, with all matrices defined relative to designated bases for the domain, intermediate, and codomain vector spaces.*)\nLemma mxof_comp (phi : 'Hom(uT, vT)) (psi : 'Hom(vT, wT)) :\n mxof e g (psi \\o phi)%VF = mxof e f phi *m mxof f g psi.\n\n(*This lemma states the relationship between matrix multiplication and the composition of linear maps. It asserts that the linear map corresponding to the matrix product of a first matrix and a second matrix is the functional composition of the linear map for the second matrix followed by the linear map for the first. This corresponds to applying the linear map of the first matrix, then the linear map of the second matrix.*)\nLemma hommx_mul (A : 'M_(m,n)) (B : 'M_(n, p)) :\n hommx e g (A *m B) = (hommx f g B \\o hommx e f A)%VF.\n\nEnd hommx_comp.\n\nSection vsms.\n\nContext {vT : vectType F}.\n(*A notation for the dimension of the target vector space.*)\nLocal Notation n := (\\dim {:vT}).\n\nVariables (e : n.-tuple vT).\n\n(*This definition specifies a function that maps a vector subspace to its corresponding projection matrix, represented with respect to a given basis.*)\nDefinition msof (V : {vspace vT}) : 'M_n := mxof e e (projv V).\n\n(*This definition specifies a function that maps a matrix to the vector subspace corresponding to the image of the linear transformation represented by that matrix, with respect to a given basis.*)\nDefinition vsof (M : 'M[F]_n) := limg (hommx e e M).\n\n(*This lemma states that if a given sequence of vectors is linearly independent, then the matrix of the identity endomorphism with respect to this sequence of vectors as both the source and target basis is the identity matrix.*)\nLemma mxof1 : free e -> mxof e e \\1 = 1%:M.\n\nHypothesis e_basis : basis_of {:vT} e.\n\n(*This lemma states that, with respect to a given basis, the linear endomorphism corresponding to the identity matrix is the identity endomorphism.*)\nLemma hommx1 : hommx e e 1%:M = \\1%VF.\n\n(*This lemma states a cancellation property where applying the subspace-to-matrix conversion after the matrix-to-subspace conversion effectively acts as the identity function on matrices.*)\nLemma msofK : cancel msof vsof.\n\n(*This lemma establishes an equivalence between a vector belonging to a specific vector subspace and its coordinate representation belonging to the image of the projection matrix associated with that subspace.*)\nLemma mem_vecof u (V : {vspace vT}) : (vecof e u \\in V) = (u <= msof V)%MS.\n\n(*This lemma establishes that a vector belongs to the vector subspace generated from a given matrix if and only if the coordinate representation of that vector is in the image of the matrix.*)\nLemma rVof_sub u M : (rVof e u <= M)%MS = (u \\in vsof M).\n\n(*This lemma states that the vector subspace generated from a matrix is a subspace of another given vector subspace if and only if the first matrix is less than or equal to the projection matrix of the second subspace, according to the partial order on matrices.*)\nLemma vsof_sub M V : (vsof M <= V)%VS = (M <= msof V)%MS.\n\n(*This lemma states that the projection matrix of a vector subspace is less than or equal to another given matrix in the matrix partial order if and only if the first vector subspace is a subspace of the one generated by the second matrix.*)\nLemma msof_sub V M : (msof V <= M)%MS = (V <= vsof M)%VS.\n\n(*This lemma provides the explicit equality stating that converting a matrix to its associated vector subspace and then converting that subspace back to a matrix results in the original matrix.*)\nLemma vsofK M : (msof (vsof M) == M)%MS.\n\n(*This lemma asserts that the function mapping a vector subspace to its projection matrix is monotonic, meaning that if one subspace is contained within another, their corresponding projection matrices will respect the same inclusion-like partial order.*)\nLemma sub_msof : {mono msof : V V' / (V <= V')%VS >-> (V <= V')%MS}.\n\n(*This lemma asserts that the function mapping a matrix to its corresponding vector subspace is monotonic, meaning that if one matrix is less than or equal to another in the matrix partial order, their generated vector subspaces will exhibit the corresponding subspace inclusion.*)\nLemma sub_vsof : {mono vsof : M M' / (M <= M')%MS >-> (M <= M')%VS}.\n\n(*This lemma states that the projection matrix corresponding to the zero vector subspace is the zero matrix.*)\nLemma msof0 : msof 0 = 0.\n\n(*This lemma states that the vector subspace generated from the zero matrix is the zero vector subspace.*)\nLemma vsof0 : vsof 0 = 0%VS.\n\n(*This lemma states that the projection matrix of a vector subspace is equal to the zero matrix if and only if the subspace itself is the zero vector subspace.*)\nLemma msof_eq0 V : (msof V == 0) = (V == 0%VS).\n\n(*This lemma states that the vector subspace generated from a matrix is the zero vector subspace if and only if the matrix itself is the zero matrix.*)\nLemma vsof_eq0 M : (vsof M == 0%VS) = (M == 0).\n\nEnd vsms.\n\nSection eigen.\n\nContext {uT : vectType F}.\n\n(*This definition specifies the eigenspace of a linear endomorphism for a given scalar value as the kernel of the endomorphism minus the scalar multiple of the identity transformation.*)\nDefinition leigenspace (phi : 'End(uT)) a := lker (phi - a *: \\1%VF).\n(*This definition specifies that a scalar is an eigenvalue of a linear endomorphism if and only if its corresponding eigenspace is not the zero vector subspace.*)\nDefinition leigenvalue phi a := leigenspace phi a != 0%VS.\n\n(*A notation for the dimension of the source vector space.*)\nLocal Notation m := (\\dim {:uT}).\nVariables (e : m.-tuple uT).\nHypothesis e_basis: basis_of {:uT} e.\n(*This definition establishes that a sequence of vectors forming a basis is also linearly independent.*)\nLet e_free := basis_free e_basis.\n\n(*This lemma states that the kernel of a linear endomorphism is equal to the vector subspace generated from the kernel of the matrix representation of that endomorphism.*)\nLemma lker_ker phi : lker phi = vsof e (kermx (mxof e e phi)).\n\n(*This lemma states that the image of a linear endomorphism is equivalent to the vector subspace generated from the matrix representation of that endomorphism.*)\nLemma limgE phi : limg phi = vsof e (mxof e e phi).\n\n(*This lemma states that the eigenspace of a linear endomorphism for a given scalar is equivalent to the vector subspace generated from the eigenspace of the matrix representation of that endomorphism for the same scalar.*)\nLemma leigenspaceE f a : leigenspace f a = vsof e (eigenspace (mxof e e f) a).\n\nEnd eigen.\nEnd passmx.", - "algebra.finalg": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype finset fingroup morphism perm action.\nFrom mathcomp Require Import ssralg countalg.\n\nLocal Open Scope ring_scope.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nModule FinRing.\n\nImport GRing.Theory.\n\n#[short(type=\"finNmodType\")]\n(*This structure defines a finite module over the rig of natural numbers. It combines the properties of an N-module, which is an additive commutative monoid with scalar multiplication by natural numbers, with the constraint that the underlying type is finite.*)\nHB.structure Definition Nmodule := {M of GRing.Nmodule M & Finite M}.\n\n#[short(type=\"finZmodType\")]\n(*This structure defines a finite module over the ring of integers. It combines the properties of a Z-module, which is an additive commutative group with scalar multiplication by integers, with the constraint that the underlying type is finite. Any finite Z-module is also a finite abelian group.*)\nHB.structure Definition Zmodule := {M of GRing.Zmodule M & Finite M}.\n\nModule ZmoduleExports.\n(*This notation provides the finite group mixin for the additive group of a given finite ring-like structure, allowing its additive part to be treated as a finite group. It packages the proofs of associativity of addition, the identity property of zero, and the existence of additive inverses.*)\nNotation \"[ 'finGroupMixin' 'of' R 'for' +%R ]\" :=\n (isMulGroup.Build R (@addrA _) (@add0r _) (@addNr _))\n (format \"[ 'finGroupMixin' 'of' R 'for' +%R ]\") : form_scope.\nEnd ZmoduleExports.\nHB.export ZmoduleExports.\n\n#[short(type=\"finPzSemiRingType\")]\n(*This structure defines a finite P-zero-semiring. This is a finite algebraic structure with an additive commutative monoid and a multiplicative monoid, where multiplication distributes over addition, and the additive identity is an absorbing element for multiplication.*)\nHB.structure Definition PzSemiRing := {R of GRing.PzSemiRing R & Finite R}.\n\n#[short(type=\"finNzSemiRingType\")]\n(*This structure defines a finite semiring, which is a finite algebraic structure equipped with an associative addition and an associative multiplication, a multiplicative identity, and an additive identity that is also an absorbing element for multiplication.*)\nHB.structure Definition NzSemiRing := {R of GRing.NzSemiRing R & Finite R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.NzSemiRing instead.\")]\nNotation SemiRing R := (NzSemiRing R) (only parsing).\n\nModule SemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.NzSemiRing.sort instead.\")]\n(*A deprecated notation for the carrier type of a finite semiring. This refers to the set of elements on which the semiring operations are defined.*)\nNotation sort := (NzSemiRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.NzSemiRing.on instead.\")]\nNotation on R := (NzSemiRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.NzSemiRing.copy instead.\")]\nNotation copy T U := (NzSemiRing.copy T U) (only parsing).\nEnd SemiRing.\n\n#[short(type=\"finPzRingType\")]\n(*This structure defines a finite P-zero-ring. This is a finite algebraic structure where addition forms a commutative group and multiplication is associative and distributes over addition, and where the additive identity is an absorbing element for multiplication.*)\nHB.structure Definition PzRing := {R of GRing.PzRing R & Finite R}.\n\n#[short(type=\"finNzRingType\")]\n(*This structure defines a finite unital ring, which is a finite algebraic structure with associative addition and multiplication, additive inverses, a multiplicative identity, and where multiplication distributes over addition.*)\nHB.structure Definition NzRing := {R of GRing.NzRing R & Finite R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.NzRing instead.\")]\nNotation Ring R := (NzRing R) (only parsing).\n\nModule Ring.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.NzRing.sort instead.\")]\n(*This notation refers to the carrier type of a finite commutative non-zero semiring structure, representing the set of its elements.*)\nNotation sort := (NzRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.NzRing.on instead.\")]\nNotation on R := (NzRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.NzRing.copy instead.\")]\nNotation copy T U := (NzRing.copy T U) (only parsing).\nEnd Ring.\n\n#[short(type=\"finComPzSemiRingType\")]\n(*This definition specifies the algebraic structure of a finite commutative semiring where the additive identity (zero) and multiplicative identity (one) are not required to be distinct.*)\nHB.structure Definition ComPzSemiRing :=\n {R of GRing.ComPzSemiRing R & Finite R}.\n\n#[short(type=\"finComNzSemiRingType\")]\n(*This definition specifies the algebraic structure of a finite commutative semiring where the additive identity (zero) and multiplicative identity (one) are required to be distinct elements.*)\nHB.structure Definition ComNzSemiRing :=\n {R of GRing.ComNzSemiRing R & Finite R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.ComNzSemiRing instead.\")]\nNotation ComSemiRing R := (ComNzSemiRing R) (only parsing).\n\nModule ComSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.ComNzSemiRing.sort instead.\")]\n(*This notation provides a shorthand for accessing the underlying carrier type of a finite commutative non-zero ring structure.*)\nNotation sort := (ComNzSemiRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.ComNzSemiRing.on instead.\")]\nNotation on R := (ComNzSemiRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.ComNzSemiRing.copy instead.\")]\nNotation copy T U := (ComNzSemiRing.copy T U) (only parsing).\nEnd ComSemiRing.\n\n#[short(type=\"finComPzRingType\")]\n(*This definition specifies the structure for a finite commutative pseudo-ring, which is a type equipped with ring operations such that multiplication is commutative, the set of elements is finite, and the ring may be the trivial zero ring where the additive and multiplicative identities are equal.*)\nHB.structure Definition ComPzRing := {R of GRing.ComPzRing R & Finite R}.\n\n#[short(type=\"finComNzRingType\")]\n(*This definition specifies the structure for a finite commutative non-zero ring, which is a type equipped with ring operations such that multiplication is commutative, the set of elements is finite, and the additive and multiplicative identities are distinct.*)\nHB.structure Definition ComNzRing := {R of GRing.ComNzRing R & Finite R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.ComNzRing instead.\")]\nNotation ComRing R := (ComNzRing R) (only parsing).\n\nModule ComRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.ComNzRing.sort instead.\")]\n(*A parsing-only notation that defines 'sort' as an alias for the carrier type of a commutative non-zero ring. This allows for a generic name for the type in expressions, with the concrete type being determined by the context.*)\nNotation sort := (ComNzRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.ComNzRing.on instead.\")]\nNotation on R := (ComNzRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.ComNzRing.copy instead.\")]\nNotation copy T U := (ComNzRing.copy T U) (only parsing).\nEnd ComRing.\n\n#[short(type=\"finUnitRingType\")]\n(*This definition introduces the structure for a finite ring that has a multiplicative identity element.*)\nHB.structure Definition UnitRing := {R of GRing.UnitRing R & Finite R}.\n\n#[short(type=\"finComUnitRingType\")]\n(*This definition introduces the structure for a finite, commutative ring that has a multiplicative identity element.*)\nHB.structure Definition ComUnitRing := {R of GRing.ComUnitRing R & Finite R}.\n\n#[short(type=\"finIdomainType\")]\n(*This definition introduces the structure for a finite integral domain, which is a finite, commutative ring with no non-zero divisors of zero.*)\nHB.structure Definition IntegralDomain :=\n {R of GRing.IntegralDomain R & Finite R}.\n\n#[short(type=\"finFieldType\")]\n(*This definition introduces the structure for a finite field, which is a finite, commutative ring where every non-zero element has a multiplicative inverse.*)\nHB.structure Definition Field := {R of GRing.Field R & Finite R}.\n\n#[short(type=\"finLmodType\")]\n(*This definition specifies the structure for a finite left module over a given non-zero ring.*)\nHB.structure Definition Lmodule (R : nzRingType) :=\n {M of GRing.Lmodule R M & Finite M}.\n\n#[short(type=\"finLalgType\")]\n(*This definition introduces the structure for a finite left algebra over a given non-zero ring.*)\nHB.structure Definition Lalgebra (R : nzRingType) :=\n {M of GRing.Lalgebra R M & Finite M}.\n\n#[short(type=\"finAlgType\")]\n(*This definition introduces the structure for a finite algebra over a given non-zero ring.*)\nHB.structure Definition Algebra (R : nzRingType) :=\n {M of GRing.Algebra R M & Finite M}.\n\n#[short(type=\"finUnitAlgType\")]\n(*This definition introduces the structure for a finite unitary algebra over a given unitary ring.*)\nHB.structure Definition UnitAlgebra (R : unitRingType) :=\n {M of GRing.UnitAlgebra R M & Finite M}.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : Zmodule.type) := [finGroupMixin of R for +%R].\nCoercion Zmodule_to_baseFinGroup (R : Zmodule.type) := BaseFinGroup.clone R _.\nCoercion Zmodule_to_finGroup (R : Zmodule.type) := FinGroup.clone R _.\n\nSection AdditiveGroup.\n\nVariable U : finZmodType.\nImplicit Types x y : U.\n\n(*This lemma states that for any finite Z-module, the identity element of its underlying additive group is equal to the zero element.*)\nLemma zmod1gE : 1%g = 0 :> U. \n(*This lemma states that for any element in a finite Z-module, its inverse with respect to the underlying additive group operation is its additive opposite.*)\nLemma zmodVgE x : x^-1%g = - x. \n(*This lemma states that for any two elements in a finite Z-module, their product under the underlying additive group operation is equal to their sum.*)\nLemma zmodMgE x y : (x * y)%g = x + y. \n(*This lemma states that for any element of a finite Z-module and any natural number, raising the element to the power of the natural number under the underlying additive group operation is equivalent to the scalar multiplication of the element by that number.*)\nLemma zmodXgE n x : (x ^+ n)%g = x *+ n. \n(*This lemma states that for any two elements in a finite Z-module, the group multiplication operation, which corresponds to addition, is commutative.*)\nLemma zmod_mulgC x y : commute x y.\n\n(*This lemma states that any subset of elements from a finite Z-module forms an abelian group under the induced additive group operation.*)\nLemma zmod_abelian (A : {set U}) : abelian A.\n\nEnd AdditiveGroup.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : NzRing.type) := [finGroupMixin of R for +%R].\nCoercion NzRing_to_baseFinGroup (R : NzRing.type) := BaseFinGroup.clone R _.\nCoercion NzRing_to_finGroup (R : NzRing.type) := FinGroup.clone R _.\n\n(*This is a record factory that provides a canonical way to construct a non-zero ring structure on a given type, serving as a building block for more complex algebraic hierarchies.*)\nHB.factory Record isNzRing R of NzRing R := {}.\n\nModule isRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.isNzRing.Build instead.\")]\nNotation Build R := (isNzRing.Build R) (only parsing).\nEnd isRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use FinRing.isNzRing instead.\")]\nNotation isRing R := (isNzRing R) (only parsing).\n\nHB.builders Context R of isNzRing R.\n(*This definition provides a boolean predicate that is true if and only if two given elements of a ring are mutual multiplicative inverses, meaning their product in either order equals the multiplicative identity.*)\n Definition is_inv (x y : R) := (x * y == 1) && (y * x == 1).\n(*This definition specifies the set of all unit elements in a ring, where a unit is an element that possesses a multiplicative inverse.*)\n Definition unit := [qualify a x : R | [exists y, is_inv x y]].\n(*This definition provides a function that computes the multiplicative inverse of a given ring element. If the element is a unit, it returns its inverse; otherwise, it returns the element itself.*)\n Definition inv x := odflt x (pick (is_inv x)).\n\n(*This lemma states that for any unit element in a ring, multiplying its inverse by the element itself yields the multiplicative identity.*)\n Lemma mulVr : {in unit, left_inverse 1 inv *%R}.\n \n\n(*This lemma states that for any unit element in a ring, multiplying the element by its inverse yields the multiplicative identity.*)\n Lemma mulrV : {in unit, right_inverse 1 inv *%R}.\n \n\n(*This lemma states that a ring element is a unit if there exists another element that serves as both its left and right multiplicative inverse.*)\n Lemma intro_unit x y : y * x = 1 /\\ x * y = 1 -> x \\is a unit.\n \n\n(*This lemma states that for any ring element that is not a unit, the inverse function returns the element itself.*)\n Lemma invr_out : {in [predC unit], inv =1 id}.\n \n\n HB.instance Definition _ :=\n GRing.NzRing_hasMulInverse.Build R mulVr mulrV intro_unit invr_out.\nHB.end.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : ComNzRing.type) := [finGroupMixin of R for +%R].\nCoercion ComNzRing_to_baseFinGroup (R : ComNzRing.type) :=\n BaseFinGroup.clone R _.\nCoercion ComNzRing_to_finGroup (R : ComNzRing.type) := FinGroup.clone R _.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : UnitRing.type) := [finGroupMixin of R for +%R].\nCoercion UnitRing_to_baseFinGroup (R : UnitRing.type) := BaseFinGroup.clone R _.\nCoercion UnitRing_to_finGroup (R : UnitRing.type) := FinGroup.clone R _.\n\nSection UnitsGroup.\n\nVariable R : finUnitRingType.\n\n(*This inductive type defines the group of units of a finite unitary ring as a dependent pair, packaging a ring element with a proof that it is a unit.*)\nInductive unit_of := Unit (x : R) of x \\is a GRing.unit.\nBind Scope group_scope with unit_of.\n\nImplicit Types u v : unit_of.\n(*This definition provides a function to extract the underlying ring element from a value representing an element of the group of units.*)\nDefinition uval u := let: Unit x _ := u in x.\n\n#[export] HB.instance Definition _ := [isSub for uval].\n#[export] HB.instance Definition _ := [Finite of unit_of by <:].\n\n(*This definition specifies the identity element of the group of units, which is constructed from the multiplicative identity of the underlying ring.*)\nDefinition unit1 := Unit (@GRing.unitr1 _).\n(*This lemma states that the multiplicative inverse of a unit element in a ring is itself a unit.*)\nLemma unit_inv_proof u : (val u)^-1 \\is a GRing.unit.\n\n(*This definition specifies the inversion operation for the group of units. It computes the inverse of a given unit and packages it as an element of the group of units type.*)\nDefinition unit_inv u := Unit (unit_inv_proof u).\n(*This lemma states that the product of two unit elements in a ring is also a unit.*)\nLemma unit_mul_proof u v : val u * val v \\is a GRing.unit.\n\n(*This definition specifies the multiplication operation for the group of units. It computes the product of the underlying ring elements of two units and packages the result as an element of the group of units type.*)\nDefinition unit_mul u v := Unit (unit_mul_proof u v).\n(*This lemma states that the multiplication operation on the group of units is associative.*)\nLemma unit_muluA : associative unit_mul.\n\n(*This lemma states that the multiplicative identity of the group of units acts as a left identity for the unit multiplication operation.*)\nLemma unit_mul1u : left_id unit1 unit_mul.\n\n(*This lemma states that for any unit, its multiplicative inverse is a left inverse with respect to unit multiplication, yielding the multiplicative identity.*)\nLemma unit_mulVu : left_inverse unit1 unit_inv unit_mul.\n\n(*This lemma states that the underlying ring element corresponding to the multiplicative identity of the group of units is the multiplicative identity of the ring.*)\nLemma val_unit1 : val (1%g : unit_of) = 1. \n(*This lemma states that the underlying ring element of the product of two units is equal to the product of their respective underlying ring elements.*)\nLemma val_unitM x y : val (x * y : unit_of)%g = val x * val y.\n\n(*This lemma states that the underlying ring element of the multiplicative inverse of a unit is equal to the multiplicative inverse of the underlying ring element of that unit.*)\nLemma val_unitV x : val (x^-1 : unit_of)%g = (val x)^-1. \n(*This lemma states that the underlying ring element of a unit raised to an integer power is equal to the underlying ring element of that unit raised to the same integer power.*)\nLemma val_unitX n x : val (x ^+ n : unit_of)%g = val x ^+ n.\n\n(*This definition specifies the action of a unit on a ring element as the right multiplication of the ring element by the underlying value of the unit.*)\nDefinition unit_act x u := x * val u.\n(*This lemma provides a definitional equality for the action of a unit on a ring element, asserting that it is equivalent to right multiplication of the ring element by the underlying value of the unit.*)\nLemma unit_actE x u : unit_act x u = x * val u. \n\nCanonical unit_action :=\n @TotalAction _ _ unit_act (@mulr1 _) (fun _ _ _ => mulrA _ _ _).\n\n(*This lemma states that the canonical action of the group of units on its underlying ring satisfies the axioms of a group action.*)\nLemma unit_is_groupAction : @is_groupAction _ R setT setT unit_action.\n\nCanonical unit_groupAction := GroupAction unit_is_groupAction.\n\nEnd UnitsGroup.\n\nModule Import UnitsGroupExports.\nBind Scope group_scope with unit_of.\nArguments unit_of R%_type.\nCanonical unit_action.\nCanonical unit_groupAction.\nEnd UnitsGroupExports.\nHB.export UnitsGroupExports.\n\nNotation unit R Ux := (@Unit R%type _ Ux).\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : ComUnitRing.type) := [finGroupMixin of R for +%R].\nCoercion ComUnitRing_to_baseFinGroup (R : ComUnitRing.type) :=\n BaseFinGroup.clone R _.\nCoercion ComUnitRing_to_finGroup (R : ComUnitRing.type) :=\n FinGroup.clone R _.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : IntegralDomain.type) :=\n [finGroupMixin of R for +%R].\nCoercion IntegralDomain_to_baseFinGroup (R : IntegralDomain.type) :=\n BaseFinGroup.clone R _.\nCoercion IntegralDomain_to_finGroup (R : IntegralDomain.type) :=\n FinGroup.clone R _.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : Field.type) := [finGroupMixin of R for +%R].\nCoercion Field_to_baseFinGroup (R : Field.type) := BaseFinGroup.clone R _.\nCoercion Field_to_finGroup (R : Field.type) := FinGroup.clone R _.\n\n(*A record that encapsulates the properties defining a field structure on a given type, used as a factory to construct field instances.*)\nHB.factory Record isField F of Field F := {}.\n\nHB.builders Context F of isField F.\n(*This recursive function determines the truth value of a first-order logic formula within a given field by interpreting its atomic formulas, logical connectives, and quantifiers, using an environment that maps free variables to field elements.*)\n Fixpoint sat e f :=\n match f with\n | GRing.Bool b => b\n | t1 == t2 => (GRing.eval e t1 == GRing.eval e t2)%bool\n | GRing.Unit t => GRing.eval e t \\is a GRing.unit\n | f1 /\\ f2 => sat e f1 && sat e f2\n | f1 \\/ f2 => sat e f1 || sat e f2\n | f1 ==> f2 => (sat e f1 ==> sat e f2)%bool\n | ~ f1 => ~~ sat e f1\n | ('exists 'X_k, f1) => [exists x : F, sat (set_nth 0%R e k x) f1]\n | ('forall 'X_k, f1) => [forall x : F, sat (set_nth 0%R e k x) f1]\n end%T.\n\n(*This lemma states that the provided satisfaction function for first-order logic over a field constitutes a decision procedure, meaning it can algorithmically determine the truth of any formula.*)\n Lemma decidable : GRing.decidable_field_axiom sat.\n \n\n HB.instance Definition _ := GRing.Field_isDecField.Build F decidable.\nHB.end.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : nzRingType) (M : Lmodule.type R) :=\n [finGroupMixin of M for +%R].\n\nCoercion Lmodule_to_baseFinGroup (R : nzRingType) (M : Lmodule.type R) :=\n BaseFinGroup.clone M _.\nCoercion Lmodule_to_finGroup (R : nzRingType) (M : Lmodule.type R)\n : finGroupType :=\n FinGroup.clone (M : Type) _.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : nzRingType) (M : Lalgebra.type R) :=\n [finGroupMixin of M for +%R].\nCoercion Lalgebra_to_baseFinGroup (R : nzRingType) (M : Lalgebra.type R) :=\n BaseFinGroup.clone M _.\nCoercion Lalgebra_to_finGroup (R : nzRingType) (M : Lalgebra.type R) :=\n FinGroup.clone M _.\n\n#[export, non_forgetful_inheritance]\nHB.instance Definition _ (R : nzRingType) (M : Algebra.type R) :=\n [finGroupMixin of M for +%R].\nCoercion Algebra_to_baseFinGroup (R : nzRingType) (M : Algebra.type R) :=\n BaseFinGroup.clone M _.\nCoercion Algebra_to_finGroup (R : nzRingType) (M : Algebra.type R) :=\n FinGroup.clone M _.\n\n#[export, non_forgetful_inheritance]\n(*This lemma states that the underlying value of the additive identity element in a Z-module's corresponding additive group representation is the zero element of the Z-module.*)\nDefinition zmod1gE := zmod1gE.\n(*This lemma states that the underlying value of the additive inverse of an element in a Z-module's group representation is the additive inverse of that element's underlying value.*)\nDefinition zmodVgE := zmodVgE.\n(*This lemma states that the underlying value of the product of two elements in a Z-module's additive group representation is the sum of their individual underlying values.*)\nDefinition zmodMgE := zmodMgE.\n(*This lemma states that the underlying value of an element raised to an integer power in a Z-module's additive group representation is the result of scaling the element's underlying value by that integer.*)\nDefinition zmodXgE := zmodXgE.\n(*This lemma states that the group operation corresponding to addition in a Z-module is commutative.*)\nDefinition zmod_mulgC := zmod_mulgC.\n(*This lemma states that the additive group structure associated with a Z-module is abelian.*)\nDefinition zmod_abelian := zmod_abelian.\n(*This lemma states that for any ring with a multiplicative identity, the value of the unit element corresponding to the ring's multiplicative identity is the multiplicative identity itself.*)\nDefinition val_unit1 := val_unit1.\n(*This definition states that the function embedding the group of units into its parent ring is a monoid morphism, meaning it preserves multiplication.*)\nDefinition val_unitM := val_unitM.\n(*This definition asserts that the embedding of a unit, which is an invertible element, into its underlying ring preserves the multiplicative structure.*)\nDefinition val_unitX := val_unitX.\n(*This definition specifies that the canonical map from the group of units to the ring is a multiplicative morphism.*)\nDefinition val_unitV := val_unitV.\n(*This definition provides the evaluation rule for the action of a ring's unit group on a module, stating that the action of a unit on a module element corresponds to the scalar multiplication of the element by the ring element underlying the unit.*)\nDefinition unit_actE := unit_actE.\n\nEnd Theory.\n\nEnd FinRing.\n\nImport FinRing.\nHB.reexport.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use finNzSemiRingType instead.\")]\n(*A deprecated notation, which should be replaced by `finNzSemiRingType`, for the type of finite, non-trivial semirings, defined as semirings where the additive identity is distinct from the multiplicative identity.*)\nNotation finSemiRingType := (finNzSemiRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use finNzRingType instead.\")]\n(*A deprecated notation, which should be replaced by `finNzRingType`, for the type of finite, non-trivial rings, defined as rings where the additive identity is distinct from the multiplicative identity.*)\nNotation finRingType := (finNzRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use finComNzSemiRingType instead.\")]\n(*A deprecated notation, which should be replaced by `finComNzSemiRingType`, for the type of finite, commutative, non-trivial semirings, defined as semirings where the additive identity is distinct from the multiplicative identity.*)\nNotation finComSemiRingType := (finComNzSemiRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use finComNzRingType instead.\")]\n(*A deprecated notation, which should be replaced by `finComNzRingType`, for the type of finite, commutative, non-trivial rings, defined as rings where the additive identity is distinct from the multiplicative identity.*)\nNotation finComRingType := (finComNzRingType) (only parsing).\n\n(*This lemma states that the cardinality of any finite non-trivial ring is strictly greater than one.*)\nLemma card_finNzRing_gt1 (R : finNzRingType) : 1 < #|R|.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use card_finNzRing_gt1 instead.\")]\n(*A deprecated notation, which should be replaced by `card_finNzRing_gt1`, for the lemma stating that the number of elements in any finite non-trivial ring is greater than one.*)\nNotation card_finRing_gt1 := (card_finNzRing_gt1) (only parsing).\n\n(*A notation for the type of invertible elements, also known as units, of a given ring.*)\nNotation \"{ 'unit' R }\" := (unit_of R) (format \"{ 'unit' R }\") : type_scope.\nPrenex Implicits FinRing.uval.\n(*A notation for the canonical action of a ring's group of units on an inferred module. This notation can represent either a basic multiplicative action structure or a full group action structure, which includes proofs of the group action axioms, depending on the context.*)\nNotation \"''U'\" := (unit_action _) : action_scope.\n(*This instance endows the boolean type with a canonical non-zero ring structure.*)\nNotation \"''U'\" := (unit_groupAction _) : groupAction_scope.\n\n(*This lemma states that for any finite field, the number of units is equal to the total number of elements in the field minus one.*)\nLemma card_finField_unit (F : finFieldType) : #|[set: {unit F}]| = #|F|.-1.\n\n#[hnf] HB.instance Definition _ := GRing.NzRing.on bool.", - "algebra.all_algebra": "From mathcomp Require Export ssralg.\nFrom mathcomp Require Export ssrnum.\nFrom mathcomp Require Export finalg.\nFrom mathcomp Require Export countalg.\nFrom mathcomp Require Export poly.\nFrom mathcomp Require Export polydiv.\nFrom mathcomp Require Export polyXY.\nFrom mathcomp Require Export qpoly.\nFrom mathcomp Require Export ssrint.\nFrom mathcomp Require Export archimedean.\nFrom mathcomp Require Export rat.\nFrom mathcomp Require Export intdiv.\nFrom mathcomp Require Export interval.\nFrom mathcomp Require Import interval_inference.\nFrom mathcomp Require Export matrix.\nFrom mathcomp Require Export mxpoly.\nFrom mathcomp Require Export mxalgebra.\nFrom mathcomp Require Export mxred.\nFrom mathcomp Require Export vector.\nFrom mathcomp Require Export ring_quotient.\nFrom mathcomp Require Export fraction.\nFrom mathcomp Require Export zmodp.\nFrom mathcomp Require Export sesquilinear.", - "algebra.mxred": "From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype finfun bigop fingroup perm order.\nFrom mathcomp Require Import ssralg zmodp matrix mxalgebra poly polydiv mxpoly.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GRing.Theory.\nImport Monoid.Theory.\n\nLocal Open Scope ring_scope.\n\nSection ConjMx.\nContext {F : fieldType}.\n\n(*This definition calculates the matrix representing a linear transformation on a subspace. It takes a matrix whose rows span the subspace and a square matrix representing the linear map, and returns a new square matrix computed as the product of the spanning matrix, the linear map's matrix, and the pseudo-inverse of the spanning matrix.*)\nDefinition conjmx (m n : nat)\n (V : 'M_(m, n)) (f : 'M[F]_n) : 'M_m := V *m f *m pinvmx V.\nNotation restrictmx V := (conjmx (row_base V)).\n\n(*This lemma states that if a first subspace is stable under a given linear map, and a second subspace is stable under the map restricted to the first subspace, then the composite subspace is stable under the original linear map.*)\nLemma stablemx_comp (m n p : nat) (V : 'M[F]_(m, n)) (W : 'M_(n, p)) (f : 'M_p) :\n stablemx W f -> stablemx V (conjmx W f) -> stablemx (V *m W) f.\n\n(*This lemma states that for a subspace stable under a linear map, checking the stability of a second subspace under the restricted linear map is equivalent to checking the stability of the composed subspace under the original linear map.*)\nLemma stablemx_restrict m n (A : 'M[F]_n) (V : 'M_n) (W : 'M_(m, \\rank V)):\n stablemx V A -> stablemx W (restrictmx V A) = stablemx (W *m row_base V) A.\n\n(*This lemma states that the matrix conjugation operation with respect to a given matrix is a homomorphism for matrix multiplication. Specifically, conjugating the product of two matrices gives the same result as multiplying their individual conjugated forms, provided the subspace associated with the conjugation matrix is stable under both original matrices.*)\nLemma conjmxM (m n : nat) (V : 'M[F]_(m, n)) :\n {in [pred f | stablemx V f] &, {morph conjmx V : f g / f *m g}}.\n\n(*This lemma states that matrix conjugation is transitive. Conjugating a matrix by the product of two other matrices is equivalent to successively conjugating by the second matrix and then by the first, under certain conditions of row independence and subspace stability.*)\nLemma conjMmx (m n p : nat) (V : 'M[F]_(m, n)) (W : 'M_(n, p)) (f : 'M_p) :\n row_free (V *m W) -> stablemx W f -> stablemx V (conjmx W f) ->\n conjmx (V *m W) f = conjmx V (conjmx W f).\n\n(*This lemma provides a transitivity property for matrix conjugation, stating that conjugating by a product of an invertible matrix and another matrix is equivalent to sequential conjugation, first by the second matrix and then by the first, given that the second matrix has linearly independent rows and defines a stable subspace for the matrix being conjugated.*)\nLemma conjuMmx (m n : nat) (V : 'M[F]_m) (W : 'M_(m, n)) (f : 'M_n) :\n V \\in unitmx -> row_free W -> stablemx W f ->\n conjmx (V *m W) f = conjmx V (conjmx W f).\n\n(*This lemma states a transitivity property for matrix conjugation where the inner conjugation matrix is invertible. Conjugating by a product of two matrices where the second is invertible is equivalent to sequential conjugation, provided the first matrix has linearly independent rows and is stable under the map conjugated by the second matrix.*)\nLemma conjMumx (m n : nat) (V : 'M[F]_(m, n)) (W f : 'M_n) :\n W \\in unitmx -> row_free V -> stablemx V (conjmx W f) ->\n conjmx (V *m W) f = conjmx V (conjmx W f).\n\n(*This lemma states that for square invertible matrices, matrix conjugation is transitive. Conjugating a matrix by the product of two invertible matrices is equivalent to conjugating by the second matrix and then conjugating the result by the first.*)\nLemma conjuMumx (n : nat) (V W f : 'M[F]_n) :\n V \\in unitmx -> W \\in unitmx ->\n conjmx (V *m W) f = conjmx V (conjmx W f).\n\n(*This lemma states that conjugating a scalar matrix by any matrix with linearly independent rows leaves the scalar matrix unchanged.*)\nLemma conjmx_scalar (m n : nat) (V : 'M[F]_(m, n)) (a : F) :\n row_free V -> conjmx V a%:M = a%:M.\n\n(*This lemma states that conjugating any matrix by a zero matrix of appropriate dimensions results in a zero matrix.*)\nLemma conj0mx (m n : nat) f : conjmx (0 : 'M[F]_(m, n)) f = 0.\n\n(*This lemma states that conjugating a zero matrix by any other matrix results in a zero matrix.*)\nLemma conjmx0 (m n : nat) (V : 'M[F]_(m, n)) : conjmx V 0 = 0.\n\n(*This lemma states that for an invertible square matrix, the general matrix conjugation operation simplifies to the standard similarity transformation, which is the product of the given matrix, the matrix to be conjugated, and the inverse of the given matrix.*)\nLemma conjumx (n : nat) (V : 'M_n) (f : 'M[F]_n) : V \\in unitmx ->\n conjmx V f = V *m f *m invmx V.\n\n(*This lemma states that conjugating any square matrix by the identity matrix of the same size leaves the matrix unchanged.*)\nLemma conj1mx (n : nat) (f : 'M[F]_n) : conjmx 1%:M f = f.\n\n(*This lemma states that for an invertible matrix, conjugating another matrix by its inverse is equivalent to performing a similarity transformation involving the product of the inverse matrix, the other matrix, and the original invertible matrix.*)\nLemma conjVmx (n : nat) (V : 'M_n) (f : 'M[F]_n) : V \\in unitmx ->\n conjmx (invmx V) f = invmx V *m f *m V.\n\n(*This lemma states that for an invertible matrix, applying a conjugation by the inverse matrix after a conjugation by the original matrix cancels the operation and returns the initial matrix.*)\nLemma conjmxK (n : nat) (V f : 'M[F]_n) :\n V \\in unitmx -> conjmx (invmx V) (conjmx V f) = f.\n\n(*This lemma states that for an invertible matrix, applying a conjugation by the matrix after a conjugation by its inverse cancels the operation and returns the initial matrix.*)\nLemma conjmxVK (n : nat) (V f : 'M[F]_n) :\n V \\in unitmx -> conjmx V (conjmx (invmx V) f) = f.\n\n(*This lemma states that matrix conjugation commutes with polynomial evaluation. Evaluating a polynomial at a conjugated matrix is equivalent to conjugating the result of evaluating the same polynomial at the original matrix, provided the conjugation matrix has linearly independent rows and defines a stable subspace.*)\nLemma horner_mx_conj m n p (B : 'M[F]_(n.+1, m.+1)) (f : 'M_m.+1) :\n row_free B -> stablemx B f ->\n horner_mx (conjmx B f) p = conjmx B (horner_mx f p).\n\n(*This lemma states that similarity transformation commutes with polynomial evaluation. Evaluating a polynomial at a matrix that has been transformed by similarity is equivalent to applying the same similarity transformation to the result of evaluating the polynomial at the original matrix.*)\nLemma horner_mx_uconj n p (B : 'M[F]_(n.+1)) (f : 'M_n.+1) :\n B \\is a GRing.unit ->\n horner_mx (B *m f *m invmx B) p = B *m horner_mx f p *m invmx B.\n\n(*This lemma states that a similarity transformation using the inverse of an invertible matrix commutes with polynomial evaluation. Evaluating a polynomial at a matrix transformed by the inverse is equivalent to transforming the result of the polynomial evaluation by the same inverse similarity transformation.*)\nLemma horner_mx_uconjC n p (B : 'M[F]_(n.+1)) (f : 'M_n.+1) :\n B \\is a GRing.unit ->\n horner_mx (invmx B *m f *m B) p = invmx B *m horner_mx f p *m B.\n\n(*This lemma states that under conditions of row independence and subspace stability, the minimal polynomial of a conjugated matrix divides the minimal polynomial of the original matrix.*)\nLemma mxminpoly_conj m n (V : 'M[F]_(m.+1, n.+1)) (f : 'M_n.+1) :\n row_free V -> stablemx V f -> mxminpoly (conjmx V f) %| mxminpoly f.\n\n(*This lemma states that the minimal polynomial of a matrix is invariant under similarity transformations, meaning that two matrices related by such a transformation share the same minimal polynomial.*)\nLemma mxminpoly_uconj n (V : 'M[F]_(n.+1)) (f : 'M_n.+1) :\n V \\in unitmx -> mxminpoly (conjmx V f) = mxminpoly f.\n\nSection fixed_stablemx_space.\nVariables (m n : nat).\nImplicit Types (V : 'M[F]_(m, n)) (f : 'M[F]_n).\nImplicit Types (a : F) (p : {poly F}).\n\nSection Sub.\nVariable (k : nat).\nImplicit Types (W : 'M[F]_(k, m)).\n\n(*This lemma states that a subspace is contained in the kernel of a polynomial evaluated at a conjugated matrix if and only if the image of that subspace under the conjugation transformation is contained in the kernel of the same polynomial evaluated at the original matrix, given conditions of row independence and stability.*)\nLemma sub_kermxpoly_conjmx V f p W : stablemx V f -> row_free V ->\n (W <= kermxpoly (conjmx V f) p)%MS = (W *m V <= kermxpoly f p)%MS.\n\n(*This lemma establishes a correspondence between the eigenspaces of a matrix and its conjugated form. It states that a subspace is contained within the eigenspace of a conjugated matrix for a given eigenvalue if and only if the image of that subspace under the conjugation transformation is contained within the eigenspace of the original matrix for the same eigenvalue, under conditions of stability and row independence.*)\nLemma sub_eigenspace_conjmx V f a W : stablemx V f -> row_free V ->\n (W <= eigenspace (conjmx V f) a)%MS = (W *m V <= eigenspace f a)%MS.\n\nEnd Sub.\n\n(*This lemma states that the characteristic polynomial of a conjugated matrix divides the characteristic polynomial of the original matrix, provided the conjugation is performed with respect to a stable subspace with a basis of linearly independent rows.*)\nLemma eigenpoly_conjmx V f : stablemx V f -> row_free V ->\n {subset eigenpoly (conjmx V f) <= eigenpoly f}.\n\n(*This lemma states that under conditions of row independence and subspace stability, any eigenvalue of a conjugated matrix is also an eigenvalue of the original matrix.*)\nLemma eigenvalue_conjmx V f : stablemx V f -> row_free V ->\n {subset eigenvalue (conjmx V f) <= eigenvalue f}.\n\n(*This lemma states that if a matrix with linearly independent rows spans a subspace that is entirely contained within an eigenspace of another matrix for a specific eigenvalue, then the conjugation of the second matrix by the first yields the scalar matrix corresponding to that eigenvalue.*)\nLemma conjmx_eigenvalue a V f : (V <= eigenspace f a)%MS -> row_free V ->\n conjmx V f = a%:M.\n\nEnd fixed_stablemx_space.\nEnd ConjMx.\nNotation restrictmx V := (conjmx (row_base V)).\n\n(*This definition provides a generalized notion of similarity, stating that a matrix is 'similar to' a given property via a transformation matrix if the result of conjugating the original matrix by the transformation matrix satisfies that property.*)\nDefinition similar_to {F : fieldType} {m n} (P : 'M_(m, n)) A\n (C : {pred 'M[F]_m}) := C (conjmx P A).\n\nNotation similar P A B := (similar_to P A (PredOfSimpl.coerce (pred1 B))).\nNotation similar_in D A B := (exists2 P, P \\in D & similar P A B).\nNotation similar_in_to D A C := (exists2 P, P \\in D & similar_to P A C).\nNotation all_similar_to D As C := (exists2 P, P \\in D & all [pred A | similar_to P A C] As).\n\nNotation similar_diag P A := (similar_to P A is_diag_mx).\nNotation diagonalizable_in D A := (similar_in_to D A is_diag_mx).\nNotation diagonalizable A := (diagonalizable_in unitmx A).\nNotation codiagonalizable_in D As := (all_similar_to D As is_diag_mx).\nNotation codiagonalizable As := (codiagonalizable_in unitmx As).\n\nNotation similar_trig P A := (similar_to P A is_trig_mx).\nNotation trigonalizable_in D A := (similar_in_to D A is_trig_mx).\nNotation trigonalizable A := (trigonalizable_in unitmx A).\nNotation cotrigonalizable_in D As := (all_similar_to D As is_trig_mx).\nNotation cotrigonalizable As := (cotrigonalizable_in unitmx As).\n\nSection Similarity.\nContext {F : fieldType}.\n\n(*This lemma states that if a matrix A is similar to a matrix B via a transformation matrix P, and the subspace associated with P is stable under A, then the product of P and A is equal to the product of B and P.*)\nLemma similarPp m n {P : 'M[F]_(m, n)} {A B} :\n stablemx P A -> similar P A B -> P *m A = B *m P.\n\n(*This lemma states that if a transformation matrix with linearly independent rows satisfies the intertwining relation where that matrix times a first matrix equals a second matrix times the transformation matrix, then the first matrix is similar to the second matrix via the transformation matrix.*)\nLemma similarW m n {P : 'M[F]_(m, n)} {A B} : row_free P ->\n P *m A = B *m P -> similar P A B.\n\nSection Similar.\n\nContext {n : nat}.\nImplicit Types (f g p : 'M[F]_n) (fs : seq 'M[F]_n) (d : 'rV[F]_n).\n\n(*This lemma states that for an invertible square matrix, the general definition of matrix similarity is equivalent to the standard definition, where one matrix is obtained from another by a similarity transformation using the invertible matrix and its inverse.*)\nLemma similarP {p f g} : p \\in unitmx ->\n reflect (p *m f = g *m p) (similar p f g).\n\n(*This lemma states that for an invertible matrix, similarity between two other matrices is equivalent to one matrix being the result of conjugating the other by the invertible matrix.*)\nLemma similarRL {p f g} : p \\in unitmx ->\n reflect (g = p *m f *m invmx p) (similar p f g).\n\n(*This lemma states that for an invertible matrix, two other matrices are similar if and only if one matrix is equal to the conjugation of the other by the inverse of the invertible matrix.*)\nLemma similarLR {p f g} : p \\in unitmx ->\n reflect (f = conjmx (invmx p) g) (similar p f g).\n\nEnd Similar.\n\n(*This lemma states that if two square matrices are similar by means of an invertible matrix, then their minimal polynomials are identical.*)\nLemma similar_mxminpoly {n} {p f g : 'M[F]_n.+1} : p \\in unitmx ->\n similar p f g -> mxminpoly f = mxminpoly g.\n\n(*This lemma states that a square matrix is diagonally similar with respect to the basis formed by the rows of a given matrix if and only if the restriction of the square matrix's transformation to the subspace spanned by those rows is represented by a diagonal matrix.*)\nLemma similar_diag_row_base m n (P : 'M[F]_(m, n)) (A : 'M_n) :\n similar_diag (row_base P) A = is_diag_mx (restrictmx P A).\n\n(*This lemma states that a square matrix is diagonally similar with respect to a given change-of-basis matrix if and only if all off-diagonal entries of the conjugation of the square matrix by the change-of-basis matrix are zero.*)\nLemma similar_diagPp m n (P : 'M[F]_(m, n)) A :\n reflect (forall i j : 'I__, i != j :> nat -> conjmx P A i j = 0)\n (similar_diag P A).\n\n(*This lemma states that for an invertible square matrix, a second square matrix is diagonally similar with respect to it if and only if the matrix product of the invertible matrix, the second matrix, and the inverse of the invertible matrix results in a diagonal matrix.*)\nLemma similar_diagP n (P : 'M[F]_n) A : P \\in unitmx ->\n reflect (forall i j : 'I__, i != j :> nat -> (P *m A *m invmx P) i j = 0)\n (similar_diag P A).\n\n(*This lemma relates diagonal similarity to matrix similarity, stating that a matrix is diagonally similar with respect to a change-of-basis matrix if and only if there exists a diagonal matrix to which the first matrix is similar, with the change-of-basis matrix acting as the similarity transformation.*)\nLemma similar_diagPex {m} {n} {P : 'M[F]_(m, n)} {A} :\n reflect (exists D, similar P A (diag_mx D)) (similar_diag P A).\n\n(*This lemma states that for an invertible square matrix, a second square matrix is diagonally similar with respect to it if and only if the second matrix is equal to the conjugation of some diagonal matrix by the inverse of the invertible matrix.*)\nLemma similar_diagLR n {P : 'M[F]_n} {A} : P \\in unitmx ->\n reflect (exists D, A = conjmx (invmx P) (diag_mx D)) (similar_diag P A).\n\n(*This lemma states that for an invertible matrix and a second square matrix that is diagonally similar with respect to it, the minimal polynomial of the second matrix is the product of linear polynomials, where each polynomial corresponds to a distinct diagonal entry of the resulting diagonal matrix.*)\nLemma similar_diag_mxminpoly {n} {p f : 'M[F]_n.+1}\n (rs := undup [seq conjmx p f i i | i <- enum 'I_n.+1]) :\n p \\in unitmx -> similar_diag p f ->\n mxminpoly f = \\prod_(r <- rs) ('X - r%:P).\n\nEnd Similarity.\n\n(*This lemma states that for a square matrix and a collection of matrices representing subspaces that form a direct sum, are row-free, and are stable under the square matrix's transformation, the square matrix is diagonally similar with respect to the combined basis if and only if it is diagonally similar with respect to the basis of each individual subspace.*)\nLemma similar_diag_sum (F : fieldType) (m n : nat) (p_ : 'I_n -> nat)\n (V_ : forall i, 'M[F]_(p_ i, m)) (f : 'M[F]_m) :\n mxdirect (\\sum_i <>) ->\n (forall i, stablemx (V_ i) f) ->\n (forall i, row_free (V_ i)) ->\n similar_diag (\\mxcol_i V_ i) f = [forall i, similar_diag (V_ i) f].\n\nSection Diag.\nVariable (F : fieldType).\n\n(*This lemma states that a sequence of matrices containing only a single matrix is codiagonalizable if and only if that single matrix is diagonalizable.*)\nLemma codiagonalizable1 n (A : 'M[F]_n) :\n codiagonalizable [:: A] <-> diagonalizable A.\n\n(*This lemma states that a sequence of square matrices is codiagonalizable if and only if there exists a single change-of-basis matrix with full row rank that makes every matrix in the sequence diagonally similar.*)\nLemma codiagonalizablePfull n (As : seq 'M[F]_n) :\n codiagonalizable As <-> exists m,\n exists2 P : 'M_(m, n), row_full P & all [pred A | similar_diag P A] As.\n\n(*This lemma states that a sequence of matrices is codiagonalizable if the underlying vector space can be decomposed into a direct sum of subspaces, where each subspace is stable under all matrices in the sequence, and the sequence of restrictions of the matrices to each subspace is itself codiagonalizable.*)\nLemma codiagonalizable_on m n (V_ : 'I_n -> 'M[F]_m) (As : seq 'M[F]_m) :\n (\\sum_i V_ i :=: 1%:M)%MS -> mxdirect (\\sum_i V_ i) ->\n (forall i, all (fun A => stablemx (V_ i) A) As) ->\n (forall i, codiagonalizable (map (restrictmx (V_ i)) As)) -> codiagonalizable As.\n\n(*This lemma states that any diagonal matrix is diagonalizable.*)\nLemma diagonalizable_diag {n} (d : 'rV[F]_n) : diagonalizable (diag_mx d).\n\nHint Resolve diagonalizable_diag : core.\n\n(*This lemma states that any scalar matrix is diagonalizable.*)\nLemma diagonalizable_scalar {n} (a : F) : diagonalizable (a%:M : 'M_n).\n\nHint Resolve diagonalizable_scalar : core.\n\n(*This lemma states that the zero matrix is diagonalizable.*)\nLemma diagonalizable0 {n} : diagonalizable (0 : 'M[F]_n).\n\nHint Resolve diagonalizable0 : core.\n\n(*This lemma states that a square matrix is diagonalizable if and only if there exists a sequence of distinct scalars for which the sum of the corresponding eigenspaces of the matrix equals the entire vector space.*)\nLemma diagonalizablePeigen {n} {f : 'M[F]_n} :\n diagonalizable f <->\n exists2 rs, uniq rs & (\\sum_(r <- rs) eigenspace f r :=: 1%:M)%MS.\n\n(*This lemma provides a characterization of a diagonalizable matrix, stating that a square matrix is diagonalizable if and only if its minimal polynomial divides a product of distinct linear factors.*)\nLemma diagonalizableP n' (n := n'.+1) (f : 'M[F]_n) :\n diagonalizable f <->\n exists2 rs, uniq rs & mxminpoly f %| \\prod_(x <- rs) ('X - x%:P).\n\n(*This lemma states that the matrix representing the restriction of a diagonal matrix's transformation to a stable subspace is diagonalizable, provided the subspace is spanned by linearly independent vectors.*)\nLemma diagonalizable_conj_diag m n (V : 'M[F]_(m, n)) (d : 'rV[F]_n) :\n stablemx V (diag_mx d) -> row_free V -> diagonalizable (conjmx V (diag_mx d)).\n\n(*This lemma states that a sequence of square matrices is codiagonalizable if and only if there exists a single invertible matrix that, when used for a similarity transformation, diagonalizes every matrix in the sequence.*)\nLemma codiagonalizableP n (fs : seq 'M[F]_n) :\n {in fs &, forall f g, comm_mx f g} /\\ (forall f, f \\in fs -> diagonalizable f)\n <-> codiagonalizable fs.", - "algebra.poly": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype bigop finset tuple div ssralg.\nFrom mathcomp Require Import countalg binomial.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope unity_root_scope.\n\nImport GRing.Theory.\nLocal Open Scope ring_scope.\n\nReserved Notation \"{ 'poly' T }\" (format \"{ 'poly' T }\").\nReserved Notation \"c %:P\" (format \"c %:P\").\nReserved Notation \"p ^:P\" (format \"p ^:P\").\nReserved Notation \"'X\".\nReserved Notation \"''X^' n\" (at level 3, n at level 2, format \"''X^' n\").\nReserved Notation \"\\poly_ ( i < n ) E\"\n (at level 36, E at level 36, i, n at level 50,\n format \"\\poly_ ( i < n ) E\").\nReserved Notation \"p \\Po q\" (at level 50).\nReserved Notation \"p ^`N ( n )\" (format \"p ^`N ( n )\").\nReserved Notation \"n .-unity_root\" (format \"n .-unity_root\").\nReserved Notation \"n .-primitive_root\" (format \"n .-primitive_root\").\n\n(*This is a local notation for simplifying expressions within a monoid structure.*)\nLocal Notation simp := Monoid.simpm.\n\nSection Polynomial.\n\nVariable R : nzSemiRingType.\n\n(*This record defines a univariate polynomial over a ring. A polynomial is represented by a finite sequence of its coefficients, with the constraint that the last element of the sequence, corresponding to the leading coefficient, must be non-zero unless the polynomial is the zero polynomial.*)\nRecord polynomial := Polynomial {polyseq :> seq R; _ : last 1 polyseq != 0}.\n\nHB.instance Definition _ := [isSub for polyseq].\n(*This lemma states that the function which extracts the sequence of coefficients from a polynomial is injective. Consequently, two polynomials are equal if and only if their corresponding sequences of coefficients are equal.*)\nLemma poly_inj : injective polyseq. \n\n(*This definition provides a function to retrieve the coefficient of a polynomial at a specified degree index.*)\nDefinition coefp i (p : polynomial) := p`_i.\n\nEnd Polynomial.\n\nBind Scope ring_scope with polynomial.\nArguments polynomial R%_type.\nArguments polyseq {R} p%_R.\nArguments poly_inj {R} [p1%_R p2%_R] : rename.\nArguments coefp {R} i%_N / p%_R.\n(*This notation represents the type of univariate polynomials whose coefficients are elements of a given ring type.*)\nNotation \"{ 'poly' T }\" := (polynomial T) : type_scope.\n\nSection SemiPolynomialTheory.\n\nVariable R : nzSemiRingType.\nImplicit Types (a b c x y z : R) (p q r d : {poly R}).\n\n(*This definition gives the leading coefficient of a polynomial, which is the coefficient of its highest degree term.*)\nDefinition lead_coef p := p`_(size p).-1.\n(*This lemma states that the leading coefficient of a polynomial is equal to its coefficient at the index corresponding to its degree, which is its size minus one.*)\nLemma lead_coefE p : lead_coef p = p`_(size p).-1. \n\n(*This definition represents the zero polynomial, which has no non-zero coefficients.*)\nDefinition poly_nil := @Polynomial R [::] (oner_neq0 R).\n(*This definition constructs a constant polynomial from a given ring element. If the element is zero, it produces the zero polynomial.*)\nDefinition polyC c : {poly R} := insubd poly_nil [:: c].\n\n(**)\nLocal Notation \"c %:P\" := (polyC c).\n\n(*This lemma states that the coefficient sequence of a constant polynomial created from a ring element is a sequence containing only that element if it is non-zero, and an empty sequence otherwise.*)\nLemma polyseqC c : c%:P = nseq (c != 0) c :> seq R.\n\n(*This lemma states that the size of a constant polynomial generated from a ring element is one if the element is non-zero, and zero if the element is zero.*)\nLemma size_polyC c : size c%:P = (c != 0).\n\n(*This lemma asserts that for a constant polynomial, the coefficient at index zero is the constant value itself, while coefficients at all other indices are zero.*)\nLemma coefC c i : c%:P`_i = if i == 0 then c else 0.\n\n(*This lemma states that retrieving the constant term of a constant polynomial returns the original ring element from which it was constructed.*)\nLemma polyCK : cancel polyC (coefp 0).\n\n(*This lemma states that the function for creating constant polynomials is injective, meaning two ring elements are equal if and only if their corresponding constant polynomials are equal.*)\nLemma polyC_inj : injective polyC.\n\n(*This lemma states that the leading coefficient of a constant polynomial is the ring element from which it was created.*)\nLemma lead_coefC c : lead_coef c%:P = c.\n\n(*This lemma provides an extensionality principle for polynomials, stating that two polynomials are equal if and only if they are equal as functions from indices to coefficients.*)\nLemma polyP p q : nth 0 p =1 nth 0 q <-> p = q.\n\n(*This lemma states that any polynomial with a size of at most one must be a constant polynomial, and is equal to the constant polynomial formed from its own coefficient at index zero.*)\nLemma size1_polyC p : size p <= 1 -> p = (p`_0)%:P.\n\n(*This definition constructs a new polynomial by prepending a given ring element as the new constant coefficient, effectively shifting all existing terms of the original polynomial to the next higher degree.*)\nDefinition cons_poly c p : {poly R} :=\n if p is Polynomial ((_ :: _) as s) ns then\n @Polynomial R (c :: s) ns\n else c%:P.\n\n(*This lemma describes the coefficient sequence of a polynomial created by prepending a new constant coefficient: it is the new coefficient followed by the original polynomial's sequence, unless the original polynomial was zero, in which case it is simply the constant polynomial of the new coefficient.*)\nLemma polyseq_cons c p :\n cons_poly c p = (if ~~ nilp p then c :: p else c%:P) :> seq R.\n\n(*This lemma specifies the size of a polynomial after prepending a new constant coefficient. The size increases by one, unless adding a zero coefficient to the zero polynomial, which results in the zero polynomial of size zero.*)\nLemma size_cons_poly c p :\n size (cons_poly c p) = (if nilp p && (c == 0) then 0 else (size p).+1).\n\n(*This lemma describes the coefficients of a polynomial constructed by prepending a constant: the coefficient at index zero is the new constant, and any other coefficient at index i corresponds to the coefficient at index i minus one of the original polynomial.*)\nLemma coef_cons c p i : (cons_poly c p)`_i = if i == 0 then c else p`_i.-1.\n\n(*This definition provides a function to convert a finite sequence of ring elements, representing coefficients, into a canonical polynomial. It trims any extraneous leading zeros from the sequence.*)\nDefinition Poly := foldr cons_poly 0%:P.\n\n(*This lemma states that converting a finite sequence of ring elements into a polynomial results in a polynomial whose underlying sequence is identical to the original one, provided the original sequence is already in canonical form (e.g. its last element is non-zero).*)\nLemma PolyK c s : last c s != 0 -> Poly s = s :> seq R.\n\n(*This lemma states that applying the polynomial construction function to the coefficient sequence of an already-existing polynomial returns the original polynomial, showing the function is an identity for canonical representations.*)\nLemma polyseqK p : Poly p = p.\n\n(*This lemma asserts that the size of a polynomial constructed from a sequence of coefficients is at most the length of that sequence, as leading zeros may be removed.*)\nLemma size_Poly s : size (Poly s) <= size s.\n\n(*This lemma states that the coefficients of a polynomial constructed from a sequence of ring elements are identical to the elements of that sequence at corresponding indices.*)\nLemma coef_Poly s i : (Poly s)`_i = s`_i.\n\n(*This definition specifies how to construct a polynomial from a given length and a function that generates a coefficient for each index up to that length.*)\nDefinition poly_expanded_def n E := Poly (mkseq E n).\n(*This fact defines a key used to lock the definition of the polynomial constructor, making it opaque and preventing its direct unfolding during proofs.*)\nFact poly_key : unit. \n(*This definition provides an opaque function for building a polynomial by specifying its length and a function to generate its coefficients, serving as the basis for big operator notation for polynomials.*)\nDefinition poly := locked_with poly_key poly_expanded_def.\nCanonical poly_unlockable := [unlockable fun poly].\n(**)\nLocal Notation \"\\poly_ ( i < n ) E\" := (poly n (fun i : nat => E)).\n\n(*This lemma states that a polynomial constructed from a coefficient function up to a certain degree bound is represented by the finite sequence of its coefficients, provided the leading coefficient is not zero.*)\nLemma polyseq_poly n E :\n E n.-1 != 0 -> \\poly_(i < n) E i = mkseq [eta E] n :> seq R.\n\n(*This lemma states that the size of a polynomial constructed from a coefficient function over a given range is less than or equal to the upper bound of that range.*)\nLemma size_poly n E : size (\\poly_(i < n) E i) <= n.\n\n(*This lemma states that if the leading coefficient is non-zero, the size of a polynomial constructed from a coefficient function over a given range is equal to the upper bound of that range.*)\nLemma size_poly_eq n E : E n.-1 != 0 -> size (\\poly_(i < n) E i) = n.\n\n(*This lemma states that the coefficient for a given degree of a polynomial constructed from a function is equal to the value of that function at that degree if the degree is within the specified range, and zero otherwise.*)\nLemma coef_poly n E k : (\\poly_(i < n) E i)`_k = (if k < n then E k else 0).\n\n(*This lemma states that for a non-zero polynomial constructed from a coefficient function over a positive-length range, its leading coefficient is the value of the function at the highest index of the range, provided that value is not zero.*)\nLemma lead_coef_poly n E :\n n > 0 -> E n.-1 != 0 -> lead_coef (\\poly_(i < n) E i) = E n.-1.\n\n(*This lemma states that any polynomial is equal to the polynomial reconstructed from its own sequence of coefficients up to its size.*)\nLemma coefK p : \\poly_(i < size p) p`_i = p.\n\n(*This definition specifies polynomial addition by constructing a new polynomial whose coefficients are the sum of the corresponding coefficients of the two input polynomials, up to the maximum of their sizes.*)\nDefinition add_poly_def p q := \\poly_(i < maxn (size p) (size q)) (p`_i + q`_i).\n(*This fact provides an opaque key used to lock the definition of polynomial addition, controlling its computational behavior within the proof assistant.*)\nFact add_poly_key : unit. \n(*This definition introduces the standard operation for adding two polynomials.*)\nDefinition add_poly := locked_with add_poly_key add_poly_def.\nCanonical add_poly_unlockable := [unlockable fun add_poly].\n\n(*This fact states that the coefficient of any given degree in the sum of two polynomials is equal to the sum of the coefficients of that same degree from the original polynomials.*)\nFact coef_add_poly p q i : (add_poly p q)`_i = p`_i + q`_i.\n\n(*This fact asserts that polynomial addition is an associative operation.*)\nFact add_polyA : associative add_poly.\n\n(*This fact asserts that polynomial addition is a commutative operation.*)\nFact add_polyC : commutative add_poly.\n\n(*This fact asserts that the zero polynomial is the left identity element for polynomial addition.*)\nFact add_poly0 : left_id 0%:P add_poly.\n\nHB.instance Definition _ := GRing.isNmodule.Build (polynomial R)\n add_polyA add_polyC add_poly0.\n\n(*This lemma states that the constant polynomial with value zero is identical to the zero element of the polynomial ring.*)\nLemma polyC0 : 0%:P = 0 :> {poly R}. \n\n(*This lemma states that the zero polynomial is represented by an empty sequence of coefficients.*)\nLemma polyseq0 : (0 : {poly R}) = [::] :> seq R.\n\n(*This lemma states that the size of the zero polynomial is zero.*)\nLemma size_poly0 : size (0 : {poly R}) = 0%N.\n\n(*This lemma states that every coefficient of the zero polynomial is the zero element of the underlying ring.*)\nLemma coef0 i : (0 : {poly R})`_i = 0.\n\n(*This lemma states that the leading coefficient of the zero polynomial is the zero element of the underlying ring.*)\nLemma lead_coef0 : lead_coef 0 = 0 :> R. \n\n(*This lemma states that the boolean property of a polynomial's size being zero is equivalent to the boolean property of the polynomial being equal to the zero polynomial.*)\nLemma size_poly_eq0 p : (size p == 0) = (p == 0).\n\n(*This lemma states that the boolean property of a polynomial's size being less than or equal to zero is equivalent to the boolean property of the polynomial being equal to the zero polynomial.*)\nLemma size_poly_leq0 p : (size p <= 0) = (p == 0).\n\n(*This lemma provides a reflective equivalence, stating that a polynomial is the zero polynomial if and only if its size is less than or equal to zero.*)\nLemma size_poly_leq0P p : reflect (p = 0) (size p <= 0).\n\n(*This lemma states that the boolean property of a polynomial's size being greater than zero is equivalent to the boolean property of the polynomial being different from the zero polynomial.*)\nLemma size_poly_gt0 p : (0 < size p) = (p != 0).\n\n(*This lemma states that if the size of a polynomial is strictly greater than some natural number, then the polynomial is not the zero polynomial.*)\nLemma gt_size_poly_neq0 p n : (size p > n)%N -> p != 0.\n\n(*This lemma states that checking whether a polynomial is nil is equivalent to checking whether that polynomial is equal to the zero polynomial.*)\nLemma nil_poly p : nilp p = (p == 0).\n\n(*This lemma states that for any given polynomial, it is either equal to the zero polynomial, or its size is strictly greater than zero.*)\nLemma poly0Vpos p : {p = 0} + {size p > 0}.\n\n(*This lemma states that for any non-zero polynomial, its size is equal to the successor of its predecessor, which confirms that its size is a positive natural number.*)\nLemma polySpred p : p != 0 -> size p = (size p).-1.+1.\n\n(*This lemma states that the boolean property of a polynomial's leading coefficient being zero is equivalent to the boolean property of the polynomial itself being the zero polynomial.*)\nLemma lead_coef_eq0 p : (lead_coef p == 0) = (p == 0).\n\n(*This lemma states that a constant polynomial is equal to the zero polynomial if and only if its underlying constant value is the zero element of the ring.*)\nLemma polyC_eq0 (c : R) : (c%:P == 0) = (c == 0).\n\n(*This lemma provides a reflective equivalence, stating that a polynomial has a size of one if and only if it is a constant polynomial with a non-zero coefficient.*)\nLemma size_poly1P p : reflect (exists2 c, c != 0 & p = c%:P) (size p == 1).\n\n(*This lemma states that the size of a constant polynomial is at most one.*)\nLemma size_polyC_leq1 (c : R) : (size c%:P <= 1)%N.\n\n(*This lemma establishes that the size of a polynomial is less than or equal to a given natural number if and only if all coefficients of the polynomial at indices greater than or equal to that number are zero.*)\nLemma leq_sizeP p i : reflect (forall j, i <= j -> p`_j = 0) (size p <= i).\n\n(*This lemma states that the coefficient at a given index of the sum of two polynomials is the sum of the coefficients of the individual polynomials at that same index.*)\nLemma coefD p q i : (p + q)`_i = p`_i + q`_i.\n\n(*This lemma states that the operation of creating a constant polynomial from a ring element is a morphism with respect to addition; in other words, the constant polynomial of a sum of two ring elements is the sum of their corresponding constant polynomials.*)\nLemma polyCD : {morph polyC : a b / a + b}.\n\n(*This lemma states that the size of the sum of two polynomials is less than or equal to the maximum of the sizes of the two polynomials.*)\nLemma size_polyD p q : size (p + q) <= maxn (size p) (size q).\n\n(*This lemma states that if the size of one polynomial is strictly greater than the size of another, the size of their sum is equal to the size of the larger polynomial.*)\nLemma size_polyDl p q : size p > size q -> size (p + q) = size p.\n\n(*This lemma states that the size of a summation of polynomials over a sequence is less than or equal to the maximum size found among all the polynomials being summed.*)\nLemma size_sum I (r : seq I) (P : pred I) (F : I -> {poly R}) :\n size (\\sum_(i <- r | P i) F i) <= \\max_(i <- r | P i) size (F i).\n\n(*This lemma states that if the size of one polynomial is strictly greater than the size of another, the leading coefficient of their sum is the same as the leading coefficient of the larger polynomial.*)\nLemma lead_coefDl p q : size p > size q -> lead_coef (p + q) = lead_coef p.\n\n(*This lemma states that if the size of a second polynomial is strictly greater than the size of a first one, the leading coefficient of their sum is the same as the leading coefficient of the second polynomial.*)\nLemma lead_coefDr p q : size q > size p -> lead_coef (p + q) = lead_coef q.\n\n(*This definition specifies the multiplication of two polynomials by defining the coefficient at each index of the resulting polynomial as the Cauchy product of the coefficients of the input polynomials.*)\nDefinition mul_poly_def p q :=\n \\poly_(i < (size p + size q).-1) (\\sum_(j < i.+1) p`_j * q`_(i - j)).\n(*This fact provides a key for managing the computational definition of polynomial multiplication, allowing it to be locked and unlocked.*)\nFact mul_poly_key : unit. \n(*This definition establishes the main operator for polynomial multiplication, using a locked implementation to control its unfolding in proofs.*)\nDefinition mul_poly := locked_with mul_poly_key mul_poly_def.\nCanonical mul_poly_unlockable := [unlockable fun mul_poly].\n\n(*This fact states that the coefficient at a given index of the product of two polynomials is the sum of products of coefficients from the original polynomials whose indices sum to the given index.*)\nFact coef_mul_poly p q i :\n (mul_poly p q)`_i = \\sum_(j < i.+1) p`_j * q`_(i - j)%N.\n\n(*This fact provides an alternative but equivalent formula for the coefficient at a given index of the product of two polynomials, where the roles of the two polynomials in the summation are swapped.*)\nFact coef_mul_poly_rev p q i :\n (mul_poly p q)`_i = \\sum_(j < i.+1) p`_(i - j)%N * q`_j.\n\n(*This fact asserts that polynomial multiplication is an associative operation.*)\nFact mul_polyA : associative mul_poly.\n\n(*This fact asserts that the constant polynomial representing one is the left identity element for polynomial multiplication.*)\nFact mul_1poly : left_id 1%:P mul_poly.\n\n(*This fact asserts that the constant polynomial representing one is the right identity element for polynomial multiplication.*)\nFact mul_poly1 : right_id 1%:P mul_poly.\n\n(*This fact asserts that polynomial multiplication is left-distributive over polynomial addition.*)\nFact mul_polyDl : left_distributive mul_poly +%R.\n\n(*This fact asserts that polynomial multiplication is right-distributive over polynomial addition.*)\nFact mul_polyDr : right_distributive mul_poly +%R.\n\n(*This fact asserts that the zero polynomial is the left absorbing element for polynomial multiplication, meaning any polynomial multiplied by it on the left results in the zero polynomial.*)\nFact mul_0poly : left_zero 0%:P mul_poly.\n\n(*This fact asserts that the zero polynomial is the right absorbing element for polynomial multiplication, meaning any polynomial multiplied by it on the right results in the zero polynomial.*)\nFact mul_poly0 : right_zero 0%:P mul_poly.\n\n(*This fact states that the constant polynomial representing one is not equal to the zero polynomial.*)\nFact poly1_neq0 : 1%:P != 0 :> {poly R}.\n\n(*This lemma states that the constant polynomial with value one is identical to the multiplicative identity of the polynomial ring.*)\nLemma polyC1 : 1%:P = 1 :> {poly R}. \n\n(*This lemma states that the polynomial ring's multiplicative identity corresponds to a sequence of coefficients containing a single element, which is the multiplicative identity of the underlying ring.*)\nLemma polyseq1 : (1 : {poly R}) = [:: 1] :> seq R.\n\n(*This lemma states that the size of the multiplicative identity polynomial is one.*)\nLemma size_poly1 : size (1 : {poly R}) = 1.\n\n(*This lemma states that the coefficient at any given index of the multiplicative identity polynomial is one if the index is zero, and zero otherwise.*)\nLemma coef1 i : (1 : {poly R})`_i = (i == 0)%:R.\n\n(*This lemma states that the leading coefficient of the multiplicative identity polynomial is the ring's multiplicative identity element.*)\nLemma lead_coef1 : lead_coef 1 = 1 :> R. \n\n(*This lemma provides the formula for the coefficient at a given index of a product of two polynomials, defining it as the Cauchy product of the coefficients of the input polynomials.*)\nLemma coefM p q i : (p * q)`_i = \\sum_(j < i.+1) p`_j * q`_(i - j)%N.\n\n(*This lemma provides an alternative but equivalent formula for the coefficient at a given index of a product of two polynomials, with the roles of the two polynomials swapped in the summation.*)\nLemma coefMr p q i : (p * q)`_i = \\sum_(j < i.+1) p`_(i - j)%N * q`_j.\n\n(*This lemma states that the constant term of the product of two polynomials is the product of their respective constant terms.*)\nLemma coef0M p q : (p * q)`_0 = p`_0 * q`_0.\n\n(*This lemma states that the constant coefficient of a product of a family of polynomials is equal to the product of the constant coefficients of those polynomials.*)\nLemma coef0_prod I rI (F : I -> {poly R}) P :\n (\\prod_(i <- rI| P i) F i)`_0 = \\prod_(i <- rI | P i) (F i)`_0.\n\n(*This lemma states that the size of the product of two polynomials is less than or equal to the sum of their sizes minus one.*)\nLemma size_polyMleq p q : size (p * q) <= (size p + size q).-1.\n\n(*This lemma states that the product of the leading coefficients of two polynomials is equal to the coefficient of their product at the degree corresponding to the sum of their individual degrees.*)\nLemma mul_lead_coef p q :\n lead_coef p * lead_coef q = (p * q)`_(size p + size q).-2.\n\n(*This lemma states that if the product of the leading coefficients of two polynomials is non-zero, then the size of their product polynomial is equal to the sum of their sizes minus one.*)\nLemma size_proper_mul p q :\n lead_coef p * lead_coef q != 0 -> size (p * q) = (size p + size q).-1.\n\n(*This lemma states that if the product of the leading coefficients of two polynomials is non-zero, then this product is the leading coefficient of the product polynomial.*)\nLemma lead_coef_proper_mul p q :\n let c := lead_coef p * lead_coef q in c != 0 -> lead_coef (p * q) = c.\n\n(*This lemma provides an upper bound for the size of a product of a family of polynomials, stating that it is less than or equal to the sum of the sizes of the individual polynomials plus one, minus the number of polynomials in the product.*)\nLemma size_poly_prod_leq (I : finType) (P : pred I) (F : I -> {poly R}) :\n size (\\prod_(i | P i) F i) <= (\\sum_(i | P i) size (F i)).+1 - #|P|.\n\n(*This lemma states that the coefficient at a given degree of the product of a constant polynomial and another polynomial is equal to the product of the constant and the coefficient of the other polynomial at that same degree.*)\nLemma coefCM c p i : (c%:P * p)`_i = c * p`_i.\n\n(*This lemma states that the coefficient at a given degree of the product of a polynomial and a constant polynomial is equal to the product of the coefficient of the first polynomial at that same degree and the constant.*)\nLemma coefMC c p i : (p * c%:P)`_i = p`_i * c.\n\n(*This lemma states that the function mapping a ring element to a constant polynomial is a ring morphism with respect to multiplication; that is, the constant polynomial of a product of two elements is the product of their corresponding constant polynomials.*)\nLemma polyCM : {morph polyC : a b / a * b}.\n\n(*This lemma provides an upper bound for the size of a polynomial raised to a natural number power, stating it is less than or equal to the product of the polynomial's degree and the exponent, plus one.*)\nLemma size_poly_exp_leq p n : size (p ^+ n) <= ((size p).-1 * n).+1.\n\nEnd SemiPolynomialTheory.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"renamed to `size_polyD`\")]\n(*This is a deprecated notation, an alias for size_polyD, which relates to the size of the sum or difference of polynomials.*)\nNotation size_add := size_polyD (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"renamed to `size_polyDl`\")]\n(*This is a deprecated notation, an alias for size_polyDl, which relates to the size of a sum of a list of polynomials.*)\nNotation size_addl := size_polyDl (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"renamed to `size_polyMleq`\")]\n(*This is a deprecated notation, an alias for size_polyMleq, which provides an upper bound on the size of the product of two polynomials.*)\nNotation size_mul_leq := size_polyMleq (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"renamed to `size_poly_prod_leq`\")]\n(*This is a deprecated notation, an alias for size_poly_prod_leq, which provides an upper bound on the size of a product of a family of polynomials.*)\nNotation size_prod_leq := size_poly_prod_leq (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"renamed to `size_poly_exp_leq`\")]\n(*This is a deprecated notation, an alias for size_poly_exp_leq, which provides an upper bound on the size of a polynomial raised to a power.*)\nNotation size_exp_leq := size_poly_exp_leq (only parsing).\n\nSection PolynomialTheory.\n\nVariable R : nzRingType.\nImplicit Types (a b c x y z : R) (p q r d : {poly R}).\n\n(*A notation that represents the constant polynomial whose value is a given ring element.*)\nLocal Notation \"c %:P\" := (polyC c).\n\n(*A notation for constructing a polynomial of a given size, where the coefficient for each degree is specified by an expression that depends on the degree index.*)\nLocal Notation \"\\poly_ ( i < n ) E\" := (poly n (fun i : nat => E)).\n\n(*This definition specifies the additive inverse of a polynomial as a new polynomial of the same size, where each coefficient is the additive inverse of the corresponding coefficient in the original polynomial.*)\nDefinition opp_poly_def p := \\poly_(i < size p) - p`_i.\n(*This fact serves as a key to lock the definition of the additive inverse of a polynomial, a mechanism used to manage definition unfolding in proofs.*)\nFact opp_poly_key : unit. \n(*This definition provides the additive inverse of a polynomial, implemented as a locked definition that computes the pointwise additive inverse of its coefficients.*)\nDefinition opp_poly := locked_with opp_poly_key opp_poly_def.\nCanonical opp_poly_unlockable := [unlockable fun opp_poly].\n\n(*This fact states that the coefficient at a given degree of the additive inverse of a polynomial is equal to the additive inverse of the coefficient of the original polynomial at that same degree.*)\nFact coef_opp_poly p i : (opp_poly p)`_i = - p`_i.\n\n(*This fact establishes that adding a polynomial to its additive inverse results in the zero polynomial, formally stating that the additive inverse operation is a left inverse for polynomial addition.*)\nFact add_polyN : left_inverse 0%:P opp_poly (@add_poly _).\n\nHB.instance Definition _ := GRing.Nmodule_isZmodule.Build (polynomial R)\n add_polyN.\n\n(*This lemma states that the coefficient at a given degree of the additive inverse of a polynomial is equal to the additive inverse of the coefficient of the original polynomial at that same degree.*)\nLemma coefN p i : (- p)`_i = - p`_i.\n\n(*This lemma states that the coefficient at a given degree of the difference of two polynomials is equal to the difference of their coefficients at that same degree.*)\nLemma coefB p q i : (p - q)`_i = p`_i - q`_i.\n\nHB.instance Definition _ i := GRing.isZmodMorphism.Build {poly R} R (coefp i)\n (fun p => (coefB p)^~ i).\n\n(*This lemma states that the coefficient at a given degree of a polynomial scaled by a natural number is equal to the coefficient of the original polynomial at that same degree scaled by the same natural number.*)\nLemma coefMn p n i : (p *+ n)`_i = p`_i *+ n.\n\n(*This lemma states that the coefficient at a given degree of a polynomial scaled by an integer is equal to the coefficient of the original polynomial at that same degree scaled by the same integer.*)\nLemma coefMNn p n i : (p *- n)`_i = p`_i *- n.\n\n(*This lemma states that the coefficient at a given degree of a sum of a family of polynomials is equal to the sum of the coefficients of those polynomials at that same degree.*)\nLemma coef_sum I (r : seq I) (P : pred I) (F : I -> {poly R}) k :\n (\\sum_(i <- r | P i) F i)`_k = \\sum_(i <- r | P i) (F i)`_k.\n\n(*This lemma states that the function mapping a ring element to a constant polynomial preserves the additive inverse; that is, the constant polynomial of the additive inverse of an element is the additive inverse of its constant polynomial.*)\nLemma polyCN : {morph (@polyC R) : c / - c}.\n\n(*This lemma states that the function mapping a ring element to a constant polynomial preserves subtraction; that is, the constant polynomial of the difference of two elements is the difference of their corresponding constant polynomials.*)\nLemma polyCB : {morph (@polyC R) : a b / a - b}.\n\nHB.instance Definition _ := GRing.isZmodMorphism.Build R {poly R} (@polyC _) polyCB.\n\n(*This lemma states that the function mapping a ring element to a constant polynomial preserves scaling by a natural number; that is, the constant polynomial of an element scaled by a natural number is the corresponding constant polynomial scaled by the same natural number.*)\nLemma polyCMn n : {morph (@polyC R) : c / c *+ n}. \n\n(*This lemma states that the size of the additive inverse of a polynomial is the same as the size of the original polynomial.*)\nLemma size_polyN p : size (- p) = size p.\n\n(*This lemma states that the leading coefficient of the additive inverse of a polynomial is equal to the additive inverse of the leading coefficient of the original polynomial.*)\nLemma lead_coefN p : lead_coef (- p) = - lead_coef p.\n\n(*This fact asserts that the function embedding a ring element into a constant polynomial is a monoid morphism, meaning it preserves the multiplicative identity and the multiplication operation.*)\nFact polyC_is_monoid_morphism : monoid_morphism (@polyC R).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `polyC_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, provides the proof components showing that the function for embedding a ring element into a constant polynomial preserves multiplication and the multiplicative identity.*)\nDefinition polyC_multiplicative :=\n (fun g => (g.2, g.1)) polyC_is_monoid_morphism.\nHB.instance Definition _ := GRing.isMonoidMorphism.Build R {poly R} (@polyC R)\n polyC_is_monoid_morphism.\n\n(*This lemma states that embedding a ring element raised to a natural number power into a constant polynomial is equivalent to embedding the ring element first and then raising the resulting polynomial to the same power.*)\nLemma polyC_exp n : {morph (@polyC R) : c / c ^+ n}. \n\n(*This lemma asserts that converting a natural number into a constant polynomial is equivalent to first converting the natural number into a ring element and then embedding that ring element as a constant polynomial.*)\nLemma polyC_natr n : n%:R%:P = n%:R :> {poly R}.\n\n(*This lemma states that the characteristic of a polynomial ring is identical to the characteristic of its underlying coefficient ring.*)\nLemma pchar_poly : [pchar {poly R}] =i [pchar R].\n\n(*This lemma states that the size of a polynomial remains unchanged when it is multiplied by negative one raised to any natural number power.*)\nLemma size_Msign p n : size ((-1) ^+ n * p) = size p.\n\n(*This fact asserts that the function extracting the constant coefficient from a polynomial is a monoid morphism, meaning it preserves the multiplicative identity and the product operation.*)\nFact coefp0_is_monoid_morphism : monoid_morphism (coefp 0 : {poly R} -> R).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `coefp0_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, constructs the proof that the function extracting the constant coefficient of a polynomial is a multiplicative morphism.*)\nDefinition coefp0_multiplicative :=\n (fun g => (g.2, g.1)) coefp0_is_monoid_morphism.\nHB.instance Definition _ := GRing.isMonoidMorphism.Build {poly R} R (coefp 0)\n coefp0_is_monoid_morphism.\n\n(*This definition specifies a function that scales a polynomial by a ring element. The resulting polynomial is formed by multiplying each coefficient of the input polynomial by the given ring element.*)\nDefinition scale_poly_def a (p : {poly R}) := \\poly_(i < size p) (a * p`_i).\n(*This fact provides an opaque key used to lock the definition of the polynomial scaling function, controlling its unfolding to maintain abstraction.*)\nFact scale_poly_key : unit. \n(*This definition introduces a function that scales a polynomial by a ring element. The implementation is locked to ensure abstraction and can only be accessed through specific lemmas.*)\nDefinition scale_poly := locked_with scale_poly_key scale_poly_def.\nCanonical scale_poly_unlockable := [unlockable fun scale_poly].\n\n(*This fact asserts that the operation of scaling a polynomial by a ring element is equivalent to polynomial multiplication with the corresponding constant polynomial.*)\nFact scale_polyE a p : scale_poly a p = a%:P * p.\n\n(*This fact asserts an associativity property for polynomial scaling, stating that sequentially scaling a polynomial by two ring elements is equivalent to scaling it once by their product.*)\nFact scale_polyA a b p : scale_poly a (scale_poly b p) = scale_poly (a * b) p.\n\n(*This fact asserts that the multiplicative identity element of the coefficient ring acts as a left identity for the polynomial scaling operation, meaning scaling a polynomial by one leaves it unchanged.*)\nFact scale_1poly : left_id 1 scale_poly.\n\n(*This fact asserts that scaling a sum of two polynomials by a ring element is equivalent to adding the results of scaling each polynomial individually by that same ring element.*)\nFact scale_polyDr a : {morph scale_poly a : p q / p + q}.\n\n(*This fact asserts that scaling a polynomial by the sum of two ring elements is equivalent to adding the results of scaling the polynomial by each ring element individually.*)\nFact scale_polyDl p : {morph scale_poly^~ p : a b / a + b}.\n\n(*This fact asserts that scaling the product of two polynomials by a ring element is equivalent to scaling only the first polynomial by that ring element before performing the multiplication.*)\nFact scale_polyAl a p q : scale_poly a (p * q) = scale_poly a p * q.\n\nHB.instance Definition _ := GRing.Zmodule_isLmodule.Build R (polynomial R)\n scale_polyA scale_1poly scale_polyDr scale_polyDl.\nHB.instance Definition _ := GRing.Lmodule_isLalgebra.Build R (polynomial R)\n scale_polyAl.\n\n(*This lemma states that multiplying a polynomial by a constant polynomial is equivalent to the scalar multiplication of the polynomial by the corresponding ring element.*)\nLemma mul_polyC a p : a%:P * p = a *: p.\n\n(*This lemma states that the scalar multiplication of a constant polynomial by a ring element yields the constant polynomial corresponding to the product of the scalar and the original constant value.*)\nLemma scale_polyC a b : a *: b%:P = (a * b)%:P.\n\n(*This lemma states that the canonical embedding of a ring element into the polynomial algebra is identical to the operation that creates a constant polynomial from that ring element.*)\nLemma alg_polyC a : a%:A = a%:P :> {poly R}.\n\n(*This lemma states that the coefficient at a given index of a scalar-multiplied polynomial is equal to the product of the scalar and the coefficient of the original polynomial at that same index.*)\nLemma coefZ a p i : (a *: p)`_i = a * p`_i.\n\n(*This lemma states that the size of a polynomial after scalar multiplication is less than or equal to the size of the original polynomial.*)\nLemma size_scale_leq a p : size (a *: p) <= size p.\n\nHB.instance Definition _ i := GRing.isScalable.Build R {poly R} R *%R (coefp i)\n (fun a => (coefZ a) ^~ i).\nHB.instance Definition _ := GRing.Linear.on (coefp 0).\n\n(*This definition specifies the indeterminate polynomial, often denoted 'X', as the polynomial whose coefficient for degree zero is the zero element and whose coefficient for degree one is the unit element of the ring.*)\nDefinition polyX_def := @Poly R [:: 0; 1].\n(*This fact provides an opaque key used to lock the definition of the indeterminate polynomial 'X', controlling its unfolding to maintain abstraction.*)\nFact polyX_key : unit. \n(*This definition introduces the indeterminate polynomial, often denoted 'X', for a given polynomial ring. Its definition is locked to ensure abstract handling.*)\nDefinition polyX : {poly R} := locked_with polyX_key polyX_def.\nCanonical polyX_unlockable := [unlockable of polyX].\n(*A notation representing the indeterminate of a univariate polynomial, which is defined as the monomial of degree one with a coefficient of one.*)\nLocal Notation \"'X\" := polyX.\n\n(*This lemma states that the coefficient sequence of the indeterminate polynomial 'X' is the sequence consisting of the ring's zero element followed by its unit element.*)\nLemma polyseqX : 'X = [:: 0; 1] :> seq R.\n\n(*This lemma states that the size of the indeterminate polynomial 'X' is two.*)\nLemma size_polyX : size 'X = 2. \n\n(*This lemma states that the comparison for equality between the polynomial 'X' and the zero polynomial evaluates to the boolean value false.*)\nLemma polyX_eq0 : ('X == 0) = false.\n\n(*This lemma states that the coefficient of the polynomial 'X' for a given degree is equal to the ring's unit element if the degree is one, and zero otherwise.*)\nLemma coefX i : 'X`_i = (i == 1)%:R.\n\n(*This lemma states that the leading coefficient of the polynomial 'X' is the unit element of the ring.*)\nLemma lead_coefX : lead_coef 'X = 1.\n\n(*This lemma states that any given polynomial commutes multiplicatively with the polynomial 'X'.*)\nLemma commr_polyX p : GRing.comm p 'X.\n\n(*This lemma states that the coefficient of a specific degree for the polynomial resulting from multiplying a polynomial by 'X' is zero if the degree is zero, and is otherwise equal to the coefficient of the next lower degree of the original polynomial.*)\nLemma coefMX p i : (p * 'X)`_i = (if (i == 0)%N then 0 else p`_i.-1).\n\n(*This lemma states that the coefficient of a specific degree for the polynomial resulting from multiplying 'X' by a polynomial is zero if the degree is zero, and is otherwise equal to the coefficient of the next lower degree of the original polynomial.*)\nLemma coefXM p i : ('X * p)`_i = (if (i == 0)%N then 0 else p`_i.-1).\n\n(*This lemma states that constructing a polynomial by prepending a given ring element as the new constant term to an existing polynomial is equivalent to multiplying the existing polynomial by 'X' and then adding the constant polynomial corresponding to the given ring element.*)\nLemma cons_poly_def p a : cons_poly a p = p * 'X + a%:P.\n\n(*This lemma provides an induction principle for polynomials. It states that to prove a property holds for all polynomials, it is sufficient to prove it for the zero polynomial and to show that if the property holds for a given polynomial, it also holds for the polynomial constructed by multiplying it by 'X' and adding a constant.*)\nLemma poly_ind (K : {poly R} -> Type) :\n K 0 -> (forall p c, K p -> K (p * 'X + c%:P)) -> (forall p, K p).\n\n(*This lemma states that the sequence of coefficients of the polynomial obtained by adding a constant to the polynomial 'X' is a two-element sequence containing the constant followed by the ring's unit element.*)\nLemma polyseqXaddC a : 'X + a%:P = [:: a; 1] :> seq R.\n\n(*This lemma states that the sequence of coefficients of the polynomial obtained by subtracting a constant from the polynomial 'X' is a two-element sequence containing the additive inverse of the constant followed by the ring's unit element.*)\nLemma polyseqXsubC a : 'X - a%:P = [:: - a; 1] :> seq R.\n\n(*This lemma states that the size, or number of coefficients, of the polynomial formed by subtracting a constant from the polynomial 'X' is two.*)\nLemma size_XsubC a : size ('X - a%:P) = 2.\n\n(*This lemma states that the size, or number of coefficients, of the polynomial formed by adding a constant to the polynomial 'X' is two.*)\nLemma size_XaddC b : size ('X + b%:P) = 2.\n\n(*This lemma states that the leading coefficient of the polynomial formed by adding a constant to 'X' is the ring's unit element.*)\nLemma lead_coefXaddC a : lead_coef ('X + a%:P) = 1.\n\n(*This lemma states that the leading coefficient of the polynomial formed by subtracting a constant from 'X' is the ring's unit element.*)\nLemma lead_coefXsubC a : lead_coef ('X - a%:P) = 1.\n\n(*This lemma states that the polynomial resulting from subtracting any constant from 'X' is never equal to the zero polynomial, an inequality that evaluates to the boolean value false.*)\nLemma polyXsubC_eq0 a : ('X - a%:P == 0) = false.\n\n(*This lemma states that the size of the polynomial formed by multiplying a polynomial by 'X' and adding a constant is zero if both the polynomial and the constant are zero, and otherwise is one greater than the size of the original polynomial.*)\nLemma size_MXaddC p c :\n size (p * 'X + c%:P) = (if (p == 0) && (c == 0) then 0 else (size p).+1).\n\n(*This lemma states that for any non-zero polynomial, the sequence of coefficients of the polynomial resulting from its multiplication by 'X' is obtained by prepending a zero to its original sequence of coefficients.*)\nLemma polyseqMX p : p != 0 -> p * 'X = 0 :: p :> seq R.\n\n(*This lemma states that for any non-zero polynomial, the size of the polynomial resulting from its multiplication by 'X' is one greater than its original size.*)\nLemma size_mulX p : p != 0 -> size (p * 'X) = (size p).+1.\n\n(*This lemma states that the leading coefficient of the polynomial resulting from multiplying a given polynomial by 'X' is the same as the leading coefficient of the original polynomial.*)\nLemma lead_coefMX p : lead_coef (p * 'X) = lead_coef p.\n\n(*This lemma states that for any non-zero ring element, the size of the polynomial which is the product of 'X' and the constant polynomial of that element is two.*)\nLemma size_XmulC a : a != 0 -> size ('X * a%:P) = 2.\n\n(*This notation represents the polynomial 'X' raised to the power of a given natural number.*)\nLocal Notation \"''X^' n\" := ('X ^+ n).\n\n(*This lemma states that the coefficient for a given degree of the polynomial 'X' raised to a natural number power is the ring's unit element if the degree equals the exponent, and zero otherwise.*)\nLemma coefXn n i : 'X^n`_i = (i == n)%:R.\n\n(*This lemma states that the sequence of coefficients for the polynomial 'X' raised to a natural number power consists of a sequence of zeros of that length, followed by the ring's unit element.*)\nLemma polyseqXn n : 'X^n = rcons (nseq n 0) 1 :> seq R.\n\n(*This lemma states that the size of the polynomial 'X' raised to a given natural number power is one greater than that number.*)\nLemma size_polyXn n : size 'X^n = n.+1.\n\n(*This lemma states that any given polynomial commutes multiplicatively with any natural number power of the polynomial 'X'.*)\nLemma commr_polyXn p n : GRing.comm p 'X^n.\n\n(*This lemma states that the leading coefficient of any natural number power of the polynomial 'X' is the ring's unit element.*)\nLemma lead_coefXn n : lead_coef 'X^n = 1.\n\n(*This lemma states that for any positive natural number power, the leading coefficient of the polynomial formed by adding a constant to 'X' raised to that power is the ring's unit element.*)\nLemma lead_coefXnaddC n c : 0 < n -> lead_coef ('X^n + c%:P) = 1.\n\n(*This lemma states that for any positive natural number power, the leading coefficient of the polynomial formed by subtracting a constant from 'X' raised to that power is the ring's unit element.*)\nLemma lead_coefXnsubC n c : 0 < n -> lead_coef ('X^n - c%:P) = 1.\n\n(*This lemma states that for any positive natural number power, the size of the polynomial formed by adding a constant to 'X' raised to that power is one greater than the power.*)\nLemma size_XnaddC n c : 0 < n -> size ('X^n + c%:P) = n.+1.\n\n(*This lemma states that for any positive natural number power, the size of the polynomial formed by subtracting a constant from 'X' raised to that power is one greater than the power.*)\nLemma size_XnsubC n c : 0 < n -> size ('X^n - c%:P) = n.+1.\n\n(*This lemma states that for a non-zero polynomial and a natural number, the polynomial product of the original polynomial and the monomial 'X' raised to the power of the natural number is represented by a sequence of coefficients formed by prepending a number of zeros equal to the given natural number to the original polynomial's coefficient sequence.*)\nLemma polyseqMXn n p : p != 0 -> p * 'X^n = ncons n 0 p :> seq R.\n\n(*This lemma states that the coefficient at a given index of a polynomial multiplied by 'X' raised to a certain power is zero if the index is less than the power, and is otherwise equal to the coefficient of the original polynomial at the index minus the power.*)\nLemma coefMXn n p i : (p * 'X^n)`_i = if i < n then 0 else p`_(i - n).\n\n(*This lemma states that for a non-zero polynomial, the size of the polynomial resulting from multiplying it by 'X' raised to a natural number power is the sum of that natural number and the size of the original polynomial.*)\nLemma size_mulXn n p : p != 0 -> size (p * 'X^n) = (n + size p)%N.\n\n(*This lemma states that the coefficient at a given index of the product of 'X' raised to a power and another polynomial is zero if the index is less than the power, and is otherwise equal to the coefficient of the second polynomial at the index minus the power.*)\nLemma coefXnM n p i : ('X^n * p)`_i = if i < n then 0 else p`_(i - n).\n\n(*This lemma states that the coefficient at a specific index of a sum of scaled monomials is equal to the sum of the scalars of those monomials whose exponent matches the given index.*)\nLemma coef_sumMXn I (r : seq I) (P : pred I) (p : I -> R) (n : I -> nat) k :\n (\\sum_(i <- r | P i) p i *: 'X^(n i))`_k =\n \\sum_(i <- r | P i && (n i == k)) p i.\n\n(*This lemma states that a polynomial constructed from a function that provides coefficients for each degree is equal to the sum, over a range of natural numbers, of each coefficient multiplied by 'X' raised to the power of the corresponding index.*)\nLemma poly_def n E : \\poly_(i < n) E i = \\sum_(i < n) E i *: 'X^i.\n\n(*This definition specifies the predicate for a polynomial to be monic, which holds if and only if the leading coefficient of the polynomial is equal to one.*)\nDefinition monic_pred := fun p => lead_coef p == 1.\nArguments monic_pred _ /.\n(*This definition introduces the type of monic polynomials, which are polynomials whose leading coefficient is equal to one.*)\nDefinition monic := [qualify p | monic_pred p].\n\n(*This lemma asserts that the boolean test for a polynomial being monic is equivalent to the boolean comparison of its leading coefficient with one.*)\nLemma monicE p : (p \\is monic) = (lead_coef p == 1). \n(*This lemma provides a reflection principle, establishing that the boolean statement asserting a polynomial is monic is true if and only if the proposition that its leading coefficient is one holds.*)\nLemma monicP p : reflect (lead_coef p = 1) (p \\is monic).\n\n(*This lemma states that the constant polynomial one is a monic polynomial.*)\nLemma monic1 : 1 \\is monic. \n(*This lemma states that the monomial 'X' is a monic polynomial.*)\nLemma monicX : 'X \\is monic. \n(*This lemma states that the monomial 'X' raised to any natural number power is a monic polynomial.*)\nLemma monicXn n : 'X^n \\is monic. \n\n(*This lemma states that any monic polynomial is not equal to the zero polynomial.*)\nLemma monic_neq0 p : p \\is monic -> p != 0.\n\n(*This lemma states that if a monic polynomial is multiplied by a second polynomial, the leading coefficient of the resulting product is the same as the leading coefficient of the second polynomial.*)\nLemma lead_coef_monicM p q : p \\is monic -> lead_coef (p * q) = lead_coef q.\n\n(*This lemma states that if a polynomial is multiplied by a monic polynomial, the leading coefficient of the resulting product is the same as the leading coefficient of the first polynomial.*)\nLemma lead_coef_Mmonic p q : q \\is monic -> lead_coef (p * q) = lead_coef p.\n\n(*This lemma states that for a monic polynomial and a non-zero polynomial, the size of their product is one less than the sum of their individual sizes.*)\nLemma size_monicM p q :\n p \\is monic -> q != 0 -> size (p * q) = (size p + size q).-1.\n\n(*This lemma states that for a non-zero polynomial and a monic polynomial, the size of their product is one less than the sum of their individual sizes.*)\nLemma size_Mmonic p q :\n p != 0 -> q \\is monic -> size (p * q) = (size p + size q).-1.\n\n(*This lemma states that when a monic polynomial is multiplied by another polynomial, the resulting product is monic if and only if the second polynomial is also monic.*)\nLemma monicMl p q : p \\is monic -> (p * q \\is monic) = (q \\is monic).\n\n(*This lemma states that when a polynomial is multiplied by a monic polynomial, the resulting product is monic if and only if the first polynomial is also monic.*)\nLemma monicMr p q : q \\is monic -> (p * q \\is monic) = (p \\is monic).\n\n(*This fact asserts that the set of monic polynomials is closed under multiplication; that is, the product of any two monic polynomials is also a monic polynomial.*)\nFact monic_mulr_closed : mulr_closed monic.\n\nHB.instance Definition _ := GRing.isMulClosed.Build {poly R} monic_pred\n monic_mulr_closed.\n\n(*This lemma states that raising a monic polynomial to any natural number power results in a monic polynomial.*)\nLemma monic_exp p n : p \\is monic -> p ^+ n \\is monic.\n\n(*This lemma states that a finite product of polynomials is monic if every polynomial in the product is monic.*)\nLemma monic_prod I rI (P : pred I) (F : I -> {poly R}):\n (forall i, P i -> F i \\is monic) -> \\prod_(i <- rI | P i) F i \\is monic.\n\n(*This lemma states that a polynomial of the form 'X' plus a constant is a monic polynomial.*)\nLemma monicXaddC c : 'X + c%:P \\is monic.\n\n(*This lemma states that a polynomial of the form 'X' minus a constant is a monic polynomial.*)\nLemma monicXsubC c : 'X - c%:P \\is monic.\n\n(*This lemma states that the product of a sequence of polynomials, where each polynomial is of the form 'X' minus a constant, is a monic polynomial.*)\nLemma monic_prod_XsubC I rI (P : pred I) (F : I -> R) :\n \\prod_(i <- rI | P i) ('X - (F i)%:P) \\is monic.\n\n(*This lemma states that the leading coefficient of the product of a sequence of polynomials, where each polynomial has the form 'X' minus a constant, is equal to one.*)\nLemma lead_coef_prod_XsubC I rI (P : pred I) (F : I -> R) :\n lead_coef (\\prod_(i <- rI | P i) ('X - (F i)%:P)) = 1.\n\n(*This lemma states that the size of the polynomial formed by the product of factors 'X' minus a constant, taken over a sequence of constants, is equal to the length of the sequence plus one.*)\nLemma size_prod_XsubC I rI (F : I -> R) :\n size (\\prod_(i <- rI) ('X - (F i)%:P)) = (size rI).+1.\n\n(*This lemma states that the size of a polynomial of the form 'X' minus a constant, when raised to a natural number power, is equal to that power plus one.*)\nLemma size_exp_XsubC n a : size (('X - a%:P) ^+ n) = n.+1.\n\n(*This lemma states that for any positive natural number, the polynomial formed by adding a constant to 'X' raised to that number's power is a monic polynomial.*)\nLemma monicXnaddC n c : 0 < n -> 'X^n + c%:P \\is monic.\n\n(*This lemma states that for any non-zero natural number and any ring element, the polynomial formed by subtracting the constant polynomial of the ring element from the monomial X raised to the power of the natural number is a monic polynomial.*)\nLemma monicXnsubC n c : 0 < n -> 'X^n - c%:P \\is monic.\n\n(*This lemma states that if the leading coefficient of a polynomial is a left regular element, then the polynomial itself is also a left regular element.*)\nLemma lreg_lead p : GRing.lreg (lead_coef p) -> GRing.lreg p.\n\n(*This lemma states that if the leading coefficient of a polynomial is a right regular element, then the polynomial itself is also a right regular element.*)\nLemma rreg_lead p : GRing.rreg (lead_coef p) -> GRing.rreg p.\n\n(*This lemma states that if the leading coefficient of a polynomial is a left regular element, then the polynomial is not the zero polynomial.*)\nLemma lreg_lead0 p : GRing.lreg (lead_coef p) -> p != 0.\n\n(*This lemma states that if the leading coefficient of a polynomial is a right regular element, then the polynomial is not the zero polynomial.*)\nLemma rreg_lead0 p : GRing.rreg (lead_coef p) -> p != 0.\n\n(*This lemma states that if a ring element is left regular, then the size of the polynomial resulting from the left scalar multiplication of another polynomial by that ring element is equal to the size of the original polynomial.*)\nLemma lreg_size c p : GRing.lreg c -> size (c *: p) = size p.\n\n(*This lemma states that for a left regular ring element and a polynomial, the boolean check for equality between the left scalar product of the element and the polynomial and the zero polynomial is equivalent to the boolean check for equality between the polynomial and the zero polynomial.*)\nLemma lreg_polyZ_eq0 c p : GRing.lreg c -> (c *: p == 0) = (p == 0).\n\n(*This lemma states that if a ring element is left regular, the leading coefficient of the polynomial resulting from the left scalar multiplication of another polynomial by that element is equal to the product of the ring element and the leading coefficient of the original polynomial.*)\nLemma lead_coef_lreg c p :\n GRing.lreg c -> lead_coef (c *: p) = c * lead_coef p.\n\n(*This lemma states that if a ring element is right regular, then the size of the polynomial resulting from multiplying another polynomial on the right by the constant polynomial of that ring element is equal to the size of the original polynomial.*)\nLemma rreg_size c p : GRing.rreg c -> size (p * c%:P) = size p.\n\n(*This lemma states that for a right regular ring element and a polynomial, the boolean check for equality between the product of the polynomial and the constant polynomial of the ring element and the zero polynomial is equivalent to the boolean check for equality between the original polynomial and the zero polynomial.*)\nLemma rreg_polyMC_eq0 c p : GRing.rreg c -> (p * c%:P == 0) = (p == 0).\n\n(*This lemma states that for three polynomials corresponding to a quotient, a remainder, and a divisor, if the leading coefficient of the divisor is a right regular element and the size of the remainder is strictly less than the size of the divisor, then their combination as 'quotient times divisor plus remainder' is the zero polynomial if and only if both the quotient and the remainder are themselves the zero polynomial.*)\nLemma rreg_div0 q r d :\n GRing.rreg (lead_coef d) -> size r < size d ->\n (q * d + r == 0) = (q == 0) && (r == 0).\n\n(*This lemma states that a monic polynomial commutes with the constant polynomial formed from its leading coefficient, and that its leading coefficient is a right regular element.*)\nLemma monic_comreg p :\n p \\is monic -> GRing.comm p (lead_coef p)%:P /\\ GRing.rreg (lead_coef p).\n\n(*This lemma states that any monic polynomial is a left regular element.*)\nLemma monic_lreg p : p \\is monic -> GRing.lreg p.\n\n(*This lemma states that any monic polynomial is a right regular element.*)\nLemma monic_rreg p : p \\is monic -> GRing.rreg p.\n\nImplicit Types s rs : seq R.\n(*This recursive function implements Horner's method to evaluate a polynomial at a given value. It takes a finite sequence of coefficients, representing the polynomial in order of increasing degree, and a ring element, and returns the evaluation of the polynomial at that element.*)\nFixpoint horner_rec s x := if s is a :: s' then horner_rec s' x * x + a else 0.\n(*This definition provides the value of a polynomial evaluated at a specific point, computed using Horner's method. It takes a polynomial and a ring element as input and returns the resulting ring element.*)\nDefinition horner p := horner_rec p.\n\n(*A notation for the evaluation of a univariate polynomial at a specific point, yielding a value in the underlying ring.*)\nLocal Notation \"p .[ x ]\" := (horner p x) : ring_scope.\n\n(*This lemma states that evaluating the zero polynomial at any ring element yields the zero ring element.*)\nLemma horner0 x : (0 : {poly R}).[x] = 0.\n\n(*This lemma states that evaluating a constant polynomial at any ring element yields the constant value itself.*)\nLemma hornerC c x : (c%:P).[x] = c.\n\n(*This lemma states that evaluating the indeterminate polynomial X at a ring element yields that same element.*)\nLemma hornerX x : 'X.[x] = x.\n\n(*This lemma states that the evaluation of a polynomial formed by multiplying an original polynomial by the indeterminate X and adding a new constant term is equal to the evaluation of the original polynomial at the given value, multiplied by that value, plus the constant term.*)\nLemma horner_cons p c x : (cons_poly c p).[x] = p.[x] * x + c.\n\n(*This lemma states that evaluating a polynomial at the zero element of the ring yields the polynomial's constant coefficient.*)\nLemma horner_coef0 p : p.[0] = p`_0.\n\n(*This lemma states that the evaluation of a polynomial formed by multiplying another polynomial by the indeterminate X and then adding a constant polynomial, when evaluated at a value, is equal to the result of evaluating the first polynomial at that value, multiplying by the value, and then adding the constant.*)\nLemma hornerMXaddC p c x : (p * 'X + c%:P).[x] = p.[x] * x + c.\n\n(*This lemma states that evaluating the product of a polynomial and the indeterminate X at a value is equivalent to evaluating the polynomial at that value and then multiplying by the value.*)\nLemma hornerMX p x : (p * 'X).[x] = p.[x] * x.\n\n(*This lemma states that evaluating a polynomial constructed from a finite sequence of coefficients at a given value is equivalent to applying the recursive Horner evaluation function to that sequence and value.*)\nLemma horner_Poly s x : (Poly s).[x] = horner_rec s x.\n\n(*This lemma provides the expanded sum definition of polynomial evaluation. It states that evaluating a polynomial at a value is equivalent to computing the sum, over all indices from zero up to the polynomial's size, of the product of the coefficient at each index and the value raised to the power of that index.*)\nLemma horner_coef p x : p.[x] = \\sum_(i < size p) p`_i * x ^+ i.\n\n(*This lemma provides an alternative form for the expanded sum definition of polynomial evaluation. It states that if the size of a polynomial is less than or equal to a natural number, then evaluating the polynomial at a value is equivalent to summing the terms of the coefficient at an index times the value to the power of the index, for all indices up to the given natural number.*)\nLemma horner_coef_wide n p x :\n size p <= n -> p.[x] = \\sum_(i < n) p`_i * x ^+ i.\n\n(*This lemma states that evaluating a polynomial constructed from a function over a range of indices at a given value is equivalent to the sum of the function's output at each index times the value raised to the power of that index, over the same range of indices.*)\nLemma horner_poly n E x : (\\poly_(i < n) E i).[x] = \\sum_(i < n) E i * x ^+ i.\n\n(*This lemma states that evaluating the additive inverse of a polynomial at a value yields the additive inverse of the evaluation of the original polynomial at that value.*)\nLemma hornerN p x : (- p).[x] = - p.[x].\n\n(*This lemma states that evaluating the sum of two polynomials at a value is equivalent to adding the individual evaluations of each polynomial at that value.*)\nLemma hornerD p q x : (p + q).[x] = p.[x] + q.[x].\n\n(*This lemma states that evaluating a polynomial, formed by subtracting a constant from the indeterminate 'X', at a given ring element results in the value obtained by subtracting that same constant from the ring element.*)\nLemma hornerXsubC a x : ('X - a%:P).[x] = x - a.\n\n(*This lemma states that the Horner evaluation of a sum of polynomials is equal to the sum of the Horner evaluations of each individual polynomial, where the sum is taken over a sequence of elements that satisfy a given predicate.*)\nLemma horner_sum I (r : seq I) (P : pred I) F x :\n (\\sum_(i <- r | P i) F i).[x] = \\sum_(i <- r | P i) (F i).[x].\n\n(*This lemma states that evaluating a polynomial, which is the product of a constant polynomial and another polynomial, at a given ring element is equivalent to multiplying the constant by the evaluation of the second polynomial at that same element.*)\nLemma hornerCM a p x : (a%:P * p).[x] = a * p.[x].\n\n(*This lemma states that evaluating a polynomial scaled by an integer at a given ring element is equivalent to multiplying that integer by the result of evaluating the original polynomial at the same element.*)\nLemma hornerZ c p x : (c *: p).[x] = c * p.[x].\n\n(*This lemma states that evaluating a polynomial multiplied by a natural number at a given ring element is equivalent to multiplying the evaluation of the original polynomial at that element by the same natural number.*)\nLemma hornerMn n p x : (p *+ n).[x] = p.[x] *+ n.\n\n(*This definition introduces a predicate that holds for a polynomial and a ring element if the ring element commutes with every coefficient of the polynomial.*)\nDefinition comm_coef p x := forall i, p`_i * x = x * p`_i.\n\n(*This definition introduces a predicate that holds for a polynomial and a ring element if the ring element commutes with the result of evaluating the polynomial at that element.*)\nDefinition comm_poly p x := x * p.[x] = p.[x] * x.\n\n(*This lemma states that if a ring element commutes with all coefficients of a polynomial, then it also commutes with the value of the polynomial evaluated at that ring element.*)\nLemma comm_coef_poly p x : comm_coef p x -> comm_poly p x.\n\n(*This lemma states that any ring element commutes with the evaluation of the zero polynomial at that element.*)\nLemma comm_poly0 x : comm_poly 0 x.\n\n(*This lemma states that any ring element commutes with the evaluation of the constant polynomial one at that element.*)\nLemma comm_poly1 x : comm_poly 1 x.\n\n(*This lemma states that any ring element commutes with the evaluation of the indeterminate polynomial 'X' at that element.*)\nLemma comm_polyX x : comm_poly 'X x.\n\n(*This lemma states that if a ring element commutes with the evaluations of two separate polynomials at that element, then it also commutes with the evaluation of their sum at the same element.*)\nLemma comm_polyD p q x: comm_poly p x -> comm_poly q x -> comm_poly (p + q) x.\n\n(*This lemma states that if two ring elements commute, and the first element also commutes with all coefficients of a given polynomial, then the first element will commute with the result of evaluating that polynomial at the second element.*)\nLemma commr_horner a b p : GRing.comm a b -> comm_coef p a -> GRing.comm a p.[b].\n\n(*This lemma states that the evaluation of the product of two polynomials at a ring element is the product of their individual evaluations, provided that the ring element commutes with the value obtained from evaluating the second polynomial at that same element.*)\nLemma hornerM_comm p q x : comm_poly q x -> (p * q).[x] = p.[x] * q.[x].\n\n(*This lemma states that if a ring element commutes with the evaluations of two separate polynomials at that element, then it also commutes with the evaluation of their product at the same element.*)\nLemma comm_polyM p q x: comm_poly p x -> comm_poly q x -> comm_poly (p * q) x.\n\n(*This lemma states that evaluating a natural number power of a polynomial at a ring element is equivalent to taking the same power of the polynomial's evaluation at that element, provided that the ring element commutes with the value obtained by evaluating the polynomial at that element.*)\nLemma horner_exp_comm p x n : comm_poly p x -> (p ^+ n).[x] = p.[x] ^+ n.\n\n(*This lemma states that if a ring element commutes with the evaluation of a polynomial at that element, then it also commutes with the evaluation of any natural number power of that polynomial at the same element.*)\nLemma comm_poly_exp p n x: comm_poly p x -> comm_poly (p ^+ n) x.\n\n(*This lemma states that evaluating the polynomial, which is the indeterminate 'X' raised to a natural number power, at a given ring element yields that element raised to the same power.*)\nLemma hornerXn x n : ('X^n).[x] = x ^+ n.\n\n(*This definition aggregates a collection of lemmas that serve as simplification rules for the Horner evaluation of polynomials, particularly addressing cases involving sums, negations, constants, scalar multiples, and products where commutativity conditions hold.*)\nDefinition hornerE_comm :=\n (hornerD, hornerN, hornerX, hornerC, horner_cons,\n simp, hornerCM, hornerZ,\n (fun p x => hornerM_comm p (comm_polyX x))).\n\n(*This definition defines the set of roots of a given polynomial as a predicate that is true for any ring element for which the polynomial evaluates to zero.*)\nDefinition root p : pred R := fun x => p.[x] == 0.\n\n(*This lemma states that a ring element is a member of the set of roots of a polynomial if and only if the boolean test for equality between the polynomial's evaluation at that element and zero yields true.*)\nLemma mem_root p x : x \\in root p = (p.[x] == 0).\n\n(*This lemma establishes the equivalence between a ring element being a root of a polynomial and the boolean expression that checks if the polynomial evaluates to zero at that element.*)\nLemma rootE p x : (root p x = (p.[x] == 0)) * ((x \\in root p) = (p.[x] == 0)).\n\n(*This lemma provides a reflection principle, connecting the boolean value indicating that a ring element is a root of a polynomial to the propositional statement that the polynomial's evaluation at that element equals zero.*)\nLemma rootP p x : reflect (p.[x] = 0) (root p x).\n\n(*This lemma provides a reflection principle, asserting that the boolean indicating an element is a root of a polynomial is true if and only if the boolean expression comparing the polynomial's evaluation at that element with zero is true.*)\nLemma rootPt p x : reflect (p.[x] == 0) (root p x).\n\n(*This lemma provides a reflection principle for the negation case, asserting that an element is not a root of a polynomial if and only if the boolean expression comparing the polynomial's evaluation with zero is false.*)\nLemma rootPf p x : reflect ((p.[x] == 0) = false) (~~ root p x).\n\n(*This lemma states that a ring element is a root of a constant polynomial if and only if the constant itself is zero.*)\nLemma rootC a x : root a%:P x = (a == 0).\n\n(*This lemma states that any ring element is a root of the zero polynomial.*)\nLemma root0 x : root 0 x.\n\n(*This lemma states that no ring element is a root of the constant polynomial one, assuming one is not equal to zero.*)\nLemma root1 x : ~~ root 1 x.\n\n(*This lemma states that a ring element is a root of the indeterminate polynomial 'X' if and only if that element is zero.*)\nLemma rootX x : root 'X x = (x == 0).\n\n(*This lemma states that a ring element is a root of the additive inverse of a polynomial if and only if it is a root of the original polynomial.*)\nLemma rootN p x : root (- p) x = root p x.\n\n(*This lemma states that if a non-zero polynomial has a root, then its size, which is its degree plus one, must be greater than one.*)\nLemma root_size_gt1 a p : p != 0 -> root p a -> 1 < size p.\n\n(*This lemma states that an element is a root of the linear polynomial formed by subtracting a constant from the indeterminate 'X', if and only if the element is equal to that constant.*)\nLemma root_XsubC a x : root ('X - a%:P) x = (x == a).\n\n(*This lemma states that an element is a root of the linear polynomial formed by adding a constant to the indeterminate 'X', if and only if the element is equal to the additive inverse of that constant.*)\nLemma root_XaddC a x : root ('X + a%:P) x = (x == - a).\n\n(*This theorem states that an element is a root of a given polynomial if and only if the polynomial can be expressed as the product of another polynomial and the linear factor formed by subtracting the root from the indeterminate 'X'.*)\nTheorem factor_theorem p a : reflect (exists q, p = q * ('X - a%:P)) (root p a).\n\n(*This lemma asserts the existence of a unique natural number, which is the multiplicity of a given element for a polynomial, such that the polynomial can be expressed as the product of another polynomial and a linear factor raised to the power of the multiplicity, where the other polynomial does not have the given element as a root, provided the original polynomial is not zero.*)\nLemma multiplicity_XsubC p a :\n {m | exists2 q, (p != 0) ==> ~~ root q a & p = q * ('X - a%:P) ^+ m}.\n\n#[deprecated(since=\"mathcomp 2.3.0\",note=\"Use size_XnsubC instead.\")]\n(*This deprecated lemma states that for any positive natural number, the size of the polynomial 'X to the power of n, minus one' is equal to that natural number plus one.*)\nLemma size_Xn_sub_1 n : n > 0 -> size ('X^n - 1 : {poly R}) = n.+1.\n\n#[deprecated(since=\"mathcomp 2.3.0'\",note=\"Use monicXnsubC instead.\")]\n(*This deprecated lemma states that for any positive natural number, the polynomial 'X to the power of n, minus one' is a monic polynomial.*)\nLemma monic_Xn_sub_1 n : n > 0 -> 'X^n - 1 \\is monic.\n\n(*This definition specifies an n-th root of unity as any element that is a root of the polynomial 'X to the power of n, minus one'.*)\nDefinition root_of_unity n : pred R := root ('X^n - 1).\n(*This notation takes a natural number and represents the predicate testing if a ring element is a root of unity for that number. The predicate holds if the ring element raised to the power of the natural number is equal to one.*)\nLocal Notation \"n .-unity_root\" := (root_of_unity n) : ring_scope.\n\n(*This lemma states that an element is an n-th root of unity if and only if that element raised to the power of n is equal to one.*)\nLemma unity_rootE n z : n.-unity_root z = (z ^+ n == 1).\n\n(*This lemma provides a boolean reflection of the property that an element is an n-th root of unity, stating it is equivalent to the condition that the element raised to the power of n equals one.*)\nLemma unity_rootP n z : reflect (z ^+ n = 1) (n.-unity_root z).\n\n(*This definition specifies a primitive n-th root of unity as an element for which n is the smallest positive integer exponent that results in one when the element is raised to that power.*)\nDefinition primitive_root_of_unity n z :=\n (n > 0) && [forall i : 'I_n, i.+1.-unity_root z == (i.+1 == n)].\n(*This notation takes a natural number and represents the predicate that checks if a ring element is a primitive root of unity for that number. An element is a primitive root of unity for a positive natural number if that number is the smallest positive integer for which the element raised to that power is equal to one.*)\nLocal Notation \"n .-primitive_root\" := (primitive_root_of_unity n) : ring_scope.\n\n(*This lemma states that if an element raised to a positive natural number exponent equals one, then there exists a unique natural number m such that the element is a primitive m-th root of unity and m divides the original exponent.*)\nLemma prim_order_exists n z :\n n > 0 -> z ^+ n = 1 -> {m | m.-primitive_root z & (m %| n)}.\n\nSection OnePrimitive.\n\nVariables (n : nat) (z : R).\nHypothesis prim_z : n.-primitive_root z.\n\n(*This lemma states that the order of a primitive root of unity must be a positive natural number.*)\nLemma prim_order_gt0 : n > 0. \n(*This definition provides a local name for the proof that the order of a primitive root of unity must be a positive natural number.*)\nLet n_gt0 := prim_order_gt0.\n\n(*This lemma states that a primitive n-th root of unity raised to the power of n equals one.*)\nLemma prim_expr_order : z ^+ n = 1.\n\n(*This lemma states that for a primitive n-th root of unity, raising it to any natural number power is equivalent to raising it to the power of the remainder of that number divided by its order n.*)\nLemma prim_expr_mod i : z ^+ (i %% n) = z ^+ i.\n\n(*This lemma states that for a primitive n-th root of unity, a power of that root equals one if and only if the exponent is a multiple of n.*)\nLemma prim_order_dvd i : (n %| i) = (z ^+ i == 1).\n\n(*This lemma states that for a primitive n-th root of unity, two powers of the root are equal if and only if their exponents are congruent modulo n.*)\nLemma eq_prim_root_expr i j : (z ^+ i == z ^+ j) = (i == j %[mod n]).\n\n(*This lemma states that if an element is a primitive n-th root of unity, then raising it to the power of a natural number k results in a primitive m-th root of unity, where m is equal to n divided by the greatest common divisor of n and k.*)\nLemma exp_prim_root k : (n %/ gcdn k n).-primitive_root (z ^+ k).\n\n(*This lemma states that if an element is a primitive n-th root of unity and a natural number m divides n, then the element raised to the power of n divided by m is a primitive m-th root of unity.*)\nLemma dvdn_prim_root m : (m %| n)%N -> m.-primitive_root (z ^+ (n %/ m)).\n\n(*This lemma states that a primitive root of unity is never the zero element of the ring.*)\nLemma prim_root_eq0 : (z == 0) = (n == 0%N).\n\nEnd OnePrimitive.\n\n(*This lemma states that for a primitive n-th root of unity, raising it to a power k yields another primitive n-th root of unity if and only if the exponent k is coprime to n.*)\nLemma prim_root_exp_coprime n z k :\n n.-primitive_root z -> n.-primitive_root (z ^+ k) = coprime k n.\n\nImplicit Type S : {pred R}.\n\n(*This definition creates a predicate that is true for a given polynomial if and only if all of its coefficients belong to a specified set of ring elements.*)\nDefinition polyOver_pred S := fun p : {poly R} => all (mem S) p.\nArguments polyOver_pred _ _ /.\n(*This definition establishes a type for polynomials whose coefficients are all members of a given set of ring elements.*)\nDefinition polyOver S := [qualify a p | polyOver_pred S p].\n\n(*This lemma states that if one set of ring elements is a subset of another, then the type of polynomials with coefficients from the first set is a subtype of the polynomials with coefficients from the second set.*)\nLemma polyOverS (S1 S2 : {pred R}) :\n {subset S1 <= S2} -> {subset polyOver S1 <= polyOver S2}.\n\n(*This lemma states that the zero polynomial qualifies as a polynomial over any given set of ring elements.*)\nLemma polyOver0 S : 0 \\is a polyOver S.\n\n(*This lemma states that a polynomial constructed from a finite sequence of coefficients belongs to the type of polynomials over a given set if all coefficients in the sequence are members of that set.*)\nLemma polyOver_poly S n E :\n (forall i, i < n -> E i \\in S) -> \\poly_(i < n) E i \\is a polyOver S.\n\nSection PolyOverAdd.\n\nVariable S : addrClosed R.\n\n(*This lemma provides a boolean reflection for the property that a polynomial belongs to the type of polynomials over a given additive subgroup, stating this is equivalent to all of its coefficients being members of that subgroup.*)\nLemma polyOverP {p} : reflect (forall i, p`_i \\in S) (p \\in polyOver S).\n\n(*This lemma states that a constant polynomial, formed from a ring element, is considered a polynomial over a specific subset of the ring if and only if the original ring element is a member of that subset.*)\nLemma polyOverC c : (c%:P \\in polyOver S) = (c \\in S).\n\n(*This fact asserts that the set of polynomials whose coefficients are all drawn from a specific subset of a ring is closed under polynomial addition.*)\nFact polyOver_addr_closed : addr_closed (polyOver S).\n\n(*This lemma states that for a set of polynomials whose coefficients belong to a semiring subset that is closed under multiplication by two, this set of polynomials is also closed under multiplication by the ring element two.*)\nLemma polyOver_mulr_2closed : GRing.mulr_2closed (polyOver S).\n\n(*This fact asserts that if a subset of a ring is closed under additive negation, then the set of polynomials with coefficients from that subset is also closed under additive negation.*)\nFact polyOverNr (zmodS : zmodClosed R) : oppr_closed (polyOver zmodS).\n\nHB.instance Definition _ (zmodS : zmodClosed R) :=\n GRing.isOppClosed.Build {poly R} (polyOver_pred zmodS) (@polyOverNr _).\n\nSection PolyOverSemiring.\n\nVariable S : semiringClosed R.\n\n(*This fact asserts that the constant polynomial representing the multiplicative identity one is a member of the set of polynomials over any semiring-closed subset.*)\nFact polyOver_mul1_closed : 1 \\in (polyOver S).\n\n(*This lemma states that if a polynomial has all its coefficients in a given subset of a ring, and it is scaled by an element from that same subset, the resulting polynomial also has all its coefficients in that subset.*)\nLemma polyOverZ : {in S & polyOver S, forall c p, c *: p \\is a polyOver S}.\n\n(*This lemma states that the indeterminate monomial, often denoted as 'X', is a member of the set of polynomials over any given semiring-closed subset of the base ring.*)\nLemma polyOverX : 'X \\in polyOver S.\n\n(*This lemma states that for any natural number power, the monomial consisting of the indeterminate 'X' raised to that power is a member of the set of polynomials over any given semiring-closed subset.*)\nLemma polyOverXn n : 'X^n \\in polyOver S.\n\n(*This lemma states that if a polynomial has all its coefficients in a given subset of a ring, and it is evaluated at a point that is also in that subset, then the result of the evaluation will be an element of that same subset.*)\nLemma rpred_horner : {in polyOver S & S, forall p x, p.[x] \\in S}.\n\nEnd PolyOverSemiring.\n\nSection PolyOverRing.\n\nVariable S : subringClosed R.\n\n(*This lemma states that the polynomial formed by adding the indeterminate 'X' to a constant is considered a polynomial over a specific subset of a ring if and only if the constant itself is an element of that subset.*)\nLemma polyOverXaddC c : ('X + c%:P \\in polyOver S) = (c \\in S).\n\n(*This lemma states that for any natural number power, a polynomial formed by adding the indeterminate 'X' raised to that power and a constant is considered a polynomial over a specific subset of a ring if and only if the constant is an element of that subset.*)\nLemma polyOverXnaddC n c : ('X^n + c%:P \\is a polyOver S) = (c \\in S).\n\n(*This lemma states that the polynomial formed by subtracting a constant from the indeterminate 'X' is considered a polynomial over a specific subring subset if and only if the constant itself is an element of that subset.*)\nLemma polyOverXsubC c : ('X - c%:P \\in polyOver S) = (c \\in S).\n\n(*This lemma states that for any natural number power, a polynomial formed by subtracting a constant from the indeterminate 'X' raised to that power is considered a polynomial over a specific subring subset if and only if the constant is an element of that subset.*)\nLemma polyOverXnsubC n c : ('X^n - c%:P \\is a polyOver S) = (c \\in S).\n\nEnd PolyOverRing.\n\n(*This definition specifies the formal derivative of a polynomial, where the coefficient of each term of degree i in the resulting polynomial is computed by taking the coefficient of the term of degree i plus one in the original polynomial and multiplying it by the scalar i plus one.*)\nDefinition deriv p := \\poly_(i < (size p).-1) (p`_i.+1 *+ i.+1).\n\n(*This notation provides a compact syntax for computing the formal derivative of a polynomial.*)\nLocal Notation \"a ^` ()\" := (deriv a).\n\n(*This lemma states that the coefficient of degree i of the derivative of a polynomial is equal to the product of the coefficient of degree i plus one of the original polynomial and the scalar value i plus one.*)\nLemma coef_deriv p i : p^`()`_i = p`_i.+1 *+ i.+1.\n\n(*This lemma states that the formal derivative of a polynomial whose coefficients all belong to a given semiring-closed subset of a ring is also a polynomial whose coefficients belong to that same subset.*)\nLemma polyOver_deriv (ringS : semiringClosed R) :\n {in polyOver ringS, forall p, p^`() \\is a polyOver ringS}.\n\n(*This lemma states that the formal derivative of any constant polynomial is the zero polynomial.*)\nLemma derivC c : c%:P^`() = 0.\n\n(*This lemma states that the formal derivative of the indeterminate monomial 'X' is the constant polynomial one.*)\nLemma derivX : ('X)^`() = 1.\n\n(*This lemma states that the formal derivative of the indeterminate 'X' raised to a natural number power n is equal to the polynomial 'X' raised to the power n minus one, scaled by the natural number n.*)\nLemma derivXn n : ('X^n)^`() = 'X^n.-1 *+ n.\n\n(*This fact asserts that the formal derivative operation on polynomials is a linear map.*)\nFact deriv_is_linear : linear deriv.\n\nHB.instance Definition _ := GRing.isSemilinear.Build R {poly R} {poly R} _ deriv\n (GRing.semilinear_linear deriv_is_linear).\n\n(*This lemma states that the formal derivative of the zero polynomial is the zero polynomial.*)\nLemma deriv0 : 0^`() = 0.\n\n(*This lemma states that the derivative of a sum of two polynomials is equal to the sum of their individual derivatives.*)\nLemma derivD : {morph deriv : p q / p + q}.\n\n(*This lemma states that the derivative of the additive inverse of a polynomial is equal to the additive inverse of the derivative of that polynomial.*)\nLemma derivN : {morph deriv : p / - p}.\n\n(*This lemma states that the derivative of the difference of two polynomials is equal to the difference of their individual derivatives.*)\nLemma derivB : {morph deriv : p q / p - q}.\n\n(*This lemma states that the formal derivative of a polynomial formed by subtracting a constant from the indeterminate 'X' is the constant polynomial one.*)\nLemma derivXsubC (a : R) : ('X - a%:P)^`() = 1.\n\n(*This lemma states that the derivative of a polynomial scaled by a natural number is equal to the derivative of the polynomial scaled by the same natural number.*)\nLemma derivMn n p : (p *+ n)^`() = p^`() *+ n.\n\n(*This lemma states that the derivative of a polynomial scaled by an integer is equal to the derivative of the polynomial scaled by the same integer.*)\nLemma derivMNn n p : (p *- n)^`() = p^`() *- n.\n\n(*This lemma states that the derivative of a polynomial scaled by a ring element is equal to the derivative of the polynomial scaled by the same ring element.*)\nLemma derivZ c p : (c *: p)^`() = c *: p^`().\n\n(*This lemma states that the derivative of the product of a constant polynomial and another polynomial is equal to the product of that same constant polynomial and the derivative of the other polynomial.*)\nLemma deriv_mulC c p : (c%:P * p)^`() = c%:P * p^`().\n\n(*This lemma states that the derivative of a polynomial formed by multiplying a given polynomial by the indeterminate 'X' and adding a constant is equal to the sum of the original polynomial and the product of its derivative with the indeterminate 'X'.*)\nLemma derivMXaddC p c : (p * 'X + c%:P)^`() = p + p^`() * 'X.\n\n(*This lemma states the product rule for polynomial differentiation: the derivative of the product of two polynomials is the sum of the derivative of the first polynomial multiplied by the second, and the first polynomial multiplied by the derivative of the second.*)\nLemma derivM p q : (p * q)^`() = p^`() * q + p * q^`().\n\n(*This definition provides a collection of lemmas about polynomial differentiation, intended for use by automated proof tactics to simplify expressions involving derivatives.*)\nDefinition derivE := Eval lazy beta delta [morphism_2 morphism_1] in\n (derivZ, deriv_mulC, derivC, derivX, derivMXaddC, derivXsubC, derivM, derivB,\n derivD, derivN, derivXn, derivM, derivMn).\n\n(*This definition specifies the nth derivative of a polynomial as the result of applying the single-step derivative operation a given number of times.*)\nDefinition derivn n p := iter n deriv p.\n\n(*A notation for the nth derivative of a polynomial, where the base represents the polynomial and the parenthesized superscript represents the order of the derivative.*)\nLocal Notation \"a ^` ( n )\" := (derivn n a) : ring_scope.\n\n(*This lemma states that the zeroth derivative of any polynomial is the polynomial itself.*)\nLemma derivn0 p : p^`(0) = p.\n\n(*This lemma states that the first iterated derivative of a polynomial is equal to its standard single derivative.*)\nLemma derivn1 p : p^`(1) = p^`().\n\n(*This lemma provides a recursive formula for the iterated derivative, stating that the derivative of order n plus one of a polynomial is equivalent to taking the derivative of the nth derivative of that same polynomial.*)\nLemma derivnS p n : p^`(n.+1) = p^`(n)^`().\n\n(*This lemma states that the derivative of order n plus one of a polynomial can be computed by first taking a single derivative of the polynomial and then taking the nth derivative of the result.*)\nLemma derivSn p n : p^`(n.+1) = p^`()^`(n).\n\n(*This lemma provides a formula for the coefficient of degree i of the nth derivative of a polynomial. It is calculated as the coefficient of degree n plus i of the original polynomial, multiplied by the falling factorial of n plus i taken n times.*)\nLemma coef_derivn n p i : p^`(n)`_i = p`_(n + i) *+ (n + i) ^_ n.\n\n(*This lemma states that the set of polynomials with coefficients in a given closed sub-semiring is closed under the operation of taking the nth derivative.*)\nLemma polyOver_derivn (ringS : semiringClosed R) :\n {in polyOver ringS, forall p n, p^`(n) \\is a polyOver ringS}.\n\n(*This fact asserts that for any given natural number, the function that computes the nth derivative of a polynomial is a linear map.*)\nFact derivn_is_linear n : linear (derivn n).\n\nHB.instance Definition _ n :=\n GRing.isSemilinear.Build R {poly R} {poly R} _ (derivn n)\n (GRing.semilinear_linear (derivn_is_linear n)).\n\n(*This lemma states that the nth derivative of a constant polynomial is the constant polynomial itself if the order of the derivative is zero, and the zero polynomial otherwise.*)\nLemma derivnC c n : c%:P^`(n) = if n == 0 then c%:P else 0.\n\n(*This lemma states that the nth derivative operator is a morphism with respect to polynomial addition, meaning the nth derivative of a sum of two polynomials is the sum of their individual nth derivatives.*)\nLemma derivnD n : {morph derivn n : p q / p + q}.\n\n(*This lemma states that the nth derivative operator is a morphism with respect to polynomial subtraction, meaning the nth derivative of the difference of two polynomials is the difference of their individual nth derivatives.*)\nLemma derivnB n : {morph derivn n : p q / p - q}.\n\n(*This lemma states that taking the nth derivative of a polynomial that has been scaled by a natural number is equivalent to scaling the nth derivative of the polynomial by the same natural number.*)\nLemma derivnMn n m p : (p *+ m)^`(n) = p^`(n) *+ m.\n\n(*This lemma states that taking the nth derivative of a polynomial that has been scaled by an integer is equivalent to scaling the nth derivative of the polynomial by the same integer.*)\nLemma derivnMNn n m p : (p *- m)^`(n) = p^`(n) *- m.\n\n(*This lemma states that the nth derivative operator is a morphism with respect to polynomial negation, meaning the nth derivative of the negation of a polynomial is the negation of its nth derivative.*)\nLemma derivnN n : {morph derivn n : p / - p}.\n\n(*This lemma asserts that for any natural number, the function that computes the nth derivative of polynomials is scalable, meaning it commutes with scalar multiplication by elements from the base ring.*)\nLemma derivnZ n : scalable (derivn n).\n\n(*This lemma gives the formula for the nth derivative of a monomial of the form 'X' to the power of m. The result is the monomial 'X' to the power of m minus n, scaled by the falling factorial of m taken n times.*)\nLemma derivnXn m n : ('X^m)^`(n) = 'X^(m - n) *+ m ^_ n.\n\n(*This lemma provides a formula for the derivative of order n plus one of a polynomial formed by multiplying a polynomial p by the indeterminate 'X' and adding a constant. The result is expressed in terms of the nth and n plus first derivatives of p.*)\nLemma derivnMXaddC n p c :\n (p * 'X + c%:P)^`(n.+1) = p^`(n) *+ n.+1 + p^`(n.+1) * 'X.\n\n(*This lemma states that if the order of differentiation is greater than or equal to the size of a polynomial, which is one more than its degree, then the resulting derivative is the zero polynomial.*)\nLemma derivn_poly0 p n : size p <= n -> p^`(n) = 0.\n\n(*This lemma states that for any non-zero polynomial, the size of its derivative is strictly smaller than the size of the original polynomial.*)\nLemma lt_size_deriv (p : {poly R}) : p != 0 -> size p^`() < size p.\n\n(*This definition introduces the nth normalized derivative of a polynomial, where the coefficient of degree i in the resulting polynomial is computed by multiplying the coefficient of degree n plus i from the original polynomial by the binomial coefficient 'n plus i choose n'.*)\nDefinition nderivn n p := \\poly_(i < size p - n) (p`_(n + i) *+ 'C(n + i, n)).\n\n(*A notation for the nth normalized derivative of a polynomial, where the base represents the polynomial and the parenthesized superscript with an 'N' indicates the order of the normalized derivative.*)\nLocal Notation \"a ^`N ( n )\" := (nderivn n a) : ring_scope.\n\n(*This lemma specifies the formula for the coefficient of degree i of the nth normalized derivative of a polynomial. It is given by the coefficient of degree n plus i of the original polynomial, scaled by the binomial coefficient 'n plus i choose n'.*)\nLemma coef_nderivn n p i : p^`N(n)`_i = p`_(n + i) *+ 'C(n + i, n).\n\n(*This lemma formally relates the standard nth derivative of a polynomial to its nth normalized derivative, stating that the former is equal to the latter scaled by the factorial of n.*)\nLemma nderivn_def n p : p^`(n) = p^`N(n) *+ n`!.\n\n(*This lemma states that the set of polynomials with coefficients in a given closed sub-semiring is closed under the operation of taking the nth normalized derivative.*)\nLemma polyOver_nderivn (ringS : semiringClosed R) :\n {in polyOver ringS, forall p n, p^`N(n) \\in polyOver ringS}.\n\n(*This lemma states that the zeroth normalized derivative of any polynomial is the polynomial itself.*)\nLemma nderivn0 p : p^`N(0) = p.\n\n(*This lemma states that the first normalized derivative of a polynomial is identical to its standard single derivative.*)\nLemma nderivn1 p : p^`N(1) = p^`().\n\n(*This lemma states that the nth normalized formal derivative of a constant polynomial is the constant polynomial itself if the order of differentiation is zero, and is the zero polynomial otherwise.*)\nLemma nderivnC c n : (c%:P)^`N(n) = if n == 0 then c%:P else 0.\n\n(*This lemma states that the nth normalized formal derivative of the monomial X raised to the power m is equal to the monomial X raised to the power m minus n, multiplied by the binomial coefficient of m choose n.*)\nLemma nderivnXn m n : ('X^m)^`N(n) = 'X^(m - n) *+ 'C(m, n).\n\n(*This fact asserts that for any natural number, the nth normalized formal derivative operator on polynomials is a linear map.*)\nFact nderivn_is_linear n : linear (nderivn n).\n\n(*This lemma states that the nth normalized formal derivative of a sum of two polynomials is equal to the sum of their respective nth normalized formal derivatives.*)\nLemma nderivnD n : {morph nderivn n : p q / p + q}.\n\n(*This lemma states that the nth normalized formal derivative of the difference of two polynomials is equal to the difference of their respective nth normalized formal derivatives.*)\nLemma nderivnB n : {morph nderivn n : p q / p - q}.\n\n(*This lemma states that the nth normalized formal derivative of a polynomial scaled by a natural number is equal to the nth normalized formal derivative of the polynomial, scaled by the same natural number.*)\nLemma nderivnMn n m p : (p *+ m)^`N(n) = p^`N(n) *+ m.\n\n(*This lemma states that the nth normalized formal derivative of a polynomial scaled by an integer is equal to the nth normalized formal derivative of the polynomial, scaled by the same integer.*)\nLemma nderivnMNn n m p : (p *- m)^`N(n) = p^`N(n) *- m.\n\n(*This lemma states that the nth normalized formal derivative of the additive inverse of a polynomial is equal to the additive inverse of the nth normalized formal derivative of that polynomial.*)\nLemma nderivnN n : {morph nderivn n : p / - p}.\n\n(*This lemma states that for any natural number, the nth normalized formal derivative operator is scalable, meaning it commutes with scalar multiplication by elements from the base ring.*)\nLemma nderivnZ n : scalable (nderivn n).\n\n(*This lemma provides a recurrence relation for the normalized formal derivative, stating that the (n plus one)-th derivative of a polynomial formed by multiplying another polynomial by the indeterminate X and adding a constant is equal to the sum of the nth derivative of the original polynomial and the (n plus one)-th derivative of the original polynomial multiplied by X.*)\nLemma nderivnMXaddC n p c :\n (p * 'X + c%:P)^`N(n.+1) = p^`N(n) + p^`N(n.+1) * 'X.\n\n(*This lemma states that if the degree of a polynomial is strictly less than a natural number n, then its nth normalized formal derivative is the zero polynomial.*)\nLemma nderivn_poly0 p n : size p <= n -> p^`N(n) = 0.\n\n(*This lemma provides the Taylor expansion formula for a polynomial, stating that if two ring elements commute, the evaluation of a polynomial at their sum is equal to the finite sum of terms, where each term is the evaluation of the ith normalized formal derivative of the polynomial at the first element, multiplied by the second element raised to the power of i.*)\nLemma nderiv_taylor p x h :\n GRing.comm x h -> p.[x + h] = \\sum_(i < size p) p^`N(i).[x] * h ^+ i.\n\n(*This lemma provides a variation of the Taylor expansion formula for a polynomial, stating that if the size of a polynomial is less than or equal to a natural number n, and two ring elements commute, then the evaluation of the polynomial at their sum is equal to a sum up to n of terms, where each term is the evaluation of the ith normalized formal derivative of the polynomial at the first element, multiplied by the second element raised to the power of i.*)\nLemma nderiv_taylor_wide n p x h :\n GRing.comm x h -> size p <= n ->\n p.[x + h] = \\sum_(i < n) p^`N(i).[x] * h ^+ i.\n\n(*This lemma establishes a criterion for polynomial equality, stating that two polynomials of the same size are equal if their corresponding coefficient-generating functions produce the same coefficients for all valid indices.*)\nLemma eq_poly n E1 E2 : (forall i, i < n -> E1 i = E2 i) ->\n poly n E1 = poly n E2 :> {poly R}.\n\nEnd PolynomialTheory.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"renamed to `size_polyN`\")]\n(*This is a deprecated notation that was previously used for the size of the additive inverse of a polynomial and has been renamed to size_polyN.*)\nNotation size_opp := size_polyN (only parsing).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar_poly instead.\")]\n(*This is a deprecated notation that was used for the characteristic polynomial of a matrix and has been replaced by pchar_poly.*)\nNotation char_poly := pchar_poly (only parsing).\n\nPrenex Implicits polyC polyCK Poly polyseqK lead_coef root horner polyOver.\nArguments monic {R}.\n(*This notation provides a way to construct a polynomial of a given size, where the coefficients are generated by an expression that depends on the coefficient index.*)\nNotation \"\\poly_ ( i < n ) E\" := (poly n (fun i => E)) : ring_scope.\n(*This notation constructs a constant polynomial from a given ring element.*)\nNotation \"c %:P\" := (polyC c) : ring_scope.\n(*This notation represents the polynomial indeterminate, commonly known as X.*)\nNotation \"'X\" := (polyX _) : ring_scope.\n(*This notation represents the monomial X, the polynomial indeterminate, raised to a specified natural number power.*)\nNotation \"''X^' n\" := ('X ^+ n) : ring_scope.\n(*This notation represents the evaluation of a polynomial at a given value from the base ring.*)\nNotation \"p .[ x ]\" := (horner p x) : ring_scope.\n(*This notation defines the property that a ring element is an nth root of unity, meaning that when raised to the nth power, it equals one.*)\nNotation \"n .-unity_root\" := (root_of_unity n) : ring_scope.\n(*This notation defines the property that a ring element is a primitive nth root of unity, meaning it is an nth root of unity but not a kth root of unity for any smaller positive integer k.*)\nNotation \"n .-primitive_root\" := (primitive_root_of_unity n) : ring_scope.\n(*This notation represents the first formal derivative of a given polynomial.*)\nNotation \"a ^` ()\" := (deriv a) : ring_scope.\n(*This notation represents the nth formal derivative of a given polynomial, where n is a natural number.*)\nNotation \"a ^` ( n )\" := (derivn n a) : ring_scope.\n(*This notation represents the nth normalized formal derivative of a given polynomial, where the result is divided by n factorial.*)\nNotation \"a ^`N ( n )\" := (nderivn n a) : ring_scope.\n\nArguments monic_pred _ _ /.\nArguments monicP {R p}.\nArguments rootP {R p x}.\nArguments rootPf {R p x}.\nArguments rootPt {R p x}.\nArguments unity_rootP {R n z}.\nArguments polyOver_pred _ _ _ /.\nArguments polyOverP {R S p}.\nArguments polyC_inj {R} [x1 x2] eq_x12P.\nArguments eq_poly {R n} [E1] E2 eq_E12.\n\nSection IdomainPrimRoot.\nVariables (R : idomainType) (n : nat) (z : R).\nHypothesis prim_z : n.-primitive_root z.\nImport prime.\n(*This definition establishes that the order of a primitive root of unity must be a natural number greater than zero.*)\nLet n_gt0 := prim_order_gt0 prim_z.\n\n(*This lemma states that if a prime number divides the order of a primitive root of unity in an integral domain, then that prime number cannot be the characteristic of the ring.*)\nLemma prim_root_pcharF p : (p %| n)%N -> p \\in [pchar R] = false.\n\n(*This lemma states that the characteristic of an integral domain is coprime to the order of any primitive root of unity existing in that domain.*)\nLemma pchar_prim_root : [pchar R]^'.-nat n.\n\n(*This lemma states that in an integral domain containing an nth primitive root of unity, any multiple of the smallest prime factor of n is a non-zero element when interpreted as a ring element.*)\nLemma prim_root_pi_eq0 m : \\pi(n).-nat m -> m%:R != 0 :> R.\n\n(*This lemma states that if a natural number `m` divides the order `n` of a primitive root of unity in an integral domain, then the ring representation of `m` is not the zero element.*)\nLemma prim_root_dvd_eq0 m : (m %| n)%N -> m%:R != 0 :> R.\n\n(*This lemma states that the ring representation of the order of a primitive root of unity is not the zero element.*)\nLemma prim_root_natf_neq0 : n%:R != 0 :> R.\n\nEnd IdomainPrimRoot.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use prim_root_pcharF instead.\")]\n(*This notation provides a deprecated alias for `prim_root_pcharF`, intended for parsing purposes only.*)\nNotation prim_root_charF := prim_root_pcharF (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar_prim_root instead.\")]\n(*This notation provides a deprecated alias for `pchar_prim_root`, intended for parsing purposes only.*)\nNotation char_prim_root := pchar_prim_root (only parsing).\n\nSection MapPoly.\n\nSection Definitions.\n\nVariables (aR rR : nzRingType) (f : aR -> rR).\n\n(*This definition creates a new polynomial by applying a given function to each coefficient of an input polynomial.*)\nDefinition map_poly (p : {poly aR}) := \\poly_(i < size p) f p`_i.\n\n(*This lemma states that applying a function to all coefficients of a polynomial is equivalent to mapping that function over the polynomial's underlying sequence of coefficients and then constructing a new polynomial.*)\nLemma map_polyE p : map_poly p = Poly (map f p).\n\n(*This definition specifies a property for an element of a ring, which holds if that element commutes with all values in the image of a given function.*)\nDefinition commr_rmorph u := forall x, GRing.comm u (f x).\n\n(*This definition constructs a function that evaluates a transformed polynomial at a specific point, where the transformation applies a function to the polynomial's coefficients and the evaluation point is required to commute with all transformed coefficients.*)\nDefinition horner_morph u of commr_rmorph u := fun p => (map_poly p).[u].\n\nEnd Definitions.\n\nVariables aR rR : nzRingType.\n\nSection Combinatorial.\n\nVariables (iR : nzRingType) (f : aR -> rR).\n(**)\nLocal Notation \"p ^f\" := (map_poly f p) : ring_scope.\n\n(*This lemma states that applying a function to the coefficients of the zero polynomial results in the zero polynomial.*)\nLemma map_poly0 : 0^f = 0.\n\n(*This lemma states that if two functions are pointwise equal, then the transformations that apply these functions to polynomial coefficients are also pointwise equal.*)\nLemma eq_map_poly (g : aR -> rR) : f =1 g -> map_poly f =1 map_poly g.\n\n(*This lemma states that if a function acts as the identity on all coefficients of a given polynomial, then applying this function to the coefficients of that polynomial leaves the polynomial unchanged.*)\nLemma map_poly_id g (p : {poly iR}) :\n {in (p : seq iR), g =1 id} -> map_poly g p = p.\n\n(*This lemma states that if a function maps zero to zero, then the coefficient at any given degree of a transformed polynomial is equal to the function applied to the coefficient of the same degree in the original polynomial.*)\nLemma coef_map_id0 p i : f 0 = 0 -> (p^f)`_i = f p`_i.\n\n(*This lemma states that if a function maps zero to zero, transforming a polynomial constructed from a sequence of coefficients is equivalent to constructing a polynomial from the sequence obtained by applying the function to each element.*)\nLemma map_Poly_id0 s : f 0 = 0 -> (Poly s)^f = Poly (map f s).\n\n(*This lemma states that applying the composition of two functions to the coefficients of a polynomial is equivalent to first applying one function and then applying the second function to the coefficients of the resulting polynomial, provided the second function maps zero to zero.*)\nLemma map_poly_comp_id0 (g : iR -> aR) p :\n f 0 = 0 -> map_poly (f \\o g) p = (map_poly g p)^f.\n\n(*This lemma states that if a function does not map the leading coefficient of a non-zero polynomial to zero, then the size of the transformed polynomial is equal to the size of the original polynomial.*)\nLemma size_map_poly_id0 p : f (lead_coef p) != 0 -> size p^f = size p.\n\n(*This lemma states that for a non-zero polynomial, if a function does not map its leading coefficient to zero, then the transformed polynomial is zero if and only if the original polynomial is zero.*)\nLemma map_poly_eq0_id0 p : f (lead_coef p) != 0 -> (p^f == 0) = (p == 0).\n\n(*This lemma states that if a function maps zero to zero and does not map the leading coefficient of a polynomial to zero, then the leading coefficient of the transformed polynomial is the result of applying the function to the original leading coefficient.*)\nLemma lead_coef_map_id0 p :\n f 0 = 0 -> f (lead_coef p) != 0 -> lead_coef p^f = f (lead_coef p).\n\nHypotheses (inj_f : injective f) (f_0 : f 0 = 0).\n\n(*This lemma states that if a function is injective and maps zero to zero, then applying this function to a polynomial's coefficients results in a new polynomial of the same size.*)\nLemma size_map_inj_poly p : size p^f = size p.\n\n(*This lemma states that applying an injective function that maps zero to zero to the coefficients of polynomials is an injective operation on polynomials.*)\nLemma map_inj_poly : injective (map_poly f).\n\n(*This lemma states that if a function is injective and maps zero to zero, the leading coefficient of a transformed polynomial is the result of applying that function to the leading coefficient of the original polynomial.*)\nLemma lead_coef_map_inj p : lead_coef p^f = f (lead_coef p).\n\nEnd Combinatorial.\n\n(*This lemma states that if one function is a left inverse of another function that maps zero to zero, then the transformation applying the first function to polynomial coefficients is a left inverse of the transformation applying the second function.*)\nLemma map_polyK (f : aR -> rR) g :\n cancel g f -> f 0 = 0 -> cancel (map_poly g) (map_poly f).\n\n(*This lemma states that if two functions, which both map zero to zero, are pointwise equal on a subset of their domain that is closed under addition, then their corresponding polynomial map transformations are equal when applied to polynomials whose coefficients all lie within that subset.*)\nLemma eq_in_map_poly_id0 (f g : aR -> rR) (S : addrClosed aR) :\n f 0 = 0 -> g 0 = 0 -> {in S, f =1 g} ->\n {in polyOver S, map_poly f =1 map_poly g}.\n\n(*This lemma states that if two additive functions are pointwise equal on a subset of their domain that is closed under addition, then their corresponding polynomial map transformations are equal when applied to polynomials whose coefficients all lie within that subset.*)\nLemma eq_in_map_poly (f g : {additive aR -> rR}) (S : addrClosed aR) :\n {in S, f =1 g} -> {in polyOver S, map_poly f =1 map_poly g}.\n\nSection Additive.\n\nVariables (iR : nzRingType) (f : {additive aR -> rR}).\n\n(*A notation for the polynomial obtained by applying a given function to each coefficient of an input polynomial.*)\nLocal Notation \"p ^f\" := (map_poly (GRing.Additive.sort f) p) : ring_scope.\n\n(*This lemma states that the coefficient at a given degree in a polynomial transformed by a function is equal to the function applied to the original coefficient at that same degree.*)\nLemma coef_map p i : p^f`_i = f p`_i.\n\n(*This lemma states that applying a function to all coefficients of a polynomial constructed from a finite sequence is equivalent to first applying the function to each element of the sequence and then constructing a polynomial from the resulting sequence.*)\nLemma map_Poly s : (Poly s)^f = Poly (map f s).\n\n(*This lemma states that applying a composite function to the coefficients of a polynomial is equivalent to successively applying each function to the coefficients of the polynomial.*)\nLemma map_poly_comp (g : iR -> aR) p :\n map_poly (f \\o g) p = map_poly f (map_poly g p).\n\n(*This fact asserts that the operation which applies an additive homomorphism to every coefficient of a polynomial is itself an additive homomorphism between the respective polynomial rings.*)\nFact map_poly_is_zmod_morphism : zmod_morphism (map_poly f).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `map_poly_is_zmod_morphism` instead\")]\n(*This definition provides a deprecated alias for the property that mapping polynomial coefficients with an additive homomorphism is itself an additive homomorphism.*)\nDefinition map_poly_is_additive := map_poly_is_zmod_morphism.\n(*This lemma states that applying a function to the coefficients of a constant polynomial results in a constant polynomial whose value is the function applied to the original constant.*)\nLemma map_polyC a : (a%:P)^f = (f a)%:P.\n\n(*This lemma states that if applying a function to the leading coefficient of a polynomial yields a non-zero value, then the leading coefficient of the transformed polynomial is that non-zero value.*)\nLemma lead_coef_map_eq p :\n f (lead_coef p) != 0 -> lead_coef p^f = f (lead_coef p).\n\nEnd Additive.\n\nVariable f : {rmorphism aR -> rR}.\nImplicit Types p : {poly aR}.\n\n(*A notation for applying a ring morphism to each coefficient of a polynomial, resulting in a new polynomial over the codomain of the morphism.*)\nLocal Notation \"p ^f\" := (map_poly (GRing.RMorphism.sort f) p) : ring_scope.\n\n(*This fact asserts that the operation of applying a ring morphism to the coefficients of polynomials is a monoid morphism, meaning it preserves polynomial multiplication and the multiplicative identity polynomial.*)\nFact map_poly_is_monoid_morphism : monoid_morphism (map_poly f).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `map_poly_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, states that the operation of applying a ring morphism to the coefficients of polynomials preserves polynomial multiplication and the constant polynomial one.*)\nDefinition map_poly_is_multiplicative :=\n (fun g => (g.2, g.1)) map_poly_is_monoid_morphism.\nHB.instance Definition _ :=\n GRing.isMonoidMorphism.Build {poly aR} {poly rR} (map_poly f)\n map_poly_is_monoid_morphism.\n\n(*This lemma states that applying a ring morphism to the coefficients of a polynomial that has been scaled by a ring element is equivalent to first applying the morphism to the scalar and then scaling the morphism-applied polynomial with the result.*)\nLemma map_polyZ c p : (c *: p)^f = f c *: p^f.\n\n(*This lemma states that applying a ring morphism to the coefficients of the indeterminate polynomial results in the indeterminate polynomial itself.*)\nLemma map_polyX : ('X)^f = 'X.\n\n(*This lemma states that applying a ring morphism to the coefficients of a polynomial that is a power of the indeterminate results in the same power of the indeterminate.*)\nLemma map_polyXn n : ('X^n)^f = 'X^n.\n\n(*This lemma states that applying a ring morphism to the coefficients of a polynomial formed by adding the indeterminate to a constant polynomial is equivalent to adding the indeterminate to the constant polynomial obtained by applying the morphism to the original constant.*)\nLemma map_polyXaddC x : ('X + x%:P)^f = 'X + (f x)%:P.\n\n(*This lemma states that applying a ring morphism to the coefficients of a polynomial formed by subtracting a constant polynomial from the indeterminate is equivalent to subtracting the constant polynomial obtained by applying the morphism to the original constant from the indeterminate.*)\nLemma map_polyXsubC x : ('X - x%:P)^f = 'X - (f x)%:P.\n\n(*This lemma states that applying a ring morphism to the coefficients of a polynomial that is expressed as a product of linear factors of the form (indeterminate minus a constant) results in a new product of linear factors where the morphism has been applied to each constant term.*)\nLemma map_prod_XsubC I (rI : seq I) P F :\n (\\prod_(i <- rI | P i) ('X - (F i)%:P))^f =\n \\prod_(i <- rI | P i) ('X - (f (F i))%:P).\n\n(*This lemma states that the product of linear factors constructed from a sequence of ring elements, which is itself the result of applying a ring morphism to an original sequence, is equal to applying the morphism to the coefficients of the product of linear factors constructed from the original sequence.*)\nLemma prod_map_poly (ar : seq aR) P :\n \\prod_(x <- map f ar | P x) ('X - x%:P) =\n (\\prod_(x <- ar | P (f x)) ('X - x%:P))^f.\n\n(*This lemma states that if a polynomial is monic, then the polynomial resulting from applying a ring morphism to its coefficients is also monic.*)\nLemma monic_map p : p \\is monic -> p^f \\is monic.\n\n(*This lemma states that evaluating a morphism-applied polynomial at a morphism-applied value is equivalent to applying the ring morphism to the result of evaluating the original polynomial at the original value.*)\nLemma horner_map p x : p^f.[f x] = f p.[x].\n\n(*This lemma states that if evaluating a polynomial at a specific ring element yields a result that commutes with that same element, then the same property holds for the morphism-applied polynomial evaluated at the morphism-applied element.*)\nLemma map_comm_poly p x : comm_poly p x -> comm_poly p^f (f x).\n\n(*This lemma states that if every coefficient of a polynomial commutes with a specific ring element, then every coefficient of the morphism-applied polynomial commutes with the morphism-applied ring element.*)\nLemma map_comm_coef p x : comm_coef p x -> comm_coef p^f (f x).\n\n(*This lemma states that if a value is a root of a polynomial, then applying a ring morphism to that value results in a root of the polynomial whose coefficients have also been transformed by the same morphism.*)\nLemma rmorph_root p x : root p x -> root p^f (f x).\n\n(*This lemma states that if a ring element is an n-th root of unity, then its image under a ring morphism is also an n-th root of unity.*)\nLemma rmorph_unity_root n z : n.-unity_root z -> n.-unity_root (f z).\n\nSection HornerMorph.\n\nVariable u : rR.\nHypothesis cfu : commr_rmorph f u.\n\n(*This lemma states that a Horner-based ring morphism, when applied to a constant polynomial, yields the result of applying its underlying ring morphism to the constant coefficient.*)\nLemma horner_morphC a : horner_morph cfu a%:P = f a.\n\n(*This lemma states that a Horner-based ring morphism, when applied to the indeterminate polynomial, yields the specific ring element designated as the evaluation point for the morphism.*)\nLemma horner_morphX : horner_morph cfu 'X = u.\n\n(*This fact asserts that a Horner-based ring morphism is a semilinear map, meaning it respects scalar multiplication up to the action of its underlying ring morphism.*)\nFact horner_is_linear : linear_for (f \\; *%R) (horner_morph cfu).\n\n(*This fact asserts that a Horner-based ring morphism is a monoid morphism, meaning it preserves polynomial multiplication and the multiplicative identity.*)\nFact horner_is_monoid_morphism : monoid_morphism (horner_morph cfu).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `horner_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, states that a Horner-based ring morphism preserves polynomial multiplication and maps the constant polynomial one to the multiplicative identity of the target ring.*)\nDefinition horner_is_multiplicative :=\n (fun g => (g.2, g.1)) horner_is_monoid_morphism.\nHB.instance Definition _ :=\n GRing.isSemilinear.Build aR {poly aR} rR _ (horner_morph cfu)\n (GRing.semilinear_linear horner_is_linear).\n\n(*This lemma states that taking the formal derivative of a polynomial whose coefficients have been transformed by a ring morphism is equivalent to first taking the derivative of the original polynomial and then applying the morphism to the coefficients of the resulting derivative.*)\nLemma deriv_map p : p^f^`() = (p^`())^f.\n\n(*This lemma states that taking the n-th formal derivative of a polynomial whose coefficients have been transformed by a ring morphism is equivalent to first taking the n-th derivative of the original polynomial and then applying the morphism to the coefficients of the result.*)\nLemma derivn_map p n : p^f^`(n) = (p^`(n))^f.\n\n(*This lemma states that taking the normalized n-th formal derivative of a polynomial whose coefficients have been transformed by a ring morphism is equivalent to first taking the normalized n-th derivative of the original polynomial and then applying the morphism to the coefficients of the result.*)\nLemma nderivn_map p n : p^f^`N(n) = (p^`N(n))^f.\n\nEnd MapPoly.\n\n(*This lemma states that for a ring morphism from a field, a value is a root of a given polynomial if and only if the image of that value under the morphism is a root of the polynomial whose coefficients have been transformed by the same morphism.*)\nLemma mapf_root (F : fieldType) (R : nzRingType) (f : {rmorphism F -> R})\n (p : {poly F}) (x : F) : root (map_poly f p) (f x) = root p x.\n\nSection MorphPoly.\n\nVariable (aR rR : nzRingType) (pf : {rmorphism {poly aR} -> rR}).\n\n(*This lemma states that for any ring morphism from a polynomial ring, the image of any constant coefficient under the morphism commutes with the image of the indeterminate polynomial.*)\nLemma poly_morphX_comm : commr_rmorph (pf \\o polyC) (pf 'X).\n\n(*This lemma states the universal property of polynomial rings: any ring morphism from a polynomial ring is uniquely determined by its action on the constant coefficients and the indeterminate, and is equivalent to the corresponding Horner-based evaluation morphism.*)\nLemma poly_initial : pf =1 horner_morph poly_morphX_comm.\n\nEnd MorphPoly.\n\n(*A notation for lifting a polynomial with coefficients in a base ring to a polynomial whose coefficients are themselves constant polynomials over that same base ring.*)\nNotation \"p ^:P\" := (map_poly polyC p) : ring_scope.\n\nSection PolyCompose.\n\nVariable R : nzRingType.\nImplicit Types p q : {poly R}.\n\n(*This definition specifies the composition of two polynomials, where the second polynomial is substituted for the indeterminate in the first polynomial.*)\nDefinition comp_poly q p := p^:P.[q].\n\n(*A notation for the composition of two polynomials, which substitutes the second polynomial for the indeterminate in the first polynomial.*)\nLocal Notation \"p \\Po q\" := (comp_poly q p) : ring_scope.\n\n(*This lemma states that the size of a polynomial remains unchanged after applying a canonical conjugation to its coefficients.*)\nLemma size_map_polyC p : size p^:P = size p.\n\n(*This lemma states that a polynomial with canonically conjugated coefficients is the zero polynomial if and only if the original polynomial is the zero polynomial.*)\nLemma map_polyC_eq0 p : (p^:P == 0) = (p == 0).\n\n(*This lemma states that a ring element is a root of a polynomial with canonically conjugated coefficients if and only if the conjugate of the ring element is a root of the original polynomial.*)\nLemma root_polyC p x : root p^:P x%:P = root p x.\n\n(*This lemma provides the explicit formula for the composition of two polynomials, expressing the result as a sum over the terms of the first polynomial, where each coefficient is multiplied by the second polynomial raised to the corresponding power.*)\nLemma comp_polyE p q : p \\Po q = \\sum_(i < size p) p`_i *: q^+i.\n\n(*This lemma states that a given coefficient of the composition of two polynomials is calculated as a sum, over the indices of the first polynomial, of the product of each of its coefficients with the corresponding coefficient of the second polynomial raised to the power of the index.*)\nLemma coef_comp_poly p q n :\n (p \\Po q)`_n = \\sum_(i < size p) p`_i * (q ^+ i)`_n.\n\n(*This lemma states that the set of polynomials whose coefficients belong to a given closed sub-semiring is closed under composition; that is, composing two such polynomials results in another polynomial whose coefficients are in the same sub-semiring.*)\nLemma polyOver_comp (ringS : semiringClosed R) :\n {in polyOver ringS &, forall p q, p \\Po q \\in polyOver ringS}.\n\n(*This lemma states that composing a polynomial with a constant polynomial is equivalent to evaluating the first polynomial at the constant's value and then creating a new constant polynomial from that result.*)\nLemma comp_polyCr p c : p \\Po c%:P = p.[c]%:P.\n\n(*This lemma states that the composition of any polynomial with the zero polynomial results in a constant polynomial whose value is the constant term of the first polynomial.*)\nLemma comp_poly0r p : p \\Po 0 = (p`_0)%:P.\n\n(*This lemma states that composing a constant polynomial with any other polynomial yields the original constant polynomial.*)\nLemma comp_polyC c p : c%:P \\Po p = c%:P.\n\n(*This fact asserts that for a fixed second polynomial, the operation of polynomial composition is linear with respect to the first polynomial.*)\nFact comp_poly_is_linear p : linear (comp_poly p).\n\n(*This lemma states that the composition of the zero polynomial with any other polynomial results in the zero polynomial.*)\nLemma comp_poly0 p : 0 \\Po p = 0.\n\n(*This lemma states that polynomial composition is left-distributive over polynomial addition. That is, composing the sum of two polynomials with a third polynomial is the same as summing their individual compositions with the third polynomial.*)\nLemma comp_polyD p q r : (p + q) \\Po r = (p \\Po r) + (q \\Po r).\n\n(*This lemma states that polynomial composition is left-distributive over polynomial subtraction. That is, composing the difference of two polynomials with a third polynomial is the same as the difference of their individual compositions with the third polynomial.*)\nLemma comp_polyB p q r : (p - q) \\Po r = (p \\Po r) - (q \\Po r).\n\n(*This lemma states that scalar multiplication of a polynomial is compatible with composition on the left. That is, composing a scalar-multiplied polynomial with another polynomial is equivalent to applying the scalar multiplication after the composition.*)\nLemma comp_polyZ c p q : (c *: p) \\Po q = c *: (p \\Po q).\n\n(*This lemma states that composing any polynomial with the indeterminate monomial polynomial results in the original polynomial.*)\nLemma comp_polyXr p : p \\Po 'X = p.\n\n(*This lemma states that composing the indeterminate monomial polynomial with any second polynomial results in that second polynomial.*)\nLemma comp_polyX p : 'X \\Po p = p.\n\n(*This lemma describes how composition interacts with a linear polynomial expression. It states that composing a polynomial of the form `p * 'X + c` with another polynomial `q` is equivalent to composing `p` with `q`, multiplying the result by `q`, and then adding the constant `c`.*)\nLemma comp_poly_MXaddC c p q : (p * 'X + c%:P) \\Po q = (p \\Po q) * q + c%:P.\n\n(*This lemma states that composing a polynomial with a shift by a constant, and then composing the result with a shift by the additive inverse of that constant, yields the original polynomial.*)\nLemma comp_polyXaddC_K p z : (p \\Po ('X + z%:P)) \\Po ('X - z%:P) = p.\n\n(*This lemma provides an upper bound for the size of a composite polynomial, stating that it is less than or equal to one plus the product of the degrees of the two original polynomials.*)\nLemma size_comp_poly_leq p q :\n size (p \\Po q) <= ((size p).-1 * (size q).-1).+1.\n\n(*This lemma states that composing the monomial polynomial `'X'` raised to a power with a second polynomial is equivalent to raising that second polynomial to the same power.*)\nLemma comp_Xn_poly p n : 'X^n \\Po p = p ^+ n.\n\n(*This lemma specifies the `i`-th coefficient of a polynomial composed with the monomial `'X'` raised to a positive power `n`. The resulting coefficient is the `(i / n)`-th coefficient of the original polynomial if `i` is a multiple of `n`, and zero otherwise.*)\nLemma coef_comp_poly_Xn p n i : 0 < n ->\n (p \\Po 'X^n)`_i = if n %| i then p`_(i %/ n) else 0.\n\n(*This lemma provides the full expression for a polynomial composed with the monomial `'X'` raised to a positive power `n`, defining the new polynomial by its coefficients based on whether their index is divisible by `n`.*)\nLemma comp_poly_Xn p n : 0 < n ->\n p \\Po 'X^n = \\poly_(i < size p * n) if n %| i then p`_(i %/ n) else 0.\n\nEnd PolyCompose.\n\n(*This notation defines the infix operator for polynomial composition, where `p \\Po q` represents the composition of polynomial `p` with polynomial `q`, equivalent to evaluating `p` at `q`.*)\nNotation \"p \\Po q\" := (comp_poly q p) : ring_scope.\n\n(*This lemma states that applying a ring morphism to the coefficients of a composed polynomial is equivalent to first applying the morphism to the coefficients of each polynomial and then composing the results.*)\nLemma map_comp_poly (aR rR : nzRingType) (f : {rmorphism aR -> rR}) p q :\n map_poly f (p \\Po q) = map_poly f p \\Po map_poly f q.\n\nSection Surgery.\n\nVariable R : nzRingType.\n\nImplicit Type p q : {poly R}.\n\n(*This definition constructs a new polynomial from an existing one by taking only the coefficients at even-numbered indices. The `i`-th coefficient of the new polynomial is the `(2*i)`-th coefficient of the original polynomial.*)\nDefinition even_poly p : {poly R} := \\poly_(i < uphalf (size p)) p`_i.*2.\n\n(*This lemma states that the size of a polynomial constructed by taking only its even-indexed coefficients is at most half the size of the original polynomial, rounded up.*)\nLemma size_even_poly p : size (even_poly p) <= uphalf (size p).\n\n(*This lemma states that the `i`-th coefficient of a polynomial constructed by the `even_poly` operation is equal to the `(2*i)`-th coefficient of the original polynomial.*)\nLemma coef_even_poly p i : (even_poly p)`_i = p`_i.*2.\n\n(*This lemma provides an expanded expression for a polynomial constructed with the `even_poly` operation, applicable when there is an upper bound on the original polynomial's size. It states that if the original size is at most `2*s`, the new polynomial is formed by taking coefficients at indices `2*i` for all `i` from zero up to `s` minus one.*)\nLemma even_polyE s p : size p <= s.*2 -> even_poly p = \\poly_(i < s) p`_i.*2.\n\n(*This lemma provides the exact size for a polynomial constructed by the `even_poly` operation when the original polynomial has an odd size. In this case, the size of the resulting polynomial is exactly half the original size, rounded up.*)\nLemma size_even_poly_eq p : odd (size p) ->\n size (even_poly p) = uphalf (size p).\n\n(*This lemma states that the `even_poly` operation distributes over polynomial addition. Applying the operation to a sum of two polynomials is equivalent to summing the results of applying the operation to each polynomial individually.*)\nLemma even_polyD p q : even_poly (p + q) = even_poly p + even_poly q.\n\n(*This lemma states that applying the `even_poly` function to a polynomial that has been scaled by a scalar element is equivalent to first applying `even_poly` to the polynomial and then scaling the result by the same scalar.*)\nLemma even_polyZ k p : even_poly (k *: p) = k *: even_poly p.\n\n(*This fact asserts that the `even_poly` function is a linear transformation.*)\nFact even_poly_is_linear : linear even_poly.\n\nHB.instance Definition _ :=\n GRing.isSemilinear.Build R {poly R} {poly R} _ even_poly\n (GRing.semilinear_linear even_poly_is_linear).\n\n(*This lemma states that applying the `even_poly` function to a constant polynomial yields the constant polynomial itself.*)\nLemma even_polyC (c : R) : even_poly c%:P = c%:P.\n\n(*This definition introduces a function `odd_poly` that constructs a new polynomial from an input polynomial by taking the coefficients of the terms with odd degrees. The coefficient of the term of degree `i` in the resulting polynomial corresponds to the coefficient of the term of degree `2*i + 1` in the original polynomial.*)\nDefinition odd_poly p : {poly R} := \\poly_(i < (size p)./2) p`_i.*2.+1.\n\n(*This lemma states that the size of the polynomial resulting from the `odd_poly` function is less than or equal to half the size of the original polynomial.*)\nLemma size_odd_poly p : size (odd_poly p) <= (size p)./2.\n\n(*This lemma specifies that the coefficient of the term of degree `i` in the polynomial generated by `odd_poly` is equal to the coefficient of the term of degree `2*i + 1` in the original polynomial.*)\nLemma coef_odd_poly p i : (odd_poly p)`_i = p`_i.*2.+1.\n\n(*This lemma provides an alternative expression for the `odd_poly` of a polynomial `p` under the condition that the size of `p` is bounded by `2*s + 1`. In this case, the result is equal to a polynomial constructed from the first `s` odd-indexed coefficients of `p`.*)\nLemma odd_polyE s p :\n size p <= s.*2.+1 -> odd_poly p = \\poly_(i < s) p`_i.*2.+1.\n\n(*This lemma states that applying the `odd_poly` function to any constant polynomial results in the zero polynomial.*)\nLemma odd_polyC (c : R) : odd_poly c%:P = 0.\n\n(*This lemma states that the `odd_poly` function distributes over polynomial addition; applying it to a sum of two polynomials is the same as summing the results of applying it to each polynomial individually.*)\nLemma odd_polyD p q : odd_poly (p + q) = odd_poly p + odd_poly q.\n\n(*This lemma states that applying the `odd_poly` function to a polynomial scaled by a scalar is equivalent to first applying `odd_poly` to the polynomial and then scaling the result by the same scalar.*)\nLemma odd_polyZ k p : odd_poly (k *: p) = k *: odd_poly p.\n\n(*This fact asserts that the `odd_poly` function is a linear transformation.*)\nFact odd_poly_is_linear : linear odd_poly.\n\nHB.instance Definition _ :=\n GRing.isSemilinear.Build R {poly R} {poly R} _ odd_poly\n (GRing.semilinear_linear odd_poly_is_linear).\n\n(*This lemma states that if a non-zero polynomial has a size that is an even number, then the size of the polynomial created by the `odd_poly` function is exactly half the size of the original polynomial.*)\nLemma size_odd_poly_eq p : ~~ odd (size p) -> size (odd_poly p) = (size p)./2.\n\n(*This lemma states that extracting the odd-degree terms of a polynomial that has been multiplied by the indeterminate is equivalent to extracting the even-degree terms of the original polynomial.*)\nLemma odd_polyMX p : odd_poly (p * 'X) = even_poly p.\n\n(*This lemma states that extracting the even-degree terms of a polynomial that has been multiplied by the indeterminate is equivalent to first extracting the odd-degree terms of the original polynomial and then multiplying the resulting polynomial by the indeterminate.*)\nLemma even_polyMX p : even_poly (p * 'X) = odd_poly p * 'X.\n\n(*This lemma asserts that summing all terms of a polynomial that have an even degree is equivalent to composing the polynomial of even-indexed coefficients with the monomial of degree two.*)\nLemma sum_even_poly p :\n \\sum_(i < size p | ~~ odd i) p`_i *: 'X^i = even_poly p \\Po 'X^2.\n\n(*This lemma asserts that summing all terms of a polynomial that have an odd degree is equivalent to composing the polynomial of odd-indexed coefficients with the monomial of degree two, and then multiplying the result by the indeterminate.*)\nLemma sum_odd_poly p :\n \\sum_(i < size p | odd i) p`_i *: 'X^i = (odd_poly p \\Po 'X^2) * 'X.\n\n(*This lemma demonstrates that any polynomial can be perfectly reconstructed by adding two components: its even-degree terms, formed by composing the `even_poly` result with the second-degree monomial, and its odd-degree terms, formed by a similar composition with `odd_poly` followed by multiplication with the indeterminate.*)\nLemma poly_even_odd p : even_poly p \\Po 'X^2 + (odd_poly p \\Po 'X^2) * 'X = p.\n\n(*This definition introduces a function `take_poly` that truncates a given polynomial, creating a new polynomial containing only the terms of degree less than a specified natural number.*)\nDefinition take_poly m p := \\poly_(i < m) p`_i.\n\n(*This lemma establishes that the size of a polynomial truncated by `take_poly` to terms of degree less than a natural number `m` will be at most `m`.*)\nLemma size_take_poly m p : size (take_poly m p) <= m.\n\n(*This lemma specifies that the coefficient of a term of degree `i` in a polynomial truncated by `take_poly` to degree less than `m` is equal to the original polynomial's coefficient if `i` is less than `m`, and zero otherwise.*)\nLemma coef_take_poly m p i : (take_poly m p)`_i = if i < m then p`_i else 0.\n\n(*This lemma states that if the size of a polynomial is less than or equal to a natural number `m`, then applying the `take_poly` function with limit `m` to that polynomial returns the original polynomial unchanged.*)\nLemma take_poly_id m p : size p <= m -> take_poly m p = p.\n\n(*This lemma states that the `take_poly` function distributes over polynomial addition, meaning that truncating the sum of two polynomials is equivalent to summing their truncated versions.*)\nLemma take_polyD m p q : take_poly m (p + q) = take_poly m p + take_poly m q.\n\n(*This lemma states that the `take_poly` function commutes with scalar multiplication, meaning that truncating a scaled polynomial is equivalent to scaling the truncated polynomial.*)\nLemma take_polyZ k m p : take_poly m (k *: p) = k *: take_poly m p.\n\n(*This fact asserts that for any given natural number, the `take_poly` function is a linear transformation.*)\nFact take_poly_is_linear m : linear (take_poly m).\n\nHB.instance Definition _ m :=\n GRing.isSemilinear.Build R {poly R} {poly R} _ (take_poly m)\n (GRing.semilinear_linear (take_poly_is_linear m)).\n\n(*This lemma shows that the `take_poly` function commutes with indexed sums of polynomials, allowing the truncation to be applied to each polynomial in the sum individually before summing the results.*)\nLemma take_poly_sum m I r P (p : I -> {poly R}) :\n take_poly m (\\sum_(i <- r | P i) p i) = \\sum_(i <- r| P i) take_poly m (p i).\n\n(*This lemma states that applying the `take_poly` function with a limit of zero to any polynomial results in the zero polynomial.*)\nLemma take_poly0l p : take_poly 0 p = 0.\n\n(*This lemma states that applying the `take_poly` function to the zero polynomial results in the zero polynomial, regardless of the truncation limit.*)\nLemma take_poly0r m : take_poly m 0 = 0.\n\n(*This lemma describes how the `take_poly` truncation interacts with multiplication by a monomial. It states that truncating a polynomial that has been multiplied by the `n`-th power of the indeterminate to degree less than `m` is equivalent to first truncating the original polynomial to degree less than `m-n` and then multiplying the result by the `n`-th power of the indeterminate.*)\nLemma take_polyMXn m n p :\n take_poly m (p * 'X^n) = take_poly (m - n) p * 'X^n.\n\n(*This lemma states that if a polynomial is multiplied by the `n`-th power of the indeterminate, all its terms will have a degree of at least `n`, and therefore truncating the result to only include terms of degree less than `n` yields the zero polynomial.*)\nLemma take_polyMXn_0 n p : take_poly n (p * 'X^n) = 0.\n\n(*This lemma states that if a polynomial `p` has a size less than or equal to a natural number `n`, then taking the terms of degree less than `n` from the sum of `p` and another polynomial `q` multiplied by the `n`-th power of the indeterminate results in the original polynomial `p`.*)\nLemma take_polyDMXn n p q : size p <= n -> take_poly n (p + q * 'X^n) = p.\n\n(*This definition specifies a function that truncates a polynomial by removing its first m lowest-degree terms. The resulting polynomial is formed by the coefficients of the original polynomial starting from the m-th degree, shifted down to start from degree zero.*)\nDefinition drop_poly m p := \\poly_(i < size p - m) p`_(i + m).\n\n(*This lemma states that the coefficient of the i-th degree term of a polynomial resulting from dropping the first m terms is equal to the coefficient of the term with degree equal to i plus m in the original polynomial.*)\nLemma coef_drop_poly m p i : (drop_poly m p)`_i = p`_(i + m).\n\n(*This lemma states that if the number of terms to drop from a polynomial is greater than or equal to its size, the result is the zero polynomial.*)\nLemma drop_poly_eq0 m p : size p <= m -> drop_poly m p = 0.\n\n(*This lemma states that the size of a polynomial after dropping its first n terms is equal to the original polynomial's size minus n.*)\nLemma size_drop_poly n p : size (drop_poly n p) = (size p - n)%N.\n\n(*This lemma states that the sum of the terms of a polynomial from degree n up to its highest degree is equal to the polynomial obtained by dropping the first n terms, multiplied by the monomial 'X' raised to the power of n.*)\nLemma sum_drop_poly n p :\n \\sum_(n <= i < size p) p`_i *: 'X^i = drop_poly n p * 'X^n.\n\n(*This lemma demonstrates that the operation of dropping the first m terms of a sum of two polynomials is distributive, yielding the same result as adding the two polynomials after each has had its first m terms dropped.*)\nLemma drop_polyD m p q : drop_poly m (p + q) = drop_poly m p + drop_poly m q.\n\n(*This lemma shows that dropping the first m terms of a polynomial that has been multiplied by a scalar is equivalent to first dropping the terms and then performing the scalar multiplication.*)\nLemma drop_polyZ k m p : drop_poly m (k *: p) = k *: drop_poly m p.\n\n(*This fact asserts that for any given natural number m, the function that drops the first m terms of a polynomial is a linear map.*)\nFact drop_poly_is_linear m : linear (drop_poly m).\n\n(*This lemma states that dropping the first m terms of an indexed sum of polynomials is equivalent to summing the results of dropping the first m terms of each individual polynomial in the sum.*)\nLemma drop_poly_sum m I r P (p : I -> {poly R}) :\n drop_poly m (\\sum_(i <- r | P i) p i) = \\sum_(i <- r | P i) drop_poly m (p i).\n\n(*This lemma states that dropping the first zero terms from a polynomial leaves the polynomial unchanged.*)\nLemma drop_poly0l p : drop_poly 0 p = p.\n\n(*This lemma states that dropping any number of terms from the zero polynomial results in the zero polynomial.*)\nLemma drop_poly0r m : drop_poly m 0 = 0. \n\n(*This lemma describes how dropping terms interacts with monomial multiplication. Specifically, dropping the first m terms from a polynomial that has been multiplied by 'X' to the power of n is equivalent to dropping m minus n terms from the original polynomial and then multiplying the result by 'X' raised to the power of n minus m.*)\nLemma drop_polyMXn m n p :\n drop_poly m (p * 'X^n) = drop_poly (m - n) p * 'X^(n - m).\n\n(*This lemma states that if a polynomial is first multiplied by 'X' to the power of n, and then its first n terms are dropped, the original polynomial is recovered.*)\nLemma drop_polyMXn_id n p : drop_poly n (p * 'X^ n) = p.\n\n(*This lemma states that if the size of a polynomial p is less than or equal to a natural number n, then dropping the first n terms of the sum of p and another polynomial q multiplied by 'X' to the power of n results in the polynomial q.*)\nLemma drop_polyDMXn n p q : size p <= n -> drop_poly n (p + q * 'X^n) = q.\n\n(*This lemma states that any polynomial can be perfectly reconstructed by summing two parts: the polynomial formed by its first n terms, and the polynomial formed by its remaining terms, after the latter has been multiplied by 'X' to the power of n.*)\nLemma poly_take_drop n p : take_poly n p + drop_poly n p * 'X^n = p.\n\n(*This lemma provides a criterion for polynomial equality. It states that two polynomials are equal if the polynomials formed by their first n terms are equal, and the polynomials formed by dropping their first n terms are also equal.*)\nLemma eqp_take_drop n p q :\n take_poly n p = take_poly n q -> drop_poly n p = drop_poly n q -> p = q.\n\nEnd Surgery.\n\n(*This definition provides a curated collection of fundamental lemmas and properties related to computing the coefficients of polynomials under various operations, such as addition, multiplication, scalar multiplication, composition, and derivation.*)\nDefinition coefE :=\n (coef0, coef1, coefC, coefX, coefXn, coef_sumMXn,\n coefZ, coefMC, coefCM, coefXnM, coefMXn, coefXM, coefMX, coefMNn, coefMn,\n coefN, coefB, coefD, coef_even_poly, coef_odd_poly,\n coef_take_poly, coef_drop_poly, coef_cons, coef_Poly, coef_poly,\n coef_deriv, coef_nderivn, coef_derivn, coef_map, coef_sum,\n coef_comp_poly_Xn, coef_comp_poly).\n\nSection PolynomialComNzRing.\n\nVariable R : comNzRingType.\nImplicit Types p q : {poly R}.\n\n(*This fact asserts that polynomial multiplication is commutative for polynomials over a commutative ring, meaning the order of the two polynomials in a product does not affect the result.*)\nFact poly_mul_comm p q : p * q = q * p.\n\nHB.instance Definition _ := GRing.PzRing_hasCommutativeMul.Build (polynomial R)\n poly_mul_comm.\nHB.instance Definition _ := GRing.Lalgebra_isComAlgebra.Build R (polynomial R).\n\n(*This lemma provides a formula, analogous to Vieta's formulas, for the n-th coefficient of a polynomial constructed by multiplying linear factors of the form 'X' minus a constant. The coefficient is expressed as a signed sum of products of the constants, where each product is taken over a subset of the constants of a specific size.*)\nLemma coef_prod_XsubC (ps : seq R) (n : nat) :\n (n <= size ps)%N ->\n (\\prod_(p <- ps) ('X - p%:P))`_n =\n (-1) ^+ (size ps - n)%N *\n \\sum_(I in {set 'I_(size ps)} | #|I| == (size ps - n)%N)\n \\prod_(i in I) ps`_i.\n\n(*This lemma states that for a non-empty product of linear factors of the form 'X' minus a constant, the coefficient of the term with a degree one less than the total number of factors is equal to the negative of the sum of all the constants.*)\nLemma coefPn_prod_XsubC (ps : seq R) : size ps != 0 ->\n (\\prod_(p <- ps) ('X - p%:P))`_((size ps).-1) =\n - \\sum_(p <- ps) p.\n\n(*This lemma states that the constant term of a polynomial formed by the product of linear factors of the form 'X' minus a constant is equal to the product of all the constants, multiplied by negative one raised to the power of the number of factors.*)\nLemma coef0_prod_XsubC (ps : seq R) :\n (\\prod_(p <- ps) ('X - p%:P))`_0 =\n (-1) ^+ (size ps) * \\prod_(p <- ps) p.\n\n(*This lemma states that evaluating the product of two polynomials at a given point yields the same result as multiplying the values obtained by evaluating each polynomial individually at that point.*)\nLemma hornerM p q x : (p * q).[x] = p.[x] * q.[x].\n\n(*This lemma states that evaluating a polynomial raised to a natural number power at a given point is equivalent to raising the value of the polynomial at that point to the same power.*)\nLemma horner_exp p x n : (p ^+ n).[x] = p.[x] ^+ n.\n\n(*This lemma states that evaluating an indexed product of polynomials at a given point is equivalent to taking the product of the values obtained by evaluating each individual polynomial in the product at that point.*)\nLemma horner_prod I r (P : pred I) (F : I -> {poly R}) x :\n (\\prod_(i <- r | P i) F i).[x] = \\prod_(i <- r | P i) (F i).[x].\n\n(*This definition provides a curated collection of fundamental lemmas and properties related to the evaluation of polynomials using Horner's method, covering operations like addition, multiplication, exponentiation, and evaluation of constants and variables.*)\nDefinition hornerE :=\n (hornerD, hornerN, hornerX, hornerC, horner_exp,\n simp, hornerCM, hornerZ, hornerM, horner_cons).\n\n(*This definition specifies a function that, for a given value from a ring, produces a new function that evaluates any polynomial at that specific value using Horner's method.*)\nDefinition horner_eval (x : R) := horner^~ x.\n(*This lemma states that applying the evaluation function generated for a specific value to a polynomial is equivalent to the standard notation for evaluating that polynomial at the same value.*)\nLemma horner_evalE x p : horner_eval x p = p.[x]. \n\n(*This fact asserts that for any given evaluation point, the function that evaluates polynomials at that point is a linear map.*)\nFact horner_eval_is_linear x : linear_for *%R (horner_eval x).\n\n(*This fact asserts that for any given evaluation point, the function that evaluates polynomials at that point is a monoid morphism, meaning it preserves the multiplicative identity and the multiplication operation.*)\nFact horner_eval_is_monoid_morphism x : monoid_morphism (horner_eval x).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `horner_eval_is_monoid_morphism` instead\")]\n(*This deprecated definition captures the property that polynomial evaluation at a fixed point is a multiplicative function; this functionality is more completely described by the newer 'horner_eval_is_monoid_morphism' fact.*)\nDefinition horner_eval_is_multiplicative x :=\n (fun g => (g.2, g.1)) (horner_eval_is_monoid_morphism x).\nHB.instance Definition _ x :=\n GRing.isSemilinear.Build R {poly R} R _ (horner_eval x)\n (GRing.semilinear_linear (horner_eval_is_linear x)).\n\nHB.instance Definition _ x :=\n GRing.isMonoidMorphism.Build {poly R} R (horner_eval x)\n (horner_eval_is_monoid_morphism x).\n\nSection HornerAlg.\n\nVariable A : algType R. \n\nSection Defs.\n\nVariable a : A.\n\n(*This lemma states that for a given element in an algebra, multiplication with that element commutes with the canonical embedding of elements from the base ring into the algebra.*)\nLemma in_alg_comm : commr_rmorph (in_alg A) a.\n\n(*This definition specifies the Horner evaluation morphism, which maps a polynomial over a base ring to an element in an algebra by substituting a designated algebra element for the polynomial's indeterminate.*)\nDefinition horner_alg := horner_morph in_alg_comm.\n\n(*This lemma states that the Horner evaluation of a constant polynomial yields the corresponding constant element embedded in the target algebra.*)\nLemma horner_algC c : horner_alg c%:P = c%:A.\n\n(*This lemma states that the Horner evaluation of the indeterminate polynomial X yields the specific algebra element at which the evaluation is defined.*)\nLemma horner_algX : horner_alg 'X = a.\n\n(*This lemma states the universal property of polynomial algebras: any algebra morphism from a polynomial ring to another algebra is uniquely determined by the image of the indeterminate X. Specifically, the morphism is equivalent to the Horner evaluation at the image of X.*)\nLemma poly_alg_initial : pf =1 horner_alg (pf 'X).\n\nEnd HornerAlg.\n\n(*This fact asserts that the operation of composing polynomials with a fixed polynomial is a monoid morphism with respect to polynomial multiplication.*)\nFact comp_poly_is_monoid_morphism q : monoid_morphism (comp_poly q).\n\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `comp_poly_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, provides a proof that polynomial composition with a fixed polynomial is a multiplicative function.*)\nDefinition comp_poly_multiplicative q :=\n (fun g => (g.2, g.1)) (comp_poly_is_monoid_morphism q).\n(*This lemma states that polynomial composition distributes over polynomial multiplication; that is, composing a product of two polynomials with a third is equivalent to the product of their individual compositions with the third polynomial.*)\nLemma comp_polyM p q r : (p * q) \\Po r = (p \\Po r) * (q \\Po r).\n\n(*This lemma states that the operation of polynomial composition is associative.*)\nLemma comp_polyA p q r : p \\Po (q \\Po r) = (p \\Po q) \\Po r.\n\n(*This lemma states that evaluating a composite polynomial at a given value is equivalent to first evaluating the inner polynomial at that value and then evaluating the outer polynomial at the result.*)\nLemma horner_comp p q x : (p \\Po q).[x] = p.[q.[x]].\n\n(*This lemma states that a value is a root of a composite polynomial if and only if the evaluation of the inner polynomial at that value is a root of the outer polynomial.*)\nLemma root_comp p q x : root (p \\Po q) x = root p (q.[x]).\n\n(*This lemma states the chain rule for polynomial differentiation: the derivative of a composite polynomial is the product of the derivative of the outer polynomial composed with the inner polynomial and the derivative of the inner polynomial.*)\nLemma deriv_comp p q : (p \\Po q) ^`() = (p ^`() \\Po q) * q^`().\n\n(*This lemma states the power rule for polynomial differentiation: the derivative of a polynomial raised to a natural number power is the product of that power, the polynomial raised to the power minus one, and the derivative of the original polynomial.*)\nLemma deriv_exp p n : (p ^+ n)^`() = p^`() * p ^+ n.-1 *+ n.\n\n(*This definition bundles two derivative rules, likely the linearity of the derivative and the power rule, into a single pair for tactical use.*)\nDefinition derivCE := (derivE, deriv_exp).\n\nEnd PolynomialComNzRing.\n\nSection PolynomialIdomain.\n\nVariable R : idomainType.\n\nImplicit Types (a b x y : R) (p q r m : {poly R}).\n\n(*This lemma states that for two non-zero polynomials over an integral domain, the size of their product is one less than the sum of their individual sizes.*)\nLemma size_mul p q : p != 0 -> q != 0 -> size (p * q) = (size p + size q).-1.\n\n(*This fact asserts that the product of two polynomials is the zero polynomial if and only if at least one of the polynomials is itself the zero polynomial.*)\nFact poly_idomainAxiom p q : p * q = 0 -> (p == 0) || (q == 0).\n\n(*This definition specifies the predicate that identifies a polynomial as a unit, which holds if the polynomial is a constant whose value is a unit in the underlying coefficient ring.*)\nDefinition poly_unit : pred {poly R} :=\n fun p => (size p == 1) && (p`_0 \\in GRing.unit).\n\n(*This definition provides the multiplicative inverse of a polynomial. If the polynomial is a unit, its inverse is the constant polynomial corresponding to the inverse of its constant term; otherwise, it returns the polynomial itself.*)\nDefinition poly_inv p := if p \\in poly_unit then (p`_0)^-1%:P else p.\n\n(*This fact asserts that for any unit polynomial, its product with the element provided by the polynomial inverse function equals the constant polynomial one.*)\nFact poly_mulVp : {in poly_unit, left_inverse 1 poly_inv *%R}.\n\n(*This fact asserts that if a polynomial has a multiplicative inverse, then it must satisfy the predicate for being a unit polynomial.*)\nFact poly_intro_unit p q : q * p = 1 -> p \\in poly_unit.\n\n(*This fact asserts that the polynomial inverse function acts as the identity function for any polynomial that is not a unit.*)\nFact poly_inv_out : {in [predC poly_unit], poly_inv =1 id}.\n\nHB.instance Definition _ := GRing.ComNzRing_hasMulInverse.Build (polynomial R)\n poly_mulVp poly_intro_unit poly_inv_out.\n\n(*This lemma provides an equivalence, stating that a polynomial is a unit if and only if it is a constant polynomial whose constant term is a unit in the coefficient ring.*)\nLemma poly_unitE p :\n (p \\in GRing.unit) = (size p == 1) && (p`_0 \\in GRing.unit).\n\n(*This lemma provides an explicit formula for the multiplicative inverse of a polynomial. If the polynomial is a unit, its inverse is the constant polynomial formed from the inverse of its constant term; otherwise, the inverse is defined as the polynomial itself.*)\nLemma poly_invE p : p ^-1 = if p \\in GRing.unit then (p`_0)^-1%:P else p.\n\n(*This lemma states that the multiplicative inverse of a constant polynomial is the constant polynomial whose coefficient is the inverse of the original constant.*)\nLemma polyCV c : c%:P^-1 = (c^-1)%:P.\n\n(*This lemma states that a value is a root of the product of two polynomials if and only if it is a root of at least one of the individual polynomials.*)\nLemma rootM p q x : root (p * q) x = root p x || root q x.\n\n(*This lemma states that multiplying a polynomial by a non-zero scalar from the coefficient ring does not change the set of its roots.*)\nLemma rootZ x a p : a != 0 -> root (a *: p) x = root p x.\n\n(*This lemma states that for any non-zero natural number exponent, a polynomial raised to that power has the same roots as the original polynomial.*)\nLemma root_exp p n a: comm_poly p a -> (0 < n)%N -> root (p ^+ n) a = root p a.\n\n(*This lemma states that multiplying a polynomial by a non-zero scalar from the coefficient ring does not change the size of the polynomial.*)\nLemma size_scale a p : a != 0 -> size (a *: p) = size p.\n\n(*This lemma states that multiplying a polynomial by a non-zero constant polynomial does not change its size.*)\nLemma size_Cmul a p : a != 0 -> size (a%:P * p) = size p.\n\n(*This lemma states that the leading coefficient of the product of two polynomials is the product of their individual leading coefficients.*)\nLemma lead_coefM p q : lead_coef (p * q) = lead_coef p * lead_coef q.\n\n(*This lemma states that the leading coefficient of a product of polynomials over a filtered range is equal to the product of the leading coefficients of each polynomial in that range.*)\nLemma lead_coef_prod I rI (P : {pred I}) (p : I -> {poly R}) :\n lead_coef (\\prod_(i <- rI | P i) p i) = \\prod_(i <- rI | P i) lead_coef (p i).\n\n(*This lemma states that the leading coefficient of a polynomial scaled by a scalar element is equal to that scalar multiplied by the original leading coefficient of the polynomial.*)\nLemma lead_coefZ a p : lead_coef (a *: p) = a * lead_coef p.\n\n(*This lemma states that a polynomial scaled by a scalar is the zero polynomial if and only if the scalar is zero or the polynomial itself is the zero polynomial.*)\nLemma scale_poly_eq0 a p : (a *: p == 0) = (a == 0) || (p == 0).\n\n(*This lemma states that for a product of non-zero polynomials over a finite set, the size of the resulting polynomial is one plus the sum of the sizes of the individual polynomials, minus the number of polynomials in the product.*)\nLemma size_prod (I : finType) (P : pred I) (F : I -> {poly R}) :\n (forall i, P i -> F i != 0) ->\n size (\\prod_(i | P i) F i) = ((\\sum_(i | P i) size (F i)).+1 - #|P|)%N.\n\n(*This lemma states that for a product of non-zero polynomials indexed by a sequence, the size of the resulting polynomial is one plus the sum of the sizes of the individual polynomials, minus the length of the sequence.*)\nLemma size_prod_seq (I : eqType) (s : seq I) (F : I -> {poly R}) :\n (forall i, i \\in s -> F i != 0) ->\n size (\\prod_(i <- s) F i) = ((\\sum_(i <- s) size (F i)).+1 - size s)%N.\n\n(*This lemma states that the product of two polynomials has a size of one if and only if both individual polynomials have a size of one.*)\nLemma size_mul_eq1 p q : (size (p * q) == 1) = ((size p == 1) && (size q == 1)).\n\n(*This lemma establishes that the product of a selection of polynomials indexed by a sequence has a size of one if and only if every selected polynomial has a size of one.*)\nLemma size_prod_seq_eq1 (I : eqType) (s : seq I) (P : pred I) (F : I -> {poly R}) :\n reflect (forall i, P i && (i \\in s) -> size (F i) = 1)\n (size (\\prod_(i <- s | P i) F i) == 1%N).\n\n(*This lemma establishes that the product of a selection of polynomials over a finite type has a size of one if and only if every selected polynomial has a size of one.*)\nLemma size_prod_eq1 (I : finType) (P : pred I) (F : I -> {poly R}) :\n reflect (forall i, P i -> size (F i) = 1)\n (size (\\prod_(i | P i) F i) == 1).\n\n(*This lemma states that the degree of a polynomial raised to a natural number power is equal to the product of the original polynomial's degree and the exponent.*)\nLemma size_exp p n : (size (p ^+ n)).-1 = ((size p).-1 * n)%N.\n\n(*This lemma states that the leading coefficient of a polynomial raised to a power is equal to the leading coefficient of the original polynomial raised to that same power.*)\nLemma lead_coef_exp p n : lead_coef (p ^+ n) = lead_coef p ^+ n.\n\n(*This lemma states that a value is a root of a polynomial formed by the product of linear factors of the form (variable minus constant) if and only if that value is one of the constants from the factors.*)\nLemma root_prod_XsubC rs x :\n root (\\prod_(a <- rs) ('X - a%:P)) x = (x \\in rs).\n\n(*This lemma states that a value is a root of a polynomial of the form (variable minus constant) raised to a positive power if and only if that value is equal to the constant.*)\nLemma root_exp_XsubC n a x : root (('X - a%:P) ^+ n.+1) x = (x == a).\n\n(*This lemma states that the degree of the composition of two polynomials is equal to the product of their individual degrees.*)\nLemma size_comp_poly p q :\n (size (p \\Po q)).-1 = ((size p).-1 * (size q).-1)%N.\n\n(*This lemma provides a formula for the leading coefficient of the composition of two polynomials, provided the inner polynomial is not constant. It states that the resulting leading coefficient is the product of the outer polynomial's leading coefficient and the inner polynomial's leading coefficient raised to the power of the outer polynomial's degree.*)\nLemma lead_coef_comp p q : size q > 1 ->\n lead_coef (p \\Po q) = (lead_coef p) * lead_coef q ^+ (size p).-1.\n\n(*This lemma states that if the inner polynomial in a composition is not a constant, the composed polynomial is the zero polynomial if and only if the outer polynomial is the zero polynomial.*)\nLemma comp_poly_eq0 p q : size q > 1 -> (p \\Po q == 0) = (p == 0).\n\n(*This lemma states that if a polynomial is composed with a linear polynomial, which has a size of two, the size of the resulting polynomial is the same as the size of the original outer polynomial.*)\nLemma size_comp_poly2 p q : size q = 2 -> size (p \\Po q) = size p.\n\n(*This lemma states that when composing a polynomial with a linear polynomial, which has a size of two, the result is the zero polynomial if and only if the original outer polynomial was the zero polynomial.*)\nLemma comp_poly2_eq0 p q : size q = 2 -> (p \\Po q == 0) = (p == 0).\n\n(*This theorem states that for any non-zero polynomial, the number of its distinct roots is strictly less than the size of the polynomial, which is its degree plus one.*)\nTheorem max_poly_roots p rs :\n p != 0 -> all (root p) rs -> uniq rs -> size rs < size p.\n\n(*This lemma states that if a polynomial has a number of distinct roots that is greater than or equal to its size, which is its degree plus one, then the polynomial must be the zero polynomial.*)\nLemma roots_geq_poly_eq0 p (rs : seq R) : all (root p) rs -> uniq rs ->\n (size rs >= size p)%N -> p = 0.\n\nEnd PolynomialIdomain.\n\nHB.instance Definition _ (R : countNzRingType) :=\n [Countable of polynomial R by <:].\nHB.instance Definition _ (R : countComNzRingType) :=\n [Countable of polynomial R by <:].\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (R : countUnitRingType) :=\n [Countable of polynomial R by <:].\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (R : countComUnitRingType) :=\n [Countable of polynomial R by <:].\n(*This notation provides a shorthand for creating a new polynomial by applying a function to each coefficient of an input polynomial.*)\nLocal Notation \"p ^f\" := (map_poly f p) : ring_scope.\n\n(*This lemma states that applying an injective ring homomorphism, such as one from a field, to the coefficients of a polynomial does not change the polynomial's size.*)\nLemma size_map_poly p : size p^f = size p.\n\n(*This lemma states that the leading coefficient of a polynomial whose coefficients have been transformed by a ring homomorphism is the image of the original leading coefficient under that same homomorphism.*)\nLemma lead_coef_map p : lead_coef p^f = f (lead_coef p).\n\n(*This lemma states that applying an injective ring homomorphism to the coefficients of a polynomial results in the zero polynomial if and only if the original polynomial was the zero polynomial.*)\nLemma map_poly_eq0 p : (p^f == 0) = (p == 0).\n\n(*This lemma states that the function that transforms a polynomial by applying an injective ring homomorphism, such as one from a field, to its coefficients is itself an injective function.*)\nLemma map_poly_inj : injective (map_poly f).\n\n(*This lemma states that a polynomial transformed by a ring homomorphism is monic if and only if the original polynomial is monic.*)\nLemma map_monic p : (p^f \\is monic) = (p \\is monic).\n\n(*This lemma states that a polynomial transformed by a ring homomorphism from a field commutes with any value that is the image of an element from that field under the same homomorphism.*)\nLemma map_poly_com p x : comm_poly p^f (f x).\n\n(*This lemma states that a value transformed by an injective ring homomorphism from a field is a root of a transformed polynomial if and only if the original value is a root of the original polynomial.*)\nLemma fmorph_root p x : root p^f (f x) = root p x.\n\n(*This lemma states that a value transformed by an injective ring homomorphism from a field is an n-th root of unity if and only if the original value is an n-th root of unity.*)\nLemma fmorph_unity_root n z : n.-unity_root (f z) = n.-unity_root z.\n\n(*This lemma states that a value transformed by an injective ring homomorphism from a field is a primitive n-th root of unity if and only if the original value is a primitive n-th root of unity.*)\nLemma fmorph_primitive_root n z :\n n.-primitive_root (f z) = n.-primitive_root z.\n\nEnd MapFieldPoly.\n\nArguments map_poly_inj {F R} f [p1 p2] : rename.\n\nSection MaxRoots.\n\nVariable R : unitRingType.\nImplicit Types (x y : R) (rs : seq R) (p : {poly R}).\n\n(*This definition specifies a property for two ring elements, which holds if they commute with each other and if their difference is a unit, meaning it has a multiplicative inverse in the ring.*)\nDefinition diff_roots (x y : R) := (x * y == y * x) && (y - x \\in GRing.unit).\n\n(*This fixpoint definition defines a function that checks whether a given finite sequence of ring elements contains no duplicate values, returning true if all elements are distinct and false otherwise.*)\nFixpoint uniq_roots rs :=\n if rs is x :: rs' then all (diff_roots x) rs' && uniq_roots rs' else true.\n\n(*This lemma states that if a given finite sequence consists of distinct roots of a polynomial over a ring, then that polynomial can be factored as the product of another polynomial and the product of linear factors corresponding to each root in the sequence.*)\nLemma uniq_roots_prod_XsubC p rs :\n all (root p) rs -> uniq_roots rs ->\n exists q, p = q * \\prod_(z <- rs) ('X - z%:P).\n\n(*This theorem asserts that for any non-zero polynomial over an integral domain, the number of its distinct roots is strictly less than its degree plus one.*)\nTheorem max_ring_poly_roots p rs :\n p != 0 -> all (root p) rs -> uniq_roots rs -> size rs < size p.\n\n(*This lemma states that if a polynomial over an integral domain has a number of distinct roots equal to its degree, then the polynomial is equal to its leading coefficient multiplied by the product of the linear factors corresponding to those roots.*)\nLemma all_roots_prod_XsubC p rs :\n size p = (size rs).+1 -> all (root p) rs -> uniq_roots rs ->\n p = lead_coef p *: \\prod_(z <- rs) ('X - z%:P).\n\nEnd MaxRoots.\n\nSection FieldRoots.\n\nVariable F : fieldType.\nImplicit Types (p : {poly F}) (rs : seq F).\n\n(*This lemma states that any polynomial of degree one over a field is guaranteed to have a root.*)\nLemma poly2_root p : size p = 2 -> {r | root p r}.\n\n(*This lemma states that checking if a sequence of field elements corresponds to unique roots is equivalent to checking if the sequence itself contains no duplicate elements.*)\nLemma uniq_rootsE rs : uniq_roots rs = uniq rs.\n\n(*This lemma states that for a linear polynomial of the form 'a' times 'X' minus 'b' over a field, where 'a' is non-zero, a given value is a root if and only if it is equal to 'b' divided by 'a'.*)\nLemma root_ZXsubC (a b r : F) : a != 0 ->\n root (a *: 'X - b%:P) r = (r == b / a).\n\nSection UnityRoots.\n\nVariable n : nat.\n\n(*This lemma asserts that for any positive natural number 'n', the number of distinct 'n'-th roots of unity in a field is at most 'n'.*)\nLemma max_unity_roots rs :\n n > 0 -> all n.-unity_root rs -> uniq rs -> size rs <= n.\n\n(*This lemma states that if a sequence contains exactly 'n' distinct 'n'-th roots of unity for a positive natural number 'n', then the set of all 'n'-th roots of unity is equivalent to the set of elements in that sequence.*)\nLemma mem_unity_roots rs :\n n > 0 -> all n.-unity_root rs -> uniq rs -> size rs = n ->\n n.-unity_root =i rs.\n\nVariable z : F.\nHypothesis prim_z : n.-primitive_root z.\n\n(*This definition creates a finite sequence containing the first 'n' powers of a given primitive 'n'-th root of unity, starting from the zeroth power up to the power 'n' minus one.*)\nLet zn := [seq z ^+ i | i <- index_iota 0 n].\n\n(*This lemma provides the factorization of the polynomial 'X' to the power of 'n' minus one, stating it is equal to the product of linear factors 'X' minus 'r', where 'r' ranges over all the 'n'-th roots of unity generated by a primitive root.*)\nLemma factor_Xn_sub_1 : \\prod_(0 <= i < n) ('X - (z ^+ i)%:P) = 'X^n - 1.\n\n(*This lemma states that any 'n'-th root of unity can be expressed as a power of a given 'n'-th primitive root of unity, where the exponent is a natural number less than 'n'.*)\nLemma prim_rootP x : x ^+ n = 1 -> {i : 'I_n | x = z ^+ i}.\n\nEnd UnityRoots.\n\nEnd FieldRoots.\n\nSection MapPolyRoots.\n\nVariables (F : fieldType) (R : unitRingType) (f : {rmorphism F -> R}).\n\n(*This lemma states that applying an injective ring morphism to two elements from a field results in two distinct elements if and only if the original two elements were distinct.*)\nLemma map_diff_roots x y : diff_roots (f x) (f y) = (x != y).\n\n(*This lemma states that applying an injective ring morphism to each element of a sequence preserves the property of uniqueness; the resulting sequence has distinct elements if and only if the original sequence had distinct elements.*)\nLemma map_uniq_roots s : uniq_roots (map f s) = uniq s.\n\nEnd MapPolyRoots.\n\nSection AutPolyRoot.\n\nVariable F : fieldType.\nImplicit Types u v : {rmorphism F -> F}.\n\n(*This lemma states that the image of an 'n'-th primitive root of unity under a field automorphism is another 'n'-th primitive root of unity, which can be expressed as the original root raised to a power 'k', where 'k' is a natural number coprime to 'n'.*)\nLemma aut_prim_rootP u z n :\n n.-primitive_root z -> {k | coprime k n & u z = z ^+ k}.\n\n(*This lemma states that for a positive natural number 'n', the image of an 'n'-th root of unity under a field automorphism can be expressed as the original root raised to some integer power.*)\nLemma aut_unity_rootP u z n : n > 0 -> z ^+ n = 1 -> {k | u z = z ^+ k}.\n\n(*This lemma states that for any positive natural number 'n', any two field automorphisms commute when applied to an 'n'-th root of unity.*)\nLemma aut_unity_rootC u v z n : n > 0 -> z ^+ n = 1 -> u (v z) = v (u z).\n\nEnd AutPolyRoot.\n\nModule UnityRootTheory.\n\n(*This notation defines a predicate that checks if a given element of a ring is an 'n'-th root of unity, meaning the element raised to the power of 'n' is equal to one.*)\nNotation \"n .-unity_root\" := (root_of_unity n) : unity_root_scope.\n(*This notation defines a predicate to check if a given ring element is a primitive 'n'-th root of unity, meaning it is an 'n'-th root of unity and 'n' is the smallest positive integer for which this is true.*)\nNotation \"n .-primitive_root\" := (primitive_root_of_unity n) : unity_root_scope.\nOpen Scope unity_root_scope.\n\n(*This definition provides an equivalence, stating that an element is an 'n'-th root of unity if and only if that element raised to the power 'n' is equal to one.*)\nDefinition unity_rootE := unity_rootE.\n(*This definition provides a boolean-valued property that evaluates to true if a given element is an 'n'-th root of unity, and false otherwise.*)\nDefinition unity_rootP := @unity_rootP.\nArguments unity_rootP {R n z}.\n\n(*This definition asserts the existence of a primitive order for any element of finite multiplicative order in a ring; specifically, it guarantees there is a smallest positive integer 'n' such that the element raised to the power 'n' equals one.*)\nDefinition prim_order_exists := prim_order_exists.\n(*This notation refers to a lemma stating that the primitive order of any element of finite multiplicative order is strictly positive.*)\nNotation prim_order_gt0 := prim_order_gt0.\n(*This notation refers to a lemma that provides a formula for calculating the primitive order of an element raised to an integer power, based on the primitive order of the original element and the greatest common divisor of the exponent and the original order.*)\nNotation prim_expr_order := prim_expr_order.\n(*This definition establishes that two powers of an element with a finite primitive order are equal if and only if their exponents are congruent modulo that primitive order.*)\nDefinition prim_expr_mod := prim_expr_mod.\n(*This definition asserts that if an element raised to an integer power 'k' equals one, then the primitive order of that element must divide 'k'.*)\nDefinition prim_order_dvd := prim_order_dvd.\n(*This definition provides a condition for the equality of two powers of a primitive 'n'-th root of unity, stating that they are equal if and only if their exponents are congruent modulo 'n'.*)\nDefinition eq_prim_root_expr := eq_prim_root_expr.\n\n(*This definition states that the image of an 'n'-th root of unity under any ring morphism is also an 'n'-th root of unity.*)\nDefinition rmorph_unity_root := rmorph_unity_root.\n(*This definition states that the image of an 'n'-th root of unity under any field morphism is also an 'n'-th root of unity.*)\nDefinition fmorph_unity_root := fmorph_unity_root.\n(*This definition states that an injective field morphism maps a primitive 'n'-th root of unity to another primitive 'n'-th root of unity.*)\nDefinition fmorph_primitive_root := fmorph_primitive_root.\n(*This definition specifies the maximum number of roots of unity for a given integer.*)\nDefinition max_unity_roots := max_unity_roots.\n(*This definition provides a boolean predicate that checks if a given element of a field is a root of unity.*)\nDefinition mem_unity_roots := mem_unity_roots.\n(*This definition provides a boolean predicate that determines if a given element of a field is a primitive root of unity.*)\nDefinition prim_rootP := prim_rootP.\n\nEnd UnityRootTheory.\n\nModule Export Pdeg2.\n\nModule Export Field.\n\nSection Pdeg2Field.\nVariable F : fieldType.\nHypothesis nz2 : 2 != 0 :> F.\n\nVariable p : {poly F}.\nHypothesis degp : size p = 3.\n\n(*This definition gives the name `a` to the coefficient of degree two of a given polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of degree one of a given polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the constant term, which is the coefficient of degree zero, of a given polynomial `p`.*)\nLet c := p`_0.\n\n(*This lemma establishes that a given polynomial of degree two is not the zero polynomial.*)\nLet pneq0 : p != 0. \n(*This lemma establishes that the leading coefficient of a given degree-two polynomial is non-zero.*)\nLet aneq0 : a != 0.\n\n(*This lemma establishes that twice the leading coefficient of a polynomial is non-zero, given the underlying field's characteristic is not two.*)\nLet a2neq0 : 2 * a != 0. \n(*This lemma establishes that the square of twice the leading coefficient of a polynomial is non-zero, given the underlying field's characteristic is not two.*)\nLet sqa2neq0 : (2 * a) ^+ 2 != 0. \n\n(*This lemma states that for any element of the field, four times its square is equal to the square of twice that element.*)\nLet aa4 : 4 * a * a = (2 * a)^+2.\n\n(*This lemma states that any element in a field with characteristic different from two can be expressed as the sum of its half with itself.*)\nLet splitr (x : F) : x = x / 2 + x / 2.\n\n(*This lemma formally states that the polynomial `p` is equal to its explicit representation constructed from its coefficients for degrees two, one, and zero.*)\nLet pE : p = a *: 'X^2 + b *: 'X + c%:P.\n\n(*This definition introduces `delta` as the discriminant of a degree-two polynomial, computed as the square of the degree-one coefficient minus four times the product of the degree-two and degree-zero coefficients.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This lemma states that a degree-two polynomial can be rewritten in its canonical form, expressed in terms of its leading coefficient, the indeterminate, and its discriminant.*)\nLemma deg2_poly_canonical :\n p = a *: (('X + (b / (2 * a))%:P)^+2 - (delta / (4 * a ^+ 2))%:P).\n\nVariable r : F.\nHypothesis r_sqrt_delta : r ^+ 2 = delta.\n\n(*This definition specifies the first root of a quadratic polynomial, computed as the sum of the opposite of the linear coefficient and the opposite of a square root of the discriminant, all divided by twice the leading coefficient.*)\nLet r1 := (- b - r) / (2 * a).\n(*This definition specifies the second root of a quadratic polynomial, computed as the sum of the opposite of the linear coefficient and a square root of the discriminant, all divided by twice the leading coefficient.*)\nLet r2 := (- b + r) / (2 * a).\n\n(*This lemma states that a degree-two polynomial is equal to the product of its leading coefficient and two linear factors, where each linear factor corresponds to the indeterminate minus a root.*)\nLemma deg2_poly_factor : p = a *: ('X - r1%:P) * ('X - r2%:P).\n\n(*This lemma states that a value denoted as `r1` is a root of a given degree-two polynomial `p`.*)\nLemma deg2_poly_root1 : root p r1.\n\n(*This lemma states that a value denoted as `r2` is a root of a given degree-two polynomial `p`.*)\nLemma deg2_poly_root2 : root p r2.\n\nEnd Pdeg2Field.\nEnd Field.\n\nModule FieldMonic.\n\nSection Pdeg2FieldMonic.\nVariable F : fieldType.\nHypothesis nz2 : 2 != 0 :> F.\n\nVariable p : {poly F}.\nHypothesis degp : size p = 3.\nHypothesis monicp : p \\is monic.\n\n(*This definition introduces `a` as the coefficient of the degree-two term of a given degree-two polynomial.*)\nLet a := p`_2.\n(*This definition introduces `b` as the coefficient of the degree-one term of a given degree-two polynomial.*)\nLet b := p`_1.\n(*This definition introduces `c` as the constant term, or degree-zero coefficient, of a given degree-two polynomial.*)\nLet c := p`_0.\n\n(*This lemma states that the coefficient of the highest-degree term of the quadratic polynomial is equal to one, ensuring the polynomial is monic.*)\nLet a1 : a = 1. \n\n(*A field element representing the discriminant of a monic quadratic polynomial, calculated as the square of the linear coefficient minus four times the constant term.*)\nLet delta := b ^+ 2 - 4 * c.\n\n(*This lemma states that a monic quadratic polynomial can be expressed in its canonical form, which is the square of a linear term involving half of the linear coefficient, adjusted by a quarter of the discriminant.*)\nLemma deg2_poly_canonical : p = (('X + (b / 2)%:P)^+2 - (delta / 4)%:P).\n\nVariable r : F.\nHypothesis r_sqrt_delta : r ^+ 2 = delta.\n\n(*A field element representing one of the roots of a monic quadratic polynomial, calculated using the quadratic formula as the negative of the linear coefficient minus a square root of the discriminant, all divided by two.*)\nLet r1 := (- b - r) / 2.\n(*A field element representing one of the roots of a monic quadratic polynomial, calculated using the quadratic formula as the negative of the linear coefficient plus a square root of the discriminant, all divided by two.*)\nLet r2 := (- b + r) / 2.\n\n(*This lemma states that a monic quadratic polynomial can be factored into the product of two linear polynomials, where each factor corresponds to the difference between the polynomial variable and one of the roots.*)\nLemma deg2_poly_factor : p = ('X - r1%:P) * ('X - r2%:P).\n\n(*This lemma asserts that the value computed for the first root of a quadratic polynomial is indeed a root of that polynomial.*)\nLemma deg2_poly_root1 : root p r1.\n\n(*This lemma asserts that the value computed for the second root of a quadratic polynomial is indeed a root of that polynomial.*)\nLemma deg2_poly_root2 : root p r2.\n\nEnd Pdeg2FieldMonic.\nEnd FieldMonic.\nEnd Pdeg2.\n\nSection DecField.\n\nVariable F : decFieldType.\n\n(*This lemma states that any polynomial over a field with decidable equality can be factored into a product of a sequence of linear terms corresponding to its roots, and a remaining polynomial that has no roots in the field.*)\nLemma dec_factor_theorem (p : {poly F}) :\n {s : seq F & {q : {poly F} | p = q * \\prod_(x <- s) ('X - x%:P)\n /\\ (q != 0 -> forall x, ~~ root q x)}}.\n\nEnd DecField.\n\nModule PreClosedField.\nSection UseAxiom.\n\nVariable F : fieldType.\nHypothesis closedF : GRing.closed_field_axiom F.\nImplicit Type p : {poly F}.\n\n(*This lemma states that a polynomial over an algebraically closed field has at least one root if and only if it is not a non-zero constant. A polynomial is identified as a non-zero constant if the length of its internal coefficient sequence is exactly one.*)\nLemma closed_rootP p : reflect (exists x, root p x) (size p != 1).\n\n(*This lemma establishes a logical equivalence between the existence of an element that is not a root of a polynomial and the condition that the polynomial is not the zero polynomial.*)\nLemma closed_nonrootP p : reflect (exists x, ~~ root p x) (p != 0).\n\nEnd UseAxiom.\nEnd PreClosedField.\n\nSection ClosedField.\n\nVariable F : closedFieldType.\nImplicit Type p : {poly F}.\n\n(*This definition specifies a term that represents the constructive witness to the closed field property, namely a function that computes a root for any given non-constant monic polynomial.*)\nLet closedF := @solve_monicpoly F.\n\n(*This lemma states that for a polynomial over an algebraically closed numeric field, the property that every element of the field is a root of the polynomial is equivalent to the polynomial being the zero polynomial.*)\nLemma closed_rootP p : reflect (exists x, root p x) (size p != 1).\n\n(*This lemma states that for a polynomial over an algebraically closed numeric field, there exists at least one element in the field that is not a root of the polynomial if and only if the polynomial is not the zero polynomial.*)\nLemma closed_nonrootP p : reflect (exists x, ~~ root p x) (p != 0).\n\n(*This definition constructs a proof structure that encapsulates the fundamental axiom of algebraically closed fields. The axiom asserts that any polynomial that is both non-zero and non-constant must have at least one root in the field.*)\nLemma closed_field_poly_normal p :\n {r : seq F | p = lead_coef p *: \\prod_(z <- r) ('X - z%:P)}.", - "algebra.polydiv": "From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype bigop ssralg poly.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GRing.Theory.\nLocal Open Scope ring_scope.\n\nReserved Notation \"p %= q\" (at level 70, no associativity).\n\n(*This notation provides a local alias for a tactic used to simplify monoid expressions.*)\nLocal Notation simp := Monoid.simpm.\n\nModule Pdiv.\n\nModule CommonRing.\n\nSection RingPseudoDivision.\n\nVariable R : nzRingType.\nImplicit Types d p q r : {poly R}.\n\n(*This definition describes a recursive helper function for polynomial pseudo-division. It iteratively computes the quotient and remainder, stopping when the remainder's size is less than the divisor's size. In each step, it updates the quotient and remainder by performing a division step scaled by the divisor's leading coefficient.*)\nDefinition redivp_rec (q : {poly R}) :=\n let sq := size q in\n let cq := lead_coef q in\n fix loop (k : nat) (qq r : {poly R})(n : nat) {struct n} :=\n if size r < sq then (k, qq, r) else\n let m := (lead_coef r) *: 'X^(size r - sq) in\n let qq1 := qq * cq%:P + m in\n let r1 := r * cq%:P - m * q in\n if n is n1.+1 then loop k.+1 qq1 r1 n1 else (k.+1, qq1, r1).\n\n(*This definition specifies the complete behavior of polynomial pseudo-division. Given a dividend and a divisor polynomial, it returns a zero quotient and the dividend as remainder if the divisor is zero, and otherwise initiates a recursive computation.*)\nDefinition redivp_expanded_def p q :=\n if q == 0 then (0, 0, p) else redivp_rec q 0 0 p (size p).\n(*This fact introduces an opaque key used to lock a definition of pseudo-division, ensuring that users reason about it through its specified properties rather than its direct implementation.*)\nFact redivp_key : unit. \n(*This definition computes the pseudo-division of a dividend polynomial by a divisor polynomial, producing a scaling factor, a pseudo-quotient, and a pseudo-remainder. The implementation is opaque, forcing reliance on its axiomatic properties.*)\nDefinition redivp : {poly R} -> {poly R} -> nat * {poly R} * {poly R} :=\n locked_with redivp_key redivp_expanded_def.\nCanonical redivp_unlockable := [unlockable fun redivp].\n\n(*This definition extracts the pseudo-quotient polynomial from the result of a pseudo-division operation.*)\nDefinition rdivp p q := ((redivp p q).1).2.\n(*This definition extracts the pseudo-remainder polynomial from the result of a pseudo-division operation.*)\nDefinition rmodp p q := (redivp p q).2.\n(*This definition extracts the natural number scaling factor from the result of a pseudo-division operation.*)\nDefinition rscalp p q := ((redivp p q).1).1.\n(*This definition expresses pseudo-divisibility. A first polynomial pseudo-divides a second polynomial if the pseudo-remainder of the second polynomial by the first is the zero polynomial.*)\nDefinition rdvdp p q := rmodp q p == 0.\n\n(*This lemma states that the result of the main pseudo-division operation on two polynomials is a triplet formed by a scaling factor, a pseudo-quotient, and a pseudo-remainder.*)\nLemma redivp_def p q : redivp p q = (rscalp p q, rdivp p q, rmodp p q).\n\n(*This lemma states that the pseudo-quotient of the zero polynomial by any polynomial is the zero polynomial.*)\nLemma rdiv0p p : rdivp 0 p = 0.\n\n(*This lemma states that the pseudo-quotient of any polynomial by the zero polynomial is the zero polynomial.*)\nLemma rdivp0 p : rdivp p 0 = 0. \n\n(*This lemma states that if a dividend polynomial has a size strictly smaller than the divisor polynomial, their pseudo-quotient is the zero polynomial.*)\nLemma rdivp_small p q : size p < size q -> rdivp p q = 0.\n\n(*This lemma states that the size of a pseudo-quotient polynomial is at most the size of the original dividend polynomial.*)\nLemma leq_rdivp p q : size (rdivp p q) <= size p.\n\n(*This lemma states that a pseudo-division of the zero polynomial by any polynomial yields a pseudo-remainder of zero.*)\nLemma rmod0p p : rmodp 0 p = 0.\n\n(*This lemma states that a pseudo-division of any polynomial by the zero polynomial yields the original polynomial as the pseudo-remainder.*)\nLemma rmodp0 p : rmodp p 0 = p. \n\n(*This lemma states that if a dividend polynomial has a size strictly smaller than a divisor polynomial, the scaling factor from their pseudo-division is zero.*)\nLemma rscalp_small p q : size p < size q -> rscalp p q = 0.\n\n(*This lemma asserts that the size of a pseudo-remainder is strictly smaller than the size of the divisor if and only if the divisor is a non-zero polynomial.*)\nLemma ltn_rmodp p q : (size (rmodp p q) < size q) = (q != 0).\n\n(*This lemma states that for a non-zero divisor polynomial, the size of the pseudo-remainder is strictly smaller than the size of the divisor.*)\nLemma ltn_rmodpN0 p q : q != 0 -> size (rmodp p q) < size q.\n\n(*This lemma states that the pseudo-remainder of any polynomial upon division by the constant polynomial one is the zero polynomial.*)\nLemma rmodp1 p : rmodp p 1 = 0.\n\n(*This lemma states that if a dividend polynomial has a size strictly smaller than a divisor polynomial, the pseudo-remainder of their division is the dividend polynomial itself.*)\nLemma rmodp_small p q : size p < size q -> rmodp p q = p.\n\n(*This lemma states that the size of a pseudo-remainder polynomial is at most the size of the original dividend polynomial.*)\nLemma leq_rmodp m d : size (rmodp m d) <= size m.\n\n(*This lemma states that the pseudo-remainder of any polynomial upon division by a non-zero constant polynomial is the zero polynomial.*)\nLemma rmodpC p c : c != 0 -> rmodp p c%:P = 0.\n\n(*This lemma states that any polynomial pseudo-divides the zero polynomial.*)\nLemma rdvdp0 d : rdvdp d 0. \n\n(*This lemma states that the zero polynomial pseudo-divides another polynomial if and only if that other polynomial is itself the zero polynomial.*)\nLemma rdvd0p n : rdvdp 0 n = (n == 0). \n\n(*This lemma provides a boolean reflection, establishing that a polynomial being equal to zero is logically equivalent to it being pseudo-divisible by the zero polynomial.*)\nLemma rdvd0pP n : reflect (n = 0) (rdvdp 0 n).\n\n(*This lemma states that if a non-zero polynomial is pseudo-divisible by another polynomial, then that divisor polynomial must also be non-zero.*)\nLemma rdvdpN0 p q : rdvdp p q -> q != 0 -> p != 0.\n\n(*This lemma states that a polynomial pseudo-divides the constant polynomial one if and only if that polynomial is a non-zero constant.*)\nLemma rdvdp1 d : rdvdp d 1 = (size d == 1).\n\n(*This lemma states that the constant polynomial one pseudo-divides any polynomial.*)\nLemma rdvd1p m : rdvdp 1 m. \n\n(*This lemma asserts that a non-zero polynomial is not pseudo-divisible by any polynomial of strictly larger size.*)\nLemma Nrdvdp_small (n d : {poly R}) :\n n != 0 -> size n < size d -> rdvdp d n = false.\n\n(*This lemma states that the pseudo-remainder of a first polynomial divided by a second polynomial is the zero polynomial if and only if the second polynomial pseudo-divides the first.*)\nLemma rmodp_eq0P p q : reflect (rmodp p q = 0) (rdvdp q p).\n\n(*This lemma states that if a second polynomial pseudo-divides a first polynomial, then the pseudo-remainder from dividing the first by the second is the zero polynomial.*)\nLemma rmodp_eq0 p q : rdvdp q p -> rmodp p q = 0. \n\n(*This lemma states that if a first polynomial pseudo-divides a second, non-zero polynomial, then the size of the first polynomial is less than or equal to the size of the second.*)\nLemma rdvdp_leq p q : rdvdp p q -> q != 0 -> size p <= size q.\n\n(*This definition provides a function to compute the pseudo-greatest common divisor of two polynomials using the Euclidean algorithm based on pseudo-remainders. The computation terminates based on the size of the input polynomials.*)\nDefinition rgcdp p q :=\n let: (p1, q1) := if size p < size q then (q, p) else (p, q) in\n if p1 == 0 then q1 else\n let fix loop (n : nat) (pp qq : {poly R}) {struct n} :=\n let rr := rmodp pp qq in\n if rr == 0 then qq else\n if n is n1.+1 then loop n1 qq rr else rr in\n loop (size p1) p1 q1.\n\n(*This lemma states that the zero polynomial is the left identity for the polynomial pseudo-greatest common divisor operation, meaning the pseudo-GCD of the zero polynomial and any other polynomial is that other polynomial.*)\nLemma rgcd0p : left_id 0 rgcdp.\n\n(*This lemma states that the zero polynomial is the right identity for the polynomial pseudo-greatest common divisor operation, meaning the pseudo-GCD of any polynomial and the zero polynomial is the original polynomial.*)\nLemma rgcdp0 : right_id 0 rgcdp.\n\n(*This lemma provides a recursive formula for computing the pseudo-greatest common divisor of two polynomials. It states that the pseudo-GCD of the two polynomials is equal to the pseudo-GCD of the smaller-sized polynomial and the pseudo-remainder of the larger-sized polynomial divided by the smaller-sized one.*)\nLemma rgcdpE p q :\n rgcdp p q = if size p < size q\n then rgcdp (rmodp q p) p else rgcdp (rmodp p q) q.\n\n(*This inductive type specifies the correctness of commutative pseudo-division for two polynomials. A result of such a division, consisting of a scaling exponent, a quotient, and a remainder, is considered correct if it satisfies two conditions: first, the dividend scaled by the leading coefficient of the divisor raised to the scaling exponent equals the quotient times the divisor plus the remainder; and second, the size of the remainder is strictly less than the size of the divisor, provided the divisor is not the zero polynomial.*)\nVariant comm_redivp_spec m d : nat * {poly R} * {poly R} -> Type :=\n ComEdivnSpec k (q r : {poly R}) of\n (GRing.comm d (lead_coef d)%:P -> m * (lead_coef d ^+ k)%:P = q * d + r) &\n (d != 0 -> size r < size d) : comm_redivp_spec m d (k, q, r).\n\n(*This lemma states that the result of the commutative pseudo-division function, when applied to two polynomials, satisfies the correctness specification for commutative pseudo-division.*)\nLemma comm_redivpP m d : comm_redivp_spec m d (redivp m d).\n\n(*This lemma states that the pseudo-remainder of a polynomial divided by itself is the zero polynomial, provided that the polynomial commutes with its own leading coefficient.*)\nLemma rmodpp p : GRing.comm p (lead_coef p)%:P -> rmodp p p = 0.\n\n(*This definition specifies that two polynomials are considered pseudo-coprime if the size of their pseudo-greatest common divisor is equal to one.*)\nDefinition rcoprimep (p q : {poly R}) := size (rgcdp p q) == 1.\n\n(*This definition is for a recursive helper function that, given two polynomials and a counter, repeatedly divides the second polynomial by its pseudo-greatest common divisor with the first until the result is pseudo-coprime to the first polynomial, or until the counter reaches zero.*)\nFixpoint rgdcop_rec q p n :=\n if n is m.+1 then\n if rcoprimep p q then p\n else rgdcop_rec q (rdivp p (rgcdp p q)) m\n else (q == 0)%:R.\n\n(*This definition computes a polynomial derived from a second input polynomial, such that the result is pseudo-coprime to a first input polynomial. The computation proceeds by recursively dividing the second polynomial by its pseudo-greatest common divisor with the first polynomial until no common factors remain.*)\nDefinition rgdcop q p := rgdcop_rec q p (size p).\n\n(*This lemma states that applying the pseudo-coprime generation function to a first polynomial and the zero polynomial results in a boolean value indicating whether the first polynomial is itself zero.*)\nLemma rgdcop0 q : rgdcop q 0 = (q == 0)%:R.\n\nEnd RingPseudoDivision.\n\nEnd CommonRing.\n\nModule RingComRreg.\n\nImport CommonRing.\n\nSection ComRegDivisor.\n\nVariable R : nzRingType.\nVariable d : {poly R}.\nHypothesis Cdl : GRing.comm d (lead_coef d)%:P.\nHypothesis Rreg : GRing.rreg (lead_coef d).\n\nImplicit Types p q r : {poly R}.\n\n(*This lemma states that, under certain commutativity and regularity conditions on the divisor polynomial, performing pseudo-division on a polynomial of the form 'quotient times divisor plus remainder' yields a result where the new quotient and remainder are the original quotient and remainder, each scaled by a specific power of the divisor's leading coefficient.*)\nLemma redivp_eq q r :\n size r < size d ->\n let k := (redivp (q * d + r) d).1.1 in\n let c := (lead_coef d ^+ k)%:P in\n redivp (q * d + r) d = (k, q * c, r * c).\n\n(*This lemma provides the defining identity for polynomial pseudo-division under certain regularity conditions on the divisor. It states that scaling a dividend polynomial by the divisor's leading coefficient raised to a computed power is equal to the pseudo-quotient times the divisor plus the pseudo-remainder.*)\nLemma rdivp_eq p :\n p * (lead_coef d ^+ (rscalp p d))%:P = (rdivp p d) * d + (rmodp p d).\n\n(*This lemma states that a divisor polynomial pseudo-divides a dividend polynomial if a scaled version of the dividend, where the scaling factor is a power of the divisor's leading coefficient, is equal to some quotient polynomial multiplied by the divisor.*)\nLemma eq_rdvdp k q1 p:\n p * ((lead_coef d)^+ k)%:P = q1 * d -> rdvdp d p.\n\n(*This inductive type specifies the correctness of the boolean pseudo-divisibility test for two polynomials. It defines two cases: the first case asserts that divisibility is true if there exists a scaling exponent and a quotient polynomial satisfying the pseudo-division identity; the second case asserts that divisibility is false if the pseudo-remainder of the two polynomials is not the zero polynomial.*)\nVariant rdvdp_spec p q : {poly R} -> bool -> Type :=\n(**)\n | Rdvdp k q1 & p * ((lead_coef q)^+ k)%:P = q1 * q : rdvdp_spec p q 0 true\n(**)\n | RdvdpN & rmodp p q != 0 : rdvdp_spec p q (rmodp p q) false.\n\n(*This lemma connects the boolean result of the pseudo-divisibility test to its specification. It states that the pseudo-divisibility of a dividend by a divisor polynomial holds if and only if the corresponding case in the pseudo-divisibility specification is satisfied, with the pseudo-remainder serving as evidence in the non-divisible case.*)\nLemma rdvdp_eqP p : rdvdp_spec p d (rmodp p d) (rdvdp d p).\n\n(*This lemma states that for any polynomial divisor, the divisor pseudo-divides the product of any polynomial and that divisor.*)\nLemma rdvdp_mull p : rdvdp d (p * d).\n\n(*This lemma states that the pseudo-remainder from dividing the product of two polynomials by the second polynomial is always the zero polynomial.*)\nLemma rmodp_mull p : rmodp (p * d) d = 0. \n\n(*This lemma states that the pseudo-remainder of a polynomial divided by itself is the zero polynomial.*)\nLemma rmodpp : rmodp d d = 0.\n\n(*This lemma states that the quotient of the Euclidean division of a monic polynomial by itself is the constant polynomial one.*)\nLemma rdivpp : rdivp d d = (lead_coef d ^+ rscalp d d)%:P.\n\n(*This lemma states that any polynomial pseudo-divides itself.*)\nLemma rdvdpp : rdvdp d d. \n\n(*This lemma states that if a first polynomial is divisible by a second polynomial, then the product of the quotient and the second polynomial equals the first polynomial multiplied by a constant polynomial derived from the leading coefficient of the second polynomial.*)\nLemma rdivpK p : rdvdp d p ->\n rdivp p d * d = p * (lead_coef d ^+ rscalp p d)%:P.\n\nEnd ComRegDivisor.\n\nEnd RingComRreg.\n\nModule RingMonic.\n\nImport CommonRing.\n\nImport RingComRreg.\n\nSection RingMonic.\n\nVariable R : nzRingType.\nImplicit Types p q r : {poly R}.\n\nSection MonicDivisor.\n\nVariable d : {poly R}.\nHypothesis mond : d \\is monic.\n\n(*This lemma states that for a monic divisor polynomial, the extended Euclidean division of a polynomial constructed from a given quotient and a remainder correctly returns that same quotient and remainder, provided the remainder's degree is less than the divisor's degree.*)\nLemma redivp_eq q r : size r < size d ->\n let k := (redivp (q * d + r) d).1.1 in\n redivp (q * d + r) d = (k, q, r).\n\n(*This lemma states the fundamental property of Euclidean division for polynomials, where the divisor is monic. It asserts that any polynomial can be expressed as the sum of its remainder after division by a monic polynomial and the product of the corresponding quotient and the monic divisor.*)\nLemma rdivp_eq p : p = rdivp p d * d + rmodp p d.\n\n(*This lemma states that the quotient of a monic polynomial divided by itself is the constant polynomial one.*)\nLemma rdivpp : rdivp d d = 1.\n\n(*This lemma states that the quotient from the polynomial division of an expression `q * d + r` by a monic polynomial `d` is equal to `q`, provided that the size of the polynomial `r` is strictly less than the size of the polynomial `d`.*)\nLemma rdivp_addl_mul_small q r : size r < size d -> rdivp (q * d + r) d = q.\n\n(*This lemma states that the quotient from the polynomial division of an expression `q * d + r` by a monic polynomial `d` is equal to the sum of the polynomial `q` and the quotient from the division of the polynomial `r` by `d`.*)\nLemma rdivp_addl_mul q r : rdivp (q * d + r) d = q + rdivp r d.\n\n(*This lemma states that the quotient from the polynomial division of a sum of two polynomials by a monic polynomial `d` is equal to the sum of their individual quotients, provided that the first polynomial in the sum is divisible by `d`.*)\nLemma rdivpDl q r : rdvdp d q -> rdivp (q + r) d = rdivp q d + rdivp r d.\n\n(*This lemma states that the quotient from the polynomial division of a sum of two polynomials by a monic polynomial `d` is equal to the sum of their individual quotients, provided that the second polynomial in the sum is divisible by `d`.*)\nLemma rdivpDr q r : rdvdp d r -> rdivp (q + r) d = rdivp q d + rdivp r d.\n\n(*This lemma states that the quotient from the polynomial division of a product of a polynomial `p` and a monic polynomial `d` by `d` is equal to `p`.*)\nLemma rdivp_mull p : rdivp (p * d) d = p.\n\n(*This lemma states that the remainder from the polynomial division of a product of a polynomial `p` and a monic polynomial `d` by `d` is the zero polynomial.*)\nLemma rmodp_mull p : rmodp (p * d) d = 0.\n\n(*This lemma states that the remainder of the Euclidean division of a polynomial by itself is the zero polynomial.*)\nLemma rmodpp : rmodp d d = 0.\n\n(*This lemma states that the remainder from the polynomial division of an expression `q * d + r` by a monic polynomial `d` is equal to `r`, provided that the size of the polynomial `r` is strictly less than the size of the polynomial `d`.*)\nLemma rmodp_addl_mul_small q r : size r < size d -> rmodp (q * d + r) d = r.\n\n(*This lemma states that the remainder operation with respect to a monic polynomial divisor is idempotent, meaning that taking the remainder of a polynomial that is already a remainder with respect to the same divisor yields that same polynomial.*)\nLemma rmodp_id (p : {poly R}) : rmodp (rmodp p d) d = rmodp p d.\n\n(*This lemma states that the remainder of the sum of two polynomials with respect to a monic divisor is equal to the sum of their individual remainders.*)\nLemma rmodpD p q : rmodp (p + q) d = rmodp p d + rmodp q d.\n\n(*This lemma states that the remainder of the additive inverse of a polynomial with respect to a monic divisor is equal to the additive inverse of the polynomial's remainder.*)\nLemma rmodpN p : rmodp (- p) d = - (rmodp p d).\n\n(*This lemma states that the remainder of the difference of two polynomials with respect to a monic divisor is equal to the difference of their individual remainders.*)\nLemma rmodpB p q : rmodp (p - q) d = rmodp p d - rmodp q d.\n\n(*This lemma states that the remainder of a polynomial scaled by a ring element, when divided by a monic polynomial, is equal to the scalar multiplication of the polynomial's remainder by that same ring element.*)\nLemma rmodpZ a p : rmodp (a *: p) d = a *: (rmodp p d).\n\n(*This lemma states that the remainder of a finite sum of polynomials with respect to a monic divisor is equal to the sum of the remainders of each polynomial in the sum.*)\nLemma rmodp_sum (I : Type) (r : seq I) (P : pred I) (F : I -> {poly R}) :\n rmodp (\\sum_(i <- r | P i) F i) d = (\\sum_(i <- r | P i) (rmodp (F i) d)).\n\n(*This lemma states that for polynomial multiplication, taking the remainder of a product where the right-hand factor is already a remainder with respect to a monic divisor `d` is equivalent to taking the remainder of the original product.*)\nLemma rmodp_mulmr p q : rmodp (p * (rmodp q d)) d = rmodp (p * q) d.\n\n(*This lemma states that any polynomial divides itself.*)\nLemma rdvdpp : rdvdp d d.\n\n(*This lemma states that if a polynomial can be expressed as the product of another polynomial and a monic polynomial `d`, then that polynomial is divisible by `d`.*)\nLemma eq_rdvdp q1 p : p = q1 * d -> rdvdp d p.\n\n(*This lemma states that a monic polynomial `d` divides any polynomial that is a multiple of `d`.*)\nLemma rdvdp_mull p : rdvdp d (p * d).\n\n(*This lemma provides a boolean reflection of polynomial divisibility, asserting that the property of a monic polynomial `d` dividing a polynomial `p` is logically equivalent to the existence of a polynomial quotient `qq` such that `p` is the product of `qq` and `d`.*)\nLemma rdvdpP p : reflect (exists qq, p = qq * d) (rdvdp d p).\n\n(*This lemma provides a cancellation property for polynomial division, stating that if a polynomial `p` is divisible by a monic polynomial `d`, then multiplying the quotient of `p` by `d` back with `d` recovers the original polynomial `p`.*)\nLemma rdivpK p : rdvdp d p -> (rdivp p d) * d = p.\n\nEnd MonicDivisor.\n\n(*This lemma establishes that dropping the lowest `n` coefficients from a polynomial is equivalent to computing the polynomial quotient of that polynomial when divided by the monomial `X` raised to the power of `n`.*)\nLemma drop_poly_rdivp n p : drop_poly n p = rdivp p 'X^n.\n\n(*This lemma establishes that taking the lowest `n` coefficients of a polynomial is equivalent to computing the polynomial remainder of that polynomial when divided by the monomial `X` raised to the power of `n`.*)\nLemma take_poly_rmodp n p : take_poly n p = rmodp p 'X^n.\n\nEnd RingMonic.\n\nSection ComRingMonic.\n\nVariable R : comNzRingType.\nImplicit Types p q r : {poly R}.\nVariable d : {poly R}.\nHypothesis mond : d \\is monic.\n\n(*This lemma states that for polynomials over a commutative ring, taking the remainder of a product where the left-hand factor is already a remainder with respect to a monic divisor `d` is equivalent to taking the remainder of the original product.*)\nLemma rmodp_mulml p q : rmodp (rmodp p d * q) d = rmodp (p * q) d.\n\n(*This lemma states that taking the remainder of a power of a polynomial is equivalent to taking the remainder of the same power of that polynomial's remainder.*)\nLemma rmodpX p n : rmodp ((rmodp p d) ^+ n) d = rmodp (p ^+ n) d.\n\n(*This lemma states that for polynomial composition, taking the remainder of the composition where the inner polynomial is a remainder with respect to a monic divisor `d` is equivalent to taking the remainder of the original composition.*)\nLemma rmodp_compr p q : rmodp (p \\Po (rmodp q d)) d = (rmodp (p \\Po q) d).\n\nEnd ComRingMonic.\n\nEnd RingMonic.\n\nModule Ring.\n\nInclude CommonRing.\nImport RingMonic.\n\nSection ExtraMonicDivisor.\n\nVariable R : nzRingType.\n\nImplicit Types d p q r : {poly R}.\n\n(*This lemma states that the quotient of any polynomial divided by the constant polynomial one is the original polynomial itself.*)\nLemma rdivp1 p : rdivp p 1 = p.\n\n(*This lemma states that a polynomial is divisible by a linear polynomial of the form 'X minus a constant' if and only if that constant is a root of the polynomial.*)\nLemma rdvdp_XsubCl p x : rdvdp ('X - x%:P) p = root p x.\n\n(*This lemma states that the boolean result of checking if a polynomial is divisible by a linear polynomial of the form 'X minus a constant' correctly reflects whether that constant is a root of the polynomial.*)\nLemma polyXsubCP p x : reflect (p.[x] = 0) (rdvdp ('X - x%:P) p).\n\n(*This lemma establishes the factor theorem for polynomials, stating that a value is a root of a polynomial if and only if the polynomial is divisible by the linear polynomial 'X minus that value'.*)\nLemma root_factor_theorem p x : root p x = (rdvdp ('X - x%:P) p).\n\nEnd ExtraMonicDivisor.\n\nEnd Ring.\n\nModule ComRing.\n\nImport Ring.\n\nImport RingComRreg.\n\nSection CommutativeRingPseudoDivision.\n\nVariable R : comNzRingType.\n\nImplicit Types d p q m n r : {poly R}.\n\n(*This inductive type defines the specification for polynomial pseudo-division. It asserts that for a given dividend and divisor, a valid result consists of a scaling exponent, a quotient, and a remainder that satisfy the pseudo-division identity, and where the size of the remainder is strictly less than the size of the divisor, provided the divisor is not zero.*)\nVariant redivp_spec (m d : {poly R}) : nat * {poly R} * {poly R} -> Type :=\n EdivnSpec k (q r: {poly R}) of\n (lead_coef d ^+ k) *: m = q * d + r &\n (d != 0 -> size r < size d) : redivp_spec m d (k, q, r).\n\n(*This lemma states that the result of the pseudo-division function 'redivp' on two polynomials satisfies the formal specification for pseudo-division.*)\nLemma redivpP m d : redivp_spec m d (redivp m d).\n\n(*This lemma provides the fundamental equation for polynomial pseudo-division, stating that the dividend, when scaled by the leading coefficient of the divisor raised to a specific power, is equal to the quotient times the divisor plus the remainder.*)\nLemma rdivp_eq d p :\n (lead_coef d ^+ rscalp p d) *: p = rdivp p d * d + rmodp p d.\n\n(*This lemma states that the remainder and the boolean result of a polynomial pseudo-divisibility test together satisfy the formal specification for that test.*)\nLemma rdvdp_eqP d p : rdvdp_spec p d (rmodp p d) (rdvdp d p).\n\n(*This lemma provides an equivalent condition for checking if a polynomial is divisible by another, based on an equality involving terms from their pseudo-division.*)\nLemma rdvdp_eq q p :\n rdvdp q p = (lead_coef q ^+ rscalp p q *: p == rdivp p q * q).\n\nEnd CommutativeRingPseudoDivision.\n\nEnd ComRing.\n\nModule UnitRing.\n\nImport Ring.\n\nSection UnitRingPseudoDivision.\n\nVariable R : unitRingType.\nImplicit Type p q r d : {poly R}.\n\n(*This lemma states that if a list of distinct values are all roots of a given polynomial, then this polynomial is divisible by the product of the linear factors corresponding to these roots.*)\nLemma uniq_roots_rdvdp p rs :\n all (root p) rs -> uniq_roots rs -> rdvdp (\\prod_(z <- rs) ('X - z%:P)) p.\n\nEnd UnitRingPseudoDivision.\n\nEnd UnitRing.\n\nModule IdomainDefs.\n\nImport Ring.\n\nSection IDomainPseudoDivisionDefs.\n\nVariable R : idomainType.\nImplicit Type p q r d : {poly R}.\n\n(*This definition provides the logic for a polynomial division algorithm that performs a true Euclidean division if the divisor's leading coefficient is a unit, and falls back to pseudo-division otherwise, adjusting the results accordingly.*)\nDefinition edivp_expanded_def p q :=\n let: (k, d, r) as edvpq := redivp p q in\n if lead_coef q \\in GRing.unit then\n (0, (lead_coef q)^-k *: d, (lead_coef q)^-k *: r)\n else edvpq.\n(*This definition creates an opaque key used to lock the definition of the polynomial division function 'edivp', controlling its unfolding during proofs.*)\nFact edivp_key : unit. \n(*This definition provides the main, opaque function for polynomial division, which computes a scaling exponent, a quotient, and a remainder for two given polynomials over an integral domain.*)\nDefinition edivp := locked_with edivp_key edivp_expanded_def.\nCanonical edivp_unlockable := [unlockable fun edivp].\n\n(*This definition extracts the quotient polynomial from the result of the 'edivp' polynomial division function.*)\nDefinition divp p q := ((edivp p q).1).2.\n(*This definition extracts the remainder polynomial from the result of the 'edivp' polynomial division function.*)\nDefinition modp p q := (edivp p q).2.\n(*This definition extracts the scaling exponent from the result of the 'edivp' polynomial division function.*)\nDefinition scalp p q := ((edivp p q).1).1.\n(*This definition specifies a boolean predicate for polynomial divisibility, which is true if the remainder of the division of one polynomial by another is the zero polynomial.*)\nDefinition dvdp p q := modp q p == 0.\n(*This definition specifies a boolean predicate for polynomial equivalence, which is true if two polynomials mutually divide each other.*)\nDefinition eqp p q := (dvdp p q) && (dvdp q p).\n\nEnd IDomainPseudoDivisionDefs.\n\n(*This notation provides the infix operator '%/' for computing the quotient of the division of two polynomials.*)\nNotation \"m %/ d\" := (divp m d) : ring_scope.\n(*This notation provides the infix operator '%%' for computing the remainder of the division of two polynomials.*)\nNotation \"m %% d\" := (modp m d) : ring_scope.\n(*This notation provides the infix operator '%|' to check if a polynomial is divisible by another polynomial.*)\nNotation \"p %| q\" := (dvdp p q) : ring_scope.\n(*This notation provides the infix operator '%=' to check if two polynomials are equivalent, meaning they divide each other.*)\nNotation \"p %= q\" := (eqp p q) : ring_scope.\nEnd IdomainDefs.\n\nModule WeakIdomain.\n\nImport Ring ComRing UnitRing IdomainDefs.\n\nSection WeakTheoryForIDomainPseudoDivision.\n\nVariable R : idomainType.\nImplicit Type p q r d : {poly R}.\n\n(*This lemma states that the result of the 'edivp' polynomial division function is a triplet containing the scaling exponent, the quotient, and the remainder.*)\nLemma edivp_def p q : edivp p q = (scalp p q, divp p q, modp p q).\n\n(*This lemma states that if the leading coefficient of the divisor polynomial is not a unit, the 'edivp' division function behaves identically to the 'redivp' pseudo-division function.*)\nLemma edivp_redivp p q : lead_coef q \\in GRing.unit = false ->\n edivp p q = redivp p q.\n\n(*This lemma provides an explicit formula for the quotient of polynomial division, detailing how it is computed from the pseudo-division quotient based on whether the divisor's leading coefficient is a unit.*)\nLemma divpE p q :\n p %/ q = if lead_coef q \\in GRing.unit\n then lead_coef q ^- rscalp p q *: rdivp p q\n else rdivp p q.\n\n(*This lemma provides an explicit formula for the remainder of polynomial division, detailing how it is computed from the pseudo-division remainder based on whether the divisor's leading coefficient is a unit.*)\nLemma modpE p q :\n p %% q = if lead_coef q \\in GRing.unit\n then lead_coef q ^- rscalp p q *: (rmodp p q)\n else rmodp p q.\n\n(*This lemma provides an explicit formula for the scaling exponent of polynomial division, which is zero if the divisor's leading coefficient is a unit, and equals the pseudo-division scaling exponent otherwise.*)\nLemma scalpE p q :\n scalp p q = if lead_coef q \\in GRing.unit then 0 else rscalp p q.\n\n(*This lemma states that the boolean predicate for polynomial divisibility is equivalent to the boolean predicate for pseudo-divisibility.*)\nLemma dvdpE p q : p %| q = rdvdp p q.\n\n(*This lemma asserts that the scaling factor used in polynomial division, which is obtained by raising the leading coefficient of the divisor to the power of the scaling exponent, is never zero for a non-zero divisor in an integral domain.*)\nLemma lc_expn_scalp_neq0 p q : lead_coef q ^+ scalp p q != 0.\n\nHint Resolve lc_expn_scalp_neq0 : core.\n\n(*This inductive type defines the specification for the 'edivp' polynomial division algorithm, distinguishing between two cases: one for true Euclidean division when the divisor's leading coefficient is a unit, and one for pseudo-division otherwise.*)\nVariant edivp_spec (m d : {poly R}) :\n nat * {poly R} * {poly R} -> bool -> Type :=\n(**)\n|Redivp_spec k (q r: {poly R}) of\n (lead_coef d ^+ k) *: m = q * d + r & lead_coef d \\notin GRing.unit &\n (d != 0 -> size r < size d) : edivp_spec m d (k, q, r) false\n(**)\n|Fedivp_spec (q r: {poly R}) of m = q * d + r & (lead_coef d \\in GRing.unit) &\n (d != 0 -> size r < size d) : edivp_spec m d (0, q, r) true.\n\n(*This lemma states that the result of the 'edivp' polynomial division function on two polynomials correctly satisfies its formal specification, selecting the appropriate case based on whether the divisor's leading coefficient is a unit.*)\nLemma edivpP m d : edivp_spec m d (edivp m d) (lead_coef d \\in GRing.unit).\n\n(*This lemma addresses the extended Euclidean division of polynomials, stating that if a polynomial is formed by a quotient times a divisor plus a remainder, where the remainder's size is smaller than the divisor's and the divisor has a unit leading coefficient, then the extended division of this polynomial correctly recovers a triple of zero, the quotient, and the remainder.*)\nLemma edivp_eq d q r : size r < size d -> lead_coef d \\in GRing.unit ->\n edivp (q * d + r) d = (0, q, r).\n\n(*This lemma states the fundamental identity of polynomial pseudo-division: a scaled version of the dividend polynomial equals the sum of the product of the quotient and divisor, and the remainder.*)\nLemma divp_eq p q : (lead_coef q ^+ scalp p q) *: p = (p %/ q) * q + (p %% q).\n\n(*This lemma defines polynomial divisibility as a boolean check. It asserts that one polynomial divides another if and only if scaling the dividend by a specific factor yields a polynomial equal to the product of the quotient and the divisor.*)\nLemma dvdp_eq q p : (q %| p) = (lead_coef q ^+ scalp p q *: p == (p %/ q) * q).\n\n(*This lemma states that if a polynomial is divisible by another, the product of the resulting quotient and the divisor is equal to the original dividend scaled by a specific factor.*)\nLemma divpK d p : d %| p -> p %/ d * d = (lead_coef d ^+ scalp p d) *: p.\n\n(*This lemma states that if a polynomial is divisible by another, the product of the divisor and the resulting quotient is equal to the original dividend scaled by a specific factor.*)\nLemma divpKC d p : d %| p -> d * (p %/ d) = (lead_coef d ^+ scalp p d) *: p.\n\n(*This lemma provides a reflection on polynomial divisibility, stating that one polynomial divides another if and only if there exists a non-zero scalar and a third polynomial such that the scaled dividend equals the product of the third polynomial and the original divisor.*)\nLemma dvdpP q p :\n reflect (exists2 cqq, cqq.1 != 0 & cqq.1 *: p = cqq.2 * q) (q %| p).\n\n(*This lemma states that for two polynomials, with the second being non-zero, the quotient of their product divided by the second polynomial equals the first polynomial scaled by a specific factor.*)\nLemma mulpK p q : q != 0 -> p * q %/ q = lead_coef q ^+ scalp (p * q) q *: p.\n\n(*This lemma states that for two polynomials, with the second being non-zero, the quotient from dividing their product by the second polynomial is equal to the first polynomial scaled by a determined factor, regardless of the multiplication order.*)\nLemma mulKp p q : q != 0 -> q * p %/ q = lead_coef q ^+ scalp (p * q) q *: p.\n\n(*This lemma states that the pseudo-division of a non-zero polynomial by itself yields a constant polynomial corresponding to the scaling factor used in the division.*)\nLemma divpp p : p != 0 -> p %/ p = (lead_coef p ^+ scalp p p)%:P.\n\nEnd WeakTheoryForIDomainPseudoDivision.\n\n#[global] Hint Resolve lc_expn_scalp_neq0 : core.\n\nEnd WeakIdomain.\n\nModule CommonIdomain.\n\nImport Ring ComRing UnitRing IdomainDefs WeakIdomain.\n\nSection IDomainPseudoDivision.\n\nVariable R : idomainType.\nImplicit Type p q r d m n : {poly R}.\n\n(*This lemma states that the scaling exponent used in polynomial pseudo-division is zero whenever the divisor is the zero polynomial.*)\nLemma scalp0 p : scalp p 0 = 0.\n\n(*This lemma states that the quotient of a polynomial divided by another polynomial of a strictly larger size is the zero polynomial.*)\nLemma divp_small p q : size p < size q -> p %/ q = 0.\n\n(*This lemma asserts that the size of a quotient polynomial is never greater than the size of the original dividend polynomial.*)\nLemma leq_divp p q : (size (p %/ q) <= size p).\n\n(*This lemma states that the quotient of the zero polynomial divided by any other polynomial is the zero polynomial.*)\nLemma div0p p : 0 %/ p = 0.\n\n(*This lemma specifies that the quotient of any polynomial divided by the zero polynomial is defined to be the zero polynomial.*)\nLemma divp0 p : p %/ 0 = 0.\n\n(*This lemma states that dividing a polynomial by the constant polynomial with value one yields the original polynomial as the quotient.*)\nLemma divp1 m : m %/ 1 = m.\n\n(*This lemma specifies that the remainder of any polynomial divided by the zero polynomial is the original polynomial itself.*)\nLemma modp0 p : p %% 0 = p.\n\n(*This lemma states that the remainder of the zero polynomial divided by any other polynomial is the zero polynomial.*)\nLemma mod0p p : 0 %% p = 0.\n\n(*This lemma states that the remainder of any polynomial divided by the constant polynomial one is the zero polynomial.*)\nLemma modp1 p : p %% 1 = 0.\n\nHint Resolve divp0 divp1 mod0p modp0 modp1 : core.\n\n(*This lemma states that if a dividend polynomial has a size strictly smaller than the divisor polynomial, the remainder of their division is the dividend itself.*)\nLemma modp_small p q : size p < size q -> p %% q = p.\n\n(*This lemma asserts that the remainder of any polynomial divided by a non-zero constant polynomial is always the zero polynomial.*)\nLemma modpC p c : c != 0 -> p %% c%:P = 0.\n\n(*This lemma states that for any two polynomials, the remainder of their product divided by the second polynomial factor is the zero polynomial.*)\nLemma modp_mull p q : (p * q) %% q = 0.\n\n(*This lemma states that for any two polynomials, the remainder of their product divided by the first polynomial factor is the zero polynomial.*)\nLemma modp_mulr d p : (d * p) %% d = 0. \n\n(*This lemma states that the remainder of any polynomial divided by itself is the zero polynomial.*)\nLemma modpp d : d %% d = 0.\n\n(*This lemma establishes that the size of the remainder from a polynomial division is strictly smaller than the size of the divisor if and only if the divisor is not the zero polynomial.*)\nLemma ltn_modp p q : (size (p %% q) < size q) = (q != 0).\n\n(*This lemma provides an equivalence relationship for polynomial sizes, stating that for a non-zero divisor, the size of the quotient is strictly less than the size of a third polynomial if and only if the size of the dividend is strictly less than the size of the product of the third polynomial and the divisor.*)\nLemma ltn_divpl d q p : d != 0 ->\n (size (q %/ d) < size p) = (size q < size (p * d)).\n\n(*This lemma provides an equivalence relationship for polynomial sizes, stating that for a non-zero divisor, the size of a third polynomial is less than or equal to the size of the quotient if and only if the size of the product of the third polynomial and the divisor is less than or equal to the size of the dividend.*)\nLemma leq_divpr d p q : d != 0 ->\n (size p <= size (q %/ d)) = (size (p * d) <= size q).\n\n(*This lemma states that for a non-zero divisor, the quotient of a polynomial division is a non-zero polynomial if and only if the size of the divisor is less than or equal to the size of the dividend.*)\nLemma divpN0 d p : d != 0 -> (p %/ d != 0) = (size d <= size p).\n\n(*This lemma provides a formula for the size of a quotient polynomial from a division with a non-zero divisor. It is calculated as the natural number difference between the dividend's size and one less than the divisor's size.*)\nLemma size_divp p q : q != 0 -> size (p %/ q) = (size p - (size q).-1)%N.\n\n(*This lemma states that for any two polynomials, if the divisor is non-zero, then the degree of the remainder polynomial is strictly less than the degree of the divisor.*)\nLemma ltn_modpN0 p q : q != 0 -> size (p %% q) < size q.\n\n(*This lemma states that for any two polynomials, taking the remainder of a polynomial modulo a divisor, and then taking the remainder of the result by the same divisor again, yields the original remainder polynomial.*)\nLemma modp_id p q : (p %% q) %% q = p %% q.\n\n(*This lemma states that for any two polynomials, the size of the remainder polynomial from their division is less than or equal to the size of the dividend polynomial.*)\nLemma leq_modp m d : size (m %% d) <= size m.\n\n(*This lemma states that any polynomial divides the zero polynomial.*)\nLemma dvdp0 d : d %| 0. \n\nHint Resolve dvdp0 : core.\n\n(*This lemma states that the proposition that the zero polynomial divides a given polynomial is equivalent to the proposition that the given polynomial is the zero polynomial.*)\nLemma dvd0p p : (0 %| p) = (p == 0). \n\n(*This lemma states that the boolean expression for the zero polynomial dividing a given polynomial accurately reflects the proposition that this polynomial is equal to zero.*)\nLemma dvd0pP p : reflect (p = 0) (0 %| p).\n\n(*This lemma states that if a polynomial divides a second, non-zero polynomial, then the first polynomial must also be non-zero.*)\nLemma dvdpN0 p q : p %| q -> q != 0 -> p != 0.\n\n(*This lemma states that a polynomial divides the constant polynomial one if and only if that polynomial is a non-zero constant.*)\nLemma dvdp1 d : (d %| 1) = (size d == 1).\n\n(*This lemma states that the constant polynomial one divides any polynomial.*)\nLemma dvd1p m : 1 %| m. \n\n(*This lemma states that for two polynomials, if the first is non-zero and has a degree strictly smaller than the second, then the proposition that the second polynomial divides the first is false.*)\nLemma gtNdvdp p q : p != 0 -> size p < size q -> (q %| p) = false.\n\n(*This lemma states that the boolean expression for a polynomial dividing another accurately reflects the proposition that the remainder of the second polynomial divided by the first is the zero polynomial.*)\nLemma modp_eq0P p q : reflect (p %% q = 0) (q %| p).\n\n(*This lemma states that if a first polynomial divides a second, then the remainder of the second polynomial divided by the first is the zero polynomial.*)\nLemma modp_eq0 p q : (q %| p) -> p %% q = 0. \n\n(*This lemma states that for three polynomials, if a divisor polynomial divides a dividend polynomial, then the proposition that the size of the quotient polynomial is less than or equal to the size of a third polynomial is equivalent to the proposition that the size of the dividend is less than or equal to the size of the product of the third polynomial and the divisor.*)\nLemma leq_divpl d p q :\n d %| p -> (size (p %/ d) <= size q) = (size p <= size (q * d)).\n\n(*This lemma states that for two polynomials, if the first divides the second and the second is non-zero, then the size of the first polynomial must be less than or equal to the size of the second.*)\nLemma dvdp_leq p q : q != 0 -> p %| q -> size p <= size q.\n\n(*This lemma states that for two polynomials and a non-zero scalar, if the product of the first polynomial and the scalar is equal to the product of the second polynomial and a third polynomial, then the second polynomial divides the first.*)\nLemma eq_dvdp c quo q p : c != 0 -> c *: p = quo * q -> q %| p.\n\n(*This lemma states that the polynomial divisibility relation is reflexive, meaning any polynomial divides itself.*)\nLemma dvdpp d : d %| d. \n\nHint Resolve dvdpp : core.\n\n(*This lemma states that if a polynomial divides another, then the resulting quotient polynomial also divides the original dividend polynomial.*)\nLemma divp_dvd p q : p %| q -> (q %/ p) %| q.\n\n(*This lemma states that if a first polynomial divides a second, it also divides the product of that second polynomial with any third polynomial.*)\nLemma dvdp_mull m d n : d %| n -> d %| m * n.\n\n(*This lemma states that if a first polynomial divides a second, it also divides the product of that second polynomial with any third polynomial.*)\nLemma dvdp_mulr n d m : d %| m -> d %| m * n.\n\nHint Resolve dvdp_mull dvdp_mulr : core.\n\n(*This lemma states that if a first polynomial divides a second, and a third polynomial divides a fourth, then the product of the first and third polynomials divides the product of the second and fourth.*)\nLemma dvdp_mul d1 d2 m1 m2 : d1 %| m1 -> d2 %| m2 -> d1 * d2 %| m1 * m2.\n\n(*This lemma states that for three polynomials, if the first polynomial divides the second, then the proposition that the first divides the sum of the second and third is equivalent to the proposition that the first divides the third.*)\nLemma dvdp_addr m d n : d %| m -> (d %| m + n) = (d %| n).\n\n(*This lemma states that for three polynomials, if the first polynomial divides the third, then the proposition that the first divides the sum of the second and third is equivalent to the proposition that the first divides the second.*)\nLemma dvdp_addl n d m : d %| n -> (d %| m + n) = (d %| m).\n\n(*This lemma states that if a polynomial divides two other polynomials, it also divides their sum.*)\nLemma dvdp_add d m n : d %| m -> d %| n -> d %| m + n.\n\n(*This lemma states that if a polynomial divides the sum of two other polynomials, then the boolean indicating that it divides the first polynomial is equal to the boolean indicating that it divides the second.*)\nLemma dvdp_add_eq d m n : d %| m + n -> (d %| m) = (d %| n).\n\n(*This lemma states that for three polynomials, if a first polynomial divides a second one, then the proposition that the first divides the difference of the second and a third polynomial is equivalent to the proposition that the first divides the third one.*)\nLemma dvdp_subr d m n : d %| m -> (d %| m - n) = (d %| n).\n\n(*This lemma states that for three polynomials, if a first polynomial divides a third one, then the proposition that the first divides the difference of a second and the third polynomial is equivalent to the proposition that the first divides the second one.*)\nLemma dvdp_subl d m n : d %| n -> (d %| m - n) = (d %| m).\n\n(*This lemma states that if a polynomial divides two other polynomials, it also divides their difference.*)\nLemma dvdp_sub d m n : d %| m -> d %| n -> d %| m - n.\n\n(*This lemma states that for three polynomials, if a first polynomial divides a second, then the proposition that the first divides a third polynomial is equivalent to the proposition that the first divides the remainder of the third modulo the second.*)\nLemma dvdp_mod d n m : d %| n -> (d %| m) = (d %| m %% n).\n\n(*This lemma states that the polynomial divisibility relation is transitive.*)\nLemma dvdp_trans : transitive (@dvdp R).\n\n(*This lemma states that any polynomial divides the product of itself with any other polynomial.*)\nLemma dvdp_mulIl p q : p %| p * q. \n\n(*This lemma states that a given polynomial always divides the product of any other polynomial with the given polynomial.*)\nLemma dvdp_mulIr p q : q %| p * q. \n\n(*This lemma states that divisibility between two polynomials holds if and only if it holds after multiplying both polynomials on the right by a common non-zero polynomial.*)\nLemma dvdp_mul2r r p q : r != 0 -> (p * r %| q * r) = (p %| q).\n\n(*This lemma states that divisibility between two polynomials holds if and only if it holds after multiplying both polynomials on the left by a common non-zero polynomial.*)\nLemma dvdp_mul2l r p q: r != 0 -> (r * p %| r * q) = (p %| q).\n\n(*This lemma states that if a first polynomial divides a second one, then the condition that the size of a third polynomial is less than the size of the quotient of the second and first polynomials is equivalent to the condition that the size of the product of the third and first polynomials is less than the size of the second polynomial.*)\nLemma ltn_divpr d p q :\n d %| q -> (size p < size (q %/ d)) = (size (p * d) < size q).\n\n(*This lemma states that if a polynomial divides another polynomial, it also divides any positive power of that other polynomial.*)\nLemma dvdp_exp d k p : 0 < k -> d %| p -> d %| (p ^+ k).\n\n(*This lemma states that for any polynomial, a lower power of it divides a higher or equal power of it.*)\nLemma dvdp_exp2l d k l : k <= l -> d ^+ k %| d ^+ l.\n\n(*This lemma states that for a non-constant polynomial, a power of it divides another power of it if and only if the first exponent is less than or equal to the second exponent.*)\nLemma dvdp_Pexp2l d k l : 1 < size d -> (d ^+ k %| d ^+ l) = (k <= l).\n\n(*This lemma states that if a first polynomial divides a second polynomial, then any power of the first polynomial divides the same power of the second polynomial.*)\nLemma dvdp_exp2r p q k : p %| q -> p ^+ k %| q ^+ k.\n\n(*This lemma states that for a non-zero polynomial, the divisibility of a product of a second polynomial and a power of the first polynomial by another power of the first polynomial is equivalent to the divisibility of the second polynomial by the first polynomial raised to the difference of the exponents.*)\nLemma dvdp_exp_sub p q k l: p != 0 ->\n (p ^+ k %| q * p ^+ l) = (p ^+ (k - l) %| q).\n\n(*This lemma states that a linear polynomial of the form 'X minus a constant' divides another polynomial if and only if that constant is a root of the other polynomial.*)\nLemma dvdp_XsubCl p x : ('X - x%:P) %| p = root p x.\n\n(*This lemma states that if a first polynomial divides a second polynomial, then any root of the first polynomial is also a root of the second polynomial.*)\nLemma root_dvdp p q x : p %| q -> root p x -> root q x.\n\n(*This lemma provides a reflection between the boolean statement that a linear polynomial 'X minus a constant' divides a given polynomial and the proposition that the polynomial evaluates to zero at that constant.*)\nLemma polyXsubCP p x : reflect (p.[x] = 0) (('X - x%:P) %| p).\n\n(*This lemma states that a polynomial is equal to the product of its quotient with the linear polynomial 'X minus a constant' and that linear polynomial itself, if and only if the linear polynomial divides the original polynomial.*)\nLemma eqp_div_XsubC p c :\n (p == (p %/ ('X - c%:P)) * ('X - c%:P)) = ('X - c%:P %| p).\n\n(*This lemma states that a value is a root of a polynomial if and only if the polynomial is divisible by the linear factor 'X minus the value'.*)\nLemma root_factor_theorem p x : root p x = (('X - x%:P) %| p).\n\n(*This lemma states that if all elements of a sequence of distinct values are roots of a polynomial, then the polynomial is divisible by the product of all linear factors of the form 'X minus the value' for each value in the sequence.*)\nLemma uniq_roots_dvdp p rs : all (root p) rs -> uniq_roots rs ->\n (\\prod_(z <- rs) ('X - z%:P)) %| p.\n\n(*This lemma states that a value is a root of the iterated product of a sequence of polynomials if and only if that value is a root of every polynomial in the sequence.*)\nLemma root_bigmul x (ps : seq {poly R}) :\n ~~root (\\big[*%R/1]_(p <- ps) p) x = all (fun p => ~~ root p x) ps.\n\n(*This lemma provides a reflection that defines the equivalence relation for polynomials: two polynomials are equivalent if and only if there exist two non-zero scalars such that scaling the first polynomial by the first scalar results in the same polynomial as scaling the second polynomial by the second scalar.*)\nLemma eqpP m n :\n reflect (exists2 c12, (c12.1 != 0) && (c12.2 != 0) & c12.1 *: m = c12.2 *: n)\n (m %= n).\n\n(*This lemma states that if two polynomials are equivalent, then the product of the first polynomial and the leading coefficient of the second is equal to the product of the second polynomial and the leading coefficient of the first.*)\nLemma eqp_eq p q: p %= q -> (lead_coef q) *: p = (lead_coef p) *: q.\n\n(*This lemma states that the polynomial equivalence relation is reflexive, meaning any polynomial is equivalent to itself.*)\nLemma eqpxx : reflexive (@eqp R). \n\nHint Resolve eqpxx : core.\n\n(*This lemma states that if two polynomials are equal, they are also equivalent under the polynomial equivalence relation.*)\nLemma eqpW p q : p = q -> p %= q. \n\n(*This lemma states that the polynomial equivalence relation is symmetric.*)\nLemma eqp_sym : symmetric (@eqp R).\n\n(*This lemma states that the polynomial equivalence relation is transitive.*)\nLemma eqp_trans : transitive (@eqp R).\n\n(*This lemma states that the polynomial equivalence relation is left-transitive.*)\nLemma eqp_ltrans : left_transitive (@eqp R).\n\n(*This lemma states that the polynomial equivalence relation is right-transitive.*)\nLemma eqp_rtrans : right_transitive (@eqp R).\n\n(*This lemma states that a polynomial is equivalent to the zero polynomial if and only if it is itself the zero polynomial.*)\nLemma eqp0 p : (p %= 0) = (p == 0).\n\n(*This lemma states that the zero polynomial is not equivalent to the constant one polynomial.*)\nLemma eqp01 : 0 %= (1 : {poly R}) = false.\n\n(*This lemma states that scaling a polynomial by any non-zero scalar yields a polynomial that is equivalent to the original one.*)\nLemma eqp_scale p c : c != 0 -> c *: p %= p.\n\n(*This lemma states that two equivalent polynomials must have the same size.*)\nLemma eqp_size p q : p %= q -> size p = size q.\n\n(*This lemma states that a polynomial has a size of one if and only if it is equivalent to the constant one polynomial.*)\nLemma size_poly_eq1 p : (size p == 1) = (p %= 1).\n\n(*This lemma states that a linear polynomial of the form 'X minus a constant' is never equivalent to the constant one polynomial.*)\nLemma polyXsubC_eqp1 (x : R) : ('X - x%:P %= 1) = false.\n\n(*This lemma states that if a first polynomial divides a second polynomial, and the second polynomial is associated with the constant polynomial one, then the first polynomial is also associated with the constant polynomial one.*)\nLemma dvdp_eqp1 p q : p %| q -> q %= 1 -> p %= 1.\n\n(*This lemma states that for any two associated polynomials, a third polynomial divides one of them if and only if it divides the other.*)\nLemma eqp_dvdr q p d: p %= q -> d %| p = (d %| q).\n\n(*This lemma states that if two polynomials that act as divisors are associated, then one divides a third polynomial if and only if the other also divides that third polynomial.*)\nLemma eqp_dvdl d2 d1 p : d1 %= d2 -> d1 %| p = (d2 %| p).\n\n(*This lemma states that for a non-zero scalar, a first polynomial divides the scalar multiple of a second polynomial if and only if the first polynomial divides the second polynomial.*)\nLemma dvdpZr c m n : c != 0 -> m %| c *: n = (m %| n).\n\n(*This lemma states that for a non-zero scalar, the scalar multiple of a first polynomial divides a second polynomial if and only if the first polynomial divides the second polynomial.*)\nLemma dvdpZl c m n : c != 0 -> (c *: m %| n) = (m %| n).\n\n(*This lemma states that the additive inverse of a polynomial divides another polynomial if and only if the original polynomial divides it.*)\nLemma dvdpNl d p : (- d) %| p = (d %| p).\n\n(*This lemma states that a polynomial divides the additive inverse of another polynomial if and only if it divides the original polynomial.*)\nLemma dvdpNr d p : d %| (- p) = (d %| p).\n\n(*This lemma states that for any non-zero polynomial, the product of a first polynomial and the non-zero polynomial is associated with the product of a second polynomial and the same non-zero polynomial if and only if the first and second polynomials are themselves associated.*)\nLemma eqp_mul2r r p q : r != 0 -> (p * r %= q * r) = (p %= q).\n\n(*This lemma states that for any non-zero polynomial, the product of the non-zero polynomial and a first polynomial is associated with the product of the same non-zero polynomial and a second polynomial if and only if the first and second polynomials are themselves associated.*)\nLemma eqp_mul2l r p q: r != 0 -> (r * p %= r * q) = (p %= q).\n\n(*This lemma states that if a second polynomial is associated with a third polynomial, then the product of a first polynomial and the second is associated with the product of the first and the third.*)\nLemma eqp_mull r p q: q %= r -> p * q %= p * r.\n\n(*This lemma states that if a first polynomial is associated with a second polynomial, then their products with a third polynomial on the right are also associated.*)\nLemma eqp_mulr q p r : p %= q -> p * r %= q * r.\n\n(*This lemma states that if two polynomials are associated, then raising both to the same natural number power results in two associated polynomials.*)\nLemma eqp_exp p q k : p %= q -> p ^+ k %= q ^+ k.\n\n(*This lemma states that a constant polynomial is associated with the constant polynomial one if and only if its underlying scalar coefficient is non-zero.*)\nLemma polyC_eqp1 (c : R) : (c%:P %= 1) = (c != 0).\n\n(*This lemma states that any polynomial that is associated with the constant polynomial one divides every other polynomial.*)\nLemma dvdUp d p: d %= 1 -> d %| p.\n\n(*This lemma states that if a first polynomial divides a second polynomial, then the two polynomials are associated if and only if their degrees are equal.*)\nLemma dvdp_size_eqp p q : p %| q -> size p == size q = (p %= q).\n\n(*This lemma states that if two polynomials are associated, they share the same set of roots.*)\nLemma eqp_root p q : p %= q -> root p =1 root q.\n\n(*This lemma states that the two variants of the polynomial remainder operation, rmodp and modp, yield associated polynomials when applied to the same two polynomial inputs.*)\nLemma eqp_rmod_mod p q : rmodp p q %= modp p q.\n\n(*This lemma states that the two variants of the polynomial quotient operation, rdivp and divp, yield associated polynomials when applied to the same two polynomial inputs.*)\nLemma eqp_rdiv_div p q : rdivp p q %= divp p q.\n\n(*This lemma states that for three polynomials, if the first polynomial divides the third, and a second polynomial is associated with the third, then the quotient of the second polynomial by the first is associated with the quotient of the third polynomial by the first.*)\nLemma dvd_eqp_divl d p q (dvd_dp : d %| q) (eq_pq : p %= q) :\n p %/ d %= q %/ d.\n\n(*This definition specifies the greatest common divisor of two polynomials, computed using the Euclidean algorithm based on polynomial division and remainder.*)\nDefinition gcdp p q :=\n let: (p1, q1) := if size p < size q then (q, p) else (p, q) in\n if p1 == 0 then q1 else\n let fix loop (n : nat) (pp qq : {poly R}) {struct n} :=\n let rr := modp pp qq in\n if rr == 0 then qq else\n if n is n1.+1 then loop n1 qq rr else rr in\n loop (size p1) p1 q1.\nArguments gcdp : simpl never.\n\n(*This lemma states that the zero polynomial is the left identity for the greatest common divisor operation on polynomials, meaning the greatest common divisor of the zero polynomial and any other polynomial is the other polynomial itself.*)\nLemma gcd0p : left_id 0 gcdp.\n\n(*This lemma states that the zero polynomial is the right identity for the greatest common divisor operation on polynomials, meaning the greatest common divisor of any polynomial and the zero polynomial is the original polynomial itself.*)\nLemma gcdp0 : right_id 0 gcdp.\n\n(*This lemma provides the recursive property of the polynomial greatest common divisor, stating that the greatest common divisor of two polynomials is equal to the greatest common divisor of the smaller-degree polynomial and the remainder of the division of the larger-degree polynomial by the smaller-degree one.*)\nLemma gcdpE p q :\n gcdp p q = if size p < size q\n then gcdp (modp q p) p else gcdp (modp p q) q.\n\n(*This lemma states that the size of the greatest common divisor of the constant polynomial one and any other polynomial is equal to one.*)\nLemma size_gcd1p p : size (gcdp 1 p) = 1.\n\n(*This lemma states that the size of the greatest common divisor of any polynomial and the constant polynomial one is equal to one.*)\nLemma size_gcdp1 p : size (gcdp p 1) = 1.\n\n(*This lemma states that the polynomial greatest common divisor operation is idempotent, meaning that the greatest common divisor of any polynomial with itself is that same polynomial.*)\nLemma gcdpp : idempotent_op gcdp.\n\n(*This lemma states that the greatest common divisor of two polynomials divides both of the original polynomials.*)\nLemma dvdp_gcdlr p q : (gcdp p q %| p) && (gcdp p q %| q).\n\n(*This lemma states that the greatest common divisor of two polynomials divides the first of these two polynomials.*)\nLemma dvdp_gcdl p q : gcdp p q %| p. \n\n(*This lemma states that the greatest common divisor of two polynomials divides the second polynomial.*)\nLemma dvdp_gcdr p q :gcdp p q %| q. \n\n(*This lemma states that for any two polynomials, where the first polynomial is non-zero, the degree of their greatest common divisor is less than or equal to the degree of the first polynomial.*)\nLemma leq_gcdpl p q : p != 0 -> size (gcdp p q) <= size p.\n\n(*This lemma states that for any two polynomials, where the second polynomial is non-zero, the degree of their greatest common divisor is less than or equal to the degree of the second polynomial.*)\nLemma leq_gcdpr p q : q != 0 -> size (gcdp p q) <= size q.\n\n(*This lemma states that a given polynomial divides the greatest common divisor of two other polynomials if and only if it divides both of those polynomials.*)\nLemma dvdp_gcd p m n : p %| gcdp m n = (p %| m) && (p %| n).\n\n(*This lemma asserts that the greatest common divisor of two polynomials is commutative, meaning the result is associate to the greatest common divisor of the same polynomials in reverse order.*)\nLemma gcdpC p q : gcdp p q %= gcdp q p.\n\n(*This lemma states that the greatest common divisor of the constant polynomial one and any other polynomial is associate to the constant polynomial one.*)\nLemma gcd1p p : gcdp 1 p %= 1.\n\n(*This lemma states that the greatest common divisor of any polynomial and the constant polynomial one is associate to the constant polynomial one.*)\nLemma gcdp1 p : gcdp p 1 %= 1.\n\n(*This lemma states that the greatest common divisor of a first polynomial and a second polynomial is associate to the greatest common divisor of the first polynomial and the sum of the second polynomial with any multiple of the first.*)\nLemma gcdp_addl_mul p q r: gcdp r (p * r + q) %= gcdp r q.\n\n(*This lemma states that the greatest common divisor of a first polynomial and the sum of that polynomial with a second one is associate to the greatest common divisor of the first and second polynomials.*)\nLemma gcdp_addl m n : gcdp m (m + n) %= gcdp m n.\n\n(*This lemma states that the greatest common divisor of a first polynomial and the sum of a second polynomial with the first one is associate to the greatest common divisor of the first and second polynomials.*)\nLemma gcdp_addr m n : gcdp m (n + m) %= gcdp m n.\n\n(*This lemma states that the greatest common divisor of a polynomial and a multiple of that polynomial is associate to the polynomial itself.*)\nLemma gcdp_mull m n : gcdp n (m * n) %= n.\n\n(*This lemma states that the greatest common divisor of a polynomial and one of its multiples is associate to the polynomial itself.*)\nLemma gcdp_mulr m n : gcdp n (n * m) %= n.\n\n(*This lemma states that if the first of two polynomials is multiplied by a non-zero scalar, its greatest common divisor with the second polynomial remains associate to the original greatest common divisor.*)\nLemma gcdp_scalel c m n : c != 0 -> gcdp (c *: m) n %= gcdp m n.\n\n(*This lemma states that if the second of two polynomials is multiplied by a non-zero scalar, its greatest common divisor with the first polynomial remains associate to the original greatest common divisor.*)\nLemma gcdp_scaler c m n : c != 0 -> gcdp m (c *: n) %= gcdp m n.\n\n(*This lemma states that if a first polynomial divides a second polynomial, their greatest common divisor is associate to the first polynomial.*)\nLemma dvdp_gcd_idl m n : m %| n -> gcdp m n %= m.\n\n(*This lemma states that if a second polynomial divides a first polynomial, their greatest common divisor is associate to the second polynomial.*)\nLemma dvdp_gcd_idr m n : n %| m -> gcdp m n %= n.\n\n(*This lemma states that the greatest common divisor of two powers of the same polynomial is that polynomial raised to the power of the minimum of the two exponents.*)\nLemma gcdp_exp p k l : gcdp (p ^+ k) (p ^+ l) %= p ^+ minn k l.\n\n(*This lemma states that the greatest common divisor of two polynomials is the zero polynomial if and only if both polynomials are themselves the zero polynomial.*)\nLemma gcdp_eq0 p q : gcdp p q == 0 = (p == 0) && (q == 0).\n\n(*This lemma states that the greatest common divisor operation is compatible with polynomial association in its second argument; if the second of two input polynomials is replaced by an associate polynomial, the resulting greatest common divisor will be associate to the original one.*)\nLemma eqp_gcdr p q r : q %= r -> gcdp p q %= gcdp p r.\n\n(*This lemma states that the greatest common divisor operation is compatible with polynomial association in its first argument; if the first of two input polynomials is replaced by an associate polynomial, the resulting greatest common divisor will be associate to the original one.*)\nLemma eqp_gcdl r p q : p %= q -> gcdp p r %= gcdp q r.\n\n(*This lemma asserts that the greatest common divisor is compatible with polynomial association in both arguments; if two pairs of polynomials are respectively associate, their greatest common divisors are also associate.*)\nLemma eqp_gcd p1 p2 q1 q2 : p1 %= p2 -> q1 %= q2 -> gcdp p1 q1 %= gcdp p2 q2.\n\n(*This lemma states that the ring-based greatest common divisor of two polynomials is associate to the polynomial-specific greatest common divisor.*)\nLemma eqp_rgcd_gcd p q : rgcdp p q %= gcdp p q.\n\n(*This lemma, central to the Euclidean algorithm for polynomials, states that the greatest common divisor of the remainder of a polynomial division and the divisor is associate to the greatest common divisor of the original dividend and divisor.*)\nLemma gcdp_modl m n : gcdp (m %% n) n %= gcdp m n.\n\n(*This lemma, a symmetric form for the Euclidean algorithm, states that the greatest common divisor of a first polynomial and the remainder of a second polynomial divided by the first is associate to the greatest common divisor of the two original polynomials.*)\nLemma gcdp_modr m n : gcdp m (n %% m) %= gcdp m n.\n\n(*This lemma characterizes a polynomial as the greatest common divisor of two other polynomials by stating that it must divide both of them and must be divisible by any other polynomial that also divides both.*)\nLemma gcdp_def d m n :\n d %| m -> d %| n -> (forall d', d' %| m -> d' %| n -> d' %| d) ->\n gcdp m n %= d.\n\n(*This definition defines two polynomials to be coprime if the size of their greatest common divisor polynomial is equal to one.*)\nDefinition coprimep p q := size (gcdp p q) == 1%N.\n\n(*This lemma states that if two polynomials are coprime, then the size of their greatest common divisor polynomial is equal to one.*)\nLemma coprimep_size_gcd p q : coprimep p q -> size (gcdp p q) = 1.\n\n(*This lemma states that the property of two polynomials being coprime is equivalent to the boolean assertion that the size of their greatest common divisor polynomial is equal to one.*)\nLemma coprimep_def p q : coprimep p q = (size (gcdp p q) == 1).\n\n(*This lemma states that for any non-zero constant, the coprimality of a first polynomial with a second polynomial is the same as the coprimality of the product of the first polynomial and the constant with the second polynomial.*)\nLemma coprimepZl c m n : c != 0 -> coprimep (c *: m) n = coprimep m n.\n\n(*This lemma states that for any non-zero constant, the coprimality of a first polynomial with a second polynomial is the same as the coprimality of the first polynomial with the product of the second polynomial and the constant.*)\nLemma coprimepZr c m n: c != 0 -> coprimep m (c *: n) = coprimep m n.\n\n(*This lemma states that a polynomial is coprime to itself if and only if its size is equal to one.*)\nLemma coprimepp p : coprimep p p = (size p == 1).\n\n(*This lemma states that two polynomials are coprime if and only if their greatest common divisor is associated with the constant polynomial one.*)\nLemma gcdp_eqp1 p q : gcdp p q %= 1 = coprimep p q.\n\n(*This lemma states that the coprimality relation for two polynomials is symmetric.*)\nLemma coprimep_sym p q : coprimep p q = coprimep q p.\n\n(*This lemma states that the constant polynomial one is coprime to any other polynomial.*)\nLemma coprime1p p : coprimep 1 p.\n\n(*This lemma states that any polynomial is coprime to the constant polynomial one.*)\nLemma coprimep1 p : coprimep p 1.\n\n(*This lemma states that a polynomial is coprime to the zero polynomial if and only if that polynomial is associated with the constant polynomial one.*)\nLemma coprimep0 p : coprimep p 0 = (p %= 1).\n\n(*This lemma states that the zero polynomial is coprime to another polynomial if and only if that other polynomial is associated with the constant polynomial one.*)\nLemma coprime0p p : coprimep 0 p = (p %= 1).\n\n(*This lemma provides a reflection property, stating that two polynomials are coprime if and only if every common divisor of the two polynomials is associated with the constant polynomial one.*)\nLemma coprimepP p q :\n reflect (forall d, d %| p -> d %| q -> d %= 1) (coprimep p q).\n\n(*This lemma provides a reflection property for non-coprime polynomials, stating that if a first polynomial is non-zero, then it is not coprime with a second polynomial if and only if there exists a polynomial that divides their greatest common divisor and is not associated with the constant polynomial one.*)\nLemma coprimepPn p q : p != 0 ->\n reflect (exists d, (d %| gcdp p q) && ~~ (d %= 1)) (~~ coprimep p q).\n\n(*This lemma states that if a first polynomial is coprime to a second polynomial, and a third polynomial divides the second, then the first polynomial is also coprime to the third.*)\nLemma coprimep_dvdl q p r : r %| q -> coprimep p q -> coprimep p r.\n\n(*This lemma states that if a first polynomial is coprime to a second polynomial, and a third polynomial divides the first, then the third polynomial is also coprime to the second.*)\nLemma coprimep_dvdr p q r : r %| p -> coprimep p q -> coprimep r q.\n\n(*This lemma states that the coprimality of two polynomials is preserved when the first polynomial is replaced by its remainder after division by the second.*)\nLemma coprimep_modl p q : coprimep (p %% q) q = coprimep p q.\n\n(*This lemma states that the coprimality of two polynomials is preserved when the second polynomial is replaced by its remainder after division by the first.*)\nLemma coprimep_modr q p : coprimep q (p %% q) = coprimep q p.\n\n(*This lemma states that the recursive definition of polynomial coprimality is equivalent to the standard definition of polynomial coprimality.*)\nLemma rcoprimep_coprimep q p : rcoprimep q p = coprimep q p.\n\n(*This lemma states that if two polynomials are associated, then a third polynomial is coprime to one if and only if it is coprime to the other.*)\nLemma eqp_coprimepr p q r : q %= r -> coprimep p q = coprimep p r.\n\n(*This lemma states that if two polynomials are associated, then one is coprime to a third polynomial if and only if the other is also coprime to that third polynomial.*)\nLemma eqp_coprimepl p q r : q %= r -> coprimep q p = coprimep r p.\n\n(*This is a recursive helper function for computing the extended greatest common divisor of two polynomials. It takes two polynomials and a natural number as a recursion depth bound, and returns a pair of polynomial coefficients satisfying a step of the extended Euclidean algorithm.*)\nFixpoint egcdp_rec p q k {struct k} : {poly R} * {poly R} :=\n if k is k'.+1 then\n if q == 0 then (1, 0) else\n let: (u, v) := egcdp_rec q (p %% q) k' in\n (lead_coef q ^+ scalp p q *: v, (u - v * (p %/ q)))\n else (1, 0).\n\n(*This definition computes the polynomial B\u00e9zout coefficients for two given polynomials using the extended Euclidean algorithm. It returns a pair of polynomials.*)\nDefinition egcdp p q :=\n if size q <= size p then egcdp_rec p q (size q)\n else let e := egcdp_rec q p (size p) in (e.2, e.1).\n\n(*This lemma states that the result of the extended Euclidean algorithm for a polynomial and the zero polynomial is the pair of constant polynomials one and zero.*)\nLemma egcdp0 p : egcdp p 0 = (1, 0). \n\n(*This lemma states the correctness property of the recursive extended Euclidean algorithm function for polynomials. It asserts that under specific size conditions, the returned coefficients satisfy the B\u00e9zout identity and their sizes are bounded by the sizes of the input polynomials.*)\nLemma egcdp_recP : forall k p q, q != 0 -> size q <= k -> size q <= size p ->\n let e := (egcdp_rec p q k) in\n [/\\ size e.1 <= size q, size e.2 <= size p & gcdp p q %= e.1 * p + e.2 * q].\n\n(*This lemma states the correctness property of the extended Euclidean algorithm for two non-zero polynomials. It asserts that the resulting pair of polynomial coefficients satisfies the B\u00e9zout identity, and their sizes are bounded by the sizes of the opposing input polynomials.*)\nLemma egcdpP p q : p != 0 -> q != 0 -> forall (e := egcdp p q),\n [/\\ size e.1 <= size q, size e.2 <= size p & gcdp p q %= e.1 * p + e.2 * q].\n\n(*This lemma states that the greatest common divisor of two polynomials is associated with the linear combination of those polynomials using the coefficients computed by the extended Euclidean algorithm.*)\nLemma egcdpE p q (e := egcdp p q) : gcdp p q %= e.1 * p + e.2 * q.\n\n(*This lemma states B\u00e9zout's identity for polynomials, asserting that for any two polynomials, there exists a pair of coefficient polynomials such that their linear combination with the original polynomials is associated with the greatest common divisor.*)\nLemma Bezoutp p q : exists u, u.1 * p + u.2 * q %= (gcdp p q).\n\n(*This lemma provides a reflection property, establishing that two polynomials are coprime if and only if there exists a pair of coefficient polynomials whose linear combination with the original polynomials is associated with the constant polynomial one.*)\nLemma Bezout_coprimepP p q :\n reflect (exists u, u.1 * p + u.2 * q %= 1) (coprimep p q).\n\n(*This lemma states that if two polynomials are coprime, then any root of the first polynomial is not a root of the second polynomial.*)\nLemma coprimep_root p q x : coprimep p q -> root p x -> q.[x] != 0.\n\n(*This lemma states that if a first polynomial is coprime to a second polynomial, then the first polynomial divides the product of a third polynomial and the second polynomial if and only if the first polynomial divides the third polynomial.*)\nLemma Gauss_dvdpl p q d: coprimep d q -> (d %| p * q) = (d %| p).\n\n(*This lemma states that if a first polynomial is coprime to a second polynomial, then the first polynomial divides the product of the second polynomial and a third polynomial if and only if the first polynomial divides the third polynomial.*)\nLemma Gauss_dvdpr p q d: coprimep d q -> (d %| q * p) = (d %| p).\n\n(*This lemma states that if two polynomials are coprime, their product divides a third polynomial if and only if each of the two initial polynomials individually divides the third polynomial.*)\nLemma Gauss_dvdp m n p : coprimep m n -> (m * n %| p) = (m %| p) && (n %| p).\n\n(*This lemma states that if a first polynomial is coprime to a second polynomial, then the greatest common divisor of the first polynomial and the product of the second and a third polynomial is associated with the greatest common divisor of the first and third polynomials.*)\nLemma Gauss_gcdpr p m n : coprimep p m -> gcdp p (m * n) %= gcdp p n.\n\n(*This lemma states that if a first polynomial is coprime to a third polynomial, then the greatest common divisor of the first polynomial and the product of a second and the third polynomial is associated with the greatest common divisor of the first and second polynomials.*)\nLemma Gauss_gcdpl p m n : coprimep p n -> gcdp p (m * n) %= gcdp p m.\n\n(*This lemma states that a first polynomial is coprime to the product of a second and a third polynomial if and only if the first polynomial is coprime to the second and also coprime to the third.*)\nLemma coprimepMr p q r : coprimep p (q * r) = (coprimep p q && coprimep p r).\n\n(*This lemma states that the product of a first and a second polynomial is coprime to a third polynomial if and only if the first polynomial is coprime to the third and the second polynomial is also coprime to the third.*)\nLemma coprimepMl p q r: coprimep (q * r) p = (coprimep q p && coprimep r p).\n\n(*This lemma states that if a non-zero polynomial has a multiplicative inverse modulo another polynomial, then the two polynomials are coprime.*)\nLemma modp_coprime k u n : k != 0 -> (k * u) %% n %= 1 -> coprimep k n.\n\n(*This lemma states that for any positive natural number exponent, a first polynomial raised to that exponent is coprime to a second polynomial if and only if the first polynomial is coprime to the second.*)\nLemma coprimep_pexpl k m n : 0 < k -> coprimep (m ^+ k) n = coprimep m n.\n\n(*This lemma states that for any positive natural number exponent, a first polynomial is coprime to a second polynomial raised to that exponent if and only if the first polynomial is coprime to the second.*)\nLemma coprimep_pexpr k m n : 0 < k -> coprimep m (n ^+ k) = coprimep m n.\n\n(*This lemma states that if two polynomials are coprime, then the first polynomial raised to any natural number power is also coprime to the second polynomial.*)\nLemma coprimep_expl k m n : coprimep m n -> coprimep (m ^+ k) n.\n\n(*This lemma states that if two polynomials are coprime, then the first polynomial is also coprime to the second polynomial raised to any natural number power.*)\nLemma coprimep_expr k m n : coprimep m n -> coprimep m (n ^+ k).\n\n(*This lemma states that the greatest common divisor of two polynomial products, where both products share a common polynomial factor, is associated with the product of that common factor and the greatest common divisor of the other two factors.*)\nLemma gcdp_mul2l p q r : gcdp (p * q) (p * r) %= (p * gcdp q r).\n\n(*This lemma states that the greatest common divisor of two polynomial products, where both products share a common polynomial factor, is associated with the product of the greatest common divisor of the other two factors and that common factor.*)\nLemma gcdp_mul2r q r p : gcdp (q * p) (r * p) %= gcdp q r * p.\n\n(*This lemma states that the product of a polynomial and the greatest common divisor of two other polynomials is associated with the greatest common divisor of the products of the first polynomial with each of the other two.*)\nLemma mulp_gcdr p q r : r * (gcdp p q) %= gcdp (r * p) (r * q).\n\n(*This lemma states that the product of the greatest common divisor of two polynomials and a third polynomial is associated with the greatest common divisor of the products of each of the first two polynomials with the third.*)\nLemma mulp_gcdl p q r : (gcdp p q) * r %= gcdp (p * r) (q * r).\n\n(*This lemma states that if at least one of two polynomials is non-zero, then the polynomials obtained by dividing each by their greatest common divisor are coprime.*)\nLemma coprimep_div_gcd p q : (p != 0) || (q != 0) ->\n coprimep (p %/ (gcdp p q)) (q %/ gcdp p q).\n\n(*This lemma states that the result of the division of a first polynomial by a second polynomial is the zero polynomial if and only if the first polynomial is zero, the second polynomial is zero, or the size of the first polynomial is less than the size of the second.*)\nLemma divp_eq0 p q : (p %/ q == 0) = [|| p == 0, q ==0 | size p < size q].\n\n(*This lemma states that if a second polynomial divides a first polynomial, then the division of the first by the second yields the zero polynomial if and only if the first polynomial is the zero polynomial.*)\nLemma dvdp_div_eq0 p q : q %| p -> (p %/ q == 0) = (p == 0).\n\n(*This lemma states that for two non-zero polynomials, they are not coprime if and only if there exist two other non-zero polynomials, with their sizes bounded by the sizes of the original polynomials, such that the product of the first new polynomial and the first original polynomial is equal to the product of the second new polynomial and the second original polynomial.*)\nLemma Bezout_coprimepPn p q : p != 0 -> q != 0 ->\n reflect (exists2 uv : {poly R} * {poly R},\n (0 < size uv.1 < size q) && (0 < size uv.2 < size p) &\n uv.1 * p = uv.2 * q)\n (~~ (coprimep p q)).\n\n(*This lemma states that for any positive natural number exponent, a first polynomial raised to that exponent divides a second polynomial raised to the same exponent if and only if the first polynomial divides the second.*)\nLemma dvdp_pexp2r m n k : k > 0 -> (m ^+ k %| n ^+ k) = (m %| n).\n\n(*This lemma states that a given value is a root of the greatest common divisor of two polynomials if and only if it is a root of both polynomials individually.*)\nLemma root_gcd p q x : root (gcdp p q) x = root p x && root q x.\n\n(*This lemma states that a given value is a root of the iterated greatest common divisor of a sequence of polynomials if and only if it is a root of every polynomial in that sequence.*)\nLemma root_biggcd x (ps : seq {poly R}) :\n root (\\big[gcdp/0]_(p <- ps) p) x = all (fun p => root p x) ps.\n\n(*This fixpoint defines a recursive function taking two polynomials and a natural number for recursion depth. It computes a factor of the second polynomial that is coprime to the first polynomial by repeatedly replacing the second polynomial with the result of dividing it by its greatest common divisor with the first, until it becomes coprime to the first polynomial or the recursion depth is exhausted.*)\nFixpoint gdcop_rec q p k :=\n if k is m.+1 then\n if coprimep p q then p\n else gdcop_rec q (divp p (gcdp p q)) m\n else (q == 0)%:R.\n\n(*This definition specifies a function that computes the largest factor of a second polynomial that is coprime to a first polynomial, using a recursive process bounded by the size of the second polynomial.*)\nDefinition gdcop q p := gdcop_rec q p (size p).\n\n(*This inductive type defines the specification for a polynomial that is the greatest divisor of a second polynomial that is also coprime to a first polynomial. This specification asserts that the result polynomial divides the second input polynomial, is coprime to the first input polynomial unless the second is zero, and is divisible by any other polynomial that is a divisor of the second input polynomial and coprime to the first.*)\nVariant gdcop_spec q p : {poly R} -> Type :=\n GdcopSpec r of (dvdp r p) & ((coprimep r q) || (p == 0))\n & (forall d, dvdp d p -> coprimep d q -> dvdp d r)\n : gdcop_spec q p r.\n\n(*This lemma states that applying the greatest coprime divisor function to any polynomial and the zero polynomial results in a constant polynomial, which is one if the first polynomial is non-zero, and zero otherwise.*)\nLemma gdcop0 q : gdcop q 0 = (q == 0)%:R.\n\n(*This lemma proves that the recursive helper function for computing the greatest coprime divisor correctly meets its specification, provided the initial recursion depth is at least the size of the polynomial being factored.*)\nLemma gdcop_recP q p k : size p <= k -> gdcop_spec q p (gdcop_rec q p k).\n\n(*This lemma proves that the function for computing the greatest coprime divisor of two polynomials correctly meets its formal specification.*)\nLemma gdcopP q p : gdcop_spec q p (gdcop q p).\n\n(*This lemma states that the result of computing the greatest divisor of a second polynomial that is coprime to a first polynomial is, in fact, coprime to the first polynomial, provided the second polynomial is not zero.*)\nLemma coprimep_gdco p q : (q != 0)%B -> coprimep (gdcop p q) p.\n\n(*This lemma states that for a non-zero polynomial and another polynomial, a linear polynomial divides their pseudo-greatest common divisor if and only if it divides both of the original polynomials.*)\nLemma size2_dvdp_gdco p q d : p != 0 -> size d = 2 ->\n (d %| (gdcop q p)) = (d %| p) && ~~(d %| q).\n\n(*This lemma states that the pseudo-greatest common divisor of two polynomials divides the second polynomial.*)\nLemma dvdp_gdco p q : (gdcop p q) %| q. \n\n(*This lemma asserts that for a non-zero polynomial, a ring element is a root of the pseudo-greatest common divisor of two polynomials if and only if it is a root of both individual polynomials.*)\nLemma root_gdco p q x : p != 0 -> root (gdcop q p) x = root p x && ~~(root q x).\n\n(*This lemma states that if a polynomial divides another, then the composition of the first polynomial with a third polynomial divides the composition of the second polynomial with that same third polynomial.*)\nLemma dvdp_comp_poly r p q : (p %| q) -> (p \\Po r) %| (q \\Po r).\n\n(*This lemma states that the composition of the greatest common divisor of two polynomials with a third polynomial is associate to the greatest common divisor of the compositions of the original two polynomials with the third polynomial.*)\nLemma gcdp_comp_poly r p q : gcdp p q \\Po r %= gcdp (p \\Po r) (q \\Po r).\n\n(*This lemma asserts that if two polynomials are coprime, their respective compositions with a third polynomial are also coprime.*)\nLemma coprimep_comp_poly r p q : coprimep p q -> coprimep (p \\Po r) (q \\Po r).\n\n(*This lemma establishes that a polynomial is coprime to the sum of a multiple of itself and a second polynomial if and only if it is coprime to the second polynomial.*)\nLemma coprimep_addl_mul p q r : coprimep r (p * r + q) = coprimep r q.\n\n(*This definition specifies that a polynomial is irreducible if it is not constant and its only non-constant divisors are its associates.*)\nDefinition irreducible_poly p :=\n (size p > 1) * (forall q, size q != 1 -> q %| p -> q %= p) : Prop.\n\n(*This lemma states that an irreducible polynomial is always a non-zero polynomial.*)\nLemma irredp_neq0 p : irreducible_poly p -> p != 0.\n\n(*This definition provides a coercion that allows a proof of a polynomial's irreducibility to be used as a function, which asserts that any non-constant divisor of that polynomial is an associate of the polynomial itself.*)\nDefinition apply_irredp p (irr_p : irreducible_poly p) := irr_p.2.\nCoercion apply_irredp : irreducible_poly >-> Funclass.\n\n(*This lemma, known as the polynomial remainder theorem, states that the remainder of the pseudo-division of a polynomial by a linear polynomial of the form 'X - c' is the constant polynomial corresponding to the value of the original polynomial evaluated at 'c'.*)\nLemma modp_XsubC p c : p %% ('X - c%:P) = p.[c]%:P.\n\n(*This lemma states that a polynomial is coprime to a linear polynomial of the form 'X - c' if and only if 'c' is not a root of that polynomial.*)\nLemma coprimep_XsubC p c : coprimep p ('X - c%:P) = ~~ root p c.\n\n(*This lemma asserts that for any two distinct ring elements 'a' and 'b', the linear polynomials 'X - a' and 'X - b' are coprime.*)\nLemma coprimep_XsubC2 (a b : R) : b - a != 0 ->\n coprimep ('X - a%:P) ('X - b%:P).\n\n(*This lemma states that a polynomial is coprime to the monomial 'X' if and only if zero is not a root of that polynomial.*)\nLemma coprimepX p : coprimep p 'X = ~~ root p 0.\n\n(*This lemma states that for any two monic polynomials, the property of being associate is equivalent to the property of being equal.*)\nLemma eqp_monic : {in monic &, forall p q, (p %= q) = (p == q)}.\n\n(*This lemma states that a polynomial 'p' divides the product of '(X - c)' and another polynomial 'q' if and only if 'p', with the factor '(X - c)' removed if it is a root, divides 'q'.*)\nLemma dvdp_mul_XsubC p q c :\n (p %| ('X - c%:P) * q) = ((if root p c then p %/ ('X - c%:P) else p) %| q).\n\n(*This lemma states that if a polynomial divides a product of linear factors, then that polynomial must be associate to a product formed from a sub-sequence of those same linear factors.*)\nLemma dvdp_prod_XsubC (I : Type) (r : seq I) (F : I -> R) p :\n p %| \\prod_(i <- r) ('X - (F i)%:P) ->\n {m | p %= \\prod_(i <- mask m r) ('X - (F i)%:P)}.\n\n(*This lemma states that for any ring element, the linear polynomial 'X' minus that element is irreducible.*)\nLemma irredp_XsubC (x : R) : irreducible_poly ('X - x%:P).\n\n(*This lemma states that for any ring element, the linear polynomial 'X' plus that element is irreducible.*)\nLemma irredp_XaddC (x : R) : irreducible_poly ('X + x%:P).\n\n(*This lemma states that if an irreducible polynomial is divided by another polynomial, the divisor must be associate to either the constant polynomial one or to the irreducible polynomial itself.*)\nLemma irredp_XsubCP d p :\n irreducible_poly p -> d %| p -> {d %= 1} + {d %= p}.\n\n(*This lemma establishes that a polynomial divides the n-th power of a linear polynomial '(X - c)' if and only if that polynomial is associate to the k-th power of '(X - c)' for some natural number 'k' less than or equal to 'n'.*)\nLemma dvdp_exp_XsubCP (p : {poly R}) (c : R) (n : nat) :\n reflect (exists2 k, (k <= n)%N & p %= ('X - c%:P) ^+ k)\n (p %| ('X - c%:P) ^+ n).\n\nEnd IDomainPseudoDivision.\nArguments gcdp : simpl never.\n\n#[global] Hint Resolve eqpxx divp0 divp1 mod0p modp0 modp1 : core.\n#[global] Hint Resolve dvdp_mull dvdp_mulr dvdpp dvdp0 : core.\nArguments dvdp_exp_XsubCP {R p c n}.\n\nEnd CommonIdomain.\n\nModule Idomain.\n\nInclude IdomainDefs.\nExport IdomainDefs.\nInclude WeakIdomain.\nInclude CommonIdomain.\n\nEnd Idomain.\n\nModule IdomainMonic.\n\nImport Ring ComRing UnitRing IdomainDefs Idomain.\n\nSection IdomainMonic.\n\nVariable R : idomainType.\n\nImplicit Type p d r : {poly R}.\n\nSection MonicDivisor.\n\nVariable q : {poly R}.\nHypothesis monq : q \\is monic.\n\n(*This lemma states that when the divisor is a monic polynomial, the pseudo-quotient of two polynomials is equal to their Euclidean quotient.*)\nLemma divpE p : p %/ q = rdivp p q.\n\n(*This lemma states that when the divisor is a monic polynomial, the pseudo-remainder of two polynomials is equal to their Euclidean remainder.*)\nLemma modpE p : p %% q = rmodp p q.\n\n(*This lemma asserts that the scaling factor used in the pseudo-division of a polynomial by a monic polynomial is equal to the zero element of the ring.*)\nLemma scalpE p : scalp p q = 0.\n\n(*This lemma provides the division identity for polynomials where the divisor is monic, stating that a polynomial is equal to the sum of its pseudo-remainder and the product of its pseudo-quotient and the divisor.*)\nLemma divp_eq p : p = (p %/ q) * q + (p %% q).\n\n(*This lemma states that the pseudo-division of a monic polynomial by itself results in the constant polynomial one.*)\nLemma divpp p : q %/ q = 1.\n\n(*This lemma provides an equivalence for divisibility by a monic polynomial, stating that a monic polynomial divides another polynomial if and only if the second polynomial is equal to the product of its pseudo-quotient and the monic divisor.*)\nLemma dvdp_eq p : (q %| p) = (p == (p %/ q) * q).\n\n(*This lemma provides a constructive witness for divisibility by a monic polynomial, showing that a monic polynomial divides a second polynomial if and only if there exists a quotient polynomial that, when multiplied by the monic divisor, equals the second polynomial.*)\nLemma dvdpP p : reflect (exists qq, p = qq * q) (q %| p).\n\n(*This lemma provides a cancellation rule, stating that the pseudo-quotient of the product of a polynomial and a monic polynomial, when divided by the monic polynomial, is the original polynomial.*)\nLemma mulpK p : p * q %/ q = p.\n\n(*This lemma provides a cancellation rule, stating that the pseudo-quotient of the product of a monic polynomial and another polynomial, when divided by the monic polynomial, is the other polynomial.*)\nLemma mulKp p : q * p %/ q = p. \n\nEnd MonicDivisor.\n\n(*This lemma states that dropping the lowest `n` degree terms from a polynomial is equivalent to taking the quotient of that polynomial's division by the monomial `X` to the power of `n`.*)\nLemma drop_poly_divp n p : drop_poly n p = p %/ 'X^n.\n\n(*This lemma states that taking the lowest `n` degree terms from a polynomial is equivalent to taking the remainder of that polynomial's division by the monomial `X` to the power of `n`.*)\nLemma take_poly_modp n p : take_poly n p = p %% 'X^n.\n\nEnd IdomainMonic.\n\nEnd IdomainMonic.\n\nModule IdomainUnit.\n\nImport Ring ComRing UnitRing IdomainDefs Idomain.\n\nSection UnitDivisor.\n\nVariable R : idomainType.\nVariable d : {poly R}.\n\nHypothesis ulcd : lead_coef d \\in GRing.unit.\n\nImplicit Type p q r : {poly R}.\n\n(*This lemma states the fundamental property of Euclidean division for polynomials: any polynomial can be expressed as the sum of its remainder after division by a divisor polynomial and the product of its quotient and that same divisor polynomial. The divisor is assumed to have a unit leading coefficient.*)\nLemma divp_eq p : p = (p %/ d) * d + (p %% d).\n\n(*This lemma asserts the uniqueness of polynomial Euclidean division. It states that if a polynomial `p` is expressed as the sum of a product `q * d` and a remainder `r`, where the size of `r` is strictly less than the size of the divisor `d`, then `q` must be the quotient of `p` divided by `d`, and `r` must be the remainder. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma edivpP p q r : p = q * d + r -> size r < size d ->\n q = (p %/ d) /\\ r = p %% d.\n\n(*This lemma provides a condition for identifying the quotient of a polynomial division. It states that if a polynomial `p` equals the sum of a product `q * d` and a polynomial `r` whose size is less than the size of `d`, then `q` is the quotient of `p` divided by `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divpP p q r : p = q * d + r -> size r < size d -> q = (p %/ d).\n\n(*This lemma provides a condition for identifying the remainder of a polynomial division. It states that if a polynomial `p` equals the sum of a product `q * d` and a polynomial `r` whose size is less than the size of `d`, then `r` is the remainder of `p` divided by `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma modpP p q r : p = q * d + r -> size r < size d -> r = (p %% d).\n\n(*This lemma states that if a polynomial `q` has a unit leading coefficient, then another polynomial `p` is associated with `q` if and only if `p` can be expressed as the product of `q` and a non-zero scalar from the base ring.*)\nLemma ulc_eqpP p q : lead_coef q \\is a GRing.unit ->\n reflect (exists2 c : R, c != 0 & p = c *: q) (p %= q).\n\n(*This lemma states that a polynomial `p` is divisible by a divisor polynomial `d` if and only if `p` is equal to the product of the quotient of `p` divided by `d` and the divisor `d` itself. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma dvdp_eq p : (d %| p) = (p == p %/ d * d).\n\n(*This lemma states that if a polynomial `p` is associated with another polynomial `q` which has a unit leading coefficient, then `p` is equal to `q` multiplied by the scalar obtained by dividing the leading coefficient of `p` by the leading coefficient of `q`.*)\nLemma ucl_eqp_eq p q : lead_coef q \\is a GRing.unit ->\n p %= q -> p = (lead_coef p / lead_coef q) *: q.\n\n(*This lemma states that the remainder of the division of a scalar-multiplied polynomial by a divisor `d` is equal to the scalar multiplied by the remainder of the original polynomial divided by `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma modpZl c p : (c *: p) %% d = c *: (p %% d).\n\n(*This lemma states that the quotient of the division of a scalar-multiplied polynomial by a divisor `d` is equal to the scalar multiplied by the quotient of the original polynomial divided by `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divpZl c p : (c *: p) %/ d = c *: (p %/ d).\n\n(*This lemma states that if two polynomials are associated, then their remainders after division by a common divisor `d` are also associated. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma eqp_modpl p q : p %= q -> (p %% d) %= (q %% d).\n\n(*This lemma states that if two polynomials are associated, then their quotients after division by a common divisor `d` are also associated. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma eqp_divl p q : p %= q -> (p %/ d) %= (q %/ d).\n\n(*This lemma states that the remainder of the division of the additive inverse of a polynomial `p` by a divisor `d` is equal to the additive inverse of the remainder of `p` divided by `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma modpN p : (- p) %% d = - (p %% d).\n\n(*This lemma states that the quotient of the division of the additive inverse of a polynomial `p` by a divisor `d` is equal to the additive inverse of the quotient of `p` divided by `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divpN p : (- p) %/ d = - (p %/ d).\n\n(*This lemma states that the polynomial remainder operation is additive; the remainder of the sum of two polynomials when divided by a divisor `d` is equal to the sum of their individual remainders. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma modpD p q : (p + q) %% d = p %% d + q %% d.\n\n(*This lemma states that the polynomial quotient operation is additive; the quotient of the sum of two polynomials when divided by a divisor `d` is equal to the sum of their individual quotients. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divpD p q : (p + q) %/ d = p %/ d + q %/ d.\n\n(*This lemma states that right-multiplying a polynomial `q` by a divisor `d` and then taking the quotient of the result with `d` yields the original polynomial `q`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma mulpK q : (q * d) %/ d = q.\n\n(*This lemma states that left-multiplying a polynomial `q` by a divisor `d` and then taking the quotient of the result with `d` yields the original polynomial `q`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma mulKp q : (d * q) %/ d = q. \n\n(*This lemma states that for a polynomial of the form `q * d + r`, if the size of polynomial `r` is strictly smaller than the size of the divisor polynomial `d`, then the quotient of this sum divided by `d` is exactly `q`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divp_addl_mul_small q r : size r < size d -> (q * d + r) %/ d = q.\n\n(*This lemma states that for a polynomial of the form `q * d + r`, if the size of polynomial `r` is strictly smaller than the size of the divisor polynomial `d`, then the remainder of this sum divided by `d` is exactly `r`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma modp_addl_mul_small q r : size r < size d -> (q * d + r) %% d = r.\n\n(*This lemma states that the quotient of the division of a polynomial of the form `q * d + r` by the divisor `d` is equal to the sum of `q` and the quotient of `r` divided by `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divp_addl_mul q r : (q * d + r) %/ d = q + r %/ d.\n\n(*This lemma states that any polynomial `d` with a unit leading coefficient, when divided by itself, yields a quotient equal to the constant polynomial one.*)\nLemma divpp : d %/ d = 1. \n\n(*This lemma states that the size of the polynomial obtained by multiplying the quotient of `m` divided by `d` with the divisor `d` is less than or equal to the size of the original polynomial `m`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma leq_divMp m : size (m %/ d * d) <= size m.\n\n(*This lemma provides a reflection property for polynomial divisibility, stating that a polynomial `p` is divisible by a divisor `d` if and only if there exists a polynomial `q` such that `p` is equal to the product of `q` and `d`. The divisor `d` has a unit leading coefficient.*)\nLemma dvdpP p : reflect (exists q, p = q * d) (d %| p).\n\n(*This lemma states that if a polynomial `p` is divisible by a divisor `d`, then `p` is equal to the product of its quotient `p %/ d` and the divisor `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divpK p : d %| p -> p %/ d * d = p.\n\n(*This lemma states that if a polynomial `p` is divisible by a divisor `d`, then `p` is equal to the product of the divisor `d` and its quotient `p %/ d`. This holds because polynomial multiplication is commutative, and the divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divpKC p : d %| p -> d * (p %/ d) = p.\n\n(*This lemma provides an alternate way to check for equality with a quotient. It states that if a polynomial `p` is divisible by `d`, then asserting that a polynomial `q` is equal to the quotient `p %/ d` is equivalent to asserting that the product `q * d` is equal to `p`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma dvdp_eq_div p q : d %| p -> (q == p %/ d) = (q * d == p).\n\n(*This lemma provides an alternate way to check for equality with a quotient. It states that if a polynomial `p` is divisible by `d`, then asserting that `p` is equal to the product `q * d` is equivalent to asserting that the quotient `p %/ d` is equal to `q`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma dvdp_eq_mul p q : d %| p -> (p == q * d) = (p %/ d == q).\n\n(*This lemma states a property related to multiplication and division. If a polynomial `q` is divisible by `d`, then the product of another polynomial `p` and the quotient of `q` divided by `d` is equal to the quotient of the product of `p` and `q` divided by `d`. The divisor `d` is assumed to have a unit leading coefficient.*)\nLemma divp_mulA p q : d %| q -> p * (q %/ d) = p * q %/ d.\n\n(*This lemma states that if a divisor polynomial divides a dividend polynomial, then multiplying their quotient by a third polynomial is equivalent to dividing the product of the dividend and the third polynomial by the divisor.*)\nLemma divp_mulAC m n : d %| m -> m %/ d * n = m * n %/ d.\n\n(*This lemma states that if a polynomial divides two other polynomials, then the product of the first polynomial and the quotient of the second by the divisor is equal to the product of the second polynomial and the quotient of the first by the divisor.*)\nLemma divp_mulCA p q : d %| p -> d %| q -> p * (q %/ d) = q * (p %/ d).\n\n(*This lemma states that for any two polynomials and a divisor polynomial, the remainder of the product of the first polynomial and the remainder of the second with respect to the divisor, when taken with respect to the same divisor, is equal to the remainder of the product of the first and second polynomials with respect to that divisor.*)\nLemma modp_mul p q : (p * (q %% d)) %% d = (p * q) %% d.\n\nEnd UnitDivisor.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to leq_divMp.\")]\n(*This notation provides an alias for a theorem asserting a 'less than or equal to' property, likely concerning the degrees of polynomials involved in a truncated division.*)\nNotation leq_trunc_divp := leq_divMp.\n\nSection MoreUnitDivisor.\n\nVariable R : idomainType.\nVariable d : {poly R}.\nHypothesis ulcd : lead_coef d \\in GRing.unit.\n\nImplicit Types p q : {poly R}.\n\n(*This lemma states that for any two natural numbers where one is less than or equal to the other, a polynomial raised to the power of their difference is equal to the polynomial quotient of the same polynomial raised to the larger number divided by the polynomial raised to the smaller number.*)\nLemma expp_sub m n : n <= m -> (d ^+ (m - n))%N = d ^+ m %/ d ^+ n.\n\n(*This lemma states that if the leading coefficients of a common factor polynomial and a second polynomial are units, then the quotient of the product of the common factor and a first polynomial by the product of the same common factor and the second polynomial is equal to the quotient of the first polynomial by the second.*)\nLemma divp_pmul2l p q : lead_coef q \\in GRing.unit -> d * p %/ (d * q) = p %/ q.\n\n(*This lemma states that if the leading coefficients of a common factor polynomial and a first polynomial are units, then the quotient of the product of a second polynomial and the common factor by the product of the first polynomial and the same common factor is equal to the quotient of the second polynomial by the first.*)\nLemma divp_pmul2r p q : lead_coef p \\in GRing.unit -> q * d %/ (p * d) = q %/ p.\n\n(*This lemma states that if two divisor polynomials have unit leading coefficients, the result of dividing a dividend polynomial by the first divisor and then dividing that quotient by the second divisor is the same as dividing the dividend by the product of the first and second divisors.*)\nLemma divp_divl r p q :\n lead_coef r \\in GRing.unit -> lead_coef p \\in GRing.unit ->\n q %/ p %/ r = q %/ (p * r).\n\n(*This lemma states that if two divisor polynomials have unit leading coefficients, dividing a polynomial by the first divisor and then by the second is equivalent to dividing it by the second divisor and then by the first.*)\nLemma divpAC p q : lead_coef p \\in GRing.unit -> q %/ d %/ p = q %/ p %/ d.\n\n(*This lemma states that the remainder of a polynomial when divided by a scaled divisor polynomial is equal to the remainder of the same polynomial when divided by the original unscaled divisor, provided the scaling factor is a unit and the original divisor has a unit leading coefficient.*)\nLemma modpZr c p : c \\in GRing.unit -> p %% (c *: d) = (p %% d).\n\n(*This lemma states that the quotient of a polynomial divided by a scaled divisor polynomial is equal to the product of the inverse of the scaling constant and the quotient of the original polynomial divided by the unscaled divisor, provided the scaling factor is a unit and the original divisor has a unit leading coefficient.*)\nLemma divpZr c p : c \\in GRing.unit -> p %/ (c *: d) = c^-1 *: (p %/ d).\n\nEnd MoreUnitDivisor.\n\nEnd IdomainUnit.\n\nModule Field.\n\nImport Ring ComRing UnitRing.\nInclude IdomainDefs.\nExport IdomainDefs.\nInclude CommonIdomain.\n\nSection FieldDivision.\n\nVariable F : fieldType.\n\nImplicit Type p q r d : {poly F}.\n\n(*This lemma states the fundamental property of polynomial division, expressing a dividend polynomial as the sum of its remainder with respect to a divisor polynomial and the product of the quotient and the divisor polynomial.*)\nLemma divp_eq p q : p = (p %/ q) * q + (p %% q).\n\n(*This lemma establishes the uniqueness of the polynomial quotient and remainder. It states that if a dividend polynomial is expressed as the sum of a potential remainder polynomial and the product of a potential quotient polynomial and a divisor polynomial, and the degree of the potential remainder is strictly less than the degree of the divisor, then the potential quotient equals the true quotient and the potential remainder equals the true remainder.*)\nLemma divp_modpP p q d r : p = q * d + r -> size r < size d ->\n q = (p %/ d) /\\ r = p %% d.\n\n(*This lemma asserts the uniqueness of the polynomial quotient. It states that if a dividend polynomial is expressed as the sum of a potential remainder polynomial and the product of a potential quotient polynomial and a divisor polynomial, and the degree of the potential remainder is strictly less than the degree of the divisor, then the potential quotient is the true quotient of the dividend by the divisor.*)\nLemma divpP p q d r : p = q * d + r -> size r < size d ->\n q = (p %/ d).\n\n(*This lemma asserts the uniqueness of the polynomial remainder. It states that if a dividend polynomial is expressed as the sum of a potential remainder polynomial and the product of a potential quotient polynomial and a divisor polynomial, and the degree of the potential remainder is strictly less than the degree of the divisor, then the potential remainder is the true remainder of the dividend by the divisor.*)\nLemma modpP p q d r : p = q * d + r -> size r < size d -> r = (p %% d).\n\n(*This lemma states that if two non-zero polynomials over a field are associates, then the first polynomial is equal to the second polynomial scaled by the quotient of their leading coefficients.*)\nLemma eqpfP p q : p %= q -> p = (lead_coef p / lead_coef q) *: q.\n\n(*This lemma states that a divisor polynomial divides a dividend polynomial if and only if the dividend is equal to the product of the divisor and the quotient of the dividend by the divisor.*)\nLemma dvdp_eq q p : (q %| p) = (p == p %/ q * q).\n\n(*This lemma provides a characterization of associated polynomials over a field. It states that two polynomials are associates if and only if there exists a non-zero constant such that one polynomial is the result of scaling the other by that constant.*)\nLemma eqpf_eq p q : reflect (exists2 c, c != 0 & p = c *: q) (p %= q).\n\n(*This lemma expresses the linearity of the polynomial remainder operation with respect to scalar multiplication of the dividend. It states that the remainder of a scaled dividend polynomial divided by a divisor polynomial is equal to the scaling constant times the remainder of the original dividend divided by the same divisor.*)\nLemma modpZl c p q : (c *: p) %% q = c *: (p %% q).\n\n(*This lemma states that dividing the product of a first and a second polynomial by the second polynomial yields the first polynomial, provided the second polynomial is not the zero polynomial.*)\nLemma mulpK p q : q != 0 -> p * q %/ q = p.\n\n(*This lemma states that dividing the product of a first and a second polynomial by the first polynomial yields the second polynomial, provided the first polynomial is not the zero polynomial.*)\nLemma mulKp p q : q != 0 -> q * p %/ q = p.\n\n(*This lemma expresses the linearity of the polynomial quotient operation with respect to scalar multiplication of the dividend. It states that the quotient of a scaled dividend polynomial divided by a divisor polynomial is equal to the scaling constant times the quotient of the original dividend divided by the same divisor.*)\nLemma divpZl c p q : (c *: p) %/ q = c *: (p %/ q).\n\n(*This lemma states that for a non-zero scalar, the remainder of a polynomial divided by the product of that scalar and another polynomial is equal to the remainder of the first polynomial divided by the second polynomial.*)\nLemma modpZr c p d : c != 0 -> p %% (c *: d) = (p %% d).\n\n(*This lemma states that for a non-zero scalar, dividing a polynomial by the product of that scalar and another polynomial is equivalent to multiplying the inverse of the scalar by the result of dividing the first polynomial by the second.*)\nLemma divpZr c p d : c != 0 -> p %/ (c *: d) = c^-1 *: (p %/ d).\n\n(*This lemma states that if two polynomials are associated, meaning they differ only by a non-zero constant factor, then their remainders after division by any third polynomial are also associated.*)\nLemma eqp_modpl d p q : p %= q -> (p %% d) %= (q %% d).\n\n(*This lemma states that if two polynomials are associated, meaning they differ only by a non-zero constant factor, then their quotients after division by any third polynomial are also associated.*)\nLemma eqp_divl d p q : p %= q -> (p %/ d) %= (q %/ d).\n\n(*This lemma states that if two polynomials are associated, meaning they differ only by a non-zero constant factor, then the remainder of a third polynomial divided by the first is associated with the remainder of the third polynomial divided by the second.*)\nLemma eqp_modpr d p q : p %= q -> (d %% p) %= (d %% q).\n\n(*This lemma states that if a first polynomial is associated with a second, and a third polynomial is associated with a fourth, then the remainder of the division of the first by the third is associated with the remainder of the division of the second by the fourth.*)\nLemma eqp_mod p1 p2 q1 q2 : p1 %= p2 -> q1 %= q2 -> p1 %% q1 %= p2 %% q2.\n\n(*This lemma states that if two polynomials are associated, meaning they differ only by a non-zero constant factor, then the quotient of a third polynomial divided by the first is associated with the quotient of that same third polynomial divided by the second.*)\nLemma eqp_divr (d m n : {poly F}) : m %= n -> (d %/ m) %= (d %/ n).\n\n(*This lemma states that if a first polynomial is associated with a second, and a third polynomial is associated with a fourth, then the quotient of the division of the first by the third is associated with the quotient of the division of the second by the fourth.*)\nLemma eqp_div p1 p2 q1 q2 : p1 %= p2 -> q1 %= q2 -> p1 %/ q1 %= p2 %/ q2.\n\n(*This lemma states that if two polynomials are associated, their greatest common divisor with any third polynomial will also be associated.*)\nLemma eqp_gdcor p q r : q %= r -> gdcop p q %= gdcop p r.\n\n(*This lemma states that if two polynomials are associated, the greatest common divisor of the first polynomial with a third polynomial is associated with the greatest common divisor of the second polynomial with that same third polynomial.*)\nLemma eqp_gdcol p q r : q %= r -> gdcop q p %= gdcop r p.\n\n(*This lemma states that for any two polynomials, their greatest common divisor computed using the rgdcop function is associated with their standard greatest common divisor.*)\nLemma eqp_rgdco_gdco q p : rgdcop q p %= gdcop q p.\n\n(*This lemma states that the polynomial remainder operation distributes over addition, meaning the remainder of the sum of two polynomials divided by a third is the sum of their individual remainders.*)\nLemma modpD d p q : (p + q) %% d = p %% d + q %% d.\n\n(*This lemma states that the remainder of the division of the additive inverse of a polynomial by another polynomial is equal to the additive inverse of their standard remainder.*)\nLemma modpN p q : (- p) %% q = - (p %% q).\n\n(*This lemma states that the remainder of the division of the additive inverse of a polynomial by another polynomial is equal to the additive inverse of their standard remainder.*)\nLemma modNp p q : (- p) %% q = - (p %% q). \n\n(*This lemma states that polynomial division distributes over addition, meaning the quotient of the sum of two polynomials divided by a third is the sum of their individual quotients.*)\nLemma divpD d p q : (p + q) %/ d = p %/ d + q %/ d.\n\n(*This lemma states that the quotient of the division of the additive inverse of a polynomial by another polynomial is equal to the additive inverse of their standard quotient.*)\nLemma divpN p q : (- p) %/ q = - (p %/ q).\n\n(*This lemma states that for three polynomials, if the size of the third is strictly less than the size of the first, then the quotient of the sum of the third and the product of the first and second, when divided by the first, is equal to the second polynomial.*)\nLemma divp_addl_mul_small d q r : size r < size d -> (q * d + r) %/ d = q.\n\n(*This lemma states that for three polynomials, if the size of the third is strictly less than the size of the first, then the remainder of the sum of the third and the product of the first and second, when divided by the first, is equal to the third polynomial.*)\nLemma modp_addl_mul_small d q r : size r < size d -> (q * d + r) %% d = r.\n\n(*This lemma states that for a non-zero polynomial divisor, the quotient of the division of a polynomial of the form (q times d plus r) by d is equal to q plus the quotient of r divided by d.*)\nLemma divp_addl_mul d q r : d != 0 -> (q * d + r) %/ d = q + r %/ d.\n\n(*This lemma states that any non-zero polynomial divided by itself results in the constant polynomial one.*)\nLemma divpp d : d != 0 -> d %/ d = 1.\n\n(*This lemma states that the size of the product of the quotient of two polynomials and the divisor polynomial is less than or equal to the size of the original dividend polynomial.*)\nLemma leq_divMp d m : size (m %/ d * d) <= size m.\n\n(*This lemma states that if a polynomial divides another polynomial, then multiplying the quotient of their division by the divisor yields the original dividend polynomial.*)\nLemma divpK d p : d %| p -> p %/ d * d = p.\n\n(*This lemma states that if a polynomial divides another polynomial, then multiplying the divisor by the quotient of their division yields the original dividend polynomial.*)\nLemma divpKC d p : d %| p -> d * (p %/ d) = p.\n\n(*This lemma states that for a non-zero polynomial divisor that divides a dividend polynomial, the proposition that a third polynomial is equal to the quotient is equivalent to the proposition that the dividend is equal to the product of the third polynomial and the divisor.*)\nLemma dvdp_eq_div d p q : d != 0 -> d %| p -> (q == p %/ d) = (q * d == p).\n\n(*This lemma states that for a non-zero polynomial divisor that divides a dividend polynomial, the proposition that the dividend is equal to the product of a third polynomial and the divisor is equivalent to the proposition that the quotient is equal to the third polynomial.*)\nLemma dvdp_eq_mul d p q : d != 0 -> d %| p -> (p == q * d) = (p %/ d == q).\n\n(*This lemma states that if a polynomial d divides a polynomial q, then multiplying another polynomial p by the quotient of q and d is equivalent to taking the quotient of the product of p and q when divided by d.*)\nLemma divp_mulA d p q : d %| q -> p * (q %/ d) = p * q %/ d.\n\n(*This lemma states that if a polynomial d divides a polynomial m, then the product of the quotient of m and d with another polynomial n is equal to the quotient of the product of m and n when divided by d.*)\nLemma divp_mulAC d m n : d %| m -> m %/ d * n = m * n %/ d.\n\n(*This lemma states that if a polynomial divides two other polynomials, then the product of the first polynomial and the quotient of the second divided by the divisor is equal to the product of the second polynomial and the quotient of the first divided by the divisor.*)\nLemma divp_mulCA d p q : d %| p -> d %| q -> p * (q %/ d) = q * (p %/ d).\n\n(*This lemma states that for a non-zero polynomial, raising it to the power of the difference of two natural numbers, where the first is greater than or equal to the second, is equivalent to dividing the polynomial raised to the first number by the polynomial raised to the second number.*)\nLemma expp_sub d m n : d != 0 -> m >= n -> (d ^+ (m - n))%N = d ^+ m %/ d ^+ n.\n\n(*This lemma states that for non-zero polynomials, the quotient of the product of a first and a second polynomial divided by the product of the first and a third polynomial is equal to the quotient of the second polynomial divided by the third.*)\nLemma divp_pmul2l d q p : d != 0 -> q != 0 -> d * p %/ (d * q) = p %/ q.\n\n(*This lemma states that for three non-zero polynomials, dividing a product of the first and second by a product of the third and second is equivalent to dividing the first by the third.*)\nLemma divp_pmul2r d p q : d != 0 -> p != 0 -> q * d %/ (p * d) = q %/ p.\n\n(*This lemma states that for three polynomials, dividing a first polynomial by a second, and then dividing the result by a third, is equivalent to dividing the first polynomial by the product of the second and third.*)\nLemma divp_divl r p q : q %/ p %/ r = q %/ (p * r).\n\n(*This lemma states that for three polynomials, successively dividing the first by the second and then by the third yields the same result as dividing the first by the third and then by the second.*)\nLemma divpAC d p q : q %/ d %/ p = q %/ p %/ d.\n\n(*This lemma defines the result of the extended Euclidean division of two polynomials as a triplet containing a zero natural number, the quotient of the division, and the remainder of the division.*)\nLemma edivp_def p q : edivp p q = (0, p %/ q, p %% q).\n\n(*This lemma states that the quotient of the division of two polynomials is equal to the result of a raw polynomial division, scaled by the inverse of the divisor's leading coefficient raised to a power determined by a scaling factor.*)\nLemma divpE p q : p %/ q = (lead_coef q)^-(rscalp p q) *: (rdivp p q).\n\n(*This lemma states that the remainder of the division of two polynomials is equal to the result of a raw polynomial remainder operation, scaled by the inverse of the divisor's leading coefficient raised to a power determined by a scaling factor.*)\nLemma modpE p q : p %% q = (lead_coef q)^-(rscalp p q) *: (rmodp p q).\n\n(*This lemma states that the scaling factor for polynomial division is always zero.*)\nLemma scalpE p q : scalp p q = 0.\n\n(*This lemma states that the polynomial divisibility predicate defined over integral domains is equivalent to the pseudo-divisibility predicate defined over commutative non-zero rings.*)\nLemma dvdpE p q : p %| q = rdvdp p q. \n\n(*This variant defines the specification for the Euclidean division of two polynomials. It holds for a given triplet of a natural number, a quotient polynomial, and a remainder polynomial if the dividend is equal to the quotient times the divisor plus the remainder, and if the divisor is non-zero, the degree of the remainder is strictly less than the degree of the divisor.*)\nVariant edivp_spec m d : nat * {poly F} * {poly F} -> Type :=\n EdivpSpec n q r of\n m = q * d + r & (d != 0) ==> (size r < size d) : edivp_spec m d (n, q, r).\n\n(*This lemma states that the result of the extended Euclidean division of two polynomials satisfies the correctness specification for polynomial Euclidean division.*)\nLemma edivpP m d : edivp_spec m d (edivp m d).\n\n(*This lemma states that if a polynomial is expressed as the sum of a product of a quotient and a divisor, and a remainder whose degree is less than the divisor's degree, then the extended Euclidean division of that polynomial by the divisor yields a triplet containing a zero natural number, that quotient, and that remainder.*)\nLemma edivp_eq d q r : size r < size d -> edivp (q * d + r) d = (0, q, r).\n\n(*This lemma states that for three polynomials, the remainder of the division of the product of the first polynomial and the remainder of the division of the second by the third, when divided by the third polynomial, is equal to the remainder of the division of the product of the first and second polynomials by the third.*)\nLemma modp_mul p q m : (p * (q %% m)) %% m = (p * q) %% m.\n\n(*This lemma states that if a value is a root of a divisor polynomial, then evaluating the remainder of a polynomial division at that value gives the same result as evaluating the dividend polynomial at that same value.*)\nLemma horner_mod p q x : root q x -> (p %% q).[x] = p.[x].\n\n(*This lemma provides a reflection between the boolean statement that a second polynomial divides a first polynomial and the existential proposition that there is a third polynomial such that the first is the product of the third and the second.*)\nLemma dvdpP p q : reflect (exists qq, p = qq * q) (q %| p).\n\n(*This lemma provides a reflection between the boolean statement that two polynomials are coprime and the existential proposition that there exist two other polynomials, their B\u00e9zout coefficients, such that their linear combination with the original polynomials equals the constant polynomial one.*)\nLemma Bezout_eq1_coprimepP p q :\n reflect (exists u, u.1 * p + u.2 * q = 1) (coprimep p q).\n\n(*This lemma states that for two polynomials, where the second is non-zero, the first polynomial divides the product of the greatest common divisor of the two polynomials and the second polynomial raised to the power of the degree of the first.*)\nLemma dvdp_gdcor p q : q != 0 -> p %| (gdcop q p) * (q ^+ size p).\n\n(*This lemma states that if a polynomial of degree at most three is divisible by another polynomial whose degree is strictly between zero and the first polynomial's degree, then the first polynomial must have a root.*)\nLemma reducible_cubic_root p q :\n size p <= 4 -> 1 < size q < size p -> q %| p -> {r | root p r}.\n\n(*This lemma states that a polynomial of degree two or three is irreducible if it has no roots in the base field.*)\nLemma cubic_irreducible p :\n 1 < size p <= 4 -> (forall x, ~~ root p x) -> irreducible_poly p.\n\nSection Multiplicity.\n\n(*This definition specifies the multiplicity of a value in a polynomial as the largest natural number power such that the polynomial factor corresponding to that value, raised to that power, divides the given polynomial.*)\nDefinition mup x q :=\n [arg max_(n > ord0 : 'I_(size q).+1 | ('X - x%:P) ^+ n %| q) n] : nat.\n\n(*This lemma states that for a non-zero polynomial, a given natural number is less than or equal to the multiplicity of a value if and only if the polynomial factor corresponding to that value, raised to the power of the natural number, divides the polynomial.*)\nLemma mup_geq x q n : q != 0 -> (n <= mup x q)%N = (('X - x%:P) ^+ n %| q).\n\n(*This lemma states that for a non-zero polynomial, the multiplicity of a value is less than or equal to a given natural number if and only if the polynomial factor corresponding to that value, raised to the power of that natural number plus one, does not divide the polynomial.*)\nLemma mup_leq x q n : q != 0 ->\n (mup x q <= n)%N = ~~ (('X - x%:P) ^+ n.+1 %| q).\n\n(*This lemma states that for a non-zero polynomial, the multiplicity of a value is strictly less than a given natural number if and only if the polynomial factor corresponding to that value, raised to the power of that natural number, does not divide the polynomial.*)\nLemma mup_ltn x q n : q != 0 -> (mup x q < n)%N = ~~ (('X - x%:P) ^+ n %| q).\n\n(*This lemma states that for a non-zero polynomial, the linear polynomial factor corresponding to a given value divides the polynomial if and only if the multiplicity of that value in the polynomial is greater than zero.*)\nLemma XsubC_dvd x q : q != 0 -> ('X - x%:P %| q) = (0 < mup x q)%N.\n\n(*This lemma states that the multiplicity of a first value in a polynomial defined as the linear factor of a second value raised to a natural number power is equal to that power if the two values are equal, and zero otherwise.*)\nLemma mup_XsubCX n x y :\n mup x (('X - y%:P) ^+ n) = (if (y == x) then n else 0)%N.\n\n(*This lemma states that if a value is not a root of a polynomial, then its multiplicity in that polynomial is zero.*)\nLemma mupNroot x q : ~~ root q x -> mup x q = 0%N.\n\n(*This lemma states that if a value is not a root of a first polynomial factor, the multiplicity of that value in the product of the first and a second polynomial is equal to its multiplicity in the second polynomial.*)\nLemma mupMr x q1 q2 : ~~ root q1 x -> mup x (q1 * q2) = mup x q2.\n\n(*This lemma states that if a value is not a root of a second polynomial factor, the multiplicity of that value in the product of a first and the second polynomial is equal to its multiplicity in the first polynomial.*)\nLemma mupMl x q1 q2 : ~~ root q2 x -> mup x (q1 * q2) = mup x q1.\n\n(*This lemma states that for two non-zero polynomials, the multiplicity of a value in their product is the sum of the multiplicities of that value in each of the two polynomials.*)\nLemma mupM x q1 q2 : q1 != 0 -> q2 != 0 ->\n mup x (q1 * q2) = (mup x q1 + mup x q2)%N.\n\n(*This lemma states that the multiplicity of a value in a polynomial formed by the product of linear factors corresponding to elements of a finite sequence of values is equal to the number of times that value appears in the sequence.*)\nLemma mu_prod_XsubC x (s : seq F) :\n mup x (\\prod_(y <- s) ('X - y%:P)) = count_mem x s.\n\n(*This lemma states a condition for the equality of two polynomials, each formed by taking the product of linear factors derived from a finite sequence of values.*)\nLemma prod_XsubC_eq (s t : seq F) :\n \\prod_(x <- s) ('X - x%:P) = \\prod_(x <- t) ('X - x%:P) -> perm_eq s t.\n\nEnd Multiplicity.\n\nSection FieldRingMap.\n\nVariable rR : nzRingType.\n\nVariable f : {rmorphism F -> rR}.\n(**)\nLocal Notation \"p ^f\" := (map_poly f p) : ring_scope.\n\nImplicit Type a b : {poly F}.\n\n(*This lemma specifies how rational polynomial division interacts with applying a ring morphism to the polynomial coefficients. It states that the triple of a scaling factor, quotient, and remainder obtained by dividing two polynomials whose coefficients have been mapped by a morphism is equal to a new triple. This new triple consists of the scaling factor from the original division, followed by the original quotient and remainder polynomials, both with their coefficients mapped by the same morphism.*)\nLemma redivp_map a b :\n redivp a^f b^f = (rscalp a b, (rdivp a b)^f, (rmodp a b)^f).\n\nEnd FieldRingMap.\n\nSection FieldMap.\n\nVariable rR : idomainType.\n\nVariable f : {rmorphism F -> rR}.\n(*This notation represents the application of a ring morphism to a polynomial, resulting in a new polynomial where each coefficient is the image of the original coefficient under the given morphism.*)\nLocal Notation \"p ^f\" := (map_poly f p) : ring_scope.\n\nImplicit Type a b : {poly F}.\n\n(*This lemma states that performing Euclidean division on two polynomials after applying a field morphism to their coefficients yields the same result as applying the morphism to the quotient and remainder obtained from dividing the original polynomials, with a zero scaling factor.*)\nLemma edivp_map a b :\n edivp a^f b^f = (0, (a %/ b)^f, (a %% b)^f).\n\n(*This lemma states that a specific scalar value derived from two polynomials, namely the coefficient of degree one in their product, remains unchanged when a field morphism is applied to the coefficients of both polynomials.*)\nLemma scalp_map p q : scalp p^f q^f = scalp p q.\n\n(*This lemma states that applying a field morphism to the coefficients of the quotient of two polynomials is equivalent to taking the quotient of the two polynomials after their coefficients have been transformed by the morphism.*)\nLemma map_divp p q : (p %/ q)^f = p^f %/ q^f.\n\n(*This lemma states that applying a field morphism to the coefficients of the remainder of a polynomial division is equivalent to computing the remainder of the division of the two polynomials after their coefficients have been transformed by the morphism.*)\nLemma map_modp p q : (p %% q)^f = p^f %% q^f.\n\n(*This lemma states that the B\u00e9zout coefficients for two polynomials that have been transformed by a field morphism are the same as the transformed B\u00e9zout coefficients of the original two polynomials.*)\nLemma egcdp_map p q :\n egcdp (map_poly f p) (map_poly f q)\n = (map_poly f (egcdp p q).1, map_poly f (egcdp p q).2).\n\n(*This lemma states that the divisibility relationship between two polynomials is preserved under a field morphism; one polynomial divides another if and only if their images under the morphism also have the same divisibility relationship.*)\nLemma dvdp_map p q : (p^f %| q^f) = (p %| q).\n\n(*This lemma states that the property of two polynomials being associated, meaning they are equal up to multiplication by a non-zero constant, is preserved under a field morphism.*)\nLemma eqp_map p q : (p^f %= q^f) = (p %= q).\n\n(*This lemma states that applying a field morphism to the coefficients of the greatest common divisor of two polynomials yields the greatest common divisor of the two polynomials after their individual coefficients have been transformed by the morphism.*)\nLemma gcdp_map p q : (gcdp p q)^f = gcdp p^f q^f.\n\n(*This lemma states that two polynomials are coprime if and only if their images under a field morphism are also coprime.*)\nLemma coprimep_map p q : coprimep p^f q^f = coprimep p q.\n\n(*This lemma shows that an auxiliary recursive function used for polynomial composition commutes with a field morphism, meaning applying the morphism to the function's result is equivalent to calling the function on polynomials whose coefficients have already been transformed.*)\nLemma gdcop_rec_map p q n : (gdcop_rec p q n)^f = gdcop_rec p^f q^f n.\n\n(*This lemma states that polynomial composition is compatible with field morphisms. Applying a morphism to the coefficients of the composed polynomial gives the same result as composing the polynomials after their coefficients have been transformed by the morphism.*)\nLemma gdcop_map p q : (gdcop p q)^f = gdcop p^f q^f.\n\nEnd FieldMap.\n\nEnd FieldDivision.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to leq_divMp.\")]\n(*A deprecated notation, now an alias for leq_divMp. It was used to represent the relationship between polynomial division and the less-than-or-equal relation.*)\nNotation leq_trunc_divp := leq_divMp.\n\nEnd Field.\n\nModule ClosedField.\n\nImport Field.\n\nSection closed.\n\nVariable F : closedFieldType.\n\n(*This lemma states that for polynomials over an algebraically closed field, if a second polynomial does not evaluate to zero at any of the roots of a first polynomial, then the two polynomials are coprime.*)\nLemma root_coprimep (p q : {poly F}) :\n (forall x, root p x -> q.[x] != 0) -> coprimep p q.\n\n(*This lemma establishes that for polynomials over an algebraically closed field, the property of being coprime is logically equivalent to the property of not sharing any common roots.*)\nLemma coprimepP (p q : {poly F}) :\n reflect (forall x, root p x -> q.[x] != 0) (coprimep p q).\n\nEnd closed.\n\nEnd ClosedField.\n\nEnd Pdiv.", - "algebra.spectral": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype choice ssrnat.\nFrom mathcomp Require Import seq div fintype bigop ssralg finset fingroup zmodp.\nFrom mathcomp Require Import poly polydiv order ssrnum matrix mxalgebra vector.\nFrom mathcomp Require Import mxpoly mxred sesquilinear.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nReserved Notation \"u '``_' i\"\n (at level 3, i at level 2, left associativity, format \"u '``_' i\").\n\nImport GRing.Theory Order.Theory Num.Theory.\nLocal Open Scope ring_scope.\nLocal Open Scope sesquilinear_scope.\n\n(*This lemma states that for any square matrix of positive dimension over a numerically closed field, there exists an eigenvalue.*)\nLemma eigenvalue_closed {C : numClosedFieldType} n (A : 'M[C]_n) : (n > 0)%N ->\n exists a, eigenvalue A a.\n\n(*This lemma states that for any sequence of pairwise commuting square matrices of positive dimension over a numerically closed field, there exists a non-zero row vector that is a common eigenvector for all matrices in the sequence.*)\nLemma common_eigenvector {C : numClosedFieldType} n (As : seq 'M[C]_n) :\n (n > 0)%N -> {in As &, forall A B, comm_mx A B} ->\n exists2 v : 'rV_n, v != 0 & all (fun A => stablemx v A) As.\n\n(*This lemma states that if two square matrices of positive dimension over a numerically closed field commute, then there exists a non-zero row vector that is a common eigenvector for both matrices.*)\nLemma common_eigenvector2 {C : numClosedFieldType}n (A B : 'M[C]_n) :\n (n > 0)%N -> A *m B = B *m A ->\n exists2 v : 'rV_n, v != 0 & (stablemx v A) && (stablemx v B).\n\n(*This notation defines the conjugate transpose of a matrix, which is obtained by taking the transpose of the matrix and then applying complex conjugation to each of its entries.*)\nNotation \"M ^t*\" := (M ^t conjC) (at level 30) : sesquilinear_scope.\n(*This notation defines the property that a matrix has all its entries belonging to the set of real numbers.*)\nNotation realmx := (mxOver Num.real).\n\n(*This lemma states that applying the conjugate transpose operation twice to any given matrix results in the original matrix.*)\nLemma trmxCK {C : numClosedFieldType} m n (A : 'M[C]_(m, n)) : A ^t* ^t* = A.\n\nSection realmx.\nContext {C : numClosedFieldType} {m n : nat}.\nImplicit Types A B : 'M[C]_(m, n).\n\n(*This lemma states that if a matrix consists entirely of real numbers, then applying complex conjugation to the matrix leaves it unchanged.*)\nLemma realmxC A : A \\is a realmx -> A ^ conjC = A.\n\n(*This lemma states that the sum of two matrices whose entries are all real numbers is also a matrix whose entries are all real numbers.*)\nLemma realmxD A B : A \\is a realmx -> B \\is a realmx -> A + B \\is a realmx.\n\n(*This lemma states that for any two matrices with real-valued entries, the real part of their complex combination, formed by adding the first matrix to the product of the imaginary unit and the second matrix, is equal to the first matrix.*)\nLemma Remx_rect : {in realmx &, forall A B, (A + 'i *: B) ^ (@Re _) = A}.\n\n(*This lemma states that for any two matrices with real-valued entries, the imaginary part of their complex combination, formed by adding the first matrix to the product of the imaginary unit and the second matrix, is equal to the second matrix.*)\nLemma Immx_rect : {in realmx &, forall A B, (A + 'i *: B) ^ (@Im _) = B}.\n\n(*This lemma states that if two complex matrices, each expressed as the sum of a real part and an imaginary part, are equal, then their respective real parts must be equal and their respective imaginary parts must be equal.*)\nLemma eqmx_ReiIm A B A' B' :\n A \\is a realmx -> B \\is a realmx -> A' \\is a realmx -> B' \\is a realmx ->\n (A + 'i *: B) = (A' + 'i *: B') -> (A, B) = (A', B').\n\nEnd realmx.\n\n(*This lemma states that a square matrix that is symmetric and contains only real numbers is also Hermitian symmetric.*)\nLemma realsym_hermsym {C : numClosedFieldType} {n} (A : 'M[C]_n) :\n A \\is symmetricmx -> A \\is a realmx -> A \\is hermsymmx.\n\n(*This lemma states that if two matrices with real entries are similar over the general linear group, they are also similar over the subgroup of invertible matrices that also have real entries.*)\nLemma real_similar {C : numClosedFieldType} {n} (A B : 'M[C]_n) :\n similar_in unitmx A B ->\n A \\is a realmx -> B \\is a realmx -> similar_in [predI realmx & unitmx] A B.\n\nSection unitarymx.\nContext {C : numClosedFieldType}.\n\n(*This definition introduces the property of a matrix being unitary, which holds if the product of the matrix with its conjugate transpose results in the identity matrix.*)\nDefinition unitarymx {m n} := [qualify X : 'M[C]_(m, n) | X *m X ^t* == 1%:M].\n(*This fact establishes that the unitary matrix predicate is a keyed property, which allows it to be used with the library's reflection and canonical structure mechanisms.*)\nFact unitarymx_key m n : pred_key (@unitarymx m n). \nCanonical unitarymx_keyed m n := KeyedQualifier (unitarymx_key m n).\n\n(*This lemma provides a reflection property, stating that a matrix is unitary if and only if the product of the matrix with its conjugate transpose is equal to the identity matrix.*)\nLemma unitarymxP m n {M : 'M[C]_(m, n)} :\n reflect (M *m M^t* = 1%:M) (M \\is unitarymx).\n\n(*This lemma states that if a matrix is post-multiplied by a unitary matrix and then by the conjugate transpose of that unitary matrix, the result is the original matrix.*)\nLemma mulmxtVK m1 m2 n (A : 'M[C]_(m1, n)) (B : 'M[C]_(n, m2)) :\n B \\is unitarymx -> A *m B *m B^t* = A.\n\n(*This lemma states that any square unitary matrix is also an invertible matrix.*)\nLemma unitarymx_unit n (M : 'M[C]_n) : M \\is unitarymx -> M \\in unitmx.\n\n(*This lemma states that the inverse of a square unitary matrix is equal to its conjugate transpose.*)\nLemma invmx_unitary n (M : 'M[C]_n) : M \\is unitarymx -> invmx M = M^t*.\n\n(*This lemma states that if a matrix is post-multiplied by the conjugate transpose of a square unitary matrix and then by that unitary matrix itself, the result is the original matrix.*)\nLemma mulmxKtV m1 m2 n (A : 'M[C]_(m1, n)) (B : 'M[C]_(m2, n)) :\n B \\is unitarymx -> m2 = n -> A *m B^t* *m B = A.\n\n(*This lemma states that the rank of a unitary matrix is equal to its number of rows.*)\nLemma mxrank_unitary m n (M : 'M[C]_(m, n)) : M \\is unitarymx -> \\rank M = m.\n\n(*This lemma states that the product of two unitary matrices is also a unitary matrix.*)\nLemma mul_unitarymx m n p (A : 'M[C]_(m, n)) (B : 'M[C]_(n, p)) :\n A \\is unitarymx -> B \\is unitarymx -> A *m B \\is unitarymx.\n\n(*This lemma states that the Moore-Penrose pseudoinverse of a square unitary matrix is equal to its conjugate transpose.*)\nLemma pinvmx_unitary n (M : 'M[C]_n) : M \\is unitarymx -> pinvmx M = M^t*.\n\n(*This lemma states that conjugating a square matrix by a unitary matrix is equivalent to pre-multiplying by the unitary matrix and post-multiplying by its conjugate transpose.*)\nLemma conjymx n (P M : 'M[C]_n) : P \\is unitarymx -> conjmx P M = P *m M *m P^t*.\n\n(*This lemma states that a square matrix is unitary if and only if its transpose is also unitary.*)\nLemma trmx_unitary n (M : 'M[C]_n) : (M ^T \\is unitarymx) = (M \\is unitarymx).\n\n(*This lemma states that a matrix is unitary if and only if its element-wise complex conjugate is also unitary.*)\nLemma conjC_unitary m n (M : 'M[C]_(m, n)) :\n (M ^ conjC \\is unitarymx) = (M \\is unitarymx).\n\n(*This lemma states that a square matrix is unitary if and only if its conjugate transpose is also unitary.*)\nLemma trmxC_unitary n (M : 'M[C]_n) : (M ^t* \\is unitarymx) = (M \\is unitarymx).\n\nEnd unitarymx.\n\nSection normalmx.\nContext {C : numClosedFieldType} {n : nat}.\n\n(*This definition introduces the property of a square matrix being normal, which holds if the matrix commutes with its own conjugate transpose.*)\nDefinition normalmx := [qualify M : 'M[C]_n | M *m M ^t* == M ^t* *m M].\n(*This fact establishes that the normal matrix predicate is a keyed property, enabling its use with the library's reflection and canonical structure mechanisms.*)\nFact normalmx_key : pred_key normalmx. \nCanonical normalmx_keyed := KeyedQualifier normalmx_key.\n\n(*This lemma provides a reflection property, stating that a square matrix is normal if and only if it commutes with its conjugate transpose.*)\nLemma normalmxP {M : 'M[C]_n} :\n reflect (M *m M ^t* = M ^t* *m M) (M \\is normalmx).\n\n(*This lemma states that any Hermitian matrix is also a normal matrix.*)\nLemma hermitian_normalmx (A : 'M[C]_n) : A \\is hermsymmx -> A \\is normalmx.\n\n(*This lemma states that any symmetric matrix whose entries are all real numbers is also a normal matrix.*)\nLemma symmetric_normalmx (A : 'M[C]_n) : A \\is symmetricmx ->\n A \\is a realmx -> A \\is normalmx.\n\nEnd normalmx.\n\nSection Spectral.\nVariable (C : numClosedFieldType).\nSet Default Proof Using \"C\".\n\n(*This definition establishes the standard Hermitian inner product, which is defined as the bilinear form associated with the identity matrix where the first vector argument is conjugated.*)\nLocal Notation dotmx_def := (form_of_matrix (@conjC _) 1%:M).\n(*This definition provides a function for computing the standard Hermitian inner product of two row vectors over a numerically closed field.*)\nDefinition dotmx n (u v : 'rV[C]_n) := dotmx_def u%R v%R.\n\nHB.instance Definition _ n := Bilinear.copy (@dotmx n) dotmx_def.\n\n(*A notation for the Hermitian inner product of two vectors.*)\nLocal Notation \"''[' u , v ]\" := (dotmx u v) : ring_scope.\n(*A notation for the squared norm of a vector, defined as the Hermitian inner product of the vector with itself.*)\nLocal Notation \"''[' u ]\" := '[u, u]%R : ring_scope.\n\nHB.instance Definition _ n := Hermitian.copy (@dotmx n) dotmx_def.\n\n(*This lemma states that the Hermitian inner product of two row vectors is equal to the single entry of the matrix resulting from multiplying the first vector by the conjugate transpose of the second vector.*)\nLemma dotmxE n (u v : 'rV[C]_n) : '[u, v] = ( u *m v ^t* ) 0 0.\n\n(*This lemma provides a characterization of a unitary matrix, stating that a matrix is unitary if and only if its set of row vectors is orthonormal, meaning the inner product of any two distinct rows is zero and the inner product of any row with itself is one.*)\nLemma row_unitarymxP m n {M : 'M[C]_(m, n)} :\n reflect (forall i j, '[row i M, row j M] = (i == j)%:R) (M \\is unitarymx).\n\n(*A notation for accessing the element at a specific column index of a row vector.*)\nLocal Notation \"u '``_' i\" := (u 0%R i).\n\n(*This fact states that the Hermitian inner product is positive-definite, meaning the inner product of any non-zero vector with itself results in a positive real number.*)\nFact dotmx_is_dotmx n (u : 'rV[C]_n) : u != 0 -> 0 < '[u].\n\n(*A notation for the orthogonal complement of the subspace spanned by the rows of a given matrix, with respect to the standard Hermitian inner product.*)\nLocal Notation \"B ^!\" :=\n (orthomx (@conjC C) (mx_of_hermitian (hermitian1mx _)) B) : matrix_set_scope.\n(*A notation representing that the row space of one matrix is orthogonal to the row space of another matrix. This holds if the row space of the first matrix is a subspace of the orthogonal complement of the row space of the second.*)\nLocal Notation \"A '_|_ B\" := (A%MS <= B^!)%MS : bool_scope.\n\n(*This lemma states that the row space of one matrix is orthogonal to the row space of another matrix if and only if the matrix product of the first matrix and the conjugate transpose of the second matrix yields the zero matrix.*)\nLemma orthomx1E m n p (A : 'M[C]_(m, n)) (B : 'M_(p, n)) :\n (A '_|_ B)%MS = (A *m B^t* == 0).\n\n(*This lemma establishes that the boolean statement asserting orthogonality between the row spaces of two matrices is equivalent to the proposition that the product of the first matrix and the conjugate transpose of the second matrix is the zero matrix.*)\nLemma orthomx1P m n p {A : 'M[C]_(m, n)} {B : 'M_(p, n)} :\n reflect (A *m B^t* = 0) (A '_|_ B).\n\n(*This lemma states that if the row space of one matrix is orthogonal to the row space of another, then the intersection of their row spaces contains only the zero vector.*)\nLemma orthomx_disj n p q (A : 'M[C]_(p, n)) (B :'M_(q, n)) :\n A '_|_ B -> (A :&: B = 0)%MS.\n\n(*This lemma states that the intersection of the row space of a matrix and its orthogonal complement contains only the zero vector.*)\nLemma orthomx_ortho_disj n p (A : 'M[C]_(p, n)) : (A :&: A^! = 0)%MS.\n\n(*This lemma states that the rank of the orthogonal complement of the row space of a matrix is equal to the total number of columns minus the rank of the original matrix.*)\nLemma rank_ortho p n (A : 'M[C]_(p, n)) : \\rank A^! = (n - \\rank A)%N.\n\n(*This lemma states that the sum of the rank of a matrix and the rank of its orthogonal complement is equal to the total number of columns in the matrix.*)\nLemma add_rank_ortho p n (A : 'M[C]_(p, n)) : (\\rank A + \\rank A^!)%N = n.\n\n(*This lemma states that the sum of the row space of a matrix and its orthogonal complement is equal to the entire vector space.*)\nLemma addsmx_ortho p n (A : 'M[C]_(p, n)) : (A + A^! :=: 1%:M)%MS.\n\n(*This lemma states that taking the orthogonal complement of the orthogonal complement of the row space of a matrix returns the original row space.*)\nLemma ortho_id p n (A : 'M[C]_(p, n)) : (A^!^! :=: A)%MS.\n\n(*This lemma states that the orthogonal complement of the row space of a first matrix is a subspace of the orthogonal complement of the row space of a second matrix if and only if the row space of the second matrix is a subspace of the row space of the first matrix.*)\nLemma submx_ortho p m n (U : 'M[C]_(p, n)) (V : 'M_(m, n)) :\n (U^! <= V^!)%MS = (V <= U)%MS.\n\n(*This definition specifies the orthogonal projection matrix onto the row space of a given matrix. The projection is defined onto this row space along its orthogonal complement.*)\nDefinition proj_ortho p n (U : 'M[C]_(p, n)) := proj_mx <>%MS U^!%MS.\n\n(*This lemma states that the row space of any matrix is a subspace of the sum of the row space of another matrix and its orthogonal complement.*)\nLemma sub_adds_genmx_ortho (p m n : nat) (U : 'M[C]_(p, n)) (W : 'M_(m, n)) :\n (W <= <> + U^!)%MS.\n\nLocal Hint Resolve sub_adds_genmx_ortho : core.\n\n(*This lemma states that the intersection of the row space of a matrix and its orthogonal complement is the trivial subspace containing only the zero vector.*)\nLemma cap_genmx_ortho p n (U : 'M[C]_(p, n)) : (<> :&: U^!)%MS = 0.\n\nLocal Hint Resolve cap_genmx_ortho : core.\n\n(*This lemma states that multiplying a matrix by the orthogonal projection matrix for a given subspace results in a matrix whose row space is contained within that subspace.*)\nLemma proj_ortho_sub p m n (U : 'M_(p, n)) (W : 'M_(m, n)) :\n (W *m proj_ortho U <= U)%MS.\n\n(*This lemma states that subtracting the orthogonal projection of a matrix onto a subspace from the original matrix results in a matrix whose row space is contained within the orthogonal complement of that subspace.*)\nLemma proj_ortho_compl_sub p m n (U : 'M_(p, n)) (W : 'M_(m, n)) :\n (W - W *m proj_ortho U <= U^!)%MS.\n\n(*This lemma states that if the row space of a matrix is a subspace of a given subspace, then multiplying that matrix by the orthogonal projection matrix for that subspace yields the original matrix.*)\nLemma proj_ortho_id p m n (U : 'M_(p, n)) (W : 'M_(m, n)) :\n (W <= U)%MS -> W *m proj_ortho U = W.\n\n(*This lemma states that if the row space of a matrix is a subspace of the orthogonal complement of a given subspace, then multiplying the matrix by the orthogonal projection matrix for that subspace yields the zero matrix.*)\nLemma proj_ortho_0 p m n (U : 'M_(p, n)) (W : 'M_(m, n)) :\n (W <= U^!)%MS -> W *m proj_ortho U = 0.\n\n(*This lemma states that for any matrix, the sum of its projection onto a given subspace and its projection onto the orthogonal complement of that subspace is equal to the original matrix.*)\nLemma add_proj_ortho p m n (U : 'M_(p, n)) (W : 'M_(m, n)) :\n W *m proj_ortho U + W *m proj_ortho U^!%MS = W.\n\n(*This lemma states that an orthogonal projection matrix is idempotent, meaning that multiplying the projection matrix by itself results in the same projection matrix.*)\nLemma proj_ortho_proj m n (U : 'M_(m, n)) : let P := proj_ortho U in P *m P = P.\n\n(*This lemma states that the matrix subspace spanned by the orthogonal projection onto the row space of a given matrix is equal to the row space of the matrix itself.*)\nLemma proj_orthoE p n (U : 'M_(p, n)) : (proj_ortho U :=: U)%MS.\n\n(*This lemma states that if the row space of a matrix is orthogonal to the row space of a second matrix, then for any two other matrices, the matrix product of the first with the orthogonal projection of the first space has a row space that is orthogonal to the row space of the matrix product of the second with the orthogonal projection of the second space.*)\nLemma orthomx_proj_mx_ortho p p' m m' n\n (A : 'M_(p, n)) (A' : 'M_(p', n))\n (W : 'M_(m, n)) (W' : 'M_(m', n)) :\n A '_|_ A' -> W *m proj_ortho A '_|_ W' *m proj_ortho A'.\n\n(*This lemma provides the existence proof for the Gram-Schmidt process on the rows of a complex matrix. It states that for any matrix with at least as many columns as rows, there exists a unitary matrix such that for every row index, the row of the original matrix lies in the vector subspace spanned by the rows of the unitary matrix up to that same index, and the inner product of corresponding rows is a non-negative real number.*)\nLemma schmidt_subproof m n (A : 'M[C]_(m, n)) : (m <= n)%N ->\n exists2 B : 'M_(m, n), B \\is unitarymx & [forall i : 'I_m,\n (row i A <= (\\sum_(k < m | (k <= i)%N) <>))%MS\n && ('[row i A, row i B] >= 0) ].\n\n(*This definition provides the Gram-Schmidt orthogonalization of the rows of a complex matrix. If the input matrix has at least as many columns as rows, it returns a new matrix with orthonormal rows that spans the same sequence of nested subspaces as the original matrix's rows. Otherwise, it returns the original matrix unchanged.*)\nDefinition schmidt m n (A : 'M[C]_(m, n)) :=\n if (m <= n)%N =P true is ReflectT le_mn\n then projT1 (sig2_eqW (schmidt_subproof A le_mn))\n else A.\n\n(*This lemma states that applying the `schmidt` orthogonalization function to a complex matrix with no more rows than columns results in a unitary matrix.*)\nLemma schmidt_unitarymx m n (A : 'M[C]_(m, n)) : (m <= n)%N ->\n schmidt A \\is unitarymx.\n\nHint Resolve schmidt_unitarymx : core.\n\n(*This lemma states that for any row index of a given complex matrix, that row is contained within the vector subspace spanned by the rows of the `schmidt`-orthogonalized matrix up to and including the same index.*)\nLemma row_schmidt_sub m n (A : 'M[C]_(m, n)) i :\n (row i A <= (\\sum_(k < m | (k <= i)%N) <>))%MS.\n\n(*This lemma states that for any given complex matrix and any row index, the inner product of that row from the original matrix and the corresponding row from its `schmidt`-orthogonalized version is a non-negative real number.*)\nLemma form1_row_schmidt m n (A : 'M[C]_(m, n)) i :\n '[row i A, row i (schmidt A)] >= 0.\n\n(*This lemma states that the row space of any given complex matrix is a subspace of the row space of its `schmidt`-orthogonalized version.*)\nLemma schmidt_sub m n (A : 'M[C]_(m, n)) : (A <= schmidt A)%MS.\n\nHint Resolve schmidt_sub : core.\n\n(*This lemma states that if the rows of a complex matrix form a spanning set for the entire vector space, then the row space of that matrix is equal to the row space of its `schmidt`-orthogonalized version.*)\nLemma eqmx_schmidt_full m n (A : 'M[C]_(m, n)) :\n row_full A -> (schmidt A :=: A)%MS.\n\n(*This lemma states that if the rows of a complex matrix are linearly independent, then its row space is equal to the row space of its `schmidt`-orthogonalized version.*)\nLemma eqmx_schmidt_free m n (A : 'M[C]_(m, n)) :\n row_free A -> (schmidt A :=: A)%MS.\n\n(*This definition constructs a complete unitary matrix from a given complex matrix. It does this by finding orthonormal bases for both the row space of the input matrix and its orthogonal complement using the `schmidt` process, and then combining them into a single square matrix.*)\nDefinition schmidt_complete m n (V : 'M[C]_(m, n)) :=\n col_mx (schmidt (row_base V)) (schmidt (row_base V^!%MS)).\n\n(*This lemma states that the matrix constructed by the `schmidt_complete` definition is a unitary matrix.*)\nLemma schmidt_complete_unitarymx m n (V : 'M[C]_(m, n)) :\n schmidt_complete V \\is unitarymx.\n\n(*This lemma states that any finite sequence of mutually commuting square complex matrices can be simultaneously triangularized by a single unitary matrix.*)\nLemma cotrigonalization n (As : seq 'M[C]_n) :\n {in As &, forall A B, comm_mx A B} ->\n cotrigonalizable_in (@unitarymx C n n) As.\n\n(*This theorem, known as Schur's decomposition theorem, states that any non-zero-sized square complex matrix is unitarily similar to an upper triangular matrix.*)\nTheorem Schur n (A : 'M[C]_n) : (n > 0)%N ->\n trigonalizable_in (@unitarymx C n n) A.\n\n(*This lemma states that if two square complex matrices commute, then there exists a single unitary matrix that simultaneously triangularizes both of them via a similarity transformation.*)\nLemma cotrigonalization2 n (A B : 'M[C]_n) : A *m B = B *m A ->\n exists2 P : 'M[C]_n, P \\is unitarymx &\n similar_trig P A && similar_trig P B.\n\n(*This theorem establishes the core of the spectral theorem for complex matrices. It states that a square complex matrix is normal if and only if there exists a unitary matrix and a vector of eigenvalues such that the original matrix can be expressed as the product of the inverse of the unitary matrix, a diagonal matrix formed from the eigenvalues, and the unitary matrix itself.*)\nTheorem orthomx_spectral_subproof n {A : 'M[C]_n} : reflect\n (exists2 sp : 'M_n * 'rV_n,\n sp.1 \\is unitarymx &\n A = invmx sp.1 *m diag_mx sp.2 *m sp.1)\n (A \\is normalmx).\n\n(*This definition extracts the unitary matrix from the spectral decomposition of a square complex matrix. If the input matrix is normal, it returns the unitary matrix whose columns are the eigenvectors. If the matrix is not normal, it returns the identity matrix.*)\nDefinition spectralmx n (A : 'M[C]_n) : 'M[C]_n :=\n if @orthomx_spectral_subproof _ A is ReflectT P\n then (projT1 (sig2_eqW P)).1 else 1%:M.\n\n(*This definition extracts the vector of eigenvalues from the spectral decomposition of a square complex matrix. If the input matrix is normal, it returns a row vector containing its eigenvalues. If the matrix is not normal, it returns a zero vector.*)\nDefinition spectral_diag n (A : 'M[C]_n) : 'rV_n :=\n if @orthomx_spectral_subproof _ A is ReflectT P\n then (projT1 (sig2_eqW P)).2 else 0.\n\n(*This lemma states that the matrix returned by the `spectralmx` function is always a unitary matrix.*)\nLemma spectral_unitarymx n (A : 'M[C]_n) : spectralmx A \\is unitarymx.\n\n(*This lemma states that the matrix returned by the `spectralmx` function is an invertible matrix.*)\nLemma spectral_unit n (A : 'M[C]_n) : spectralmx A \\in unitmx.\n\n(*This theorem states the main property of the spectral decomposition functions. For a normal square complex matrix, it asserts that the matrix is equal to the product of the inverse of the matrix `spectralmx`, the diagonal matrix formed from the vector `spectral_diag`, and the matrix `spectralmx` itself.*)\nTheorem orthomx_spectralP {n} {A : 'M[C]_n}\n (P := spectralmx A) (sp := spectral_diag A) :\n reflect (A = invmx P *m diag_mx sp *m P) (A \\is normalmx).\n\n(*This lemma states that for any Hermitian matrix, the vector of its eigenvalues, as computed by the spectral decomposition, contains only real numbers.*)\nLemma hermitian_spectral_diag_real n (A : 'M[C]_n) : A \\is hermsymmx ->\n spectral_diag A \\is a realmx.", - "algebra.archimedean": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype bigop order ssralg poly ssrnum ssrint.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope ring_scope.\nImport Order.TTheory GRing.Theory Num.Theory.\n\nModule Num.\nImport Num.Def.\n\n(*A mixin record that endows a numerical domain with floor, ceiling, and truncation functions. This structure provides operations to map elements of the domain to integers and natural numbers, along with properties defining these mappings, such as the floor of a real number being the greatest integer less than or equal to it. It also includes predicates to test whether an element represents an integer or a natural number.*)\nHB.mixin Record NumDomain_hasFloorCeilTruncn R of Num.NumDomain R := {\n floor : R -> int;\n ceil : R -> int;\n truncn : R -> nat;\n int_num_subdef : pred R;\n nat_num_subdef : pred R;\n floor_subproof :\n forall x,\n if x \\is Rreal then (floor x)%:~R <= x < (floor x + 1)%:~R\n else floor x == 0;\n ceil_subproof : forall x, ceil x = - floor (- x);\n truncn_subproof : forall x, truncn x = if floor x is Posz n then n else 0;\n int_num_subproof : forall x, reflect (exists n, x = n%:~R) (int_num_subdef x);\n nat_num_subproof : forall x, reflect (exists n, x = n%:R) (nat_num_subdef x);\n}.\n\n#[short(type=\"archiNumDomainType\")]\n(*This structure defines an Archimedean numerical domain, which is a numerical domain equipped with floor, ceiling, and truncation functions. These functions provide a way to relate elements of the domain to integers, a characteristic property of Archimedean structures.*)\nHB.structure Definition ArchiNumDomain :=\n { R of NumDomain_hasFloorCeilTruncn R & Num.NumDomain R }.\n\nModule ArchiNumDomainExports.\nBind Scope ring_scope with ArchiNumDomain.sort.\nEnd ArchiNumDomainExports.\nHB.export ArchiNumDomainExports.\n\n#[short(type=\"archiNumFieldType\")]\n(*This structure defines an Archimedean numerical field. It is a numerical field that additionally provides floor, ceiling, and truncation functions, allowing for integer-based approximations of its elements.*)\nHB.structure Definition ArchiNumField :=\n { R of NumDomain_hasFloorCeilTruncn R & Num.NumField R }.\n\nModule ArchiNumFieldExports.\nBind Scope ring_scope with ArchiNumField.sort.\nEnd ArchiNumFieldExports.\nHB.export ArchiNumFieldExports.\n\n#[short(type=\"archiClosedFieldType\")]\n(*This structure defines an Archimedean closed field. It combines the properties of a closed field, where all non-constant polynomials have roots, with the Archimedean property, formalized through the existence of floor and ceiling functions.*)\nHB.structure Definition ArchiClosedField :=\n { R of NumDomain_hasFloorCeilTruncn R & Num.ClosedField R }.\n\nModule ArchiClosedFieldExports.\nBind Scope ring_scope with ArchiClosedField.sort.\nEnd ArchiClosedFieldExports.\nHB.export ArchiClosedFieldExports.\n\n#[short(type=\"archiRealDomainType\")]\n(*This structure defines an Archimedean real domain. It is a numerical domain where all elements are real numbers, and which is also equipped with floor, ceiling, and truncation functions.*)\nHB.structure Definition ArchiRealDomain :=\n { R of NumDomain_hasFloorCeilTruncn R & Num.RealDomain R }.\n\nModule ArchiRealDomainExports.\nBind Scope ring_scope with ArchiRealDomain.sort.\nEnd ArchiRealDomainExports.\nHB.export ArchiRealDomainExports.\n\n#[short(type=\"archiRealFieldType\")]\n(*This structure defines an Archimedean real field. It is a numerical field of real numbers that also includes floor, ceiling, and truncation operations, reflecting its Archimedean nature.*)\nHB.structure Definition ArchiRealField :=\n { R of NumDomain_hasFloorCeilTruncn R & Num.RealField R }.\n\nModule ArchiRealFieldExports.\nBind Scope ring_scope with ArchiRealField.sort.\nEnd ArchiRealFieldExports.\nHB.export ArchiRealFieldExports.\n\n#[short(type=\"archiRcfType\")]\n(*This structure defines an Archimedean real closed field. It combines the properties of a real closed field, such as the existence of square roots for positive elements and roots for odd-degree polynomials, with the Archimedean property implemented via floor and ceiling functions.*)\nHB.structure Definition ArchiRealClosedField :=\n { R of NumDomain_hasFloorCeilTruncn R & Num.RealClosedField R }.\n\nModule ArchiRealClosedFieldExports.\nBind Scope ring_scope with ArchiRealClosedField.sort.\nEnd ArchiRealClosedFieldExports.\nHB.export ArchiRealClosedFieldExports.\n\nSection Def.\nContext {R : archiNumDomainType}.\n\nDefinition nat_num : qualifier 1 R := [qualify a x : R | nat_num_subdef x].\nDefinition int_num : qualifier 1 R := [qualify a x : R | int_num_subdef x].\n(*This definition computes a natural number that is strictly greater than the absolute value of a given element from an Archimedean numerical domain. The computation involves taking the absolute value of the input, finding its integer part as a natural number via truncation, and then incrementing the result by one.*)\nDefinition bound (x : R) := (truncn `|x|).+1.\n\nEnd Def.\n\nArguments floor {R} : rename, simpl never.\nArguments ceil {R} : rename, simpl never.\nArguments truncn {R} : rename, simpl never.\nArguments nat_num {R} : simpl never.\nArguments int_num {R} : simpl never.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn.\")]\n(*This notation is an alias for the truncation function `truncn`. It takes a number from an Archimedean structure and returns the greatest natural number less than or equal to it if the number is non-negative, and returns zero otherwise.*)\nNotation trunc := truncn.\n\nModule Def.\nExport ssrnum.Num.Def.\n\n(*This function computes the integer part of a non-negative number from an Archimedean numerical domain, returning it as a natural number. For an input greater than or equal to zero, it returns the largest integer less than or equal to that input. For a negative input, it returns zero.*)\nNotation truncn := truncn.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn.\")]\n(*A deprecated notation that computes the integer part of a non-negative number from an Archimedean numerical domain, returning it as a natural number. For an input greater than or equal to zero, it returns the largest integer less than or equal to that input. For a negative input, it returns zero.*)\nNotation trunc := truncn.\n(*A notation for the function that returns the greatest integer less than or equal to a given number.*)\nNotation floor := floor.\n(*A notation for the function that returns the smallest integer that is greater than or equal to a given number.*)\nNotation ceil := ceil.\n(*A notation for the type of natural numbers when used in a numerical context.*)\nNotation nat_num := nat_num.\n(*A notation for the type of integers when used in a numerical context.*)\nNotation int_num := int_num.\n(*A notation for a function that, for any given number in an Archimedean domain, returns an integer that is strictly greater than it.*)\nNotation archi_bound := bound.\n\nEnd Def.\n\nModule intArchimedean.\nSection intArchimedean.\n\nImplicit Types n : int.\n\n(*This lemma states a property of the embedding of integers into a real-like number system. It asserts that for an integer representable as a real number, its value is strictly less than that of the next integer. If not representable, the lemma asserts the integer is zero.*)\nLemma floorP n : if n \\is Rreal then n%:~R <= n < (n + 1)%:~R else n == 0.\n\n(*This lemma provides a computable proof that any integer, when embedded into a real-like number domain, is equal to the embedding of some integer.*)\nLemma intrP n : reflect (exists m, n = m%:~R) true.\n\n(*This lemma provides a computable proof establishing that an integer is non-negative if and only if it is equal to the embedding of some natural number into a real-like domain.*)\nLemma natrP n : reflect (exists m, n = m%:R) (0 <= n).\n\nEnd intArchimedean.\nEnd intArchimedean.\n\n#[export]\nHB.instance Definition _ :=\n @NumDomain_hasFloorCeilTruncn.Build int id id _ xpredT Rnneg_pred\n intArchimedean.floorP (fun=> esym (opprK _)) (fun=> erefl)\n intArchimedean.intrP intArchimedean.natrP.\n\nModule Import Theory.\nExport ssrnum.Num.Theory.\n\nSection ArchiNumDomainTheory.\n\nVariable R : archiNumDomainType.\nImplicit Types x y z : R.\n\n(*A notation for a generic function that converts a number to a natural number. For a non-negative input, the function returns its integer part as a natural number, and for a negative input, it returns zero.*)\nLocal Notation truncn := (@truncn R).\n(*This definition introduces the floor function, which computes the greatest integer less than or equal to a given number.*)\nLocal Notation floor := (@floor R).\n(*This definition introduces the ceiling function, which computes the smallest integer greater than or equal to a given number.*)\nLocal Notation ceil := (@ceil R).\n(*This definition introduces the `nat_num` predicate, which determines whether a given ring element corresponds to a natural number.*)\nLocal Notation nat_num := (@Def.nat_num R).\n(*This definition introduces the `int_num` predicate, which determines whether a given ring element corresponds to an integer.*)\nLocal Notation int_num := (@Def.int_num R).\n\n(*This lemma states the defining property of the floor function: for any real number, its floor is the integer that is less than or equal to the number, while the number itself is strictly less than the floor plus one. If the input is not a real number, its floor is zero.*)\nLocal Lemma floorP x :\n if x \\is Rreal then (floor x)%:~R <= x < (floor x + 1)%:~R else floor x == 0.\n\n(*This lemma states that the floor of a number is equal to the additive inverse of the ceiling of the additive inverse of that number.*)\nLemma floorNceil x : floor x = - ceil (- x).\n\n(*This lemma states that the ceiling of a number is equal to the additive inverse of the floor of the additive inverse of that number.*)\nLemma ceilNfloor x : ceil x = - floor (- x).\n\n(*This lemma provides an equivalence between the truncation of a number to a natural number and its floor. It states that the truncation is the natural number corresponding to the floor of the number if the floor is non-negative, and zero otherwise.*)\nLemma truncEfloor x : truncn x = if floor x is Posz n then n else 0.\n\n(*This lemma establishes that a ring element satisfies the `nat_num` predicate if and only if there exists a natural number that is equal to that ring element.*)\nLemma natrP x : reflect (exists n, x = n%:R) (x \\is a nat_num).\n\n(*This lemma establishes that a ring element satisfies the `int_num` predicate if and only if there exists an integer that is equal to that ring element.*)\nLemma intrP x : reflect (exists m, x = m%:~R) (x \\is a int_num).\n\n(*This lemma states that any integer, when embedded into the ring, satisfies the property of being an integer number within that ring.*)\nLemma intr_int m : m%:~R \\is a int_num. \n(*This lemma states that any natural number, when embedded into the ring, satisfies the property of being a natural number within that ring.*)\nLemma natr_nat n : n%:R \\is a nat_num. \n#[local] Hint Resolve intr_int natr_nat : core.\n\n(*This lemma states that if a ring element corresponds to an integer, then it must belong to any subring of the carrier ring.*)\nLemma rpred_int_num (S : subringClosed R) x : x \\is a int_num -> x \\in S.\n\n(*This lemma states that if a ring element corresponds to a natural number, then it must belong to any semiring of the carrier ring.*)\nLemma rpred_nat_num (S : semiringClosed R) x : x \\is a nat_num -> x \\in S.\n\n(*This lemma states that the additive identity, zero, is an integer number.*)\nLemma int_num0 : 0 \\is a int_num. \n(*This lemma states that the multiplicative identity, one, is an integer number.*)\nLemma int_num1 : 1 \\is a int_num. \n(*This lemma states that the additive identity, zero, is a natural number.*)\nLemma nat_num0 : 0 \\is a nat_num. \n(*This lemma states that the multiplicative identity, one, is a natural number.*)\nLemma nat_num1 : 1 \\is a nat_num. \n#[local] Hint Resolve int_num0 int_num1 nat_num0 nat_num1 : core.\n\n(*This fact asserts that the set of all elements satisfying the `int_num` predicate forms a subring.*)\nFact int_num_subring : subring_closed int_num.\n\n#[export]\nHB.instance Definition _ := GRing.isSubringClosed.Build R int_num_subdef\n int_num_subring.\n\n(*This fact asserts that the set of all elements satisfying the `nat_num` predicate forms a semiring.*)\nFact nat_num_semiring : semiring_closed nat_num.\n\n#[export]\n(*This lemma states that the set of natural numbers is a subset of the set of real numbers.*)\nLemma Rreal_nat : {subset nat_num <= Rreal}. \n\n(*This lemma states that the set of natural numbers is a subset of the set of integer numbers.*)\nLemma intr_nat : {subset nat_num <= int_num}.\n\n(*This lemma states that the set of integer numbers is a subset of the set of real numbers.*)\nLemma Rreal_int : {subset int_num <= Rreal}. \n\n(*This lemma states that a ring element is an integer number if and only if it is a natural number or its additive inverse is a natural number.*)\nLemma intrE x : (x \\is a int_num) = (x \\is a nat_num) || (- x \\is a nat_num).\n\n(*This lemma states that for any integer number, the square of its absolute value is equal to the square of the number itself.*)\nLemma intr_normK x : x \\is a int_num -> `|x| ^+ 2 = x ^+ 2.\n\n(*This lemma states that for any natural number, the square of its absolute value is equal to the square of the number itself.*)\nLemma natr_normK x : x \\is a nat_num -> `|x| ^+ 2 = x ^+ 2.\n\n(*This lemma states that the absolute value of any integer number is a natural number.*)\nLemma natr_norm_int x : x \\is a int_num -> `|x| \\is a nat_num.\n\n(*This lemma states that any natural number is greater than or equal to zero.*)\nLemma natr_ge0 x : x \\is a nat_num -> 0 <= x.\n\n(*This lemma states that for a natural number, being strictly greater than zero is equivalent to not being equal to zero.*)\nLemma natr_gt0 x : x \\is a nat_num -> (0 < x) = (x != 0).\n\n(*This lemma states that a ring element is a natural number if and only if it is an integer number and is greater than or equal to zero.*)\nLemma natrEint x : (x \\is a nat_num) = (x \\is a int_num) && (0 <= x).\n\n(*This lemma states that a non-negative real number is an integer if and only if it is a natural number.*)\nLemma intrEge0 x : 0 <= x -> (x \\is a int_num) = (x \\is a nat_num).\n\n(*This lemma states that any integer is equal to its absolute value multiplied by its sign, where the sign is negative one if the integer is negative and one otherwise.*)\nLemma intrEsign x : x \\is a int_num -> x = (-1) ^+ (x < 0)%R * `|x|.\n\n(*This lemma states that the absolute value of a real number which is a natural number is equal to the number itself.*)\nLemma norm_natr x : x \\is a nat_num -> `|x| = x.\n\n(*This lemma states that an integer raised to an even natural number power results in a real number that is a natural number.*)\nLemma natr_exp_even x n : ~~ odd n -> x \\is a int_num -> x ^+ n \\is a nat_num.\n\n(*This lemma states that the absolute value of any non-zero integer is greater than or equal to one.*)\nLemma norm_intr_ge1 x : x \\is a int_num -> x != 0 -> 1 <= `|x|.\n\n(*This lemma states that the square of any non-zero integer is greater than or equal to one.*)\nLemma sqr_intr_ge1 x : x \\is a int_num -> x != 0 -> 1 <= x ^+ 2.\n\n(*This lemma states that any integer is less than or equal to its square.*)\nLemma intr_ler_sqr x : x \\is a int_num -> x <= x ^+ 2.\n\n(*This lemma states that for any real number, the number itself is greater than or equal to the real representation of its floor, and strictly less than the real representation of its floor plus one.*)\nLemma real_floor_itv x : x \\is Rreal -> (floor x)%:~R <= x < (floor x + 1)%:~R.\n\n(*This lemma states that the real representation of the floor of a real number is less than or equal to the real number itself.*)\nLemma real_floor_le x : x \\is Rreal -> (floor x)%:~R <= x.\n\n(*This lemma states that any real number is strictly less than the real representation of its integer floor plus one.*)\nLemma real_floorD1_gt x : x \\is Rreal -> x < (floor x + 1)%:~R.\n\n(*This lemma states that if a real number is greater than or equal to the real representation of an integer and strictly less than the real representation of that integer plus one, then the floor of the real number is equal to that integer.*)\nLemma floor_def x m : m%:~R <= x < (m + 1)%:~R -> floor x = m.\n\n(*This lemma states that for a real number and an integer, the integer being less than or equal to the floor of the real number is equivalent to the real representation of the integer being less than or equal to the real number itself.*)\nLemma real_floor_ge_int_tmp x n : x \\is Rreal -> (n <= floor x) = (n%:~R <= x).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use real_floor_ge_int_tmp instead.\")]\n(*This lemma states that for a real number and an integer, the real representation of the integer being less than or equal to the real number is equivalent to the integer being less than or equal to the floor of the real number.*)\nLemma real_floor_ge_int x n : x \\is Rreal -> (n%:~R <= x) = (n <= floor x).\n\n(*This lemma states that for a real number and an integer, the floor of the real number being strictly less than the integer is equivalent to the real number being strictly less than the real representation of the integer.*)\nLemma real_floor_lt_int x n : x \\is Rreal -> (floor x < n) = (x < n%:~R).\n\n(*This lemma states that for a real number and an integer, the floor of the real number is equal to the integer if and only if the real number is greater than or equal to the real representation of the integer and strictly less than the real representation of the integer plus one.*)\nLemma real_floor_eq x n : x \\is Rreal ->\n (floor x == n) = (n%:~R <= x < (n + 1)%:~R).\n\n(*This lemma states that the floor function is non-decreasing, meaning that if one real number is less than or equal to another, the floor of the first number is less than or equal to the floor of the second.*)\nLemma le_floor : {homo floor : x y / x <= y}.\n\n(*This lemma states that for any real number that is an integer, applying the floor function and then coercing the resulting integer back to a real number yields the original real number.*)\nLemma intrKfloor : cancel intr floor.\n\n(*This lemma states that the real number representation of any natural number is an integer.*)\nLemma natr_int n : n%:R \\is a int_num.\n\n#[local] Hint Resolve natr_int : core.\n\n(*This lemma states that a real number is an integer if and only if it is equal to the real number representation of its floor.*)\nLemma intrEfloor x : x \\is a int_num = ((floor x)%:~R == x).\n\n(*This lemma states that applying the floor function to the real representation of an integer yields the original integer.*)\nLemma floorK : {in int_num, cancel floor intr}.\n\n(*This lemma states that the floor of the real number zero is the integer zero.*)\nLemma floor0 : floor 0 = 0. \n(*This lemma states that the floor of the real number one is the integer one.*)\nLemma floor1 : floor 1 = 1. \n#[local] Hint Resolve floor0 floor1 : core.\n\n(*This lemma states that the floor of a sum involving the real representation of an integer and a real number is the sum of that integer and the floor of the real number.*)\nLemma real_floorDzr : {in int_num & Rreal, {morph floor : x y / x + y}}.\n\n(*This lemma states that the floor of a sum involving a real number and the real representation of an integer is the sum of the floor of the real number and that integer.*)\nLemma real_floorDrz : {in Rreal & int_num, {morph floor : x y / x + y}}.\n\n(*This lemma states that the floor of the negation of the real representation of an integer is equal to the negation of that integer.*)\nLemma floorN : {in int_num, {morph floor : x / - x}}.\n\n(*This lemma states a multiplicative property for the floor function involving an integer, asserting that the floor of the product of the real representation of an integer and a real number is equal to the product of that integer and the floor of the real number.*)\nLemma floorM : {in int_num &, {morph floor : x y / x * y}}.\n\n(*This lemma states that the floor of the real representation of an integer raised to a natural number power is equal to the integer itself raised to that same power.*)\nLemma floorX n : {in int_num, {morph floor : x / x ^+ n}}.\n\n(*This lemma states that for any real number, its floor is greater than or equal to zero if and only if the real number itself is greater than or equal to zero.*)\nLemma real_floor_ge0 x : x \\is Rreal -> (0 <= floor x) = (0 <= x).\n\n(*This lemma states that the floor of a real number is strictly less than zero if and only if the real number itself is strictly less than zero.*)\nLemma floor_lt0 x : (floor x < 0) = (x < 0).\n\n(*This lemma states that for any real number, its floor is less than or equal to zero if and only if the real number is strictly less than one.*)\nLemma real_floor_le0 x : x \\is Rreal -> (floor x <= 0) = (x < 1).\n\n(*This lemma states that for a real number, its floor is strictly greater than zero if and only if the number itself is greater than or equal to one.*)\nLemma floor_gt0 x : (floor x > 0) = (x >= 1).\n\n(*This lemma states that for a real number, its floor is not equal to zero if and only if the number is either strictly less than zero or greater than or equal to one.*)\nLemma floor_neq0 x : (floor x != 0) = (x < 0) || (x >= 1).\n\n(*This lemma states that for any polynomial with integer coefficients, applying the coefficient-wise injection into real numbers followed by applying the floor function to each coefficient yields the original polynomial.*)\nLemma floorpK : {in polyOver int_num, cancel (map_poly floor) (map_poly intr)}.\n\n(*This lemma states that if a polynomial with real coefficients has the property that all its coefficients are integral, then there exists a corresponding polynomial with integer coefficients.*)\nLemma floorpP (p : {poly R}) :\n p \\is a polyOver int_num -> {q | p = map_poly intr q}.\n\n(*This lemma establishes the defining interval for the ceiling of a real number, stating that the number is strictly greater than its ceiling minus one and less than or equal to its ceiling.*)\nLemma real_ceil_itv x : x \\is Rreal -> (ceil x - 1)%:~R < x <= (ceil x)%:~R.\n\n(*This lemma states that any real number is strictly greater than its ceiling minus one.*)\nLemma real_ceilB1_lt x : x \\is Rreal -> (ceil x - 1)%:~R < x.\n\n(*This lemma states that any real number is less than or equal to its ceiling, when the ceiling is viewed as a real number.*)\nLemma real_ceil_ge x : x \\is Rreal -> x <= (ceil x)%:~R.\n\n(*This lemma provides the definitional property for the ceiling function: if a real number falls in the interval that is open on the left at an integer minus one and closed on the right at that integer, then the ceiling of the number is that integer.*)\nLemma ceil_def x m : (m - 1)%:~R < x <= m%:~R -> ceil x = m.\n\n(*This lemma states that for a real number and an integer, the ceiling of the real number is less than or equal to the integer if and only if the real number itself is less than or equal to the representation of that integer as a real number.*)\nLemma real_ceil_le_int_tmp x n : x \\is Rreal -> (ceil x <= n) = (x <= n%:~R).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use real_ceil_le_int_tmp instead.\")]\n(*This deprecated lemma states that for a real number and an integer, the real number is less than or equal to the representation of the integer as a real number if and only if the ceiling of the real number is less than or equal to that integer.*)\nLemma real_ceil_le_int x n : x \\is Rreal -> x <= n%:~R = (ceil x <= n).\n\n(*This lemma states that for a real number and an integer, the integer is strictly less than the ceiling of the real number if and only if the representation of the integer as a real number is strictly less than the real number.*)\nLemma real_ceil_gt_int x n : x \\is Rreal -> (n < ceil x) = (n%:~R < x).\n\n(*This lemma states that for a real number and an integer, the ceiling of the real number is equal to the integer if and only if the real number is strictly greater than the integer minus one and less than or equal to the integer.*)\nLemma real_ceil_eq x n : x \\is Rreal ->\n (ceil x == n) = ((n - 1)%:~R < x <= n%:~R).\n\n(*This lemma establishes that the ceiling function is monotonic, meaning that if one real number is less than or equal to another, the ceiling of the first is less than or equal to the ceiling of the second.*)\nLemma le_ceil_tmp : {homo ceil : x y / x <= y}.\n\n(*This lemma registers the injectivity of the function that maps integers to real numbers, which implies that it can be cancelled from the left side of an equality.*)\nLemma intrKceil : cancel intr ceil.\n\n(*This lemma states that a real number is an integer if and only if its ceiling, when viewed as a real number, is equal to the original number.*)\nLemma intrEceil x : x \\is a int_num = ((ceil x)%:~R == x).\n\n(*This lemma states that the ceiling function is a left inverse for the injection from integers to real numbers. That is, for any integer, taking its real representation and then its ceiling returns the original integer.*)\nLemma ceilK : {in int_num, cancel ceil intr}.\n\n(*This lemma states that the ceiling of the real number zero is the integer zero.*)\nLemma ceil0 : ceil 0 = 0. \n(*This lemma states that the ceiling of the real number one is the integer one.*)\nLemma ceil1 : ceil 1 = 1. \n#[local] Hint Resolve ceil0 ceil1 : core.\n\n(*This lemma establishes a property of the ceiling function with respect to addition, stating that the ceiling of the sum of an integer (as a real) and a real number is equal to the sum of that integer and the ceiling of the real number.*)\nLemma real_ceilDzr : {in int_num & Rreal, {morph ceil : x y / x + y}}.\n\n(*This lemma establishes a property of the ceiling function with respect to addition, stating that the ceiling of the sum of a real number and an integer (as a real) is equal to the sum of the ceiling of the real number and that integer.*)\nLemma real_ceilDrz : {in Rreal & int_num, {morph ceil : x y / x + y}}.\n\n(*This lemma states that the ceiling function commutes with negation for integer inputs; the ceiling of the negation of an integer (as a real) is the negation of that integer.*)\nLemma ceilN : {in int_num, {morph ceil : x / - x}}.\n\n(*This lemma states that the ceiling function is a homomorphism with respect to multiplication over the integers. That is, the ceiling of the product of two integers is equal to the product of their ceilings.*)\nLemma ceilM : {in int_num &, {morph ceil : x y / x * y}}.\n\n(*This lemma states that for an integer base and a natural number exponent, the ceiling of the integer raised to the power (as reals) is equal to the result of raising the ceiling of the integer to that same power.*)\nLemma ceilX n : {in int_num, {morph ceil : x / x ^+ n}}.\n\n(*This lemma states that for any real number, its ceiling is non-negative if and only if the number itself is strictly greater than negative one.*)\nLemma real_ceil_ge0 x : x \\is Rreal -> (0 <= ceil x) = (-1 < x).\n\n(*This lemma states that for a real number, its ceiling is negative if and only if the number itself is less than or equal to negative one.*)\nLemma ceil_lt0 x : (ceil x < 0) = (x <= -1).\n\n(*This lemma states that for any real number, its ceiling is less than or equal to zero if and only if the number itself is less than or equal to zero.*)\nLemma real_ceil_le0 x : x \\is Rreal -> (ceil x <= 0) = (x <= 0).\n\n(*This lemma states that for a real number, its ceiling is strictly positive if and only if the number itself is strictly positive.*)\nLemma ceil_gt0 x : (ceil x > 0) = (x > 0).\n\n(*This lemma states that for a real number, its ceiling is non-zero if and only if the number is either less than or equal to negative one or strictly greater than zero.*)\nLemma ceil_neq0 x : (ceil x != 0) = (x <= -1) || (x > 0).\n\n(*This lemma states the relationship between the ceiling and floor functions: for any real number, its ceiling is equal to its floor if the number is an integer, and is equal to its floor plus one otherwise.*)\nLemma real_ceil_floor x : x \\is Rreal ->\n ceil x = floor x + (x \\isn't a int_num).\n\n(*This lemma states that the `truncn` function, which produces a natural number from a real number, is equivalent to the following: for a non-negative real number, it is the floor of the number converted to a natural number; for a negative real number, it is zero.*)\nLemma truncn_floor x : truncn x = if 0 <= x then `|floor x|%N else 0%N.\n\n(*This lemma provides a property of the truncation of a real number. It states that if the number is non-negative, its truncation converted to a real number is less than or equal to the original number, which in turn is strictly less than the real number representation of the truncation plus one. If the number is negative, its truncation is the natural number zero.*)\nLocal Lemma truncnP x :\n if 0 <= x then (truncn x)%:R <= x < (truncn x).+1%:R else truncn x == 0%N.\n\n(*This lemma states that for any non-negative real number, its truncation, when converted back to a real number, is less than or equal to the original number, and the original number is strictly less than its truncation plus one.*)\nLemma truncn_itv x : 0 <= x -> (truncn x)%:R <= x < (truncn x).+1%:R.\n\n(*This lemma establishes an equivalence, stating that the real number representation of the truncation of a given real number is less than or equal to the original number if and only if the original number is non-negative.*)\nLemma truncn_le x : (truncn x)%:R <= x = (0 <= x).\n\n(*This lemma states that any real number is strictly less than the real number representation of its truncation incremented by one.*)\nLemma real_truncnS_gt x : x \\is Rreal -> x < (truncn x).+1%:R.\n\n(*This lemma provides a definitional property for the truncation function. It states that if a real number is greater than or equal to a given natural number and strictly less than that natural number plus one, then the truncation of the real number is equal to that natural number.*)\nLemma truncn_def x n : n%:R <= x < n.+1%:R -> truncn x = n.\n\n(*This lemma relates the comparison of a natural number with the truncation of a non-negative real number. It states that for a non-negative real number, a given natural number is less than or equal to its truncation if and only if the real representation of that natural number is less than or equal to the real number itself.*)\nLemma truncn_ge_nat x n : 0 <= x -> (n <= truncn x)%N = (n%:R <= x).\n\n(*This lemma establishes an equivalence for strict inequality involving truncation. It asserts that a natural number is strictly less than the truncation of a real number if and only if that natural number plus one, viewed as a real number, is less than or equal to the original real number.*)\nLemma truncn_gt_nat x n : (n < truncn x)%N = (n.+1%:R <= x).\n\n(*This lemma relates the truncation of a non-negative real number to a strict upper bound. It states that the truncation of a non-negative real number is strictly less than a given natural number if and only if the real number itself is strictly less than the real representation of that natural number.*)\nLemma truncn_lt_nat x n : 0 <= x -> (truncn x < n)%N = (x < n%:R).\n\n(*This lemma provides an equivalence for comparing the truncation of a real number. It states that for any real number, its truncation is less than or equal to a given natural number if and only if the real number is strictly less than that natural number plus one, viewed as a real number.*)\nLemma real_truncn_le_nat x n : x \\is Rreal -> (truncn x <= n)%N = (x < n.+1%:R).\n\n(*This lemma provides the condition for the truncation of a non-negative real number to be equal to a specific natural number. It asserts that this equality holds if and only if the real number is greater than or equal to the natural number and strictly less than the natural number plus one.*)\nLemma truncn_eq x n : 0 <= x -> (truncn x == n) = (n%:R <= x < n.+1%:R).\n\n(*This lemma states that the truncation function is non-decreasing. Specifically, if one real number is less than or equal to another, then the truncation of the first number is less than or equal to the truncation of the second number.*)\nLemma le_truncn : {homo truncn : x y / x <= y >-> (x <= y)%N}.\n\n(*This lemma states that the truncation function is the left inverse of the canonical embedding of natural numbers into the real numbers, meaning that truncating the real representation of a natural number returns the original natural number.*)\nLemma natrK : cancel (GRing.natmul 1) truncn.\n\n(*This lemma establishes a condition for a real number to be equivalent to a natural number. It asserts that a real number represents a natural number if and only if the real number representation of its truncation is equal to the original real number.*)\nLemma natrEtruncn x : (x \\is a nat_num) = ((truncn x)%:R == x).\n\n(*This lemma asserts an Archimedean property, stating that any non-negative real number is strictly less than the real value corresponding to its integer bound.*)\nLemma archi_boundP x : 0 <= x -> x < (bound x)%:R.\n\n(*This lemma states that the truncation function is the left inverse of the canonical embedding of natural numbers into the real numbers, meaning that truncating the real representation of any natural number returns the original number.*)\nLemma truncnK : {in nat_num, cancel truncn (GRing.natmul 1)}.\n\n(*This lemma states that the truncation of the real number zero is the natural number zero.*)\nLemma truncn0 : truncn 0 = 0%N. \n(*This lemma states that the truncation of the real number one is the natural number one.*)\nLemma truncn1 : truncn 1 = 1%N. \n#[local] Hint Resolve truncn0 truncn1 : core.\n\n(*This lemma asserts that the truncation function distributes over addition for real numbers that are representations of natural numbers; the truncation of the sum of two such numbers is equal to the sum of their individual truncations as natural numbers.*)\nLemma truncnD :\n {in nat_num & Rnneg, {morph truncn : x y / x + y >-> (x + y)%N}}.\n\n(*This lemma asserts that the truncation function distributes over multiplication for real numbers that are representations of natural numbers; the truncation of the product of two such numbers is equal to the product of their individual truncations as natural numbers.*)\nLemma truncnM : {in nat_num &, {morph truncn : x y / x * y >-> (x * y)%N}}.\n\n(*This lemma asserts that the truncation function commutes with exponentiation for a base that is a real number representation of a natural number and a natural number exponent; the truncation of the power is equal to the truncated base raised to the same exponent as natural numbers.*)\nLemma truncnX n : {in nat_num, {morph truncn : x / x ^+ n >-> (x ^ n)%N}}.\n\n(*This lemma provides a condition for the truncation of a real number to be positive. It states that the truncation is strictly greater than zero if and only if the real number itself is greater than or equal to one.*)\nLemma truncn_gt0 x : (0 < truncn x)%N = (1 <= x).\n\n(*This lemma provides a boolean reflection of the property that the truncation of a real number is zero. It establishes that the truncation of a real number is equal to zero is logically equivalent to the real number not being greater than or equal to one.*)\nLemma truncn0Pn x : reflect (truncn x = 0%N) (~~ (1 <= x)).\n\n(*This lemma states that truncation commutes with finite sums of real numbers that are each representations of natural numbers; the real number representation of the sum of the truncations is equal to the sum of the original real numbers.*)\nLemma sum_truncnK I r (P : pred I) F : (forall i, P i -> F i \\is a nat_num) ->\n (\\sum_(i <- r | P i) truncn (F i))%:R = \\sum_(i <- r | P i) F i.\n\n(*This lemma states that truncation commutes with finite products of real numbers that are each representations of natural numbers; the real number representation of the product of the truncations is equal to the product of the original real numbers.*)\nLemma prod_truncnK I r (P : pred I) F : (forall i, P i -> F i \\is a nat_num) ->\n (\\prod_(i <- r | P i) truncn (F i))%:R = \\prod_(i <- r | P i) F i.\n\n(*This lemma describes the structure of a finite sum of real numbers that equals one, where each term in the sum is known to be a representation of a natural number. It asserts that there must exist exactly one index for which the corresponding term is one, while all other terms satisfying the summation predicate are zero.*)\nLemma natr_sum_eq1 (I : finType) (P : pred I) (F : I -> R) :\n (forall i, P i -> F i \\is a nat_num) -> \\sum_(i | P i) F i = 1 ->\n {i : I | [/\\ P i, F i = 1 & forall j, j != i -> P j -> F j = 0]}.\n\n(*This lemma states that if the product of two real numbers, both of which represent natural numbers, is equal to one, then it must be the case that both of the original numbers are equal to one.*)\nLemma natr_mul_eq1 x y :\n x \\is a nat_num -> y \\is a nat_num -> (x * y == 1) = (x == 1) && (y == 1).\n\n(*This lemma states that if a finite product of real numbers is equal to one, and each factor is known to represent a natural number, then every factor in the product that satisfies the given predicate must be equal to one.*)\nLemma natr_prod_eq1 (I : finType) (P : pred I) (F : I -> R) :\n (forall i, P i -> F i \\is a nat_num) -> \\prod_(i | P i) F i = 1 ->\n forall i, P i -> F i = 1.\n\nVariables (U V : lmodType R) (f : {additive U -> V}).\n\n(*This lemma states that for any additive function between two modules, the function commutes with scalar multiplication when the scalar is an element of the base ring that represents a natural number.*)\nLemma raddfZ_nat a u : a \\is a nat_num -> f (a *: u) = a *: f u.\n\n(*This lemma states that any additively closed subset of a module is also closed under scalar multiplication by ring elements that represent natural numbers.*)\nLemma rpredZ_nat (S : addrClosed V) :\n {in nat_num & S, forall z u, z *: u \\in S}.\n\n(*This lemma states that for any additive function between two modules, the function commutes with scalar multiplication when the scalar is an element of the base ring that represents an integer.*)\nLemma raddfZ_int a u : a \\is a int_num -> f (a *: u) = a *: f u.\n\n(*This lemma states that for any set that is closed under integer-module operations, the subset of its elements that are also integer representatives is closed under multiplication.*)\nLemma rpredZ_int (S : zmodClosed V) :\n {in int_num & S, forall z u, z *: u \\in S}.\n\nImplicit Type nu : {rmorphism R -> R}.\n\n(*This lemma states that any ring automorphism on an Archimedean domain fixes all elements that correspond to natural numbers.*)\nLemma aut_natr nu : {in nat_num, nu =1 id}.\n\n(*This lemma states that any ring automorphism on an Archimedean domain fixes all elements that correspond to integers.*)\nLemma aut_intr nu : {in int_num, nu =1 id}.\n\nEnd ArchiNumDomainTheory.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn_itv.\")]\n(*A deprecated notation for a lemma stating that for any non-negative real number, the number is greater than or equal to its integer truncation and strictly less than its integer truncation plus one.*)\nNotation trunc_itv := truncn_itv.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn_def.\")]\n(*A deprecated notation for the definition of the integer truncation of a real number.*)\nNotation trunc_def := truncn_def.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncnK.\")]\n(*A deprecated notation for a lemma providing a cancellation rule for the truncation function, stating that truncating a non-negative real number shifted by a natural number is equivalent to shifting the truncation of the original number by that same natural number.*)\nNotation truncK := truncnK.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn0.\")]\n(*A deprecated notation for a lemma stating that the integer truncation of zero is zero.*)\nNotation trunc0 := truncn0.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn1.\")]\n(*A deprecated notation for a lemma stating that the integer truncation of one is one.*)\nNotation trunc1 := truncn1.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncnD.\")]\n(*A deprecated notation for a lemma stating that the integer truncation of a non-negative real number plus one is equal to one plus the truncation of the original number.*)\nNotation truncD := truncnD.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncnM.\")]\n(*A deprecated notation for a lemma that provides a rule for the integer truncation of a product of a non-negative real number and a natural number, expressing it in terms of the truncation of the real number and the truncation of the product of its fractional part.*)\nNotation truncM := truncnM.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncnX.\")]\n(*A deprecated notation for a lemma stating that for any non-negative real number that is an integer, the integer truncation of the number raised to a natural number power is equal to the integer truncation of the number, itself raised to that same power.*)\nNotation truncX := truncnX.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn_gt0.\")]\n(*A deprecated notation for a lemma stating that the integer truncation of a real number is positive if and only if the real number is greater than or equal to one.*)\nNotation trunc_gt0 := truncn_gt0.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn0Pn.\")]\n(*A deprecated notation for a lemma stating that the integer truncation of a real number is zero if and only if the number is non-negative and strictly less than one.*)\nNotation trunc0Pn := truncn0Pn.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to sum_truncnK.\")]\n(*A deprecated notation for a lemma relating the integer truncation of a sum of non-negative real numbers to the sum of their individual truncations.*)\nNotation sum_truncK := sum_truncnK.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to prod_truncnK.\")]\n(*A deprecated notation for a lemma that provides a rule for the integer truncation of a product of real numbers.*)\nNotation prod_truncK := prod_truncnK.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to truncn_floor.\")]\n(*A deprecated notation for a lemma stating that for any non-negative real number, its integer truncation, when viewed as an integer-valued real, is equal to its floor.*)\nNotation trunc_floor := truncn_floor.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to real_floor_le.\")]\n(*A deprecated notation for a lemma stating that any real number is greater than or equal to its floor.*)\nNotation real_ge_floor := real_floor_le.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to real_floorD1_gt.\")]\n(*A deprecated notation for a lemma stating that any real number is strictly less than its floor plus one.*)\nNotation real_lt_succ_floor := real_floorD1_gt.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to real_ceilB1_lt.\")]\n(*A deprecated notation for a lemma stating that any real number is strictly greater than its ceiling minus one.*)\nNotation real_gt_pred_ceil := real_floorD1_gt.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to real_ceil_ge.\")]\n(*A deprecated notation for a lemma stating that any real number is less than or equal to its ceiling.*)\nNotation real_le_ceil := real_ceil_ge.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to le_floor.\")]\n(*A deprecated notation for a lemma stating that an integer is less than or equal to the floor of a real number if and only if the integer, when viewed as a real number, is less than or equal to that real number.*)\nNotation floor_le := le_floor.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to le_ceil.\")]\n(*A deprecated notation for a lemma asserting an equivalence related to the ceiling function, likely that the ceiling of a real number is less than or equal to an integer if and only if the real number itself is less than or equal to that integer.*)\nNotation ceil_le := le_ceil_tmp.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to natrEtruncn.\")]\n(*A deprecated notation for a lemma stating that if a real number corresponds to a natural number, then it is equal to its own integer truncation cast back to a real number.*)\nNotation natrE := natrEtruncn.\n\nArguments natrK {R} _%_N.\nArguments intrKfloor {R}.\nArguments intrKceil {R}.\nArguments natrP {R x}.\nArguments intrP {R x}.\n#[global] Hint Resolve truncn0 truncn1 : core.\n#[global] Hint Resolve floor0 floor1 : core.\n#[global] Hint Resolve ceil0 ceil1 : core.\n#[global] Hint Extern 0 (is_true (_%:R \\is a nat_num)) => apply: natr_nat : core.\n#[global] Hint Extern 0 (is_true (_%:R \\in nat_num_subdef)) => apply: natr_nat : core.\n#[global] Hint Extern 0 (is_true (_%:~R \\is a int_num)) => apply: intr_int : core.\n#[global] Hint Extern 0 (is_true (_%:~R \\in int_num_subdef)) => apply: intr_int : core.\n#[global] Hint Extern 0 (is_true (_%:R \\is a int_num)) => apply: natr_int : core.\n#[global] Hint Extern 0 (is_true (_%:R \\in int_num_subdef)) => apply: natr_int : core.\n#[global] Hint Extern 0 (is_true (0 \\is a nat_num)) => apply: nat_num0 : core.\n#[global] Hint Extern 0 (is_true (0 \\in nat_num_subdef)) => apply: nat_num0 : core.\n#[global] Hint Extern 0 (is_true (1 \\is a nat_num)) => apply: nat_num1 : core.\n#[global] Hint Extern 0 (is_true (1 \\in int_num_subdef)) => apply: nat_num1 : core.\n#[global] Hint Extern 0 (is_true (0 \\is a int_num)) => apply: int_num0 : core.\n#[global] Hint Extern 0 (is_true (0 \\in int_num_subdef)) => apply: int_num0 : core.\n#[global] Hint Extern 0 (is_true (1 \\is a int_num)) => apply: int_num1 : core.\n#[global] Hint Extern 0 (is_true (1 \\in int_num_subdef)) => apply: int_num1 : core.\n\nSection ArchiRealDomainTheory.\n\nVariables (R : archiRealDomainType).\nImplicit Type x : R.\n\n(*This lemma states that if the bitwise bound of a real number is less than or equal to a given natural number, then the real number is strictly less than two raised to the power of that natural number.*)\nLemma upper_nthrootP x i : (bound x <= i)%N -> x < 2%:R ^+ i.\n\n(*This lemma states that any non-negative real number is strictly less than its integer truncation plus one.*)\nLemma truncnS_gt x : x < (truncn x).+1%:R.\n\n(*This lemma states that the integer truncation of a non-negative real number is less than or equal to a given natural number if and only if the real number is strictly less than that natural number plus one.*)\nLemma truncn_le_nat x n : (truncn x <= n)%N = (x < n.+1%:R).\n\n(*This lemma states that any real number is greater than or equal to its floor and strictly less than its floor plus one.*)\nLemma floor_itv x : (floor x)%:~R <= x < (floor x + 1)%:~R.\n\n(*This lemma states that any real number is greater than or equal to its floor.*)\nLemma floor_le_tmp x : (floor x)%:~R <= x. \n\n(*This lemma states that any real number is strictly less than its floor plus one.*)\nLemma floorD1_gt x : x < (floor x + 1)%:~R.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use floor_ge_int_tmp instead.\")]\n(*A deprecated lemma stating that an integer is less than or equal to the floor of a real number if and only if that integer, viewed as a real number, is less than or equal to the real number.*)\nLemma floor_ge_int x n : n%:~R <= x = (n <= floor x).\n\n(*This lemma states that an integer is less than or equal to the floor of a real number if and only if the real number representation of that integer is less than or equal to the given real number.*)\nLemma floor_ge_int_tmp x n : (n <= floor x) = (n%:~R <= x).\n\n(*This lemma states that the floor of a real number is strictly less than an integer if and only if the real number itself is strictly less than the real number representation of that integer.*)\nLemma floor_lt_int x n : (floor x < n) = (x < n%:~R).\n\n(*This lemma states that the floor of a real number is equal to a given integer if and only if the real number is greater than or equal to the real representation of the integer and strictly less than the real representation of the next integer.*)\nLemma floor_eq x n : (floor x == n) = (n%:~R <= x < (n + 1)%:~R).\n\n(*This lemma establishes that the floor function preserves addition over the integers.*)\nLemma floorDzr : {in @int_num R, {morph floor : x y / x + y}}.\n\n(*This lemma states that adding an integer to a real number before taking the floor is equivalent to taking the floor of the real number and then adding the integer.*)\nLemma floorDrz x y : y \\is a int_num -> floor (x + y) = floor x + floor y.\n\n(*This lemma states that the floor of a real number is non-negative if and only if the real number itself is non-negative.*)\nLemma floor_ge0 x : (0 <= floor x) = (0 <= x).\n\n(*This lemma states that the floor of a real number is less than or equal to zero if and only if the real number is strictly less than one.*)\nLemma floor_le0 x : (floor x <= 0) = (x < 1).\n\n(*This lemma states that a real number is strictly greater than the real representation of its ceiling minus one, and less than or equal to the real representation of its ceiling.*)\nLemma ceil_itv x : (ceil x - 1)%:~R < x <= (ceil x)%:~R.\n\n(*This lemma states that a real number is strictly greater than the real representation of its ceiling minus one.*)\nLemma ceilB1_lt x : (ceil x - 1)%:~R < x.\n\n(*This lemma states that a real number is always less than or equal to the real representation of its ceiling.*)\nLemma ceil_ge x : x <= (ceil x)%:~R. \n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use ceil_le_int_tmp instead.\")]\n(*This lemma, now deprecated, states that a real number is less than or equal to the real representation of an integer if and only if the ceiling of that real number is less than or equal to the integer.*)\nLemma ceil_le_int x n : x <= n%:~R = (ceil x <= n).\n\n(*This lemma states that the ceiling of a real number is less than or equal to an integer if and only if the real number itself is less than or equal to the real representation of that integer.*)\nLemma ceil_le_int_tmp x n : (ceil x <= n) = (x <= n%:~R).\n\n(*This lemma states that an integer is strictly less than the ceiling of a real number if and only if the real representation of the integer is strictly less than the real number.*)\nLemma ceil_gt_int x n : (n < ceil x) = (n%:~R < x).\n\n(*This lemma states that the ceiling of a real number is equal to a given integer if and only if the real number is strictly greater than the real representation of the previous integer and less than or equal to the real representation of the given integer.*)\nLemma ceil_eq x n : (ceil x == n) = ((n - 1)%:~R < x <= n%:~R).\n\n(*This lemma establishes that the ceiling function preserves addition over the integers.*)\nLemma ceilDzr : {in @int_num R, {morph ceil : x y / x + y}}.\n\n(*This lemma states that adding an integer to a real number before taking the ceiling is equivalent to taking the ceiling of the real number and then adding the integer.*)\nLemma ceilDrz x y : y \\is a int_num -> ceil (x + y) = ceil x + ceil y.\n\n(*This lemma states that the ceiling of a real number is non-negative if and only if the real number is strictly greater than negative one.*)\nLemma ceil_ge0 x : (0 <= ceil x) = (-1 < x).\n\n(*This lemma states that the ceiling of a real number is less than or equal to zero if and only if the real number itself is less than or equal to zero.*)\nLemma ceil_le0 x : (ceil x <= 0) = (x <= 0).\n\n(*This lemma states that the ceiling of a real number equals its floor if the number is an integer, and equals its floor plus one otherwise.*)\nLemma ceil_floor x : ceil x = floor x + (x \\isn't a int_num).\n\nEnd ArchiRealDomainTheory.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to floor_le_tmp.\")]\n(*This notation provides a deprecated alias for the lemma `floor_le_tmp`.*)\nNotation ge_floor := floor_le_tmp.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to floorD1_gt.\")]\n(*This notation provides a deprecated alias for the lemma `floorD1_gt`.*)\nNotation lt_succ_floor := floorD1_gt.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to ceilB1_lt.\")]\n(*This notation provides a deprecated alias for the lemma `ceilB1_lt`.*)\nNotation gt_pred_ceil := ceilB1_lt.\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to ceil_ge.\")]\n(*This notation provides a deprecated alias for the lemma `ceil_ge`.*)\nNotation le_ceil := ceil_ge.\n\nSection ArchiNumFieldTheory.\n\nVariables (R : archiNumFieldType) (nu : {rmorphism R -> R}).\n\n(*This lemma states that for a ring automorphism on an Archimedean number field, applying the automorphism to an element preserves the property of that element being a natural number.*)\nLemma natr_aut x : (nu x \\is a nat_num) = (x \\is a nat_num).\n\n(*This lemma states that for a ring automorphism on an Archimedean number field, applying the automorphism to an element preserves the property of that element being an integer.*)\nLemma intr_aut x : (nu x \\is a int_num) = (x \\is a int_num).\n\nEnd ArchiNumFieldTheory.\n\nSection ArchiClosedFieldTheory.\n\nVariable R : archiClosedFieldType.\n\nImplicit Type x : R.\n\n(*This lemma states that in a real closed field, the conjugate of an element that is a natural number is the element itself.*)\nLemma conj_natr x : x \\is a nat_num -> x^* = x.\n\n(*This lemma states that in a real closed field, the conjugate of an element that is an integer is the element itself.*)\nLemma conj_intr x : x \\is a int_num -> x^* = x.\n\nEnd ArchiClosedFieldTheory.\n\nSection ZnatPred.\n\n(*This lemma states that an integer qualifies as a natural number if and only if it is greater than or equal to zero.*)\nLemma Znat_def (n : int) : (n \\is a nat_num) = (0 <= n).\n\n(*This lemma provides a boolean reflection, asserting that an integer is classified as a natural number if and only if there exists a corresponding value of the standard natural number type.*)\nLemma ZnatP (m : int) : reflect (exists n : nat, m = n) (m \\is a nat_num).\n\nEnd ZnatPred.\n\nEnd Theory.\n\n(*This factory construct provides a mechanism to build a record indicating that a numerical domain possesses a natural number truncation function.*)\nHB.factory Record NumDomain_hasTruncn R of Num.NumDomain R := {\n trunc : R -> nat;\n nat_num : pred R;\n int_num : pred R;\n truncP : forall x,\n if 0 <= x then (trunc x)%:R <= x < (trunc x).+1%:R else trunc x == 0;\n natrE : forall x, nat_num x = ((trunc x)%:R == x);\n intrE : forall x, int_num x = nat_num x || nat_num (- x);\n}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NumDomain_hasTruncn instead.\")]\nNotation NumDomain_isArchimedean R := (NumDomain_hasTruncn R) (only parsing).\n\nModule NumDomain_isArchimedean.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use NumDomain_hasTruncn.Build instead.\")]\nNotation Build T U := (NumDomain_hasTruncn.Build T U) (only parsing).\nEnd NumDomain_isArchimedean.\n\nHB.builders Context R of NumDomain_hasTruncn R.\n\n(*This lemma states that for any non-negative number, its value lies in a half-open interval where the lower bound is the representation of its truncation as a real number, and the upper bound is the representation of its truncation plus one as a real number.*)\nFact trunc_itv x : 0 <= x -> (trunc x)%:R <= x < (trunc x).+1%:R.\n\n(*This definition introduces the floor function, which computes the greatest integer that is less than or equal to a given real number.*)\nDefinition floor (x : R) : int :=\n if 0 <= x then Posz (trunc x)\n else if x < 0 then - Posz (trunc (- x) + ~~ int_num x) else 0.\n\n(*This lemma states that for any real number, its value is greater than or equal to the representation of its floor as a real number and strictly less than the representation of its floor plus one as a real number.*)\nFact floorP x :\n if x \\is Rreal then (floor x)%:~R <= x < (floor x + 1)%:~R else floor x == 0.\n\n(*This lemma provides an alternative definition for the truncation of a number, stating that it is equal to the natural number corresponding to its floor if the floor is non-negative, and zero otherwise.*)\nFact truncE x : trunc x = if floor x is Posz n then n else 0.\n\n(*This lemma provides a rule for computing the truncation of a number, stating that if the number is greater than or equal to the real representation of a natural number and strictly less than the real representation of that natural number plus one, then its truncation is that natural number.*)\nFact trunc_def x n : n%:R <= x < n.+1%:R -> trunc x = n.\n\n(*This lemma asserts that the truncation function acts as a left inverse to the function that converts a natural number into its real number representation, meaning that truncating the real representation of a natural number yields the original natural number.*)\nFact natrK : cancel (GRing.natmul 1) trunc.\n\n(*This lemma establishes an equivalence between the boolean predicate identifying a number as an integer and the proposition that this number is the representation of some integer in the real domain.*)\nFact intrP x : reflect (exists n, x = n%:~R) (int_num x).\n\n(*This lemma establishes an equivalence between the boolean predicate identifying a number as a natural number and the proposition that this number is the representation of some natural number in the real domain.*)\nFact natrP x : reflect (exists n, x = n%:R) (nat_num x).\n\nHB.instance Definition _ :=\n @NumDomain_hasFloorCeilTruncn.Build R floor _ trunc int_num nat_num\n floorP (fun=> erefl) truncE intrP natrP.\n\nHB.end.\n\n(*This factory constructs a number domain with a truncation function from a number domain that satisfies the Archimedean axiom, which guarantees that for any number, there exists a larger natural number.*)\nHB.factory Record NumDomain_bounded_isArchimedean R of Num.NumDomain R := {\n archi_bound_subproof : Num.archimedean_axiom R\n}.\n\nHB.builders Context R of NumDomain_bounded_isArchimedean R.\n Implicit Type x : R.\n\n(*This definition denotes a function that, for any given number, returns a natural number that is guaranteed by the Archimedean axiom to be strictly greater than the given number.*)\n Definition bound x := sval (sigW (archi_bound_subproof x)).\n\n(*This lemma states that for any non-negative number, its value is strictly less than the representation of the natural number provided by the 'bound' function as a real number.*)\n Lemma boundP x : 0 <= x -> x < (bound x)%:R.\n \n\n(*This lemma proves the existence of a natural number that serves as the integer part for any given non-negative number; specifically, it shows there is a natural number whose representation as a real is less than or equal to the given number, which in turn is strictly less than the representation of that natural number plus one as a real.*)\n Fact truncn_subproof x : {m | 0 <= x -> m%:R <= x < m.+1%:R }.\n \n\n(*This definition introduces a truncation function that returns the integer part of a non-negative number by extracting it from an existence proof, and returns zero for negative numbers.*)\n Definition truncn x := if 0 <= x then sval (truncn_subproof x) else 0%N.\n\n(*This lemma states the defining property of the 'truncn' function. For a non-negative number, its value is greater than or equal to the representation of its truncation as a real number and strictly less than the representation of its truncation plus one as a real number. For a negative number, its truncation is zero.*)\n Lemma truncnP x :\n if 0 <= x then (truncn x)%:R <= x < (truncn x).+1%:R else truncn x == 0%N.\n \n\n(*This notation introduces 'nat' as an alias for the predicate 'nat_num', which checks whether a number from a number domain corresponds to a natural number.*)\nNotation nat := nat_num.\n(*This notation introduces 'int' as an alias for the predicate 'int_num', which checks whether a number from a number domain corresponds to an integer.*)\nNotation int := int_num.\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use Num.ArchiRealDomain instead.\")]\nNotation ArchiDomain T := (ArchiRealDomain T).\nModule ArchiDomain.\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use Num.ArchiRealDomain.type instead.\")]\n(*This deprecated notation provides a shorthand for the carrier type of an Archimedean structure, such as a domain or a field.*)\nNotation type := ArchiRealDomain.type.\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use Num.ArchiRealDomain.copy instead.\")]\nNotation copy T C := (ArchiRealDomain.copy T C).\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use Num.ArchiRealDomain.on instead.\")]\nNotation on T := (ArchiRealDomain.on T).\nEnd ArchiDomain.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use Num.ArchiRealField instead.\")]\nNotation ArchiField T := (ArchiRealField T).\nModule ArchiField.\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use Num.ArchiRealField.type instead.\")]\n(*This notation provides a shorthand for `ArchiRealField.type`, which is the canonical type for elements of an Archimedean real field.*)\nNotation type := ArchiRealField.type.\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use Num.ArchiRealField.copy instead.\")]\nNotation copy T C := (ArchiRealField.copy T C).\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use Num.ArchiRealField.on instead.\")]\nNotation on T := (ArchiRealField.on T).\nEnd ArchiField.\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use real_floorDzr instead.\")]\n(*This deprecated notation is an alias for the floor function, which computes the greatest integer that is less than or equal to a given real number.*)\nNotation floorD := real_floorDzr.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use real_ceilDzr instead.\")]\n(*This deprecated notation is an alias for the ceiling function, which computes the smallest integer that is greater than or equal to a given real number.*)\nNotation ceilD := real_ceilDzr.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use real_ceilDzr instead.\")]\n(*This deprecated notation is an alias for the ceiling function, which computes the smallest integer that is greater than or equal to a given real number.*)\nNotation real_ceilD := real_ceilDzr.\n\nEnd Num.\n\nExport Num.Exports.\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use archiRealDomainType instead.\")]\n(*This deprecated notation is a parsing-only alias for the type of Archimedean real integral domains. Such a structure is an ordered integral domain that is densely ordered and satisfies the Archimedean property.*)\nNotation archiDomainType := archiRealDomainType (only parsing).\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use archiRealFieldType instead.\")]\n(*This deprecated notation is a parsing-only alias for the type of Archimedean real fields. Such a structure is an ordered field that is densely ordered and satisfies the Archimedean property.*)", - "algebra.mxalgebra": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype finfun bigop finset fingroup perm order.\nFrom mathcomp Require Import div prime binomial ssralg finalg zmodp matrix.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope matrix_set_scope.\n\nImport GroupScope.\nImport GRing.Theory.\nLocal Open Scope ring_scope.\n\nReserved Notation \"\\rank A\" (at level 10, A at level 8, format \"\\rank A\").\nReserved Notation \"A ^C\" (format \"A ^C\").\n\n(*A notation for the type of matrices having a specified number of rows and one more than a specified number of columns, often used to represent affine transformations.*)\nNotation \"''A_' ( m , n )\" := 'M_(m, n ^ 2)\n (at level 8, format \"''A_' ( m , n )\") : type_scope.\n\n(*A parsing-only notation for the type of square matrices whose dimension is one greater than a given natural number, commonly used for affine transformations.*)\nNotation \"''A_' ( n )\" := 'A_(n ^ 2, n) (only parsing) : type_scope.\n\n(*A notation for the type of square matrices whose dimension is one greater than a given natural number, commonly used for affine transformations.*)\nNotation \"''A_' n\" := 'A_(n)\n (n at next level, format \"''A_' n\") : type_scope.\n\n(*A parsing-only notation for the type of matrices over a specified field, with a given number of rows and one more than a given number of columns.*)\nNotation \"''A' [ F ]_ ( m , n )\" := 'M[F]_(m, n ^ 2)\n (at level 8, only parsing) : type_scope.\n\n(*A parsing-only notation for the type of square matrices over a specified field whose dimension is one greater than a given natural number.*)\nNotation \"''A' [ F ]_ ( n )\" := 'A[F]_(n ^ 2, n)\n (only parsing) : type_scope.\n\n(*A parsing-only notation for the type of square matrices over a specified field whose dimension is one greater than a given natural number.*)\nNotation \"''A' [ F ]_ n\" := 'A[F]_(n)\n (n at level 2, only parsing) : type_scope.\n\nDelimit Scope matrix_set_scope with MS.\n\n(*A local notation for a pair of rewrite rules used for simplification, combining rules for monoid structures and the property that the opposite of zero is zero.*)\nLocal Notation simp := (Monoid.Theory.simpm, oppr0).\n\n(*A recursive function that implements the Gaussian elimination algorithm on a matrix over a field. It decomposes the matrix and returns three components: two square matrices derived from the transformation and a natural number representing the matrix's rank. This is the un-locked, primitive version of the function.*)\nFixpoint Gaussian_elimination_ {F : fieldType} {m n} : 'M[F]_(m, n) -> 'M_m * 'M_n * nat :=\n match m, n with\n | _.+1, _.+1 => fun A : 'M_(1 + _, 1 + _) =>\n if [pick ij | A ij.1 ij.2 != 0] is Some (i, j) then\n let a := A i j in let A1 := xrow i 0 (xcol j 0 A) in\n let u := ursubmx A1 in let v := a^-1 *: dlsubmx A1 in\n let: (L, U, r) := Gaussian_elimination_ (drsubmx A1 - v *m u) in\n (xrow i 0 (block_mx 1 0 v L), xcol j 0 (block_mx a%:M u 0 U), r.+1)\n else (1%:M, 1%:M, 0)\n | _, _ => fun _ => (1%:M, 1%:M, 0)\n end.\n(*This definition provides the locked interface for the Gaussian elimination algorithm. It takes a matrix over a field and returns a result comprising two square matrices and a natural number representing the rank, derived from a rank-revealing factorization.*)\nHB.lock Definition Gaussian_elimination := @Gaussian_elimination_.\nCanonical Gaussian_elimination_unlockable := Unlockable Gaussian_elimination.unlock.\n\n(*This definition computes the rank of a matrix over a field. The rank is defined as zero for matrices with zero rows or columns. For other matrices, the rank is calculated by performing Gaussian elimination and extracting the resulting rank value.*)\nHB.lock Definition mxrank (F : fieldType) m n (A : 'M_(m, n)) :=\n if [|| m == 0 | n == 0]%N then 0 else (@Gaussian_elimination F m n A).2.\nCanonical mxrank_unlockable := Unlockable mxrank.unlock.\n\nSection RowSpaceTheoryDefs.\n\nVariable F : fieldType.\nImplicit Types m n p r : nat.\n\n(**)\nLocal Notation \"''M_' ( m , n )\" := 'M[F]_(m, n) : type_scope.\n(**)\nLocal Notation \"''M_' n\" := 'M[F]_(n, n) : type_scope.\n\nVariables (m n : nat) (A : 'M_(m, n)).\n(*This definition computes the rank of a matrix, which corresponds to the number of linearly independent rows or columns.*)\nLocal Notation mxrank := (@mxrank F m n A).\n\n(*This definition holds the result of applying Gaussian elimination to a given matrix over a field.*)\nLet LUr := @Gaussian_elimination F m n A.\n\n(*This definition extracts a matrix whose columns form a basis for the column space of an original matrix, from the result of its Gaussian elimination.*)\nDefinition col_ebase := LUr.1.1.\n(*This definition extracts a matrix whose rows form a basis for the row space of an original matrix, from the result of its Gaussian elimination.*)\nDefinition row_ebase := LUr.1.2.\n\n(*This definition is a boolean predicate that is true if the rank of a matrix is equal to its number of rows, which indicates that its rows are linearly independent.*)\nDefinition row_free := mxrank == m.\n(*This definition is a boolean predicate that is true if the rank of a matrix is equal to its number of columns, which indicates that it has full column rank.*)\nDefinition row_full := mxrank == n.\n\n(*This definition constructs a matrix whose rows form a basis for the row space of a given input matrix.*)\nDefinition row_base : 'M_(mxrank, n) := pid_mx mxrank *m row_ebase.\n(*This definition constructs a matrix whose columns form a basis for the column space of a given input matrix.*)\nDefinition col_base : 'M_(m, mxrank) := col_ebase *m pid_mx mxrank.\n\n(*This definition computes a matrix whose row space is the orthogonal complement of the row space of a given input matrix.*)\nDefinition complmx : 'M_n := copid_mx mxrank *m row_ebase.\n(*This definition computes a projection matrix onto the left null space, also known as the cokernel, of a given matrix.*)\nDefinition kermx : 'M_m := copid_mx mxrank *m invmx col_ebase.\n(*This definition computes a projection matrix onto the null space, or kernel, of a given matrix.*)\nDefinition cokermx : 'M_n := invmx row_ebase *m copid_mx mxrank.\n\n(*This definition computes the Moore-Penrose pseudoinverse of a given rectangular matrix.*)\nDefinition pinvmx : 'M_(n, m) :=\n invmx row_ebase *m pid_mx mxrank *m invmx col_ebase.\n\nEnd RowSpaceTheoryDefs.\n\nImplicit Types F : fieldType.\n\nHB.lock\n(*This definition establishes a preorder relation between two matrices, which holds if the row space of the first matrix is a subspace of the row space of the second.*)\nDefinition submx F m1 m2 n (A : 'M[F]_(m1, n)) (B : 'M_(m2, n)) :=\n A *m cokermx B == 0.\nCanonical submx_unlockable := Unlockable submx.unlock.\n\nArguments mxrank {F} {m%_N n%_N} A%_MS.\nArguments complmx {F} {m%_N n%_N} A%_MS.\nArguments submx {F} {m1%_N m2%_N n%_N} A%_MS B%_MS : rename.\n\nLocal Notation \"\\rank A\" := (mxrank A) : nat_scope.\n\nLocal Notation \"A ^C\" := (complmx A) : matrix_set_scope.\n\nLocal Notation \"A <= B\" := (submx A B) : matrix_set_scope.\nLocal Notation \"A <= B <= C\" := ((A <= B) && (B <= C))%MS : matrix_set_scope.\nLocal Notation \"A == B\" := (A <= B <= A)%MS : matrix_set_scope.\n\n(*This definition establishes a strict partial order between two matrices, which holds if the row space of the first matrix is a proper subspace of the row space of the second.*)\nDefinition ltmx F m1 m2 n (A : 'M[F]_(m1, n)) (B : 'M_(m2, n)) :=\n (A <= B)%MS && ~~ (B <= A)%MS.\nArguments ltmx {F} {m1%_N m2%_N n%_N} A%_MS B%_MS.\n\nLocal Notation \"A < B\" := (ltmx A B) : matrix_set_scope.\n\n(*This definition provides an equivalence relation between two matrices, which holds if they have the same rank and their row spaces are identical.*)\nDefinition eqmx F m1 m2 n (A : 'M[F]_(m1, n)) (B : 'M_(m2, n)) :=\n prod (\\rank A = \\rank B)\n (forall m3 (C : 'M_(m3, n)),\n ((A <= C) = (B <= C)) * ((C <= A) = (C <= B)))%MS.\nArguments eqmx {F} {m1%_N m2%_N n%_N} A%_MS B%_MS.\n\nLocal Notation \"A :=: B\" := (eqmx A%MS B%MS) : matrix_set_scope.\n\nNotation stablemx V f := (V%MS *m f%R <= V%MS)%MS.\n\nSection LtmxIdentities.\n\nVariable F : fieldType.\nImplicit Types m n p r : nat.\n\n(**)\nLocal Notation \"''M_' ( m , n )\" := 'M[F]_(m, n) : type_scope.\n(**)\nLocal Notation \"''M_' n\" := 'M[F]_(n, n) : type_scope.\n\nVariables (m1 m2 n : nat) (A : 'M_(m1, n)) (B : 'M_(m2, n)).\n\n(*This lemma states that one matrix is strictly less than another if and only if the row space of the first is a subspace of the second's, but the row space of the second is not a subspace of the first's.*)\nLemma ltmxE : (A < B)%MS = ((A <= B)%MS && ~~ (B <= A)%MS). \n\n(*This lemma states that if one matrix is strictly less than another in the row space inclusion order, then its row space is a subspace of the other's.*)\nLemma ltmxW : (A < B)%MS -> (A <= B)%MS. \n\n(*This lemma states that one matrix is strictly less than another if and only if its row space is a subspace of the other's, and the two matrices do not have the same row space.*)\nLemma ltmxEneq : (A < B)%MS = (A <= B)%MS && ~~ (A == B)%MS.\n\n(*This lemma states that the row space of one matrix is a subspace of another's if and only if either the two matrices have the same row space or the first matrix is strictly less than the second.*)\nLemma submxElt : (A <= B)%MS = (A == B)%MS || (A < B)%MS.\n\nEnd LtmxIdentities.\n\n(*This definition provides a boolean predicate to check a quasi-identity property of a matrix. If the matrix is square, the predicate is true if its row space is equivalent to that of the identity matrix. If the matrix is not square, the predicate is true if it has full column rank.*)\nLocal Definition qidmx F m n (A : 'M[F]_(m, n)) :=\n if m == n then A == pid_mx n else row_full A.\n(*This definition specifies a boolean property for a square matrix, which is true if the matrix has the same row space as a given rectangular matrix and also satisfies a given quasi-identity condition.*)\nLocal Definition equivmx F m n (A : 'M[F]_(m, n)) idA (B : 'M_n) :=\n (B == A)%MS && (qidmx B == idA).\n(*This definition provides a specification for a property of a square matrix, requiring it to be equivalent to a given rectangular matrix in both row space and rank, and also to satisfy a given quasi-identity condition.*)\nLocal Definition equivmx_spec F m n (A : 'M[F]_(m, n)) idA (B : 'M_n) :=\n prod (B :=: A)%MS (qidmx B = idA).\n(*This definition constructs a canonical square matrix that serves as a witness for having the same row space as a given rectangular matrix. If the input matrix has full column rank, it produces the identity matrix; otherwise, it constructs a projection from the input matrix's row basis.*)\nLocal Definition genmx_witness F m n (A : 'M[F]_(m, n)) : 'M_n :=\n if row_full A then 1%:M else pid_mx (\\rank A) *m row_ebase A.\nHB.lock\n(*This definition computes a canonical square matrix that represents the row space of a given rectangular matrix.*)\nDefinition genmx F m n (A : 'M[F]_(m, n)) : 'M_n :=\n choose (equivmx A (row_full A)) (genmx_witness A).\nCanonical genmx_unlockable := Unlockable genmx.unlock.\n\nArguments genmx {F} {n m}%_N A%_MS : rename.\n\nLocal Notation \"<< A >>\" := (genmx A%MS) : matrix_set_scope.\n\n(*This definition is a helper function for row space addition that handles the case of adding a zero matrix by returning a canonical matrix that is conformed to the dimensions of the non-zero input matrix.*)\nLocal Definition addsmx_nop F m n (A : 'M[F]_(m, n)) :=\n conform_mx <>%MS A.\nHB.lock\n(*This definition specifies an operation for adding the row spaces of two matrices that share the same number of columns. The result is a canonical square matrix representing the sum of the input row spaces, which is computed by taking the row space of the matrix formed by vertically stacking the two input matrices.*)\nDefinition addsmx F m1 m2 n (A : 'M[F]_(m1, n)) (B : 'M_(m2, n)) : 'M_n :=\n if A == 0 then addsmx_nop B else if B == 0 then addsmx_nop A else\n <>%MS.\nCanonical addsmx_unlockable := Unlockable addsmx.unlock.\n\nArguments addsmx {F} {m1%_N m2%_N n%_N} A%_MS B%_MS : rename.\nLocal Notation \"A + B\" := (addsmx A B) : matrix_set_scope.\n\nLocal Notation \"\\sum_ ( i | P ) B\" := (\\big[addsmx/0]_(i | P) B%MS)\n : matrix_set_scope.\nLocal Notation \"\\sum_ ( i <- r | P ) B\" := (\\big[addsmx/0]_(i <- r | P) B%MS)\n : matrix_set_scope.\n\n(*This definition constructs a witness matrix intended for an intersection operation on row spaces. It returns a conformed identity matrix if the input matrix has full column rank, otherwise it returns the canonical representative of the input matrix's row space.*)\nLocal Definition capmx_witness F m n (A : 'M[F]_(m, n)) :=\n if row_full A then conform_mx 1%:M A else <>%MS.\n(*This definition normalizes a matrix for a row space intersection operation.*)\nLocal Definition capmx_norm F m n (A : 'M[F]_(m, n)) :=\n choose (equivmx A (qidmx A)) (capmx_witness A).\n(*This definition creates a new matrix by conforming a given matrix to its own normalized row space representation, an operation which effectively preserves the row space of the input matrix.*)\nLocal Definition capmx_nop F m n (A : 'M[F]_(m, n)) :=\n conform_mx (capmx_norm A) A.\n(*This definition computes a matrix whose row space is the intersection of the row spaces of two given matrices that share the same field and number of columns.*)\nDefinition capmx_gen F m1 m2 n (A : 'M[F]_(m1, n)) (B : 'M_(m2, n)) :=\n lsubmx (kermx (col_mx A B)) *m A.\nHB.lock\n(*This definition computes a matrix representing the intersection of the row spaces of two input matrices, handling special cases where one matrix represents the entire vector space and otherwise using a general intersection formula.*)\nDefinition capmx F m1 m2 n (A : 'M[F]_(m1, n)) (B : 'M_(m2, n)) : 'M_n :=\n if qidmx A then capmx_nop B else\n if qidmx B then capmx_nop A else\n if row_full B then capmx_norm A else capmx_norm (capmx_gen A B).\nCanonical capmx_unlockable := Unlockable capmx.unlock.\n\nArguments capmx {F} {m1%_N m2%_N n%_N} A%_MS B%_MS : rename.\n\nLocal Notation \"A :&: B\" := (capmx A B) : matrix_set_scope.\nLocal Notation \"\\bigcap_ ( i | P ) B\" := (\\big[capmx/1%:M]_(i | P) B)\n : matrix_set_scope.\n\nHB.lock\n(*This definition computes a matrix whose row space corresponds to the set difference between the vector subspaces represented by two matrices, which is achieved by intersecting the row space of the first matrix with the orthogonal complement of the row space of the second.*)\nDefinition diffmx F m1 m2 n (A : 'M[F]_(m1, n)) (B : 'M_(m2, n)) : 'M_n :=\n <>%MS.\nCanonical diffmx_unlockable := Unlockable diffmx.unlock.\n\nArguments diffmx {F} {m1%_N m2%_N n%_N} A%_MS B%_MS : rename.\nLocal Notation \"A :\\: B\" := (diffmx A B) : matrix_set_scope.\n\nSection RowSpaceTheory.\nVariable F : fieldType.\nImplicit Types m n p r : nat.\n(*This notation serves as a shorthand for the type of matrices with a specified number of rows and columns over a given field.*)\nLocal Notation \"''M_' ( m , n )\" := 'M[F]_(m, n) : type_scope.\n(*This notation serves as a shorthand for the type of square matrices of a specified size over a given field.*)\nLocal Notation \"''M_' n\" := 'M[F]_(n, n) : type_scope.\n\n(*This definition computes the projection matrix for projecting onto the row space of a first square matrix along the row space of a second square matrix.*)\nDefinition proj_mx n (U V : 'M_n) : 'M_n := pinvmx (col_mx U V) *m col_mx U 0.\n\n(*This notation refers to a specific implementation of the Gaussian elimination algorithm for matrices.*)\nLocal Notation GaussE := Gaussian_elimination_.\n\n(*This lemma states that the rank of a matrix is equal to the numerical rank computed by the Gaussian elimination algorithm.*)\nFact mxrankE m n (A : 'M_(m, n)) : \\rank A = (GaussE A).2.\n\n(*This lemma states that the rank of any matrix is always less than or equal to its number of rows.*)\nLemma rank_leq_row m n (A : 'M_(m, n)) : \\rank A <= m.\n\n(*This lemma states that the condition that the number of rows of a matrix is less than or equal to its rank is equivalent to the property that the rows of the matrix are linearly independent.*)\nLemma row_leq_rank m n (A : 'M_(m, n)) : (m <= \\rank A) = row_free A.\n\n(*This lemma states that the rank of any matrix is always less than or equal to its number of columns.*)\nLemma rank_leq_col m n (A : 'M_(m, n)) : \\rank A <= n.\n\n(*This lemma states that the condition that the number of columns of a matrix is less than or equal to its rank is equivalent to the property that the rows of the matrix span the entire space of row vectors.*)\nLemma col_leq_rank m n (A : 'M_(m, n)) : (n <= \\rank A) = row_full A.\n\n(*This lemma states that if two matrices have the same row space, then they share the same row-full property, meaning one has rows that span the entire vector space if and only if the other does.*)\nLemma eq_row_full m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :=: B)%MS -> row_full A = row_full B.\n\n(*This definition creates a local alias for the 1-by-1 identity matrix over the current field.*)\nLet unitmx1F := @unitmx1 F.\n(*This lemma states that the matrix representing an orthonormal basis for the row space of any given matrix has orthonormal rows itself.*)\nLemma row_ebase_unit m n (A : 'M_(m, n)) : row_ebase A \\in unitmx.\n\n(*This lemma states that the matrix representing an orthonormal basis for the column space of any given matrix has orthonormal rows.*)\nLemma col_ebase_unit m n (A : 'M_(m, n)) : col_ebase A \\in unitmx.\n\nHint Resolve rank_leq_row rank_leq_col row_ebase_unit col_ebase_unit : core.\n\n(*This lemma states that any matrix can be reconstructed through a rank decomposition by multiplying three other matrices: the orthonormal basis of its column space, a rectangular diagonal matrix with ones corresponding to the rank, and the orthonormal basis of its row space.*)\nLemma mulmx_ebase m n (A : 'M_(m, n)) :\n col_ebase A *m pid_mx (\\rank A) *m row_ebase A = A.\n\n(*This lemma states that any matrix can be reconstructed by multiplying the matrix formed by a basis of its column space with the matrix formed by a basis of its row space.*)\nLemma mulmx_base m n (A : 'M_(m, n)) : col_base A *m row_base A = A.\n\n(*This lemma states that if multiplying a given matrix by two other matrices results in an identity matrix of a certain size, then that size must be less than or equal to the rank of the given matrix.*)\nLemma mulmx1_min_rank r m n (A : 'M_(m, n)) M N :\n M *m A *m N = 1%:M :> 'M_r -> r <= \\rank A.\n\nArguments mulmx1_min_rank [r m n A].\n\n(*This lemma states that the rank of the product of two matrices is less than or equal to their shared inner dimension.*)\nLemma mulmx_max_rank r m n (M : 'M_(m, r)) (N : 'M_(r, n)) :\n \\rank (M *m N) <= r.\n\nArguments mulmx_max_rank [r m n].\n\n(*This lemma states that the rank of the transpose of a matrix is equal to the rank of the original matrix.*)\nLemma mxrank_tr m n (A : 'M_(m, n)) : \\rank A^T = \\rank A.\n\n(*This lemma states that the rank of the sum of two matrices is less than or equal to the sum of their individual ranks.*)\nLemma mxrank_add m n (A B : 'M_(m, n)) : \\rank (A + B)%R <= \\rank A + \\rank B.\n\n(*This lemma states that the rank of a product of two matrices is less than or equal to the rank of the first matrix in the product.*)\nLemma mxrankM_maxl m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :\n \\rank (A *m B) <= \\rank A.\n\n(*This lemma states that the rank of a product of two matrices is less than or equal to the rank of the second matrix in the product.*)\nLemma mxrankM_maxr m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :\n \\rank (A *m B) <= \\rank B.\n\n(*This lemma states that the rank of a matrix scaled by a scalar is less than or equal to the rank of the original matrix.*)\nLemma mxrank_scale m n a (A : 'M_(m, n)) : \\rank (a *: A) <= \\rank A.\n\n(*This lemma states that if a matrix is scaled by a non-zero scalar, its rank remains unchanged.*)\nLemma mxrank_scale_nz m n a (A : 'M_(m, n)) :\n a != 0 -> \\rank (a *: A) = \\rank A.\n\n(*This lemma states that the rank of the additive inverse of a matrix is equal to the rank of the original matrix.*)\nLemma mxrank_opp m n (A : 'M_(m, n)) : \\rank (- A) = \\rank A.\n\n(*This lemma states that the rank of a zero matrix of any dimension is zero.*)\nLemma mxrank0 m n : \\rank (0 : 'M_(m, n)) = 0%N.\n\n(*This lemma states that a matrix has a rank of zero if and only if that matrix is the zero matrix.*)\nLemma mxrank_eq0 m n (A : 'M_(m, n)) : (\\rank A == 0) = (A == 0).\n\n(*This lemma states that the product of a matrix and its cokernel matrix is the zero matrix.*)\nLemma mulmx_coker m n (A : 'M_(m, n)) : A *m cokermx A = 0.\n\n(*This lemma states that a matrix `A` representing a submodule of a matrix `B` is equivalent to the product of matrix `A` and the cokernel matrix of `B` being the zero matrix.*)\nLemma submxE m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A <= B)%MS = (A *m cokermx B == 0).\n\n(*This lemma states that if a matrix `A` represents a submodule of a matrix `B`, then the product of `A`, the Moore-Penrose pseudo-inverse of `B`, and `B` itself is equal to `A`.*)\nLemma mulmxKpV m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A <= B)%MS -> A *m pinvmx B *m B = A.\n\n(*This lemma states that for any matrix over a field with linearly independent rows, its product with its Moore-Penrose pseudo-inverse equals the identity matrix.*)\nLemma mulmxVp m n (A : 'M[F]_(m, n)) : row_free A -> A *m pinvmx A = 1%:M.\n\n(*This lemma states that for any matrix over a field with linearly independent rows, right multiplication by that matrix is a right inverse to right multiplication by its Moore-Penrose pseudo-inverse.*)\nLemma mulmxKp p m n (B : 'M[F]_(m, n)) : row_free B ->\n cancel ((@mulmx _ p _ _)^~ B) (mulmx^~ (pinvmx B)).\n\n(*This lemma provides a boolean reflection of the property that a matrix `A` represents a submodule of a matrix `B`, stating this is equivalent to the existence of another matrix `D` such that `A` equals the product of `D` and `B`.*)\nLemma submxP m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (exists D, A = D *m B) (A <= B)%MS.\n\nArguments submxP {m1 m2 n A B}.\n\n(*This lemma states that the matrix submodule relation is reflexive, meaning any matrix is a submodule of itself.*)\nLemma submx_refl m n (A : 'M_(m, n)) : (A <= A)%MS.\n\nHint Resolve submx_refl : core.\n\n(*This lemma states that the product of two matrices is a submodule of the second matrix.*)\nLemma submxMl m n p (D : 'M_(m, n)) (A : 'M_(n, p)) : (D *m A <= A)%MS.\n\n(*This lemma states that the matrix submodule relation is preserved under right multiplication, meaning if one matrix is a submodule of a second, then their respective products with a third matrix maintain the submodule relationship.*)\nLemma submxMr m1 m2 n p (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(n, p)) :\n (A <= B)%MS -> (A *m C <= B *m C)%MS.\n\n(*This lemma states that if a matrix `A` is a submodule of a matrix `B`, then the product of a third matrix `C` with `A` is also a submodule of `B`.*)\nLemma mulmx_sub m n1 n2 p (C : 'M_(m, n1)) A (B : 'M_(n2, p)) :\n (A <= B -> C *m A <= B)%MS.\n\n(*This lemma states that the matrix submodule relation is transitive.*)\nLemma submx_trans m1 m2 m3 n\n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (A <= B -> B <= C -> A <= C)%MS.\n\n(*This lemma states a transitivity property for matrix submodules: if a matrix is a proper submodule of a second matrix, and the second is a submodule of a third, then the first is a proper submodule of the third.*)\nLemma ltmx_sub_trans m1 m2 m3 n\n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (A < B)%MS -> (B <= C)%MS -> (A < C)%MS.\n\n(*This lemma states a transitivity property for matrix submodules: if a matrix is a submodule of a second matrix, and the second is a proper submodule of a third, then the first is a proper submodule of the third.*)\nLemma sub_ltmx_trans m1 m2 m3 n\n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (A <= B)%MS -> (B < C)%MS -> (A < C)%MS.\n\n(*This lemma states that the strict matrix submodule relation is transitive.*)\nLemma ltmx_trans m n : transitive (@ltmx F m m n).\n\n(*This lemma states that the strict matrix submodule relation is irreflexive.*)\nLemma ltmx_irrefl m n : irreflexive (@ltmx F m m n).\n\n(*This lemma states that the zero matrix is a submodule of any other matrix.*)\nLemma sub0mx m1 m2 n (A : 'M_(m2, n)) : ((0 : 'M_(m1, n)) <= A)%MS.\n\n(*This lemma states that for matrices over a field, if a matrix is a submodule of the zero matrix, it must be the zero matrix itself.*)\nLemma submx0null m1 m2 n (A : 'M[F]_(m1, n)) :\n (A <= (0 : 'M_(m2, n)))%MS -> A = 0.\n\n(*This lemma states that a matrix is a submodule of a zero matrix if and only if the matrix itself is a zero matrix.*)\nLemma submx0 m n (A : 'M_(m, n)) : (A <= (0 : 'M_n))%MS = (A == 0).\n\n(*This lemma states that the zero matrix is a proper submodule of another matrix if and only if that other matrix is not a zero matrix.*)\nLemma lt0mx m n (A : 'M_(m, n)) : ((0 : 'M_n) < A)%MS = (A != 0).\n\n(*This lemma states that for a matrix over a field, it is impossible for it to be a proper submodule of a zero matrix.*)\nLemma ltmx0 m n (A : 'M[F]_(m, n)) : (A < (0 : 'M_n))%MS = false.\n\n(*This lemma provides a boolean reflection of the property that a matrix is equivalent to a zero matrix in the submodule sense, stating this is the same as the matrix being equal to a zero matrix.*)\nLemma eqmx0P m n (A : 'M_(m, n)) : reflect (A = 0) (A == (0 : 'M_n))%MS.\n\n(*This lemma states that if two matrices are equivalent in the submodule sense, then one is the zero matrix if and only if the other is also the zero matrix.*)\nLemma eqmx_eq0 m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :=: B)%MS -> (A == 0) = (B == 0).\n\n(*This lemma states that if two matrices are both submodules of a third matrix, then their vertical concatenation is also a submodule of that third matrix.*)\nLemma addmx_sub m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m1, n)) (C : 'M_(m2, n)) :\n (A <= C)%MS -> (B <= C)%MS -> ((A + B)%R <= C)%MS.\n\n(*This lemma states that a matrix formed by selecting a subset of rows from another matrix `A` is a submodule of `A`.*)\nLemma rowsub_sub m1 m2 n (f : 'I_m2 -> 'I_m1) (A : 'M_(m1, n)) :\n (rowsub f A <= A)%MS.\n\n(*This lemma states that if every matrix in a given filtered sequence is a submodule of a matrix `B`, then the vertical concatenation of all these matrices is also a submodule of `B`.*)\nLemma summx_sub m1 m2 n (B : 'M_(m2, n))\n I (r : seq I) (P : pred I) (A_ : I -> 'M_(m1, n)) :\n (forall i, P i -> A_ i <= B)%MS -> ((\\sum_(i <- r | P i) A_ i)%R <= B)%MS.\n\n(*This lemma states that if a matrix is a submodule of another matrix, then the result of scaling the first matrix by a scalar is also a submodule of the second matrix.*)\nLemma scalemx_sub m1 m2 n a (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A <= B)%MS -> (a *: A <= B)%MS.\n\n(*This lemma states that any single row of a matrix, considered as a one-row matrix, is a submodule of the original matrix.*)\nLemma row_sub m n i (A : 'M_(m, n)) : (row i A <= A)%MS.\n\n(*This lemma states that if a row vector is equal to a row of a matrix, then the one-row matrix formed from that vector is a submodule of the original matrix.*)\nLemma eq_row_sub m n v (A : 'M_(m, n)) i : row i A = v -> (v <= A)%MS.\n\nArguments eq_row_sub [m n v A].\n\n(*This lemma states that the matrix composed of all the non-zero rows of a given matrix is a submodule of the original matrix.*)\nLemma nz_row_sub m n (A : 'M_(m, n)) : (nz_row A <= A)%MS.\n\n(*This lemma provides a boolean reflection of the property that a matrix is a submodule of another, stating this is equivalent to each row of the first matrix being a submodule of the second.*)\nLemma row_subP m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (forall i, row i A <= B)%MS (A <= B)%MS.\n\nArguments row_subP {m1 m2 n A B}.\n\n(*This lemma states that the row space of a first matrix is a subspace of the row space of a second matrix if and only if every row vector belonging to the row space of the first matrix also belongs to the row space of the second matrix.*)\nLemma rV_subP m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (forall v : 'rV_n, v <= A -> v <= B)%MS (A <= B)%MS.\n\nArguments rV_subP {m1 m2 n A B}.\n\n(*This lemma states that the row space of a first matrix is not a subspace of the row space of a second matrix if and only if there exists at least one row in the first matrix that is not contained in the row space of the second matrix.*)\nLemma row_subPn m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (exists i, ~~ (row i A <= B)%MS) (~~ (A <= B)%MS).\n\n(*This lemma states that for two row vectors over a field, the row space of the first vector is a subspace of the row space of the second if and only if the first vector is a scalar multiple of the second.*)\nLemma sub_rVP n (u v : 'rV[F]_n) : reflect (exists a, u = a *: v) (u <= v)%MS.\n\n(*This lemma states that the rank of a row vector over a field is one if the vector is non-zero, and zero otherwise.*)\nLemma rank_rV n (v : 'rV[F]_n) : \\rank v = (v != 0).\n\n(*This lemma states that a matrix is non-zero if and only if its row space contains at least one non-zero row vector.*)\nLemma rowV0Pn m n (A : 'M_(m, n)) :\n reflect (exists2 v : 'rV_n, v <= A & v != 0)%MS (A != 0).\n\n(*This lemma states that a matrix is equal to the zero matrix if and only if every row vector in its row space is the zero vector.*)\nLemma rowV0P m n (A : 'M_(m, n)) :\n reflect (forall v : 'rV_n, v <= A -> v = 0)%MS (A == 0).\n\n(*This lemma states that if a matrix has a full row space, then the row space of any other matrix with the same number of columns is a subspace of its row space.*)\nLemma submx_full m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n row_full B -> (A <= B)%MS.\n\n(*This lemma states that a matrix has a full row space if and only if it possesses a left inverse, that is, there exists another matrix which, when multiplied on the left, yields the identity matrix.*)\nLemma row_fullP m n (A : 'M_(m, n)) :\n reflect (exists B, B *m A = 1%:M) (row_full A).\n\nArguments row_fullP {m n A}.\n\n(*This lemma states that if a matrix has a full row space, then the function corresponding to left multiplication by that matrix is injective.*)\nLemma row_full_inj m n p A : row_full A -> injective (@mulmx F m n p A).\n\n(*This lemma states that a matrix has linearly independent rows if and only if it possesses a right inverse, that is, there exists another matrix which, when multiplied on the right, yields the identity matrix.*)\nLemma row_freeP m n (A : 'M_(m, n)) :\n reflect (exists B, A *m B = 1%:M) (row_free A).\n\n(*This lemma states that if a matrix has linearly independent rows, then the function corresponding to right multiplication by that matrix is injective.*)\nLemma row_free_inj m n p A : row_free A -> injective ((@mulmx F m n p)^~ A).\n\n(*This definition provides an alternative name for the lemma establishing that if a matrix has linearly independent rows, the function for right multiplication by that matrix is injective.*)\nDefinition row_free_injr m n p A : row_free A -> injective (mulmxr A) :=\n @row_free_inj m n p A.\n\n(*This lemma states that for a square matrix, having linearly independent rows is equivalent to being an invertible matrix.*)\nLemma row_free_unit n (A : 'M_n) : row_free A = (A \\in unitmx).\n\n(*This lemma states that for a square matrix, having a full row space is equivalent to being an invertible matrix.*)\nLemma row_full_unit n (A : 'M_n) : row_full A = (A \\in unitmx).\n\n(*This lemma states that an invertible square matrix of size n has rank equal to n.*)\nLemma mxrank_unit n (A : 'M_n) : A \\in unitmx -> \\rank A = n.\n\n(*This lemma states that the rank of an identity matrix of size n is equal to n.*)\nLemma mxrank1 n : \\rank (1%:M : 'M_n) = n. \n\n(*This lemma states that the rank of a delta matrix, which has a single non-zero entry, is equal to one.*)\nLemma mxrank_delta m n i j : \\rank (delta_mx i j : 'M_(m, n)) = 1.\n\n(*This lemma states that if the row space of a first matrix is a subspace of a second matrix's row space, then the rank of the first matrix is less than or equal to the rank of the second matrix.*)\nLemma mxrankS m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A <= B)%MS -> \\rank A <= \\rank B.\n\n(*This lemma states that the row space of any matrix is a subspace of the row space of a compatible identity matrix.*)\nLemma submx1 m n (A : 'M_(m, n)) : (A <= 1%:M)%MS.\n\n(*This lemma states that the row space of a matrix contains the row space of a compatible identity matrix if and only if the matrix has a full row space.*)\nLemma sub1mx m n (A : 'M_(m, n)) : (1%:M <= A)%MS = row_full A.\n\n(*This lemma states that the row space of a matrix is a proper subspace of the row space of a compatible identity matrix if and only if the matrix does not have a full row space.*)\nLemma ltmx1 m n (A : 'M_(m, n)) : (A < 1%:M)%MS = ~~ row_full A.\n\n(*This lemma states that the row space of an identity matrix cannot be a proper subspace of the row space of any other matrix.*)\nLemma lt1mx m n (A : 'M_(m, n)) : (1%:M < A)%MS = false.\n\n(*This lemma states that for an invertible square matrix, its Moore-Penrose pseudoinverse is equal to its standard inverse.*)\nLemma pinvmxE n (A : 'M[F]_n) : A \\in unitmx -> pinvmx A = invmx A.\n\n(*This lemma states that for a matrix with a full row space, its Moore-Penrose pseudoinverse acts as a left inverse, so that multiplying the matrix on the left by the pseudoinverse yields the identity matrix.*)\nLemma mulVpmx m n (A : 'M[F]_(m, n)) : row_full A -> pinvmx A *m A = 1%:M.\n\n(*This lemma states that if a matrix has a full row space, then its Moore-Penrose pseudoinverse has linearly independent rows.*)\nLemma pinvmx_free m n (A : 'M[F]_(m, n)) : row_full A -> row_free (pinvmx A).\n\n(*This lemma states that if a matrix has linearly independent rows, then its Moore-Penrose pseudoinverse has a full row space.*)\nLemma pinvmx_full m n (A : 'M[F]_(m, n)) : row_free A -> row_full (pinvmx A).\n\n(*This lemma states that two matrices have equal row spaces if and only if the boolean comparison of their row spaces evaluates to true.*)\nLemma eqmxP m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (A :=: B)%MS (A == B)%MS.\n\nArguments eqmxP {m1 m2 n A B}.\n\n(*This lemma states that two matrices have the same row space if and only if for every row vector, that vector belongs to the row space of the first matrix exactly when it belongs to the row space of the second.*)\nLemma rV_eqP m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (forall u : 'rV_n, (u <= A) = (u <= B))%MS (A == B)%MS.\n\n(*This lemma states that two matrices are equal if and only if they yield the same result when left-multiplied by any given row vector.*)\nLemma mulmxP (m n : nat) (A B : 'M[F]_(m, n)) :\n reflect (forall u : 'rV_m, u *m A = u *m B) (A == B).\n\n(*This lemma states that the row space of any matrix is equal to itself.*)\nLemma eqmx_refl m1 n (A : 'M_(m1, n)) : (A :=: A)%MS.\n\n(*This lemma states that the rowspace equivalence relation between two matrices is symmetric, meaning if a first matrix is rowspace-equivalent to a second matrix, then the second matrix is also rowspace-equivalent to the first.*)\nLemma eqmx_sym m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :=: B)%MS -> (B :=: A)%MS.\n\n(*This lemma states that the rowspace equivalence relation between matrices is transitive, meaning if a first matrix is rowspace-equivalent to a second, and the second is rowspace-equivalent to a third, then the first matrix is rowspace-equivalent to the third.*)\nLemma eqmx_trans m1 m2 m3 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (A :=: B)%MS -> (B :=: C)%MS -> (A :=: C)%MS.\n\n(*This lemma states that if two matrices with the same dimensions have identical rowspaces, then their ranks are equal.*)\nLemma eqmx_rank m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A == B)%MS -> \\rank A = \\rank B.\n\n(*This lemma states that if two matrices are rowspace-equivalent, they can be substituted for one another in any strict rowspace inclusion comparison with a third matrix.*)\nLemma lt_eqmx m1 m2 m3 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :=: B)%MS ->\n forall C : 'M_(m3, n), (((A < C) = (B < C))%MS * ((C < A) = (C < B))%MS)%type.\n\n(*This lemma states that if two matrices are rowspace-equivalent, then right-multiplying both by a third conformant matrix preserves rowspace equivalence.*)\nLemma eqmxMr m1 m2 n p (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(n, p)) :\n (A :=: B)%MS -> (A *m C :=: B *m C)%MS.\n\n(*This lemma states that if a matrix has full row rank, then the rowspace of its product with another matrix is equivalent to the rowspace of the second matrix.*)\nLemma eqmxMfull m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :\n row_full A -> (A *m B :=: B)%MS.\n\n(*This lemma states that any two zero matrices with the same number of columns are rowspace-equivalent, regardless of their number of rows.*)\nLemma eqmx0 m n : ((0 : 'M[F]_(m, n)) :=: (0 : 'M_n))%MS.\n\n(*This lemma states that scaling a matrix by any non-zero scalar results in a new matrix that is rowspace-equivalent to the original matrix.*)\nLemma eqmx_scale m n a (A : 'M_(m, n)) : a != 0 -> (a *: A :=: A)%MS.\n\n(*This lemma states that the additive inverse of a matrix is rowspace-equivalent to the original matrix.*)\nLemma eqmx_opp m n (A : 'M_(m, n)) : (- A :=: A)%MS.\n\n(*This lemma states that when right-multiplying two matrices by a third matrix with linearly independent rows, the rowspace inclusion relation between the resulting products is equivalent to the rowspace inclusion relation between the original two matrices.*)\nLemma submxMfree m1 m2 n p (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(n, p)) :\n row_free C -> (A *m C <= B *m C)%MS = (A <= B)%MS.\n\n(*This lemma provides a right cancellation property, stating that if two matrices become rowspace-equivalent after being right-multiplied by a matrix with linearly independent rows, then the original two matrices were already rowspace-equivalent.*)\nLemma eqmxMfree m1 m2 n p (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(n, p)) :\n row_free C -> (A *m C :=: B *m C)%MS -> (A :=: B)%MS.\n\n(*This lemma states that the rank of a matrix product is equal to the rank of the first matrix if the second matrix has linearly independent rows.*)\nLemma mxrankMfree m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :\n row_free B -> \\rank (A *m B) = \\rank A.\n\n(*This lemma states that the matrix formed by the row basis of a given matrix is rowspace-equivalent to the original matrix.*)\nLemma eq_row_base m n (A : 'M_(m, n)) : (row_base A :=: A)%MS.\n\n(*This lemma states that the row basis of any zero matrix is a zero matrix.*)\nLemma row_base0 (m n : nat) : row_base (0 : 'M[F]_(m, n)) = 0.\n\n(*This definition states that a square matrix is the identity matrix if and only if its rowspace is equal to the rowspace of the identity matrix.*)\nLet qidmx_eq1 n (A : 'M_n) : qidmx A = (A == 1%:M).\n\n(*This lemma states the defining property of the generation witness for a matrix, which relates the matrix to its canonical, full-row-rank representation via a transformation.*)\nLet genmx_witnessP m n (A : 'M_(m, n)) :\n equivmx A (row_full A) (genmx_witness A).\n\n(*This lemma states that the canonical generating matrix of a given matrix is rowspace-equivalent to the original matrix.*)\nLemma genmxE m n (A : 'M_(m, n)) : (<> :=: A)%MS.\n\n(*This lemma states that if two matrices are rowspace-equivalent, then their canonical generating matrices are identical.*)\nLemma eq_genmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :=: B -> <> = <>)%MS.\n\n(*This lemma establishes that two matrices of the same shape have equal rowspaces if and only if their canonical generating matrices are identical.*)\nLemma genmxP m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (<> = <>)%MS (A == B)%MS.\n\nArguments genmxP {m1 m2 n A B}.\n\n(*This lemma states that the canonical generating matrix of a zero matrix is itself a zero matrix.*)\nLemma genmx0 m n : <<0 : 'M_(m, n)>>%MS = 0.\n\n(*This lemma states that the canonical generating matrix of an identity matrix is the identity matrix itself.*)\nLemma genmx1 n : <<1%:M : 'M_n>>%MS = 1%:M.\n\n(*This lemma states that the canonical generating matrix operation is idempotent, meaning applying it to an already canonical generating matrix results in the same matrix.*)\nLemma genmx_id m n (A : 'M_(m, n)) : (<<<>>> = <>)%MS.\n\n(*This lemma states that the matrix formed by the row basis of any given matrix has linearly independent rows.*)\nLemma row_base_free m n (A : 'M_(m, n)) : row_free (row_base A).\n\n(*This lemma states that the rank of the canonical generating matrix of a given matrix is equal to the rank of the original matrix.*)\nLemma mxrank_gen m n (A : 'M_(m, n)) : \\rank <>%MS = \\rank A.\n\n(*This lemma states that the matrix formed by the column basis of any given matrix has full row rank.*)\nLemma col_base_full m n (A : 'M_(m, n)) : row_full (col_base A).\n\nHint Resolve row_base_free col_base_full : core.\n\n(*This lemma states that, given that the rowspace of a first matrix is a subspace of a second's, the proposition that the first matrix's rank is at most the second's is logically equivalent to the proposition that the second matrix's rowspace is a subspace of the first's.*)\nLemma mxrank_leqif_sup m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A <= B)%MS -> \\rank A <= \\rank B ?= iff (B <= A)%MS.\n\n(*This lemma states that for two matrices of the same shape, if the rowspace of the first is a subspace of the second's, the proposition that the first matrix's rank is at most the second's is logically equivalent to the proposition that their rowspaces are equal.*)\nLemma mxrank_leqif_eq m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A <= B)%MS -> \\rank A <= \\rank B ?= iff (A == B)%MS.\n\n(*This lemma provides an equivalence for strict rowspace inclusion, stating that a first matrix's rowspace is a strict subspace of a second's if and only if the first's rowspace is a subspace of the second's and the rank of the first matrix is strictly less than the rank of the second.*)\nLemma ltmxErank m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A < B)%MS = (A <= B)%MS && (\\rank A < \\rank B).\n\n(*This lemma states that if the rowspace of a first matrix is a strict subspace of the rowspace of a second matrix, then the rank of the first matrix is strictly less than the rank of the second.*)\nLemma rank_ltmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A < B)%MS -> \\rank A < \\rank B.\n\n(*This lemma states that casting a matrix to a type with a different row dimension, given a proof that the dimensions are equal, results in a matrix that is rowspace-equivalent to the original.*)\nLemma eqmx_cast m1 m2 n (A : 'M_(m1, n)) e :\n ((castmx e A : 'M_(m2, n)) :=: A)%MS.\n\n(*This lemma states that casting a matrix to a different number of rows does not change its property of being row-full.*)\nLemma row_full_castmx m1 m2 n (A : 'M_(m1, n)) e :\n row_full (castmx e A : 'M_(m2, n)) = row_full A.\n\n(*This lemma states that casting a matrix to a different number of rows does not affect its row-free property.*)\nLemma row_free_castmx m1 m2 n (A : 'M_(m1, n)) e :\n row_free (castmx e A : 'M_(m2, n)) = row_free A.\n\n(*This lemma states that conforming a matrix to the shape of another matrix results in a matrix that is equivalent, in the submatrix order, to either the first or the second original matrix.*)\nLemma eqmx_conform m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (conform_mx A B :=: A \\/ conform_mx A B :=: B)%MS.\n\n(*This definition states that applying a no-operation sum to a matrix results in a matrix that is equivalent to the original matrix in the submatrix order.*)\nLet eqmx_sum_nop m n (A : 'M_(m, n)) : (addsmx_nop A :=: A)%MS.\n\n(*This lemma states that selecting rows from a matrix using a composed function results in a submatrix of the matrix formed by selecting rows using the outer function.*)\nLemma rowsub_comp_sub (m n p q : nat) f (g : 'I_n -> 'I_p) (A : 'M_(m, q)) :\n (rowsub (f \\o g) A <= rowsub f A)%MS.\n\n(*This lemma states that if a row-selection function is pointwise equal to the composition of another row-selection function and a third function, then the matrix formed by applying the first function is a submatrix of the matrix formed by applying the second.*)\nLemma submx_rowsub (m n p q : nat) (h : 'I_n -> 'I_p) f g (A : 'M_(m, q)) :\n f =1 g \\o h -> (rowsub f A <= rowsub g A)%MS.\n\nArguments submx_rowsub [m1 m2 m3 n] h [f g A] _ : rename.\n\n(*This lemma states that composing a row-selection function with a permutation results in a matrix that is equivalent, in the submatrix order, to the matrix formed by the original selection function.*)\nLemma eqmx_rowsub_comp_perm (m1 m2 n : nat) (s : 'S_m2) f (A : 'M_(m1, n)) :\n (rowsub (f \\o s) A :=: rowsub f A)%MS.\n\n(*This lemma states that if a function for re-indexing is injective, composing it with a row-selection function results in a matrix that is equivalent, in the submatrix order, to the one created by the original selection function.*)\nLemma eqmx_rowsub_comp (m n p q : nat) f (g : 'I_n -> 'I_p) (A : 'M_(m, q)) :\n p <= n -> injective g -> (rowsub (f \\o g) A :=: rowsub f A)%MS.\n\n(*This lemma states that if a row-selection function is pointwise equal to the composition of a second row-selection function with an injective re-indexing function, then the matrix formed by applying the first function is equivalent, in the submatrix order, to the matrix formed by applying the second.*)\nLemma eqmx_rowsub (m n p q : nat) (h : 'I_n -> 'I_p) f g (A : 'M_(m, q)) :\n injective h -> p <= n -> f =1 g \\o h -> (rowsub f A :=: rowsub g A)%MS.\n\nArguments eqmx_rowsub [m1 m2 m3 n] h [f g A] _ : rename.\n\nSection AddsmxSub.\n\nVariable (m1 m2 n : nat) (A : 'M[F]_(m1, n)) (B : 'M[F]_(m2, n)).\n\n(*This lemma states that a matrix formed by vertically stacking a first and a second matrix is a submatrix of a third matrix if and only if both the first and the second matrices are individually submatrices of the third.*)\nLemma col_mx_sub m3 (C : 'M_(m3, n)) :\n (col_mx A B <= C)%MS = (A <= C)%MS && (B <= C)%MS.\n\n(*This lemma states that the sum of two matrices with potentially different numbers of rows is equivalent, in the submatrix order, to the matrix formed by vertically stacking them.*)\nLemma addsmxE : (A + B :=: col_mx A B)%MS.\n\n(*This lemma states that the sum of a first and a second matrix is a submatrix of a third matrix if and only if both the first and second matrices are individually submatrices of the third.*)\nLemma addsmx_sub m3 (C : 'M_(m3, n)) :\n (A + B <= C)%MS = (A <= C)%MS && (B <= C)%MS.\n\n(*This lemma states that a matrix is always a submatrix of its sum with another matrix.*)\nLemma addsmxSl : (A <= A + B)%MS.\n\n(*This lemma states that a matrix is always a submatrix of the sum of another matrix with it.*)\nLemma addsmxSr : (B <= A + B)%MS.\n\n(*This lemma states that the sum of a first and a second matrix is equivalent to the second matrix if and only if the first matrix is a submatrix of the second.*)\nLemma addsmx_idPr : reflect (A + B :=: B)%MS (A <= B)%MS.\n\n(*This lemma states that the sum of a first and a second matrix is equivalent to the first matrix if and only if the second matrix is a submatrix of the first.*)\nLemma addsmx_idPl : reflect (A + B :=: A)%MS (B <= A)%MS.\n\nEnd AddsmxSub.\n\n(*This lemma states that adding a zero matrix to another matrix results in a matrix equivalent, in the submatrix order, to the original matrix.*)\nLemma adds0mx m1 m2 n (B : 'M_(m2, n)) : ((0 : 'M_(m1, n)) + B :=: B)%MS.\n\n(*This lemma states that adding a matrix to a zero matrix results in a matrix equivalent, in the submatrix order, to the original matrix.*)\nLemma addsmx0 m1 m2 n (A : 'M_(m1, n)) : (A + (0 : 'M_(m2, n)) :=: A)%MS.\n\n(*This definition states that a no-operation sum applied to a matrix is equal to the zero matrix if and only if the original matrix itself is equal to the zero matrix.*)\nLet addsmx_nop_eq0 m n (A : 'M_(m, n)) : (addsmx_nop A == 0) = (A == 0).\n\n(*This definition states that applying a no-operation sum to a zero matrix results in a zero matrix.*)\nLet addsmx_nop0 m n : addsmx_nop (0 : 'M_(m, n)) = 0.\n\n(*This definition states that for a square matrix, the no-operation sum is the identity operation.*)\nLet addsmx_nop_id n (A : 'M_n) : addsmx_nop A = A.\n\n(*This lemma states that the sum of two matrices is commutative with respect to the submatrix equivalence relation.*)\nLemma addsmxC m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) : (A + B = B + A)%MS.\n\n(*This lemma states that for a square matrix, adding a zero matrix of any number of rows yields a matrix equal to the original square matrix under the submatrix equivalence.*)\nLemma adds0mx_id m1 n (B : 'M_n) : ((0 : 'M_(m1, n)) + B)%MS = B.\n\n(*This lemma states that for a square matrix, adding it to a zero matrix of any number of rows yields a matrix equal to the original square matrix under the submatrix equivalence.*)\nLemma addsmx0_id m2 n (A : 'M_n) : (A + (0 : 'M_(m2, n)))%MS = A.\n\n(*This lemma states that the sum of matrices, defined as vertical stacking, is associative with respect to the submatrix equivalence relation.*)\nLemma addsmxA m1 m2 m3 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (A + (B + C) = A + B + C)%MS.\n\nHB.instance Definition _ n :=\n Monoid.isComLaw.Build (matrix F n n) 0%MS addsmx.body\n (@addsmxA n n n n) (@addsmxC n n n) (@adds0mx_id n n).\n\n(*This lemma states that matrix multiplication distributes on the right over matrix sum, with the result being equivalent in the submatrix order.*)\nLemma addsmxMr m1 m2 n p (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(n, p)) :\n ((A + B)%MS *m C :=: A *m C + B *m C)%MS.\n\n(*This lemma states that matrix sum is monotone with respect to the submatrix relation: if a first matrix is a submatrix of a third, and a second matrix is a submatrix of a fourth, then the sum of the first and second is a submatrix of the sum of the third and fourth.*)\nLemma addsmxS m1 m2 m3 m4 n (A : 'M_(m1, n)) (B : 'M_(m2, n))\n (C : 'M_(m3, n)) (D : 'M_(m4, n)) :\n (A <= C -> B <= D -> A + B <= C + D)%MS.\n\n(*This lemma states that if a first matrix is a submatrix of a third, and a second matrix is a submatrix of a fourth, then the element-wise sum of the first and second matrices is a submatrix of the vertical stacking of the third and fourth matrices, provided the first and second matrices have identical dimensions.*)\nLemma addmx_sub_adds m m1 m2 n (A : 'M_(m, n)) (B : 'M_(m, n))\n (C : 'M_(m1, n)) (D : 'M_(m2, n)) :\n (A <= C -> B <= D -> (A + B)%R <= C + D)%MS.\n\n(*This lemma states a left cancellation property for mixed matrix sums: if a matrix B is a submatrix of a matrix A, then vertically stacking A with the element-wise sum of B and a third matrix C results in a matrix equivalent to vertically stacking A with C.*)\nLemma addsmx_addKl n m1 m2 (A : 'M_(m1, n)) (B C : 'M_(m2, n)) :\n (B <= A)%MS -> (A + (B + C)%R :=: A + C)%MS.\n\n(*This lemma states a right cancellation property for mixed matrix sums: if a matrix B is a submatrix of a matrix C, then vertically stacking the element-wise sum of A and B with C is equivalent, in the submatrix order, to vertically stacking A with C.*)\nLemma addsmx_addKr n m1 m2 (A B : 'M_(m1, n)) (C : 'M_(m2, n)) :\n (B <= C)%MS -> ((A + B)%R + C :=: A + C)%MS.\n\n(*This lemma states that matrix addition is compatible with submodule equality, meaning if two pairs of matrices are respectively equal as submodules, their sums are also equal as submodules.*)\nLemma adds_eqmx m1 m2 m3 m4 n (A : 'M_(m1, n)) (B : 'M_(m2, n))\n (C : 'M_(m3, n)) (D : 'M_(m4, n)) :\n (A :=: C -> B :=: D -> A + B :=: C + D)%MS.\n\n(*This lemma states that the submodule generated by the sum of two matrices is equal to the sum of the submodules generated by each individual matrix.*)\nLemma genmx_adds m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (<<(A + B)%MS>> = <> + <>)%MS.\n\n(*This lemma provides an equivalence: a matrix generates a submodule that is contained in the sum of two other submodules if and only if the matrix can be expressed as a linear combination of the generators of those two submodules, where the coefficients are also matrices.*)\nLemma sub_addsmxP m1 m2 m3 n\n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n reflect (exists u, A = u.1 *m B + u.2 *m C) (A <= B + C)%MS.\n\nArguments sub_addsmxP {m1 m2 m3 n A B C}.\n\nVariable I : finType.\nImplicit Type P : pred I.\n\n(*This lemma states that the submodule generated by a finite sum of matrices is equal to the sum of the submodules generated by each individual matrix in the sum.*)\nLemma genmx_sums P n (B_ : I -> 'M_n) :\n <<(\\sum_(i | P i) B_ i)%MS>>%MS = (\\sum_(i | P i) <>)%MS.\n\n(*This lemma states that if a matrix generates a submodule that is contained within another submodule from a given family, then it is also contained within the sum of all submodules from that family.*)\nLemma sumsmx_sup i0 P m n (A : 'M_(m, n)) (B_ : I -> 'M_n) :\n P i0 -> (A <= B_ i0)%MS -> (A <= \\sum_(i | P i) B_ i)%MS.\n\nArguments sumsmx_sup i0 [P m n A B_].\n\n(*This lemma establishes an equivalence: a sum of submodules is contained within another submodule if and only if each submodule in the sum is individually contained in that same submodule.*)\nLemma sumsmx_subP P m n (A_ : I -> 'M_n) (B : 'M_(m, n)) :\n reflect (forall i, P i -> A_ i <= B)%MS (\\sum_(i | P i) A_ i <= B)%MS.\n\n(*This lemma states that if a family of matrices is element-wise contained in another family of matrices in the submodule sense, then the sum of the matrices from the first family generates a submodule that is contained in the sum of the matrices from the second family.*)\nLemma summx_sub_sums P m n (A : I -> 'M[F]_(m, n)) B :\n (forall i, P i -> A i <= B i)%MS ->\n ((\\sum_(i | P i) A i)%R <= \\sum_(i | P i) B i)%MS.\n\n(*This lemma states that if each submodule generated by a matrix in a given family is contained in the submodule generated by the corresponding matrix in a second family, then the sum of the submodules from the first family is contained in the sum of the submodules from the second family.*)\nLemma sumsmxS P n (A B : I -> 'M[F]_n) :\n (forall i, P i -> A i <= B i)%MS ->\n (\\sum_(i | P i) A i <= \\sum_(i | P i) B i)%MS.\n\n(*This lemma shows that matrix summation is compatible with submodule equality. If two families of matrices are such that corresponding matrices generate the same submodule, then their respective matrix sums also generate the same submodule.*)\nLemma eqmx_sums P n (A B : I -> 'M[F]_n) :\n (forall i, P i -> A i :=: B i)%MS ->\n (\\sum_(i | P i) A i :=: \\sum_(i | P i) B i)%MS.\n\n(*This lemma provides an equivalence, stating that a matrix generates a submodule contained in a sum of other submodules if and only if that matrix can be expressed as a sum of matrix products, where each product term involves a generator of one of the submodules in the sum.*)\nLemma sub_sums_genmxP P m n p (A : 'M_(m, p)) (B_ : I -> 'M_(n, p)) :\n reflect (exists u_ : I -> 'M_(m, n), A = \\sum_(i | P i) u_ i *m B_ i)\n (A <= \\sum_(i | P i) <>)%MS.\n\n(*This lemma provides an equivalence, asserting that a matrix generates a submodule contained within a sum of submodules generated by a family of matrices if and only if the first matrix can be written as a linear combination of the matrices in the family, with matrix coefficients.*)\nLemma sub_sumsmxP P m n (A : 'M_(m, n)) (B_ : I -> 'M_n) :\n reflect (exists u_, A = \\sum_(i | P i) u_ i *m B_ i)\n (A <= \\sum_(i | P i) B_ i)%MS.\n\n(*This lemma states a distributivity property: the submodule resulting from the right multiplication of a sum of submodules by a matrix is equal to the sum of submodules generated by right-multiplying each original generator matrix by that same matrix.*)\nLemma sumsmxMr_gen P m n A (B : 'M[F]_(m, n)) :\n ((\\sum_(i | P i) A i)%MS *m B :=: \\sum_(i | P i) <>)%MS.\n\n(*This lemma states that right-multiplying a sum of submodules by a matrix is equivalent to summing the submodules that result from right-multiplying each individual generator matrix by that same matrix.*)\nLemma sumsmxMr P n (A_ : I -> 'M[F]_n) (B : 'M_n) :\n ((\\sum_(i | P i) A_ i)%MS *m B :=: \\sum_(i | P i) (A_ i *m B))%MS.\n\n(*This lemma states that the rank of an m-by-n partial identity matrix is equal to its defining natural number parameter, provided this number does not exceed the matrix dimensions.*)\nLemma rank_pid_mx m n r : r <= m -> r <= n -> \\rank (pid_mx r : 'M_(m, n)) = r.\n\n(*This lemma states that the rank of an n-by-n complementary partial identity matrix, parameterized by a natural number `r` less than or equal to `n`, is equal to the difference between `n` and `r`.*)\nLemma rank_copid_mx n r : r <= n -> \\rank (copid_mx r : 'M_n) = (n - r)%N.\n\n(*This lemma states that the rank of the orthogonal complement of the submodule generated by a matrix is equal to the number of columns of the matrix minus the rank of the matrix itself.*)\nLemma mxrank_compl m n (A : 'M_(m, n)) : \\rank A^C = (n - \\rank A)%N.\n\n(*This lemma states that the rank of a matrix whose rows form a basis for the left kernel of a given m-by-n matrix is equal to `m` minus the rank of the given matrix.*)\nLemma mxrank_ker m n (A : 'M_(m, n)) : \\rank (kermx A) = (m - \\rank A)%N.\n\n(*This lemma states that a matrix representing the basis of the left kernel of a given matrix is the zero matrix if and only if the rows of the given matrix are linearly independent.*)\nLemma kermx_eq0 n m (A : 'M_(m, n)) : (kermx A == 0) = row_free A.\n\n(*This lemma states that the rank of a matrix whose rows form a basis for the right kernel of a given m-by-n matrix is equal to `n` minus the rank of the given matrix.*)\nLemma mxrank_coker m n (A : 'M_(m, n)) : \\rank (cokermx A) = (n - \\rank A)%N.\n\n(*This lemma states that a matrix representing the basis of the right kernel of a given matrix is the zero matrix if and only if the matrix has full row rank.*)\nLemma cokermx_eq0 n m (A : 'M_(m, n)) : (cokermx A == 0) = row_full A.\n\n(*This lemma states that the matrix product of a basis for the left kernel of a matrix and the matrix itself is the zero matrix.*)\nLemma mulmx_ker m n (A : 'M_(m, n)) : kermx A *m A = 0.\n\n(*This lemma states that if the matrix product of a matrix B and a matrix A is the zero matrix, then B can be recovered by multiplying B by a projection matrix constructed from the column echelon form basis of A and the kernel basis of A.*)\nLemma mulmxKV_ker m n p (A : 'M_(n, p)) (B : 'M_(m, n)) :\n B *m A = 0 -> B *m col_ebase A *m kermx A = B.\n\n(*This lemma provides an equivalence: a matrix `B` generates a submodule contained in the left kernel of a matrix `A` if and only if the matrix product of `B` and `A` is the zero matrix.*)\nLemma sub_kermxP p m n (A : 'M_(m, n)) (B : 'M_(p, m)) :\n reflect (B *m A = 0) (B <= kermx A)%MS.\n\n(*This lemma states that the proposition that a matrix `B` generates a submodule contained in the left kernel of a matrix `A` is logically equivalent to the proposition that the matrix product of `B` and `A` equals the zero matrix.*)\nLemma sub_kermx p m n (A : 'M_(m, n)) (B : 'M_(p, m)) :\n (B <= kermx A)%MS = (B *m A == 0).\n\n(*This lemma states that the basis of the left kernel of a zero matrix generates the same submodule as the identity matrix, meaning the kernel is the entire space.*)\nLemma kermx0 m n : (kermx (0 : 'M_(m, n)) :=: 1%:M)%MS.\n\n(*This lemma states a cancellation property for matrix multiplication: if a matrix `B` has linearly independent rows, then the product of another matrix `A` and `B` is the zero matrix if and only if `A` itself is the zero matrix.*)\nLemma mulmx_free_eq0 m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :\n row_free B -> (A *m B == 0) = (A == 0).\n\n(*This lemma states that if the only row vector that yields a zero vector when right-multiplied by a matrix `A` is the zero vector itself, then the rows of matrix `A` are linearly independent.*)\nLemma inj_row_free m n (A : 'M_(m, n)) :\n (forall v : 'rV_m, v *m A = 0 -> v = 0) -> row_free A.\n\n(*This lemma establishes an equivalence: a matrix has linearly dependent rows if and only if there exists at least one row that can be generated as a linear combination of the other rows of the matrix.*)\nLemma row_freePn m n (M : 'M[F]_(m, n)) :\n reflect (exists i, (row i M <= row' i M)%MS) (~~ row_free M).\n\n(*This lemma states that the property of a matrix having linearly dependent rows is logically equivalent to the existence of a row that is in the submodule generated by the remaining rows of the matrix.*)\nLemma negb_row_free m n (M : 'M[F]_(m, n)) :\n ~~ row_free M = [exists i, (row i M <= row' i M)%MS].\n\n(*This lemma states that if the product of an m-by-n matrix and an n-by-p matrix is the zero matrix, then the sum of their ranks is less than or equal to the common inner dimension `n`.*)\nLemma mulmx0_rank_max m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :\n A *m B = 0 -> \\rank A + \\rank B <= n.\n\n(*This lemma states the Frobenius rank inequality: for three conformable matrices, the sum of the rank of the product of the first two and the rank of the product of the last two is less than or equal to the sum of the rank of the middle matrix and the rank of the product of all three.*)\nLemma mxrank_Frobenius m n p q (A : 'M_(m, n)) B (C : 'M_(p, q)) :\n \\rank (A *m B) + \\rank (B *m C) <= \\rank B + \\rank (A *m B *m C).\n\n(*This lemma states Sylvester's rank inequality: for two conformable matrices, the sum of their ranks minus their common inner dimension is less than or equal to the rank of their product.*)\nLemma mxrank_mul_min m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :\n \\rank A + \\rank B - n <= \\rank (A *m B).\n\n(*This lemma states that the sum of the row space of a matrix and its complement results in a matrix with a full row space.*)\nLemma addsmx_compl_full m n (A : 'M_(m, n)) : row_full (A + A^C)%MS.\n\n(*This lemma states that the row space of a given matrix is a subspace of the generic intersection of two other matrix row spaces if and only if it is a subspace of each of those two row spaces individually.*)\nLemma sub_capmx_gen m1 m2 m3 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (A <= capmx_gen B C)%MS = (A <= B)%MS && (A <= C)%MS.\n\n(*This definition provides a proof that a matrix is row-equivalent to its canonical row space representation, with the transformation given by a specific witness matrix.*)\nLet capmx_witnessP m n (A : 'M_(m, n)) : equivmx A (qidmx A) (capmx_witness A).\n\n(*This definition provides a specification asserting that a matrix is row-equivalent to its canonical row space representation, with the transformation given by its normalized form.*)\nLet capmx_normP m n (A : 'M_(m, n)) : equivmx_spec A (qidmx A) (capmx_norm A).\n\n(*This proposition establishes that if two matrices share the same canonical row space identity and are row-equivalent, then their normalized forms are equal.*)\nLet capmx_norm_eq m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n qidmx A = qidmx B -> (A == B)%MS -> capmx_norm A = capmx_norm B.\n\n(*This definition provides a specification asserting that a matrix is row-equivalent to its canonical row space representation, with the transformation given by its no-operation form.*)\nLet capmx_nopP m n (A : 'M_(m, n)) : equivmx_spec A (qidmx A) (capmx_nop A).\n\n(*This proposition states that if a matrix is a canonical identity matrix for a row space, then the row space of any other matrix is a subspace of its row space.*)\nLet sub_qidmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n qidmx B -> (A <= B)%MS.\n\n(*This proposition states that the matrix representing the intersection of the row spaces of two given matrices is a canonical identity matrix if and only if both of the original matrices are canonical identity matrices.*)\nLet qidmx_cap m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n qidmx (A :&: B)%MS = qidmx A && qidmx B.\n\n(*This proposition states that if two matrices have the same canonical row space representation, then the matrix representing their row space intersection is equal to its normalized form.*)\nLet capmx_eq_norm m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n qidmx A = qidmx B -> (A :&: B)%MS = capmx_norm (A :&: B)%MS.\n\n(*This lemma states that the matrix representing the intersection of the row spaces of two matrices is row-equivalent to the matrix generated by the generic row space intersection construction for those two matrices.*)\nLemma capmxE m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :&: B :=: capmx_gen A B)%MS.\n\n(*This lemma states that the intersection of the row spaces of two matrices is a subspace of the row space of the first matrix.*)\nLemma capmxSl m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) : (A :&: B <= A)%MS.\n\n(*This lemma states that the row space of a matrix is a subspace of the intersection of two other row spaces if and only if it is a subspace of each of those two row spaces individually.*)\nLemma sub_capmx m m1 m2 n (A : 'M_(m, n)) (B : 'M_(m1, n)) (C : 'M_(m2, n)) :\n (A <= B :&: C)%MS = (A <= B)%MS && (A <= C)%MS.\n\n(*This lemma states that the intersection of the row spaces of two matrices is commutative.*)\nLemma capmxC m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) : (A :&: B = B :&: A)%MS.\n\n(*This lemma states that the intersection of the row spaces of two matrices is a subspace of the row space of the second matrix.*)\nLemma capmxSr m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) : (A :&: B <= B)%MS.\n\n(*This lemma states that the intersection of the row spaces of two matrices is equivalent to the row space of the second matrix if and only if the row space of the second matrix is a subspace of the first.*)\nLemma capmx_idPr n m1 m2 (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (A :&: B :=: B)%MS (B <= A)%MS.\n\n(*This lemma states that the intersection of the row spaces of two matrices is equivalent to the row space of the first matrix if and only if the row space of the first matrix is a subspace of the second.*)\nLemma capmx_idPl n m1 m2 (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (A :&: B :=: A)%MS (A <= B)%MS.\n\n(*This lemma states that the row space intersection operation is monotonic with respect to the subspace relation.*)\nLemma capmxS m1 m2 m3 m4 n (A : 'M_(m1, n)) (B : 'M_(m2, n))\n (C : 'M_(m3, n)) (D : 'M_(m4, n)) :\n (A <= C -> B <= D -> A :&: B <= C :&: D)%MS.\n\n(*This lemma states that row space intersection is compatible with row equivalence; if two matrices are row-equivalent to two other matrices respectively, then the intersection of the first pair is row-equivalent to the intersection of the second pair.*)\nLemma cap_eqmx m1 m2 m3 m4 n (A : 'M_(m1, n)) (B : 'M_(m2, n))\n (C : 'M_(m3, n)) (D : 'M_(m4, n)) :\n (A :=: C -> B :=: D -> A :&: B :=: C :&: D)%MS.\n\n(*This lemma states that the row space of the product of a row space intersection and a third matrix is a subspace of the intersection of the row spaces of the individual products.*)\nLemma capmxMr m1 m2 n p (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(n, p)) :\n ((A :&: B) *m C <= A *m C :&: B *m C)%MS.\n\n(*This lemma states that the intersection of the row space of a zero matrix with the row space of any other matrix results in a matrix representing the trivial subspace.*)\nLemma cap0mx m1 m2 n (A : 'M_(m2, n)) : ((0 : 'M_(m1, n)) :&: A)%MS = 0.\n\n(*This lemma states that the intersection of the row space of any matrix with the row space of a zero matrix results in a matrix representing the trivial subspace.*)\nLemma capmx0 m1 m2 n (A : 'M_(m1, n)) : (A :&: (0 : 'M_(m2, n)))%MS = 0.\n\n(*This lemma states that if a matrix has a full row space, intersecting any other matrix's row space with it results in a matrix row-equivalent to that other matrix.*)\nLemma capmxT m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n row_full B -> (A :&: B :=: A)%MS.\n\n(*This lemma states that if a matrix has a full row space, its intersection with any other matrix's row space results in a matrix row-equivalent to that other matrix.*)\nLemma capTmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n row_full A -> (A :&: B :=: B)%MS.\n\n(*This proposition asserts that for any square matrix, its no-operation form is equal to the matrix itself.*)\nLet capmx_nop_id n (A : 'M_n) : capmx_nop A = A.\n\n(*This lemma states that for a square matrix, the intersection of the row space of the identity matrix with the matrix's own row space is row-equivalent to the matrix itself.*)\nLemma cap1mx n (A : 'M_n) : (1%:M :&: A = A)%MS.\n\n(*This lemma states that for a square matrix, the intersection of its row space with the row space of the identity matrix is row-equivalent to the matrix itself.*)\nLemma capmx1 n (A : 'M_n) : (A :&: 1%:M = A)%MS.\n\n(*This lemma states that the canonical generator of the intersection of two row spaces is row-equivalent to the intersection of their individual canonical generators.*)\nLemma genmx_cap m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n <>%MS = (<> :&: <>)%MS.\n\n(*This lemma states that the intersection of matrix row spaces is associative.*)\nLemma capmxA m1 m2 m3 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (A :&: (B :&: C) = A :&: B :&: C)%MS.\n\n(*This lemma states that if at least one matrix in an indexed family of matrices represents a subspace of a given matrix, then the intersection of all matrices in that family also represents a subspace of the given matrix.*)\nLemma bigcapmx_inf i0 P m n (A_ : I -> 'M_n) (B : 'M_(m, n)) :\n P i0 -> (A_ i0 <= B -> \\bigcap_(i | P i) A_ i <= B)%MS.\n\n(*This lemma states that a given matrix represents a subspace of the intersection of an indexed family of matrices if and only if it represents a subspace of every matrix in that family.*)\nLemma sub_bigcapmxP P m n (A : 'M_(m, n)) (B_ : I -> 'M_n) :\n reflect (forall i, P i -> A <= B_ i)%MS (A <= \\bigcap_(i | P i) B_ i)%MS.\n\n(*This lemma states that the space generated by the intersection of an indexed family of matrices is equal to the intersection of the spaces generated by each individual matrix in the family.*)\nLemma genmx_bigcap P n (A_ : I -> 'M_n) :\n (<<\\bigcap_(i | P i) A_ i>> = \\bigcap_(i | P i) <>)%MS.\n\n(*This lemma states a modular law for matrix spaces: if a matrix space `A` is a subspace of `C`, then the sum of `A` with the intersection of a space `B` and `C` is equal to the intersection of the sum of `A` and `B` with `C`.*)\nLemma matrix_modl m1 m2 m3 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (A <= C -> A + (B :&: C) :=: (A + B) :&: C)%MS.\n\n(*This lemma states a dual modular law for matrix spaces: if a matrix space `C` is a subspace of `A`, then the sum of the intersection of `A` and a space `B` with `C` is equal to the intersection of `A` with the sum of `B` and `C`.*)\nLemma matrix_modr m1 m2 m3 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) (C : 'M_(m3, n)) :\n (C <= A -> (A :&: B) + C :=: A :&: (B + C))%MS.\n\n(*This lemma states that the intersection of a matrix space with its complement results in the zero matrix space.*)\nLemma capmx_compl m n (A : 'M_(m, n)) : (A :&: A^C)%MS = 0.\n\n(*This lemma states that the sum of the rank of the product of two matrices `A` and `B` and the rank of the intersection of the space of `A` with the kernel space of `B` is equal to the rank of matrix `A`.*)\nLemma mxrank_mul_ker m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :\n (\\rank (A *m B) + \\rank (A :&: kermx B))%N = \\rank A.\n\n(*This lemma provides a condition for rank preservation under matrix multiplication: the rank of the product of two matrices `A` and `f` is equal to the rank of `A` if and only if the intersection of the space of `A` and the kernel space of `f` is the zero matrix space.*)\nLemma mxrank_injP m n p (A : 'M_(m, n)) (f : 'M_(n, p)) :\n reflect (\\rank (A *m f) = \\rank A) ((A :&: kermx f)%MS == 0).\n\n(*This lemma states that if the intersection of two matrix spaces is the zero space, then the rank of the sum of these two spaces is equal to the sum of their individual ranks.*)\nLemma mxrank_disjoint_sum m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :&: B)%MS = 0 -> \\rank (A + B)%MS = (\\rank A + \\rank B)%N.\n\n(*This lemma defines the difference of two matrix spaces, `A` and `B`, as the intersection of space `A` with the complement of the space generated by the intersection of `A` and `B`.*)\nLemma diffmxE m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :\\: B :=: A :&: (capmx_gen A B)^C)%MS.\n\n(*This lemma states that the space generated by the difference of two matrix spaces is equal to that difference itself, indicating the difference is a closed subspace.*)\nLemma genmx_diff m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (<> = A :\\: B)%MS.\n\n(*This lemma states that the difference of two matrix spaces, `A` minus `B`, is a subspace of `A`.*)\nLemma diffmxSl m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) : (A :\\: B <= A)%MS.\n\n(*This lemma states that the intersection of the difference of two matrix spaces, `A` minus `B`, with the matrix space `B` is the zero matrix space.*)\nLemma capmx_diff m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n ((A :\\: B) :&: B)%MS = 0.\n\n(*This lemma states that a matrix space `A` is equal to the sum of two spaces: the difference of `A` and another space `B`, and the intersection of `A` and `B`.*)\nLemma addsmx_diff_cap_eq m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :\\: B + A :&: B :=: A)%MS.\n\n(*This lemma states that the rank of a matrix space `A` is equal to the sum of the rank of its intersection with another space `B` and the rank of its difference with `B`.*)\nLemma mxrank_cap_compl m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (\\rank (A :&: B) + \\rank (A :\\: B))%N = \\rank A.\n\n(*This lemma provides Grassmann's formula for matrix spaces, stating that the sum of the rank of the sum of two spaces and the rank of their intersection is equal to the sum of their individual ranks.*)\nLemma mxrank_sum_cap m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (\\rank (A + B) + \\rank (A :&: B) = \\rank A + \\rank B)%N.\n\n(*This lemma states that the rank of the sum of two matrix spaces is less than or equal to the sum of their individual ranks, with equality holding if and only if their intersection is the zero space.*)\nLemma mxrank_adds_leqif m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n \\rank (A + B) <= \\rank A + \\rank B ?= iff (A :&: B <= (0 : 'M_n))%MS.\n\n(*This lemma states that the rank of a block matrix formed by vertically stacking a given matrix on top of a zero matrix is equal to the rank of the original given matrix.*)\nLemma rank_col_mx0 m n p (A : 'M_(m, n)) :\n \\rank (col_mx A (0 : 'M_(p, n))) = \\rank A.\n\n(*This lemma states that the rank of a block matrix formed by vertically stacking a zero matrix on top of a given matrix is equal to the rank of the original given matrix.*)\nLemma rank_col_0mx m n p (A : 'M_(m, n)) :\n \\rank (col_mx (0 : 'M_(p, n)) A) = \\rank A.\n\n(*This lemma states that the rank of a block matrix formed by horizontally concatenating a given matrix with a zero matrix is equal to the rank of the original given matrix.*)\nLemma rank_row_mx0 m n p (A : 'M_(m, n)) :\n \\rank (row_mx A (0 : 'M_(m, p))) = \\rank A.\n\n(*This lemma states that the rank of a block matrix formed by horizontally concatenating a zero matrix with a given matrix is equal to the rank of the original given matrix.*)\nLemma rank_row_0mx m n p (A : 'M_(m, n)) :\n \\rank (row_mx (0 : 'M_(m, p)) A) = \\rank A.\n\n(*This lemma states that the rank of a block diagonal matrix, constructed from two matrices on the diagonal and zero matrices off-diagonal, is equal to the sum of the ranks of the two diagonal matrices.*)\nLemma rank_diag_block_mx m n p q\n (A : 'M_(m, n)) (B : 'M_(p, q)) :\n \\rank (block_mx A 0 0 B) = (\\rank A + \\rank B)%N.\n\n(*This lemma states that multiplying any matrix by the projection matrix onto a first space along a second space results in a matrix space that is a subspace of the first space.*)\nLemma proj_mx_sub m n U V (W : 'M_(m, n)) : (W *m proj_mx U V <= U)%MS.\n\n(*This lemma states that if a matrix space `W` is a subspace of the sum of two spaces `U` and `V`, then the difference between `W` and its projection onto `U` along `V` is a subspace of `V`.*)\nLemma proj_mx_compl_sub m n U V (W : 'M_(m, n)) :\n (W <= U + V -> W - W *m proj_mx U V <= V)%MS.\n\n(*This lemma states that if two matrix spaces `U` and `V` are disjoint, and a third space `W` is a subspace of `U`, then the projection of `W` onto `U` along `V` is equal to `W` itself.*)\nLemma proj_mx_id m n U V (W : 'M_(m, n)) :\n (U :&: V = 0)%MS -> (W <= U)%MS -> W *m proj_mx U V = W.\n\n(*This lemma states that if two matrix spaces `U` and `V` are disjoint, and a third space `W` is a subspace of `V`, then the projection of `W` onto `U` along `V` is the zero matrix space.*)\nLemma proj_mx_0 m n U V (W : 'M_(m, n)) :\n (U :&: V = 0)%MS -> (W <= V)%MS -> W *m proj_mx U V = 0.\n\n(*This lemma states that if two matrix spaces `U` and `V` are disjoint and a third space `W` is a subspace of their sum, then `W` is equal to the sum of its projection onto `U` along `V` and its projection onto `V` along `U`.*)\nLemma add_proj_mx m n U V (W : 'M_(m, n)) :\n (U :&: V = 0)%MS -> (W <= U + V)%MS ->\n W *m proj_mx U V + W *m proj_mx V U = W.\n\n(*This lemma states that for any two disjoint matrix spaces `U` and `V`, the projection matrix onto `U` along `V` is idempotent, meaning its product with itself is itself.*)\nLemma proj_mx_proj n (U V : 'M_n) :\n let P := proj_mx U V in (U :&: V = 0)%MS -> P *m P = P.\n\n(*This lemma states that if the rank of a matrix `U` is preserved after right-multiplication by a matrix `f`, then there exists an invertible matrix `g` such that the product of `U` and `f` is equal to the product of `U` and `g`.*)\nLemma complete_unitmx m n (U : 'M_(m, n)) (f : 'M_n) :\n \\rank (U *m f) = \\rank U -> {g : 'M_n | g \\in unitmx & U *m f = U *m g}.\n\n(*This lemma states that two matrix spaces `U` and `V` are isomorphic if and only if there exists an invertible matrix `g` such that `U` can be obtained by right-multiplying `V` with `g`.*)\nLemma eqmxMunitP m n (U V : 'M_(m, n)) :\n reflect (exists2 P, P \\in unitmx & U = P *m V) (U == V)%MS.\n\n(*This lemma states that if two matrices with the same number of columns have equal rank, then there exists an invertible square matrix such that the second matrix is row-equivalent to the first matrix multiplied by this invertible matrix.*)\nLemma eq_rank_unitmx m1 m2 n (U : 'M_(m1, n)) (V : 'M_(m2, n)) :\n \\rank U = \\rank V -> {f : 'M_n | f \\in unitmx & V :=: U *m f}%MS.\n\nSection MaxRankSubMatrix.\nVariables (m n : nat) (A : 'M_(m, n)).\n\n(*This definition specifies a function that, for a given matrix, produces an injective finite function selecting a set of row indices, which corresponds to a submatrix whose rank is maximal and equal to the rank of the original matrix.*)\nDefinition maxrankfun : 'I_m ^ \\rank A :=\n [arg max_(f > finfun (widen_ord (rank_leq_row A))) \\rank (rowsub f A)].\n(*A local notation for the function that selects row indices to form a maximal rank submatrix.*)\nLocal Notation mxf := maxrankfun.\n\n(*This lemma asserts that the submatrix formed by selecting rows of a given matrix, using the function that maximizes the rank of the resulting submatrix, has linearly independent rows.*)\nLemma maxrowsub_free : row_free (rowsub mxf A).\n\n(*This lemma states that the submatrix formed by selecting rows to achieve maximal rank is row-equivalent to the original matrix, meaning they share the same row space.*)\nLemma eq_maxrowsub : (rowsub mxf A :=: A)%MS.\n\n(*This lemma proves that the function selecting row indices to form a maximal rank submatrix is injective, ensuring that it always selects distinct rows.*)\nLemma maxrankfun_inj : injective mxf.\n\nVariable (rkA : row_full A).\n\n(*This lemma establishes that the submatrix created by selecting rows to achieve maximal rank has full row rank, meaning its rank is equal to its number of rows.*)\nLemma maxrowsub_full : row_full (rowsub mxf A).\n\nHint Resolve maxrowsub_full : core.\n\n(*This definition specifies a function that, for a matrix with full column rank, selects a set of row indices to form a square submatrix of maximal rank. It is constructed from the general maximal rank submatrix function under the assumption that the matrix's rank equals its number of columns.*)\nDefinition fullrankfun : 'I_m ^ n := finfun (mxf \\o cast_ord (esym (eqP rkA))).\n(*A local notation for the function that selects row indices to form a full-rank square submatrix.*)\nLocal Notation frf := fullrankfun.\n\n(*This lemma asserts that the square submatrix formed by selecting rows using the full-rank selection function has full row rank.*)\nLemma fullrowsub_full : row_full (rowsub frf A).\n\n(*This lemma states that the square submatrix created by selecting rows using the full-rank selection function is an invertible matrix.*)\nLemma fullrowsub_unit : rowsub frf A \\in unitmx.\n\n(*This lemma establishes that the square submatrix formed by selecting rows via the full-rank selection function has linearly independent rows.*)\nLemma fullrowsub_free : row_free (rowsub frf A).\n\n(*This lemma proves that the rank of the square submatrix, obtained by applying the full-rank row selection function, is equal to the number of columns of the original matrix.*)\nLemma mxrank_fullrowsub : \\rank (rowsub frf A) = n.\n\n(*This lemma states that the square submatrix formed using the full-rank row selection function is row-equivalent to the original matrix, indicating they have the same row space.*)\nLemma eq_fullrowsub : (rowsub frf A :=: A)%MS.\n\n(*This lemma proves that the function for selecting rows to form a full-rank square submatrix is injective, meaning it selects distinct rows.*)\nLemma fullrankfun_inj : injective frf.\n\nEnd MaxRankSubMatrix.\n\nSection SumExpr.\n\n(*An inductive proposition that formally associates a matrix with a natural number, representing a potential rank. For a base matrix, this number is its actual rank. For a vertical block matrix sum, it is the sum of the numbers associated with each block.*)\nInductive mxsum_spec n : forall m, 'M[F]_(m, n) -> nat -> Prop :=\n | TrivialMxsum m A\n : @mxsum_spec n m A (\\rank A)\n | ProperMxsum m1 m2 T1 T2 r1 r2 of\n @mxsum_spec n m1 T1 r1 & @mxsum_spec n m2 T2 r2\n : mxsum_spec (T1 + T2)%MS (r1 + r2)%N.\nArguments mxsum_spec {n%_N m%_N} T%_MS r%_N.\n\n(*A structure that pairs a matrix with a natural number, called the formal rank sum, along with a proof that this pair satisfies the matrix sum specification.*)\nStructure mxsum_expr m n := Mxsum {\n(*A function that returns a matrix whose row space represents the sum of the subspaces in a matrix sum expression.*)\n mxsum_val :> wrapped 'M_(m, n);\n(*A function that returns the rank of the matrix sum expression, which is the dimension of the sum of the represented subspaces.*)\n mxsum_rank : wrapped nat;\n _ : mxsum_spec (unwrap mxsum_val) (unwrap mxsum_rank)\n}.\n\nCanonical trivial_mxsum m n A :=\n @Mxsum m n (Wrap A) (Wrap (\\rank A)) (TrivialMxsum A).\n\n(*A structure that bundles a square matrix with an associated natural number representing its formal rank sum, accompanied by a proof that this association adheres to the matrix sum specification.*)\nStructure proper_mxsum_expr n := ProperMxsumExpr {\n(*A function that returns a matrix whose row space represents the sum of subspaces for a matrix sum expression that is known to be a direct sum.*)\n proper_mxsum_val :> 'M_n;\n(*A function that returns the rank of a matrix sum expression known to be a direct sum, which is equal to the sum of the ranks of the component subspaces.*)\n proper_mxsum_rank : nat;\n _ : mxsum_spec proper_mxsum_val proper_mxsum_rank\n}.\n\n(*This definition extracts the underlying proof term from a proper matrix sum expression, which justifies the association between the matrix and its formal rank sum.*)\nDefinition proper_mxsumP n (S : proper_mxsum_expr n) :=\n let: ProperMxsumExpr _ _ termS := S return mxsum_spec S (proper_mxsum_rank S)\n in termS.\n\nCanonical sum_mxsum n (S : proper_mxsum_expr n) :=\n @Mxsum n n (wrap (S : 'M_n)) (wrap (proper_mxsum_rank S)) (proper_mxsumP S).\n\nSection Binary.\nVariable (m1 m2 n : nat) (S1 : mxsum_expr m1 n) (S2 : mxsum_expr m2 n).\n(*A proof term establishing that the matrix sum specification holds for the vertical block sum of two matrices from matrix sum expressions, with the formal rank sum being the sum of their individual formal rank sums.*)\nFact binary_mxsum_proof :\n mxsum_spec (unwrap S1 + unwrap S2)\n (unwrap (mxsum_rank S1) + unwrap (mxsum_rank S2)).\n\nCanonical binary_mxsum_expr := ProperMxsumExpr binary_mxsum_proof.\nEnd Binary.\n\nSection Nary.\nContext J (r : seq J) (P : pred J) n (S_ : J -> mxsum_expr n n).\n(*A proof term demonstrating that the matrix sum specification is satisfied for an iterated vertical block sum of matrices from a family of matrix sum expressions, where the resulting formal rank sum is the sum of the individual formal rank sums.*)\nFact nary_mxsum_proof :\n mxsum_spec (\\sum_(j <- r | P j) unwrap (S_ j))\n (\\sum_(j <- r | P j) unwrap (mxsum_rank (S_ j))).\n\nCanonical nary_mxsum_expr := ProperMxsumExpr nary_mxsum_proof.\nEnd Nary.\n\n(*This definition provides a boolean predicate that evaluates to true if and only if the actual rank of the matrix within a matrix sum expression is equal to its associated formal rank sum.*)\nDefinition mxdirect_def m n T of phantom 'M_(m, n) (unwrap (mxsum_val T)) :=\n \\rank (unwrap T) == unwrap (mxsum_rank T).\n\nEnd SumExpr.\n\nNotation mxdirect A := (mxdirect_def (Phantom 'M_(_,_) A%MS)).\n\n(*This lemma establishes the logical equivalence between the boolean condition for a direct matrix sum and the proposition that the actual rank of the matrix in a proper matrix sum expression equals its formal rank sum.*)\nLemma mxdirectP n (S : proper_mxsum_expr n) :\n reflect (\\rank S = proper_mxsum_rank S) (mxdirect S).\n\nArguments mxdirectP {n S}.\n\n(*This lemma states that a trivial matrix sum expression, which is constructed from a single matrix where the formal rank is its actual rank, always satisfies the direct sum condition.*)\nLemma mxdirect_trivial m n A : mxdirect (unwrap (@trivial_mxsum m n A)).\n\n(*This lemma states that the actual rank of the matrix in a matrix sum expression is less than or equal to its formal rank sum, and moreover, equality holds if and only if the expression satisfies the direct sum condition.*)\nLemma mxrank_sum_leqif m n (S : mxsum_expr m n) :\n \\rank (unwrap S) <= unwrap (mxsum_rank S) ?= iff mxdirect (unwrap S).\n\n(*This lemma provides an equational characterization of the direct sum condition, stating that it is equivalent to the boolean equality between the actual rank of the matrix and its formal rank sum.*)\nLemma mxdirectE m n (S : mxsum_expr m n) :\n mxdirect (unwrap S) = (\\rank (unwrap S) == unwrap (mxsum_rank S)).\n\n(*This lemma states that the direct sum condition for a matrix sum expression is equivalent to the boolean condition that the actual rank of the matrix is greater than or equal to its formal rank sum.*)\nLemma mxdirectEgeq m n (S : mxsum_expr m n) :\n mxdirect (unwrap S) = (\\rank (unwrap S) >= unwrap (mxsum_rank S)).\n\nSection BinaryDirect.\n\nVariables m1 m2 n : nat.\n\n(*This lemma asserts that the vertical block sum of two matrix sum expressions satisfies the direct sum condition if and only if both individual expressions are direct and the intersection of the row spaces of their matrices is trivial.*)\nLemma mxdirect_addsE (S1 : mxsum_expr m1 n) (S2 : mxsum_expr m2 n) :\n mxdirect (unwrap S1 + unwrap S2)\n = [&& mxdirect (unwrap S1), mxdirect (unwrap S2)\n & unwrap S1 :&: unwrap S2 == 0]%MS.\n\n(*This lemma establishes that for two matrices, the condition for their vertical block sum to be a direct sum is logically equivalent to the intersection of their row spaces being the trivial space.*)\nLemma mxdirect_addsP (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n reflect (A :&: B = 0)%MS (mxdirect (A + B)).\n\nEnd BinaryDirect.\n\nSection NaryDirect.\n\nVariables (P : pred I) (n : nat).\n\n(*This local definition specifies a condition for a given matrix in a family, asserting that its row space has a trivial intersection with the space spanned by the rows of all other matrices in the family that satisfy a given predicate.*)\nLet TIsum A_ i := (A_ i :&: (\\sum_(j | P j && (j != i)) A_ j) = 0 :> 'M_n)%MS.\n\n(*This lemma states that a sum of matrix expressions is a direct sum if and only if each individual expression corresponds to a direct matrix and the collection satisfies a specific structural property for iterated sums.*)\nLet mxdirect_sums_recP (S_ : I -> mxsum_expr n n) :\n reflect (forall i, P i -> mxdirect (unwrap (S_ i)) /\\ TIsum (unwrap \\o S_) i)\n (mxdirect (\\sum_(i | P i) (unwrap (S_ i)))).\n\n(*This lemma states that a sum of matrices is a direct sum if and only if for each matrix in the collection, its intersection with the sum of all other matrices in the collection is the zero matrix space.*)\nLemma mxdirect_sumsP (A_ : I -> 'M_n) :\n reflect (forall i, P i -> A_ i :&: (\\sum_(j | P j && (j != i)) A_ j) = 0)%MS\n (mxdirect (\\sum_(i | P i) A_ i)).\n\n(*This lemma states that a sum of matrix expressions is a direct sum if and only if two conditions hold: first, every individual underlying matrix is direct, and second, the sum of these underlying matrices is itself a direct sum.*)\nLemma mxdirect_sumsE (S_ : I -> mxsum_expr n n) (xunwrap := unwrap) :\n reflect (and (forall i, P i -> mxdirect (unwrap (S_ i)))\n (mxdirect (\\sum_(i | P i) (xunwrap (S_ i)))))\n (mxdirect (\\sum_(i | P i) (unwrap (S_ i)))).\n\nEnd NaryDirect.\n\nSection SubDaddsmx.\n\nVariables m m1 m2 n : nat.\nVariables (A : 'M[F]_(m, n)) (B1 : 'M[F]_(m1, n)) (B2 : 'M[F]_(m2, n)).\n\n(*This lemma states that the rank of a matrix representing a direct sum of two subspaces is equal to the sum of the ranks of the matrices representing the individual subspaces.*)\nVariant sub_daddsmx_spec : Prop :=\n SubDaddsmxSpec A1 A2 of (A1 <= B1)%MS & (A2 <= B2)%MS & A = A1 + A2\n & forall C1 C2, (C1 <= B1)%MS -> (C2 <= B2)%MS ->\n A = C1 + C2 -> C1 = A1 /\\ C2 = A2.\n\n(*This lemma states that if a matrix is a submatrix of the sum of two matrices with zero intersection, then it admits a unique decomposition into two component matrices, where each component is a submatrix of the corresponding matrix from the original sum.*)\nLemma sub_daddsmx : (B1 :&: B2 = 0)%MS -> (A <= B1 + B2)%MS -> sub_daddsmx_spec.\n\nEnd SubDaddsmx.\n\nSection SubDsumsmx.\n\nVariables (P : pred I) (m n : nat) (A : 'M[F]_(m, n)) (B : I -> 'M[F]_n).\n\n(*This lemma states that the rank of a matrix representing a direct sum of a family of subspaces is equal to the sum of the ranks of all matrices in the family.*)\nVariant sub_dsumsmx_spec : Prop :=\n SubDsumsmxSpec A_ of forall i, P i -> (A_ i <= B i)%MS\n & A = \\sum_(i | P i) A_ i\n & forall C, (forall i, P i -> C i <= B i)%MS ->\n A = \\sum_(i | P i) C i -> {in SimplPred P, C =1 A_}.\n\n(*This lemma states that if a matrix is a submatrix of a direct sum of a family of matrices, then it can be uniquely expressed as a sum of component matrices, where each component is a submatrix of the corresponding matrix in the original family.*)\nLemma sub_dsumsmx :\n mxdirect (\\sum_(i | P i) B i) -> (A <= \\sum_(i | P i) B i)%MS ->\n sub_dsumsmx_spec.\n\nEnd SubDsumsmx.\n\nSection Eigenspace.\n\nVariables (n : nat) (g : 'M_n).\n\n(*This definition specifies the eigenspace of a square matrix for a given scalar as the kernel of the matrix resulting from subtracting the identity matrix scaled by that scalar from the square matrix.*)\nDefinition eigenspace a := kermx (g - a%:M).\n(*This definition specifies that a scalar is an eigenvalue of a matrix if the eigenspace corresponding to that scalar is not the zero matrix space.*)\nDefinition eigenvalue : pred F := fun a => eigenspace a != 0.\n\n(*This lemma states that a matrix represents a subspace of an eigenspace if and only if multiplying this matrix on the right by the original square matrix is equivalent to scaling the matrix by the corresponding eigenvalue.*)\nLemma eigenspaceP a m (W : 'M_(m, n)) :\n reflect (W *m g = a *: W) (W <= eigenspace a)%MS.\n\n(*This lemma states that a scalar is an eigenvalue of a matrix if and only if there exists a non-zero row vector such that multiplying the vector by the matrix results in the original vector scaled by the scalar.*)\nLemma eigenvalueP a :\n reflect (exists2 v : 'rV_n, v *m g = a *: v & v != 0) (eigenvalue a).\n\nNotation stablemx V f := (V%MS *m f%R <= V%MS)%MS.\n\n(*This lemma states that a row vector's subspace is stable under multiplication by a square matrix if and only if that vector belongs to an eigenspace of the matrix for some scalar.*)\nLemma eigenvectorP {v : 'rV_n} :\n reflect (exists a, (v <= eigenspace a)%MS) (stablemx v g).\n\n(*This lemma states that the sum of the eigenspaces associated with a set of distinct eigenvalues of a matrix is a direct sum.*)\nLemma mxdirect_sum_eigenspace (P : pred I) a_ :\n {in P &, injective a_} -> mxdirect (\\sum_(i | P i) eigenspace (a_ i)).\n\nEnd Eigenspace.\n\nEnd RowSpaceTheory.\n\n#[global] Hint Resolve submx_refl : core.\nArguments submxP {F m1 m2 n A B}.\nArguments eq_row_sub [F m n v A].\nArguments row_subP {F m1 m2 n A B}.\nArguments rV_subP {F m1 m2 n A B}.\nArguments row_subPn {F m1 m2 n A B}.\nArguments sub_rVP {F n u v}.\nArguments rV_eqP {F m1 m2 n A B}.\nArguments rowV0Pn {F m n A}.\nArguments rowV0P {F m n A}.\nArguments eqmx0P {F m n A}.\nArguments row_fullP {F m n A}.\nArguments row_freeP {F m n A}.\nArguments eqmxP {F m1 m2 n A B}.\nArguments genmxP {F m1 m2 n A B}.\nArguments addsmx_idPr {F m1 m2 n A B}.\nArguments addsmx_idPl {F m1 m2 n A B}.\nArguments sub_addsmxP {F m1 m2 m3 n A B C}.\nArguments sumsmx_sup [F I] i0 [P m n A B_].\nArguments sumsmx_subP {F I P m n A_ B}.\nArguments sub_sumsmxP {F I P m n A B_}.\nArguments sub_kermxP {F p m n A B}.\nArguments capmx_idPr {F n m1 m2 A B}.\nArguments capmx_idPl {F n m1 m2 A B}.\nArguments bigcapmx_inf [F I] i0 [P m n A_ B].\nArguments sub_bigcapmxP {F I P m n A B_}.\nArguments mxrank_injP {F m n} p {A f}.\nArguments mxdirectP {F n S}.\nArguments mxdirect_addsP {F m1 m2 n A B}.\nArguments mxdirect_sumsP {F I P n A_}.\nArguments mxdirect_sumsE {F I P n S_}.\nArguments eigenspaceP {F n g a m W}.\nArguments eigenvalueP {F n g a}.\nArguments submx_rowsub [F m1 m2 m3 n] h [f g A] _ : rename.\nArguments eqmx_rowsub [F m1 m2 m3 n] h [f g A] _ : rename.\n\nArguments mxrank {F m%_N n%_N} A%_MS.\nArguments complmx {F m%_N n%_N} A%_MS.\nArguments row_full {F m%_N n%_N} A%_MS.\nArguments submx {F m1%_N m2%_N n%_N} A%_MS B%_MS : rename.\nArguments ltmx {F m1%_N m2%_N n%_N} A%_MS B%_MS.\nArguments eqmx {F m1%_N m2%_N n%_N} A%_MS B%_MS.\nArguments addsmx {F m1%_N m2%_N n%_N} A%_MS B%_MS : rename.\nArguments capmx {F m1%_N m2%_N n%_N} A%_MS B%_MS : rename.\nArguments diffmx {F m1%_N m2%_N n%_N} A%_MS B%_MS : rename.\nArguments genmx {F m%_N n%_N} A%_R : rename.\n(*A notation that represents the rank of a matrix.*)\nNotation \"\\rank A\" := (mxrank A) : nat_scope.\n(*A notation that represents the row space generated by a given matrix.*)\nNotation \"<< A >>\" := (genmx A) : matrix_set_scope.\n(*A notation that represents the orthogonal complement of the row space of a given matrix.*)\nNotation \"A ^C\" := (complmx A) : matrix_set_scope.\n(*A notation that signifies that the row space of one matrix is a subspace of the row space of another.*)\nNotation \"A <= B\" := (submx A B) : matrix_set_scope.\n(*A notation that signifies that the row space of one matrix is a proper subspace of the row space of another.*)\nNotation \"A < B\" := (ltmx A B) : matrix_set_scope.\n(*A chained notation signifying that the row space of one matrix is a subspace of the row space of a second matrix, which in turn is a subspace of the row space of a third matrix.*)\nNotation \"A <= B <= C\" := ((submx A B) && (submx B C)) : matrix_set_scope.\n(*A chained notation signifying that the row space of one matrix is a proper subspace of the row space of a second matrix, which in turn is a subspace of the row space of a third matrix.*)\nNotation \"A < B <= C\" := (ltmx A B && submx B C) : matrix_set_scope.\n(*A chained notation signifying that the row space of one matrix is a subspace of the row space of a second matrix, which in turn is a proper subspace of the row space of a third matrix.*)\nNotation \"A <= B < C\" := (submx A B && ltmx B C) : matrix_set_scope.\n(*A chained notation signifying that the row space of one matrix is a proper subspace of the row space of a second matrix, which in turn is a proper subspace of the row space of a third matrix.*)\nNotation \"A < B < C\" := (ltmx A B && ltmx B C) : matrix_set_scope.\n(*A notation signifying that the row spaces of two matrices are equal.*)\nNotation \"A == B\" := ((submx A B) && (submx B A)) : matrix_set_scope.\n(*A notation that signifies that two matrices represent the same row space.*)\nNotation \"A :=: B\" := (eqmx A B) : matrix_set_scope.\n(*A notation that represents the sum of the row spaces of two matrices.*)\nNotation \"A + B\" := (addsmx A B) : matrix_set_scope.\n(*A notation that represents the intersection of the row spaces of two matrices.*)\nNotation \"A :&: B\" := (capmx A B) : matrix_set_scope.\n(*A notation for the difference between two row spaces, representing the intersection of the first row space with the orthogonal complement of the second.*)\nNotation \"A :\\: B\" := (diffmx A B) : matrix_set_scope.\nNotation mxdirect S := (mxdirect_def (Phantom 'M_(_,_) S%MS)).\n\n(*A notation for the sum of the row spaces of matrices from a collection indexed by elements in a list that satisfy a given predicate.*)\nNotation \"\\sum_ ( i <- r | P ) B\" :=\n (\\big[addsmx/0%R]_(i <- r | P%B) B%MS) : matrix_set_scope.\n(*A notation for the sum of the row spaces of matrices from a collection indexed by the elements of a given list.*)\nNotation \"\\sum_ ( i <- r ) B\" :=\n (\\big[addsmx/0%R]_(i <- r) B%MS) : matrix_set_scope.\n(*A notation for the sum of the row spaces of matrices from a collection indexed by a range of natural numbers that satisfy a given predicate.*)\nNotation \"\\sum_ ( m <= i < n | P ) B\" :=\n (\\big[addsmx/0%R]_(m <= i < n | P%B) B%MS) : matrix_set_scope.\n(*A notation for the sum of the row spaces of matrices from a collection indexed by a given range of natural numbers.*)\nNotation \"\\sum_ ( m <= i < n ) B\" :=\n (\\big[addsmx/0%R]_(m <= i < n) B%MS) : matrix_set_scope.\n(*A notation for the sum of the row spaces of matrices from a collection, where the sum is taken over all indices satisfying a given predicate.*)\nNotation \"\\sum_ ( i | P ) B\" :=\n (\\big[addsmx/0%R]_(i | P%B) B%MS) : matrix_set_scope.\n(*This notation defines the sum of a family of matrix sets indexed by a variable, where the range of the index is inferred from the context.*)\nNotation \"\\sum_ i B\" :=\n (\\big[addsmx/0%R]_i B%MS) : matrix_set_scope.\n(*This notation defines the sum of a family of matrix sets over an index that belongs to a given finite type and satisfies a specific boolean property.*)\nNotation \"\\sum_ ( i : t | P ) B\" :=\n (\\big[addsmx/0%R]_(i : t | P%B) B%MS) (only parsing) : matrix_set_scope.\n(*This notation defines the sum of a family of matrix sets over an index that ranges over all elements of a given finite type.*)\nNotation \"\\sum_ ( i : t ) B\" :=\n (\\big[addsmx/0%R]_(i : t) B%MS) (only parsing) : matrix_set_scope.\n(*This notation defines the sum of a family of matrix sets over a natural number index that is strictly less than a given bound and satisfies a specific boolean property.*)\nNotation \"\\sum_ ( i < n | P ) B\" :=\n (\\big[addsmx/0%R]_(i < n | P%B) B%MS) : matrix_set_scope.\n(*This notation defines the sum of a family of matrix sets over a natural number index that is strictly less than a given bound.*)\nNotation \"\\sum_ ( i < n ) B\" :=\n (\\big[addsmx/0%R]_(i < n) B%MS) : matrix_set_scope.\n(*This notation defines the sum of a family of matrix sets over an index that is an element of a given set and satisfies a specific boolean property.*)\nNotation \"\\sum_ ( i 'in' A | P ) B\" :=\n (\\big[addsmx/0%R]_(i in A | P%B) B%MS) : matrix_set_scope.\n(*This notation defines the sum of a family of matrix sets over an index that ranges over all elements of a given set.*)\nNotation \"\\sum_ ( i 'in' A ) B\" :=\n (\\big[addsmx/0%R]_(i in A) B%MS) : matrix_set_scope.\n\n(*This notation defines the intersection of a family of matrix sets over an index drawn from a given finite sequence that also satisfies a specific boolean property.*)\nNotation \"\\bigcap_ ( i <- r | P ) B\" :=\n (\\big[capmx/1%:M]_(i <- r | P%B) B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over an index that ranges over all elements of a given finite sequence.*)\nNotation \"\\bigcap_ ( i <- r ) B\" :=\n (\\big[capmx/1%:M]_(i <- r) B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over a natural number index within a given range, which also satisfies a specific boolean property.*)\nNotation \"\\bigcap_ ( m <= i < n | P ) B\" :=\n (\\big[capmx/1%:M]_(m <= i < n | P%B) B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over a natural number index that ranges from a given lower bound up to, but not including, an upper bound.*)\nNotation \"\\bigcap_ ( m <= i < n ) B\" :=\n (\\big[capmx/1%:M]_(m <= i < n) B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets indexed by a variable that satisfies a specific boolean property, where the range of the index is inferred from the context.*)\nNotation \"\\bigcap_ ( i | P ) B\" :=\n (\\big[capmx/1%:M]_(i | P%B) B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets indexed by a variable, where the range of the index is inferred from the context.*)\nNotation \"\\bigcap_ i B\" :=\n (\\big[capmx/1%:M]_i B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over an index that belongs to a given finite type and satisfies a specific boolean property.*)\nNotation \"\\bigcap_ ( i : t | P ) B\" :=\n (\\big[capmx/1%:M]_(i : t | P%B) B%MS) (only parsing) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over an index that ranges over all elements of a given finite type.*)\nNotation \"\\bigcap_ ( i : t ) B\" :=\n (\\big[capmx/1%:M]_(i : t) B%MS) (only parsing) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over a natural number index that is strictly less than a given bound and satisfies a specific boolean property.*)\nNotation \"\\bigcap_ ( i < n | P ) B\" :=\n (\\big[capmx/1%:M]_(i < n | P%B) B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over a natural number index that is strictly less than a given bound.*)\nNotation \"\\bigcap_ ( i < n ) B\" :=\n (\\big[capmx/1%:M]_(i < n) B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over an index that is an element of a given set and satisfies a specific boolean property.*)\nNotation \"\\bigcap_ ( i 'in' A | P ) B\" :=\n (\\big[capmx/1%:M]_(i in A | P%B) B%MS) : matrix_set_scope.\n(*This notation defines the intersection of a family of matrix sets over an index that ranges over all elements of a given set.*)\nNotation \"\\bigcap_ ( i 'in' A ) B\" :=\n (\\big[capmx/1%:M]_(i in A) B%MS) : matrix_set_scope.\n\nSection Stability.\n\nVariable (F : fieldType).\n\n(*This lemma states that if two matrix sets are equal, then the property that the first set is stable under right multiplication by a given square matrix holds if and only if the second set is also stable under the same multiplication.*)\nLemma eqmx_stable m m' n (V : 'M[F]_(m, n)) (V' : 'M[F]_(m', n)) (f : 'M[F]_n) :\n (V :=: V')%MS -> stablemx V f = stablemx V' f.\n\nSection FixedDim.\n\nVariables (m n : nat) (V W : 'M[F]_(m, n)) (f g : 'M[F]_n).\n\n(*This lemma states that a matrix set representing a collection of row vectors is stable under right multiplication by a square matrix if and only if the vector space generated by these row vectors is also stable under the same multiplication.*)\nLemma stablemx_row_base : (stablemx (row_base V) f) = (stablemx V f).\n\n(*This lemma states that if a matrix set spans the entire vector space of row vectors of a given dimension, then it is stable under right multiplication by any compatible square matrix.*)\nLemma stablemx_full : row_full V -> stablemx V f. \n\n(*This lemma states that if a matrix set is stable under right multiplication by two separate square matrices, then it is also stable under right multiplication by the matrix product of those two matrices.*)\nLemma stablemxM : stablemx V f -> stablemx V g -> stablemx V (f *m g).\n\n(*This lemma states that if a matrix set is stable under right multiplication by two separate square matrices, then it is also stable under right multiplication by the sum of those two matrices.*)\nLemma stablemxD : stablemx V f -> stablemx V g -> stablemx V (f + g).\n\n(*This lemma states that a matrix set is stable under right multiplication by a given square matrix if and only if it is also stable under right multiplication by the additive inverse of that matrix.*)\nLemma stablemxN : stablemx V (- f) = stablemx V f.\n\n(*This lemma states that any matrix set is stable under right multiplication by any scalar matrix.*)\nLemma stablemxC x : stablemx V x%:M.\n\n(*This lemma states that any matrix set is stable under right multiplication by the zero matrix.*)\nLemma stablemx0 : stablemx V 0. \n\n(*This lemma states that if two matrix sets are both stable under right multiplication by the same square matrix, then their sum as matrix sets is also stable under right multiplication by that same matrix.*)\nLemma stableDmx : stablemx V f -> stablemx W f -> stablemx (V + W)%MS f.\n\n(*This lemma states that a matrix set is stable under right multiplication by a square matrix if and only if the set containing the additive inverses of its elements is also stable under the same multiplication.*)\nLemma stableNmx : stablemx (- V) f = stablemx V f.\n\n(*This lemma states that the zero matrix set, which contains only the zero matrix, is stable under right multiplication by any compatible square matrix.*)\nLemma stable0mx : stablemx (0 : 'M_(m, n)) f. \n\nEnd FixedDim.\n\n(*This lemma states that the matrix representation of a given element is stable under the action of a given matrix.*)\nLemma stableCmx (m n : nat) x (f : 'M[F]_(m, n)) : stablemx x%:M f.\n\n(*This lemma states that if a collection of matrix subspaces, indexed by a finite type, are all individually stable under the action of a given matrix, then the sum of these subspaces is also stable under the same matrix.*)\nLemma stablemx_sums (n : nat) (I : finType) (V_ : I -> 'M[F]_n) (f : 'M_n) :\n (forall i, stablemx (V_ i) f) -> stablemx (\\sum_i V_ i)%MS f.\n\n(*This lemma states that if a matrix subspace is a unit subspace, representing the entire vector space, then it is stable under the action of any square matrix of the appropriate dimension.*)\nLemma stablemx_unit (n : nat) (V f : 'M[F]_n) : V \\in unitmx -> stablemx V f.\n\nSection Commutation.\n\nVariable (n : nat).\nImplicit Types (f g : 'M[F]_n).\n\n(*This lemma states that if two square matrices commute, then the image of the first matrix is a stable subspace under the action of the second matrix.*)\nLemma comm_mx_stable (f g : 'M[F]_n) : comm_mx f g -> stablemx f g.\n\n(*This lemma states that if two square matrices commute, then the kernel of the first matrix is a stable subspace under the action of the second matrix.*)\nLemma comm_mx_stable_ker (f g : 'M[F]_n) :\n comm_mx f g -> stablemx (kermx f) g.\n\n(*This lemma states that if two square matrices commute, then for any given scalar, the corresponding eigenspace of the first matrix is a stable subspace under the action of the second matrix.*)\nLemma comm_mx_stable_eigenspace (f g : 'M[F]_n) a :\n comm_mx f g -> stablemx (eigenspace f a) g.\n\nEnd Commutation.\n\nEnd Stability.\n\nSection DirectSums.\nVariables (F : fieldType) (I : finType) (P : pred I).\n\n(*This lemma asserts that the sum of a collection of one-dimensional matrix subspaces is a direct sum, provided that the function generating the basis vector for each subspace is injective on the index set.*)\nLemma mxdirect_delta n f : {in P &, injective f} ->\n mxdirect (\\sum_(i | P i) <>).\n\nEnd DirectSums.\n\nSection CardGL.\n\nVariable F : finFieldType.\n\n(*This lemma provides a formula for the number of elements in the general linear group of a given positive dimension over a finite field, expressing it as the product of a power of the field's cardinality and a product of terms related to powers of the field's cardinality.*)\nLemma card_GL n : n > 0 ->\n #|'GL_n[F]| = (#|F| ^ 'C(n, 2) * \\prod_(1 <= i < n.+1) (#|F| ^ i - 1))%N.\n\n(*This lemma provides a formula for the cardinality of the general linear group of a given positive dimension over a finite field, derived using LUP decomposition. The formula is expressed as the product of a power of the field's cardinality and a product over terms involving powers of the field's cardinality.*)\nLemma LUP_card_GL n : n > 0 ->\n #|'GL_n[F]| = (#|F| ^ 'C(n, 2) * \\prod_(1 <= i < n.+1) (#|F| ^ i - 1))%N.\n\n(*This lemma states that the number of elements in the one-dimensional general linear group over a finite field is equal to the cardinality of the field minus one.*)\nLemma card_GL_1 : #|'GL_1[F]| = #|F|.-1.\n\n(*This lemma gives the specific formula for the number of elements in the two-dimensional general linear group over a finite field.*)\nLemma card_GL_2 : #|'GL_2[F]| = (#|F| * #|F|.-1 ^ 2 * #|F|.+1)%N.\n\nEnd CardGL.\n\n(*This lemma states that for a prime number, the exponent of that prime in the prime factorization of the number of elements in the general linear group of a given dimension over the prime field is equal to the binomial coefficient of the dimension taken two at a time.*)\nLemma logn_card_GL_p n p : prime p -> logn p #|'GL_n(p)| = 'C(n, 2).\n\nSection MatrixAlgebra.\n\nVariables F : fieldType.\n\n(*A local notation that expresses that a given matrix is an element of a given matrix subspace.*)\nLocal Notation \"A \\in R\" := (@submx F _ _ _ (mxvec A) R).\n\n(*This lemma states that the zero matrix is always an element of any matrix subspace.*)\nLemma mem0mx m n (R : 'A_(m, n)) : 0 \\in R.\n\n(*This lemma states that if a matrix is an element of the zero matrix subspace, then that matrix must be the zero matrix.*)\nLemma memmx0 n A : (A \\in (0 : 'A_n)) -> A = 0.\n\n(*This lemma establishes an equivalence: a square matrix is an element of the subspace spanned by the identity matrix if and only if that matrix is a scalar matrix.*)\nLemma memmx1 n (A : 'M_n) : (A \\in mxvec 1%:M) = is_scalar_mx A.\n\n(*This lemma states that one matrix subspace is a subset of another if and only if every matrix belonging to the first subspace also belongs to the second.*)\nLemma memmx_subP m1 m2 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :\n reflect (forall A, A \\in R1 -> A \\in R2) (R1 <= R2)%MS.\n\nArguments memmx_subP {m1 m2 n R1 R2}.\n\n(*This lemma states that two matrix subspaces are equal if and only if they contain exactly the same set of matrices.*)\nLemma memmx_eqP m1 m2 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :\n reflect (forall A, (A \\in R1) = (A \\in R2)) (R1 == R2)%MS.\n\nArguments memmx_eqP {m1 m2 n R1 R2}.\n\n(*This lemma states that a matrix is an element of the sum of two matrix subspaces if and only if it can be expressed as the sum of a matrix from the first subspace and a matrix from the second subspace.*)\nLemma memmx_addsP m1 m2 n A (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :\n reflect (exists D, [/\\ D.1 \\in R1, D.2 \\in R2 & A = D.1 + D.2])\n (A \\in R1 + R2)%MS.\n\nArguments memmx_addsP {m1 m2 n A R1 R2}.\n\n(*This lemma states that a matrix is an element of the sum of an indexed family of matrix subspaces if and only if it can be decomposed into a sum of matrices, where each matrix in the sum belongs to the corresponding subspace from the family.*)\nLemma memmx_sumsP (I : finType) (P : pred I) n (A : 'M_n) R_ :\n reflect (exists2 A_, A = \\sum_(i | P i) A_ i & forall i, A_ i \\in R_ i)\n (A \\in \\sum_(i | P i) R_ i)%MS.\n\nArguments memmx_sumsP {I P n A R_}.\n\n(*This lemma states that for a matrix subspace that contains the identity matrix, having a rank greater than one is equivalent to containing at least one non-scalar matrix.*)\nLemma has_non_scalar_mxP m n (R : 'A_(m, n)) :\n (1%:M \\in R)%MS ->\n reflect (exists2 A, A \\in R & ~~ is_scalar_mx A)%MS (1 < \\rank R).\n\n(*This definition specifies the product of two matrix subspaces as the matrix subspace generated by all possible matrix products formed by taking one matrix from the first subspace and one from the second.*)\nDefinition mulsmx m1 m2 n (R1 : 'A[F]_(m1, n)) (R2 : 'A_(m2, n)) :=\n (\\sum_i <>)%MS.\n\nArguments mulsmx {m1%_N m2%_N n%_N} R1%_MS R2%_MS.\n\n(*A local notation for the product of two matrix subspaces.*)\nLocal Notation \"R1 * R2\" := (mulsmx R1 R2) : matrix_set_scope.\n\n(*This lemma states that generating a matrix subspace from the product of two matrix subspaces yields the same product subspace, confirming that the product operation already produces a valid subspace.*)\nLemma genmx_muls m1 m2 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :\n <<(R1 * R2)%MS>>%MS = (R1 * R2)%MS.\n\n(*This lemma states that the matrix product of any matrix from a first matrix subspace and any matrix from a second matrix subspace is an element of the product of those two subspaces.*)\nLemma mem_mulsmx m1 m2 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) A1 A2 :\n (A1 \\in R1 -> A2 \\in R2 -> A1 *m A2 \\in R1 * R2)%MS.\n\n(*This lemma states that the product of two matrix subspaces is a subset of a third matrix subspace if and only if the matrix product of any element from the first subspace and any element from the second subspace is always an element of the third subspace.*)\nLemma mulsmx_subP m1 m2 m n\n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) (R : 'A_(m, n)) :\n reflect (forall A1 A2, A1 \\in R1 -> A2 \\in R2 -> A1 *m A2 \\in R)\n (R1 * R2 <= R)%MS.\n\nArguments mulsmx_subP {m1 m2 m n R1 R2 R}.\n\n(*This lemma states that the product of matrix subspaces is monotonic with respect to the subset relation: if a first pair of subspaces are subsets of a second pair of subspaces respectively, then the product of the first pair is a subset of the product of the second pair.*)\nLemma mulsmxS m1 m2 m3 m4 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n))\n (R3 : 'A_(m3, n)) (R4 : 'A_(m4, n)) :\n (R1 <= R3 -> R2 <= R4 -> R1 * R2 <= R3 * R4)%MS.\n\n(*This lemma states that the product of matrix subspaces respects equality: if two pairs of matrix subspaces are respectively equal, then their products are also equal.*)\nLemma muls_eqmx m1 m2 m3 m4 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n))\n (R3 : 'A_(m3, n)) (R4 : 'A_(m4, n)) :\n (R1 :=: R3 -> R2 :=: R4 -> R1 * R2 = R3 * R4)%MS.\n\n(*This lemma states that a matrix belongs to the product of two matrix subspaces if and only if it can be expressed as a finite sum of matrix products, where each product is formed by an element from the first subspace and an element from the second.*)\nLemma mulsmxP m1 m2 n A (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :\n reflect (exists2 A1, forall i, A1 i \\in R1\n & exists2 A2, forall i, A2 i \\in R2\n & A = \\sum_(i < n ^ 2) A1 i *m A2 i)\n (A \\in R1 * R2)%MS.\n\nArguments mulsmxP {m1 m2 n A R1 R2}.\n\n(*This lemma asserts the associativity of the product of matrix subspaces, stating that for three given matrix subspaces, the order in which the products are calculated does not affect the final resulting subspace.*)\nLemma mulsmxA m1 m2 m3 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) (R3 : 'A_(m3, n)) :\n (R1 * (R2 * R3) = R1 * R2 * R3)%MS.\n\n(*This lemma states that the product of matrix sets is left-distributive over the sum of matrix sets. Specifically, it asserts that the product of the sum of two matrix sets with a third matrix set is equal to the sum of the individual products.*)\nLemma mulsmxDl m1 m2 m3 n\n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) (R3 : 'A_(m3, n)) :\n ((R1 + R2) * R3 = R1 * R3 + R2 * R3)%MS.\n\n(*This lemma states that the product of matrix sets is right-distributive over the sum of matrix sets. Specifically, it asserts that the product of a matrix set with the sum of two other matrix sets is equal to the sum of the individual products.*)\nLemma mulsmxDr m1 m2 m3 n\n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) (R3 : 'A_(m3, n)) :\n (R1 * (R2 + R3) = R1 * R2 + R1 * R3)%MS.\n\n(*This lemma states that the product of any matrix set with the zero matrix set results in the zero matrix set.*)\nLemma mulsmx0 m1 m2 n (R1 : 'A_(m1, n)) : (R1 * (0 : 'A_(m2, n)) = 0)%MS.\n\n(*This lemma states that the product of the zero matrix set with any matrix set results in the zero matrix set.*)\nLemma muls0mx m1 m2 n (R2 : 'A_(m2, n)) : ((0 : 'A_(m1, n)) * R2 = 0)%MS.\n\n(*This definition specifies the property of a matrix set being a left ideal with respect to another. It holds if the product of the first matrix set and the second matrix set is a subset of the second matrix set.*)\nDefinition left_mx_ideal m1 m2 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :=\n (R1 * R2 <= R2)%MS.\n\n(*This definition specifies the property of a matrix set being a right ideal with respect to another. It holds if the product of the second matrix set and the first matrix set is a subset of the second matrix set.*)\nDefinition right_mx_ideal m1 m2 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :=\n (R2 * R1 <= R2)%MS.\n\n(*This definition specifies the property of a matrix set being a two-sided ideal with respect to another. It holds if the first matrix set is both a left ideal and a right ideal with respect to the second.*)\nDefinition mx_ideal m1 m2 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :=\n left_mx_ideal R1 R2 && right_mx_ideal R1 R2.\n\n(*This definition specifies the properties of a multiplicative identity element for a set of matrices. An element is the identity if it is not the zero matrix, belongs to the set, and acts as both a left and right identity under matrix multiplication for every matrix in the set.*)\nDefinition mxring_id m n (R : 'A_(m, n)) e :=\n [/\\ e != 0,\n e \\in R,\n forall A, A \\in R -> e *m A = A\n & forall A, A \\in R -> A *m e = A]%MS.\n\n(*This definition provides a constructive predicate to determine if a non-zero set of matrices possesses a multiplicative identity element.*)\nDefinition has_mxring_id m n (R : 'A[F]_(m , n)) :=\n (R != 0) &&\n (row_mx 0 (row_mx (mxvec R) (mxvec R))\n <= row_mx (cokermx R) (row_mx (lin_mx (mulmx R \\o lin_mulmx))\n (lin_mx (mulmx R \\o lin_mulmxr))))%MS.\n\n(*This definition specifies that a set of matrices forms a matrix ring if it is closed under matrix multiplication and contains a multiplicative identity element.*)\nDefinition mxring m n (R : 'A_(m, n)) :=\n left_mx_ideal R R && has_mxring_id R.\n\n(*This lemma states that the constructive property of a matrix set having a multiplicative identity is logically equivalent to the existence of an element that satisfies the definition of a multiplicative identity for that set.*)\nLemma mxring_idP m n (R : 'A_(m, n)) :\n reflect (exists e, mxring_id R e) (has_mxring_id R).\n\nArguments mxring_idP {m n R}.\n\nSection CentMxDef.\n\nVariables (m n : nat) (R : 'A[F]_(m, n)).\n\n(*This definition specifies a function that, given a square matrix, produces an output matrix used to determine if the input matrix commutes with all matrices in a given set. The function's output is zero if and only if the input matrix commutes with every matrix in the reference set.*)\nDefinition cent_mx_fun (B : 'M[F]_n) := R *m lin_mx (mulmxr B \\- mulmx B).\n\n(*This lemma states that the function for computing the commutator matrix relative to a set of matrices is a linear transformation.*)\nLemma cent_mx_fun_is_linear : linear cent_mx_fun.\n\n(*This definition specifies the centralizer of a given set of matrices as the set of all matrices that commute with every matrix in the given set. It is formally defined as the kernel of the associated commutator function.*)\nDefinition cent_mx := kermx (lin_mx cent_mx_fun).\n\n(*This definition specifies the center of a given set of matrices as the set of all matrices that are elements of the given set and also commute with every matrix in that set.*)\nDefinition center_mx := (R :&: cent_mx)%MS.\n\nEnd CentMxDef.\n\n(*This notation represents the centralizer of a given set of matrices, which is the set of all matrices that commute with every matrix in the given set.*)\nLocal Notation \"''C' ( R )\" := (cent_mx R) : matrix_set_scope.\n(*This notation represents the center of a given set of matrices, which consists of all matrices within that set that commute with every other matrix in the set.*)\nLocal Notation \"''Z' ( R )\" := (center_mx R) : matrix_set_scope.\n\n(*This lemma states that a matrix belongs to the centralizer of a given matrix set if and only if it commutes with every matrix formed from each row of a basis matrix for that set.*)\nLemma cent_rowP m n B (R : 'A_(m, n)) :\n reflect (forall i (A := vec_mx (row i R)), A *m B = B *m A) (B \\in 'C(R))%MS.\n\nArguments cent_rowP {m n B R}.\n\n(*This lemma states that a matrix belongs to the centralizer of a given matrix set if and only if it commutes with every matrix that is an element of that set.*)\nLemma cent_mxP m n B (R : 'A_(m, n)) :\n reflect (forall A, A \\in R -> A *m B = B *m A) (B \\in 'C(R))%MS.\n\nArguments cent_mxP {m n B R}.\n\n(*This lemma states that any scalar matrix is an element of the centralizer of any given set of matrices, meaning it commutes with all matrices in that set.*)\nLemma scalar_mx_cent m n a (R : 'A_(m, n)) : (a%:M \\in 'C(R))%MS.\n\n(*This lemma states that the center of a set of matrices is always a subset of the original set.*)\nLemma center_mx_sub m n (R : 'A_(m, n)) : ('Z(R) <= R)%MS.\n\n(*This lemma states that a matrix is an element of the center of a matrix set if and only if it belongs to that set and commutes with every other matrix in the set.*)\nLemma center_mxP m n A (R : 'A_(m, n)) :\n reflect (A \\in R /\\ forall B, B \\in R -> B *m A = A *m B)\n (A \\in 'Z(R))%MS.\n\nArguments center_mxP {m n A R}.\n\n(*This lemma states that the multiplicative identity element of a matrix ring is unique.*)\nLemma mxring_id_uniq m n (R : 'A_(m, n)) e1 e2 :\n mxring_id R e1 -> mxring_id R e2 -> e1 = e2.\n\n(*This lemma states that the centralizer of a set of matrices is closed under matrix multiplication.*)\nLemma cent_mx_ideal m n (R : 'A_(m, n)) : left_mx_ideal 'C(R)%MS 'C(R)%MS.\n\n(*This lemma states that for matrices with a positive number of columns, the centralizer of any set of matrices forms a matrix ring.*)\nLemma cent_mx_ring m n (R : 'A_(m, n)) : n > 0 -> mxring 'C(R)%MS.\n\n(*This lemma states that if two matrix sets are two-sided ideals of their direct sum, then the center of this direct sum is equal to the sum of the centers of the individual matrix sets.*)\nLemma mxdirect_adds_center m1 m2 n (R1 : 'A_(m1, n)) (R2 : 'A_(m2, n)) :\n mx_ideal (R1 + R2)%MS R1 -> mx_ideal (R1 + R2)%MS R2 ->\n mxdirect (R1 + R2) ->\n ('Z((R1 + R2)%MS) :=: 'Z(R1) + 'Z(R2))%MS.\n\n(*This lemma states that if a matrix set is the direct sum of a finite family of matrix sets, where each component is an ideal of the total sum, then the center of the total matrix set is equal to the sum of the centers of the component sets.*)\nLemma mxdirect_sums_center (I : finType) m n (R : 'A_(m, n)) R_ :\n (\\sum_i R_ i :=: R)%MS -> mxdirect (\\sum_i R_ i) ->\n (forall i : I, mx_ideal R (R_ i)) ->\n ('Z(R) :=: \\sum_i 'Z(R_ i))%MS.\n\nEnd MatrixAlgebra.\n\nArguments mulsmx {F m1%_N m2%_N n%_N} R1%_MS R2%_MS.\nArguments left_mx_ideal {F m1%_N m2%_N n%_N} R%_MS S%_MS : rename.\nArguments right_mx_ideal {F m1%_N m2%_N n%_N} R%_MS S%_MS : rename.\nArguments mx_ideal {F m1%_N m2%_N n%_N} R%_MS S%_MS : rename.\nArguments mxring_id {F m%_N n%_N} R%_MS e%_R.\nArguments has_mxring_id {F m%_N n%_N} R%_MS.\nArguments mxring {F m%_N n%_N} R%_MS.\nArguments cent_mx {F m%_N n%_N} R%_MS.\nArguments center_mx {F m%_N n%_N} R%_MS.\n\n(*This notation expresses that a given matrix is an element of a given set of matrices, which is defined as being in the submodule generated by that set.*)\nNotation \"A \\in R\" := (submx (mxvec A) R) : matrix_set_scope.\n(*This notation represents the product of two sets of matrices, which is the set containing all possible matrix products where the first factor is from the first set and the second factor is from the second set.*)\nNotation \"R * S\" := (mulsmx R S) : matrix_set_scope.\n(*This notation defines the centralizer of a matrix, which is the set of all matrices that commute with it.*)\nNotation \"''C' ( R )\" := (cent_mx R) : matrix_set_scope.\n(*This notation represents the set of matrices within a given matrix set that commute with every matrix in another given matrix set.*)\nNotation \"''C_' R ( S )\" := (R :&: 'C(S))%MS : matrix_set_scope.\n(*This notation represents the set of matrices within a given matrix set that commute with every matrix in another given matrix set.*)\nNotation \"''C_' ( R ) ( S )\" := ('C_R(S))%MS (only parsing) : matrix_set_scope.\n(*This notation defines the center of a matrix algebra, which is the set of all matrices that commute with every other matrix in the algebra.*)\nNotation \"''Z' ( R )\" := (center_mx R) : matrix_set_scope.\n\nArguments memmx_subP {F m1 m2 n R1 R2}.\nArguments memmx_eqP {F m1 m2 n R1 R2}.\nArguments memmx_addsP {F m1 m2 n} A {R1 R2}.\nArguments memmx_sumsP {F I P n A R_}.\nArguments mulsmx_subP {F m1 m2 m n R1 R2 R}.\nArguments mulsmxP {F m1 m2 n A R1 R2}.\nArguments mxring_idP F {m n R}.\nArguments cent_rowP {F m n B R}.\nArguments cent_mxP {F m n B R}.\nArguments center_mxP {F m n A R}.\n\nSection MapMatrixSpaces.\n\nVariables (aF rF : fieldType) (f : {rmorphism aF -> rF}).\n(*This notation represents the application of a ring morphism to each entry of a matrix, yielding a new matrix over the codomain of the morphism.*)\nLocal Notation \"A ^f\" := (map_mx f A) : ring_scope.\n\n(*This lemma states that performing Gaussian elimination on a matrix whose entries have been transformed by a field morphism yields a tuple containing the transformed column echelon basis, the transformed row echelon basis, and the original rank of the matrix.*)\nLemma Gaussian_elimination_map m n (A : 'M_(m, n)) :\n Gaussian_elimination_ A^f = ((col_ebase A)^f, (row_ebase A)^f, \\rank A).\n\n(*This lemma states that the rank of a matrix remains unchanged after applying a field morphism to all of its entries.*)\nLemma mxrank_map m n (A : 'M_(m, n)) : \\rank A^f = \\rank A.\n\n(*This lemma states that a matrix has linearly independent rows if and only if the matrix resulting from applying a field morphism to its entries also has linearly independent rows.*)\nLemma row_free_map m n (A : 'M_(m, n)) : row_free A^f = row_free A.\n\n(*This lemma states that a matrix has rows that span the entire space if and only if the matrix resulting from applying a field morphism to its entries also has rows that span the entire space.*)\nLemma row_full_map m n (A : 'M_(m, n)) : row_full A^f = row_full A.\n\n(*This lemma states that applying a field morphism to the entries of the row echelon basis of a matrix produces the same result as first applying the morphism to the matrix entries and then computing its row echelon basis.*)\nLemma map_row_ebase m n (A : 'M_(m, n)) : (row_ebase A)^f = row_ebase A^f.\n\n(*This lemma states that applying a field morphism to the entries of the column echelon basis of a matrix produces the same result as first applying the morphism to the matrix entries and then computing its column echelon basis.*)\nLemma map_col_ebase m n (A : 'M_(m, n)) : (col_ebase A)^f = col_ebase A^f.\n\n(*This lemma states that applying a field morphism to the row basis of a matrix yields a matrix that is equivalent, up to reshaping, to the row basis of the matrix whose entries have been transformed by the morphism.*)\nLemma map_row_base m n (A : 'M_(m, n)) :\n (row_base A)^f = castmx (mxrank_map A, erefl n) (row_base A^f).\n\n(*This lemma states that applying a field morphism to the column basis of a matrix yields a matrix that is equivalent, up to reshaping, to the column basis of the matrix whose entries have been transformed by the morphism.*)\nLemma map_col_base m n (A : 'M_(m, n)) :\n (col_base A)^f = castmx (erefl m, mxrank_map A) (col_base A^f).\n\n(*This lemma states that applying a field morphism to the entries of the Moore-Penrose pseudoinverse of a matrix is equivalent to computing the pseudoinverse of the matrix whose entries have been transformed by the morphism.*)\nLemma map_pinvmx m n (A : 'M_(m, n)) : (pinvmx A)^f = pinvmx A^f.\n\n(*This lemma states that applying a field morphism to the basis of the kernel of a matrix results in the basis of the kernel of the matrix whose entries have been transformed by the morphism.*)\nLemma map_kermx m n (A : 'M_(m, n)) : (kermx A)^f = kermx A^f.\n\n(*This lemma states that applying a field morphism to the basis of the cokernel of a matrix results in the basis of the cokernel of the matrix whose entries have been transformed by the morphism.*)\nLemma map_cokermx m n (A : 'M_(m, n)) : (cokermx A)^f = cokermx A^f.\n\n(*This lemma states that the row space of one matrix is a subspace of the row space of another matrix if and only if the same relationship holds for the matrices after applying a field morphism to their entries.*)\nLemma map_submx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A^f <= B^f)%MS = (A <= B)%MS.\n\n(*This lemma states that the row space of one matrix is a proper subspace of the row space of another matrix if and only if the same relationship holds for the matrices after applying a field morphism to their entries.*)\nLemma map_ltmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A^f < B^f)%MS = (A < B)%MS.\n\n(*This lemma states that two matrices generate the same row space if and only if they generate the same row space after a field morphism has been applied to their entries.*)\nLemma map_eqmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A^f :=: B^f)%MS <-> (A :=: B)%MS.\n\n(*This lemma states that the row space generated by a matrix, after applying a field morphism to its entries, is the same as the row space generated by the matrix whose entries have been transformed by that morphism.*)\nLemma map_genmx m n (A : 'M_(m, n)) : (<>^f :=: <>)%MS.\n\n(*This lemma states that applying a field morphism to the basis of the sum of two row spaces is equivalent to taking the sum of the row spaces of the matrices after their entries have been transformed by the morphism.*)\nLemma map_addsmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (((A + B)%MS)^f :=: A^f + B^f)%MS.\n\n(*This lemma states that applying a field morphism to a generator of the intersection of two row spaces is equivalent to computing a generator for the intersection of the row spaces of the matrices after their entries have been transformed by the morphism.*)\nLemma map_capmx_gen m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (capmx_gen A B)^f = capmx_gen A^f B^f.\n\n(*This lemma states that the intersection of two row spaces, when transformed by a field morphism, is equal to the intersection of the row spaces of the transformed matrices.*)\nLemma map_capmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n ((A :&: B)^f :=: A^f :&: B^f)%MS.\n\n(*This lemma states that the orthogonal complement of a row space, when transformed by a field morphism, is equal to the orthogonal complement of the row space of the transformed matrix.*)\nLemma map_complmx m n (A : 'M_(m, n)) : (A^C^f = A^f^C)%MS.\n\n(*This lemma states that the difference of two row spaces, when transformed by a field morphism, is equal to the difference of the row spaces of the transformed matrices.*)\nLemma map_diffmx m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n ((A :\\: B)^f :=: A^f :\\: B^f)%MS.\n\n(*This lemma states that applying a field morphism to an eigenspace basis of a matrix for a given eigenvalue yields the eigenspace basis of the transformed matrix for the transformed eigenvalue.*)\nLemma map_eigenspace n (g : 'M_n) a : (eigenspace g a)^f = eigenspace g^f (f a).\n\n(*This lemma states that a scalar is an eigenvalue of a matrix if and only if the image of the scalar under a field morphism is an eigenvalue of the image of the matrix under the same morphism.*)\nLemma eigenvalue_map n (g : 'M_n) a : eigenvalue g^f (f a) = eigenvalue g a.\n\n(*This lemma states that a matrix is a member of a matrix space if and only if the matrix transformed by a field morphism is a member of the similarly transformed matrix space.*)\nLemma memmx_map m n A (E : 'A_(m, n)) : (A^f \\in E^f)%MS = (A \\in E)%MS.\n\n(*This lemma states that the product of two matrix spaces, when transformed by a field morphism, is equivalent to the product of the two transformed matrix spaces.*)\nLemma map_mulsmx m1 m2 n (E1 : 'A_(m1, n)) (E2 : 'A_(m2, n)) :\n ((E1 * E2)%MS^f :=: E1^f * E2^f)%MS.\n\n(*This lemma states that the centralizer of a matrix space, when transformed by a field morphism, is equal to the centralizer of the transformed matrix space.*)\nLemma map_cent_mx m n (E : 'A_(m, n)) : ('C(E)%MS)^f = 'C(E^f)%MS.\n\n(*This lemma states that applying a given function element-wise to every matrix in the center of a matrix algebra results in the same set of matrices as the center of the algebra containing the original matrices after the function has been applied to their elements.*)\nLemma map_center_mx m n (E : 'A_(m, n)) : (('Z(E))^f :=: 'Z(E^f))%MS.\n\nEnd MapMatrixSpaces.\n\nSection RowColDiagBlockMatrix.\nImport tagnat.\nContext {F : fieldType} {n : nat} {p_ : 'I_n -> nat}.\n\n(*This lemma states that a block column matrix, constructed by vertically stacking a sequence of matrices, is equal to the matrix sum of each of these matrices after they have been individually embedded into their respective block positions within a larger matrix of appropriate dimensions.*)\nLemma eqmx_col {m} (V_ : forall i, 'M[F]_(p_ i, m)) :\n (\\mxcol_i V_ i :=: \\sum_i <>)%MS.\n\n(*This lemma states that the rank of a block diagonal matrix is equal to the sum of the ranks of the individual square matrices that form its diagonal blocks.*)\nLemma rank_mxdiag (V_ : forall i, 'M[F]_(p_ i)) :\n (\\rank (\\mxdiag_i V_ i) = \\sum_i \\rank (V_ i))%N.", - "algebra.ssrint": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat choice seq.\nFrom mathcomp Require Import fintype finfun bigop order ssralg countalg ssrnum.\nFrom mathcomp Require Import poly.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope int_scope.\nDeclare Scope distn_scope.\nDeclare Scope rat_scope.\n\nReserved Notation \"*~%R\" (format \" *~%R\").\nReserved Notation \"x *~ n\" (at level 40, left associativity, format \"x *~ n\").\nReserved Notation \"n %:~R\" (left associativity, format \"n %:~R\").\n\nReserved Notation \"n %:Z\" (left associativity, format \"n %:Z\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"n = m :> 'int'\" (format \"n = m :> 'int'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"n == m :> 'int'\" (format \"n == m :> 'int'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"n != m :> 'int'\" (format \"n != m :> 'int'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"n <> m :> 'int'\" (format \"n <> m :> 'int'\").\n\nImport Order.TTheory GRing.Theory Num.Theory.\nDelimit Scope int_scope with Z.\nLocal Open Scope int_scope.\n\n(*This inductive type defines the integers. An integer is either a non-negative value, represented by a natural number, or a negative value, also constructed from a natural number.*)\nVariant int : Set := Posz of nat | Negz of nat.\n\n(*This notation converts a natural number into the corresponding non-negative integer.*)\nNotation \"n %:Z\" := (Posz n) (only parsing) : int_scope.\n(*A notation that coerces a natural number into its corresponding non-negative integer representation.*)\nNotation \"n %:Z\" := (Posz n) (only parsing) : ring_scope.\n\nNotation \"n = m :> 'int'\" := (@eq int n%Z m%Z) (only parsing) : ring_scope.\n(*A notation for expressing the propositional equality of two natural numbers when they are interpreted as integers.*)\nNotation \"n = m :> 'int'\" := (Posz n = Posz m) (only printing) : ring_scope.\nNotation \"n == m :> 'int'\" := ((n%Z : int) == (m%Z : int)) (only parsing)\n : ring_scope.\n(*A notation for expressing the boolean equality of two natural numbers when they are interpreted as integers.*)\nNotation \"n == m :> 'int'\" := (Posz n == Posz m) (only printing) : ring_scope.\nNotation \"n != m :> 'int'\" := ((n%Z : int) != (m%Z : int)) (only parsing)\n : ring_scope.\n(*A notation for expressing the boolean inequality of two natural numbers when they are interpreted as integers.*)\nNotation \"n != m :> 'int'\" := (Posz n != Posz m) (only printing) : ring_scope.\nNotation \"n <> m :> 'int'\" := (not (@eq int n%Z m%Z)) (only parsing)\n : ring_scope.\n(*A notation for expressing the propositional inequality of two natural numbers when they are interpreted as integers.*)\nNotation \"n <> m :> 'int'\" := (Posz n <> Posz m) (only printing) : ring_scope.\n\n(*This definition provides a function to convert a textual representation of a number, as parsed by Coq's number notation system, into the corresponding integer value.*)\nDefinition parse_int (x : Number.int) : int :=\n match x with\n | Number.IntDecimal (Decimal.Pos u) => Posz (Nat.of_uint u)\n | Number.IntDecimal (Decimal.Neg u) => Negz (Nat.of_uint u).-1\n | Number.IntHexadecimal (Hexadecimal.Pos u) => Posz (Nat.of_hex_uint u)\n | Number.IntHexadecimal (Hexadecimal.Neg u) => Negz (Nat.of_hex_uint u).-1\n end.\n\n(*This definition provides a function to convert an integer value into a textual representation suitable for printing, compatible with Coq's number notation system.*)\nDefinition print_int (x : int) : Number.int :=\n match x with\n | Posz n => Number.IntDecimal (Decimal.Pos (Nat.to_uint n))\n | Negz n => Number.IntDecimal (Decimal.Neg (Nat.to_uint n.+1))\n end.\n\nNumber Notation int parse_int print_int : int_scope.\n\n(*This definition provides a function that maps an integer to a value in a sum type of natural numbers, with non-negative integers mapping to the left component and negative integers mapping to the right component.*)\nDefinition natsum_of_int (m : int) : nat + nat :=\n match m with Posz p => inl _ p | Negz n => inr _ n end.\n\n(*This definition provides a function that converts a value from a sum type of natural numbers back into an integer, serving as the inverse to natsum_of_int.*)\nDefinition int_of_natsum (m : nat + nat) :=\n match m with inl p => Posz p | inr n => Negz n end.\n\n(*This lemma states that applying natsum_of_int to an integer and then int_of_natsum to the result yields the original integer.*)\nLemma natsum_of_intK : cancel natsum_of_int int_of_natsum.\n\nHB.instance Definition _ := Countable.copy int (can_type natsum_of_intK).\n\n(*This lemma states that the boolean equality test for two natural numbers yields the same result as the boolean equality test for the corresponding non-negative integers.*)\nLemma eqz_nat (m n : nat) : (m%:Z == n%:Z) = (m == n). \n\nModule intZmod.\nSection intZmod.\n\n(*This definition specifies the rule for adding two integers.*)\nDefinition addz (m n : int) :=\n match m, n with\n | Posz m', Posz n' => Posz (m' + n')\n | Negz m', Negz n' => Negz (m' + n').+1\n | Posz m', Negz n' => if n' < m' then Posz (m' - n'.+1) else Negz (n' - m')\n | Negz n', Posz m' => if n' < m' then Posz (m' - n'.+1) else Negz (n' - m')\n end.\n\n(*This definition specifies the rule for computing the additive inverse of an integer.*)\nDefinition oppz m :=\n match m with\n | Posz n => if n is (n'.+1)%N then Negz n' else Posz 0\n | Negz n => Posz (n.+1)%N\n end.\nArguments oppz : simpl never.\n\n(*A notation for the additive inverse of an integer.*)\nLocal Notation \"-%Z\" := (@oppz) : int_scope.\n(*A notation for the additive inverse of an integer.*)\nLocal Notation \"- x\" := (oppz x) : int_scope.\n(*A notation for the addition of two integers.*)\nLocal Notation \"+%Z\" := (@addz) : int_scope.\n(*A notation for the addition of two integers.*)\nLocal Notation \"x + y\" := (addz x y) : int_scope.\n(*A notation for integer subtraction, defined as the sum of the first integer and the additive inverse of the second.*)\nLocal Notation \"x - y\" := (x + - y) : int_scope.\n\n(*This lemma states that the conversion from natural numbers to non-negative integers is a morphism for addition; that is, converting the sum of two natural numbers yields the same result as adding their integer representations.*)\nLemma PoszD : {morph Posz : m n / (m + n)%N >-> m + n}. \n\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma provides an identity for the negative integer constructor, stating that a negative integer built from a natural number `n` is equal to the additive inverse of the integer corresponding to `n` plus one.*)\nLemma NegzE (n : nat) : Negz n = - n.+1. \n\n(*This definition establishes the principle of induction over integers, allowing a property to be proven for all integers by proving it for zero, for successors of non-negative integers, and for predecessors of non-positive integers.*)\nLemma int_rect (P : int -> Type) :\n P 0 -> (forall n : nat, P n -> P (n.+1))\n -> (forall n : nat, P (- n) -> P (- (n.+1)))\n -> forall n : int, P n.\n\n(*This definition provides the recursion principle for signed integers, allowing a function to be defined by specifying its behavior on non-negative integers and negative integers separately.*)\nDefinition int_rec := int_rect.\n(*This definition provides the induction principle for signed integers, allowing a property to be proven for all integers by establishing it for the non-negative case and the negative case.*)\nDefinition int_ind := int_rect.\n\n(*This inductive type provides a structural case analysis for an integer. It asserts that any given integer must be one of three forms: zero, a positive integer, or a negative integer.*)\nVariant int_spec (x : int) : int -> Type :=\n(*This lemma states that scaling any element of a z-module by the integer zero results in the zero element of that module.*)\n| ZintNull of x = 0 : int_spec x 0\n(**)\n| ZintPos n of x = n.+1 : int_spec x n.+1\n(**)\n| ZintNeg n of x = - (n.+1)%:Z : int_spec x (- n.+1).\n\n(*This lemma states that any signed integer can be viewed through its concrete representation, allowing proofs to proceed by case analysis on whether the integer is non-negative or negative.*)\nLemma intP x : int_spec x x. \n\n(*This lemma states that integer addition is commutative.*)\nLemma addzC : commutative addz.\n\n(*This lemma states that zero is the left identity element for integer addition.*)\nLemma add0z : left_id 0 addz. \n\n(*This lemma states that applying the additive inverse operation twice to an integer returns the original integer.*)\nLemma oppzK : involutive oppz. \n\n(*This lemma states that the additive inverse operation distributes over integer addition; the inverse of a sum is the sum of the inverses.*)\nLemma oppzD : {morph oppz : m n / m + n}.\n\n(*This lemma states that for any integer, adding one to the result of subtracting one from that integer yields the original integer.*)\nLemma add1Pz (n : int) : 1 + (n - 1) = n.\n\n(*This lemma states that for any integer, adding one and then subtracting one results in the original integer.*)\nLemma subSz1 (n : int) : 1 + n - 1 = n.\n\n(*This lemma states that for a given natural number and an integer, adding the successor of the natural number to the integer is equivalent to adding one to the sum of the original natural number and the integer.*)\nLemma addSnz (m : nat) (n : int) : m.+1%N + n = 1 + (m + n).\n\n(*This lemma states that for two given integers, adding one to the first integer and then adding the second integer is the same as adding one to the sum of the two integers.*)\nLemma addSz (m n : int) : (1 + m) + n = 1 + (m + n).\n\n(*This lemma states that for two given integers, subtracting one from the first integer and then adding the second integer is equivalent to subtracting one from the sum of the two integers.*)\nLemma addPz (m n : int) : (m - 1) + n = (m + n) - 1.\n\n(*This lemma states that integer addition is an associative operation.*)\nLemma addzA : associative addz.\n\n(*This lemma states that the additive inverse function provides a left inverse for every integer with respect to integer addition and the identity element zero.*)\nLemma addNz : left_inverse (0:int) oppz addz. \n\n(*This lemma states that for any natural number that is greater than zero, its predecessor represented as an integer is equal to subtracting one from its integer representation.*)\nLemma predn_int (n : nat) : 0 < n -> n.-1%:Z = n - 1.\n\n(*This definition builds a mixin that endows the type of integers with a module structure over the ring of integers, based on properties like the associativity of integer addition and the existence of additive inverses.*)\nDefinition Mixin := GRing.isZmodule.Build int addzA addzC add0z addNz.\n\nEnd intZmod.\nArguments oppz : simpl never.\nEnd intZmod.\n\nHB.instance Definition _ := intZmod.Mixin.\n\nHB.instance Definition _ := GRing.isNmodMorphism.Build nat int Posz\n (erefl, intZmod.PoszD).\n\nLocal Open Scope ring_scope.\n\nSection intZmoduleTheory.\n\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that the function embedding natural numbers into integers is a morphism with respect to addition, meaning it maps the sum of two natural numbers to the sum of their integer representations.*)\nLemma PoszD : {morph Posz : n m / (n + m)%N >-> n + m}. \n\n(*This lemma states that the function for creating negative integers from natural numbers maps a natural number to the additive inverse of the integer representation of its successor.*)\nLemma NegzE (n : nat) : Negz n = -(n.+1)%:Z. \n\n(*This definition provides a recursion principle for integers, allowing a property to be proven for all integers by proving it for zero, for the successor of any non-negative integer under the assumption that it holds for that integer, and for the predecessor of any non-positive integer under the assumption that it holds for that integer.*)\nLemma int_rect (P : int -> Type) :\n P 0 -> (forall n : nat, P n -> P (n.+1)%N)\n -> (forall n : nat, P (- (n%:Z)) -> P (- (n.+1%N%:Z)))\n -> forall n : int, P n.\n\n(*This definition is an alias for the integer induction principle.*)\nDefinition int_rec := int_rect.\n(*This definition is an alias for the integer induction principle.*)\nDefinition int_ind := int_rect.\n\n(*This inductive type provides a case analysis for a given integer, specifying that it is either zero, a positive integer represented as the successor of a natural number, or a negative integer represented as the additive inverse of the successor of a natural number.*)\nVariant int_spec (x : int) : int -> Type :=\n(*This lemma states that scaling any element of a z-module by the integer zero results in the zero element of that module.*)\n| ZintNull : int_spec x 0\n(**)\n| ZintPos n : int_spec x n.+1\n(**)\n| ZintNeg n : int_spec x (- (n.+1)%:Z).\n\n(*This lemma states that for any integer, a proof of its structural case analysis as defined by `int_spec` can be constructed.*)\nLemma intP x : int_spec x x.\n\n(*This definition establishes that applying the additive inverse operation twice to any integer returns the original integer.*)\nDefinition oppzD := @opprD int.\n\n(*This lemma states that if a natural number is less than or equal to another natural number, then the difference of their integer representations is equal to the integer representation of their difference as natural numbers.*)\nLemma subzn (m n : nat) : (n <= m)%N -> m%:Z - n%:Z = (m - n)%N.\n\n(*This lemma states that the difference between the integer representations of the successors of two natural numbers is equal to the difference of the integer representations of the original natural numbers.*)\nLemma subzSS (m n : nat) : m.+1%:Z - n.+1%:Z = m%:Z - n%:Z.\n\nEnd intZmoduleTheory.\n\nModule intRing.\nSection intRing.\n\nLocal Coercion Posz : nat >-> int.\n\n(*This definition specifies the multiplication of two integers by performing a case analysis on the signs of the two integers.*)\nDefinition mulz (m n : int) :=\n match m, n with\n | Posz m', Posz n' => (m' * n')%N%:Z\n | Negz m', Negz n' => (m'.+1%N * n'.+1%N)%N%:Z\n | Posz m', Negz n' => - (m' * (n'.+1%N))%N%:Z\n | Negz n', Posz m' => - (m' * (n'.+1%N))%N%:Z\n end.\n\n(*This notation defines `*%Z` as the multiplication operation for integers, intended for use within the integer scope.*)\nLocal Notation \"*%Z\" := (@mulz) : int_scope.\n(*This notation defines the infix operator `*` for the multiplication of two integers, intended for use within the integer scope.*)\nLocal Notation \"x * y\" := (mulz x y) : int_scope.\n\n(*This lemma states that zero is a left absorbing element for integer multiplication.*)\nLemma mul0z : left_zero 0 *%Z.\n\n(*This lemma states that integer multiplication is commutative.*)\nLemma mulzC : commutative mulz.\n\n(*This lemma states that zero is a right absorbing element for integer multiplication.*)\nLemma mulz0 : right_zero 0 *%Z.\n\n(*This lemma states that multiplying an integer by the additive inverse of another integer is equivalent to the additive inverse of their product.*)\nLemma mulzN (m n : int) : (m * (- n))%Z = - (m * n)%Z.\n\n(*This lemma states that multiplying the additive inverse of an integer by another integer is equivalent to the additive inverse of their product.*)\nLemma mulNz (m n : int) : ((- m) * n)%Z = - (m * n)%Z.\n\n(*This lemma states that integer multiplication is associative.*)\nLemma mulzA : associative mulz.\n\n(*This lemma states that the integer one is the left identity element for integer multiplication.*)\nLemma mul1z : left_id 1%Z mulz.\n\n(*This lemma states that the product of an integer with the integer representation of the successor of a natural number is equal to the sum of that integer and its product with the integer representation of the original natural number.*)\nLemma mulzS (x : int) (n : nat) : (x * n.+1%:Z)%Z = x + (x * n)%Z.\n\n(*This lemma states that integer multiplication is left-distributive over integer addition, meaning that multiplying an integer by the sum of two other integers is equivalent to the sum of the products of the first integer with each of the other two integers.*)\nLemma mulz_addl : left_distributive mulz (+%R).\n\n(*This lemma states that the integer one is not equal to the integer zero.*)\nLemma nonzero1z : 1%Z != 0. \n\n(*This definition provides the mixin that equips the type of integers with the structure of a commutative, non-zero ring by packaging proofs of associativity, commutativity, identity for multiplication, distributivity, and the fact that one is not zero.*)\nDefinition comMixin := GRing.Zmodule_isComNzRing.Build int\n mulzA mulzC mul1z mulz_addl nonzero1z.\n\nEnd intRing.\nEnd intRing.\n\nHB.instance Definition _ := intRing.comMixin.\n\nSection intRingTheory.\n\nImplicit Types m n : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that the coercion from natural numbers to integers is a multiplicative morphism, meaning it preserves multiplication. The integer representation of the product of two natural numbers is equal to the product of their integer representations.*)\nLemma PoszM : {morph Posz : n m / (n * m)%N >-> n * m}. \n\n(*This lemma states that for any natural number, its successor, when converted to an integer, is equal to one plus the integer representation of the original natural number.*)\nLemma intS (n : nat) : n.+1%:Z = 1 + n%:Z. \n\n(*This lemma states that for any natural number that is greater than zero, the integer representation of its predecessor is equal to its integer representation minus one.*)\nLemma predn_int (n : nat) : (0 < n)%N -> n.-1%:Z = n%:Z - 1.\n\nEnd intRingTheory.\n\nHB.instance Definition _ := GRing.isMonoidMorphism.Build nat int Posz\n (erefl, PoszM).\n\nModule intUnitRing.\nSection intUnitRing.\nImplicit Types m n : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This definition specifies the predicate for being a unit in the ring of integers. An integer satisfies this predicate if and only if it is equal to one or negative one.*)\nDefinition unitz := [qualify a n : int | (n == 1) || (n == -1)].\n(*This definition provides the multiplicative inverse function for integers. For any given integer, its inverse is defined to be the integer itself, which is valid for the units one and negative one.*)\nDefinition invz n : int := n.\n\n(*This lemma states that for any integer that is a unit, multiplying its multiplicative inverse by the integer itself results in one, establishing that the defined inverse function is a left inverse for units.*)\nLemma mulVz : {in unitz, left_inverse 1%R invz *%R}.\n\n(*This lemma states that the product of an integer and a natural number is equal to one if and only if the integer is one and the natural number is one.*)\nLemma mulzn_eq1 m (n : nat) : (m * n == 1) = (m == 1) && (n == 1).\n\n(*This lemma states that if the product of two integers is one, then the right-hand factor of the product must be a unit.*)\nLemma unitzPl m n : n * m = 1 -> m \\is a unitz.\n\n(*This lemma states that for any integer that is not a unit, the multiplicative inverse function is equivalent to the identity function, meaning it returns the integer itself.*)\nLemma invz_out : {in [predC unitz], invz =1 id}.\n\n(*This lemma states the integral domain property for integers: if the product of two integers is zero, then at least one of the integers must be zero.*)\nLemma idomain_axiomz m n : m * n = 0 -> (m == 0) || (n == 0).\n\n(*This instance provides the proof that integer multiplication is commutative, establishing the integers as a commutative ring structure.*)\nDefinition comMixin := GRing.ComNzRing_hasMulInverse.Build int\n mulVz unitzPl invz_out.\n\nEnd intUnitRing.\nEnd intUnitRing.\n\nHB.instance Definition _ := intUnitRing.comMixin.\nHB.instance Definition _ := GRing.ComUnitRing_isIntegral.Build int\n intUnitRing.idomain_axiomz.\n\n(*This definition computes the absolute value of an integer, returning it as a natural number. For a non-negative integer, it returns the integer itself. For a negative integer, it returns its positive counterpart.*)\nDefinition absz m := match m with Posz p => p | Negz n => n.+1 end.\n(*This notation defines subtraction for integers as the addition of the first integer and the additive inverse of the second integer.*)\nNotation \"m - n\" := (@GRing.add int m%N (@GRing.opp int n%N)) : distn_scope.\nArguments absz m%_distn_scope.\n(**)\nLocal Notation \"`| m |\" := (absz m) : nat_scope.\n\nModule intOrdered.\nSection intOrdered.\nImplicit Types m n p : int.\nLocal Coercion Posz : nat >-> int.\n\nLocal Notation normz m := (absz m)%:Z.\n\n(*This definition establishes the 'less than or equal to' relation for integers. It returns true if the first integer is less than or equal to the second integer, and false otherwise, handling comparisons between positive, negative, and zero values correctly.*)\nDefinition lez m n :=\n match m, n with\n | Posz m', Posz n' => (m' <= n')%N\n | Posz m', Negz n' => false\n | Negz m', Posz n' => true\n | Negz m', Negz n' => (n' <= m')%N\n end.\n\n(*This definition establishes the 'less than' relation for integers. It returns true if the first integer is strictly less than the second integer, and false otherwise.*)\nDefinition ltz m n :=\n match m, n with\n | Posz m', Posz n' => (m' < n')%N\n | Posz m', Negz n' => false\n | Negz m', Posz n' => true\n | Negz m', Negz n' => (n' < m')%N\n end.\n\n(*This lemma states that the sum of two non-negative integers is also a non-negative integer.*)\nFact lez_add m n : lez 0 m -> lez 0 n -> lez 0 (m + n).\n\n(*This lemma states that the product of two non-negative integers is also a non-negative integer.*)\nFact lez_mul m n : lez 0 m -> lez 0 n -> lez 0 (m * n).\n\n(*This lemma states that if an integer is both greater than or equal to zero and less than or equal to zero, then that integer must be equal to zero.*)\nFact lez_anti m : lez 0 m -> lez m 0 -> m = 0.\n\n(*This lemma states that an integer is less than or equal to a second integer if and only if the result of subtracting the first integer from the second is greater than or equal to zero.*)\nLemma subz_ge0 m n : lez 0 (n - m) = lez m n.\n\n(*This lemma states that for any pair of integers, either the first is less than or equal to the second, or the second is less than or equal to the first, establishing the totality of the integer order.*)\nFact lez_total m n : lez m n || lez n m.\n\n(*This lemma states that the absolute value of the additive inverse of an integer is equal to the absolute value of the integer itself.*)\nFact normzN m : normz (- m) = normz m.\n\n(*This lemma states that if an integer is greater than or equal to zero, its absolute value is equal to the integer itself.*)\nFact gez0_norm m : lez 0 m -> normz m = m.\n\n(*This lemma states that an integer is strictly less than a second integer if and only if it is not equal to the second integer and is less than or equal to the second integer.*)\nFact ltz_def m n : (ltz m n) = (n != m) && (lez m n).\n\n(*This definition bundles proofs of order properties for integers, such as compatibility with addition and multiplication, antisymmetry, and totality, to formally construct the structure of an ordered integral domain for the integers.*)\nDefinition Mixin := Num.IntegralDomain_isLeReal.Build int\n lez_add lez_mul lez_anti subz_ge0 (lez_total 0) normzN gez0_norm ltz_def.\n\nEnd intOrdered.\nEnd intOrdered.\n\n(*This lemma states that for any two natural numbers, comparing them using the 'less than or equal to' relation after converting them to integers yields the same boolean result as comparing them directly as natural numbers.*)\nLemma lez_nat m n : (m <= n :> int) = (m <= n)%N. \n\n(*This lemma states that for any two natural numbers, comparing them using the 'less than' relation after converting them to integers yields the same boolean result as comparing them directly as natural numbers.*)\nLemma ltz_nat m n : (m < n :> int) = (m < n)%N.\n\n(*This definition groups two lemmas concerning the equivalence of order relations between natural numbers and their integer counterparts, covering both 'less than' and 'less than or equal to'.*)\nDefinition ltez_nat := (lez_nat, ltz_nat).\n\n(*This lemma states that an integer obtained by taking the additive inverse of a natural number is always less than or equal to an integer obtained by converting any natural number.*)\nLemma leNz_nat m n : (- m%:Z <= n). \n\n(*This lemma provides a condition for when the additive inverse of an integer derived from a natural number is strictly less than an integer derived from another natural number. This holds true if and only if at least one of the two original natural numbers is not zero.*)\nLemma ltNz_nat m n : (- m%:Z < n) = (m != 0) || (n != 0).\n\n(*This definition groups two lemmas about order comparisons between the additive inverse of a natural-number-derived integer and another natural-number-derived integer.*)\nDefinition lteNz_nat := (leNz_nat, ltNz_nat).\n\n(*This lemma states that an integer derived from a natural number is less than or equal to the additive inverse of an integer derived from another natural number if and only if both original natural numbers are zero.*)\nLemma lezN_nat m n : (m%:Z <= - n%:Z) = (m == 0) && (n == 0).\n\n(*This lemma states that an integer derived from a natural number can never be strictly less than the additive inverse of an integer derived from another natural number.*)\nLemma ltzN_nat m n : (m%:Z < - n%:Z) = false.\n\n(*This lemma states that zero is less than or equal to any integer derived from a natural number.*)\nLemma le0z_nat n : 0 <= n :> int. \n\n(*This lemma asserts that an integer derived from a natural number is less than or equal to zero if and only if that natural number is zero.*)\nLemma lez0_nat n : n <= 0 :> int = (n == 0 :> nat). \n\n(*This definition groups two lemmas concerning order comparisons between a natural-number-derived integer and the additive inverse of another natural-number-derived integer.*)\nDefinition ltezN_nat := (lezN_nat, ltzN_nat).\n(*This definition aggregates a comprehensive collection of lemmas that relate the order properties of integers with their natural number counterparts, covering comparisons between positive, negative, and zero values.*)\nDefinition ltez_natE := (ltez_nat, lteNz_nat, ltezN_nat, le0z_nat, lez0_nat).\n\n(*This lemma states that for any integer, being strictly greater than zero is equivalent to being greater than or equal to one.*)\nLemma gtz0_ge1 x : (0 < x) = (1 <= x). \n\n(*This lemma states that for any two integers, the sum of one and the first integer being less than or equal to the second integer is equivalent to the first integer being strictly less than the second integer.*)\nLemma lez1D x y : (1 + x <= y) = (x < y).\n\n(*This lemma states that for any two integers, the sum of the first integer and one being less than or equal to the second integer is equivalent to the first integer being strictly less than the second integer.*)\nLemma lezD1 x y : (x + 1 <= y) = (x < y).\n\n(*This lemma states that an integer is strictly less than one plus another integer if and only if the first integer is less than or equal to the second.*)\nLemma ltz1D x y : (x < 1 + y) = (x <= y).\n\n(*This lemma states that an integer is strictly less than another integer plus one if and only if the first integer is less than or equal to the second.*)\nLemma ltzD1 x y : (x < y + 1) = (x <= y).\n\nEnd intOrderedTheory.\n\nBind Scope ring_scope with int.\n\n(*This definition provides a generic way to multiply an element of an additive commutative group by an integer. For a positive integer, it corresponds to repeated addition of the element. For a negative integer, it corresponds to repeated addition of the additive inverse of the element. For zero, it results in the zero element of the group.*)\nDefinition intmul (R : zmodType) (x : R) (n : int) :=\n match n with\n | Posz n => (x *+ n)%R\n | Negz n => (x *- (n.+1))%R\n end.\nArguments intmul : simpl never.\n\n(*This notation provides a syntax for the curried function that multiplies an element of an additive commutative group by an integer.*)\nNotation \"*~%R\" := (@intmul _) : function_scope.\n(*This notation represents the multiplication of an element from an additive commutative group by an integer, serving as an external scalar multiplication.*)\nNotation \"x *~ n\" := (intmul x n) : ring_scope.\n(*This notation defines a function that maps an integer to an element of an additive commutative group by scaling a fixed base element. In a ring context, this base element is typically the multiplicative identity, establishing the canonical map from integers into the ring.*)\nNotation intr := ( *~%R 1).\n\n(*This notation represents the canonical conversion of an integer into a ring element, computed by multiplying the ring's multiplicative identity by the given integer.*)\nNotation \"n %:~R\" := (1 *~ n)%R : ring_scope.\n\n(*This lemma states that multiplying an element of an additive commutative group by a positive integer is equivalent to repeatedly adding that element a number of times corresponding to the integer's value.*)\nLemma pmulrn (R : zmodType) (x : R) (n : nat) : x *+ n = x *~ n%:Z.\n\n(*This lemma states that multiplying an element of an additive commutative group by a negative integer is equivalent to repeatedly subtracting that element a number of times corresponding to the absolute value of the integer.*)\nLemma nmulrn (R : zmodType) (x : R) (n : nat) : x *- n = x *~ - n%:Z.\n\nSection ZintLmod.\n\n(*This definition serves as an identity function on types, creating an alias for a given type to associate it with a canonical structure of a module over the ring of integers.*)\nDefinition zmodule (M : Type) : Type := M.\n(*This notation provides a syntax for aliasing a type to signify that it is being considered as a module over the ring of integers.*)\nLocal Notation \"M ^z\" := (zmodule M) (format \"M ^z\") : type_scope.\nLocal Coercion Posz : nat >-> int.\n\nVariable M : zmodType.\n\nImplicit Types m n : int.\nImplicit Types x y z : M.\n\n(*This fact establishes an associativity property for integer scalar multiplication, stating that scaling a group element by a first integer and then scaling the result by a second integer is equivalent to scaling the original element by the product of the two integers.*)\nFact mulrzA_C m n x : (x *~ n) *~ m = x *~ (m * n).\n\n(*This fact states that the order of scalar multiplication by two integers does not matter; scaling an element by a first integer and then by a second integer yields the same result as scaling by the second integer first and then by the first.*)\nFact mulrzAC m n x : (x *~ n) *~ m = (x *~ m) *~ n.\n\n(*This fact states that multiplying an element of an additive commutative group by the integer one results in the element itself.*)\nFact mulr1z (x : M) : x *~ 1 = x. \n\n(*This fact asserts that scalar multiplication by an integer distributes over the addition in the additive commutative group. Specifically, the result of adding two elements and then multiplying by an integer is the same as multiplying each element by the integer first and then adding the results.*)\nFact mulrzDl m : {morph ( *~%R^~ m : M -> M) : x y / x + y}.\n\n(*This lemma states that multiplying a group element by an integer difference, where the integers originate from two natural numbers, is equal to the difference of separately multiplying the group element by each integer.*)\nLemma mulrzBl_nat (m n : nat) x : x *~ (m%:Z - n%:Z) = x *~ m - x *~ n.\n\n(*This fact asserts that scalar multiplication distributes over integer addition. Specifically, multiplying an element by the sum of two integers is equivalent to summing the results of multiplying the element by each integer separately.*)\nFact mulrzDr x : {morph *~%R x : m n / m + n}.\n\nHB.instance Definition _ := GRing.Zmodule.on M^z. \nHB.instance Definition _ := @GRing.Zmodule_isLmodule.Build _ M^z\n (fun n x => x *~ n) mulrzA_C mulr1z mulrzDl mulrzDr.\n\n(*This lemma establishes the equivalence between the generic left scalar multiplication operation and the specific integer multiplication defined for the type, when that type is viewed as a module over the integers.*)\nLemma scalezrE n x : n *: (x : M^z) = x *~ n. \n\n(*This lemma provides an associativity-like property for integer scalar multiplication, stating that for any two integers, scaling a group element by their product is equivalent to scaling the element by the first integer and then scaling the result by the second. This property holds due to the commutativity of integer multiplication.*)\nLemma mulrzA x m n : x *~ (m * n) = x *~ m *~ n.\n\n(*This lemma states that multiplying any element of an additive commutative group by the integer zero results in the zero element of the group.*)\nLemma mulr0z x : x *~ 0 = 0. \n\n(*This lemma states that multiplying the zero element of an additive commutative group by any integer results in the zero element itself.*)\nLemma mul0rz n : 0 *~ n = 0 :> M.\n\n(*This lemma states that multiplying an element by the negative of an integer is equivalent to taking the additive inverse of the result of multiplying the element by the integer.*)\nLemma mulrNz x n : x *~ (- n) = - (x *~ n).\n\n(*This lemma states that multiplying an element of an additive commutative group by the integer negative one yields the additive inverse of that element.*)\nLemma mulrN1z x : x *~ (- 1) = - x. \n\n(*This lemma states that multiplying the additive inverse of an element by an integer is equivalent to taking the additive inverse of the result of multiplying the original element by that integer.*)\nLemma mulNrz x n : (- x) *~ n = - (x *~ n).\n\n(*This lemma states that scalar multiplication distributes over integer subtraction; multiplying an element by the difference of two integers is equivalent to the difference of the scalar multiplications of the element by each integer.*)\nLemma mulrzBr x m n : x *~ (m - n) = x *~ m - x *~ n.\n\n(*This lemma states that scalar multiplication by an integer distributes over subtraction in the additive commutative group; multiplying the difference of two elements by an integer is equivalent to the difference of the scalar multiplications of each element by that integer.*)\nLemma mulrzBl x y n : (x - y) *~ n = x *~ n - y *~ n.\n\n(*This lemma states that multiplying an element of an additive commutative group by a positive integer derived from a natural number is equivalent to repeatedly adding the element that number of times.*)\nLemma mulrz_nat (n : nat) x : x *~ n%:R = x *+ n.\n\n(*This lemma states that for an element in an integer module, the scalar multiplication by a sum of integers is equal to the sum of the scalar multiplications by each integer.*)\nLemma mulrz_sumr : forall x I r (P : pred I) F,\n x *~ (\\sum_(i <- r | P i) F i) = \\sum_(i <- r | P i) x *~ F i.\n\n(*This lemma states that the scalar multiplication of a sum of module elements by an integer on the right is equal to the sum of the right scalar multiplications of each element by that integer.*)\nLemma mulrz_suml : forall n I r (P : pred I) (F : I -> M),\n (\\sum_(i <- r | P i) F i) *~ n= \\sum_(i <- r | P i) F i *~ n.\n\n(*This is a deprecated notation, an alias for a lemma concerning the left distributivity of integer scalar multiplication, and its use should be replaced.*)\nNotation mulrzDl_tmp := mulrzDl.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use mulrzDr instead.\")]\n(*This is a deprecated notation, an alias for a lemma concerning the right distributivity of integer scalar multiplication, and its use should be replaced.*)\nNotation mulrzDr_tmp := mulrzDr.\n\n(*This lemma asserts that for a function with a finite domain and a codomain that is a module over the integers, scalar multiplication of the function by an integer is pointwise. Applying the scaled function to an argument yields the same result as applying the original function and then scaling the result by the integer.*)\nLemma ffunMzE (I : finType) (M : zmodType) (f : {ffun I -> M}) z x :\n (f *~ z) x = f x *~ z.\n\n(*This lemma states that embedding an integer into the ring of integers results in the original integer.*)\nLemma intz (n : int) : n%:~R = n.\n\n(*This lemma states that embedding a natural number into the ring of integers is equivalent to converting the natural number to a base integer type and then coercing it.*)\nLemma natz (n : nat) : n%:R = n%:Z :> int.\n\nSection RintMod.\n\nLocal Coercion Posz : nat >-> int.\nVariable R : pzRingType.\n\nImplicit Types m n : int.\nImplicit Types x y z : R.\n\n(*This lemma states that for elements in a ring, scalar multiplication by an integer on the left followed by ring multiplication is equivalent to performing the ring multiplication first and then the scalar multiplication by the same integer.*)\nLemma mulrzAl n x y : (x *~ n) * y = (x * y) *~ n.\n\n(*This lemma states that for elements in a ring, ring multiplication with a right-hand operand that has been scalar-multiplied by an integer is equivalent to performing the ring multiplication first and then scalar-multiplying the result by that integer.*)\nLemma mulrzAr n x y : x * (y *~ n) = (x * y) *~ n.\n\n(*This lemma states that, for an element in a ring, left-multiplication by the ring element corresponding to an integer is equivalent to the right scalar multiplication of the element by that integer.*)\nLemma mulrzl x n : n%:~R * x = x *~ n. \n\n(*This lemma states that, for an element in a ring, right-multiplication by the ring element corresponding to an integer is equivalent to the right scalar multiplication of the element by that integer.*)\nLemma mulrzr x n : x * n%:~R = x *~ n. \n\n(*This lemma states that for a ring element, scalar multiplication of its additive inverse by the additive inverse of an integer is equivalent to the scalar multiplication of the original element by the original integer.*)\nLemma mulNrNz n x : (- x) *~ (- n) = x *~ n.\n\n(*This lemma states that the scalar multiplication of a ring element by a boolean value results in the element itself if the boolean is true, and the zero element of the ring if the boolean is false.*)\nLemma mulrbz x (b : bool) : x *~ b = (if b then x else 0).\n\n(*This lemma states that embedding the additive inverse of an integer into a ring is equivalent to embedding the integer first and then taking its additive inverse within the ring.*)\nLemma intrN n : (- n)%:~R = - n%:~R :> R. \n\n(*This lemma states that embedding the sum of two integers into a ring is equivalent to embedding each integer separately and then summing them within the ring.*)\nLemma intrD m n : (m + n)%:~R = m%:~R + n%:~R :> R. \n\n(*This lemma states that embedding the difference of two integers into a ring is equivalent to embedding each integer separately and then taking their difference within the ring.*)\nLemma intrB m n : (m - n)%:~R = m%:~R - n%:~R :> R. \n\n(*This lemma states that embedding the product of two integers into a ring is equivalent to embedding each integer separately and then multiplying them within the ring.*)\nLemma intrM m n : (m * n)%:~R = m%:~R * n%:~R :> R.\n\n(*This lemma states that the function that maps an integer to the corresponding ring element, by scalar-multiplying the ring's multiplicative identity, is a monoid morphism.*)\nLemma intmul1_is_monoid_morphism : monoid_morphism ( *~%R (1 : R)).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `intmul1_is_monoid_morphism` instead\")]\n(*This is a deprecated definition that provides a proof that the function mapping an integer to its corresponding ring element is multiplicative, derived from the `intmul1_is_monoid_morphism` lemma. It should be replaced by `intmul1_is_monoid_morphism`.*)\nDefinition intmul1_is_multiplicative :=\n (fun g => (g.2,g.1)) intmul1_is_monoid_morphism.\n(*This lemma states that for any element in a ring, its scalar multiplication by the integer two is equivalent to adding the element to itself.*)\nLemma mulr2z n : n *~ 2 = n + n. \n\nEnd RintMod.\n\n(*This lemma states that for integers, scalar multiplication of one integer by another is equivalent to their standard multiplication.*)\nLemma mulrzz m n : m *~ n = m * n. \n\n(*This lemma states that multiplying an integer by two is equivalent to adding the integer to itself.*)\nLemma mulz2 n : n * 2%:Z = n + n. \n\n(*This lemma states that multiplying two by an integer is equivalent to adding the integer to itself.*)\nLemma mul2z n : 2%:Z * n = n + n. \n\nSection LMod.\n\nVariable R : pzRingType.\nVariable V : (lmodType R).\nLocal Coercion Posz : nat >-> int.\n\nImplicit Types m n : int.\nImplicit Types x y z : R.\nImplicit Types u v w : V.\n\n(*This lemma states that for a vector in a left module over a ring, left scalar multiplication by the ring element corresponding to an integer is equivalent to right scalar multiplication of the vector by that integer.*)\nLemma scaler_int n v : n%:~R *: v = v *~ n.\n\n(*This lemma provides an associativity rule for scalar multiplication in a left module over a ring. It states that right scalar multiplication by an integer, applied to a vector that has already been scaled by a ring element, is equivalent to scaling the vector by the result of scalar-multiplying the original ring element by that integer.*)\nLemma scalerMzl a v n : (a *: v) *~ n = (a *~ n) *: v.\n\n(*This lemma provides an associativity rule for scalar multiplication in a left module over a ring. It states that right scalar multiplication by an integer, applied to a vector that has already been scaled by a ring element, is equivalent to scaling by the ring element the result of applying the integer scalar multiplication to the original vector.*)\nLemma scalerMzr a v n : (a *: v) *~ n = a *: (v *~ n).\n\nEnd LMod.\n\n(*This lemma states that for an element in a module over the integers, its right scalar multiplication by an integer is unchanged if that integer is first explicitly embedded into the ring of integers.*)\nLemma mulrz_int (M : zmodType) (n : int) (x : M) : x *~ n%:~R = x *~ n.\n\nSection MorphTheory.\nLocal Coercion Posz : nat >-> int.\nSection Additive.\nVariables (U V : zmodType) (f : {additive U -> V}).\n\n(*This lemma states that any additive function between two integer modules also preserves the right scalar multiplication by an integer.*)\nLemma raddfMz n : {morph f : x / x *~ n}.\n\nEnd Additive.\n\nSection Multiplicative.\n\nVariables (R S : pzRingType) (f : {rmorphism R -> S}).\n\n(*This lemma states that any ring morphism between two rings preserves the right scalar multiplication by an integer.*)\nLemma rmorphMz : forall n, {morph f : x / x *~ n}. \n\n(*This lemma states that a ring morphism maps the canonical embedding of an integer in the source ring to the canonical embedding of the same integer in the target ring.*)\nLemma rmorph_int : forall n, f n%:~R = n%:~R.\n\nEnd Multiplicative.\n\nSection Linear.\n\nVariable R : pzRingType.\nVariables (U V : lmodType R) (f : {linear U -> V}).\n\n(*This lemma states that for any linear map between two modules over a ring, applying the map to a vector scaled by an integer is equivalent to first applying the map to the vector and then scaling the resulting vector by the same integer.*)\nLemma linearMn : forall n, {morph f : x / x *~ n}. \n\nEnd Linear.\n\n(*This lemma states that any additive function between two modules over the integers is also scalable, meaning it preserves scalar multiplication.*)\nLemma raddf_int_scalable (aV rV : lmodType int) (f : {additive aV -> rV}) :\n scalable f.\n\nSection Zintmul1rMorph.\n\nVariable R : pzRingType.\n\n(*This lemma states that if two elements in a ring commute, then the first element also commutes with the second element scaled by any integer.*)\nLemma commrMz (x y : R) n : GRing.comm x y -> GRing.comm x (y *~ n).\n\n(*This lemma states that any element in a ring commutes with the ring element obtained by embedding an integer into the ring.*)\nLemma commr_int (x : R) n : GRing.comm x n%:~R.\n\nEnd Zintmul1rMorph.\n\nSection ZintBigMorphism.\n\nVariable R : pzRingType.\n\n(*This lemma states that for a finite sum of natural numbers, embedding the total sum into a ring is equivalent to first embedding each individual natural number into the ring and then performing the summation within the ring.*)\nLemma sumMz : forall I r (P : pred I) F,\n (\\sum_(i <- r | P i) F i)%N%:~R = \\sum_(i <- r | P i) ((F i)%:~R) :> R.\n\n(*This lemma states that for a finite product of natural numbers, embedding the final product into a ring is equivalent to first embedding each individual natural number into the ring and then performing the product within the ring.*)\nLemma prodMz : forall I r (P : pred I) F,\n (\\prod_(i <- r | P i) F i)%N%:~R = \\prod_(i <- r | P i) ((F i)%:~R) :> R.\n\nEnd ZintBigMorphism.\n\nSection Frobenius.\n\nVariable R : nzRingType.\nImplicit Types x y : R.\n\nVariable p : nat.\nHypothesis pcharFp : p \\in [pchar R].\n\n(*This notation defines the expression 'x ^f' as the result of applying the Frobenius automorphism to a ring element x, which raises x to the power of the ring's characteristic.*)\nLocal Notation \"x ^f\" := (pFrobenius_aut pcharFp x).\n\n(*This lemma states that applying the Frobenius automorphism to a ring element that has been scaled by an integer is equivalent to first applying the automorphism to the element and then scaling the result by the same integer.*)\nLemma pFrobenius_autMz x n : (x *~ n)^f = x^f *~ n.\n\n(*This lemma states that the Frobenius automorphism leaves unchanged any ring element that is obtained by embedding an integer into the ring.*)\nLemma pFrobenius_aut_int n : (n%:~R)^f = n%:~R.\n\nEnd Frobenius.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_autMz instead.\")]\n(*This is a deprecated notation, now an alias for pFrobenius_autMz, which states that the Frobenius automorphism commutes with scalar multiplication by an integer.*)\nNotation Frobenius_autMz := (pFrobenius_autMz) (only parsing).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pFrobenius_aut_int instead.\")]\n(*This is a deprecated notation, now an alias for pFrobenius_aut_int, which states that the Frobenius automorphism acts as the identity on ring elements that originate from integers.*)\nNotation Frobenius_aut_int := (pFrobenius_aut_int) (only parsing).\n\nSection NumMorphism.\n\nSection PO.\n\nVariables (R : numDomainType).\n\nImplicit Types n m : int.\nImplicit Types x y : R.\n\n(*This lemma states that any ring homomorphism from the integers to a numerical domain is uniquely determined and is equal to the canonical embedding of integers into that domain.*)\nLemma rmorphzP (f : {rmorphism int -> R}) : f =1 ( *~%R 1).\n\n(*This lemma states that multiplying two elements of an ordered ring by the same positive integer preserves the less-than-or-equal-to relation between them.*)\nLemma ler_pMz2r n (hn : 0 < n) : {mono *~%R^~ n :x y / x <= y :> R}.\n\n(*This lemma states that multiplying two elements of an ordered ring by the same positive integer preserves the strict less-than relation between them.*)\nLemma ltr_pMz2r n (hn : 0 < n) : {mono *~%R^~ n : x y / x < y :> R}.\n\n(*This lemma states that multiplying two elements of an ordered ring by the same negative integer reverses the less-than-or-equal-to relation between them.*)\nLemma ler_nMz2r n (hn : n < 0) : {mono *~%R^~ n : x y /~ x <= y :> R}.\n\n(*This lemma states that multiplying two elements of an ordered ring by the same negative integer reverses the strict less-than relation between them.*)\nLemma ltr_nMz2r n (hn : n < 0) : {mono *~%R^~ n : x y /~ x < y :> R}.\n\n(*This lemma states that multiplying two elements of an ordered ring by the same non-negative integer preserves the less-than-or-equal-to relation between them.*)\nLemma ler_wpMz2r n (hn : 0 <= n) : {homo *~%R^~ n : x y / x <= y :> R}.\n\n(*This lemma states that multiplying two elements of an ordered ring by the same non-positive integer reverses the less-than-or-equal-to relation between them.*)\nLemma ler_wnMz2r n (hn : n <= 0) : {homo *~%R^~ n : x y /~ x <= y :> R}.\n\n(*This lemma states that in an ordered ring, the product of a non-negative element and a non-negative integer is also a non-negative element.*)\nLemma mulrz_ge0 x n (x0 : 0 <= x) (n0 : 0 <= n) : 0 <= x *~ n.\n\n(*This lemma states that in an ordered ring, the product of a non-positive element and a non-positive integer is a non-negative element.*)\nLemma mulrz_le0 x n (x0 : x <= 0) (n0 : n <= 0) : 0 <= x *~ n.\n\n(*This lemma states that in an ordered ring, the product of a non-negative element and a non-positive integer is a non-positive element.*)\nLemma mulrz_ge0_le0 x n (x0 : 0 <= x) (n0 : n <= 0) : x *~ n <= 0.\n\n(*This lemma states that in an ordered ring, the product of a non-positive element and a non-negative integer is a non-positive element.*)\nLemma mulrz_le0_ge0 x n (x0 : x <= 0) (n0 : 0 <= n) : x *~ n <= 0.\n\n(*This lemma states that for any positive integer, an element in an ordered ring scaled by that integer is strictly positive if and only if the original element is strictly positive.*)\nLemma pmulrz_lgt0 x n (n0 : 0 < n) : 0 < x *~ n = (0 < x).\n\n(*This lemma states that for any negative integer, an element in an ordered ring scaled by that integer is strictly positive if and only if the original element is strictly negative.*)\nLemma nmulrz_lgt0 x n (n0 : n < 0) : 0 < x *~ n = (x < 0).\n\n(*This lemma states that for any positive integer, an element in an ordered ring scaled by that integer is strictly negative if and only if the original element is strictly negative.*)\nLemma pmulrz_llt0 x n (n0 : 0 < n) : x *~ n < 0 = (x < 0).\n\n(*This lemma states that for any negative integer, an element in an ordered ring scaled by that integer is strictly negative if and only if the original element is strictly positive.*)\nLemma nmulrz_llt0 x n (n0 : n < 0) : x *~ n < 0 = (0 < x).\n\n(*This lemma states that for any positive integer, an element in an ordered ring scaled by that integer is non-negative if and only if the original element is non-negative.*)\nLemma pmulrz_lge0 x n (n0 : 0 < n) : 0 <= x *~ n = (0 <= x).\n\n(*This lemma states that for any negative integer, an element in an ordered ring scaled by that integer is non-negative if and only if the original element is non-positive.*)\nLemma nmulrz_lge0 x n (n0 : n < 0) : 0 <= x *~ n = (x <= 0).\n\n(*This lemma states that for any positive integer, an element in an ordered ring scaled by that integer is non-positive if and only if the original element is non-positive.*)\nLemma pmulrz_lle0 x n (n0 : 0 < n) : x *~ n <= 0 = (x <= 0).\n\n(*This lemma states that for any negative integer, an element in an ordered ring scaled by that integer is non-positive if and only if the original element is non-negative.*)\nLemma nmulrz_lle0 x n (n0 : n < 0) : x *~ n <= 0 = (0 <= x).\n\n(*This lemma states that for any non-negative real number, the function that multiplies an integer by this real number is non-decreasing with respect to the standard order on integers and reals.*)\nLemma ler_wpMz2l x (hx : 0 <= x) : {homo *~%R x : x y / x <= y}.\n\n(*This lemma states that for any non-positive real number, the function that multiplies an integer by this real number is non-increasing, meaning it reverses the standard 'less than or equal to' relationship between integers.*)\nLemma ler_wnMz2l x (hx : x <= 0) : {homo *~%R x : x y /~ x <= y}.\n\n(*This lemma states that for any strictly positive real number, the function mapping an integer to its product with this real number is an injective and non-decreasing map from the integers to the real numbers, both with their standard 'less than or equal to' order.*)\nLemma ler_pMz2l x (hx : 0 < x) : {mono *~%R x : x y / x <= y}.\n\n(*This lemma states that for any strictly negative real number, the function mapping an integer to its product with this real number is an injective and non-increasing map, reversing the standard 'less than or equal to' order.*)\nLemma ler_nMz2l x (hx : x < 0) : {mono *~%R x : x y /~ x <= y}.\n\n(*This lemma states that for any strictly positive real number, the function that multiplies an integer by this real number is strictly increasing, preserving the 'less than' relation between integers and their resulting real products.*)\nLemma ltr_pMz2l x (hx : 0 < x) : {mono *~%R x : x y / x < y}.\n\n(*This lemma states that for any strictly negative real number, the function that multiplies an integer by this real number is strictly decreasing, reversing the 'less than' relation between integers.*)\nLemma ltr_nMz2l x (hx : x < 0) : {mono *~%R x : x y /~ x < y}.\n\n(*This lemma states that the product of a strictly positive real number and an integer is strictly positive if and only if the integer is strictly positive.*)\nLemma pmulrz_rgt0 x n (x0 : 0 < x) : 0 < x *~ n = (0 < n).\n\n(*This lemma states that the product of a strictly negative real number and an integer is strictly positive if and only if the integer is strictly negative.*)\nLemma nmulrz_rgt0 x n (x0 : x < 0) : 0 < x *~ n = (n < 0).\n\n(*This lemma states that the product of a strictly positive real number and an integer is strictly negative if and only if the integer is strictly negative.*)\nLemma pmulrz_rlt0 x n (x0 : 0 < x) : x *~ n < 0 = (n < 0).\n\n(*This lemma states that the product of a strictly negative real number and an integer is strictly negative if and only if the integer is strictly positive.*)\nLemma nmulrz_rlt0 x n (x0 : x < 0) : x *~ n < 0 = (0 < n).\n\n(*This lemma states that the product of a strictly positive real number and an integer is non-negative if and only if the integer is non-negative.*)\nLemma pmulrz_rge0 x n (x0 : 0 < x) : 0 <= x *~ n = (0 <= n).\n\n(*This lemma states that the product of a strictly negative real number and an integer is non-negative if and only if the integer is non-positive.*)\nLemma nmulrz_rge0 x n (x0 : x < 0) : 0 <= x *~ n = (n <= 0).\n\n(*This lemma states that the product of a strictly positive real number and an integer is non-positive if and only if the integer is non-positive.*)\nLemma pmulrz_rle0 x n (x0 : 0 < x) : x *~ n <= 0 = (n <= 0).\n\n(*This lemma states that the product of a strictly negative real number and an integer is non-positive if and only if the integer is non-negative.*)\nLemma nmulrz_rle0 x n (x0 : x < 0) : x *~ n <= 0 = (0 <= n).\n\n(*This lemma states that for any non-zero real number, the function that multiplies an integer by this real number is injective.*)\nLemma mulrIz x (hx : x != 0) : injective ( *~%R x).\n\n(*This lemma states that an integer is less than or equal to another integer if and only if the real number representation of the first is less than or equal to the real number representation of the second.*)\nLemma ler_int m n : (m%:~R <= n%:~R :> R) = (m <= n).\n\n(*This lemma states that an integer is strictly less than another integer if and only if the real number representation of the first is strictly less than the real number representation of the second.*)\nLemma ltr_int m n : (m%:~R < n%:~R :> R) = (m < n).\n\n(*This lemma states that two integers are equal if and only if their corresponding real number representations are equal.*)\nLemma eqr_int m n : (m%:~R == n%:~R :> R) = (m == n).\n\n(*This lemma states that an integer is non-negative if and only if its corresponding real number representation is non-negative.*)\nLemma ler0z n : (0 <= n%:~R :> R) = (0 <= n).\n\n(*This lemma states that an integer is strictly positive if and only if its corresponding real number representation is strictly positive.*)\nLemma ltr0z n : (0 < n%:~R :> R) = (0 < n).\n\n(*This lemma states that an integer is non-positive if and only if its corresponding real number representation is non-positive.*)\nLemma lerz0 n : (n%:~R <= 0 :> R) = (n <= 0).\n\n(*This lemma states that an integer is strictly negative if and only if its corresponding real number representation is strictly negative.*)\nLemma ltrz0 n : (n%:~R < 0 :> R) = (n < 0).\n\n(*This lemma states that an integer is greater than or equal to one if and only if its corresponding real number representation is greater than or equal to one.*)\nLemma ler1z (n : int) : (1 <= n%:~R :> R) = (1 <= n).\n\n(*This lemma states that an integer is strictly greater than one if and only if its corresponding real number representation is strictly greater than one.*)\nLemma ltr1z (n : int) : (1 < n%:~R :> R) = (1 < n).\n\n(*This lemma states that an integer is less than or equal to one if and only if its corresponding real number representation is less than or equal to one.*)\nLemma lerz1 n : (n%:~R <= 1 :> R) = (n <= 1).\n\n(*This lemma states that an integer is strictly less than one if and only if its corresponding real number representation is strictly less than one.*)\nLemma ltrz1 n : (n%:~R < 1 :> R) = (n < 1).\n\n(*This lemma states that an integer is equal to zero if and only if its corresponding real number representation is equal to zero.*)\nLemma intr_eq0 n : (n%:~R == 0 :> R) = (n == 0).\n\n(*This lemma states that the product of a real number and an integer is zero if and only if the integer is zero or the real number is zero.*)\nLemma mulrz_eq0 x n : (x *~ n == 0) = ((n == 0) || (x == 0)).\n\n(*This lemma states that the product of a real number and an integer is non-zero if and only if both the integer and the real number are non-zero.*)\nLemma mulrz_neq0 x n : x *~ n != 0 = ((n != 0) && (x != 0)).\n\n(*This lemma states that the representation of an integer as a real number is a member of the canonical set of real numbers.*)\nLemma realz n : (n%:~R : R) \\in Num.real.\n\nHint Resolve realz : core.\n\n(*This definition establishes the injectivity of the canonical mapping from the integers into a non-trivial ring, where non-triviality is ensured by the condition that one is not equal to zero.*)\nDefinition intr_inj := @mulrIz 1 (oner_neq0 R).\n\nEnd PO.\n\nEnd NumMorphism.\n\nEnd MorphTheory.\n\nArguments intr_inj {R} [x1 x2].\n\n(*This definition provides a way to compute the power of a ring element raised to an integer exponent. If the exponent is a non-negative integer, it computes the standard power by repeated multiplication. If the exponent is a negative integer, it computes the power of the multiplicative inverse of the ring element.*)\nDefinition exprz (R : unitRingType) (x : R) (n : int) :=\n match n with\n | Posz n => x ^+ n\n | Negz n => x ^- (n.+1)\n end.\nArguments exprz : simpl never.\n\n(*This notation represents the exponentiation of a ring element to an integer power.*)\nNotation \"x ^ n\" := (exprz x n) : ring_scope.\n\nSection ExprzUnitRing.\n\nVariable R : unitRingType.\nImplicit Types x y : R.\nImplicit Types m n : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that raising a ring element to a non-negative integer power is equivalent to raising that same element to the power of the corresponding natural number.*)\nLemma exprnP x (n : nat) : x ^+ n = x ^ n. \n\n(*This lemma states that raising the multiplicative inverse of a ring element to a natural number power is equivalent to raising the original element to the power of the corresponding negative integer.*)\nLemma exprnN x (n : nat) : x ^- n = x ^ -n%:Z.\n\n(*This lemma states that any ring element raised to the power of zero is equal to the multiplicative identity, one.*)\nLemma expr0z x : x ^ 0 = 1. \n\n(*This lemma states that any ring element raised to the power of one is equal to the element itself.*)\nLemma expr1z x : x ^ 1 = x. \n\n(*This lemma states that any ring element raised to the power of negative one is equal to its multiplicative inverse.*)\nLemma exprN1 x : x ^ (-1) = x^-1. \n\n(*This lemma states that the multiplicative inverse of a ring element raised to an integer power is equal to the same element raised to the additive inverse of that integer power.*)\nLemma invr_expz x n : (x ^ n)^-1 = x ^ (- n).\n\n(*This lemma states that raising the multiplicative inverse of a ring element to an integer power is equivalent to raising the original element to the additive inverse of that integer power.*)\nLemma exprz_inv x n : (x^-1) ^ n = x ^ (- n).\n\n(*This lemma states that the multiplicative identity of a ring, one, raised to any integer power is equal to one.*)\nLemma exp1rz n : 1 ^ n = 1 :> R.\n\n(*This lemma provides a recursive definition for exponentiation, stating that a ring element raised to the power of a successor of a natural number is equal to the element multiplied by itself raised to the power of that natural number.*)\nLemma exprSz x (n : nat) : x ^ n.+1 = x * x ^ n. \n\n(*This lemma provides a right-associative recursive definition for exponentiation, stating that a ring element raised to the power of a successor of a natural number is equal to the element raised to the power of that natural number multiplied by the element itself.*)\nLemma exprSzr x (n : nat) : x ^ n.+1 = x ^ n * x. \n\n(*This fact states that for any two non-negative integer exponents, raising a ring element to their sum is equivalent to the product of the ring element raised to each exponent individually.*)\nFact exprzD_nat x (m n : nat) : x ^ (m%:Z + n) = x ^ m * x ^ n.\n\n(*This fact states that for any two negative integer exponents, raising a ring element to their sum is equivalent to the product of the ring element raised to each exponent individually.*)\nFact exprzD_Nnat x (m n : nat) : x ^ (-m%:Z + -n%:Z) = x ^ (-m%:Z) * x ^ (-n%:Z).\n\n(*This lemma states that for a given ring element, raising it to the sum of two integer exponents is equal to the product of the element raised to each exponent, provided both exponents are non-negative or both are non-positive.*)\nLemma exprzD_ss x m n : (0 <= m) && (0 <= n) || (m <= 0) && (n <= 0)\n -> x ^ (m + n) = x ^ m * x ^ n.\n\n(*This lemma states that the zero element of a ring raised to an integer power is equal to one if the exponent is zero, and zero otherwise.*)\nLemma exp0rz n : 0 ^ n = (n == 0)%:~R :> R.\n\n(*This lemma states that if two ring elements commute, then the first element also commutes with any integer power of the second element.*)\nLemma commrXz x y n : GRing.comm x y -> GRing.comm x (y ^ n).\n\n(*This lemma states that for two commuting unit elements in a ring, raising their product to an integer power is equivalent to the product of each element raised individually to that same power.*)\nLemma exprMz_comm x y n : x \\is a GRing.unit -> y \\is a GRing.unit ->\n GRing.comm x y -> (x * y) ^ n = x ^ n * y ^ n.\n\n(*This lemma states that for two commuting ring elements, raising their product to a non-negative integer power is equivalent to the product of each element raised individually to that same power.*)\nLemma commrXz_wmulls x y n :\n 0 <= n -> GRing.comm x y -> (x * y) ^ n = x ^ n * y ^ n.\n\n(*This lemma states that if a ring element is a unit, then that element raised to any integer power is also a unit.*)\nLemma unitrXz x n (ux : x \\is a GRing.unit) : x ^ n \\is a GRing.unit.\n\n(*This lemma states that for any unit element in a ring, raising it to the sum of two integer exponents is equal to the product of the element raised to each of those exponents individually.*)\nLemma exprzDr x (ux : x \\is a GRing.unit) m n : x ^ (m + n) = x ^ m * x ^ n.\n\n(*This lemma states that for a unit element in a ring, raising it to an integer power and then raising the result to another integer power is equivalent to raising the original element to the product of the two integer powers.*)\nLemma exprz_exp x m n : (x ^ m) ^ n = (x ^ (m * n)).\n\n(*This lemma states that for a unit element in a ring, the order of applying two integer exponentiations can be swapped, as raising the element to a first power and then a second is equivalent to raising it to the second power and then the first.*)\nLemma exprzAC x m n : (x ^ m) ^ n = (x ^ n) ^ m.\n\n(*This lemma states that for an element that is not a unit in a ring, raising it to the additive inverse of a non-negative integer is equivalent to raising it to that same non-negative integer.*)\nLemma exprz_out x n (nux : x \\isn't a GRing.unit) (hn : 0 <= n) :\n x ^ (- n) = x ^ n.\n\nEnd ExprzUnitRing.\n\nSection Exprz_Zint_UnitRing.\n\nVariable R : unitRingType.\nImplicit Types x y : R.\nImplicit Types m n : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that for a non-negative integer exponent, raising the product of a ring element and an integer scalar to that power is equivalent to the product of the ring element raised to that power and the integer scalar raised to that same power.*)\nLemma exprz_pMzl x m n : 0 <= n -> (x *~ m) ^ n = x ^ n *~ (m ^ n).\n\n(*This lemma states that for a non-negative integer exponent, raising the ring element corresponding to an integer to that power is equivalent to the ring element corresponding to the integer raised to that same power.*)\nLemma exprz_pintl m n (hn : 0 <= n) : m%:~R ^ n = (m ^ n)%:~R :> R.\n\n(*This lemma states that if a ring element is a unit and an integer scalar maps to a unit in the ring, then raising their product to any integer power is equal to the product of the scalar value raised to that power and the ring element raised to that power.*)\nLemma exprzMzl x m n (ux : x \\is a GRing.unit) (um : m%:~R \\is a @GRing.unit R):\n (x *~ m) ^ n = (m%:~R ^ n) * x ^ n :> R.\n\n(*This lemma states that raising the additive inverse of a ring element to an integer power is equivalent to multiplying the element raised to that power by the ring element for negative one raised to the same power.*)\nLemma expNrz x n : (- x) ^ n = (-1) ^ n * x ^ n :> R.\n\n(*This lemma states that if a ring element raised to a non-zero integer power is a unit, then the original element must also be a unit.*)\nLemma unitr_n0expz x n :\n n != 0 -> (x ^ n \\is a GRing.unit) = (x \\is a GRing.unit).\n\n(*This lemma states that for an integer that is either zero, one, or negative one, the multiplicative inverse of its canonical image in a ring is equal to the image itself.*)\nLemma intrV (n : int) :\n n \\in [:: 0; 1; -1] -> n%:~R ^-1 = n%:~R :> R.\n\n(*This lemma states that any ring morphism preserves integer exponentiation when applied to elements that are units in the domain ring.*)\nLemma rmorphXz (R' : unitRingType) (f : {rmorphism R -> R'}) n :\n {in GRing.unit, {morph f : x / x ^ n}}.\n\nEnd Exprz_Zint_UnitRing.\n\nSection ExprzIdomain.\n\nVariable R : idomainType.\nImplicit Types x y : R.\nImplicit Types m n : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that for an element of an integral domain, raising it to an integer power results in zero if and only if the exponent is a non-zero integer and the base element is zero.*)\nLemma expfz_eq0 x n : (x ^ n == 0) = (n != 0) && (x == 0).\n\n(*This lemma states that in an integral domain, a non-zero element raised to any integer power remains non-zero.*)\nLemma expfz_neq0 x n : x != 0 -> x ^ n != 0.\n\n(*This lemma states that for any two units in an integral domain, the integer power of their product is equal to the product of their individual integer powers.*)\nLemma exprzMl x y n (ux : x \\is a GRing.unit) (uy : y \\is a GRing.unit) :\n (x * y) ^ n = x ^ n * y ^ n.\n\n(*This lemma states that for any non-zero element of an integral domain, the multiplicative inverse of the element raised to an integer power is equal to the multiplicative inverse of the element, raised to that same integer power.*)\nLemma expfV (x : R) (i : int) : (x ^ i) ^-1 = (x ^-1) ^ i.\n\nEnd ExprzIdomain.\n\nSection ExprzField.\n\nVariable F : fieldType.\nImplicit Types x y : F.\nImplicit Types m n : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that for a non-zero element of a field, raising it to the power of a sum of two integers is equivalent to multiplying the results of raising the element to each integer power individually.*)\nLemma expfzDr x m n : x != 0 -> x ^ (m + n) = x ^ m * x ^ n.\n\n(*This lemma states that for any element of a field, raising it to the power of a sum of two integers is equivalent to the product of the powers, provided that the sum of the exponents is not zero.*)\nLemma expfz_n0addr x m n : m + n != 0 -> x ^ (m + n) = x ^ m * x ^ n.\n\n(*This lemma states that for any two elements in a field, the integer power of their product is equal to the product of their individual integer powers.*)\nLemma expfzMl x y n : (x * y) ^ n = x ^ n * y ^ n.\n\n(*This lemma states that any ring morphism from a field to a unit ring preserves integer exponentiation.*)\nLemma fmorphXz (R : unitRingType) (f : {rmorphism F -> R}) n :\n {morph f : x / x ^ n}.\n\nEnd ExprzField.\n\nSection ExprzNumDomain.\n\nVariable R : numDomainType.\nImplicit Types x y : R.\nImplicit Types m n : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that a non-negative element of a numerical domain raised to any integer power results in a non-negative value.*)\nLemma exprz_ge0 n x (hx : 0 <= x) : (0 <= x ^ n).\n\n(*This lemma states that a positive element of a numerical domain raised to any integer power results in a positive value.*)\nLemma exprz_gt0 n x (hx : 0 < x) : (0 < x ^ n).\n\n(*This definition bundles two lemmas, one stating that integer powers of non-negative elements are non-negative, and another stating that integer powers of positive elements are positive.*)\nDefinition exprz_gte0 := (exprz_ge0, exprz_gt0).\n\n(*This lemma states that for an element of a numerical domain between zero and one, inclusive, the function that maps a non-negative integer to the element raised to that integer's power is non-increasing.*)\nLemma ler_wpiXz2l x (x0 : 0 <= x) (x1 : x <= 1) :\n {in >= 0 &, {homo exprz x : x y /~ x <= y}}.\n\n(*This fact states that for an element of a numerical domain that is greater than or equal to one, the function that maps a non-negative integer to the element raised to that integer's power is non-decreasing.*)\nFact ler_wpeXz2l x (x1 : 1 <= x) : {in >= 0 &, {homo exprz x : x y / x <= y}}.\n\n(*This lemma states that for a non-negative element of a numerical domain, raising it to an integer power results in one if and only if the exponent is zero or the base is one.*)\nLemma pexprz_eq1 x n (x0 : 0 <= x) : (x ^ n == 1) = ((n == 0) || (x == 1)).\n\n(*This lemma states that for a fixed non-negative integer exponent, the function that raises an element to that power is non-decreasing on the domain of non-negative elements of a numerical domain.*)\nLemma ler_wpXz2r n (hn : 0 <= n) :\n {in >= 0 & , {homo (@exprz R)^~ n : x y / x <= y}}.\n\nEnd ExprzNumDomain.\n\nSection ExprzOrder.\n\nVariable R : realFieldType.\nImplicit Types x y : R.\nImplicit Types m n : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that for an element of a real field between zero and one, inclusive, the function that maps a strictly negative integer to the element raised to that integer's power is non-increasing.*)\nLemma ler_wniXz2l x (x0 : 0 <= x) (x1 : x <= 1) :\n {in < 0 &, {homo exprz x : x y /~ x <= y}}.\n\n(*This fact states that for an element of a real field greater than or equal to one, the function that maps a non-positive integer to the element raised to that integer's power is non-decreasing.*)\nFact ler_wneXz2l x (x1 : 1 <= x) : {in <= 0 &, {homo exprz x : x y / x <= y}}.\n\n(*This lemma states that for an element of a real field that is greater than or equal to one, the function mapping an integer to the element raised to that integer's power is non-decreasing over the set of all integers.*)\nLemma ler_weXz2l x (x1 : 1 <= x) : {homo exprz x : x y / x <= y}.\n\n(*This lemma states that for a positive element of a real field that is not equal to one, the function mapping an integer to the element raised to that integer's power is injective.*)\nLemma ieexprIz x (x0 : 0 < x) (nx1 : x != 1) : injective (exprz x).\n\n(*This lemma states that for an element of a real field strictly between zero and one, the function mapping a non-negative integer to the element raised to that integer's power is strictly decreasing.*)\nLemma ler_piXz2l x (x0 : 0 < x) (x1 : x < 1) :\n {in >= 0 &, {mono exprz x : x y /~ x <= y}}.\n\n(*This lemma states that for an element of a real field strictly between zero and one, an inequality between two non-negative integer exponents is equivalent to the reversed inequality between the powers of the element raised to those exponents.*)\nLemma ltr_piXz2l x (x0 : 0 < x) (x1 : x < 1) :\n {in >= 0 &, {mono exprz x : x y /~ x < y}}.\n\n(*This lemma states that for an element of a real field strictly between zero and one, the function mapping a strictly negative integer to the element raised to that integer's power is strictly decreasing.*)\nLemma ler_niXz2l x (x0 : 0 < x) (x1 : x < 1) :\n {in < 0 &, {mono exprz x : x y /~ x <= y}}.\n\n(*This lemma states that for an element of a real field strictly between zero and one, an inequality between two strictly negative integer exponents is equivalent to the reversed inequality between the powers of the element raised to those exponents.*)\nLemma ltr_niXz2l x (x0 : 0 < x) (x1 : x < 1) :\n {in < 0 &, {mono (exprz x) : x y /~ x < y}}.\n\n(*This lemma states that for an element of a real field greater than one, the function mapping an integer to the element raised to that integer's power is strictly increasing over the set of all integers.*)\nLemma ler_eXz2l x (x1 : 1 < x) : {mono exprz x : x y / x <= y}.\n\n(*This lemma states that for an element of a real field greater than one, an inequality between two integer exponents is equivalent to the same inequality between the powers of the element raised to those exponents.*)\nLemma ltr_eXz2l x (x1 : 1 < x) : {mono exprz x : x y / x < y}.\n\n(*This lemma states that for a fixed non-positive integer exponent, the function that raises an element to that power is non-increasing on the domain of positive elements of a real field.*)\nLemma ler_wnXz2r n (hn : n <= 0) :\n {in > 0 & , {homo (@exprz R)^~ n : x y /~ x <= y}}.\n\n(*This lemma states that for any non-zero integer exponent, the function that raises an element to that power is injective on the domain of non-negative real numbers.*)\nLemma pexpIrz n (n0 : n != 0) : {in >= 0 &, injective ((@exprz R)^~ n)}.\n\n(*This lemma states that for any non-zero integer exponent, the function that raises an element to that power is injective on the domain of non-positive real numbers.*)\nLemma nexpIrz n (n0 : n != 0) : {in <= 0 &, injective ((@exprz R)^~ n)}.\n\n(*This lemma states that for any positive integer exponent, the function that raises a non-negative number from a numeric domain to that exponent is non-decreasing.*)\nLemma ler_pXz2r n (hn : 0 < n) :\n {in >= 0 & , {mono ((@exprz R)^~ n) : x y / x <= y}}.\n\n(*This lemma states that for any positive integer exponent, the function that raises a non-negative number from a numeric domain to that exponent is strictly increasing.*)\nLemma ltr_pXz2r n (hn : 0 < n) :\n {in >= 0 & , {mono ((@exprz R)^~ n) : x y / x < y}}.\n\n(*This lemma states that for any negative integer exponent, the function that raises a positive number from a numeric domain to that exponent is non-increasing.*)\nLemma ler_nXz2r n (hn : n < 0) :\n {in > 0 & , {mono ((@exprz R)^~ n) : x y /~ x <= y}}.\n\n(*This lemma states that for any negative integer exponent, the function that raises a positive number from a numeric domain to that exponent is strictly decreasing.*)\nLemma ltr_nXz2r n (hn : n < 0) :\n {in > 0 & , {mono ((@exprz R)^~ n) : x y /~ x < y}}.\n\n(*This lemma states that for any non-zero integer exponent, two non-negative numbers from a numeric domain raised to that exponent are equal if and only if the original numbers are equal.*)\nLemma eqrXz2 n x y : n != 0 -> 0 <= x -> 0 <= y -> (x ^ n == y ^ n) = (x == y).\n\nEnd ExprzOrder.\n\n(*A notation for the sign function on a numeric domain, which returns one, negative one, or zero as an element of that domain, depending on whether the input is positive, negative, or zero, respectively.*)\nLocal Notation sgr := Num.sg.\n\nSection Sgz.\n\nVariable R : numDomainType.\nImplicit Types x y z : R.\nImplicit Types m n p : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This definition specifies the integer sign function for an element of a numeric domain. It returns the integer one if the element is positive, negative one if it is negative, and zero if it is zero.*)\nDefinition sgz x : int := if x == 0 then 0 else if x < 0 then -1 else 1.\n\n(*This lemma provides an equivalent computational formula for the integer sign function of an element from a numeric domain, expressing it using multiplication and exponentiation involving booleans.*)\nLemma sgz_def x : sgz x = (-1) ^+ (x < 0)%R *+ (x != 0).\n\n(*This lemma states that the sign of an element from a numeric domain, represented as an element of that domain, is equal to the integer sign of that same element converted into an element of the domain.*)\nLemma sgrEz x : sgr x = (sgz x)%:~R. \n\n(*This lemma states that the integer sign of any positive element from a numeric domain is one.*)\nLemma gtr0_sgz x : 0 < x -> sgz x = 1.\n\n(*This lemma states that the integer sign of any negative element from a numeric domain is negative one.*)\nLemma ltr0_sgz x : x < 0 -> sgz x = -1.\n\n(*This lemma states that the integer sign of the zero element in a numeric domain is zero.*)\nLemma sgz0 : sgz (0 : R) = 0. \n(*This lemma states that the integer sign of the multiplicative identity element in a numeric domain is one.*)\nLemma sgz1 : sgz (1 : R) = 1. \n(*This lemma states that the integer sign of the additive inverse of the multiplicative identity in a numeric domain is negative one.*)\nLemma sgzN1 : sgz (-1 : R) = -1. \n\n(*This definition bundles three lemmas concerning the integer sign of zero, one, and negative one in a numeric domain into a single composite proof object.*)\nDefinition sgzE := (sgz0, sgz1, sgzN1).\n\n(*This lemma states that applying the integer sign function to the result of the domain-specific sign function of an element is equivalent to applying the integer sign function directly to the element.*)\nLemma sgz_sgr x : sgz (sgr x) = sgz x.\n\n(*This lemma states that the natural number absolute value of the integer sign of an element from a numeric domain is one if the element is non-zero and zero if the element is zero.*)\nLemma normr_sgz x : `|sgz x| = (x != 0).\n\n(*This lemma states that the absolute value of the sign of an element from a numeric domain, where both sign and absolute value are represented within the same domain, is the multiplicative identity if the element is non-zero, and zero otherwise.*)\nLemma normr_sg x : `|sgr x| = (x != 0)%:~R.\n\nEnd Sgz.\n\nSection MoreSgz.\n\nVariable R : numDomainType.\n\n(*This lemma states that the integer sign of an integer that has been converted into an element of a numeric domain is the same as the integer sign of the original integer.*)\nLemma sgz_int m : sgz (m%:~R : R) = sgz m.\n\n(*This lemma states that for any integer, its sign represented as an integer is equal to its integer sign.*)\nLemma sgrz (n : int) : sgr n = sgz n. \n\n(*This lemma states that converting the integer sign of an integer to an element of a numeric domain yields the same result as first converting the integer to an element of the domain and then taking its sign within that domain.*)\nLemma intr_sg m : (sgr m)%:~R = sgr (m%:~R) :> R.\n\n(*This lemma establishes the idempotence of the integer sign function, stating that applying the function twice to an element of a numeric domain is equivalent to applying it once.*)\nLemma sgz_id (x : R) : sgz (sgz x) = sgz x.\n\nEnd MoreSgz.\n\nSection SgzReal.\n\nVariable R : realDomainType.\nImplicit Types x y z : R.\nImplicit Types m n p : int.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma provides a complete characterization of the integer sign function for an element of a real domain, stating that its value is one if and only if the element is positive, negative one if and only if the element is negative, and zero if and only if the element is zero.*)\nLemma sgz_cp0 x :\n ((sgz x == 1) = (0 < x)) *\n ((sgz x == -1) = (x < 0)) *\n ((sgz x == 0) = (x == 0)).\n\n(*This inductive type provides a casing analysis for an element of a real domain based on its sign. It defines three constructors, one for a zero element, one for a positive element, and one for a negative element, each capturing the corresponding properties of the element, its sign, and its absolute value.*)\nVariant sgz_val x : bool -> bool -> bool -> bool -> bool -> bool\n -> bool -> bool -> bool -> bool -> bool -> bool\n -> bool -> bool -> bool -> bool -> bool -> bool\n -> R -> R -> int -> Set :=\n(*This lemma states that the sign of a signed integer is zero if and only if the integer itself is zero.*)\n | SgzNull of x = 0 : sgz_val x true true true true false false\n true false false true false false true false false true false false 0 0 0\n(*This lemma states that the sign of a signed integer is one if and only if the integer is strictly greater than zero.*)\n | SgzPos of x > 0 : sgz_val x false false true false false true\n false false true false false true false false true false false true x 1 1\n(*This lemma states that the sign of a signed integer is negative one if and only if the integer is strictly less than zero.*)\n | SgzNeg of x < 0 : sgz_val x false true false false true false\n false true false false true false false true false false true false (-x) (-1) (-1).\n\n(*This lemma proves that the case analysis defined by `sgz_val` is exhaustive for any element of a real domain, effectively providing a total view of the element's properties based on its sign.*)\nLemma sgzP x :\n sgz_val x (0 == x) (x <= 0) (0 <= x) (x == 0) (x < 0) (0 < x)\n (0 == sgr x) (-1 == sgr x) (1 == sgr x)\n (sgr x == 0) (sgr x == -1) (sgr x == 1)\n (0 == sgz x) (-1 == sgz x) (1 == sgz x)\n (sgz x == 0) (sgz x == -1) (sgz x == 1) `|x| (sgr x) (sgz x).\n\n(*This lemma states that the integer sign of the additive inverse of an element from a real domain is the additive inverse of the integer sign of the element.*)\nLemma sgzN x : sgz (- x) = - sgz x.\n\n(*This lemma states that the square of the integer sign of an element from a real domain is one if the element is non-zero, and zero if the element is zero.*)\nLemma mulz_sg x : sgz x * sgz x = (x != 0)%:~R.\n\n(*This lemma states that the product of the integer signs of two elements from a real domain is equal to one if and only if the first element is non-zero and the signs of the two elements are equal.*)\nLemma mulz_sg_eq1 x y : (sgz x * sgz y == 1) = (x != 0) && (sgz x == sgz y).\n\n(*This lemma states that the product of the integer signs of two elements from a real domain is equal to negative one if and only if the first element is non-zero and its sign is the additive inverse of the sign of the second element.*)\nLemma mulz_sg_eqN1 x y : (sgz x * sgz y == -1) = (x != 0) && (sgz x == - sgz y).\n\n(*This lemma states that the integer sign function is multiplicative, meaning the sign of the product of two elements from a real domain is equal to the product of their individual integer signs.*)\nLemma sgzM x y : sgz (x * y) = sgz x * sgz y.\n\n(*This lemma states that the sign of a real number raised to a natural number power is equal to the sign of that real number, itself raised to the same natural number power.*)\nLemma sgzX (n : nat) x : sgz (x ^+ n) = (sgz x) ^+ n.\n\n(*This lemma states that the sign of a real number is zero if and only if the real number is zero.*)\nLemma sgz_eq0 x : (sgz x == 0) = (x == 0).\n\n(*This lemma states that for a non-zero real number, its sign raised to a natural number power is equal to its sign raised to a power determined by the parity of that natural number, where an odd exponent is treated as one and an even exponent as zero.*)\nLemma sgz_odd (n : nat) x : x != 0 -> (sgz x) ^+ n = (sgz x) ^+ (odd n).\n\n(*This lemma states that the sign of a real number is greater than zero if and only if the real number itself is positive.*)\nLemma sgz_gt0 x : (sgz x > 0) = (x > 0).\n\n(*This lemma states that the sign of a real number is less than zero if and only if the real number itself is negative.*)\nLemma sgz_lt0 x : (sgz x < 0) = (x < 0).\n\n(*This lemma states that the sign of a real number is non-negative if and only if the real number itself is non-negative.*)\nLemma sgz_ge0 x : (sgz x >= 0) = (x >= 0).\n\n(*This lemma states that the sign of a real number is non-positive if and only if the real number itself is non-positive.*)\nLemma sgz_le0 x : (sgz x <= 0) = (x <= 0).\n\n(*This lemma states that the sign of the product of a real number and the sign of another real number is equal to the product of the signs of both real numbers.*)\nLemma sgz_smul x y : sgz (y *~ (sgz x)) = (sgz x) * (sgz y).\n\n(*This lemma states that the sign of the product of two integers is equal to the product of their signs.*)\nLemma sgrMz m x : sgr (x *~ m) = sgr x *~ sgr m.\n\nEnd SgzReal.\n\n(*This lemma states that the signs of two real numbers are equal if and only if both numbers being zero is equivalent and both numbers being positive is equivalent.*)\nLemma sgz_eq (R R' : realDomainType) (x : R) (y : R') :\n (sgz x == sgz y) = ((x == 0) == (y == 0)) && ((0 < x) == (0 < y)).\n\n(*This lemma states that embedding the integer value of negative one raised to a natural number power into a ring is equivalent to raising the ring's negative one to that same natural number power.*)\nLemma intr_sign (R : pzRingType) s : ((-1) ^+ s)%:~R = (-1) ^+ s :> R.\n\nSection Absz.\n\nImplicit Types m n p : int.\nOpen Scope nat_scope.\nLocal Coercion Posz : nat >-> int.\n\n(*This lemma states that the absolute value of an integer that comes from a natural number is equal to that natural number itself.*)\nLemma absz_nat (n : nat) : `|n| = n. \n\n(*This lemma states that the absolute value of an integer is equal to the integer value of the absolute value of that integer when viewed as a real number.*)\nLemma abszE (m : int) : `|m| = `|m|%R :> int. \n\n(*This lemma states that the absolute value of the integer zero is zero.*)\nLemma absz0 : `|0%R| = 0. \n\n(*This lemma states that the absolute value of the additive inverse of an integer is equal to the absolute value of the integer itself.*)\nLemma abszN m : `|- m| = `|m|. \n\n(*This lemma states that the absolute value of an integer is zero if and only if the integer itself is zero.*)\nLemma absz_eq0 m : (`|m| == 0) = (m == 0%R). \n\n(*This lemma states that the absolute value of an integer is positive if and only if the integer is non-zero.*)\nLemma absz_gt0 m : (`|m| > 0) = (m != 0%R). \n\n(*This lemma states that the absolute value of the integer one is one.*)\nLemma absz1 : `|1%R| = 1. \n\n(*This lemma states that the absolute value of the integer negative one is one.*)\nLemma abszN1 : `|-1%R| = 1. \n\n(*This lemma states that taking the absolute value of the absolute value of an integer yields the same result as taking the absolute value just once.*)\nLemma absz_id m : `|(`|m|)| = `|m|. \n\n(*This lemma states that the absolute value of the product of two integers is equal to the product of their absolute values.*)\nLemma abszM m1 m2 : `|(m1 * m2)%R| = `|m1| * `|m2|.\n\n(*This lemma states that the absolute value of an integer raised to a natural number power is equal to the absolute value of that integer, itself raised to the same natural number power.*)\nLemma abszX (n : nat) m : `|m ^+ n| = `|m| ^ n.\n\n(*This lemma states that the absolute value of the sign of an integer is one if the integer is non-zero, and zero otherwise.*)\nLemma absz_sg m : `|sgr m| = (m != 0%R). \n\n(*This lemma states that for any non-negative integer, its absolute value is equal to the integer itself.*)\nLemma gez0_abs m : (0 <= m)%R -> `|m| = m :> int.\n\n(*This lemma states that for any positive integer, its absolute value is equal to the integer itself.*)\nLemma gtz0_abs m : (0 < m)%R -> `|m| = m :> int.\n\n(*This lemma states that for any non-positive integer, its absolute value is equal to its additive inverse.*)\nLemma lez0_abs m : (m <= 0)%R -> `|m| = - m :> int.\n\n(*This lemma states that for any negative integer, its absolute value is equal to its additive inverse.*)\nLemma ltz0_abs m : (m < 0)%R -> `|m| = - m :> int.\n\n(*This lemma states that any integer is less than or equal to its absolute value.*)\nLemma lez_abs m : m <= `|m|%N :> int.\n\n(*This lemma states that the absolute value of negative one raised to any natural number power is one.*)\nLemma absz_sign s : `|(-1) ^+ s| = 1.\n\n(*This lemma states that the absolute value of an integer multiplied by negative one raised to a natural number power is equal to the absolute value of the original integer.*)\nLemma abszMsign s m : `|((-1) ^+ s * m)%R| = `|m|.\n\n(*This lemma states that an integer can be expressed as the product of its sign factor and its absolute value, where the sign factor is negative one if the integer is negative and one otherwise.*)\nLemma mulz_sign_abs m : ((-1) ^+ (m < 0)%R * `|m|%:Z)%R = m.\n\n(*This lemma states that the additive inverse of an integer is equal to the product of its absolute value and a sign factor, where the sign factor is negative one if the integer is positive and one otherwise.*)\nLemma mulz_Nsign_abs m : ((-1) ^+ (0 < m)%R * `|m|%:Z)%R = - m.\n\n(*This lemma states that an integer is equal to the product of its sign factor and its absolute value, where the sign factor is negative one if the integer is negative and one otherwise.*)\nLemma intEsign m : m = ((-1) ^+ (m < 0)%R * `|m|%:Z)%R.\n\n(*This lemma states that the absolute value of an integer is equal to the product of the integer and its sign factor, where the sign factor is negative one if the integer is negative and one otherwise.*)\nLemma abszEsign m : `|m|%:Z = ((-1) ^+ (m < 0)%R * m)%R.\n\n(*This lemma states that any integer is equal to the product of its sign function and its absolute value.*)\nLemma intEsg m : m = (sgz m * `|m|%:Z)%R.\n\n(*This lemma states that the absolute value of an integer is equal to the product of the integer and its sign function.*)\nLemma abszEsg m : (`|m|%:Z = sgz m * m)%R.\n\nEnd Absz.\n\nSection MoreAbsz.\nVariable R : numDomainType.\nImplicit Type i : int.\n\n(*This lemma states that for an element in a numerical domain, scaling it by the natural number absolute value of an integer is equivalent to scaling it by the integer corresponding to that absolute value.*)\nLemma mulr_absz (x : R) i : x *+ `|i| = x *~ `|i|.\n\n(*This lemma states that for any integer, coercing its natural number absolute value into a numerical domain yields the same result as first coercing the absolute value to an integer and then into the numerical domain.*)\nLemma natr_absz i : `|i|%:R = `|i|%:~R :> R.\n\nEnd MoreAbsz.\n\nModule Export IntDist.\n\n(*This definition locally equips the type of integers with the structure of a module over the natural numbers.*)\nLocal Definition int_nmodType : nmodType := int.\n(*This definition locally equips the type of integers with the structure of a module over the integers.*)\nLocal Definition int_zmodType : zmodType := int.\n(*This notation defines the subtraction of two natural numbers within the distance scope by first coercing them to integers and then performing integer subtraction, which is addition of the additive inverse.*)\nNotation \"m - n\" :=\n (@GRing.add int_nmodType (m%N : int)\n (@GRing.opp int_zmodType (n%N : int))) : distn_scope.\nArguments absz m%_distn_scope.\n(*This notation represents the absolute value of an integer, resulting in a natural number.*)\nNotation \"`| m |\" := (absz m) : nat_scope.\nCoercion Posz : nat >-> int.\n\nSection Distn.\n\nOpen Scope nat_scope.\nImplicit Type m : int.\nImplicit Types n d : nat.\n\n(*This lemma states that the distance between two integers, defined as the absolute value of their difference, is symmetric.*)\nLemma distnC m1 m2 : `|m1 - m2| = `|m2 - m1|.\n\n(*This lemma states that the distance between two natural numbers is invariant under left addition, meaning that adding the same natural number to both does not change their distance.*)\nLemma distnDl d n1 n2 : `|d + n1 - (d + n2)| = `|n1 - n2|.\n\n(*This lemma states that the distance between two natural numbers is invariant under right addition, meaning that adding the same natural number to both does not change their distance.*)\nLemma distnDr d n1 n2 : `|n1 + d - (n2 + d)| = `|n1 - n2|.\n\n(*This lemma states that if a first natural number is less than or equal to a second natural number, then their distance is equal to the difference of the second minus the first.*)\nLemma distnEr n1 n2 : n1 <= n2 -> `|n1 - n2| = n2 - n1.\n\n(*This lemma states that if a second natural number is less than or equal to a first natural number, then their distance is equal to the difference of the first minus the second.*)\nLemma distnEl n1 n2 : n2 <= n1 -> `|n1 - n2| = n1 - n2.\n\n(*This lemma states that the distance between any natural number and zero is the natural number itself.*)\nLemma distn0 n : `|n - 0| = n.\n\n(*This lemma states that the distance between zero and any natural number is the natural number itself.*)\nLemma dist0n n : `|0 - n| = n.\n\n(*This lemma states that the distance between any integer and itself is zero.*)\nLemma distnn m : `|m - m| = 0.\n\n(*This lemma states that the distance between two natural numbers is zero if and only if the two numbers are equal.*)\nLemma distn_eq0 n1 n2 : (`|n1 - n2| == 0) = (n1 == n2).\n\n(*This lemma states that the distance between a natural number and its successor is one.*)\nLemma distnS n : `|n - n.+1| = 1.\n\n(*This lemma states that the distance between the successor of a natural number and the number itself is one.*)\nLemma distSn n : `|n.+1 - n| = 1.\n\n(*This lemma states that the distance between two natural numbers is one if and only if they are consecutive.*)\nLemma distn_eq1 n1 n2 :\n (`|n1 - n2| == 1) = (if n1 < n2 then n1.+1 == n2 else n1 == n2.+1).\n\n(*This lemma states the triangle inequality for the distance between integers: the distance between a first and a third integer is less than or equal to the sum of the distance from the first to a second integer and the distance from the second to the third.*)\nLemma leqD_dist m1 m2 m3 : `|m1 - m3| <= `|m1 - m2| + `|m2 - m3|.\n\n(*This lemma refines the triangle inequality for integers, stating that the equality case, where the distance between two integers is the sum of their distances to a third intermediate integer, holds if and only if the intermediate integer lies between the other two in the standard ordering.*)\nLemma leqifD_distz m1 m2 m3 :\n `|m1 - m3| <= `|m1 - m2| + `|m2 - m3|\n ?= iff (m1 <= m2 <= m3)%R || (m3 <= m2 <= m1)%R.\n\n(*This lemma refines the triangle inequality for natural numbers, stating that the equality case, where the distance between two natural numbers is the sum of their distances to a third intermediate number, holds if and only if the intermediate number lies between the other two in the standard ordering.*)\nLemma leqifD_dist n1 n2 n3 :\n `|n1 - n3| <= `|n1 - n2| + `|n2 - n3|\n ?= iff (n1 <= n2 <= n3) || (n3 <= n2 <= n1).\n\n(*This lemma provides an identity relating the squared distance of two natural numbers to their squares and product: the square of their distance plus twice their product equals the sum of their squares.*)\nLemma sqrn_dist n1 n2 : `|n1 - n2| ^ 2 + 2 * (n1 * n2) = n1 ^ 2 + n2 ^ 2.\n\nEnd Distn.\n\nEnd IntDist.\n\nSection NormInt.\n\nVariable R : numDomainType.\n\n(*This lemma states that for an integer, the ring element obtained by coercing its natural number absolute value into a numerical domain is the same as the norm of the ring element obtained by coercing the integer itself.*)\nLemma intr_norm m : `|m|%:~R = `|m%:~R : R|.\n\n(*This lemma states a homogeneity property of the norm with respect to integer scaling, asserting that the norm of a numerical domain element scaled by an integer is equivalent to scaling the norm of the original element by the absolute value of that integer.*)\nLemma normrMz m (x : R) : `|x *~ m| = `|x| *~ `|m|.\n\n(*This lemma states that raising the ring element negative one to an integer power is equivalent to raising it to the power of the absolute value of that integer.*)\nLemma expN1r (i : int) : (-1 : R) ^ i = (-1) ^+ `|i|.\n\nEnd NormInt.\n\nSection PolyZintRing.\n\nVariable R : nzRingType.\nImplicit Types x y z: R.\nImplicit Types m n : int.\nImplicit Types i j k : nat.\nImplicit Types p q r : {poly R}.\n\n(*This lemma states that for a polynomial over a ring, the coefficient of a given degree in the polynomial scaled by an integer is equal to the corresponding coefficient of the original polynomial scaled by that same integer.*)\nLemma coefMrz p n i : (p *~ n)`_i = (p`_i *~ n).\n\n(*This lemma states that the function embedding a ring element into a constant polynomial is a morphism with respect to scalar multiplication by an integer. That is, creating a constant polynomial from a ring element that has been scaled by an integer is equivalent to scaling the constant polynomial of the original ring element by the same integer.*)\nLemma polyCMz n : {morph (@polyC R) : c / c *~ n}.\n\n(*This lemma states that evaluating a polynomial scaled by an integer at a given ring element yields the same result as evaluating the original polynomial at that element and then scaling the result by the same integer.*)\nLemma hornerMz n p x : (p *~ n).[x] = p.[x] *~ n.\n\n(*This lemma states that evaluating the constant polynomial corresponding to an integer at any ring element returns the ring element corresponding to that integer.*)\nLemma horner_int n x : (n%:~R : {poly R}).[x] = n%:~R.\n\n(*This lemma states that the formal derivative of a polynomial scaled by an integer is equivalent to the formal derivative of the original polynomial scaled by that same integer.*)\nLemma derivMz n p : (p *~ n)^`() = p^`() *~ n.\n\n(*This lemma states that scaling a polynomial by an integer is equivalent to multiplying that polynomial by the constant polynomial corresponding to the same integer.*)\nLemma mulpz p n : p *~ n = n%:~R *: p.\n\nEnd PolyZintRing.\n\nSection rpred.\n\n(*This lemma states that any subset of a Z-module that is closed under its additive group structure is also closed under scalar multiplication by any integer.*)\nLemma rpredMz (M : zmodType) (S : zmodClosed M) m :\n {in S, forall u, u *~ m \\in S}.\n\n(*This lemma states that any subring of a ring with a canonical integer map contains the image of any integer under that map.*)\nLemma rpred_int (R : pzRingType) (S : subringClosed R) m : m%:~R \\in S.\n\n(*This lemma states that for a left module over a ring, any subset that is closed under the Z-module structure is also closed under scalar multiplication by ring elements that are canonical images of integers.*)\nLemma rpredZint (R : pzRingType) (M : lmodType R) (S : zmodClosed M) m :\n {in S, forall u, m%:~R *: u \\in S}.\n\n(*This lemma states that any subset of a unit ring that is closed under division is also closed under exponentiation by any integer.*)\nLemma rpredXz (R : unitRingType) (S : divClosed R) m :\n {in S, forall x, x ^ m \\in S}.\n\n(*This lemma states that for a subset of a unit ring closed under division, an element belongs to the subset if and only if its inverse also belongs to the subset, by showing that membership is equivalent for an element and that element raised to a power of plus or minus one.*)\nLemma rpredXsign (R : unitRingType) (S : divClosed R) n x :\n (x ^ ((-1) ^+ n) \\in S) = (x \\in S).", - "algebra.countalg": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype bigop ssralg.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope ring_scope.\nImport GRing.Theory CodeSeq.\n\nModule CountRing.\n\nImport GRing.Theory.\n\n#[short(type=\"countNmodType\")]\n(*This structure defines a module over the semiring of natural numbers that is also a countable type. This means it is an additive commutative monoid equipped with a scalar multiplication by natural numbers, where all elements of the type can be enumerated.*)\nHB.structure Definition Nmodule := {M of GRing.Nmodule M & Countable M}.\n\n#[short(type=\"countZmodType\")]\n(*This structure defines a module over the ring of integers that is also a countable type. This means it is an additive abelian group whose elements can all be enumerated.*)\nHB.structure Definition Zmodule := {M of GRing.Zmodule M & Countable M}.\n\n#[short(type=\"countPzSemiRingType\")]\n(*This structure defines a semiring of characteristic zero that is also a countable type. This means it is an algebraic structure with addition and multiplication where repeatedly adding the multiplicative identity a positive number of times never results in the additive identity, and all of its elements can be enumerated.*)\nHB.structure Definition PzSemiRing := {R of GRing.PzSemiRing R & Countable R}.\n\n#[short(type=\"countNzSemiRingType\")]\n(*This structure defines a non-trivial semiring that is also a countable type. This means it is an algebraic structure with addition and multiplication where the additive identity is distinct from the multiplicative identity, and whose elements can all be enumerated.*)\nHB.structure Definition NzSemiRing := {R of GRing.NzSemiRing R & Countable R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.NzSemiRing instead.\")]\nNotation SemiRing R := (NzSemiRing R) (only parsing).\n\nModule SemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.NzSemiRing.sort instead.\")]\n(*This notation refers to the underlying type of elements for a countable, non-trivial semiring.*)\nNotation sort := (NzSemiRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.NzSemiRing.on instead.\")]\nNotation on R := (NzSemiRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.NzSemiRing.copy instead.\")]\nNotation copy T U := (NzSemiRing.copy T U) (only parsing).\nEnd SemiRing.\n\n#[short(type=\"countPzRingType\")]\n(*This structure defines a ring of characteristic zero that is also a countable type. This means it is an algebraic structure with addition, subtraction, and multiplication, where repeated addition of the multiplicative identity never yields the additive identity unless the number of additions is zero, and whose elements can all be enumerated.*)\nHB.structure Definition PzRing := {R of GRing.PzRing R & Countable R}.\n\n#[short(type=\"countNzRingType\")]\n(*This structure defines a non-trivial ring that is also a countable type. This means it is an algebraic structure with addition, subtraction, and multiplication where the additive identity is distinct from the multiplicative identity, and whose elements can all be enumerated.*)\nHB.structure Definition NzRing := {R of GRing.NzRing R & Countable R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.NzRing instead.\")]\nNotation Ring R := (NzRing R) (only parsing).\n\nModule Ring.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.NzRing.sort instead.\")]\n(*This notation provides a shorthand to access the underlying carrier type of a countable nontrivial commutative semiring structure.*)\nNotation sort := (NzRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.NzRing.on instead.\")]\nNotation on R := (NzRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.NzRing.copy instead.\")]\nNotation copy T U := (NzRing.copy T U) (only parsing).\nEnd Ring.\n\n#[short(type=\"countComPzSemiRingType\")]\n(*This structure defines a countable commutative semiring with a proper zero. This is a type equipped with commutative addition and multiplication, where the additive and multiplicative identities are distinct, and whose elements form a countable set.*)\nHB.structure Definition ComPzSemiRing :=\n {R of GRing.ComPzSemiRing R & Countable R}.\n\n#[short(type=\"countComNzSemiRingType\")]\n(*This structure defines a countable nontrivial commutative semiring. This is a type equipped with commutative addition and multiplication operations, where the additive and multiplicative identities are distinct, and whose elements form a countable set.*)\nHB.structure Definition ComNzSemiRing :=\n {R of GRing.ComNzSemiRing R & Countable R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.ComNzSemiRing instead.\")]\nNotation ComSemiRing R := (ComNzSemiRing R) (only parsing).\n\nModule ComSemiRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.ComNzSemiRing.sort instead.\")]\n(*A notation that refers to the underlying carrier type of a structure representing a countable, commutative, non-trivial ring.*)\nNotation sort := (ComNzSemiRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.ComNzSemiRing.on instead.\")]\nNotation on R := (ComNzSemiRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.ComNzSemiRing.copy instead.\")]\nNotation copy T U := (ComNzSemiRing.copy T U) (only parsing).\nEnd ComSemiRing.\n\n#[short(type=\"countComPzRingType\")]\n(*This definition specifies the algebraic structure for a type that is a commutative ring with a multiplicative identity, where this multiplicative identity may be equal to the additive identity, and whose underlying set of elements is countable.*)\nHB.structure Definition ComPzRing := {R of GRing.ComPzRing R & Countable R}.\n\n#[short(type=\"countComNzRingType\")]\n(*This definition specifies the algebraic structure for a type that is a commutative ring whose multiplicative identity is distinct from its additive identity, and whose underlying set of elements is countable.*)\nHB.structure Definition ComNzRing := {R of GRing.ComNzRing R & Countable R}.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.ComNzRing instead.\")]\nNotation ComRing R := (ComNzRing R) (only parsing).\n\nModule ComRing.\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.ComNzRing.sort instead.\")]\n(*This definition creates a sorted sequence of all elements of a finite ordered type that satisfy a given boolean predicate. The sequence is ordered according to the canonical order of the type.*)\nNotation sort := (ComNzRing.sort) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.ComNzRing.on instead.\")]\nNotation on R := (ComNzRing.on R) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use CountRing.ComNzRing.copy instead.\")]\nNotation copy T U := (ComNzRing.copy T U) (only parsing).\nEnd ComRing.\n\n#[short(type=\"countUnitRingType\")]\n(*This structure defines a countable unit ring, which is a ring equipped with a multiplicative identity element, built upon a type that is also countable.*)\nHB.structure Definition UnitRing := {R of GRing.UnitRing R & Countable R}.\n\n#[short(type=\"countComUnitRingType\")]\n(*This structure defines a countable commutative unit ring, which is a commutative ring equipped with a multiplicative identity element, built upon a type that is also countable.*)\nHB.structure Definition ComUnitRing := {R of GRing.ComUnitRing R & Countable R}.\n\n#[short(type=\"countIdomainType\")]\n(*This structure defines a countable integral domain, which is a non-trivial commutative ring with a multiplicative identity and no zero-divisors, where the underlying type is countable.*)\nHB.structure Definition IntegralDomain :=\n {R of GRing.IntegralDomain R & Countable R}.\n\n#[short(type=\"countFieldType\")]\n(*This structure defines a countable field, which is a commutative ring where every non-zero element has a multiplicative inverse, and where the underlying type is countable.*)\nHB.structure Definition Field := {R of GRing.Field R & Countable R}.\n\n#[short(type=\"countDecFieldType\")]\n(*This structure defines a countable decidable field, which is a countable field equipped with a boolean-valued equality test.*)\nHB.structure Definition DecidableField :=\n {R of GRing.DecidableField R & Countable R}.\n\n#[short(type=\"countClosedFieldType\")]\n(*This structure defines a countable algebraically closed field, which is a countable field where every non-constant single-variable polynomial with coefficients from the field has at least one root within that same field.*)\nHB.structure Definition ClosedField := {R of GRing.ClosedField R & Countable R}.\n\nModule ReguralExports.\nHB.instance Definition _ (R : countType) := Countable.on R^o.\nHB.instance Definition _ (R : countNmodType) := Nmodule.on R^o.\nHB.instance Definition _ (R : countZmodType) := Zmodule.on R^o.\nHB.instance Definition _ (R : countPzSemiRingType) := PzSemiRing.on R^o.\nHB.instance Definition _ (R : countNzSemiRingType) := NzSemiRing.on R^o.\nHB.instance Definition _ (R : countPzRingType) := PzRing.on R^o.\nHB.instance Definition _ (R : countNzRingType) := NzRing.on R^o.\nHB.instance Definition _ (R : countComPzSemiRingType) := ComPzSemiRing.on R^o.\nHB.instance Definition _ (R : countComNzSemiRingType) := ComNzSemiRing.on R^o.\nHB.instance Definition _ (R : countComPzRingType) := ComPzRing.on R^o.\nHB.instance Definition _ (R : countComNzRingType) := ComNzRing.on R^o.\nHB.instance Definition _ (R : countUnitRingType) := UnitRing.on R^o.\nHB.instance Definition _ (R : countComUnitRingType) := ComUnitRing.on R^o.\nHB.instance Definition _ (R : countIdomainType) := IntegralDomain.on R^o.\nHB.instance Definition _ (R : countFieldType) := Field.on R^o.\nHB.instance Definition _ (R : countDecFieldType) := DecidableField.on R^o.\n(*This is a deprecated notation which serves as an alias for the type of a countable semi-ring structure that includes a multiplicative identity distinct from the additive identity.*)\nNotation countSemiRingType := (countNzSemiRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use countNzRingType instead.\")]\n(*This is a deprecated notation which serves as an alias for the type of a countable ring structure that includes a multiplicative identity distinct from the additive identity.*)\nNotation countRingType := (countNzRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use countComNzSemiRingType instead.\")]\n(*This is a deprecated notation which serves as an alias for the type of a countable commutative semi-ring structure that includes a multiplicative identity distinct from the additive identity.*)\nNotation countComSemiRingType := (countComNzSemiRingType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use countComNzRingType instead.\")]\n(*This is a deprecated notation which serves as an alias for the type of a countable commutative ring structure that includes a multiplicative identity distinct from the additive identity.*)", - "algebra.qpoly": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype tuple bigop binomial finset finfun ssralg.\nFrom mathcomp Require Import countalg finalg poly polydiv perm fingroup matrix.\nFrom mathcomp Require Import mxalgebra mxpoly vector countalg.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GRing.Theory.\nImport Pdiv.CommonRing.\nImport Pdiv.RingMonic.\nImport Pdiv.Field.\nImport FinRing.Theory.\nLocal Open Scope ring_scope.\n\nReserved Notation \"'{poly_' n R }\" (n at level 2, format \"'{poly_' n R }\").\nReserved Notation \"''nX^' i\" (at level 3, i at level 2, format \"''nX^' i\").\nReserved Notation \"x .-lagrange\" (format \"x .-lagrange\").\nReserved Notation \"x .-lagrange_\" (format \"x .-lagrange_\").\nReserved Notation \"'qX\".\nReserved Notation \"{ 'poly' '%/' p }\"\n (p at level 2, format \"{ 'poly' '%/' p }\").\n\nSection poly_of_size_zmod.\nContext {R : nzRingType}.\nImplicit Types (n : nat).\n\nSection poly_of_size.\nVariable (n : nat).\n\n(*This definition defines a predicate that checks if the size of a given polynomial over a ring is less than or equal to a specified natural number.*)\nDefinition poly_of_size_pred := fun p : {poly R} => size p <= n.\nArguments poly_of_size_pred _ /.\n(*This definition introduces the type of polynomials over a ring whose size is less than or equal to a given natural number.*)\nDefinition poly_of_size := [qualify a p | poly_of_size_pred p].\n\n(*This lemma states that the set of polynomials with a size less than or equal to a given natural number forms a submodule, meaning it contains the zero polynomial and is closed under addition and scalar multiplication.*)\nLemma npoly_submod_closed : submod_closed poly_of_size.\n\n(*This record defines the type for polynomials of bounded size. An element of this type consists of a polynomial over a ring and a proof that its size is less than or equal to a given natural number.*)\nRecord npoly : predArgType := NPoly {\n polyn :> {poly R};\n _ : polyn \\is a poly_of_size n\n}.\n\nHB.instance Definition _ := [isSub for @polyn].\n\n(*This lemma states that the underlying polynomial of an element of the bounded-size polynomial type has a size that is less than or equal to the specified bound.*)\nLemma npoly_is_a_poly_of_size (p : npoly) : val p \\is a poly_of_size n.\n\nHint Resolve npoly_is_a_poly_of_size : core.\n\n(*This lemma states that the size of any polynomial of bounded size is less than or equal to the specified natural number bound.*)\nLemma size_npoly (p : npoly) : size p <= n.\n\nHint Resolve size_npoly : core.\n\nHB.instance Definition _ := [Choice of npoly by <:].\nHB.instance Definition _ := [SubChoice_isSubLmodule of npoly by <:].\n\n(*This definition provides a function to convert a polynomial of bounded size into a row vector of the same length, where the vector's entries are the polynomial's coefficients.*)\nDefinition npoly_rV : npoly -> 'rV[R]_n := poly_rV \\o val.\n(*This definition provides a function to convert a row vector of a given length into a polynomial of a correspondingly bounded size, where the polynomial's coefficients are taken from the vector's entries.*)\nDefinition rVnpoly : 'rV[R]_n -> npoly :=\n insubd (0 : npoly) \\o rVpoly.\nArguments rVnpoly /.\nArguments npoly_rV /.\n\n(*This lemma states that converting a row vector to a polynomial of bounded size and then converting it back to a row vector results in the original row vector.*)\nLemma npoly_rV_K : cancel npoly_rV rVnpoly.\n\n(*This lemma states that converting a polynomial of bounded size to a row vector and then converting it back to a polynomial of bounded size results in the original polynomial.*)\nLemma rVnpolyK : cancel rVnpoly npoly_rV.\n\nHint Resolve npoly_rV_K rVnpolyK : core.\n\n(*This lemma states that the type of polynomials with a size bounded by a natural number satisfies the axioms of a vector space of that same dimension.*)\nLemma npoly_vect_axiom : Vector.axiom n npoly.\n\n(*A notation for the type of polynomials over a given ring with a size less than or equal to a specified natural number.*)\nNotation \"'{poly_' n R }\" := (@npoly R n) : type_scope.\n\n#[global]\nHint Resolve size_npoly npoly_is_a_poly_of_size : core.\n\nArguments poly_of_size_pred _ _ _ /.\nArguments npoly : clear implicits.\n\nHB.instance Definition _ (R : countNzRingType) n :=\n [Countable of {poly_n R} by <:].\n\n(*This lemma states that the function embedding a polynomial of bounded size into the general type of polynomials is a linear map.*)\nLemma polyn_is_linear : linear (@polyn _ _ : {poly_n R} -> _).\n\n(*This fact asserts that the size of the zero polynomial is less than or equal to any given natural number bound.*)\nFact size_npoly0 : size (0 : {poly R}) <= n.\n\n(*This definition provides the zero element within the type of polynomials of a given bounded size.*)\nDefinition npoly0 := NPoly (size_npoly0).\n\n(*A key used to lock the implementation of the polynomial projection function, controlling its programmatic expansion.*)\nFact npolyp_key : unit. \n(*This definition defines a function that projects a general polynomial onto the type of polynomials with a bounded size by truncating its higher-degree coefficients.*)\nDefinition npolyp : {poly R} -> {poly_n R} :=\n locked_with npolyp_key (mk_npoly \\o (nth 0)).\n\n(*This definition provides a function to construct a polynomial of bounded size from a given finite sequence of coefficients.*)\nDefinition npoly_of_seq := npolyp \\o Poly.\n\n(*This lemma states that two polynomials of bounded size are equal if and only if their corresponding sequences of coefficients are equal.*)\nLemma npolyP (p q : {poly_n R}) : nth 0 p =1 nth 0 q <-> p = q.\n\n(*This lemma states that the coefficient at a given index of a projected bounded-size polynomial is equal to the original polynomial's coefficient if the index is within the bound, and zero otherwise.*)\nLemma coef_npolyp (p : {poly R}) i : (npolyp p)`_i = if i < n then p`_i else 0.\n\n(*This lemma states that for a polynomial with a size bounded by a given natural number, any coefficient at an index greater than or equal to that bound is zero.*)\nLemma big_coef_npoly (p : {poly_n R}) i : n <= i -> p`_i = 0.\n\n(*This lemma states that if a general polynomial already has a size within the specified bound, projecting it to the bounded-size polynomial type and then viewing it again as a general polynomial yields the original polynomial.*)\nLemma npolypK (p : {poly R}) : size p <= n -> npolyp p = p :> {poly R}.\n\n(*This lemma states that the coefficient at a given index of a sum of bounded-size polynomials is equal to the sum of the coefficients at that same index from each polynomial in the sum.*)\nLemma coefn_sum (I : Type) (r : seq I) (P : pred I)\n (F : I -> {poly_n R}) (k : nat) :\n (\\sum_(i <- r | P i) F i)`_k = \\sum_(i <- r | P i) (F i)`_k.\n\nEnd npoly_theory.\nArguments mk_npoly {R} n E.\nArguments npolyp {R} n p.\n\nSection fin_npoly.\n\nVariable R : finNzRingType.\nVariable n : nat.\nImplicit Types p q : {poly_n R}.\n\n(*This definition provides a finite sequence containing all possible polynomials of a given bounded size over a finite ring.*)\nDefinition npoly_enum : seq {poly_n R} :=\n if n isn't n.+1 then [:: npoly0 _] else\n pmap insub [seq \\poly_(i < n.+1) c (inord i) | c : (R ^ n.+1)%type].\n\n(*This lemma states that the finite sequence enumerating all polynomials of a given bounded size contains no duplicate elements.*)\nLemma npoly_enum_uniq : uniq npoly_enum.\n\n(*This lemma states that any polynomial of a given bounded size over a finite ring is a member of the canonical enumeration of all such polynomials.*)\nLemma mem_npoly_enum p : p \\in npoly_enum.\n\n(*This lemma states that the number of distinct polynomials of size bounded by a natural number over a finite ring is equal to the cardinality of the ring raised to the power of that natural number.*)\nLemma card_npoly : #|{poly_n R}| = (#|R| ^ n)%N.\n\nEnd fin_npoly.\n\nSection Irreducible.\n\nVariable R : finIdomainType.\nVariable p : {poly R}.\n\n(*This definition provides a boolean-valued test to determine if a given polynomial over a finite integral domain is irreducible. A polynomial is considered irreducible if it is non-constant and cannot be factored into a product of two non-constant polynomials.*)\nDefinition irreducibleb :=\n ((1 < size p) &&\n [forall q : {poly_((size p).-1) R},\n (Pdiv.Ring.rdvdp q p)%R ==> (size q <= 1)])%N.\n\n(*This lemma establishes that the boolean test for polynomial irreducibility correctly reflects the logical proposition of a polynomial being irreducible.*)\nLemma irreducibleP : reflect (irreducible_poly p) irreducibleb.\n\nEnd Irreducible.\n\nSection Vspace.\n\nVariable (K : fieldType) (n : nat).\n\n(*This lemma states that the dimension of the vector space formed by polynomials over a field with a size bounded by a natural number is equal to that natural number.*)\nLemma dim_polyn : \\dim (fullv : {vspace {poly_n K}}) = n.\n\n(*This definition establishes the canonical basis for polynomials of degree less than a given natural number. It is a finite sequence where the element at each index corresponds to the monomial with the indeterminate raised to the power of that index.*)\nDefinition npolyX : n.-tuple {poly_n K} := [tuple npolyp n 'X^i | i < n].\n(*This notation represents the i-th monomial in the canonical basis for polynomials of degree less than a given natural number, corresponding to the indeterminate raised to the power of the index.*)\nNotation \"''nX^' i\" := (tnth npolyX i).\n\n(*This lemma states that the polynomial obtained by selecting the i-th element of the canonical monomial basis for polynomials of degree less than a given natural number is equal to the monomial with the indeterminate raised to the power of that index.*)\nLemma npolyXE (i : 'I_n) : 'nX^i = 'X^i :> {poly _}.\n\n(*This lemma states that accessing the i-th coefficient of the canonical monomial basis tuple yields the i-th monomial of that basis.*)\nLemma nth_npolyX (i : 'I_n) : npolyX`_i = 'nX^i.\n\n(*This lemma states that the canonical monomial basis for polynomials of degree less than a given natural number forms a linearly independent set.*)\nLemma npolyX_free : free npolyX.\n\n(*This lemma states that the canonical monomial basis for polynomials of degree less than a given natural number constitutes a basis for the entire vector space of such polynomials.*)\nLemma npolyX_full : basis_of fullv npolyX.\n\n(*This lemma states that the i-th coordinate of a polynomial, with respect to the canonical monomial basis, is equal to the i-th coefficient of that polynomial.*)\nLemma npolyX_coords (p : {poly_n K}) i : coord npolyX i p = p`_i.\n\n(*This lemma states that any polynomial whose degree is less than a given natural number can be expressed as a linear combination of the canonical monomial basis vectors, where the scalar for each basis vector is the corresponding coefficient of the polynomial.*)\nLemma npolyX_gen (p : {poly K}) : (size p <= n)%N ->\n p = \\sum_(i < n) p`_i *: 'nX^i.\n\nSection lagrange.\n\nVariables (x : nat -> K).\n\n(*This notation defines the i-th Lagrange basis polynomial for a given set of distinct evaluation points. This polynomial is constructed to evaluate to one at the i-th point and to zero at all other specified points.*)\nNotation lagrange_def := (fun i :'I_n =>\n let k := i in let p := \\prod_(j < n | j != k) ('X - (x j)%:P)\n in (p.[x k]^-1)%:P * p).\n\n(*A fact used as a key to create an opaque definition for the Lagrange basis, ensuring that its definition is not unfolded during computations.*)\nFact lagrange_key : unit. \n\n(*This definition establishes the Lagrange basis as a finite sequence of Lagrange polynomials, each corresponding to a distinct evaluation point. The definition is opaque, preventing its internal structure from being unfolded.*)\nDefinition lagrange := locked_with lagrange_key\n [tuple npolyp n (lagrange_def i) | i < n].\n(*This notation provides access to the i-th polynomial within the Lagrange basis sequence.*)\nNotation lagrange_ := (tnth lagrange).\n\nHypothesis n_gt0 : (0 < n)%N.\nHypothesis x_inj : injective x.\n\n(*This local lemma states that the i-th Lagrange basis polynomial, when evaluated at the j-th specified point, yields one if the indices i and j are the same, and zero otherwise.*)\nLet lagrange_def_sample (i j : 'I_n) : (lagrange_def i).[x j] = (i == j)%:R.\n\n(*This local lemma states that the size of any individual Lagrange basis polynomial, which corresponds to its degree plus one, is equal to the total number of evaluation points.*)\nLet size_lagrange_def i : size (lagrange_def i) = n.\n\n(*This lemma provides the explicit definition of the i-th Lagrange basis polynomial, equating the opaque term with its underlying constructive formula.*)\nLemma lagrangeE i : lagrange_ i = lagrange_def i :> {poly _}.\n\n(*This lemma states that accessing the i-th coefficient of the Lagrange basis tuple yields the i-th Lagrange polynomial of that basis.*)\nLemma nth_lagrange (i : 'I_n) : lagrange`_i = lagrange_ i.\n\n(*This lemma states that the size of the i-th Lagrange basis polynomial is equal to the total number of evaluation points.*)\nLemma size_lagrange_ i : size (lagrange_ i) = n.\n\n(*This lemma states that the length of the finite sequence representing the Lagrange basis is equal to the number of evaluation points.*)\nLemma size_lagrange : size lagrange = n.\n\n(*This lemma states the fundamental property of the Lagrange basis: the i-th basis polynomial, when evaluated at the j-th specified point, yields one if the indices i and j are identical, and zero otherwise.*)\nLemma lagrange_sample (i j : 'I_n) : (lagrange_ i).[x j] = (i == j)%:R.\n\n(*This lemma states that the Lagrange basis forms a linearly independent set of polynomials.*)\nLemma lagrange_free : free lagrange.\n\n(*This lemma states that the Lagrange basis constitutes a basis for the entire vector space of polynomials whose degree is less than the number of evaluation points.*)\nLemma lagrange_full : basis_of fullv lagrange.\n\n(*This lemma states that the i-th coordinate of a polynomial with respect to the Lagrange basis is equal to the value of that polynomial when evaluated at the i-th specified point.*)\nLemma lagrange_coords (p : {poly_n K}) i : coord lagrange i p = p.[x i].\n\n(*This lemma provides the Lagrange interpolation formula, stating that any polynomial with a degree less than the number of evaluation points can be expressed as a linear combination of the Lagrange basis polynomials, where the scalar for each basis polynomial is the value of the original polynomial at the corresponding point.*)\nLemma lagrange_gen (p : {poly K}) : (size p <= n)%N ->\n p = \\sum_(i < n) p.[x i]%:P * lagrange_ i.\n\nEnd lagrange.\n\nEnd Vspace.\n\n(*This notation likely represents a monomial, which is a polynomial consisting of a single term. This term is formed by a coefficient, represented by the first placeholder, multiplied by an indeterminate raised to a power, specified by the second placeholder. The double apostrophe prefix suggests that the expression is coerced to a standard polynomial type.*)\nNotation \"''nX^' i\" := (tnth (npolyX _) i) : ring_scope.\n(*This notation represents the Lagrange polynomial constructed from a given finite sequence of ring elements. This polynomial is defined such that its values at a specific set of evaluation points, typically roots of unity, correspond to the elements of the input sequence.*)\nNotation \"x .-lagrange\" := (lagrange x) : ring_scope.\n(*This notation represents a function that maps a natural number to the corresponding coefficient of the Lagrange polynomial generated from a given finite sequence of ring elements.*)\nNotation \"x .-lagrange_\" := (tnth x.-lagrange) : ring_scope.\n\nSection Qpoly.\n\nVariable R : nzRingType.\nVariable h : {poly R}.\n\n(*This definition produces a suitable monic polynomial to be used as a modulus. Given an input polynomial, it returns the input itself if it is monic and has a degree of at least one. Otherwise, it defaults to returning the simple indeterminate polynomial.*)\nDefinition mk_monic := \n if (1 < size h)%N && (h \\is monic) then h else 'X.\n\n(*This definition establishes the type for quotient polynomials modulo a given polynomial. An element of this type is a polynomial whose degree is strictly less than the degree of the modulus polynomial, serving as the canonical representative in the quotient ring.*)\nDefinition qpoly := {poly_(size mk_monic).-1 R}.\nEnd Qpoly.\n\n(*This notation represents the type of quotient polynomials. It signifies the set of all polynomials considered equivalent modulo a specific polynomial, which acts as the modulus.*)\nNotation \"{ 'poly' '%/' p }\" := (qpoly p) : type_scope.\n \nSection QpolyProp.\n\nVariable R : nzRingType.\nVariable h : {poly R}.\n\n(*This lemma states that the polynomial generated by the `mk_monic` function, which is used as a modulus, is always a monic polynomial, meaning its leading coefficient is one.*)\nLemma monic_mk_monic : (mk_monic h) \\is monic.\n\n \n\n(*This lemma states that the size of the modulus polynomial produced by `mk_monic` is always strictly greater than one, which implies that the degree of the modulus is at least one.*)\nLemma size_mk_monic_gt1 : (1 < size (mk_monic h))%N.\n\n(*This lemma states that the size of the modulus polynomial produced by `mk_monic` is always strictly greater than zero, which ensures that it is not the zero polynomial.*)\nLemma size_mk_monic_gt0 : (0 < size (mk_monic h))%N.\n\n(*This lemma states that the modulus polynomial produced by the `mk_monic` function is never equal to the zero polynomial.*)\nLemma mk_monic_neq0 : mk_monic h != 0.\n\n(*This lemma states that the size of any polynomial belonging to a quotient polynomial type is strictly less than the size of the corresponding modulus polynomial.*)\nLemma size_mk_monic (p : {poly %/ h}) : size p < size (mk_monic h).\n\n(*This lemma states that taking the remainder of any polynomial upon division by the modulus polynomial results in a polynomial whose size is within the bounds required for it to be an element of the corresponding quotient polynomial type.*)\nLemma poly_of_size_mod p :\n rmodp p (mk_monic h) \\is a poly_of_size (size (mk_monic h)).-1.\n\n(*This definition specifies a function that converts an arbitrary polynomial into its canonical representative in the quotient polynomial ring. This is achieved by computing the remainder of the input polynomial upon division by the modulus polynomial.*)\nDefinition in_qpoly p : {poly %/ h} := NPoly (poly_of_size_mod p).\n\n(*This lemma states that if an input polynomial already has a degree smaller than the modulus polynomial, converting it to the quotient polynomial type results in the same polynomial, as it is already in its canonical form.*)\nLemma in_qpoly_small (p : {poly R}) :\n size p < size (mk_monic h) -> in_qpoly p = p :> {poly R}.\n\n(*This lemma states that mapping the zero polynomial into a quotient polynomial type results in the zero element of that type.*)\nLemma in_qpoly0 : in_qpoly 0 = 0.\n\n(*This lemma states that the function for converting polynomials to the quotient ring preserves addition. Applying the conversion to a sum of two polynomials yields the same result as converting each polynomial individually and then performing the addition within the quotient ring.*)\nLemma in_qpolyD p q : in_qpoly (p + q) = in_qpoly p + in_qpoly q.\n\n(*This lemma states that the function for converting polynomials to the quotient ring preserves scalar multiplication. Applying the conversion to a polynomial scaled by a ring element yields the same result as converting the polynomial first and then scaling it within the quotient ring.*)\nLemma in_qpolyZ a p : in_qpoly (a *: p) = a *: in_qpoly p.\n\n(*This fact asserts that the function converting polynomials to the quotient ring is a linear map, meaning it preserves both addition and scalar multiplication.*)\nFact in_qpoly_is_linear : linear in_qpoly.\n\n(*This lemma serves as a proof that any constant polynomial has a size that is small enough to be considered a member of the quotient polynomial type, as the modulus polynomial is guaranteed to have a degree of at least one.*)\nLemma qpolyC_proof k :\n (k%:P : {poly R}) \\is a poly_of_size (size (mk_monic h)).-1.\n\n(*This definition describes a function that embeds an element from the base ring into the quotient polynomial ring by treating it as a constant polynomial.*)\nDefinition qpolyC k : {poly %/ h} := NPoly (qpolyC_proof k).\n\n(*This lemma states that embedding a ring element into the quotient polynomial ring as a constant polynomial and then viewing it as a general polynomial is equivalent to creating the constant polynomial directly.*)\nLemma qpolyCE k : qpolyC k = k%:P :> {poly R}.\n\n(*This lemma states that embedding the zero element of the base ring into the quotient polynomial ring results in the zero element of the quotient ring.*)\nLemma qpolyC0 : qpolyC 0 = 0.\n\n(*This definition establishes the multiplicative identity element in the quotient polynomial ring, which corresponds to the constant polynomial with value one.*)\nDefinition qpoly1 := qpolyC 1.\n\n(*This definition specifies multiplication in the quotient polynomial ring. The operation involves multiplying two quotient polynomials as if they were ordinary polynomials and then taking the remainder of the product with respect to the modulus polynomial.*)\nDefinition qpoly_mul (q1 q2 : {poly %/ h}) : {poly %/ h} :=\n in_qpoly ((q1 : {poly R}) * q2).\n\n(*This lemma states that the constant polynomial one acts as a left identity for multiplication within the quotient polynomial ring.*)\nLemma qpoly_mul1z : left_id qpoly1 qpoly_mul.\n\n(*This lemma states that the constant polynomial one acts as a right identity for multiplication within the quotient polynomial ring.*)\nLemma qpoly_mulz1 : right_id qpoly1 qpoly_mul.\n\n(*This lemma states that the multiplicative identity of the quotient polynomial ring, which is the constant polynomial one, is distinct from the additive identity, the zero polynomial.*)\nLemma qpoly_nontrivial : qpoly1 != 0.\n\n(*This definition establishes the canonical representative of the indeterminate variable within the quotient polynomial ring.*)\nDefinition qpolyX := in_qpoly 'X.\n(*This notation represents the canonical representative of a polynomial's indeterminate variable within a quotient polynomial ring.*)\nNotation \"'qX\" := qpolyX.\n\n(*This lemma states that if the modulus polynomial is both monic and has a degree of at least two, then the indeterminate of the quotient polynomial ring is identical to the standard polynomial indeterminate.*)\nLemma qpolyXE : 2 < size h -> h \\is monic -> 'qX = 'X :> {poly R}.\n\nEnd QpolyProp.\n\n(*A notation for the indeterminate 'X' in a quotient polynomial ring.*)\nNotation \"'qX\" := (qpolyX _) : ring_scope.\n\n(*This lemma states that applying the operation to make a polynomial monic to the indeterminate polynomial 'X' leaves it unchanged, as 'X' is already monic.*)\nLemma mk_monic_X (R : nzRingType) : mk_monic 'X = 'X :> {poly R}.\n\n(*This lemma states that applying the operation to make a polynomial monic to 'X' raised to a positive natural number power leaves it unchanged, as such polynomials are inherently monic.*)\nLemma mk_monic_Xn (R : nzRingType) n : mk_monic 'X^n = 'X^n.-1.+1 :> {poly R}.\n\n(*This lemma states that the cardinality of a quotient polynomial ring modulo a polynomial over a finite non-zero ring is equal to the cardinality of the base ring raised to the power of the degree of the monic polynomial associated with the modulus.*)\nLemma card_qpoly (R : finNzRingType) (h : {poly R}):\n #|{poly %/ h}| = #|R| ^ (size (mk_monic h)).-1.\n\n(*This lemma provides the cardinality of a quotient polynomial ring when the modulus is a monic polynomial of degree at least one. It states that the cardinality is the size of the base finite ring raised to the power of the degree of the monic modulus polynomial.*)\nLemma card_monic_qpoly (R : finNzRingType) (h : {poly R}):\n 1 < size h -> h \\is monic -> #|{poly %/ h}| = #|R| ^ (size h).-1.\n\nSection QRing.\n\nVariable A : comNzRingType.\nVariable h : {poly A}.\n\n(*This lemma states that multiplication in a quotient polynomial ring is a commutative operation, given that the base ring is commutative.*)\nLemma qpoly_mulC : commutative (@qpoly_mul A h).\n\n(*This lemma states that multiplication in a quotient polynomial ring is an associative operation.*)\nLemma qpoly_mulA : associative (@qpoly_mul A h).\n\n(*This lemma states that multiplication in a quotient polynomial ring is right-distributive over addition.*)\nLemma qpoly_mul_addr : right_distributive (@qpoly_mul A h) +%R.\n\n(*This lemma states that multiplication in a quotient polynomial ring is left-distributive over addition.*)\nLemma qpoly_mul_addl : left_distributive (@qpoly_mul A h) +%R.\n\nHB.instance Definition _ := GRing.Zmodule_isComNzRing.Build {poly__ A} qpoly_mulA\n qpoly_mulC (@qpoly_mul1z _ h) qpoly_mul_addl (@qpoly_nontrivial _ h).\nHB.instance Definition _ := GRing.ComNzRing.on {poly %/ h}.\n\n(*This lemma states that the canonical projection from a polynomial ring to its quotient ring maps the multiplicative identity of the polynomial ring to the multiplicative identity of the quotient ring.*)\nLemma in_qpoly1 : in_qpoly h 1 = 1.\n\n(*This lemma states that the canonical projection from a polynomial ring to its quotient ring preserves multiplication, meaning the projection of a product of two polynomials is equal to the product of their individual projections.*)\nLemma in_qpolyM q1 q2 : in_qpoly h (q1 * q2) = in_qpoly h q1 * in_qpoly h q2.\n\n(*This fact asserts that the canonical projection from a polynomial ring to its quotient ring is a monoid morphism, meaning it preserves the multiplicative identity and the multiplication operation.*)\nFact in_qpoly_monoid_morphism : monoid_morphism (in_qpoly h).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `in_qpoly_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, provides a legacy way to state that the canonical projection from a polynomial ring to its quotient ring is a multiplicative morphism.*)\nDefinition in_qpoly_is_multiplicative :=\n (fun g => (g.2,g.1)) in_qpoly_monoid_morphism.\nHB.instance Definition _ :=\n GRing.isMonoidMorphism.Build {poly A} {poly %/ h} (in_qpoly h)\n in_qpoly_monoid_morphism.\n\n(*This lemma states that the canonical representative in a polynomial ring of a sum of elements from a quotient ring is equal to the sum of the canonical representatives of those individual elements.*)\nLemma poly_of_qpoly_sum I (r : seq I) (P1 : pred I) (F : I -> {poly %/ h}) :\n ((\\sum_(i <- r | P1 i) F i) =\n \\sum_(p <- r | P1 p) ((F p) : {poly A}) :> {poly A})%R.\n\n(*This lemma states that the canonical polynomial representative of the sum of two quotient polynomials is equal to the sum of their individual canonical polynomial representatives.*)\nLemma poly_of_qpolyD (p q : {poly %/ h}) :\n p + q= (p : {poly A}) + q :> {poly A}.\n\n(*This lemma states that the canonical polynomial representation of a natural number injected into a quotient polynomial ring is the same as the constant polynomial corresponding to that natural number.*)\nLemma qpolyC_natr p : (p%:R : {poly %/ h}) = p%:R :> {poly A}.\n\n(*This lemma states that the characteristic of a quotient polynomial ring is equal to the characteristic of its base ring.*)\nLemma pchar_qpoly : [pchar {poly %/ h}] =i [pchar A].\n\n(*This lemma states that the canonical polynomial representative of the product of two quotient polynomials is obtained by computing the product of their canonical polynomial representatives and then taking the remainder of this result modulo the monic generator of the quotient.*)\nLemma poly_of_qpolyM (p q : {poly %/ h}) :\n p * q = rmodp ((p : {poly A}) * q) (mk_monic h) :> {poly A}.\n\n(*This lemma states that the canonical polynomial representative of a quotient polynomial raised to a natural number power is obtained by raising its canonical polynomial representative to the same power and then taking the remainder of this result modulo the monic generator of the quotient.*)\nLemma poly_of_qpolyX (p : {poly %/ h}) n :\n p ^+ n = rmodp ((p : {poly A}) ^+ n) (mk_monic h) :> {poly A}.\n\n(*This lemma states that the canonical embedding of a constant from a base ring into its quotient polynomial ring preserves additive inverses; the image of the opposite of an element is the opposite of the image of that element.*)\nLemma qpolyCN (a : A) : qpolyC h (- a) = -(qpolyC h a).\n\n(*This lemma asserts that the canonical embedding of constants from a base ring into its quotient polynomial ring is a morphism for addition, meaning the embedding of a sum of two elements is equal to the sum of their individual embeddings.*)\nLemma qpolyCD : {morph (qpolyC h) : a b / a + b >-> a + b}%R.\n\n(*This lemma asserts that the canonical embedding of constants from a base ring into its quotient polynomial ring is a morphism for multiplication, meaning the embedding of a product of two elements is equal to the product of their individual embeddings.*)\nLemma qpolyCM : {morph (qpolyC h) : a b / a * b >-> a * b}%R.\n\n(*This lemma states that the canonical embedding of constants from a base ring into its quotient polynomial ring is a Z-module morphism, meaning it preserves zero and addition.*)\nLemma qpolyC_is_zmod_morphism : zmod_morphism (qpolyC h).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `qpolyC_is_zmod_morphism` instead\")]\n(*This definition, now deprecated, is an alias indicating that the canonical embedding of constants into a quotient polynomial ring is an additive morphism.*)\nDefinition qpolyC_is_additive := qpolyC_is_zmod_morphism.\n\n(*This lemma states that the canonical embedding of constants from a base ring into its quotient polynomial ring is a monoid morphism, meaning it preserves the multiplicative identity and multiplication.*)\nLemma qpolyC_is_monoid_morphism : monoid_morphism (qpolyC h).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `qpolyC_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, provides a legacy way to state that the canonical embedding of constants into a quotient polynomial ring is a multiplicative morphism.*)\nDefinition qpolyC_is_multiplicative :=\n (fun g => (g.2,g.1)) qpolyC_is_monoid_morphism.\n\nHB.instance Definition _ := GRing.isZmodMorphism.Build A {poly %/ h} (qpolyC h)\n qpolyC_is_zmod_morphism.\nHB.instance Definition _ :=\n GRing.isMonoidMorphism.Build A {poly %/ h} (qpolyC h)\n qpolyC_is_monoid_morphism.\n\n(*This definition introduces scalar multiplication for a quotient polynomial, where a ring element scales a given quotient polynomial.*)\nDefinition qpoly_scale k (p : {poly %/ h}) : {poly %/ h} := (k *: p)%R.\n\n(*This fact asserts an associativity property for scalar multiplication on quotient polynomials: scaling a quotient polynomial by one ring element and then by another is equivalent to scaling the polynomial by the product of the two ring elements.*)\nFact qpoly_scaleA a b p :\n qpoly_scale a (qpoly_scale b p) = qpoly_scale (a * b) p.\n\n(*This fact asserts that the multiplicative identity of the base ring acts as a left identity for scalar multiplication on quotient polynomials, meaning scaling by this element has no effect.*)\nFact qpoly_scale1l : left_id 1%R qpoly_scale.\n\n(*This fact asserts that scalar multiplication on quotient polynomials distributes on the right over addition, meaning scaling the sum of two quotient polynomials by a ring element is equivalent to adding the scaled versions of each polynomial.*)\nFact qpoly_scaleDr a : {morph qpoly_scale a : p q / (p + q)%R}.\n\n(*This fact establishes that the operation of scaling a quotient polynomial is a linear morphism with respect to its scalar argument, meaning that scaling by a sum of two elements is equivalent to the sum of the results of scaling by each element individually.*)\nFact qpoly_scaleDl p : {morph qpoly_scale^~ p : a b / a + b}%R.\n\n(*This fact states that scaling a product of two quotient polynomials by a ring element is equivalent to multiplying the scaled first polynomial by the second polynomial.*)\nFact qpoly_scaleAl a p q : qpoly_scale a (p * q) = (qpoly_scale a p * q).\n\n(*This fact states that scaling a product of two quotient polynomials by a ring element is equivalent to multiplying the first polynomial by the scaled second polynomial.*)\nFact qpoly_scaleAr a p q : qpoly_scale a (p * q) = p * (qpoly_scale a q).\n\nHB.instance Definition _ := GRing.Lmodule_isLalgebra.Build A {poly__ A}\n qpoly_scaleAl.\nHB.instance Definition _ := GRing.Lalgebra.on {poly %/ h}.\n\nHB.instance Definition _ := GRing.Lalgebra_isAlgebra.Build A {poly__ A}\n qpoly_scaleAr.\n(*This lemma states that scaling a quotient polynomial by a scalar gives a result whose underlying representative polynomial is the same as scaling the original representative polynomial by that same scalar.*)\nLemma poly_of_qpolyZ (p : {poly %/ h}) a :\n a *: p = a *: (p : {poly A}) :> {poly A}.\n\nEnd QRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar_qpoly instead.\")]\n(*This deprecated notation provides a parsing-only alias for the canonical term representing the characteristic polynomial of an endomorphism on a quotient polynomial module. Users are advised to use the canonical name instead.*)\nNotation char_qpoly := (pchar_qpoly) (only parsing).\n\nSection Field.\n\nVariable R : fieldType.\nVariable h : {poly R}.\n\n(*This notation defines a local shorthand for the monic polynomial obtained by normalizing a given polynomial modulus.*)\nLocal Notation hQ := (mk_monic h).\n\n(*This definition provides a computational inverse for a quotient polynomial. If the polynomial is coprime to the monic modulus, it returns its multiplicative inverse; otherwise, it returns the original polynomial.*)\nDefinition qpoly_inv (p : {poly %/ h}) :=\n if coprimep hQ p then let v : {poly %/ h} := in_qpoly h (egcdp hQ p).2 in\n ((lead_coef (v * p)) ^-1 *: v) else p.\n\n(*This lemma states that for a quotient polynomial that is coprime to the modulus, multiplying its computed inverse on the left by the polynomial itself yields the multiplicative identity.*)\nLemma qpoly_mulVz (p : {poly %/ h}) : coprimep hQ p -> (qpoly_inv p * p = 1)%R.\n\n(*This lemma states that for a quotient polynomial that is coprime to the modulus, multiplying the polynomial by its computed inverse on the right yields the multiplicative identity.*)\nLemma qpoly_mulzV (p : {poly %/ h}) :\n coprimep hQ p -> (p * (qpoly_inv p) = 1)%R.\n\n(*This lemma states that if a quotient polynomial has a left multiplicative inverse, then it must be coprime to the modulus.*)\nLemma qpoly_intro_unit (p q : {poly %/ h}) : (q * p = 1)%R -> coprimep hQ p.\n\n(*This lemma states that if a quotient polynomial is not coprime to the modulus, then the computed inverse of the polynomial is the polynomial itself.*)\nLemma qpoly_inv_out (p : {poly %/ h}) : ~~ coprimep hQ p -> qpoly_inv p = p.\n\nHB.instance Definition _ := GRing.ComNzRing_hasMulInverse.Build {poly__ _}\n qpoly_mulVz qpoly_intro_unit qpoly_inv_out.\n(*This lemma states that if a polynomial is irreducible and does not divide a second polynomial, then the two polynomials are coprime.*)\nLemma irreducible_poly_coprime (A : idomainType) (p q : {poly A}) :\n irreducible_poly p -> coprimep p q = ~~(p %| q)%R.", - "algebra.num_theory.orderedzmod": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import ssrAC div fintype path bigop order finset fingroup.\nFrom mathcomp Require Import ssralg poly.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nReserved Notation \"n .-root\" (format \"n .-root\").\nReserved Notation \"'i\".\nReserved Notation \"'Re z\" (at level 10, z at level 8).\nReserved Notation \"'Im z\" (at level 10, z at level 8).\n\nLocal Open Scope order_scope.\nLocal Open Scope group_scope.\nLocal Open Scope ring_scope.\n\nImport Order.TTheory GRing.Theory.\n\n(*A display parameter used to specify the canonical order relations for ring-like structures.*)\nFact ring_display : Order.disp_t. \n\nModule Num.\n\n#[short(type=\"porderZmodType\")]\n(*This structure describes a type that is both a module over the integers and a partially ordered set, where the order relation is associated with a specific ring display.*)\nHB.structure Definition POrderedZmodule :=\n { R of Order.isPOrder ring_display R & GRing.Zmodule R }.\n\nModule Export Def.\n\n(*A notation for the 'less than or equal to' relation, specific to the canonical order on ring-like structures.*)\nNotation ler := (@Order.le ring_display _) (only parsing).\n(*A notation for the curried 'less than or equal to' relation on a specified ring-like type, returning a two-argument boolean predicate.*)\nNotation \"@ 'ler' R\" := (@Order.le ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n(*A notation for the 'less than' relation, specific to the canonical order on ring-like structures.*)\nNotation ltr := (@Order.lt ring_display _) (only parsing).\n(*A notation for the curried 'less than' relation on a specified ring-like type, returning a two-argument boolean predicate.*)\nNotation \"@ 'ltr' R\" := (@Order.lt ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n(*A notation for the 'greater than or equal to' relation, specific to the canonical order on ring-like structures.*)\nNotation ger := (@Order.ge ring_display _) (only parsing).\n(*A notation for the curried 'greater than or equal to' relation on a specified ring-like type, returning a two-argument boolean predicate.*)\nNotation \"@ 'ger' R\" := (@Order.ge ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n(*A notation for the 'greater than' relation, specific to the canonical order on ring-like structures.*)\nNotation gtr := (@Order.gt ring_display _) (only parsing).\n(*A notation for the curried 'greater than' relation on a specified ring-like type, returning a two-argument boolean predicate.*)\nNotation \"@ 'gtr' R\" := (@Order.gt ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n(*A notation for the boolean test of the 'less than or equal to' relation, intended for use in conditional expressions involving ring-like structures.*)\nNotation lerif := (@Order.leif ring_display _) (only parsing).\n(*A notation for the curried boolean test of the 'less than or equal to' relation on a specified ring-like type, returning a two-argument boolean predicate for use in conditional expressions.*)\nNotation \"@ 'lerif' R\" := (@Order.leif ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n(*A notation for the boolean test of the 'less than' relation, intended for use in conditional expressions involving ring-like structures.*)\nNotation lterif := (@Order.lteif ring_display _) (only parsing).\n(*A notation for the curried boolean test of the 'less than' relation on a specified ring-like type, returning a two-argument boolean predicate for use in conditional expressions.*)\nNotation \"@ 'lteif' R\" := (@Order.lteif ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n(*A notation that checks if two elements of a ring-like structure are comparable, meaning one is less than or equal to the other.*)\nNotation comparabler := (@Order.comparable ring_display _) (only parsing).\n(*A notation for the curried comparability test on a specified ring-like type, returning a two-argument boolean predicate that is true if one input is less than or equal to the other.*)\nNotation \"@ 'comparabler' R\" := (@Order.comparable ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n(*A notation for the maximum of two elements according to the canonical order on a ring-like structure.*)\nNotation maxr := (@Order.max ring_display _).\n(*A notation for the curried maximum function on a specified ring-like type, returning a function that takes two elements and yields the greater of the two.*)\nNotation \"@ 'maxr' R\" := (@Order.max ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n(*A notation for the minimum of two elements according to the canonical order on a ring-like structure.*)\nNotation minr := (@Order.min ring_display _).\n(*A notation for the curried minimum function on a specified ring-like type, returning a function that takes two elements and yields the lesser of the two.*)\nNotation \"@ 'minr' R\" := (@Order.min ring_display R)\n (at level 10, R at level 8, only parsing) : function_scope.\n\nSection Def.\nContext {R : porderZmodType}.\n\n(*This definition is a predicate that returns true if a given element of a partially ordered Z-module is strictly greater than zero.*)\nDefinition Rpos_pred := fun x : R => 0 < x.\n(*This definition establishes a subtype qualifier for elements of a partially ordered Z-module that are strictly greater than zero.*)\nDefinition Rpos : qualifier 0 R := [qualify x | Rpos_pred x].\n(*This definition is a predicate that returns true if a given element of a partially ordered Z-module is strictly less than zero.*)\nDefinition Rneg_pred := fun x : R => x < 0.\n(*This definition establishes a subtype qualifier for elements of a partially ordered Z-module that are strictly less than zero.*)\nDefinition Rneg : qualifier 0 R := [qualify x : R | Rneg_pred x].\n(*This definition is a predicate that returns true if a given element of a partially ordered Z-module is greater than or equal to zero.*)\nDefinition Rnneg_pred := fun x : R => 0 <= x.\n(*This definition establishes a subtype qualifier for elements of a partially ordered Z-module that are greater than or equal to zero.*)\nDefinition Rnneg : qualifier 0 R := [qualify x : R | Rnneg_pred x].\n(*This definition is a predicate that returns true if a given element of a partially ordered Z-module is less than or equal to zero.*)\nDefinition Rnpos_pred := fun x : R => x <= 0.\n(*This definition establishes a subtype qualifier for elements of a partially ordered Z-module that are less than or equal to zero.*)\nDefinition Rnpos : qualifier 0 R := [qualify x : R | Rnpos_pred x].\n(*This definition is a predicate that returns true if a given element of a partially ordered Z-module is comparable with zero, meaning it is either greater than or equal to zero, or less than or equal to zero.*)\nDefinition Rreal_pred := fun x : R => (0 <= x) || (x <= 0).\n(*This definition establishes a subtype qualifier for elements of a partially ordered Z-module that are comparable with zero.*)\nDefinition Rreal : qualifier 0 R := [qualify x : R | Rreal_pred x].\n\nEnd Def.\n\nArguments Rpos_pred _ _ /.\nArguments Rneg_pred _ _ /.\nArguments Rnneg_pred _ _ /.\nArguments Rreal_pred _ _ /.\nEnd Def.\n\n(*This notation represents the less-than-or-equal-to relation between two real numbers.*)\nNotation le := ler (only parsing).\n(*This notation represents the strict less-than relation between two real numbers.*)\nNotation lt := ltr (only parsing).\n(*This notation represents the greater-than-or-equal-to relation between two real numbers.*)\nNotation ge := ger (only parsing).\n(*This notation represents the strict greater-than relation between two real numbers.*)\nNotation gt := gtr (only parsing).\n(*This notation represents a boolean-valued function that checks if a first real number is less than or equal to a second real number.*)\nNotation leif := lerif (only parsing).\n(*This notation represents a boolean-valued function that checks if a first real number is strictly less than a second real number.*)\nNotation lteif := lterif (only parsing).\n(*This notation represents a boolean-valued function that checks if two real numbers are comparable, meaning one is less than or equal to the other.*)\nNotation comparable := comparabler (only parsing).\n(*This notation represents the function that returns the greater of two real numbers.*)\nNotation max := maxr.\n(*This notation represents the function that returns the smaller of two real numbers.*)\nNotation min := minr.\n(*This notation represents the predicate that determines if a real number is strictly positive.*)\nNotation pos := Rpos.\n(*This notation represents the predicate that determines if a real number is strictly negative.*)\nNotation neg := Rneg.\n(*This notation represents the predicate that determines if a real number is non-negative, meaning greater than or equal to zero.*)\nNotation nneg := Rnneg.\n(*This notation represents the predicate that determines if a real number is non-positive, meaning less than or equal to zero.*)\nNotation npos := Rnpos.\n(*This notation represents a predicate that is always true for any real number, typically used for type annotation purposes.*)\nNotation real := Rreal.\n\nModule Import Syntax.\n\n(*This notation represents the less-than-or-equal-to relation between two real numbers as a two-argument function.*)\nNotation \"<=%R\" := le : function_scope.\n(*This notation represents the greater-than-or-equal-to relation between two real numbers as a two-argument function.*)\nNotation \">=%R\" := ge : function_scope.\n(*This notation represents the strict less-than relation between two real numbers as a two-argument function.*)\nNotation \"<%R\" := lt : function_scope.\n(*This notation represents the strict greater-than relation between two real numbers as a two-argument function.*)\nNotation \">%R\" := gt : function_scope.\n(*This notation represents a boolean-valued function that tests if a first real number is less than or equal to a second.*)\nNotation \"=<%R\" := comparable : function_scope.\n(*This notation represents a boolean-valued function that tests if two real numbers are incomparable, meaning neither is less than or equal to the other.*)\nNotation \"><%R\" := (fun x y => ~~ (comparable x y)) : function_scope.\n\n(*This notation creates a predicate that tests if its argument, a real number, is less than or equal to a specified real number.*)\nNotation \"<= y\" := (ge y) : ring_scope.\n(*This notation creates a predicate that tests if its argument, a real number, is less than or equal to a specified real number, allowing an explicit type to be provided for the specified number.*)\nNotation \"<= y :> T\" := (<= (y : T)) (only parsing) : ring_scope.\n(*This notation creates a predicate that tests if its argument, a real number, is greater than or equal to a specified real number.*)\nNotation \">= y\" := (le y) : ring_scope.\n(*This notation creates a predicate that tests if its argument, a real number, is greater than or equal to a specified real number, allowing an explicit type to be provided for the specified number.*)\nNotation \">= y :> T\" := (>= (y : T)) (only parsing) : ring_scope.\n\n(*This notation creates a predicate that tests if its argument, a real number, is strictly less than a specified real number.*)\nNotation \"< y\" := (gt y) : ring_scope.\n(*This notation creates a predicate that tests if its argument, a real number, is strictly less than a specified real number, allowing an explicit type to be provided for the specified number.*)\nNotation \"< y :> T\" := (< (y : T)) (only parsing) : ring_scope.\n(*This notation creates a predicate that tests if its argument, a real number, is strictly greater than a specified real number.*)\nNotation \"> y\" := (lt y) : ring_scope.\n(*This notation creates a predicate that tests if its argument, a real number, is strictly greater than a specified real number, allowing an explicit type to be provided for the specified number.*)\nNotation \"> y :> T\" := (> (y : T)) (only parsing) : ring_scope.\n\n(*A notation representing the 'less than or equal to' relation between two elements in an ordered type.*)\nNotation \"x <= y\" := (le x y) : ring_scope.\n(*A notation representing the 'less than or equal to' relation between two elements, where the elements are explicitly cast to a given type before comparison.*)\nNotation \"x <= y :> T\" := ((x : T) <= (y : T)) (only parsing) : ring_scope.\n(*A notation representing the 'greater than or equal to' relation between two elements, defined as the second element being less than or equal to the first.*)\nNotation \"x >= y\" := (y <= x) (only parsing) : ring_scope.\n(*A notation representing the 'greater than or equal to' relation between two elements, where the elements are explicitly cast to a given type before comparison.*)\nNotation \"x >= y :> T\" := ((x : T) >= (y : T)) (only parsing) : ring_scope.\n\n(*A notation representing the strict 'less than' relation between two elements in an ordered type.*)\nNotation \"x < y\" := (lt x y) : ring_scope.\n(*A notation representing the strict 'less than' relation between two elements, where the elements are explicitly cast to a given type before comparison.*)\nNotation \"x < y :> T\" := ((x : T) < (y : T)) (only parsing) : ring_scope.\n(*A notation representing the strict 'greater than' relation between two elements, defined as the second element being strictly less than the first.*)\nNotation \"x > y\" := (y < x) (only parsing) : ring_scope.\n(*A notation representing the strict 'greater than' relation between two elements, where the elements are explicitly cast to a given type before comparison.*)\nNotation \"x > y :> T\" := ((x : T) > (y : T)) (only parsing) : ring_scope.\n\n(*A chained comparison notation that asserts that a first element is less than or equal to a second element, and the second element is less than or equal to a third element.*)\nNotation \"x <= y <= z\" := ((x <= y) && (y <= z)) : ring_scope.\n(*A chained comparison notation that asserts that a first element is strictly less than a second element, and the second element is less than or equal to a third element.*)\nNotation \"x < y <= z\" := ((x < y) && (y <= z)) : ring_scope.\n(*A chained comparison notation that asserts that a first element is less than or equal to a second element, and the second element is strictly less than a third element.*)\nNotation \"x <= y < z\" := ((x <= y) && (y < z)) : ring_scope.\n(*A chained comparison notation that asserts that a first element is strictly less than a second element, and the second element is strictly less than a third element.*)\nNotation \"x < y < z\" := ((x < y) && (y < z)) : ring_scope.\n\n(*A notation for a rewrite lemma, stating that the relation 'first element is less than or equal to second element' is logically equivalent to a given boolean condition.*)\nNotation \"x <= y ?= 'iff' C\" := (lerif x y C) : ring_scope.\n(*A notation for a rewrite lemma, stating that the relation 'first element is less than or equal to second element' is logically equivalent to a given boolean condition, where the elements are explicitly cast to a given type.*)\nNotation \"x <= y ?= 'iff' C :> R\" := ((x : R) <= (y : R) ?= iff C)\n (only parsing) : ring_scope.\n\n(*A notation for a rewrite lemma asserting that a given boolean condition implies that a first element is strictly less than a second element.*)\nNotation \"x < y ?<= 'if' C\" := (lterif x y C) : ring_scope.\n(*A notation for a rewrite lemma asserting that a given boolean condition implies that a first element is strictly less than a second element, where the elements are explicitly cast to a given type.*)\nNotation \"x < y ?<= 'if' C :> R\" := ((x : R) < (y : R) ?<= if C)\n (only parsing) : ring_scope.\n\n(*A notation for a predicate that is satisfied by any element that is comparable to a given element, meaning one is less than or equal to the other.*)\nNotation \">=< y\" := [pred x | comparable x y] : ring_scope.\n(*A notation for a predicate that is satisfied by any element that is comparable to a given element, where the given element is explicitly cast to a specified type.*)\nNotation \">=< y :> T\" := (>=< (y : T)) (only parsing) : ring_scope.\n(*A notation representing the boolean property that two elements are comparable, which is true if one element is less than or equal to the other.*)\nNotation \"x >=< y\" := (comparable x y) : ring_scope.\n\n(*A notation for a predicate that is satisfied by any element that is comparable to another given element, meaning one is less than or equal to the other.*)\nNotation \">< y\" := [pred x | ~~ comparable x y] : ring_scope.\n(*A notation for a predicate that is satisfied by any element that is comparable to a given element, where the given element is explicitly cast to a specified type.*)\nNotation \">< y :> T\" := (>< (y : T)) (only parsing) : ring_scope.\n(*A notation representing the boolean property that two elements are comparable, which is true if one element is less than or equal to the other.*)\nNotation \"x >< y\" := (~~ (comparable x y)) : ring_scope.\n\nExport Order.PreOCoercions.\n\nEnd Syntax.\n\nModule Export Theory.\n\nEnd Theory.\n\nModule Exports. HB.reexport. End Exports.\nEnd Num.", - "algebra.num_theory.numfield": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import ssrAC div fintype path bigop order finset fingroup.\nFrom mathcomp Require Import ssralg poly orderedzmod numdomain.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope order_scope.\nLocal Open Scope group_scope.\nLocal Open Scope ring_scope.\n\nImport Order.TTheory GRing.Theory.\nImport orderedzmod.Num numdomain.Num.\n\nModule Num.\n\n#[short(type=\"numFieldType\")]\n(*This structure defines a number field as a type that is simultaneously a field, an integral domain, a partially ordered Z-module, a normed Z-module, and a number ring. It represents an algebraic structure with addition, subtraction, multiplication, division, an order relation, and a norm.*)\nHB.structure Definition NumField := { R of GRing.UnitRing_isField R &\n GRing.IntegralDomain R &\n POrderedZmodule R &\n NormedZmodule (POrderedZmodule.clone R _) R &\n isNumRing R }.\n\nModule NumFieldExports.\nBind Scope ring_scope with NumField.sort.\nEnd NumFieldExports.\nHB.export NumFieldExports.\n\n(*This structure extends a number field with properties of a field containing an imaginary unit. It specifies an element whose square is negative one, a conjugation operation, and a rule relating the squared norm of an element to the product of the element and its conjugate.*)\nHB.mixin Record NumField_isImaginary R of NumField R := {\n imaginary : R;\n conj_op : {rmorphism R -> R};\n sqrCi : imaginary ^+ 2 = - 1;\n normCK : forall x, `|x| ^+ 2 = x * conj_op x;\n}.\n\n#[short(type=\"numClosedFieldType\")]\n(*This structure defines a closed field as a number field that is algebraically closed and also possesses the properties of a number field with an imaginary unit, including a conjugation operation.*)\nHB.structure Definition ClosedField :=\n { R of NumField_isImaginary R & GRing.ClosedField R & NumField R }.\n\nModule ClosedFieldExports.\nBind Scope ring_scope with ClosedField.sort.\nEnd ClosedFieldExports.\nHB.export ClosedFieldExports.\n\n#[short(type=\"realFieldType\")]\n(*This structure defines a real field as a number field that is equipped with a total order relation, meaning any two elements are comparable.*)\nHB.structure Definition RealField :=\n { R of Order.Total ring_display R & NumField R }.\n\nModule RealFieldExports.\nBind Scope ring_scope with RealField.sort.\nEnd RealFieldExports.\nHB.export RealFieldExports.\n\n(*This structure extends a real field with the axiom that guarantees the intermediate value theorem holds for polynomials. This axiom states that for any polynomial that takes opposite signs at the endpoints of an interval, there must be a root within that interval.*)\nHB.mixin Record RealField_isClosed R of RealField R := {\n poly_ivt_subproof : real_closed_axiom R\n}.\n\n#[short(type=\"rcfType\")]\n(*This structure defines a real closed field as a totally ordered field where every positive element has a square root and every polynomial of odd degree has at least one root. This is captured by combining the real field structure with the axiom for the intermediate value theorem for polynomials.*)\nHB.structure Definition RealClosedField :=\n { R of RealField_isClosed R & RealField R }.\n\nModule RealClosedFieldExports.\nBind Scope ring_scope with RealClosedField.sort.\nEnd RealClosedFieldExports.\nHB.export RealClosedFieldExports.\n\nSection RealClosed.\nVariable R : rcfType.\n\n(*This lemma states that a type satisfies the real closed field axiom, which is established by proving the Intermediate Value Theorem for polynomials.*)\nLemma poly_ivt : real_closed_axiom R. \n\n(*This fact asserts the existence of a principal square root for any element in a real closed field. It guarantees that for any given element, there exists a non-negative element whose square is equal to the original element if the original element was non-negative, and is zero otherwise.*)\nFact sqrtr_subproof (x : R) :\n exists2 y, 0 <= y & (if 0 <= x then y ^+ 2 == x else y == 0) : bool.\n\nEnd RealClosed.\n\nModule Import Def.\n\n(*This definition provides a function that computes the principal square root of an element in a real closed field. The result is always a non-negative number. If the input is non-negative, the square of the result is equal to the input; otherwise, the result is zero.*)\nDefinition sqrtr {R} x := s2val (sig2W (@sqrtr_subproof R x)).\n\nEnd Def.\n\n(*This defines `sqrt` as a notation for the principal square root function `sqrtr` on a real closed field.*)\nNotation sqrt := sqrtr.\n\nModule Export Theory.\nSection NumFieldTheory.\n\nVariable F : numFieldType.\nImplicit Types x y z t : F.\n\n(*This lemma states that in a number field, any element that is strictly greater than zero is a unit, meaning it has a multiplicative inverse.*)\nLemma unitf_gt0 x : 0 < x -> x \\is a GRing.unit.\n\n(*This lemma states that in a number field, any element that is strictly less than zero is a unit, meaning it has a multiplicative inverse.*)\nLemma unitf_lt0 x : x < 0 -> x \\is a GRing.unit.\n\n(*This lemma states that for positive elements in a number field, the multiplicative inversion function is monotonically decreasing. If a first positive element is less than or equal to a second positive element, then the inverse of the second element is less than or equal to the inverse of the first.*)\nLemma lef_pV2 : {in pos &, {mono (@GRing.inv F) : x y /~ x <= y}}.\n\n(*This lemma states that for negative elements in a number field, the multiplicative inversion function is monotonically decreasing. If a first negative element is less than or equal to a second negative element, then the inverse of the second element is less than or equal to the inverse of the first.*)\nLemma lef_nV2 : {in neg &, {mono (@GRing.inv F) : x y /~ x <= y}}.\n\n(*This lemma states that for positive elements in a number field, the multiplicative inversion function is strictly monotonically decreasing. If a first positive element is strictly less than a second positive element, then the inverse of the second element is strictly less than the inverse of the first.*)\nLemma ltf_pV2 : {in pos &, {mono (@GRing.inv F) : x y /~ x < y}}.\n\n(*This lemma states that for negative elements in a number field, the multiplicative inversion function is strictly monotonically decreasing. If a first negative element is strictly less than a second negative element, then the inverse of the second element is strictly less than the inverse of the first.*)\nLemma ltf_nV2 : {in neg &, {mono (@GRing.inv F) : x y /~ x < y}}.\n\n(*This definition packages two lemmas together: one stating that multiplicative inversion is monotonically decreasing for positive elements under the less-than-or-equal-to relation, and another stating it is strictly monotonically decreasing under the strict less-than relation.*)\nDefinition ltef_pV2 := (lef_pV2, ltf_pV2).\n(*This definition packages two lemmas together: one stating that multiplicative inversion is monotonically decreasing for negative elements under the less-than-or-equal-to relation, and another stating it is strictly monotonically decreasing under the strict less-than relation.*)\nDefinition ltef_nV2 := (lef_nV2, ltf_nV2).\n\n(*This lemma states that for any two positive elements in a number field, the proposition that the first element is strictly less than the multiplicative inverse of the second is equivalent to the proposition that the second element is strictly less than the multiplicative inverse of the first.*)\nLemma invf_pgt : {in pos &, forall x y, (x < y^-1) = (y < x^-1)}.\n\n(*This lemma states that for any two positive elements in a number field, the proposition that the first element is less than or equal to the multiplicative inverse of the second is equivalent to the proposition that the second element is less than or equal to the multiplicative inverse of the first.*)\nLemma invf_pge : {in pos &, forall x y, (x <= y^-1) = (y <= x^-1)}.\n\n(*This lemma states that for any two negative elements in a number field, the proposition that the first element is strictly less than the multiplicative inverse of the second is equivalent to the proposition that the second element is strictly less than the multiplicative inverse of the first.*)\nLemma invf_ngt : {in neg &, forall x y, (x < y^-1) = (y < x^-1)}.\n\n(*This lemma states that for any two negative elements in a number field, the proposition that the first element is less than or equal to the multiplicative inverse of the second is equivalent to the proposition that the second element is less than or equal to the multiplicative inverse of the first.*)\nLemma invf_nge : {in neg &, forall x y, (x <= y^-1) = (y <= x^-1)}.\n\n(*This lemma states that for a positive element of a number field, its multiplicative inverse is strictly greater than one if and only if the element itself is strictly less than one.*)\nLemma invf_gt1 x : 0 < x -> (1 < x^-1) = (x < 1).\n\n(*This lemma states that for a positive element of a number field, its multiplicative inverse is greater than or equal to one if and only if the element itself is less than or equal to one.*)\nLemma invf_ge1 x : 0 < x -> (1 <= x^-1) = (x <= 1).\n\n(*This definition packages two lemmas concerning the relationship between a positive element and its multiplicative inverse relative to one: one for the non-strict comparison 'greater than or equal to', and one for the strict comparison 'greater than'.*)\nDefinition invf_gte1 := (invf_ge1, invf_gt1).\n\n(*This lemma states that for any two positive elements in a number field, the proposition that the multiplicative inverse of the first element is strictly less than the second is equivalent to the proposition that the multiplicative inverse of the second element is strictly less than the first.*)\nLemma invf_plt : {in pos &, forall x y, (x^-1 < y) = (y^-1 < x)}.\n\n(*This lemma states that for any two positive elements in a number field, the proposition that the multiplicative inverse of the first element is less than or equal to the second is equivalent to the proposition that the multiplicative inverse of the second element is less than or equal to the first.*)\nLemma invf_ple : {in pos &, forall x y, (x^-1 <= y) = (y^-1 <= x)}.\n\n(*This lemma states that for any two negative elements in a number field, the proposition that the multiplicative inverse of the first element is strictly less than the second is equivalent to the proposition that the multiplicative inverse of the second element is strictly less than the first.*)\nLemma invf_nlt : {in neg &, forall x y, (x^-1 < y) = (y^-1 < x)}.\n\n(*This lemma states that for any two negative elements in a number field, the proposition that the multiplicative inverse of the first element is less than or equal to the second is equivalent to the proposition that the multiplicative inverse of the second element is less than or equal to the first.*)\nLemma invf_nle : {in neg &, forall x y, (x^-1 <= y) = (y^-1 <= x)}.\n\n(*This lemma states that for a positive element of a number field, its multiplicative inverse is less than or equal to one if and only if the element itself is greater than or equal to one.*)\nLemma invf_le1 x : 0 < x -> (x^-1 <= 1) = (1 <= x).\n\n(*This lemma states that for any positive field element, its multiplicative inverse is less than one if and only if the element itself is greater than one.*)\nLemma invf_lt1 x : 0 < x -> (x^-1 < 1) = (1 < x).\n\n(*This definition groups two lemmas concerning the comparison of the multiplicative inverse of a positive field element with one: one lemma for the less-than-or-equal-to relation and another for the strict less-than relation.*)\nDefinition invf_lte1 := (invf_le1, invf_lt1).\n(*This definition bundles four lemmas that relate comparing a positive field element with one to comparing its multiplicative inverse with one, covering all four inequality relations: less than, less than or equal to, greater than, and greater than or equal to.*)\nDefinition invf_cp1 := (invf_gte1, invf_lte1).\n\n(*This lemma states that for a positive field element, an inequality where a value is less than or equal to a quotient can be rewritten as an equivalent inequality where the product of that value and the divisor is less than or equal to the dividend.*)\nLemma ler_pdivlMr z x y : 0 < z -> (x <= y / z) = (x * z <= y).\n\n(*This lemma states that for a positive field element, a strict inequality where a value is less than a quotient can be rewritten as an equivalent strict inequality where the product of that value and the divisor is less than the dividend.*)\nLemma ltr_pdivlMr z x y : 0 < z -> (x < y / z) = (x * z < y).\n\n(*This definition aggregates two lemmas for rewriting an inequality involving division by a positive field element, one for the less-than-or-equal-to relation and one for the strict less-than relation.*)\nDefinition lter_pdivlMr := (ler_pdivlMr, ltr_pdivlMr).\n\n(*This lemma states that for a positive field element, an inequality where a quotient is less than or equal to a value can be rewritten as an equivalent inequality where the dividend is less than or equal to the product of that value and the divisor.*)\nLemma ler_pdivrMr z x y : 0 < z -> (y / z <= x) = (y <= x * z).\n\n(*This lemma states that for a positive field element, a strict inequality where a quotient is less than a value can be rewritten as an equivalent strict inequality where the dividend is less than the product of that value and the divisor.*)\nLemma ltr_pdivrMr z x y : 0 < z -> (y / z < x) = (y < x * z).\n\n(*This definition combines two lemmas that allow rewriting an inequality where a quotient is compared to a value, covering both the less-than-or-equal-to and the strict less-than cases when the divisor is positive.*)\nDefinition lter_pdivrMr := (ler_pdivrMr, ltr_pdivrMr).\n\n(*This lemma states that for a positive field element, an inequality asserting that a value is less than or equal to a product involving a multiplicative inverse can be transformed into an equivalent inequality where the product of that value and the non-inverted element is less than or equal to the other factor.*)\nLemma ler_pdivlMl z x y : 0 < z -> (x <= z^-1 * y) = (z * x <= y).\n\n(*This lemma states that for a positive field element, a strict inequality asserting that a value is less than a product involving a multiplicative inverse can be transformed into an equivalent strict inequality where the product of that value and the non-inverted element is less than the other factor.*)\nLemma ltr_pdivlMl z x y : 0 < z -> (x < z^-1 * y) = (z * x < y).\n\n(*This definition groups two lemmas for rewriting an inequality involving multiplication by the inverse of a positive field element, one for the less-than-or-equal-to case and one for the strict less-than case.*)\nDefinition lter_pdivlMl := (ler_pdivlMl, ltr_pdivlMl).\n\n(*This lemma states that for a positive field element, an inequality where a product involving a multiplicative inverse is less than or equal to another value can be rewritten as an equivalent inequality where one factor is less than or equal to the product of the other value and the non-inverted element.*)\nLemma ler_pdivrMl z x y : 0 < z -> (z^-1 * y <= x) = (y <= z * x).\n\n(*This lemma states that for a positive field element, a strict inequality where a product involving a multiplicative inverse is less than another value can be rewritten as an equivalent strict inequality where one factor is less than the product of the other value and the non-inverted element.*)\nLemma ltr_pdivrMl z x y : 0 < z -> (z^-1 * y < x) = (y < z * x).\n\n(*This definition combines two lemmas that allow rewriting an inequality where a product involving an inverse is compared to a value, covering both the less-than-or-equal-to and the strict less-than cases when the base of the inverse is positive.*)\nDefinition lter_pdivrMl := (ler_pdivrMl, ltr_pdivrMl).\n\n(*This lemma states that for a negative field element, an inequality where a value is less than or equal to a quotient can be rewritten by multiplying by the divisor, which reverses the inequality direction, making the dividend less than or equal to the product of the original value and the divisor.*)\nLemma ler_ndivlMr z x y : z < 0 -> (x <= y / z) = (y <= x * z).\n\n(*This lemma states that for a negative field element, a strict inequality where a value is less than a quotient can be rewritten by multiplying by the divisor, which reverses the inequality direction, making the dividend less than the product of the original value and the divisor.*)\nLemma ltr_ndivlMr z x y : z < 0 -> (x < y / z) = (y < x * z).\n\n(*This definition aggregates two lemmas for rewriting an inequality involving division by a negative field element by multiplying through, one for the less-than-or-equal-to relation and one for the strict less-than relation, both of which reverse the inequality.*)\nDefinition lter_ndivlMr := (ler_ndivlMr, ltr_ndivlMr).\n\n(*This lemma states that for a negative field element, an inequality where a quotient is less than or equal to a value can be rewritten by multiplying by the divisor, which reverses the inequality direction, making the product of the value and the divisor less than or equal to the dividend.*)\nLemma ler_ndivrMr z x y : z < 0 -> (y / z <= x) = (x * z <= y).\n\n(*This lemma states that for a negative field element, a strict inequality where a quotient is less than a value can be rewritten by multiplying by the divisor, which reverses the inequality direction, making the product of the value and the divisor less than the dividend.*)\nLemma ltr_ndivrMr z x y : z < 0 -> (y / z < x) = (x * z < y).\n\n(*This definition combines two lemmas that allow rewriting an inequality where a quotient is compared to a value by multiplying by a negative divisor, covering both the less-than-or-equal-to and the strict less-than cases, both of which reverse the inequality.*)\nDefinition lter_ndivrMr := (ler_ndivrMr, ltr_ndivrMr).\n\n(*This lemma states that for a negative field element, an inequality asserting that a value is less than or equal to a product involving a multiplicative inverse can be transformed by multiplying by the non-inverted element, which reverses the inequality, making the other factor less than or equal to the new product.*)\nLemma ler_ndivlMl z x y : z < 0 -> (x <= z^-1 * y) = (y <= z * x).\n\n(*This lemma states that for a negative field element, a strict inequality asserting that a value is less than a product involving a multiplicative inverse can be transformed by multiplying by the non-inverted element, which reverses the inequality, making the other factor less than the new product.*)\nLemma ltr_ndivlMl z x y : z < 0 -> (x < z^-1 * y) = (y < z * x).\n\n(*This definition groups two lemmas for rewriting an inequality involving multiplication by the inverse of a negative field element, covering both non-strict and strict less-than cases, both of which reverse the inequality.*)\nDefinition lter_ndivlMl := (ler_ndivlMl, ltr_ndivlMl).\n\n(*This lemma states that for a negative field element, an inequality where a product involving a multiplicative inverse is less than or equal to another value can be transformed by multiplying by the non-inverted element, which reverses the inequality, making the new product less than or equal to the original factor.*)\nLemma ler_ndivrMl z x y : z < 0 -> (z^-1 * y <= x) = (z * x <= y).\n\n(*This lemma states that for a negative field element, a strict inequality where a product involving a multiplicative inverse is less than another value can be transformed by multiplying by the non-inverted element, which reverses the inequality, making the new product less than the original factor.*)\nLemma ltr_ndivrMl z x y : z < 0 -> (z^-1 * y < x) = (z * x < y).\n\n(*This definition combines two lemmas that allow rewriting an inequality where a product involving an inverse of a negative number is compared to a value, covering both the less-than-or-equal-to and strict less-than cases, both of which reverse the inequality.*)\nDefinition lter_ndivrMl := (ler_ndivrMl, ltr_ndivrMl).\n\n(*This lemma states that if one natural number divides another, then the field representation of their natural number quotient is equal to the field division of their respective field representations.*)\nLemma natf_div m d : (d %| m)%N -> (m %/ d)%:R = m%:R / d%:R :> F.\n\n(*This lemma asserts that the norm function on a field is a morphism with respect to multiplicative inversion, meaning that the norm of the inverse of an element is equal to the inverse of its norm.*)\nLemma normfV : {morph (norm : F -> F) : x / x ^-1}.\n\n(*This lemma asserts that the norm function on a field is a morphism with respect to division, meaning that the norm of a quotient of two elements is equal to the quotient of their norms.*)\nLemma normf_div : {morph (norm : F -> F) : x y / x / y}.\n\n(*This lemma states that the multiplicative inverse of the sign of a field element is equal to the real sign of that element.*)\nLemma invr_sg x : (sg x)^-1 = sgr x.\n\n(*This lemma states that the real sign of the multiplicative inverse of a field element is identical to the real sign of the element itself.*)\nLemma sgrV x : sgr x^-1 = sgr x.\n\n(*This lemma states that any field element is equal to the sum of its two halves.*)\nLemma splitr x : x = x / 2%:R + x / 2%:R.\n\n(*This lemma states that for a positive field element, a conditional less-than comparison between a first value and a second value divided by the positive element is equivalent to the same conditional comparison between the first value multiplied by the positive element and the second value.*)\nLemma lteif_pdivlMr C z x y :\n 0 < z -> x < y / z ?<= if C = (x * z < y ?<= if C).\n\n(*This lemma states that for a positive field element, a conditional less-than comparison between a first value divided by the positive element and a second value is equivalent to the same conditional comparison between the first value and the second value multiplied by the positive element.*)\nLemma lteif_pdivrMr C z x y :\n 0 < z -> y / z < x ?<= if C = (y < x * z ?<= if C).\n\n(*This lemma states that for a positive field element, a conditional less-than comparison between a first value and the product of the inverse of the positive element and a second value is equivalent to the same conditional comparison between the product of the positive element and the first value and the second value.*)\nLemma lteif_pdivlMl C z x y :\n 0 < z -> x < z^-1 * y ?<= if C = (z * x < y ?<= if C).\n\n(*This lemma states that for a positive field element, a conditional less-than comparison between the product of the inverse of the positive element and a first value and a second value is equivalent to the same conditional comparison between the first value and the product of the positive element and the second value.*)\nLemma lteif_pdivrMl C z x y :\n 0 < z -> z^-1 * y < x ?<= if C = (y < z * x ?<= if C).\n\n(*This lemma states that for a negative field element, a conditional less-than comparison between a first value and a second value divided by the negative element is equivalent to the same conditional comparison between the second value and the product of the first value and the negative element.*)\nLemma lteif_ndivlMr C z x y :\n z < 0 -> x < y / z ?<= if C = (y < x * z ?<= if C).\n\n(*This lemma states that for a negative field element, a conditional less-than comparison between a first value divided by the negative element and a second value is equivalent to the same conditional comparison between the product of the second value and the negative element and the first value.*)\nLemma lteif_ndivrMr C z x y :\n z < 0 -> y / z < x ?<= if C = (x * z < y ?<= if C).\n\n(*This lemma states that for a negative field element, a conditional less-than comparison between a first value and the product of the inverse of the negative element and a second value is equivalent to the same conditional comparison between the second value and the product of the first value and the negative element.*)\nLemma lteif_ndivlMl C z x y :\n z < 0 -> x < z^-1 * y ?<= if C = (y < z * x ?<= if C).\n\n(*This lemma states that for a negative field element, a conditional less-than comparison between the product of the inverse of the negative element and a first value and a second value is equivalent to the same conditional comparison between the product of the second value and the negative element and the first value.*)\nLemma lteif_ndivrMl C z x y :\n z < 0 -> z^-1 * y < x ?<= if C = (z * x < y ?<= if C).\n\nLocal Notation mid x y := ((x + y) / 2).\n\n(*This lemma states that if a first field element is less than or equal to a second field element, then their arithmetic mean is both greater than or equal to the first element and less than or equal to the second element.*)\nLemma midf_le x y : x <= y -> (x <= mid x y) * (mid x y <= y).\n\n(*This lemma states that if a first field element is strictly less than a second field element, then their arithmetic mean is both strictly greater than the first element and strictly less than the second element.*)\nLemma midf_lt x y : x < y -> (x < mid x y) * (mid x y < y).\n\n(*This definition pairs the lemma about the arithmetic mean for non-strict inequalities with the corresponding lemma for strict inequalities.*)\nDefinition midf_lte := (midf_le, midf_lt).\n\n(*This lemma provides a boolean reflection stating that a first field element is less than or equal to a second field element if and only if for every strictly positive value, the first element is less than or equal to the sum of the second element and that positive value.*)\nLemma ler_addgt0Pr x y : reflect (forall e, e > 0 -> x <= y + e) (x <= y).\n\n(*This lemma provides a boolean reflection stating that a first field element is less than or equal to a second field element if and only if for every strictly positive value, the first element is less than or equal to the sum of that positive value and the second element.*)\nLemma ler_addgt0Pl x y : reflect (forall e, e > 0 -> x <= e + y) (x <= y).\n\n(*This lemma states that if any field element being strictly less than a first value implies it is also strictly less than a second value, then the first value must be less than or equal to the second value.*)\nLemma lt_le a b : (forall x, x < a -> x < b) -> a <= b.\n\n(*This lemma states that if any field element being strictly greater than a second value implies it is also strictly greater than a first value, then the first value must be less than or equal to the second value.*)\nLemma gt_ge a b : (forall x, b < x -> a < x) -> a <= b.\n\n(*This lemma states that for two real numbers, their product is less than or equal to the arithmetic mean of their squares if and only if the two numbers are equal.*)\nLemma real_leif_mean_square x y :\n x \\is real -> y \\is real -> x * y <= mid (x ^+ 2) (y ^+ 2) ?= iff (x == y).\n\n(*This lemma states that for two real numbers, their product is less than or equal to the square of their arithmetic mean if and only if the two numbers are equal.*)\nLemma real_leif_AGM2 x y :\n x \\is real -> y \\is real -> x * y <= mid x y ^+ 2 ?= iff (x == y).\n\n(*This lemma states the Arithmetic-Geometric Mean inequality: for a finite collection of non-negative field elements, their product is less than or equal to their arithmetic mean raised to the power of the number of elements, with equality holding if and only if all elements in the collection are equal.*)\nLemma leif_AGM (I : finType) (A : {pred I}) (E : I -> F) :\n let n := #|A| in let mu := (\\sum_(i in A) E i) / n%:R in\n {in A, forall i, 0 <= E i} ->\n \\prod_(i in A) E i <= mu ^+ n\n ?= iff [forall i in A, forall j in A, E i == E j].\n\nImplicit Type p : {poly F}.\n(*This lemma, known as Cauchy's bound, states that for any non-zero polynomial, there exists an upper bound such that the absolute value of every root of the polynomial is less than or equal to that bound.*)\nLemma Cauchy_root_bound p : p != 0 -> {b | forall x, root p x -> `|x| <= b}.\n\n(*This lemma states a consequence of Lagrange's theorem, asserting that for a finite group and its subgroup, the index of the subgroup, when interpreted as a field element, is equal to the size of the group divided by the size of the subgroup.*)\nLemma natf_indexg (gT : finGroupType) (G H : {group gT}) :\n H \\subset G -> #|G : H|%:R = (#|G|%:R / #|H|%:R)%R :> F.\n\nEnd NumFieldTheory.\n\nSection RealField.\nVariables F : realFieldType.\nImplicit Type x y : F.\n\n(*This lemma states that for two real numbers, their product is less than or equal to the arithmetic mean of their squares, with equality holding if and only if the two numbers are equal.*)\nLemma leif_mean_square x y : x * y <= (x ^+ 2 + y ^+ 2) / 2 ?= iff (x == y).\n\n(*This lemma states that for two real numbers, their product is less than or equal to the square of their arithmetic mean, with equality holding if and only if the two numbers are equal.*)\nLemma leif_AGM2 x y : x * y <= ((x + y) / 2)^+ 2 ?= iff (x == y).\n\nSection MinMax.\n\n(*This lemma provides an explicit formula for the maximum of two real numbers, stating that it is equal to half the sum of the two numbers plus the absolute value of their difference.*)\nLemma maxr_absE x y : Num.max x y = (x + y + `|x - y|) / 2.\n\n(*This lemma provides an explicit formula for the minimum of two real numbers, stating that it is equal to half the sum of the two numbers minus the absolute value of their difference.*)\nLemma minr_absE x y : Num.min x y = (x + y - `|x - y|) / 2.\n\nEnd MinMax.\n\nEnd RealField.\n\nSection RealClosedFieldTheory.\n\nVariable R : rcfType.\nImplicit Types a x y : R.\n\n(*This lemma asserts that a real closed field satisfies the real closed axiom, which is the intermediate value theorem for polynomials: if a polynomial takes values of opposite signs at two points, it must have a root between them.*)\nLemma poly_ivt : real_closed_axiom R. \n\n(*This lemma states that the square root of an element in a real closed field is always greater than or equal to zero.*)\nLemma sqrtr_ge0 a : 0 <= sqrt a.\n\nHint Resolve sqrtr_ge0 : core.\n\n(*This lemma states that for any non-negative element in a real closed field, squaring its principal square root returns the original element.*)\nLemma sqr_sqrtr a : 0 <= a -> sqrt a ^+ 2 = a.\n\n(*This lemma states that the square root of a real number is zero if the number is less than or equal to zero.*)\nLemma ler0_sqrtr a : a <= 0 -> sqrt a = 0.\n\n(*This lemma states that the square root of a real number is zero if the number is strictly less than zero.*)\nLemma ltr0_sqrtr a : a < 0 -> sqrt a = 0.\n\n(*This inductive type provides a case analysis for the properties of the square root of a real number, distinguishing between the case where the input is negative, resulting in a square root of zero, and the case where the input is the square of a non-negative number, yielding that number as the root.*)\nVariant sqrtr_spec a : R -> bool -> bool -> R -> Type :=\n(*This definition establishes a property for an element of a number structure that holds if the additive inverse of the element has a square root.*)\n| IsNoSqrtr of a < 0 : sqrtr_spec a a false true 0\n(**)\n| IsSqrtr b of 0 <= b : sqrtr_spec a (b ^+ 2) true false b.\n\n(*This lemma states that the square root function, along with booleans indicating whether its real input is non-negative or negative, collectively satisfy the case-analysis specification for the square root.*)\nLemma sqrtrP a : sqrtr_spec a a (0 <= a) (a < 0) (sqrt a).\n\n(*This lemma states that the square root of the square of a real number is equal to the absolute value of that number.*)\nLemma sqrtr_sqr a : sqrt (a ^+ 2) = `|a|.\n\n(*This lemma states that for any non-negative real number and another real number, the square root of their product is equal to the product of their individual square roots.*)\nLemma sqrtrM a b : 0 <= a -> sqrt (a * b) = sqrt a * sqrt b.\n\n(*This lemma states that the square root of the real number zero is zero.*)\nLemma sqrtr0 : sqrt 0 = 0 :> R.\n\n(*This lemma states that the square root of the real number one is one.*)\nLemma sqrtr1 : sqrt 1 = 1 :> R.\n\n(*This lemma states that the square root of a real number is equal to zero if and only if the number itself is less than or equal to zero.*)\nLemma sqrtr_eq0 a : (sqrt a == 0) = (a <= 0).\n\n(*This lemma states that the square root of a real number is strictly positive if and only if the number itself is strictly positive.*)\nLemma sqrtr_gt0 a : (0 < sqrt a) = (0 < a).\n\n(*This lemma states that for any two non-negative real numbers, their square roots are equal if and only if the numbers themselves are equal.*)\nLemma eqr_sqrt a b : 0 <= a -> 0 <= b -> (sqrt a == sqrt b) = (a == b).\n\n(*This lemma states that the square root function for real numbers is monotonic, meaning that if one real number is less than or equal to another, its square root will also be less than or equal to the other's square root.*)\nLemma ler_wsqrtr : {homo @sqrt R : a b / a <= b}.\n\n(*This lemma states that the square root function is monotonic when restricted to the domain of non-negative real numbers.*)\nLemma ler_psqrt : {in @nneg R &, {mono sqrt : a b / a <= b}}.\n\n(*This lemma states that for any real number and any non-negative real number, the square root of the first is less than or equal to the square root of the second if and only if the first number is less than or equal to the second.*)\nLemma ler_sqrt a b : 0 <= b -> (sqrt a <= sqrt b) = (a <= b).\n\n(*This lemma states that for any real number and any strictly positive real number, the square root of the first is strictly less than the square root of the second if and only if the first number is strictly less than the second.*)\nLemma ltr_sqrt a b : 0 < b -> (sqrt a < sqrt b) = (a < b).\n\n(*This lemma states that for any non-negative real number, the square root of its multiplicative inverse is equal to the multiplicative inverse of its square root.*)\nLemma sqrtrV x : 0 <= x -> sqrt (x^-1) = (sqrt x)^-1.\n\nEnd RealClosedFieldTheory.\n\n(*This notation introduces a postfix star operator to represent the complex conjugate of an element in a field with conjugation.*)\nNotation \"z ^*\" := (conj_op z) : ring_scope.\nNotation \"'i\" := imaginary : ring_scope.\n\nSection ClosedFieldTheory.\n\nVariable C : numClosedFieldType.\nImplicit Types a x y z : C.\n\n(*This definition asserts that the squared norm of an element in a closed field is equal to the product of the element and its complex conjugate.*)\nDefinition normCK : forall x, `|x| ^+ 2 = x * x^* := normCK.\n\n(*This definition asserts that the square of the imaginary unit is equal to negative one.*)\nDefinition sqrCi : 'i ^+ 2 = -1 :> C := sqrCi.\n\n(*This lemma states that the product of the imaginary unit with itself equals negative one.*)\nLemma mulCii : 'i * 'i = -1 :> C. \n\n(*This lemma states that the complex conjugation operation is an involution, meaning that applying it twice to any element returns the original element.*)\nLemma conjCK : involutive (@conj_op C).\n\n(*This definition provides a shorthand for the sum of a complex number and its conjugate, which is equivalent to twice its real part.*)\nLet Re2 z := z + z^*.\n(*This definition provides a predicate that is true if and only if the imaginary part of a given complex number is non-negative.*)\nDefinition nnegIm z := (0 <= 'i * (z^* - z)).\n(*This definition specifies a custom comparison relation between two complex numbers, used for selecting a canonical root. The relation holds if the second number having a non-negative imaginary part implies the first number also does, and if twice the real part of the second number is less than or equal to twice the real part of the first.*)\nDefinition argCle y z := nnegIm z ==> nnegIm y && (Re2 z <= Re2 y).\n\n(*This inductive type defines the specification for a canonical nth root of a complex number. It asserts that a given complex number is an nth root of the input and is the canonical choice among all possible nth roots according to a specific argument-based ordering.*)\nVariant rootC_spec n (x : C) : Type :=\n RootCspec (y : C) of if (n > 0)%N then y ^+ n = x else y = 0\n & forall z, (n > 0)%N -> z ^+ n = x -> argCle y z.\n\n(*This fact asserts the existence of a canonical nth root for any complex number and any natural number, satisfying the properties laid out in the root specification.*)\nFact rootC_subproof n x : rootC_spec n x.\n\n(*This definition provides a function that returns the canonical nth root of a complex number by extracting it from the existential proof of its existence.*)\nDefinition nthroot n x := let: RootCspec y _ _ := rootC_subproof n x in y.\n(*This notation provides a syntax for expressing the nth root of a complex number, where n is a natural number.*)\nNotation \"n .-root\" := (nthroot n) : ring_scope.\n(*This notation defines `sqrtC` as an alias for the principal square root operation, which is equivalent to taking the second root.*)\nNotation sqrtC := 2.-root.\n\n(*This fact serves as a typeclass inference lock, likely to prevent ambiguity by fixing the interpretation of the real part of a complex number within a given scope.*)\nFact Re_lock : unit. \n(*This fact provides a lock for the definition of the imaginary part, used to control its unfolding during proofs.*)\nFact Im_lock : unit. \n(*This definition computes the real part of a complex number by taking the average of the number and its complex conjugate.*)\nDefinition Re z := locked_with Re_lock ((z + z^ / 2%:R).\n(*This definition computes the imaginary part of a complex number using the formula where the difference between the conjugate and the number is multiplied by the imaginary unit and then divided by two.*)\nDefinition Im z := locked_with Im_lock ('i * (z^* - z) / 2%:R).\n(**)\nNotation \"'Re z\" := (Re z) : ring_scope.\n(**)\nNotation \"'Im z\" := (Im z) : ring_scope.\n\n(*This lemma states that the real part of a complex number is equal to half the sum of the number and its complex conjugate.*)\nLemma ReE z : 'Re z = (z + z^ / 2%:R. \n(*This lemma states that the imaginary part of a complex number is equal to the product of the imaginary unit and the difference between the complex conjugate and the number, all divided by two.*)\nLemma ImE z : 'Im z = 'i * (z^* - z) / 2%:R.\n\n(*This lemma asserts that the complex number representation of two is not equal to the complex number representation of zero.*)\nLet nz2 : 2 != 0 :> C. \n\n(*This lemma states that the square of the norm of a complex number equals the product of that number and its complex conjugate.*)\nLemma normCKC x : `|x| ^+ 2 = x^* * x. \n\n(*This lemma states that the product of any complex number with its conjugate results in a value that is greater than or equal to zero.*)\nLemma mul_conjC_ge0 x : 0 <= x * x^*.\n\n(*This lemma states that the product of a complex number with its conjugate is strictly greater than zero if and only if the complex number is not zero.*)\nLemma mul_conjC_gt0 x : (0 < x * x^* ) = (x != 0).\n\n(*This lemma states that the product of a complex number with its conjugate is equal to zero if and only if the complex number is zero.*)\nLemma mul_conjC_eq0 x : (x * x^* == 0) = (x == 0).\n\n(*This lemma establishes that a complex number's conjugate is greater than or equal to zero if and only if the original complex number is greater than or equal to zero.*)\nLemma conjC_ge0 x : (0 <= x^* ) = (0 <= x).\n\n(*This lemma states that the complex conjugate of a complex number that was created by embedding a natural number is equal to the original complex number.*)\nLemma conjC_nat n : (n%:R)^* = n%:R :> C. \n(*This lemma states that the complex conjugate of zero is zero.*)\nLemma conjC0 : 0^* = 0 :> C. \n(*This lemma states that the complex conjugate of one is one.*)\nLemma conjC1 : 1^* = 1 :> C. \n(*This lemma states that the complex conjugate of negative one is negative one.*)\nLemma conjCN1 : (- 1)^* = - 1 :> C. \n(*This lemma states that the conjugate of a complex number is zero if and only if the original complex number is zero.*)\nLemma conjC_eq0 x : (x^* == 0) = (x == 0). \n\n(*This lemma states that the multiplicative inverse of a complex number is equal to its conjugate multiplied by the reciprocal of its squared norm.*)\nLemma invC_norm x : x^-1 = `|x| ^- 2 * x^*.\n\n(*This lemma states that a complex number is a real number if and only if it is equal to its own complex conjugate.*)\nLemma CrealE x : (x \\is real) = (x^* == x).\n\n(*This lemma provides a reflection property, establishing that the boolean statement asserting a complex number is equal to its conjugate is equivalent to the proposition that the number is real.*)\nLemma CrealP {x} : reflect (x^* = x) (x \\is real).\n\n(*This lemma states that if a complex number is a real number, then its complex conjugate is equal to itself.*)\nLemma conj_Creal x : x \\is real -> x^* = x.\n\n(*This lemma states that the norm of any complex number is a real number, meaning its complex conjugate is equal to itself.*)\nLemma conj_normC z : `|z|^* = `|z|.\n\n(*This lemma states that the complex conjugation function, when restricted to the domain of real numbers, acts as the identity function.*)\nLemma CrealJ : {mono (@conj_op C) : x / x \\is Num.real}.\n\n(*This lemma states that if a complex number is greater than or equal to zero, then it must be equal to its own complex conjugate.*)\nLemma geC0_conj x : 0 <= x -> x^* = x.\n\n(*This lemma states that for any non-negative complex number and any positive natural number exponent, if the complex number raised to that exponent equals one, then the complex number itself must be one.*)\nLemma geC0_unit_exp x n : 0 <= x -> (x ^+ n.+1 == 1) = (x == 1).\n\n(*This tactic provides a method for reasoning about nth roots of complex numbers by unfolding the definition of the nth root and performing a case analysis on its underlying proof structure.*)\nLtac case_rootC := rewrite /nthroot; case: (rootC_subproof _ _).\n\n(*This lemma states that the zeroth root of any complex number is defined to be zero.*)\nLemma root0C x : 0.-root x = 0. \n\n(*This lemma states that for any positive natural number, the nth root operation and the nth power operation are inverses of each other, meaning taking the nth root of a number raised to the nth power returns the original number.*)\nLemma rootCK n : (n > 0)%N -> cancel n.-root (fun x => x ^+ n).\n\n(*This lemma states that the first root of any complex number is the number itself.*)\nLemma root1C x : 1.-root x = x. \n\n(*This lemma states that for any natural number, the corresponding root of the complex number zero is equal to the complex number zero.*)\nLemma rootC0 n : n.-root 0 = 0.\n\n(*This lemma states that for any positive natural number, the corresponding root function on complex numbers is injective, meaning that distinct complex numbers have distinct roots.*)\nLemma rootC_inj n : (n > 0)%N -> injective n.-root.\n\n(*This lemma states that for any positive natural number, the corresponding root function on complex numbers reflects equality, meaning the boolean equality of the roots of two complex numbers is equivalent to the boolean equality of the numbers themselves.*)\nLemma eqr_rootC n : (n > 0)%N -> {mono n.-root : x y / x == y}.\n\n(*This lemma states that for any positive natural number and any complex number, the boolean statement that the corresponding root of the complex number is zero is equivalent to the boolean statement that the complex number itself is zero.*)\nLemma rootC_eq0 n x : (n > 0)%N -> (n.-root x == 0) = (x == 0).\n\n(*This lemma states that the imaginary unit is not a real number.*)\nLemma nonRealCi : ('i : C) \\isn't real.\n\n(*This lemma states that the imaginary unit is not equal to the complex number zero.*)\nLemma neq0Ci : 'i != 0 :> C. \n\n(*This lemma states that the norm of the imaginary unit is equal to one.*)\nLemma normCi : `|'i| = 1 :> C.\n\n(*This lemma states that the multiplicative inverse of the imaginary unit is equal to the additive inverse of the imaginary unit.*)\nLemma invCi : 'i^-1 = - 'i :> C.\n\n(*This lemma states that the complex conjugate of the imaginary unit is equal to its additive inverse.*)\nLemma conjCi : 'i^* = - 'i :> C.\n\n(*This lemma states that any complex number is equal to the sum of its real part and the product of the imaginary unit with its imaginary part.*)\nLemma Crect x : x = 'Re x + 'i * 'Im x.\n\n(*This lemma states that two complex numbers are equal if and only if their respective real parts are equal and their respective imaginary parts are equal.*)\nLemma eqCP x y : x = y <-> ('Re x = 'Re y) /\\ ('Im x = 'Im y).\n\n(*This lemma states that the boolean equality of two complex numbers is equivalent to the logical conjunction of the boolean equality of their real parts and the boolean equality of their imaginary parts.*)\nLemma eqC x y : (x == y) = ('Re x == 'Re y) && ('Im x == 'Im y).\n\n(*This lemma states that the real part of any complex number is a real number.*)\nLemma Creal_Re x : 'Re x \\is real.\n\n(*This lemma states that the imaginary part of any complex number is a real number.*)\nLemma Creal_Im x : 'Im x \\is real.\n\nHint Resolve Creal_Re Creal_Im : core.\n\n(*This fact states that the function that takes the real part of a complex number is a Z-module morphism, meaning it preserves addition and the zero element.*)\nFact Re_is_zmod_morphism : zmod_morphism Re.\n\n#[export]\nHB.instance Definition _ := GRing.isZmodMorphism.Build C C Re Re_is_zmod_morphism.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `Re_is_zmod_morphism` instead\")]\n(*This definition provides a deprecated alias for the fact that the real part function is a Z-module morphism.*)\nDefinition Re_is_additive := Re_is_zmod_morphism.\n\n(*This fact states that the function that takes the imaginary part of a complex number is a Z-module morphism, meaning it preserves addition and the zero element.*)\nFact Im_is_zmod_morphism : zmod_morphism Im.\n\n#[export]\n(*This definition provides a deprecated alias for the fact that the imaginary part function is a Z-module morphism.*)\nDefinition Im_is_additive := Im_is_zmod_morphism.\n\n(*This lemma provides a reflection, stating that a complex number is a real number if and only if its imaginary part is equal to zero.*)\nLemma Creal_ImP z : reflect ('Im z = 0) (z \\is real).\n\n(*This lemma provides a reflection, stating that a complex number is a real number if and only if its real part is equal to the number itself.*)\nLemma Creal_ReP z : reflect ('Re z = z) (z \\in real).\n\n(*This lemma states that for any real number, the real part function acts as a morphism with respect to left multiplication by that real number.*)\nLemma ReMl : {in real, forall x, {morph Re : z / x * z}}.\n\n(*This lemma states that for any real number, the real part function acts as a morphism with respect to right multiplication by that real number.*)\nLemma ReMr : {in real, forall x, {morph Re : z / z * x}}.\n\n(*This lemma states that for any real number, the imaginary part function acts as a morphism with respect to left multiplication by that real number.*)\nLemma ImMl : {in real, forall x, {morph Im : z / x * z}}.\n\n(*This lemma states that for any real number, the imaginary part function acts as a morphism with respect to right multiplication by that real number.*)\nLemma ImMr : {in real, forall x, {morph Im : z / z * x}}.\n\n(*This lemma states that the real part of the imaginary unit is equal to zero.*)\nLemma Re_i : 'Re 'i = 0. \n\n(*This lemma states that the imaginary part of the imaginary unit is equal to one.*)\nLemma Im_i : 'Im 'i = 1.\n\n(*This lemma states that the real part of the conjugate of a complex number is equal to the real part of the original complex number.*)\nLemma Re_conj z : 'Re z^* = 'Re z.\n\n(*This lemma states that the imaginary part of the conjugate of a complex number is equal to the additive inverse of the imaginary part of the original complex number.*)\nLemma Im_conj z : 'Im z^* = - 'Im z.\n\n(*This lemma states that for any two real numbers, the real part of the complex number constructed by summing the first real number with the product of the imaginary unit and the second real number is equal to the first real number.*)\nLemma Re_rect : {in real &, forall x y, 'Re (x + 'i * y) = x}.\n\n(*This lemma states that for any two real numbers, the imaginary part of the complex number constructed by summing the first real number with the product of the imaginary unit and the second real number is equal to the second real number.*)\nLemma Im_rect : {in real &, forall x y, 'Im (x + 'i * y) = y}.\n\n(*This lemma states that for any two real numbers, the conjugate of the complex number formed with the first number as the real part and the second number as the imaginary part is a complex number with the same real part and the negated imaginary part.*)\nLemma conjC_rect : {in real &, forall x y, (x + 'i * y)^* = x - 'i * y}.\n\n(*This lemma states that the sum of two complex numbers, given in rectangular form, is a complex number whose real part is the sum of the real parts of the summands and whose imaginary part is the sum of their imaginary parts.*)\nLemma addC_rect x1 y1 x2 y2 :\n (x1 + 'i * y1) + (x2 + 'i * y2) = x1 + x2 + 'i * (y1 + y2).\n\n(*This lemma states that the additive inverse of a complex number given in rectangular form is a complex number whose real and imaginary parts are the additive inverses of the original real and imaginary parts, respectively.*)\nLemma oppC_rect x y : - (x + 'i * y) = - x + 'i * (- y).\n\n(*This lemma states that the difference of two complex numbers given in rectangular form is a new complex number whose real part is the difference of the original real parts and whose imaginary part is the difference of the original imaginary parts.*)\nLemma subC_rect x1 y1 x2 y2 :\n (x1 + 'i * y1) - (x2 + 'i * y2) = x1 - x2 + 'i * (y1 - y2).\n\n(*This lemma states that the product of two complex numbers, given in rectangular form, has a real part equal to the product of their real parts minus the product of their imaginary parts, and an imaginary part equal to the sum of the cross-products of the real and imaginary parts.*)\nLemma mulC_rect x1 y1 x2 y2 : (x1 + 'i * y1) * (x2 + 'i * y2) =\n x1 * x2 - y1 * y2 + 'i * (x1 * y2 + x2 * y1).\n\n(*This lemma states that the imaginary part of the product of two complex numbers is equal to the sum of the product of the first number's real part and the second's imaginary part, and the product of the second number's real part and the first's imaginary part.*)\nLemma ImM x y : 'Im (x * y) = 'Re x * 'Im y + 'Re y * 'Im x.\n\n(*This lemma states that the imaginary part of the product of the imaginary unit and a complex number is equal to the real part of that complex number.*)\nLemma ImMil x : 'Im ('i * x) = 'Re x.\n\n(*This lemma states that the real part of the product of the imaginary unit and a complex number is equal to the additive inverse of the imaginary part of that complex number.*)\nLemma ReMil x : 'Re ('i * x) = - 'Im x.\n\n(*This lemma states that the real part of the product of a complex number and the imaginary unit is equal to the additive inverse of the imaginary part of that complex number.*)\nLemma ReMir x : 'Re (x * 'i) = - 'Im x. \n\n(*This lemma states that the imaginary part of the product of a complex number and the imaginary unit is equal to the real part of that complex number.*)\nLemma ImMir x : 'Im (x * 'i) = 'Re x. \n\n(*This lemma states that the real part of the product of two complex numbers is the product of their real parts minus the product of their imaginary parts.*)\nLemma ReM x y : 'Re (x * y) = 'Re x * 'Re y - 'Im x * 'Im y.\n\n(*This lemma states that for any two real numbers, the squared norm of the complex number they form is equal to the sum of their squares.*)\nLemma normC2_rect :\n {in real &, forall x y, `|x + 'i * y| ^+ 2 = x ^+ 2 + y ^+ 2}.\n\n(*This lemma states that the squared norm of any complex number is equal to the sum of the square of its real part and the square of its imaginary part.*)\nLemma normC2_Re_Im z : `|z| ^+ 2 = 'Re z ^+ 2 + 'Im z ^+ 2.\n\n(*This lemma states a formula for the multiplicative inverse of a complex number constructed from two elements from a ring with conjugation, expressing it as the quotient of a complex number formed from the conjugates of those elements and the squared norm of the original complex number.*)\nLemma invC_Crect x y : (x + 'i * y)^-1 = (x^* - 'i * y^ / `|x + 'i * y| ^+ 2.\n\n(*This lemma states that for any two real numbers, the multiplicative inverse of the complex number they form is equal to the quotient of its conjugate and the sum of the squares of its real and imaginary parts.*)\nLemma invC_rect :\n {in real &, forall x y, (x + 'i * y)^-1 = (x - 'i * y) / (x ^+ 2 + y ^+ 2)}.\n\n(*This lemma states that the imaginary part of the multiplicative inverse of a complex number is equal to the additive inverse of its original imaginary part divided by its squared norm.*)\nLemma ImV x : 'Im x^-1 = - 'Im x / `|x| ^+ 2.\n\n(*This lemma states that the real part of the multiplicative inverse of a complex number is equal to its original real part divided by its squared norm.*)\nLemma ReV x : 'Re x^-1 = 'Re x / `|x| ^+ 2.\n\n(*This lemma states that multiplying a complex number in rectangular form by a scalar on the right results in a new complex number where both the original real and imaginary parts have been multiplied by that scalar.*)\nLemma rectC_mulr x y z : (x + 'i * y) * z = x * z + 'i * (y * z).\n\n(*This lemma states that multiplying a scalar by a complex number in rectangular form on the left results in a new complex number where both the original real and imaginary parts have been multiplied by that scalar.*)\nLemma rectC_mull x y z : z * (x + 'i * y) = z * x + 'i * (z * y).\n\n(*This lemma states a general formula for the division of two complex numbers constructed from pairs of elements from a ring with conjugation, expressing the result in terms of the conjugates of the components of the divisor and the squared norm of the divisor.*)\nLemma divC_Crect x1 y1 x2 y2 :\n (x1 + 'i * y1) / (x2 + 'i * y2) =\n (x1 * x2^* + y1 * y2^* + 'i * (x2^* * y1 - x1 * y2^) /\n `|x2 + 'i * y2| ^+ 2.\n\n(*This lemma states that for four real numbers, the quotient of the two complex numbers formed from them is a complex number whose real part is the sum of the product of the first and third numbers and the product of the second and fourth numbers, all divided by the sum of squares of the third and fourth numbers, and whose imaginary part is the difference of the product of the third and second numbers and the product of the first and fourth numbers, all divided by the same sum of squares.*)\nLemma divC_rect x1 y1 x2 y2 :\n x1 \\is real -> y1 \\is real -> x2 \\is real -> y2 \\is real ->\n (x1 + 'i * y1) / (x2 + 'i * y2) =\n (x1 * x2 + y1 * y2 + 'i * (x2 * y1 - x1 * y2)) /\n (x2 ^+ 2 + y2 ^+ 2).\n\n(*This lemma states that the imaginary part of the quotient of two complex numbers is the difference between the product of the divisor's real part and the dividend's imaginary part, and the product of the dividend's real part and the divisor's imaginary part, all divided by the squared norm of the divisor.*)\nLemma Im_div x y : 'Im (x / y) = ('Re y * 'Im x - 'Re x * 'Im y) / `|y| ^+ 2.\n\n(*This lemma states that the real part of the quotient of two complex numbers is the sum of the product of their real parts and the product of their imaginary parts, all divided by the squared norm of the divisor.*)\nLemma Re_div x y : 'Re (x / y) = ('Re x * 'Re y + 'Im x * 'Im y) / `|y| ^+ 2.\n\n(*This lemma states that the absolute value of the real part of a complex number is always less than or equal to its norm, and that equality holds precisely when the complex number is a real number.*)\nLemma leif_normC_Re_Creal z : `|'Re z| <= `|z| ?= iff (z \\is real).\n\n(*This lemma states that the real part of a complex number is always less than or equal to its norm, and that equality holds precisely when the complex number is a non-negative real number.*)\nLemma leif_Re_Creal z : 'Re z <= `|z| ?= iff (0 <= z).\n\n(*This lemma states that two complex numbers are equal if they have the same norm, the same real part, and the product of their imaginary parts is non-negative.*)\nLemma eqC_semipolar x y :\n `|x| = `|y| -> 'Re x = 'Re y -> 0 <= 'Im x * 'Im y -> x = y.\n\n(*This lemma establishes a logical equivalence between a boolean predicate on two complex numbers and a propositional statement. The proposition asserts that if the second complex number has a non-negative imaginary part, then the first complex number must also have a non-negative imaginary part and the real part of the second must be less than or equal to the real part of the first.*)\nLet argCleP y z :\n reflect (0 <= 'Im z -> 0 <= 'Im y /\\ 'Re z <= 'Re y) (argCle y z).\n\n(*This lemma states that for a positive integer index, the function that maps a real number to the real part of its principal complex root of that index is non-decreasing.*)\nLemma rootC_Re_max n x y :\n (n > 0)%N -> y ^+ n = x -> 0 <= 'Im y -> 'Re y <= 'Re (n.-root x).\n\n(*This lemma states that for any natural number greater than one, there exists a complex number that is an nth root of unity and has a negative real part.*)\nLet neg_unity_root n : (n > 1)%N -> exists2 w : C, w ^+ n = 1 & 'Re w < 0.\n\n(*This lemma states that for any natural number greater than one and any complex number, the imaginary part of the principal nth root of that complex number is greater than or equal to zero.*)\nLemma Im_rootC_ge0 n x : (n > 1)%N -> 0 <= 'Im (n.-root x).\n\n(*This lemma states that for any natural number greater than one and any complex number, the principal nth root of that complex number cannot be a negative real number.*)\nLemma rootC_lt0 n x : (1 < n)%N -> (n.-root x < 0) = false.\n\n(*This lemma states that for any positive natural number and any complex number, the principal nth root of the complex number is a non-negative real number if and only if the complex number itself is a non-negative real number.*)\nLemma rootC_ge0 n x : (n > 0)%N -> (0 <= n.-root x) = (0 <= x).\n\n(*This lemma states that for any positive natural number and any complex number, the principal nth root of the complex number is a positive real number if and only if the complex number itself is a positive real number.*)\nLemma rootC_gt0 n x : (n > 0)%N -> (n.-root x > 0) = (x > 0).\n\n(*This lemma states that for any natural number greater than one and any complex number, the principal nth root of the complex number is a non-positive real number if and only if the complex number is zero.*)\nLemma rootC_le0 n x : (1 < n)%N -> (n.-root x <= 0) = (x == 0).\n\n(*This lemma states that for any positive natural number, the principal nth root function is non-decreasing when applied to non-negative real numbers.*)\nLemma ler_rootCl n : (n > 0)%N -> {in Num.nneg, {mono n.-root : x y / x <= y}}.\n\n(*This lemma states that for any positive natural number, the principal nth root function is non-decreasing over the set of non-negative real numbers.*)\nLemma ler_rootC n : (n > 0)%N -> {in Num.nneg &, {mono n.-root : x y / x <= y}}.\n\n(*This lemma states that for any positive natural number, the principal nth root function is strictly increasing when applied to non-negative real numbers.*)\nLemma ltr_rootCl n : (n > 0)%N -> {in Num.nneg, {mono n.-root : x y / x < y}}.\n\n(*This lemma states that for any positive natural number, the principal nth root function is strictly increasing over the set of non-negative real numbers.*)\nLemma ltr_rootC n : (n > 0)%N -> {in Num.nneg &, {mono n.-root : x y / x < y}}.\n\n(*This lemma states that for any positive natural number and any non-negative real number, the principal nth root of the number raised to the nth power is equal to the original number.*)\nLemma exprCK n x : (0 < n)%N -> 0 <= x -> n.-root (x ^+ n) = x.\n\n(*This lemma states that for any natural number and any complex number, the norm of the principal nth root of the complex number is equal to the principal nth root of the norm of that complex number.*)\nLemma norm_rootC n x : `|n.-root x| = n.-root `|x|.\n\n(*This lemma states that for any positive natural number, any non-negative real number, and any integer exponent, the principal nth root of the real number raised to the exponent is equal to the principal nth root of the real number, which is then raised to the same exponent.*)\nLemma rootCX n x k : (n > 0)%N -> 0 <= x -> n.-root (x ^+ k) = n.-root x ^+ k.\n\n(*This lemma states that for any positive natural number, the principal nth root of one is one.*)\nLemma rootC1 n : (n > 0)%N -> n.-root 1 = 1.\n\n(*This lemma states that for a positive natural number exponent and a non-negative real number, taking the principal nth root of the number raised to that exponent is equivalent to first taking the principal nth root of the number and then raising the result to that same exponent.*)\nLemma rootCpX n x k : (k > 0)%N -> 0 <= x -> n.-root (x ^+ k) = n.-root x ^+ k.\n\n(*This lemma states that for any non-negative real number, the principal nth root of its multiplicative inverse is equal to the multiplicative inverse of its principal nth root.*)\nLemma rootCV n x : 0 <= x -> n.-root x^-1 = (n.-root x)^-1.\n\n(*This lemma states that for any positive natural number and any complex number, the principal nth root of the complex number is equal to one if and only if the complex number itself is equal to one.*)\nLemma rootC_eq1 n x : (n > 0)%N -> (n.-root x == 1) = (x == 1).\n\n(*This lemma states that for any positive natural number and any complex number, the principal nth root of the complex number is a real number greater than or equal to one if and only if the complex number itself is a real number greater than or equal to one.*)\nLemma rootC_ge1 n x : (n > 0)%N -> (n.-root x >= 1) = (x >= 1).\n\n(*This lemma states that for any positive natural number and any complex number, the principal nth root of the complex number is a real number greater than one if and only if the complex number itself is a real number greater than one.*)\nLemma rootC_gt1 n x : (n > 0)%N -> (n.-root x > 1) = (x > 1).\n\n(*This lemma states that for any positive natural number and any non-negative real number, its principal nth root is less than or equal to one if and only if the number itself is less than or equal to one.*)\nLemma rootC_le1 n x : (n > 0)%N -> 0 <= x -> (n.-root x <= 1) = (x <= 1).\n\n(*This lemma states that for any positive natural number and any non-negative real number, its principal nth root is less than one if and only if the number itself is less than one.*)\nLemma rootC_lt1 n x : (n > 0)%N -> 0 <= x -> (n.-root x < 1) = (x < 1).\n\n(*This lemma states that for any two non-negative real numbers, the principal nth root of their product is equal to the product of their individual principal nth roots.*)\nLemma rootCMl n x z : 0 <= x -> n.-root (x * z) = n.-root x * n.-root z.\n\n(*This lemma states that for any two non-negative real numbers, the principal nth root of their product, taken in either order, is equal to the product of their principal nth roots.*)\nLemma rootCMr n x z : 0 <= x -> n.-root (z * x) = n.-root z * n.-root x.\n\n(*This lemma states that the imaginary unit is equal to the principal square root of negative one.*)\nLemma imaginaryCE : 'i = sqrtC (-1).\n\n(*This lemma states the inequality of arithmetic and geometric means: for any finite collection of non-negative real numbers, the nth root of their product is less than or equal to their arithmetic mean, where n is the number of elements in the collection. Furthermore, equality holds if and only if all the numbers in the collection are equal.*)\nLemma leif_rootC_AGM (I : finType) (A : {pred I}) (n := #|A|) E :\n {in A, forall i, 0 <= E i} ->\n n.-root (\\prod_(i in A) E i) <= (\\sum_(i in A) E i) / n%:R\n ?= iff [forall i in A, forall j in A, E i == E j].\n\n(*This lemma states that the principal square root of zero is zero.*)\nLemma sqrtC0 : sqrtC 0 = 0. \n(*This lemma states that the principal square root of one is one.*)\nLemma sqrtC1 : sqrtC 1 = 1. \n(*This lemma states that for any complex number, squaring its principal square root returns the original number.*)\nLemma sqrtCK x : sqrtC x ^+ 2 = x. \n(*This lemma states that for any non-negative real number, the principal square root of its square is equal to the original number.*)\nLemma sqrCK x : 0 <= x -> sqrtC (x ^+ 2) = x. \n\n(*This lemma states that the complex square root of a complex number is greater than or equal to zero if and only if the number itself is greater than or equal to zero.*)\nLemma sqrtC_ge0 x : (0 <= sqrtC x) = (0 <= x). \n(*This lemma states that the complex square root of a complex number is equal to zero if and only if the number itself is equal to zero.*)\nLemma sqrtC_eq0 x : (sqrtC x == 0) = (x == 0). \n(*This lemma states that the complex square root of a complex number is strictly greater than zero if and only if the number itself is strictly greater than zero.*)\nLemma sqrtC_gt0 x : (sqrtC x > 0) = (x > 0). \n(*This lemma states that the proposition 'the complex square root of a complex number is strictly less than zero' is always false.*)\nLemma sqrtC_lt0 x : (sqrtC x < 0) = false. \n(*This lemma states that the complex square root of a complex number is less than or equal to zero if and only if the number itself is equal to zero.*)\nLemma sqrtC_le0 x : (sqrtC x <= 0) = (x == 0). \n\n(*This lemma states that the complex square root function is monotonic over non-negative numbers, meaning that for any two non-negative numbers, if the first is less than or equal to the second, then the square root of the first is less than or equal to the square root of the second.*)\nLemma ler_sqrtC : {in Num.nneg &, {mono sqrtC : x y / x <= y}}.\n\n(*This lemma states that the complex square root function is strictly monotonic over non-negative numbers, meaning that for any two non-negative numbers, if the first is strictly less than the second, then the square root of the first is strictly less than the square root of the second.*)\nLemma ltr_sqrtC : {in Num.nneg &, {mono sqrtC : x y / x < y}}.\n\n(*This lemma states that the complex square root function preserves equality, meaning that if two complex numbers are equal, their complex square roots are also equal.*)\nLemma eqr_sqrtC : {mono sqrtC : x y / x == y}.\n\n(*This lemma states that the complex square root function is injective, meaning that distinct complex numbers map to distinct complex square roots.*)\nLemma sqrtC_inj : injective sqrtC.\n\n(*This lemma establishes that for non-negative numbers, the complex square root function is a multiplicative morphism, meaning the square root of a product of two numbers is equal to the product of their square roots.*)\nLemma sqrtCM : {in Num.nneg &, {morph sqrtC : x y / x * y}}.\n\n(*This lemma states that if a complex number is greater than or equal to zero, its complex square root is a real number.*)\nLemma sqrtC_real x : 0 <= x -> sqrtC x \\in Num.real.\n\n(*This lemma states that the complex square root of the square of a complex number simplifies to the original number if and only if the imaginary part of the number is non-negative and it is not a strictly negative real number.*)\nLemma sqrCK_P x : reflect (sqrtC (x ^+ 2) = x) ((0 <= 'Im x) && ~~ (x < 0)).\n\n(*This lemma defines the norm of a complex number as the complex square root of the product of the number and its complex conjugate.*)\nLemma normC_def x : `|x| = sqrtC (x * x^* ).\n\n(*This lemma states that the norm of the complex conjugate of a complex number is equal to the norm of the original number.*)\nLemma norm_conjC x : `|x^*| = `|x|.\n\n(*This lemma states that for any two real numbers, the norm of the complex number formed by them is equal to the complex square root of the sum of their squares.*)\nLemma normC_rect :\n {in real &, forall x y, `|x + 'i * y| = sqrtC (x ^+ 2 + y ^+ 2)}.\n\n(*This lemma states that the norm of a complex number is equal to the complex square root of the sum of the squares of its real and imaginary parts.*)\nLemma normC_Re_Im z : `|z| = sqrtC ('Re z ^+ 2 + 'Im z ^+ 2).\n\n(*This lemma states that if the norm of the sum of two complex numbers equals the sum of their individual norms, then there exists a complex number of unit norm such that both original numbers can be expressed as their respective norms multiplied by this unit-norm number.*)\nLemma normCDeq x y :\n `|x + y| = `|x| + `|y| ->\n {t : C | `|t| == 1 & (x, y) = (`|x| * t, `|y| * t)}.\n\n(*This lemma states that if the norm of a finite sum of complex numbers equals the sum of their individual norms, then there exists a single complex number of unit norm such that each term in the sum is the product of its own norm and this common unit-norm number.*)\nLemma normC_sum_eq (I : finType) (P : pred I) (F : I -> C) :\n `|\\sum_(i | P i) F i| = \\sum_(i | P i) `|F i| ->\n {t : C | `|t| == 1 & forall i, P i -> F i = `|F i| * t}.\n\n(*This lemma states that if the norm of a finite sum of complex numbers equals the sum of their individual norms, and each number in the sum has a norm of one, then all numbers in the sum must be equal to a single common complex number, which also has a norm of one.*)\nLemma normC_sum_eq1 (I : finType) (P : pred I) (F : I -> C) :\n `|\\sum_(i | P i) F i| = (\\sum_(i | P i) `|F i|) ->\n (forall i, P i -> `|F i| = 1) ->\n {t : C | `|t| == 1 & forall i, P i -> F i = t}.\n\n(*This lemma states that given two indexed collections of complex numbers over a finite domain, if the norm of each number in the first collection is less than or equal to the corresponding number in the second collection, and if the sum of all numbers in the first collection equals the sum of all numbers in the second, then each number in the first collection must be equal to its corresponding number in the second.*)\nLemma normC_sum_upper (I : finType) (P : pred I) (F G : I -> C) :\n (forall i, P i -> `|F i| <= G i) ->\n \\sum_(i | P i) F i = \\sum_(i | P i) G i ->\n forall i, P i -> F i = G i.\n\n(*This lemma states that if the norm of the difference of two complex numbers equals the difference of their individual norms, then there exists a complex number of unit norm such that both original numbers can be expressed as their respective norms multiplied by this unit-norm number.*)\nLemma normCBeq x y :\n `|x - y| = `|x| - `|y| -> {t | `|t| == 1 & (x, y) = (`|x| * t, `|y| * t)}.\n\nEnd ClosedFieldTheory.\n\n(*This notation defines `n .-root` as the function that computes the principal nth root of a complex number, where `n` is a natural number.*)\nNotation \"n .-root\" := (@nthroot _ n).\n(*This definition provides a shorthand for the canonical second root, or principal square root, of a complex number.*)\nNotation sqrtC := 2.-root.\n(*A notation for the imaginary unit, which is the complex number whose square is equal to negative one.*)\nNotation \"'i\" := imaginary : ring_scope.\n(*A notation for the real part of a given complex number.*)\nNotation \"'Re z\" := (Re z) : ring_scope.\n(*A notation for the imaginary part of a given complex number.*)\nNotation \"'Im z\" := (Im z) : ring_scope.\n\nArguments conjCK {C} x.\nArguments sqrCK {C} [x] le0x.\nArguments sqrCK_P {C x}.\n\n#[global] Hint Extern 0 (is_true (in_mem ('Re _) _)) =>\n solve [apply: Creal_Re] : core.\n#[global] Hint Extern 0 (is_true (in_mem ('Im _) _)) =>\n solve [apply: Creal_Im] : core.\n\nModule Export Pdeg2.\n\nModule NumClosed.\n\nSection Pdeg2NumClosed.\n\nVariables (F : numClosedFieldType) (p : {poly F}).\n\nHypothesis degp : size p = 3.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This definition represents one of the two roots of a degree-two polynomial, computed using the quadratic formula by taking the negation of the linear coefficient, subtracting the square root of the discriminant, and dividing the result by twice the leading coefficient.*)\nLet r1 := (- b - sqrtC delta) / (2 * a).\n(*This definition represents the second of two roots of a degree-two polynomial, computed using the quadratic formula by taking the negation of the linear coefficient, adding the square root of the discriminant, and dividing the result by twice the leading coefficient.*)\nLet r2 := (- b + sqrtC delta) / (2 * a).\n\n(*This lemma states that any degree-two polynomial over a numerically closed field can be factored into the product of its leading coefficient and two linear polynomials, where each linear polynomial is the result of subtracting a root from the polynomial's indeterminate.*)\nLemma deg2_poly_factor : p = a *: ('X - r1%:P) * ('X - r2%:P).\n\n(*This lemma states that if the discriminant `delta` of the polynomial `p` is non-negative, then the value `r1` is a root of `p`.*)\nLemma deg2_poly_root1 : root p r1.\n\n(*This lemma states that if the discriminant `delta` of the polynomial `p` is non-negative, then the value `r2` is a root of `p`.*)\nLemma deg2_poly_root2 : root p r2.\n\nEnd Pdeg2NumClosed.\n\nEnd NumClosed.\n\nModule NumClosedMonic.\n\nExport FieldMonic.\n\nSection Pdeg2NumClosedMonic.\n\nVariables (F : numClosedFieldType) (p : {poly F}).\n\nHypothesis degp : size p = 3.\nHypothesis monicp : p \\is monic.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * c.\n\n(*This definition specifies `r1` as a root of a monic quadratic polynomial over a numerically closed field, calculated by subtracting a square root of the discriminant from the negated coefficient of degree one, and then dividing the result by two.*)\nLet r1 := (- b - sqrtC delta) / 2.\n(*This definition specifies `r2` as a root of a monic quadratic polynomial over a numerically closed field, calculated by adding a square root of the discriminant to the negated coefficient of degree one, and then dividing the result by two.*)\nLet r2 := (- b + sqrtC delta) / 2.\n\n(*This lemma states that a monic quadratic polynomial over a numerically closed field factors as the product of two linear polynomials, each obtained by subtracting one of the polynomial's roots from the indeterminate.*)\nLemma deg2_poly_factor : p = ('X - r1%:P) * ('X - r2%:P).\n\n(*This lemma asserts that the first of the two roots calculated by the quadratic formula is a genuine root of a given monic quadratic polynomial over a numerically closed field.*)\nLemma deg2_poly_root1 : root p r1.\n\n(*This lemma asserts that the second of the two roots calculated by the quadratic formula is a genuine root of a given monic quadratic polynomial over a numerically closed field.*)\nLemma deg2_poly_root2 : root p r2.\n\nEnd Pdeg2NumClosedMonic.\nEnd NumClosedMonic.\n\nModule Real.\n\nSection Pdeg2Real.\n\nVariable F : realFieldType.\n\nSection Pdeg2RealConvex.\n\nVariable p : {poly F}.\nHypothesis degp : size p = 3.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\nHypothesis age0 : 0 <= a.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This lemma proves that the polynomial `p` is not the zero polynomial, which is a precondition for being a degree 2 polynomial.*)\nLet pneq0 : p != 0. \n(*This hypothesis asserts that the coefficient `a` of the degree 2 term of the polynomial `p` is not zero.*)\nLet aneq0 : a != 0.\n\n(*This hypothesis asserts that the coefficient `a` of the degree 2 term of the polynomial `p` is strictly positive.*)\nLet agt0 : 0 < a. \n(*This lemma states that four times the leading coefficient `a` is strictly positive, a consequence of `a` being positive.*)\nLet a4gt0 : 0 < 4 * a. \n\n(*This lemma states that for a convex quadratic polynomial, its value at the point defined by the negative of its degree-one coefficient divided by twice its degree-two coefficient is less than or equal to its value at any other point.*)\nLemma deg2_poly_min x : p.[- b / (2 * a)] <= p.[x].\n\n(*This lemma states that the minimum value of a convex quadratic polynomial is equal to the negative of its discriminant divided by the product of four and its degree-two coefficient.*)\nLemma deg2_poly_minE : p.[- b / (2 * a)] = - delta / (4 * a).\n\n(*This lemma establishes an equivalence: a quadratic polynomial with a positive leading coefficient is strictly positive for all inputs if and only if its discriminant is negative.*)\nLemma deg2_poly_gt0 : reflect (forall x, 0 < p.[x]) (delta < 0).\n\n(*This lemma establishes an equivalence: a quadratic polynomial with a positive leading coefficient is non-negative for all inputs if and only if its discriminant is non-positive.*)\nLemma deg2_poly_ge0 : reflect (forall x, 0 <= p.[x]) (delta <= 0).\n\nEnd Pdeg2RealConvex.\n\nSection Pdeg2RealConcave.\n\nVariable p : {poly F}.\nHypothesis degp : size p = 3.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\nHypothesis ale0 : a <= 0.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This lemma states that the size of the additive inverse of the polynomial `p` is 3, implying that the negated polynomial is also of degree 2.*)\nLet degpN : size (- p) = 3. \n(*This lemma states that the horizontal coordinate of the vertex of the parabola associated with the additive inverse of the polynomial p, calculated from its coefficients, is equal to the same coordinate calculated from the coefficients of the original polynomial p.*)\nLet b2a : - (- p)`_1 / (2 * (- p)`_2) = - b / (2 * a).\n\n(*This lemma proves that the discriminant of the additive inverse of a quadratic polynomial `p` is equal to the discriminant of `p`.*)\nLet deltaN : (- p)`_1 ^+ 2 - 4 * (- p)`_2 * (- p)`_0 = delta.\n\n(*This lemma states that for a concave quadratic polynomial p, its value at any point is less than or equal to its value at the vertex.*)\nLemma deg2_poly_max x : p.[x] <= p.[- b / (2 * a)].\n\n(*This lemma states that the maximum value of a concave quadratic polynomial p, achieved at its vertex, is equal to the negation of its discriminant divided by four times its degree-two coefficient.*)\nLemma deg2_poly_maxE : p.[- b / (2 * a)] = - delta / (4 * a).\n\n(*This lemma states that for a concave quadratic polynomial, the property that its value is strictly less than zero for all inputs is equivalent to its discriminant being strictly less than zero.*)\nLemma deg2_poly_lt0 : reflect (forall x, p.[x] < 0) (delta < 0).\n\n(*This lemma states that for a concave quadratic polynomial, the property that its value is less than or equal to zero for all inputs is equivalent to its discriminant being less than or equal to zero.*)\nLemma deg2_poly_le0 : reflect (forall x, p.[x] <= 0) (delta <= 0).\n\nEnd Pdeg2RealConcave.\nEnd Pdeg2Real.\n\nSection Pdeg2RealClosed.\n\nVariable F : rcfType.\n\nSection Pdeg2RealClosedConvex.\n\nVariable p : {poly F}.\nHypothesis degp : size p = 3.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This lemma states that the given degree-two polynomial is not the zero polynomial.*)\nLet pneq0 : p != 0. \n(*This lemma states that the leading coefficient of the given degree-two polynomial is not equal to zero.*)\nLet aneq0 : a != 0.\n\n(*This lemma states that four times the square of the polynomial's leading coefficient is equal to the square of twice that same coefficient.*)\nLet sqa2 : 4 * a ^+ 2 = (2 * a) ^+ 2. \n(*This lemma establishes that the number 2 is not equal to zero in the underlying field, meaning the field's characteristic is not 2.*)\nLet nz2 : 2 != 0 :> F. \n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This definition provides the formula for one of the roots of a quadratic polynomial, identified as `r1`, which is computed by subtracting the square root of the discriminant from the additive inverse of the degree-one coefficient, and then dividing by twice the leading coefficient.*)\nLet r1 := (- b - sqrt delta) / (2 * a).\n(*This definition provides the formula for the other root of a quadratic polynomial, identified as `r2`, which is computed by adding the square root of the discriminant to the additive inverse of the degree-one coefficient, and then dividing by twice the leading coefficient.*)\nLet r2 := (- b + sqrt delta) / (2 * a).\n\n(*This lemma states that if the discriminant of a quadratic polynomial is non-negative, then the polynomial can be factored as the product of its leading coefficient and two linear polynomials corresponding to its two roots.*)\nLemma deg2_poly_factor : 0 <= delta -> p = a *: ('X - r1%:P) * ('X - r2%:P).\n\n(*This lemma states that if the discriminant `delta` of the polynomial `p` is non-negative, then the value `r1` is a root of `p`.*)\nLemma deg2_poly_root1 : 0 <= delta -> root p r1.\n\n(*This lemma states that if the discriminant `delta` of the polynomial `p` is non-negative, then the value `r2` is a root of `p`.*)\nLemma deg2_poly_root2 : 0 <= delta -> root p r2.\n\n(*This lemma establishes an equivalence: a quadratic polynomial `p` has no real roots if and only if its discriminant is negative.*)\nLemma deg2_poly_noroot : reflect (forall x, ~~ root p x) (delta < 0).\n\nHypothesis age0 : 0 <= a.\n\n(*This lemma states that the leading coefficient of the convex quadratic polynomial is strictly greater than zero.*)\nLet agt0 : 0 < a. \n(*This lemma states that twice the leading coefficient of the convex quadratic polynomial is strictly greater than zero.*)\nLet a2gt0 : 0 < 2 * a. \n(*This lemma states that four times the leading coefficient of the convex quadratic polynomial is strictly greater than zero.*)\nLet a4gt0 : 0 < 4 * a. \n(*This lemma states that four times the square of the leading coefficient of the convex quadratic polynomial is strictly greater than zero.*)\nLet aa4gt0 : 0 < 4 * a * a. \n\n(*This lemma states an algebraic identity for an arbitrary field element, which equates a scaled, squared expression involving the polynomial's coefficients with another squared expression, and is used to complete the square.*)\nLet xb4 x : (x + b / (2 * a)) ^+ 2 * (4 * a * a) = (x * (2 * a) + b) ^+ 2.\n\n(*This lemma states that if the leading coefficient is positive, the value of the quadratic polynomial `p` is strictly positive for any input `x` that is strictly less than the smaller root `r1`.*)\nLemma deg2_poly_gt0l x : x < r1 -> 0 < p.[x].\n\n(*This lemma states that if the leading coefficient is positive, the value of the quadratic polynomial `p` is strictly positive for any input `x` that is strictly greater than the larger root `r2`.*)\nLemma deg2_poly_gt0r x : r2 < x -> 0 < p.[x].\n\n(*This lemma states that if the leading coefficient is positive, the value of the quadratic polynomial `p` is strictly negative for any input `x` that is strictly between its two roots `r1` and `r2`.*)\nLemma deg2_poly_lt0m x : r1 < x < r2 -> p.[x] < 0.\n\n(*This lemma states that if the leading coefficient is positive, the value of the quadratic polynomial `p` is non-negative for any input `x` that is less than or equal to the smaller root `r1`.*)\nLemma deg2_poly_ge0l x : x <= r1 -> 0 <= p.[x].\n\n(*This lemma states that if the leading coefficient is positive, the value of the quadratic polynomial `p` is non-negative for any input `x` that is greater than or equal to the larger root `r2`.*)\nLemma deg2_poly_ge0r x : r2 <= x -> 0 <= p.[x].\n\n(*This lemma states that if the discriminant is non-negative and the leading coefficient is positive, the value of the quadratic polynomial `p` is non-positive for any input `x` that is between or equal to its two roots `r1` and `r2`.*)\nLemma deg2_poly_le0m x : 0 <= delta -> r1 <= x <= r2 -> p.[x] <= 0.\n\nEnd Pdeg2RealClosedConvex.\n\nSection Pdeg2RealClosedConcave.\n\nVariable p : {poly F}.\nHypothesis degp : size p = 3.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This definition defines `r1` as a root of a quadratic polynomial with a non-negative discriminant, calculated using the quadratic formula as the sum of the additive inverse of the degree-one coefficient and the square root of the discriminant, all divided by twice the degree-two coefficient.*)\nLet r1 := (- b + sqrt delta) / (2 * a).\n(*This definition defines `r2` as a root of a quadratic polynomial with a non-negative discriminant, calculated using the quadratic formula as the difference of the additive inverse of the degree-one coefficient and the square root of the discriminant, all divided by twice the degree-two coefficient.*)\nLet r2 := (- b - sqrt delta) / (2 * a).\n\nHypothesis ale0 : a <= 0.\n\n(*This lemma states that the size of the additive inverse of the quadratic polynomial p is three.*)\nLet degpN : size (- p) = 3. \n(*This definition provides a proof that the coefficient of degree two of the additive inverse of a concave polynomial `p` is greater than or equal to zero.*)\nLet aNge0 : 0 <= (- p)`_2. \n(*This lemma states that the discriminant of the additive inverse of the quadratic polynomial p is equal to the discriminant of the original polynomial p.*)\nLet deltaN : (- p)`_1 ^+ 2 - 4 * (- p)`_2 * (- p)`_0 = delta.\n\n(*This definition provides a proof that a root of the additive inverse of a polynomial `p`, calculated with the quadratic formula, is equal to the root `r1` of the original polynomial `p`.*)\nLet r1N : (- (- p)`_1 - sqrt delta) / (2 * (- p)`_2) = r1.\n\n(*This definition provides a proof that a root of the additive inverse of a polynomial `p`, calculated with the quadratic formula, is equal to the root `r2` of the original polynomial `p`.*)\nLet r2N : (- (- p)`_1 + sqrt delta) / (2 * (- p)`_2) = r2.\n\n(*This lemma states that for a concave quadratic polynomial with two distinct real roots, any real-valued input strictly less than the smaller root `r1` results in a polynomial value that is strictly less than zero.*)\nLemma deg2_poly_lt0l x : x < r1 -> p.[x] < 0.\n\n(*This lemma states that for a concave quadratic polynomial with two distinct real roots, any real-valued input strictly greater than the larger root `r2` results in a polynomial value that is strictly less than zero.*)\nLemma deg2_poly_lt0r x : r2 < x -> p.[x] < 0.\n\n(*This lemma states that for a concave quadratic polynomial with two distinct real roots, any real-valued input strictly between its two roots `r1` and `r2` results in a polynomial value that is strictly greater than zero.*)\nLemma deg2_poly_gt0m x : r1 < x < r2 -> 0 < p.[x].\n\n(*This lemma states that for a concave quadratic polynomial with at least one real root, any real-valued input less than or equal to the smaller root `r1` results in a polynomial value that is less than or equal to zero.*)\nLemma deg2_poly_le0l x : x <= r1 -> p.[x] <= 0.\n\n(*This lemma states that for a concave quadratic polynomial with at least one real root, any real-valued input greater than or equal to the larger root `r2` results in a polynomial value that is less than or equal to zero.*)\nLemma deg2_poly_le0r x : r2 <= x -> p.[x] <= 0.\n\n(*This lemma states that for a concave quadratic polynomial with a non-negative discriminant, any real-valued input between or equal to its real roots `r1` and `r2` results in a polynomial value that is greater than or equal to zero.*)\nLemma deg2_poly_ge0m x : 0 <= delta -> r1 <= x <= r2 -> 0 <= p.[x].\n\nEnd Pdeg2RealClosedConcave.\nEnd Pdeg2RealClosed.\nEnd Real.\n\nModule RealMonic.\n\nImport Real.\nExport FieldMonic.\n\nSection Pdeg2RealMonic.\n\nVariable F : realFieldType.\n\nVariable p : {poly F}.\nHypothesis degp : size p = 3.\nHypothesis monicp : p \\is monic.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * c.\n\n(*This lemma proves that the leading coefficient `a` of a polynomial `p` is equal to 1, given that `p` is monic.*)\nLet a1 : a = 1. \n(*This proof establishes that two times the leading coefficient of the monic quadratic polynomial is equal to two.*)\nLet a2 : 2 * a = 2. \n(*This proof establishes that four times the leading coefficient of the monic quadratic polynomial is equal to four.*)\nLet a4 : 4 * a = 4. \n\n(*This lemma states that a monic quadratic polynomial achieves its minimum value at the point corresponding to the negative of its degree-one coefficient divided by two.*)\nLemma deg2_poly_min x : p.[- b / 2] <= p.[x].\n\n(*This lemma shows that for a monic polynomial, the simplified discriminant formula is equivalent to the general one, since its leading coefficient is one.*)\nLet deltam : delta = b ^+ 2 - 4 * a * c. \n\n(*This lemma states that the minimum value of a monic quadratic polynomial is equal to the negation of its discriminant divided by four.*)\nLemma deg2_poly_minE : p.[- b / 2] = - delta / 4.\n\n(*This lemma states that a convex quadratic polynomial has a value greater than zero for all inputs if and only if its discriminant is less than zero.*)\nLemma deg2_poly_gt0 : reflect (forall x, 0 < p.[x]) (delta < 0).\n\n(*This lemma states that a convex quadratic polynomial has a value greater than or equal to zero for all inputs if and only if its discriminant is less than or equal to zero.*)\nLemma deg2_poly_ge0 : reflect (forall x, 0 <= p.[x]) (delta <= 0).\n\nEnd Pdeg2RealMonic.\n\nSection Pdeg2RealClosedMonic.\n\nVariables (F : rcfType) (p : {poly F}).\nHypothesis degp : size p = 3.\nHypothesis monicp : p \\is monic.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This proof establishes that the leading coefficient of the monic quadratic polynomial is equal to one.*)\nLet a1 : a = 1. \n\n(*This definition introduces `delta` as the discriminant of a monic quadratic polynomial over a numerically closed field, calculated by subtracting four times the constant term from the square of the coefficient of degree one.*)\nLet delta := b ^+ 2 - 4 * c.\n\n(*This proof establishes that the simplified discriminant, which assumes a leading coefficient of one, is equal to the general formula for the discriminant, which is the square of the degree-one coefficient minus four times the product of the leading and constant coefficients.*)\nLet deltam : delta = b ^+ 2 - 4 * a * c. \n\n(*This definition defines `r1` as one of the roots of a monic quadratic polynomial, calculated as the sum of the additive inverse of the coefficient of degree one and the additive inverse of the square root of the discriminant, all divided by two.*)\nLet r1 := (- b - sqrt delta) / 2.\n(*This definition defines `r2` as one of the roots of a monic quadratic polynomial, calculated as the sum of the additive inverse of the coefficient of degree one and the square root of the discriminant, all divided by two.*)\nLet r2 := (- b + sqrt delta) / 2.\n\n(*This lemma states that the field element corresponding to the number two is not equal to zero.*)\nLet nz2 : 2 != 0 :> F. \n\n(*This lemma states that if the discriminant of a monic quadratic polynomial is non-negative, then the polynomial is equal to the product of two linear polynomials, `X minus r1` and `X minus r2`, where `r1` and `r2` are its roots.*)\nLemma deg2_poly_factor : 0 <= delta -> p = ('X - r1%:P) * ('X - r2%:P).\n\n(*This lemma states that if the discriminant of a quadratic polynomial is non-negative, the value computed using the first root formula is indeed a root of the polynomial.*)\nLemma deg2_poly_root1 : 0 <= delta -> root p r1.\n\n(*This lemma states that if the discriminant of a quadratic polynomial is non-negative, the value computed using the second root formula is indeed a root of the polynomial.*)\nLemma deg2_poly_root2 : 0 <= delta -> root p r2.\n\n(*This lemma states that a quadratic polynomial has no roots if and only if its discriminant is less than zero.*)\nLemma deg2_poly_noroot : reflect (forall x, ~~ root p x) (delta < 0).\n\n(*This lemma states that for a convex quadratic polynomial with real roots, its value is strictly positive for any input value that is less than its smaller root.*)\nLemma deg2_poly_gt0l x : x < r1 -> 0 < p.[x].\n\n(*This lemma states that for a convex quadratic polynomial with real roots, its value is strictly positive for any input value that is greater than its larger root.*)\nLemma deg2_poly_gt0r x : r2 < x -> 0 < p.[x].\n\n(*This lemma states that for a convex quadratic polynomial with real roots, its value is strictly negative for any input value that is strictly between its two roots.*)\nLemma deg2_poly_lt0m x : r1 < x < r2 -> p.[x] < 0.\n\n(*This lemma states that for a convex quadratic polynomial with real roots, its value is non-negative for any input value that is less than or equal to its smaller root.*)\nLemma deg2_poly_ge0l x : x <= r1 -> 0 <= p.[x].\n\n(*This lemma states that for a convex quadratic polynomial with real roots, its value is non-negative for any input value that is greater than or equal to its larger root.*)\nLemma deg2_poly_ge0r x : r2 <= x -> 0 <= p.[x].\n\n(*This lemma states that for a convex quadratic polynomial with a non-negative discriminant, its value is non-positive for any input value that lies between or is equal to its two roots.*)\nLemma deg2_poly_le0m x : 0 <= delta -> r1 <= x <= r2 -> p.[x] <= 0.\n\nEnd Pdeg2RealClosedMonic.\nEnd RealMonic.\nEnd Pdeg2.\n\nSection Degle2PolyRealConvex.\n\nVariable (F : realFieldType) (p : {poly F}).\nHypothesis degp : (size p <= 3)%N.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This lemma states that for a polynomial of at most degree two, if the coefficient of its quadratic term is non-negative and the polynomial evaluates to a non-negative value for all inputs, then the discriminant of the polynomial must be less than or equal to zero.*)\nLemma deg_le2_poly_delta_ge0 : 0 <= a -> (forall x, 0 <= p.[x]) -> delta <= 0.\n\nEnd Degle2PolyRealConvex.\n\nSection Degle2PolyRealConcave.\n\nVariable (F : realFieldType) (p : {poly F}).\nHypothesis degp : (size p <= 3)%N.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This lemma states that for a polynomial of degree at most two, if the coefficient of the degree-two term is non-positive and the polynomial's value is non-positive for all inputs, then its discriminant must be less than or equal to zero.*)\nLemma deg_le2_poly_delta_le0 : a <= 0 -> (forall x, p.[x] <= 0) -> delta <= 0.\n\nEnd Degle2PolyRealConcave.\n\nSection Degle2PolyRealClosedConvex.\n\nVariable (F : rcfType) (p : {poly F}).\nHypothesis degp : (size p <= 3)%N.\n\n(*This definition gives the name `a` to the coefficient of the degree 2 term of a polynomial `p`.*)\nLet a := p`_2.\n(*This definition gives the name `b` to the coefficient of the degree 1 term of a polynomial `p`.*)\nLet b := p`_1.\n(*This definition gives the name `c` to the coefficient of the degree 0 term, or constant term, of a polynomial `p`.*)\nLet c := p`_0.\n\n(*This definition assigns the name `delta` to the discriminant of a quadratic polynomial `p`, calculated as the square of the coefficient of degree 1 minus four times the product of the coefficients of degree 2 and degree 0.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This lemma states that if a polynomial of degree at most two evaluates to a non-negative value for all inputs, then its discriminant must be less than or equal to zero.*)\nLemma deg_le2_poly_ge0 : (forall x, 0 <= p.[x]) -> delta <= 0.\n\nEnd Degle2PolyRealClosedConvex.\n\nSection Degle2PolyRealClosedConcave.\n\nVariable (F : rcfType) (p : {poly F}).\nHypothesis degp : (size p <= 3)%N.\n\n(*This definition assigns the name `a` to the coefficient of degree two of a given degree-two polynomial.*)\nLet a := p`_2.\n(*This definition assigns the name `b` to the coefficient of degree one of a given degree-two polynomial.*)\nLet b := p`_1.\n(*This definition assigns the name `c` to the coefficient of degree zero of a given degree-two polynomial.*)\nLet c := p`_0.\n\n(*This definition defines `delta` as the discriminant of a quadratic polynomial, calculated as the square of the degree-one coefficient minus four times the product of the leading coefficient and the constant term.*)\nLet delta := b ^+ 2 - 4 * a * c.\n\n(*This lemma states that a polynomial of degree at most two is non-positive for all arguments if and only if either its degree-two coefficient is negative and its discriminant is non-positive, or the polynomial itself is a non-positive constant.*)\nLemma deg_le2_poly_le0 : (forall x, p.[x] <= 0) -> delta <= 0.\n\nEnd Degle2PolyRealClosedConcave.\nEnd Theory.\n\nModule Exports. HB.reexport. End Exports.\n\nEnd Num.", - "algebra.num_theory.numdomain": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import ssrAC div fintype path bigop order finset fingroup.\nFrom mathcomp Require Import ssralg poly orderedzmod.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope order_scope.\nLocal Open Scope group_scope.\nLocal Open Scope ring_scope.\n\nImport Order.TTheory GRing.Theory.\nImport orderedzmod.Num.\n\nModule Num.\n\n(*A mixin for a Z-module that equips it with a seminorm. This seminorm maps elements of the module to a partially ordered Z-module and is required to satisfy the triangle inequality, compatibility with integer scalar multiplication, and invariance under additive inversion.*)\nHB.mixin Record Zmodule_isSemiNormed (R : POrderedZmodule.type) M\n of GRing.Zmodule M := {\n norm : M -> R;\n ler_normD : forall x y, norm (x + y) <= norm x + norm y;\n normrMn : forall x n, norm (x *+ n) = norm x *+ n;\n normrN : forall x, norm (- x) = norm x;\n}.\n\n#[short(type=\"semiNormedZmodType\")]\n(*A structure representing a Z-module equipped with a seminorm, which is a function that maps module elements to a partially ordered Z-module and satisfies the triangle inequality.*)\nHB.structure Definition SemiNormedZmodule (R : porderZmodType) :=\n { M of Zmodule_isSemiNormed R M & GRing.Zmodule M }.\n\n(*A mixin for a seminormed Z-module that enforces the positive-definite property. This property promotes the seminorm to a norm by requiring that any element with a seminorm of zero must be the zero element.*)\nHB.mixin Record SemiNormedZmodule_isPositiveDefinite\n (R : POrderedZmodule.type) M of @SemiNormedZmodule R M := {\n normr0_eq0 : forall x : M, norm x = 0 -> x = 0;\n}.\n\n#[short(type=\"normedZmodType\")]\n(*A structure representing a Z-module equipped with a norm. A norm is a seminorm that is also positive-definite, meaning only the zero element has a norm of zero.*)\nHB.structure Definition NormedZmodule (R : porderZmodType) :=\n { M of SemiNormedZmodule_isPositiveDefinite R M & SemiNormedZmodule R M }.\nArguments norm {R M} x : rename.\n\n(*A factory record used to construct a normed Z-module from a Z-module by providing a norm function and proofs of its properties in a single structure. These properties include the triangle inequality, positive-definiteness, compatibility with integer scalar multiplication, and invariance under additive inverse.*)\nHB.factory Record Zmodule_isNormed (R : POrderedZmodule.type) M\n of GRing.Zmodule M := {\n norm : M -> R;\n ler_normD : forall x y, norm (x + y) <= norm x + norm y;\n normr0_eq0 : forall x, norm x = 0 -> x = 0;\n normrMn : forall x n, norm (x *+ n) = norm x *+ n;\n normrN : forall x, norm (- x) = norm x;\n}.\nHB.builders Context (R : POrderedZmodule.type) M of Zmodule_isNormed R M.\n HB.instance Definition _ :=\n Zmodule_isSemiNormed.Build R M ler_normD normrMn normrN.\n HB.instance Definition _ :=\n SemiNormedZmodule_isPositiveDefinite.Build R M normr0_eq0.\nHB.end.\n\nModule NormedZmoduleExports.\nBind Scope ring_scope with NormedZmodule.sort.\n\nEnd NormedZmoduleExports.\nHB.export NormedZmoduleExports.\n\n(*A mixin that specifies the properties of a numerical ring. It requires that the sum of two positive elements is positive, that any two non-negative elements are comparable, that the norm is submultiplicative, and that the order relation is defined in terms of the norm and subtraction.*)\nHB.mixin Record isNumRing R of GRing.NzRing R & POrderedZmodule R\n & NormedZmodule (POrderedZmodule.clone R _) R := {\n addr_gt0 : forall x y : R, 0 < x -> 0 < y -> 0 < (x + y);\n ger_leVge : forall x y : R, 0 <= x -> 0 <= y -> (x <= y) || (y <= x);\n normrM : {morph (norm : R -> R) : x y / x * y};\n ler_def : forall x y : R, (x <= y) = (norm (y - x) == (y - x));\n}.\n\n#[short(type=\"numDomainType\")]\n(*A structure for numerical domains, which are integral domains equipped with a compatible ordered ring structure and a norm. This structure ensures properties such as positivity of sums of positive elements, comparability of non-negative elements, and a norm-based definition of the order.*)\nHB.structure Definition NumDomain := { R of\n GRing.IntegralDomain R &\n POrderedZmodule R &\n NormedZmodule (POrderedZmodule.clone R _) R &\n isNumRing R\n }.\nArguments addr_gt0 {_} [x y] : rename.\nArguments ger_leVge {_} [x y] : rename.\n\nModule NumDomainExports.\nBind Scope ring_scope with NumDomain.sort.\nEnd NumDomainExports.\nHB.export NumDomainExports.\n\nModule Export Def.\n\n(*A notation that provides an alternative name for the norm function.*)\nNotation normr := norm.\n(**)\nNotation \"`| x |\" := (norm x) : ring_scope.\n\nSection NumDomainDef.\nContext {R : numDomainType}.\n\n(*Defines the sign function for an element of a numerical domain. It returns negative one if the input element is less than zero, one if the input element is greater than zero, and zero if the input element is equal to zero.*)\nDefinition sgr (x : R) : R := if x == 0 then 0 else if x < 0 then -1 else 1.\n\nEnd NumDomainDef.\n\nEnd Def.\n\n(*A notation that provides a shorter alternative name for the sign function `sgr`.*)\nNotation sg := sgr.\n\nModule Export Syntax.\n\n(*This notation denotes the norm of an element from a normed algebraic structure, which is a value representing its magnitude, akin to an absolute value.*)\nNotation \"`| x |\" := (norm x) : ring_scope.\n\nEnd Syntax.\n\nSection ExtensionAxioms.\n\nVariable R : numDomainType.\n\n(*This definition specifies an axiom asserting that for any element in an ordered numerical domain, the element is either greater than or equal to zero, or less than or equal to zero.*)\nDefinition real_axiom : Prop := forall x : R, x \\is real.\n\n(*This definition specifies the Archimedean axiom, which asserts that for any element in an ordered numerical domain, there exists a natural number whose value as a ring element is strictly greater than the absolute value of that element.*)\nDefinition archimedean_axiom : Prop := forall x : R, exists ub, `|x| < ub%:R.\n\n(*This definition specifies the real-closed field axiom, which postulates the intermediate value property for polynomials: for any univariate polynomial over the domain, if its value is non-positive at one point and non-negative at another, then there must be a root of the polynomial between those two points.*)\nDefinition real_closed_axiom : Prop :=\n forall (p : {poly R}) (a b : R),\n a <= b -> p.[a] <= 0 <= p.[b] -> exists2 x, a <= x <= b & root p x.\n\nEnd ExtensionAxioms.\n\n#[short(type=\"realDomainType\")]\n(*This structure defines a 'Real Domain', which is a numerical domain that is also equipped with a total order, meaning any two elements within it are comparable.*)\nHB.structure Definition RealDomain :=\n { R of Order.Total ring_display R & NumDomain R }.\n\nModule RealDomainExports.\nBind Scope ring_scope with RealDomain.sort.\nEnd RealDomainExports.\nHB.export RealDomainExports.\n\nModule Import Internals.\n\nSection NumDomain.\nVariable R : numDomainType.\nImplicit Types x y : R.\n\n(*This lemma states that an element is greater than or equal to zero if and only if its absolute value is equal to the element itself.*)\nLemma ger0_def x : (0 <= x) = (`|x| == x).\n\n(*This lemma states that the difference of a first element and a second element is greater than or equal to zero if and only if the second element is less than or equal to the first element.*)\nLemma subr_ge0 x y : (0 <= x - y) = (y <= x).\n\n(*This lemma states that the additive inverse of an element is greater than or equal to zero if and only if the element is less than or equal to zero.*)\nLemma oppr_ge0 x : (0 <= - x) = (x <= 0).\n\n(*This lemma states that zero is less than or equal to one.*)\nLemma ler01 : 0 <= 1 :> R.\n\n(*This lemma states that zero is strictly less than one.*)\nLemma ltr01 : 0 < 1 :> R. \n\n(*This lemma states that an element is greater than or equal to zero if and only if the element is either equal to zero or strictly greater than zero.*)\nLemma le0r x : (0 <= x) = (x == 0) || (0 < x).\n\n(*This lemma states that if two elements are each greater than or equal to zero, their sum is also greater than or equal to zero.*)\nLemma addr_ge0 x y : 0 <= x -> 0 <= y -> 0 <= x + y.\n\n(*This lemma states that for a strictly positive first element, the product of the first element and a second element is strictly positive if and only if the second element is strictly positive.*)\nLemma pmulr_rgt0 x y : 0 < x -> (0 < x * y) = (0 < y).\n\n(*This lemma states that an element satisfies the 'is positive' predicate if and only if it is strictly greater than zero.*)\nLemma posrE x : (x \\is pos) = (0 < x). \n(*This lemma states that an element satisfies the 'is non-negative' predicate if and only if it is greater than or equal to zero.*)\nLemma nnegrE x : (x \\is nneg) = (0 <= x). \n(*This lemma states that an element satisfies the 'is real' predicate if and only if it is either greater than or equal to zero or less than or equal to zero.*)\nLemma realE x : (x \\is real) = (0 <= x) || (x <= 0). \n\n(*This fact establishes that the set of positive elements in a numerical domain is closed under division.*)\nFact pos_divr_closed : divr_closed (@pos R).\n\n#[export]\nHB.instance Definition _ := GRing.isDivClosed.Build R Rpos_pred\n pos_divr_closed.\n\n(*This fact establishes that the set of non-negative elements in a numerical domain is closed under division.*)\nFact nneg_divr_closed : divr_closed (@nneg R).\n\n#[export]\nHB.instance Definition _ := GRing.isDivClosed.Build R Rnneg_pred\n nneg_divr_closed.\n\n(*This fact establishes that the set of non-negative elements in a numerical domain is closed under addition.*)\nFact nneg_addr_closed : addr_closed (@nneg R).\n\n#[export]\nHB.instance Definition _ := GRing.isAddClosed.Build R Rnneg_pred\n nneg_addr_closed.\n\n(*This fact establishes that the set of elements in a numerical domain that are comparable to zero is closed under the operation of taking the additive inverse.*)\nFact real_oppr_closed : oppr_closed (@real R).\n\n#[export]\nHB.instance Definition _ := GRing.isOppClosed.Build R Rreal_pred\n real_oppr_closed.\n\n(*This fact establishes that the set of elements in a numerical domain that are comparable to zero is closed under addition.*)\nFact real_addr_closed : addr_closed (@real R).\n\n#[export]\nHB.instance Definition _ := GRing.isAddClosed.Build R Rreal_pred\n real_addr_closed.\n\n(*This fact establishes that the set of elements in a numerical domain that are comparable to zero is closed under division.*)\nFact real_divr_closed : divr_closed (@real R).\n\n#[export]\n(*This lemma states that every element in a real domain type satisfies the 'real' predicate, meaning it is comparable to zero.*)\nLemma num_real (R : realDomainType) (x : R) : x \\is real.\n\nModule Exports. HB.reexport. End Exports.\n\nEnd Internals.\n\nModule PredInstances.\n\nExport Internals.Exports.\n\nEnd PredInstances.\n\nModule Export Theory.\n\nSection NumIntegralDomainTheory.\n\nVariable R : numDomainType.\nImplicit Types (V : semiNormedZmodType R) (x y z t : R).\nImplicit Types (W : normedZmodType R).\n\n(*This definition re-exports the triangle inequality for a semi-normed module, which states that the norm of the sum of two vectors is less than or equal to the sum of their individual norms.*)\nDefinition ler_normD V (x y : V) : `|x + y| <= `|x| + `|y| :=\n ler_normD x y.\n(*This definition re-exports the property that the sum of two strictly positive elements in a numerical domain is also strictly positive.*)\nDefinition addr_gt0 x y : 0 < x -> 0 < y -> 0 < x + y := @addr_gt0 R x y.\n(*This definition re-exports a property of a normed module, stating that if the norm of a vector is zero, then the vector itself must be the zero vector.*)\nDefinition normr0_eq0 W (x : W) : `|x| = 0 -> x = 0 := @normr0_eq0 R W x.\n(*This definition re-exports a property of a totally ordered numerical domain, which states that any two non-negative elements are comparable.*)\nDefinition ger_leVge x y : 0 <= x -> 0 <= y -> (x <= y) || (y <= x) :=\n @ger_leVge R x y.\n(*This definition establishes that the absolute value function in a numerical domain is a multiplicative morphism, meaning the absolute value of a product of two elements equals the product of their absolute values.*)\nDefinition normrM : {morph norm : x y / (x : R) * y} := @normrM R.\n(*This definition re-exports the characterization of the less-than-or-equal-to relation, stating that one element is less than or equal to another if and only if the absolute value of their difference equals their difference.*)\nDefinition ler_def x y : (x <= y) = (`|y - x| == y - x) := ler_def x y.\n(*This definition re-exports the property that the norm of a vector scaled by a natural number is equal to the norm of the original vector multiplied by that same natural number.*)\nDefinition normrMn V (x : V) n : `|x *+ n| = `|x| *+ n := normrMn x n.\n(*This definition states that the absolute value of the additive inverse of a real number is equal to the absolute value of the number itself.*)\nDefinition normrN V (x : V) : `|- x| = `|x| := normrN x.\n\n(*This lemma states that an element of a numerical domain is considered positive if and only if it is strictly greater than zero.*)\nLemma posrE x : (x \\is pos) = (0 < x). \n(*This lemma states that a real number is negative if and only if it is strictly less than zero.*)\nLemma negrE x : (x \\is neg) = (x < 0). \n(*This lemma states that an element of a numerical domain is considered non-negative if and only if it is greater than or equal to zero.*)\nLemma nnegrE x : (x \\is nneg) = (0 <= x). \n(*This lemma states that a real number is non-positive if and only if it is less than or equal to zero.*)\nLemma nposrE x : (x \\is npos) = (x <= 0). \n(*This lemma states that an element of a numerical domain satisfies the 'real' property if and only if it is either greater than or equal to zero or less than or equal to zero.*)\nLemma realE x : (x \\is real) = (0 <= x) || (x <= 0). \n\n(*This lemma states that a real number is strictly greater than zero if and only if it is both non-negative and not equal to zero.*)\nLemma lt0r x : (0 < x) = (x != 0) && (0 <= x). \n(*This lemma states that an element in a numerical domain is greater than or equal to zero if and only if it is equal to zero or it is strictly greater than zero.*)\nLemma le0r x : (0 <= x) = (x == 0) || (0 < x). \n\n(*This lemma states that if a real number is strictly greater than zero, then it is not equal to zero.*)\nLemma lt0r_neq0 (x : R) : 0 < x -> x != 0. \n(*This lemma states that if a real number is strictly less than zero, then it is not equal to zero.*)\nLemma ltr0_neq0 (x : R) : x < 0 -> x != 0. \n\n(*This lemma states that for a strictly positive element in a numerical domain, its product with a second element is strictly positive if and only if the second element is also strictly positive.*)\nLemma pmulr_rgt0 x y : 0 < x -> (0 < x * y) = (0 < y).\n\n(*This lemma states that for any two real numbers, if the first is strictly positive, then their product is non-negative if and only if the second number is also non-negative.*)\nLemma pmulr_rge0 x y : 0 < x -> (0 <= x * y) = (0 <= y).\n\n(*This lemma states that in a numerical domain, the additive identity is less than or equal to the multiplicative identity.*)\nLemma ler01 : 0 <= 1 :> R. \n(*This lemma states that in a numerical domain, the additive identity is strictly less than the multiplicative identity.*)\nLemma ltr01 : 0 < 1 :> R. \n(*This lemma states that the real number representation of any natural number is greater than or equal to zero.*)\nLemma ler0n n : 0 <= n%:R :> R. \nHint Extern 0 (is_true (@Order.le ring_display _ _ _)) =>\n (apply: ler01) : core.\nHint Extern 0 (is_true (@Order.lt ring_display _ _ _)) =>\n (apply: ltr01) : core.\nHint Extern 0 (is_true (@Order.le ring_display _ _ _)) =>\n (apply: ler0n) : core.\n(*This lemma states that the real number representation of the successor of any natural number is strictly greater than zero.*)\nLemma ltr0Sn n : 0 < n.+1%:R :> R.\n\n(*This lemma states that the real number representation of a natural number is strictly greater than zero if and only if the natural number itself is strictly greater than zero.*)\nLemma ltr0n n : (0 < n%:R :> R) = (0 < n)%N.\n\nHint Extern 0 (is_true (@Order.lt ring_display _ _ _)) =>\n (apply: ltr0Sn) : core.\n\n(*This lemma states that the real number representation of a natural number is equal to zero if and only if the natural number itself is zero.*)\nLemma pnatr_eq0 n : (n%:R == 0 :> R) = (n == 0)%N.\n\n(*This lemma states that the characteristic of the ring of real numbers is zero.*)\nLemma pchar_num : [pchar R] =i pred0.\n\n(*This lemma states that an element in a numerical domain is greater than or equal to zero if and only if its absolute value is equal to the element itself.*)\nLemma ger0_def x : (0 <= x) = (`|x| == x). \n(*This lemma provides a reflection principle, stating that the proposition that a real number is non-negative is logically equivalent to its absolute value being equal to itself.*)\nLemma normr_idP {x} : reflect (`|x| = x) (0 <= x).\n\n(*This lemma states that if a real number is greater than or equal to zero, then its absolute value is equal to the number itself.*)\nLemma ger0_norm x : 0 <= x -> `|x| = x. \n(*This lemma states that the absolute value of the real number one is one.*)\nLemma normr1 : `|1 : R| = 1. \n(*This lemma states that the absolute value of the real number representation of a natural number is equal to that same real number representation.*)\nLemma normr_nat n : `|n%:R : R| = n%:R. \n\n(*This lemma states that the absolute value of a finite product of real numbers, indexed over a sequence, is equal to the product of their absolute values.*)\nLemma normr_prod I r (P : pred I) (F : I -> R) :\n `|\\prod_(i <- r | P i) F i| = \\prod_(i <- r | P i) `|F i|.\n\n(*This lemma states that the absolute value of a real number raised to a natural number power is equal to the absolute value of that real number raised to the same power.*)\nLemma normrX n x : `|x ^+ n| = `|x| ^+ n.\n\n(*This declaration establishes that the real absolute value function is a homomorphism with respect to multiplication over the group of unit real numbers.*)\nLemma normr_unit : {homo (@norm _ R) : x / x \\is a GRing.unit}.\n\n(*This lemma states that the absolute value of the multiplicative inverse of a unit real number is equal to the multiplicative inverse of its absolute value.*)\nLemma normrV : {in GRing.unit, {morph (@norm _ R) : x / x ^-1}}.\n\n(*This lemma states that the absolute value of the real number negative one is one.*)\nLemma normrN1 : `|-1 : R| = 1.\n\n(*This lemma establishes a property for a generalized indexed operation over a sequence of real-valued terms, specified by a binary operator and an initial value.*)\nLemma big_real x0 op I (P : pred I) F (s : seq I) :\n {in real &, forall x y, op x y \\is real} -> x0 \\is real ->\n {in P, forall i, F i \\is real} -> \\big[op/x0]_(i <- s | P i) F i \\is real.\n\n(*This lemma states that the sum of a sequence of real numbers, computed over indices that satisfy a given predicate, is itself a real number, provided that all the function values for those indices are real.*)\nLemma sum_real I (P : pred I) (F : I -> R) (s : seq I) :\n {in P, forall i, F i \\is real} -> \\sum_(i <- s | P i) F i \\is real.\n\n(*This lemma states that the product of a sequence of real numbers, computed over indices that satisfy a given predicate, is itself a real number, provided that all the function values for those indices are real.*)\nLemma prod_real I (P : pred I) (F : I -> R) (s : seq I) :\n {in P, forall i, F i \\is real} -> \\prod_(i <- s | P i) F i \\is real.\n\nSection SemiNormedZmoduleTheory.\n\nVariable V : semiNormedZmodType R.\nImplicit Types (v w : V).\n\n(*This lemma states that the norm of the zero element in a semi-normed module is equal to zero.*)\nLemma normr0 : `|0 : V| = 0.\n\n(*This lemma states that the norm of the difference between two elements in a semi-normed module is symmetric, meaning it is equal to the norm of the difference taken in the opposite order.*)\nLemma distrC v w : `|v - w| = `|w - v|.\n\n(*This lemma states that the absolute value of the norm of an element from a semi-normed module is equal to the norm of that element itself.*)\nLemma normr_id v : `| `|v| | = `|v|.\n\n(*This lemma states that the norm of any element in a semi-normed module is greater than or equal to zero.*)\nLemma normr_ge0 v : 0 <= `|v|. \n\n(*This lemma states that the proposition that the norm of an element in a semi-normed module is less than zero is false.*)\nLemma normr_lt0 v : `|v| < 0 = false.\n\n(*This lemma states that if the norm of an element in a semi-normed module is greater than zero, then that element is not the zero element.*)\nLemma gtr0_norm_neq0 v : `|v| > 0 -> (v != 0).\n\n(*This lemma states that if the norm of an element in a semi-normed module is greater than zero, then the proposition that this element is equal to the zero element is false.*)\nLemma gtr0_norm_eq0F v : `|v| > 0 -> (v == 0) = false.\n\nEnd SemiNormedZmoduleTheory.\n\nSection NormedZmoduleTheory.\n\nVariable V : normedZmodType R.\nImplicit Types (v w : V).\n\n(*This lemma states that the norm of an element in a normed module is equal to zero if and only if the element itself is the zero element.*)\nLemma normr0P v : reflect (`|v| = 0) (v == 0).\n\n(*This definition establishes the logical equivalence between the proposition that the norm of an element in a normed module is zero and the proposition that the element itself is zero.*)\nDefinition normr_eq0 v := sameP (`|v| =P 0) (normr0P v).\n\n(*This lemma states that the proposition that the norm of an element in a normed module is less than or equal to zero is equivalent to the proposition that the element is the zero element.*)\nLemma normr_le0 v : `|v| <= 0 = (v == 0).\n\n(*This lemma states that the proposition that the norm of an element in a normed module is greater than zero is equivalent to the proposition that the element is not the zero element.*)\nLemma normr_gt0 v : `|v| > 0 = (v != 0).\n\nEnd NormedZmoduleTheory.\n\n(*This definition aggregates a collection of fundamental properties of the real number norm, including its value at zero and one, its behavior with negation, non-negativity, and its relation to equality with zero.*)\nDefinition normrE := (normr_id, normr0, normr1, normrN1, normr_ge0, normr_eq0,\n normr_lt0, normr_le0, normr_gt0, normrN).\n\n(*This lemma states that a real number is less than or equal to zero if and only if its absolute value is equal to its additive inverse.*)\nLemma ler0_def x : (x <= 0) = (`|x| == - x).\n\n(*This lemma states that if a real number is less than or equal to zero, then its absolute value is equal to its additive inverse.*)\nLemma ler0_norm x : x <= 0 -> `|x| = - x.\n\n(*This definition provides a proof that for any real number strictly greater than zero, its absolute value is equal to the number itself.*)\nDefinition gtr0_norm x (hx : 0 < x) := ger0_norm (ltW hx).\n(*This definition provides a proof that for any real number strictly less than zero, its absolute value is equal to its additive inverse.*)\nDefinition ltr0_norm x (hx : x < 0) := ler0_norm (ltW hx).\n\n(*This lemma states that the absolute value function is non-decreasing when restricted to the domain of non-negative real numbers.*)\nLemma ger0_le_norm :\n {in nneg &, {mono (@normr _ R) : x y / x <= y}}.\n\n(*This lemma states that the absolute value function is non-decreasing when restricted to the domain of positive real numbers.*)\nLemma gtr0_le_norm :\n {in pos &, {mono (@normr _ R) : x y / x <= y}}.\n\n(*This lemma states that the absolute value function is non-increasing when restricted to the domain of non-positive real numbers, meaning it reverses the order.*)\nLemma ler0_ge_norm :\n {in npos &, {mono (@normr _ R) : x y / x <= y >-> x >= y}}.\n\n(*This lemma states that the absolute value function is non-increasing when restricted to the domain of negative real numbers, meaning it reverses the order.*)\nLemma ltr0_ge_norm :\n {in neg &, {mono (@normr _ R) : x y / x <= y >-> x >= y}}.\n\n(*This lemma states that for any two real numbers, the proposition that their difference is greater than or equal to zero is equivalent to the proposition that the first number is less than or equal to the second.*)\nLemma subr_ge0 x y : (0 <= y - x) = (x <= y). \n(*This lemma states that the difference of a second element and a first element is strictly positive if and only if the first element is strictly less than the second element.*)\nLemma subr_gt0 x y : (0 < y - x) = (x < y).\n\n(*This lemma states that for any two real numbers, the proposition that the difference of the second and first number is less than or equal to zero is equivalent to the proposition that the second number is less than or equal to the first.*)\nLemma subr_le0 x y : (y - x <= 0) = (y <= x).\n \n(*This lemma states that for any two real numbers, the proposition that the difference of the second and first number is strictly less than zero is equivalent to the proposition that the second number is strictly less than the first.*)\nLemma subr_lt0 x y : (y - x < 0) = (y < x).\n \n\n(*This definition groups together the lemmas establishing the equivalence between a subtraction being non-positive or negative and the corresponding ordering of the two real numbers.*)\nDefinition subr_lte0 := (subr_le0, subr_lt0).\n(*This definition groups together the lemmas establishing the equivalence between a subtraction being non-negative or positive and the corresponding ordering of the two real numbers.*)\nDefinition subr_gte0 := (subr_ge0, subr_gt0).\n(*This definition aggregates lemmas that relate the sign of the difference between two real numbers to their relative order.*)\nDefinition subr_cp0 := (subr_lte0, subr_gte0).\n\n(*This lemma states that the proposition that zero and any given real number are comparable is equivalent to the proposition that the given number is indeed a real number.*)\nLemma comparable0r x : (0 >=< x)%R = (x \\is Num.real). \n\n(*This lemma states that an element from a real number domain is comparable to zero if and only if that element is a real number.*)\nLemma comparabler0 x : (x >=< 0)%R = (x \\is Num.real).\n\n(*This lemma states that for any two elements from a real number domain, their difference is comparable to zero if and only if the two elements are comparable to each other.*)\nLemma subr_comparable0 x y : (x - y >=< 0)%R = (x >=< y)%R.\n\n(*This lemma states that two elements from a real number domain are comparable to each other if and only if their difference is a real number.*)\nLemma comparablerE x y : (x >=< y)%R = (x - y \\is Num.real).\n\n(*This lemma states that the comparability relation on a real number domain is transitive.*)\nLemma comparabler_trans : transitive (comparable : rel R).\n\n(*This definition bundles two lemmas, one concerning the 'less than or equal to' relation with zero and one, and another concerning the 'less than' relation with zero and one, into a single pair.*)\nDefinition lter01 := (ler01, ltr01).\n\n(*This lemma states that if two elements in a numerical domain are both greater than or equal to zero, their sum is also greater than or equal to zero.*)\nLemma addr_ge0 x y : 0 <= x -> 0 <= y -> 0 <= x + y.\n\nEnd NumIntegralDomainTheory.\n\n#[deprecated(since=\"mathcomp 2.4.0\",note=\"Use pchar_num instead.\")]\n(*This is a deprecated notation that serves as a parsing-only alias for pchar_num. It is recommended to use pchar_num instead.*)\nNotation char_num := pchar_num (only parsing).\n\nArguments ler01 {R}.\nArguments ltr01 {R}.\nArguments normr_idP {R x}.\nArguments normr0P {R V v}.\n#[global] Hint Extern 0 (is_true (@Order.le ring_display _ _ _)) =>\n (apply: ler01) : core.\n#[global] Hint Extern 0 (is_true (@Order.lt ring_display _ _ _)) =>\n (apply: ltr01) : core.\n#[global] Hint Extern 0 (is_true (@Order.le ring_display _ _ _)) =>\n (apply: ler0n) : core.\n#[global] Hint Extern 0 (is_true (@Order.lt ring_display _ _ _)) =>\n (apply: ltr0Sn) : core.\n#[global] Hint Extern 0 (is_true (0 <= norm _)) => apply: normr_ge0 : core.\n\n(*This lemma states that the norm of any element in a numeric domain is a non-negative number.*)\nLemma normr_nneg (R : numDomainType) (x : R) : `|x| \\is Num.nneg.\n\n#[global] Hint Resolve normr_nneg : core.\n\nSection NumDomainOperationTheory.\n\nVariable R : numDomainType.\nImplicit Types x y z t : R.\n\n(*This lemma states that the additive inverse function on a numeric domain is monotonically decreasing, meaning that if one element is less than or equal to another, then the additive inverse of the second is less than or equal to the additive inverse of the first.*)\nLemma lerN2 : {mono -%R : x y /~ x <= y :> R}.\n\nHint Resolve lerN2 : core.\n(*This lemma states that the additive inverse function on a numeric domain is strictly monotonically decreasing, meaning that if one element is strictly less than another, then the additive inverse of the second is strictly less than the additive inverse of the first.*)\nLemma ltrN2 : {mono -%R : x y /~ x < y :> R}.\n\nHint Resolve ltrN2 : core.\n(*This definition bundles two lemmas about the monotonically decreasing nature of the additive inverse function, one for the 'less than or equal to' relation and one for the 'strictly less than' relation.*)\nDefinition lterN2 := (lerN2, ltrN2).\n\n(*This lemma states that for any two elements in a numeric domain, the first element being less than or equal to the additive inverse of the second is equivalent to the second element being less than or equal to the additive inverse of the first.*)\nLemma lerNr x y : (x <= - y) = (y <= - x).\n\n(*This lemma states that for any two elements in a numeric domain, the first element being strictly less than the additive inverse of the second is equivalent to the second element being strictly less than the additive inverse of the first.*)\nLemma ltrNr x y : (x < - y) = (y < - x).\n\n(*This definition bundles two lemmas expressing the symmetry of inequalities involving additive inverses, one for 'less than or equal to' and one for 'strictly less than'.*)\nDefinition lterNr := (lerNr, ltrNr).\n\n(*This lemma states that for any two elements in a numeric domain, the additive inverse of the first element being less than or equal to the second is equivalent to the additive inverse of the second element being less than or equal to the first.*)\nLemma lerNl x y : (- x <= y) = (- y <= x).\n\n(*This lemma states that for any two elements in a numeric domain, the additive inverse of the first element being strictly less than the second is equivalent to the additive inverse of the second element being strictly less than the first.*)\nLemma ltrNl x y : (- x < y) = (- y < x).\n\n(*This definition bundles two lemmas expressing the symmetry of inequalities involving additive inverses where the inverse is on the left side, one for 'less than or equal to' and one for 'strictly less than'.*)\nDefinition lterNl := (lerNl, ltrNl).\n\n(*This lemma states that the additive inverse of an element in a numerical domain is greater than or equal to zero if and only if the original element is less than or equal to zero.*)\nLemma oppr_ge0 x : (0 <= - x) = (x <= 0). \n\n(*This lemma states that for any element in a numeric domain, its additive inverse is strictly greater than zero if and only if the element itself is strictly less than zero.*)\nLemma oppr_gt0 x : (0 < - x) = (x < 0). \n\n(*This definition bundles two lemmas that relate the sign of an element to the sign of its additive inverse, specifically for the cases where the inverse is greater than or equal to zero and strictly greater than zero.*)\nDefinition oppr_gte0 := (oppr_ge0, oppr_gt0).\n\n(*This lemma states that for any element in a numeric domain, its additive inverse is less than or equal to zero if and only if the element itself is greater than or equal to zero.*)\nLemma oppr_le0 x : (- x <= 0) = (0 <= x). \n\n(*This lemma states that for any element in a numeric domain, its additive inverse is strictly less than zero if and only if the element itself is strictly greater than zero.*)\nLemma oppr_lt0 x : (- x < 0) = (0 < x). \n\n(*This lemma states that for any element in a numeric domain that is strictly greater than zero, its additive inverse is strictly less than the element itself.*)\nLemma gtrN x : 0 < x -> - x < x.\n\n(*This definition bundles two lemmas that relate the sign of an element to the sign of its additive inverse, specifically for the cases where the inverse is less than or equal to zero and strictly less than zero.*)\nDefinition oppr_lte0 := (oppr_le0, oppr_lt0).\n(*This definition groups four lemmas concerning the relationship between the sign of an element and the sign of its additive inverse when compared to zero.*)\nDefinition oppr_cp0 := (oppr_gte0, oppr_lte0).\n(*This definition bundles a collection of lemmas regarding the interaction between the order relations and the additive inverse operation, including properties of sign-flipping and monotonicity.*)\nDefinition lterNE := (oppr_cp0, lterN2).\n\n(*This lemma states that if an element in a numeric domain is greater than or equal to zero, then its additive inverse is less than or equal to zero, and its additive inverse is also less than or equal to the element itself.*)\nLemma ge0_cp x : 0 <= x -> (- x <= 0) * (- x <= x).\n\n(*This lemma states that if an element in a numeric domain is strictly greater than zero, then it follows that the element is greater than or equal to zero, its additive inverse is less than or equal to zero, its additive inverse is less than or equal to the element, its additive inverse is strictly less than zero, and its additive inverse is strictly less than the element.*)\nLemma gt0_cp x : 0 < x ->\n (0 <= x) * (- x <= 0) * (- x <= x) * (- x < 0) * (- x < x).\n\n(*This lemma states that if an element in a numeric domain is less than or equal to zero, then its additive inverse is greater than or equal to zero, and the element itself is less than or equal to its additive inverse.*)\nLemma le0_cp x : x <= 0 -> (0 <= - x) * (x <= - x).\n\n(*This lemma states that if an element in a numeric domain is strictly less than zero, then it follows that the element is less than or equal to zero, its additive inverse is greater than or equal to zero, the element is less than or equal to its additive inverse, its additive inverse is strictly greater than zero, and the element is strictly less than its additive inverse.*)\nLemma lt0_cp x :\n x < 0 -> (x <= 0) * (0 <= - x) * (x <= - x) * (0 < - x) * (x < - x).\n\n(*This lemma states that any number that is greater than or equal to zero is a real number.*)\nLemma ger0_real x : 0 <= x -> x \\is real.\n\n(*This lemma states that any number that is less than or equal to zero is a real number.*)\nLemma ler0_real x : x <= 0 -> x \\is real.\n\n(*This lemma states that any number that is strictly greater than zero is a real number.*)\nLemma gtr0_real x : 0 < x -> x \\is real. \n\n(*This lemma states that any number that is strictly less than zero is a real number.*)\nLemma ltr0_real x : x < 0 -> x \\is real. \n\n(*This lemma states that the number zero is a real number.*)\nLemma real0 : 0 \\is @real R. \n(*This lemma states that the number one is a real number.*)\nLemma real1 : 1 \\is @real R. \n(*This lemma states that the representation of any natural number as a real number is itself a real number.*)\nLemma realn n : n%:R \\is @real R. \n#[local] Hint Resolve real0 real1 : core.\n\n(*This lemma states that for any two numbers that are both less than or equal to zero, one must be less than or equal to the other.*)\nLemma ler_leVge x y : x <= 0 -> y <= 0 -> (x <= y) || (y <= x).\n\n(*This lemma states that for any two real numbers, one must be less than or equal to the other.*)\nLemma real_leVge x y : x \\is real -> y \\is real -> (x <= y) || (y <= x).\n\n(*This lemma states that any two real numbers are comparable, meaning one is either less than, equal to, or greater than the other.*)\nLemma real_comparable x y : x \\is real -> y \\is real -> x >=< y.\n\n(*This lemma states that the difference between any two real numbers is also a real number.*)\nLemma realB : {in real &, forall x y, x - y \\is real}.\n\n(*This lemma states that the additive inverse of any real number is also a real number.*)\nLemma realN : {mono (@GRing.opp R) : x / x \\is real}.\n\n(*This lemma states that the property of the difference of two numbers being a real number is symmetric; that is, the difference of the first and second is real if and only if the difference of the second and first is real.*)\nLemma realBC x y : (x - y \\is real) = (y - x \\is real).\n\n(*This lemma states that the sum of any two real numbers is also a real number.*)\nLemma realD : {in real &, forall x y, x + y \\is real}.\n\n(*This variant type provides a constructive case analysis for the comparison of two numbers. It has two constructors: one for the case where the first number is less than or equal to the second, and another for the case where the second number is strictly less than the first. Each case also provides the minimum, maximum, and absolute difference of the two numbers.*)\nVariant ler_xor_gt (x y : R) : R -> R -> R -> R -> R -> R ->\n bool -> bool -> Set :=\n(**)\n | LerNotGt of x <= y : ler_xor_gt x y x x y y (y - x) (y - x) true false\n(**)\n | GtrNotLe of y < x : ler_xor_gt x y y y x x (x - y) (x - y) false true.\n\n(*This variant type provides a constructive case analysis for the strict comparison of two numbers. It has two constructors: one for the case where the first number is strictly less than the second, and another for the case where the second number is greater than or equal to the first. Each case also provides the minimum, maximum, and absolute difference of the two numbers.*)\nVariant ltr_xor_ge (x y : R) : R -> R -> R -> R -> R -> R ->\n bool -> bool -> Set :=\n(**)\n | LtrNotGe of x < y : ltr_xor_ge x y x x y y (y - x) (y - x) false true\n(**)\n | GerNotLt of y <= x : ltr_xor_ge x y y y x x (x - y) (x - y) true false.\n\n(*This variant type provides a constructive three-way comparison of two numbers. It has three constructors representing the cases where the first number is strictly less than, strictly greater than, or equal to the second number. Each case also provides the minimum, maximum, absolute difference, and boolean results for various comparison operators.*)\nVariant comparer x y : R -> R -> R -> R -> R -> R ->\n bool -> bool -> bool -> bool -> bool -> bool -> Set :=\n(**)\n | ComparerLt of x < y : comparer x y x x y y (y - x) (y - x)\n false false false true false true\n(**)\n | ComparerGt of x > y : comparer x y y y x x (x - y) (x - y)\n false false true false true false\n(**)\n | ComparerEq of x = y : comparer x y x x x x 0 0\n true true true true false false.\n\n(*This lemma states that for any two real numbers, one can constructively determine whether the first is less than or equal to the second, or the second is strictly less than the first. It provides the minimum, maximum, and absolute difference accordingly.*)\nLemma real_leP x y : x \\is real -> y \\is real ->\n ler_xor_gt x y (min y x) (min x y) (max y x) (max x y)\n `|x - y| `|y - x| (x <= y) (y < x).\n\n(*This lemma states that for any two real numbers, one can constructively determine whether the first is strictly less than the second, or the second is greater than or equal to the first. It provides the minimum, maximum, and absolute difference accordingly.*)\nLemma real_ltP x y : x \\is real -> y \\is real ->\n ltr_xor_ge x y (min y x) (min x y) (max y x) (max x y)\n `|x - y| `|y - x| (y <= x) (x < y).\n\n(*This lemma states that for any two real numbers, the proposition that the first is strictly less than the second is equivalent to the negation of the proposition that the second is greater than or equal to the first.*)\nLemma real_ltNge : {in real &, forall x y, (x < y) = ~~ (y <= x)}.\n\n(*This lemma states that for any two real numbers, the proposition that the first is less than or equal to the second is equivalent to the negation of the proposition that the second is strictly less than the first.*)\nLemma real_leNgt : {in real &, forall x y, (x <= y) = ~~ (y < x)}.\n\n(*This lemma states that for any two real numbers, one can constructively perform a three-way comparison, determining whether the first is strictly less than, strictly greater than, or equal to the second. It also provides the minimum, maximum, absolute difference, and boolean results for various comparisons.*)\nLemma real_ltgtP x y : x \\is real -> y \\is real ->\n comparer x y (min y x) (min x y) (max y x) (max x y) `|x - y| `|y - x|\n (y == x) (x == y) (x >= y) (x <= y) (x > y) (x < y).\n\n(*This variant type provides a constructive case analysis for the comparison of a number with zero. It has two constructors: one for the case where the number is greater than or equal to zero, and another for the case where it is strictly less than zero. Each case also provides the minimum and maximum of the number and zero, as well as its absolute value.*)\nVariant ger0_xor_lt0 (x : R) : R -> R -> R -> R -> R ->\n bool -> bool -> Set :=\n(**)\n | Ger0NotLt0 of 0 <= x : ger0_xor_lt0 x 0 0 x x x false true\n(**)\n | Ltr0NotGe0 of x < 0 : ger0_xor_lt0 x x x 0 0 (- x) true false.\n\n(*This variant type provides a constructive case analysis for the comparison of a number with zero. It has two constructors: one for the case where the number is less than or equal to zero, and another for the case where it is strictly greater than zero. Each case also provides the minimum and maximum of the number and zero, as well as its absolute value.*)\nVariant ler0_xor_gt0 (x : R) : R -> R -> R -> R -> R ->\n bool -> bool -> Set :=\n(**)\n | Ler0NotLe0 of x <= 0 : ler0_xor_gt0 x x x 0 0 (- x) false true\n(**)\n | Gtr0NotGt0 of 0 < x : ler0_xor_gt0 x 0 0 x x x true false.\n\n(*This variant type provides a constructive three-way comparison of a number with zero. It has three constructors representing the cases where the number is strictly greater than, strictly less than, or equal to zero. Each case also provides the minimum and maximum of the number and zero, its absolute value, and boolean results for various comparisons with zero.*)\nVariant comparer0 x : R -> R -> R -> R -> R ->\n bool -> bool -> bool -> bool -> bool -> bool -> Set :=\n(*This constructor represents the case where an element of an ordered type is strictly greater than zero, bundling a proof of this fact.*)\n | ComparerGt0 of 0 < x : comparer0 x 0 0 x x x false false false true false true\n(*This constructor represents the case where an element of an ordered type is strictly less than zero, bundling a proof of this fact.*)\n | ComparerLt0 of x < 0 : comparer0 x x x 0 0 (- x) false false true false true false\n(*This constructor represents the case where an element of an ordered type is equal to zero, bundling a boolean proof of this fact.*)\n | ComparerEq0 of x = 0 : comparer0 x 0 0 0 0 0 true true true true false false.\n\n(*This lemma states that for any real number, one can constructively determine whether it is greater than or equal to zero or strictly less than zero. It provides the minimum and maximum of the number and zero, as well as its absolute value, accordingly.*)\nLemma real_ge0P x : x \\is real -> ger0_xor_lt0 x\n (min 0 x) (min x 0) (max 0 x) (max x 0)\n `|x| (x < 0) (0 <= x).\n\n(*This lemma states that for any real number, one can constructively determine whether it is less than or equal to zero or strictly greater than zero. It provides the minimum and maximum of the number and zero, as well as its absolute value, accordingly.*)\nLemma real_le0P x : x \\is real -> ler0_xor_gt0 x\n (min 0 x) (min x 0) (max 0 x) (max x 0)\n `|x| (0 < x) (x <= 0).\n\n(*This lemma states that for any real number, one can constructively perform a three-way comparison with zero, determining whether it is strictly greater than, strictly less than, or equal to zero. It also provides the minimum and maximum of the number and zero, its absolute value, and boolean results for various comparisons.*)\nLemma real_ltgt0P x : x \\is real ->\n comparer0 x (min 0 x) (min x 0) (max 0 x) (max x 0)\n `|x| (0 == x) (x == 0) (x <= 0) (0 <= x) (x < 0) (x > 0).\n\n(*This lemma states that the maximum of any two real numbers is also a real number.*)\nLemma max_real : {in real &, forall x y, max x y \\is real}.\n\n(*This lemma states that the minimum of any two real numbers is also a real number.*)\nLemma min_real : {in real &, forall x y, min x y \\is real}.\n\n(*This lemma states that the computed maximum of a function over a sequence of numbers is itself a finite real number, provided that the initial default value is a finite real number and the function produces a finite real number for every element of the sequence satisfying a given predicate.*)\nLemma bigmax_real I x0 (r : seq I) (P : pred I) (f : I -> R):\n x0 \\is real -> {in P, forall i : I, f i \\is real} ->\n \\big[max/x0]_(i <- r | P i) f i \\is real.\n\n(*This lemma states that the computed minimum of a function over a sequence of numbers is itself a finite real number, provided that the initial default value is a finite real number and the function produces a finite real number for every element of the sequence satisfying a given predicate.*)\nLemma bigmin_real I x0 (r : seq I) (P : pred I) (f : I -> R):\n x0 \\is real -> {in P, forall i : I, f i \\is real} ->\n \\big[min/x0]_(i <- r | P i) f i \\is real.\n\n(*This lemma states that for any two finite real numbers, the property of them being unequal is equivalent to the disjunction of the first being strictly less than the second or the second being strictly less than the first.*)\nLemma real_neqr_lt : {in real &, forall x y, (x != y) = (x < y) || (y < x)}.\n\n(*This lemma states that if a first number is less than or equal to a second number, then the difference obtained by subtracting the first from the second is a finite real number.*)\nLemma lerB_real x y : x <= y -> y - x \\is real.\n\n(*This lemma states that if a first number is less than or equal to a second number, then the difference obtained by subtracting the second from the first is a finite real number.*)\nLemma gerB_real x y : x <= y -> x - y \\is real.\n\n(*This lemma states that if a number is less than or equal to another number, then the boolean value indicating whether the first number is a finite real number is equal to the boolean value indicating whether the second number is a finite real number.*)\nLemma ler_real y x : x <= y -> (x \\is real) = (y \\is real).\n\n(*This lemma states that if a number is greater than or equal to another number, then the boolean value indicating whether the first number is a finite real number is equal to the boolean value indicating whether the second number is a finite real number.*)\nLemma ger_real x y : y <= x -> (x \\is real) = (y \\is real).\n\n(*This lemma states that if a number is greater than or equal to one, then that number is a finite real number.*)\nLemma ger1_real x : 1 <= x -> x \\is real. \n(*This lemma states that if a number is less than or equal to one, then that number is a finite real number.*)\nLemma ler1_real x : x <= 1 -> x \\is real. \n\n(*This lemma states that the proposition that a non-real number is less than or equal to a finite real number is false.*)\nLemma Nreal_leF x y : y \\is real -> x \\notin real -> (x <= y) = false.\n\n(*This lemma states that the proposition that a finite real number is less than or equal to a non-real number is false.*)\nLemma Nreal_geF x y : y \\is real -> x \\notin real -> (y <= x) = false.\n\n(*This lemma states that the proposition that a non-real number is strictly less than a finite real number is false.*)\nLemma Nreal_ltF x y : y \\is real -> x \\notin real -> (x < y) = false.\n\n(*This lemma states that the proposition that a finite real number is strictly less than a non-real number is false.*)\nLemma Nreal_gtF x y : y \\is real -> x \\notin real -> (y < x) = false.\n\n(*This lemma provides a 'without loss of generality' principle for proving a property for any pair of finite real numbers. It states that if a property is symmetric, meaning that if it holds for an ordered pair, it also holds for the reversed pair, then to prove it for all pairs of finite real numbers, it is sufficient to prove it only for pairs where the first element is less than or equal to the second.*)\nLemma real_wlog_ler P :\n (forall a b, P b a -> P a b) -> (forall a b, a <= b -> P a b) ->\n forall a b : R, a \\is real -> b \\is real -> P a b.\n\n(*This lemma provides a 'without loss of generality' principle for proving a property for any pair of finite real numbers. It states that if a property holds when its two arguments are equal and is symmetric, meaning that if it holds for an ordered pair, it also holds for the reversed pair, then to prove it for all pairs of finite real numbers, it is sufficient to prove it only for pairs where the first element is strictly less than the second.*)\nLemma real_wlog_ltr P :\n (forall a, P a a) -> (forall a b, (P b a -> P a b)) ->\n (forall a b, a < b -> P a b) ->\n forall a b : R, a \\is real -> b \\is real -> P a b.\n\n(*This lemma states that addition of real numbers is monotonic on the left. Specifically, for any fixed real number, the function that adds it to another real number preserves the 'less than or equal to' relationship.*)\nLemma lerD2l x : {mono +%R x : y z / y <= z}.\n\n(*This lemma states that addition of real numbers is monotonic on the right. Specifically, for any fixed real number, the function that adds another real number to it preserves the 'less than or equal to' relationship.*)\nLemma lerD2r x : {mono +%R^~ x : y z / y <= z}.\n\n(*This lemma states that addition of real numbers is strictly monotonic on the left. Specifically, for any fixed real number, the function that adds it to another real number preserves the 'strictly less than' relationship.*)\nLemma ltrD2l x : {mono +%R x : y z / y < z}.\n\n(*This lemma states that addition of real numbers is strictly monotonic on the right. Specifically, for any fixed real number, the function that adds another real number to it preserves the 'strictly less than' relationship.*)\nLemma ltrD2r x : {mono +%R^~ x : y z / y < z}.\n\n(*This definition combines the proofs that addition of real numbers is monotonic on the left and on the right with respect to the 'less than or equal to' relation.*)\nDefinition lerD2 := (lerD2l, lerD2r).\n(*This definition combines the proofs that addition of real numbers is strictly monotonic on the left and on the right with respect to the 'strictly less than' relation.*)\nDefinition ltrD2 := (ltrD2l, ltrD2r).\n(*This definition groups the monotonicity properties of real number addition, combining the proofs for both the 'less than or equal to' and 'strictly less than' relations.*)\nDefinition lterD2 := (lerD2, ltrD2).\n\n(*This lemma states that the 'less than or equal to' relation is compatible with addition. If a first number is less than or equal to a second, and a third number is less than or equal to a fourth, then the sum of the first and third is less than or equal to the sum of the second and fourth.*)\nLemma lerD x y z t : x <= y -> z <= t -> x + z <= y + t.\n\n(*This lemma describes the interaction between strict and non-strict inequalities with respect to addition. If a first number is less than or equal to a second, and a third number is strictly less than a fourth, then the sum of the first and third is strictly less than the sum of the second and fourth.*)\nLemma ler_ltD x y z t : x <= y -> z < t -> x + z < y + t.\n\n(*This lemma describes the interaction between strict and non-strict inequalities with respect to addition. If a first number is strictly less than a second, and a third number is less than or equal to a fourth, then the sum of the first and third is strictly less than the sum of the second and fourth.*)\nLemma ltr_leD x y z t : x < y -> z <= t -> x + z < y + t.\n\n(*This lemma states that the 'strictly less than' relation is compatible with addition. If a first number is strictly less than a second, and a third number is strictly less than a fourth, then the sum of the first and third is strictly less than the sum of the second and fourth.*)\nLemma ltrD x y z t : x < y -> z < t -> x + z < y + t.\n\n(*This lemma states that if a first number is less than or equal to a second, and a fourth number is less than or equal to a third, then subtracting the third from the first yields a result that is less than or equal to subtracting the fourth from the second.*)\nLemma lerB x y z t : x <= y -> t <= z -> x - z <= y - t.\n\n(*This lemma states that if a first number is less than or equal to a second, and a fourth number is strictly less than a third, then subtracting the third from the first yields a result that is strictly less than subtracting the fourth from the second.*)\nLemma ler_ltB x y z t : x <= y -> t < z -> x - z < y - t.\n\n(*This lemma states that if a first number is strictly less than a second, and a fourth number is less than or equal to a third, then subtracting the third from the first yields a result that is strictly less than subtracting the fourth from the second.*)\nLemma ltr_leB x y z t : x < y -> t <= z -> x - z < y - t.\n\n(*This lemma states that if a first number is strictly less than a second, and a fourth number is strictly less than a third, then subtracting the third from the first yields a result that is strictly less than subtracting the fourth from the second.*)\nLemma ltrB x y z t : x < y -> t < z -> x - z < y - t.\n\n(*This lemma states that an inequality where the difference of a first and second number is less than or equal to a third number is equivalent to the first number being less than or equal to the sum of the third and second numbers.*)\nLemma lerBlDr x y z : (x - y <= z) = (x <= z + y).\n\n(*This lemma states that a strict inequality where the difference of a first and second number is less than a third number is equivalent to the first number being strictly less than the sum of the third and second numbers.*)\nLemma ltrBlDr x y z : (x - y < z) = (x < z + y).\n\n(*This lemma states that an inequality where a first number is less than or equal to the difference of a second and third number is equivalent to the sum of the first and third numbers being less than or equal to the second number.*)\nLemma lerBrDr x y z : (x <= y - z) = (x + z <= y).\n\n(*This lemma states that a strict inequality where a first number is less than the difference of a second and third number is equivalent to the sum of the first and third numbers being strictly less than the second number.*)\nLemma ltrBrDr x y z : (x < y - z) = (x + z < y).\n\n(*This definition groups two lemmas that provide rules for moving a term involved in a subtraction across a 'less than or equal to' comparison by turning it into an addition.*)\nDefinition lerBDr := (lerBlDr, lerBrDr).\n(*This definition groups two lemmas that provide rules for moving a term involved in a subtraction across a 'less than' comparison by turning it into an addition.*)\nDefinition ltrBDr := (ltrBlDr, ltrBrDr).\n(*This definition combines lemmas for rewriting both strict and non-strict inequalities involving subtraction into equivalent inequalities involving addition.*)\nDefinition lterBDr := (lerBDr, ltrBDr).\n\n(*This lemma states that an inequality where the difference of a first and second number is less than or equal to a third number is equivalent to the first number being less than or equal to the sum of the second and third numbers.*)\nLemma lerBlDl x y z : (x - y <= z) = (x <= y + z).\n\n(*This lemma states that a strict inequality where the difference of a first and second number is less than a third number is equivalent to the first number being strictly less than the sum of the second and third numbers.*)\nLemma ltrBlDl x y z : (x - y < z) = (x < y + z).\n\n(*This lemma states that an inequality where a first number is less than or equal to the difference of a second and third number is equivalent to the sum of the third and first numbers being less than or equal to the second number.*)\nLemma lerBrDl x y z : (x <= y - z) = (z + x <= y).\n\n(*This lemma states that a strict inequality where a first number is less than the difference of a second and third number is equivalent to the sum of the third and first numbers being strictly less than the second number.*)\nLemma ltrBrDl x y z : (x < y - z) = (z + x < y).\n\n(*This definition bundles two lemmas that transform 'less than or equal to' inequalities involving subtraction into equivalent inequalities with addition, specifying that the moved term becomes the first operand in the new sum.*)\nDefinition lerBDl := (lerBlDl, lerBrDl).\n(*This definition bundles two lemmas that transform strict 'less than' inequalities involving subtraction into equivalent strict inequalities with addition, specifying that the moved term becomes the first operand in the new sum.*)\nDefinition ltrBDl := (ltrBlDl, ltrBrDl).\n(*This definition combines lemmas for rewriting both strict and non-strict inequalities involving subtraction by converting them to addition, with specific control over the operand order in the resulting sum.*)\nDefinition lterBDl := (lerBDl, ltrBDl).\n\n(*This lemma states that an inequality asserting a number is less than or equal to its sum with another number is equivalent to zero being less than or equal to that other number.*)\nLemma lerDl x y : (x <= x + y) = (0 <= y).\n\n(*This lemma states that a strict inequality asserting a number is less than its sum with another number is equivalent to zero being strictly less than that other number.*)\nLemma ltrDl x y : (x < x + y) = (0 < y).\n\n(*This lemma states that an inequality asserting a number is less than or equal to the sum of another number and itself is equivalent to zero being less than or equal to that other number.*)\nLemma lerDr x y : (x <= y + x) = (0 <= y).\n\n(*This lemma states that a strict inequality asserting a number is less than the sum of another number and itself is equivalent to zero being strictly less than that other number.*)\nLemma ltrDr x y : (x < y + x) = (0 < y).\n\n(*This lemma states that an inequality where a number is greater than or equal to the sum of itself and another number is equivalent to that other number being non-positive.*)\nLemma gerDl x y : (x + y <= x) = (y <= 0).\n\n(*This lemma states that an inequality where a number is greater than or equal to its difference with another number is equivalent to that other number being non-negative.*)\nLemma gerBl x y : (x - y <= x) = (0 <= y).\n\n(*This lemma states that a strict inequality where a number is greater than the sum of itself and another number is equivalent to that other number being negative.*)\nLemma gtrDl x y : (x + y < x) = (y < 0).\n\n(*This lemma states that a strict inequality where a number is greater than its difference with another number is equivalent to that other number being positive.*)\nLemma gtrBl x y : (x - y < x) = (0 < y).\n\n(*This lemma states that an inequality where a number is greater than or equal to the sum of another number and itself is equivalent to that other number being non-positive.*)\nLemma gerDr x y : (y + x <= x) = (y <= 0).\n\n(*This lemma states that a strict inequality where a number is greater than the sum of another number and itself is equivalent to that other number being negative.*)\nLemma gtrDr x y : (y + x < x) = (y < 0).\n\n(*This definition bundles a set of lemmas for simplifying inequalities involving addition by providing rules for cancelling a common term from both sides of strict and non-strict inequalities.*)\nDefinition cprD := (lerDl, lerDr, gerDl, gerDl,\n ltrDl, ltrDr, gtrDl, gtrDl).\n\n(*This lemma states that adding a non-negative number to the larger side of a 'less than or equal to' inequality preserves the relation.*)\nLemma ler_wpDl y x z : 0 <= x -> y <= z -> y <= x + z.\n\n(*This lemma states that adding a non-negative number to the larger side of a strict 'less than' inequality preserves the relation.*)\nLemma ltr_wpDl y x z : 0 <= x -> y < z -> y < x + z.\n\n(*This lemma states that adding a positive number to the larger side of a 'less than or equal to' inequality makes the inequality strict.*)\nLemma ltr_pwDl y x z : 0 < x -> y <= z -> y < x + z.\n\n(*This lemma states that adding a positive number to the larger side of a strict 'less than' inequality preserves the strict inequality.*)\nLemma ltr_pDl y x z : 0 < x -> y < z -> y < x + z.\n\n(*This lemma states that adding a non-positive number to the smaller side of a 'less than or equal to' inequality preserves the inequality.*)\nLemma ler_wnDl y x z : x <= 0 -> y <= z -> x + y <= z.\n\n(*This lemma states that if a first real number is less than or equal to zero, and a second real number is strictly less than a third, then the sum of the first and second numbers is strictly less than the third.*)\nLemma ltr_wnDl y x z : x <= 0 -> y < z -> x + y < z.\n\n(*This lemma states that if a first real number is strictly less than zero, and a second real number is less than or equal to a third, then the sum of the first and second numbers is strictly less than the third.*)\nLemma ltr_nwDl y x z : x < 0 -> y <= z -> x + y < z.\n\n(*This lemma states that if a first real number is strictly less than zero, and a second real number is strictly less than a third, then the sum of the first and second numbers is strictly less than the third.*)\nLemma ltr_nDl y x z : x < 0 -> y < z -> x + y < z.\n\n(*This lemma states that if a first real number is greater than or equal to zero, and a second real number is less than or equal to a third, then the second number is less than or equal to the sum of the third number and the first number.*)\nLemma ler_wpDr y x z : 0 <= x -> y <= z -> y <= z + x.\n\n(*This lemma states that if a first real number is greater than or equal to zero, and a second real number is strictly less than a third, then the second number is strictly less than the sum of the third number and the first number.*)\nLemma ltr_wpDr y x z : 0 <= x -> y < z -> y < z + x.\n\n(*This lemma states that if a first real number is strictly greater than zero, and a second real number is less than or equal to a third, then the second number is strictly less than the sum of the third number and the first number.*)\nLemma ltr_pwDr y x z : 0 < x -> y <= z -> y < z + x.\n\n(*This lemma states that if a first real number is strictly greater than zero, and a second real number is strictly less than a third, then the second number is strictly less than the sum of the third number and the first number.*)\nLemma ltr_pDr y x z : 0 < x -> y < z -> y < z + x.\n\n(*This lemma states that if a first real number is less than or equal to zero, and a second real number is less than or equal to a third, then the sum of the second and first numbers is less than or equal to the third number.*)\nLemma ler_wnDr y x z : x <= 0 -> y <= z -> y + x <= z.\n\n(*This lemma states that if a first real number is less than or equal to zero, and a second real number is strictly less than a third, then the sum of the second and first numbers is strictly less than the third number.*)\nLemma ltr_wnDr y x z : x <= 0 -> y < z -> y + x < z.\n\n(*This lemma states that if a first real number is strictly less than zero, and a second real number is less than or equal to a third, then the sum of the second and first numbers is strictly less than the third number.*)\nLemma ltr_nwDr y x z : x < 0 -> y <= z -> y + x < z.\n\n(*This lemma states that if a first real number is strictly less than zero, and a second real number is strictly less than a third, then the sum of the second and first numbers is strictly less than the third number.*)\nLemma ltr_nDr y x z : x < 0 -> y < z -> y + x < z.\n\n(*This lemma states that for two non-negative real numbers, their sum is equal to zero if and only if both numbers are individually equal to zero.*)\nLemma paddr_eq0 (x y : R) :\n 0 <= x -> 0 <= y -> (x + y == 0) = (x == 0) && (y == 0).\n\n(*This lemma states that for two non-positive real numbers, their sum is equal to zero if and only if both numbers are individually equal to zero.*)\nLemma naddr_eq0 (x y : R) :\n x <= 0 -> y <= 0 -> (x + y == 0) = (x == 0) && (y == 0).\n\n(*This lemma states that for two real numbers of the same sign, meaning both non-negative or both non-positive, their sum is equal to zero if and only if both numbers are individually equal to zero.*)\nLemma addr_ss_eq0 (x y : R) :\n (0 <= x) && (0 <= y) || (x <= 0) && (y <= 0) ->\n (x + y == 0) = (x == 0) && (y == 0).\n\n(*This lemma states that the sum of real numbers produced by a function over a finite sequence of elements is greater than or equal to zero, provided that the function yields a non-negative value for every element in the sequence that satisfies a given predicate.*)\nLemma sumr_ge0 I (r : seq I) (P : pred I) (F : I -> R) :\n (forall i, P i -> (0 <= F i)) -> 0 <= \\sum_(i <- r | P i) (F i).\n\n(*This lemma states that for two functions that produce real numbers, if the first function's output is less than or equal to the second's for all elements in a finite sequence satisfying a predicate, then the sum of the first function's values is less than or equal to the sum of the second function's values over those same elements.*)\nLemma ler_sum I (r : seq I) (P : pred I) (F G : I -> R) :\n (forall i, P i -> F i <= G i) ->\n \\sum_(i <- r | P i) F i <= \\sum_(i <- r | P i) G i.\n\n(*This lemma states that for two functions from natural numbers to real numbers, if the first function's output is less than or equal to the second's for all natural numbers in a given range, then the sum of the first function's values over that range is less than or equal to the sum of the second function's values over the same range.*)\nLemma ler_sum_nat (m n : nat) (F G : nat -> R) :\n (forall i, (m <= i < n)%N -> F i <= G i) ->\n \\sum_(m <= i < n) F i <= \\sum_(m <= i < n) G i.\n\n(*This lemma states that for a sum of non-negative real numbers over a finite sequence, the sum is equal to zero if and only if every term in the sum is individually equal to zero. Specifically, for every element in the sequence, if it satisfies the given predicate, its corresponding function value must be zero.*)\nLemma psumr_eq0 (I : eqType) (r : seq I) (P : pred I) (F : I -> R) :\n (forall i, P i -> 0 <= F i) ->\n (\\sum_(i <- r | P i) (F i) == 0) = (all (fun i => (P i) ==> (F i == 0)) r).\n\n(*This lemma states that if a sum of non-negative real numbers over all elements of a finite type that satisfy a given predicate is equal to zero, then the function producing these numbers must evaluate to zero for every element that satisfies the predicate.*)\nLemma psumr_eq0P (I : finType) (P : pred I) (F : I -> R) :\n (forall i, P i -> 0 <= F i) -> \\sum_(i | P i) F i = 0 ->\n (forall i, P i -> F i = 0).\n\n(*This lemma states that for a sum of non-negative real numbers over a finite sequence, the sum is not equal to zero if and only if there exists at least one element in the sequence that both satisfies a given predicate and corresponds to a strictly positive function value.*)\nLemma psumr_neq0 (I : eqType) (r : seq I) (P : pred I) (F : I -> R) :\n (forall i, P i -> 0 <= F i) ->\n (\\sum_(i <- r | P i) (F i) != 0) = (has (fun i => P i && (0 < F i)) r).\n\n(*This lemma states that if a sum of non-negative real numbers over all elements of a finite type that satisfy a given predicate is not equal to zero, then there must exist at least one element that satisfies the predicate and for which the function produces a strictly positive value.*)\nLemma psumr_neq0P (I : finType) (P : pred I) (F : I -> R) :\n (forall i, P i -> 0 <= F i) -> \\sum_(i | P i) F i <> 0 ->\n (exists i, P i && (0 < F i)).\n\n(*This lemma states that for a strictly positive real number, the function that performs left-multiplication by this number is monotonic; that is, it preserves the less-than-or-equal-to relation.*)\nLemma ler_pM2l x : 0 < x -> {mono *%R x : x y / x <= y}.\n\n(*This lemma states that for a strictly positive real number, the function that performs left-multiplication by this number is strictly monotonic; that is, it preserves the strict less-than relation.*)\nLemma ltr_pM2l x : 0 < x -> {mono *%R x : x y / x < y}.\n\n(*This definition bundles two properties, stating that for a strictly positive real number, left-multiplication by this number preserves both the less-than-or-equal-to relation and the strict less-than relation.*)\nDefinition lter_pM2l := (ler_pM2l, ltr_pM2l).\n\n(*This lemma states that for a strictly positive real number, the function that performs right-multiplication by this number is monotonic; that is, it preserves the less-than-or-equal-to relation.*)\nLemma ler_pM2r x : 0 < x -> {mono *%R^~ x : x y / x <= y}.\n\n(*This lemma states that for a strictly positive real number, the function that performs right-multiplication by this number is strictly monotonic; that is, it preserves the strict less-than relation.*)\nLemma ltr_pM2r x : 0 < x -> {mono *%R^~ x : x y / x < y}.\n\n(*This definition bundles two properties, stating that for a strictly positive real number, right-multiplication by this number preserves both the less-than-or-equal-to relation and the strict less-than relation.*)\nDefinition lter_pM2r := (ler_pM2r, ltr_pM2r).\n\n(*This lemma states that for a strictly negative real number, the function that performs left-multiplication by this number is anti-monotonic; that is, it reverses the less-than-or-equal-to relation, mapping it to a greater-than-or-equal-to relation.*)\nLemma ler_nM2l x : x < 0 -> {mono *%R x : x y /~ x <= y}.\n\n(*This lemma states that for a strictly negative real number, the function that performs left-multiplication by this number is strictly anti-monotonic; that is, it reverses the strict less-than relation, mapping it to a strict greater-than relation.*)\nLemma ltr_nM2l x : x < 0 -> {mono *%R x : x y /~ x < y}.\n\n(*This definition bundles two properties, stating that for a strictly negative real number, left-multiplication by this number is anti-monotonic, reversing both the less-than-or-equal-to relation and the strict less-than relation.*)\nDefinition lter_nM2l := (ler_nM2l, ltr_nM2l).\n\n(*This lemma states that for a negative ring element, the function of right multiplication by that element is non-increasing, meaning it reverses the 'less than or equal to' relationship.*)\nLemma ler_nM2r x : x < 0 -> {mono *%R^~ x : x y /~ x <= y}.\n\n(*This lemma states that for a negative ring element, the function of right multiplication by that element is strictly non-increasing, meaning it reverses the strict 'less than' relationship.*)\nLemma ltr_nM2r x : x < 0 -> {mono *%R^~ x : x y /~ x < y}.\n\n(*This definition bundles two lemmas, one stating that right multiplication by a negative ring element is non-increasing for the 'less than or equal to' relation, and the other stating it is strictly non-increasing for the 'less than' relation.*)\nDefinition lter_nM2r := (ler_nM2r, ltr_nM2r).\n\n(*This lemma states that for a non-negative ring element, the function of left multiplication by that element is non-decreasing, meaning it preserves the 'less than or equal to' relationship.*)\nLemma ler_wpM2l x : 0 <= x -> {homo *%R x : y z / y <= z}.\n\n(*This lemma states that for a non-negative ring element, the function of right multiplication by that element is non-decreasing, meaning it preserves the 'less than or equal to' relationship.*)\nLemma ler_wpM2r x : 0 <= x -> {homo *%R^~ x : y z / y <= z}.\n\n(*This lemma states that for a non-positive ring element, the function of left multiplication by that element is non-increasing, meaning it reverses the 'less than or equal to' relationship.*)\nLemma ler_wnM2l x : x <= 0 -> {homo *%R x : y z /~ y <= z}.\n\n(*This lemma states that for a non-positive ring element, the function of right multiplication by that element is non-increasing, meaning it reverses the 'less than or equal to' relationship.*)\nLemma ler_wnM2r x : x <= 0 -> {homo *%R^~ x : y z /~ y <= z}.\n\n(*This lemma states that for four ring elements, if two elements are less than or equal to their respective counterparts, and the two smaller elements are both non-negative, then the product of the smaller elements is less than or equal to the product of the larger elements.*)\nLemma ler_pM x1 y1 x2 y2 :\n 0 <= x1 -> 0 <= x2 -> x1 <= y1 -> x2 <= y2 -> x1 * x2 <= y1 * y2.\n\n(*This lemma states that for four ring elements, if two elements are strictly less than their respective counterparts, and the two smaller elements are both non-negative, then the product of the smaller elements is strictly less than the product of the larger elements.*)\nLemma ltr_pM x1 y1 x2 y2 :\n 0 <= x1 -> 0 <= x2 -> x1 < y1 -> x2 < y2 -> x1 * x2 < y1 * y2.\n\n(*This lemma states that for any positive natural number, the function that repeatedly adds a ring element to itself that many times is non-decreasing, preserving the 'less than or equal to' relation.*)\nLemma ler_pMn2r n : (0 < n)%N -> {mono (@GRing.natmul R)^~ n : x y / x <= y}.\n\n(*This lemma states that for any positive natural number, the function that repeatedly adds a ring element to itself that many times is strictly increasing, preserving the strict 'less than' relation.*)\nLemma ltr_pMn2r n : (0 < n)%N -> {mono (@GRing.natmul R)^~ n : x y / x < y}.\n\n(*This lemma asserts that for any positive natural number, the function that repeatedly adds a ring element to itself that many times is injective, meaning different ring elements will produce different results.*)\nLemma pmulrnI n : (0 < n)%N -> injective ((@GRing.natmul R)^~ n).\n\n(*This lemma states that for any positive natural number, the function that repeatedly adds a ring element to itself that many times preserves and reflects equality; two ring elements are equal if and only if their results under this function are equal.*)\nLemma eqr_pMn2r n : (0 < n)%N -> {mono (@GRing.natmul R)^~ n : x y / x == y}.\n\n(*This lemma states that for any positive natural number, the repeated sum of a ring element is positive if and only if the ring element itself is positive.*)\nLemma pmulrn_lgt0 x n : (0 < n)%N -> (0 < x *+ n) = (0 < x).\n\n(*This lemma states that for any positive natural number, the repeated sum of a ring element is negative if and only if the ring element itself is negative.*)\nLemma pmulrn_llt0 x n : (0 < n)%N -> (x *+ n < 0) = (x < 0).\n\n(*This lemma states that for any positive natural number, the repeated sum of a ring element is non-negative if and only if the ring element itself is non-negative.*)\nLemma pmulrn_lge0 x n : (0 < n)%N -> (0 <= x *+ n) = (0 <= x).\n\n(*This lemma states that for any positive natural number, the repeated sum of a ring element is non-positive if and only if the ring element itself is non-positive.*)\nLemma pmulrn_lle0 x n : (0 < n)%N -> (x *+ n <= 0) = (x <= 0).\n\n(*This lemma states that if one ring element is strictly less than another, then the repeated sum of the first element is strictly less than the repeated sum of the second if and only if the number of repetitions is a positive natural number.*)\nLemma ltr_wMn2r x y n : x < y -> (x *+ n < y *+ n) = (0 < n)%N.\n\n(*This lemma states that for a positive natural number, the function that repeatedly adds a ring element to itself that number of times is strictly increasing, preserving the strict 'less than' relation.*)\nLemma ltr_wpMn2r n : (0 < n)%N -> {homo (@GRing.natmul R)^~ n : x y / x < y}.\n\n(*This lemma states that the function which repeatedly adds a ring element to itself a given number of times is non-decreasing, preserving the 'less than or equal to' relationship.*)\nLemma ler_wMn2r n : {homo (@GRing.natmul R)^~ n : x y / x <= y}.\n\n(*This lemma states that if a ring element is non-negative, then repeatedly adding it to itself any number of times results in a non-negative value.*)\nLemma mulrn_wge0 x n : 0 <= x -> 0 <= x *+ n.\n\n(*This lemma states that if a ring element is non-positive, then repeatedly adding it to itself any number of times results in a non-positive value.*)\nLemma mulrn_wle0 x n : x <= 0 -> x *+ n <= 0.\n\n(*This lemma provides an equivalence for comparing the repeated sums of two ring elements. It states that the repeated sum of a first element is less than or equal to the repeated sum of a second element if and only if the number of repetitions is zero or the first element is less than or equal to the second.*)\nLemma lerMn2r n x y : (x *+ n <= y *+ n) = ((n == 0) || (x <= y)).\n\n(*This lemma provides an equivalence for the strict comparison of repeated sums of two ring elements. It states that the repeated sum of a first element is strictly less than the repeated sum of a second element if and only if the number of repetitions is a positive natural number and the first element is strictly less than the second.*)\nLemma ltrMn2r n x y : (x *+ n < y *+ n) = ((0 < n)%N && (x < y)).\n\n(*This lemma states that the repeated sum of a first ring element equals the repeated sum of a second ring element if and only if the number of repetitions is zero or the two ring elements are themselves equal.*)\nLemma eqrMn2r n x y : (x *+ n == y *+ n) = (n == 0)%N || (x == y).\n\n(*This lemma states that the repeated sum of a ring element equals zero if and only if either the ring element is zero or the number of repetitions is zero.*)\nLemma mulrn_eq0 x n : (x *+ n == 0) = ((n == 0)%N || (x == 0)).\n\n(*This lemma states that a ring element is equal to its additive inverse if and only if the element is zero.*)\nLemma eqNr x : (- x == x) = (x == 0).\n\n(*This lemma states that for any non-zero ring element, the function that computes its repeated sum for a given number of times is injective with respect to the number of repetitions.*)\nLemma mulrIn x : x != 0 -> injective (GRing.natmul x).\n\n(*This lemma states that for a non-negative ring element, the function mapping a natural number to the repeated sum of that element is non-decreasing; if a first natural number is less than or equal to a second, then the repeated sum for the first number is less than or equal to the repeated sum for the second number.*)\nLemma ler_wpMn2l x :\n 0 <= x -> {homo (@GRing.natmul R x) : m n / (m <= n)%N >-> m <= n}.\n\n(*This lemma states that for a non-positive ring element, the function mapping a natural number to the repeated sum of that element is non-increasing; if a first natural number is less than or equal to a second, then the repeated sum for the second number is less than or equal to the repeated sum for the first number.*)\nLemma ler_wnMn2l x :\n x <= 0 -> {homo (@GRing.natmul R x) : m n / (n <= m)%N >-> m <= n}.\n\n(*This lemma states that for a ring element that is greater than zero, its product with a natural number is also greater than zero if and only if the natural number is positive.*)\nLemma mulrn_wgt0 x n : 0 < x -> 0 < x *+ n = (0 < n)%N.\n\n(*This lemma states that for a ring element that is less than zero, its product with a natural number is also less than zero if and only if the natural number is positive.*)\nLemma mulrn_wlt0 x n : x < 0 -> x *+ n < 0 = (0 < n)%N.\n\n(*This lemma states that for a ring element greater than zero, the function that multiplies it by a natural number is non-decreasing; that is, if one natural number is less than or equal to another, their respective products with the ring element maintain the same order relation.*)\nLemma ler_pMn2l x :\n 0 < x -> {mono (@GRing.natmul R x) : m n / (m <= n)%N >-> m <= n}.\n\n(*This lemma states that for a ring element greater than zero, the function that multiplies it by a natural number is strictly increasing; that is, if one natural number is strictly less than another, their respective products with the ring element maintain the same strict order relation.*)\nLemma ltr_pMn2l x :\n 0 < x -> {mono (@GRing.natmul R x) : m n / (m < n)%N >-> m < n}.\n\n(*This lemma states that for a ring element less than zero, the function that multiplies it by a natural number is non-increasing; that is, if one natural number is less than or equal to another, their respective products with the ring element have the reverse order relation.*)\nLemma ler_nMn2l x :\n x < 0 -> {mono (@GRing.natmul R x) : m n / (n <= m)%N >-> m <= n}.\n\n(*This lemma states that for a ring element less than zero, the function that multiplies it by a natural number is strictly decreasing; that is, if one natural number is strictly less than another, their respective products with the ring element have the reverse strict order relation.*)\nLemma ltr_nMn2l x :\n x < 0 -> {mono (@GRing.natmul R x) : m n / (n < m)%N >-> m < n}.\n\n(*This lemma states that for any two natural numbers, the non-strict order relation between them is equivalent to the non-strict order relation between their corresponding representations as ring elements.*)\nLemma ler_nat m n : (m%:R <= n%:R :> R) = (m <= n)%N.\n\n(*This lemma states that for any two natural numbers, the strict order relation between them is equivalent to the strict order relation between their corresponding representations as ring elements.*)\nLemma ltr_nat m n : (m%:R < n%:R :> R) = (m < n)%N.\n\n(*This lemma states that for any two natural numbers, their equality is equivalent to the equality of their corresponding representations as ring elements.*)\nLemma eqr_nat m n : (m%:R == n%:R :> R) = (m == n)%N.\n\n(*This lemma states that a natural number's representation as a ring element is equal to the ring's multiplicative identity if and only if the natural number itself is one.*)\nLemma pnatr_eq1 n : (n%:R == 1 :> R) = (n == 1)%N.\n\n(*This lemma states that the ring representation of a natural number is less than or equal to the ring's zero element if and only if the natural number is itself zero.*)\nLemma lern0 n : (n%:R <= 0 :> R) = (n == 0).\n\n(*This lemma states that the ring representation of a natural number is never strictly less than the ring's zero element.*)\nLemma ltrn0 n : (n%:R < 0 :> R) = false.\n\n(*This lemma states that the ring's multiplicative identity is less than or equal to the ring representation of a natural number if and only if the natural number one is less than or equal to that natural number.*)\nLemma ler1n n : 1 <= n%:R :> R = (1 <= n)%N. \n(*This lemma states that the ring's multiplicative identity is strictly less than the ring representation of a natural number if and only if the natural number one is strictly less than that natural number.*)\nLemma ltr1n n : 1 < n%:R :> R = (1 < n)%N. \n(*This lemma states that the ring representation of a natural number is less than or equal to the ring's multiplicative identity if and only if the natural number is less than or equal to one.*)\nLemma lern1 n : n%:R <= 1 :> R = (n <= 1)%N. \n(*This lemma states that the ring representation of a natural number is strictly less than the ring's multiplicative identity if and only if the natural number itself is strictly less than one.*)\nLemma ltrn1 n : n%:R < 1 :> R = (n < 1)%N. \n\n(*This lemma states that in an ordered ring, the additive inverse of the multiplicative identity is strictly less than zero.*)\nLemma ltrN10 : -1 < 0 :> R. \n(*This lemma states that in an ordered ring, the additive inverse of the multiplicative identity is less than or equal to zero.*)\nLemma lerN10 : -1 <= 0 :> R. \n(*This lemma states that in an ordered ring, it is false that the multiplicative identity is strictly less than zero.*)\nLemma ltr10 : 1 < 0 :> R = false. \n(*This lemma states that in a non-trivial ordered ring, it is false that the multiplicative identity is less than or equal to zero.*)\nLemma ler10 : 1 <= 0 :> R = false. \n(*This lemma states that in an ordered ring, it is false that zero is strictly less than the additive inverse of the multiplicative identity.*)\nLemma ltr0N1 : 0 < -1 :> R = false. \n(*This lemma states that in a non-trivial ordered ring, it is false that zero is less than or equal to the additive inverse of the multiplicative identity.*)\nLemma ler0N1 : 0 <= -1 :> R = false. \n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"use `mulrn_wgt0` instead\")]\n(*This lemma states that for a positive ring element, its product with a natural number is positive if and only if the natural number is positive. This lemma is deprecated in favor of the lemma named `mulrn_wgt0`.*)\nLemma pmulrn_rgt0 x n : 0 < x -> 0 < x *+ n = (0 < n)%N.\n\n(*This lemma states that for a positive ring element, its product with any natural number is never negative.*)\nLemma pmulrn_rlt0 x n : 0 < x -> x *+ n < 0 = false.\n\n(*This lemma states that for a positive ring element, its product with any natural number is always non-negative.*)\nLemma pmulrn_rge0 x n : 0 < x -> 0 <= x *+ n.\n\n(*This lemma states that for a positive ring element, its product with a natural number is less than or equal to zero if and only if the natural number is zero.*)\nLemma pmulrn_rle0 x n : 0 < x -> x *+ n <= 0 = (n == 0)%N.\n\n(*This lemma states that for a negative ring element, its product with any natural number is never positive.*)\nLemma nmulrn_rgt0 x n : x < 0 -> 0 < x *+ n = false.\n\n(*This lemma states that for a negative ring element, its product with a natural number is non-negative if and only if the natural number is zero.*)\nLemma nmulrn_rge0 x n : x < 0 -> 0 <= x *+ n = (n == 0)%N.\n\n(*This lemma states that for a negative ring element, its product with any natural number is always non-positive.*)\nLemma nmulrn_rle0 x n : x < 0 -> x *+ n <= 0.\n\n(*This lemma states that in an ordered ring, the product of a positive ring element with another ring element is negative if and only if the second ring element is negative.*)\nLemma pmulr_rlt0 x y : 0 < x -> (x * y < 0) = (y < 0).\n\n(*This lemma states that for a positive first number, its product with a second number is less than or equal to zero if and only if the second number is less than or equal to zero.*)\nLemma pmulr_rle0 x y : 0 < x -> (x * y <= 0) = (y <= 0).\n\n(*This lemma states that for a positive first number, the product of a second number with the first number is greater than zero if and only if the second number is also greater than zero.*)\nLemma pmulr_lgt0 x y : 0 < x -> (0 < y * x) = (0 < y).\n\n(*This lemma states that for a positive first number, the product of a second number with the first number is greater than or equal to zero if and only if the second number is also greater than or equal to zero.*)\nLemma pmulr_lge0 x y : 0 < x -> (0 <= y * x) = (0 <= y).\n\n(*This lemma states that for a positive first number, the product of a second number with the first number is less than zero if and only if the second number is also less than zero.*)\nLemma pmulr_llt0 x y : 0 < x -> (y * x < 0) = (y < 0).\n\n(*This lemma states that for a positive first number, the product of a second number with the first number is less than or equal to zero if and only if the second number is also less than or equal to zero.*)\nLemma pmulr_lle0 x y : 0 < x -> (y * x <= 0) = (y <= 0).\n\n(*This lemma states that when a first number is negative, the product of this number and a second number is greater than zero if and only if the second number is also negative.*)\nLemma nmulr_rgt0 x y : x < 0 -> (0 < x * y) = (y < 0).\n\n(*This lemma states that when a first number is negative, the product of this number and a second number is greater than or equal to zero if and only if the second number is less than or equal to zero.*)\nLemma nmulr_rge0 x y : x < 0 -> (0 <= x * y) = (y <= 0).\n\n(*This lemma states that when a first number is negative, the product of this number and a second number is less than zero if and only if the second number is greater than zero.*)\nLemma nmulr_rlt0 x y : x < 0 -> (x * y < 0) = (0 < y).\n\n(*This lemma states that when a first number is negative, the product of this number and a second number is less than or equal to zero if and only if the second number is greater than or equal to zero.*)\nLemma nmulr_rle0 x y : x < 0 -> (x * y <= 0) = (0 <= y).\n\n(*This lemma states that when a first number is negative, the product of a second number and the first number is greater than zero if and only if the second number is also negative.*)\nLemma nmulr_lgt0 x y : x < 0 -> (0 < y * x) = (y < 0).\n\n(*This lemma states that when a first number is negative, the product of a second number and the first number is greater than or equal to zero if and only if the second number is less than or equal to zero.*)\nLemma nmulr_lge0 x y : x < 0 -> (0 <= y * x) = (y <= 0).\n\n(*This lemma states that when a first number is negative, the product of a second number and the first number is less than zero if and only if the second number is greater than zero.*)\nLemma nmulr_llt0 x y : x < 0 -> (y * x < 0) = (0 < y).\n\n(*This lemma states that when a first number is negative, the product of a second number and the first number is less than or equal to zero if and only if the second number is greater than or equal to zero.*)\nLemma nmulr_lle0 x y : x < 0 -> (y * x <= 0) = (0 <= y).\n\n(*This lemma states that the product of two numbers that are both greater than or equal to zero is itself greater than or equal to zero.*)\nLemma mulr_ge0 x y : 0 <= x -> 0 <= y -> 0 <= x * y.\n\n(*This lemma states that the product of two numbers that are both less than or equal to zero is greater than or equal to zero.*)\nLemma mulr_le0 x y : x <= 0 -> y <= 0 -> 0 <= x * y.\n\n(*This lemma states that the product of a number greater than or equal to zero and a number less than or equal to zero is itself less than or equal to zero.*)\nLemma mulr_ge0_le0 x y : 0 <= x -> y <= 0 -> x * y <= 0.\n\n(*This lemma states that the product of a number less than or equal to zero and a number greater than or equal to zero is itself less than or equal to zero.*)\nLemma mulr_le0_ge0 x y : x <= 0 -> 0 <= y -> x * y <= 0.\n\n(*This lemma states that the product of two numbers that are both greater than zero is itself greater than zero.*)\nLemma mulr_gt0 x y : 0 < x -> 0 < y -> 0 < x * y.\n\n(*This lemma states that for two numbers that are both greater than or equal to zero, their product is greater than zero if and only if both numbers are themselves greater than zero.*)\nLemma mulr_ge0_gt0 x y : 0 <= x -> 0 <= y -> (0 < x * y) = (0 < x) && (0 < y).\n\n(*This lemma states that if a function maps all specified indices in a finite sequence to values that are greater than or equal to zero, then the product of these values is also greater than or equal to zero.*)\nLemma prodr_ge0 I r (P : pred I) (E : I -> R) :\n (forall i, P i -> 0 <= E i) -> 0 <= \\prod_(i <- r | P i) E i.\n\n(*This lemma states that if a function maps all specified indices in a finite sequence to values that are strictly greater than zero, then the product of these values is also strictly greater than zero.*)\nLemma prodr_gt0 I r (P : pred I) (E : I -> R) :\n (forall i, P i -> 0 < E i) -> 0 < \\prod_(i <- r | P i) E i.\n\n(*This lemma states that for two functions mapping indices to values, if for all specified indices in a finite sequence the value from the first function is non-negative and less than or equal to the value from the second function, then the iterated product of values from the first function is less than or equal to the iterated product of values from the second function.*)\nLemma ler_prod I r (P : pred I) (E1 E2 : I -> R) :\n (forall i, P i -> 0 <= E1 i <= E2 i) ->\n \\prod_(i <- r | P i) E1 i <= \\prod_(i <- r | P i) E2 i.\n\n(*This lemma states that if for every index satisfying a given predicate in a sequence, a first function's value is non-negative and strictly less than a second function's value, and there exists at least one such index, then the product of the first function's values over those indices is strictly less than the product of the second function's values.*)\nLemma ltr_prod I r (P : pred I) (E1 E2 : I -> R) :\n has P r -> (forall i, P i -> 0 <= E1 i < E2 i) ->\n \\prod_(i <- r | P i) E1 i < \\prod_(i <- r | P i) E2 i.\n\n(*This lemma states that given two functions from natural numbers to a ring, if for every natural number in a non-empty range, the value of the first function is non-negative and strictly less than the value of the second function, then the product of the first function's values over that range is strictly less than the product of the second function's values.*)\nLemma ltr_prod_nat (E1 E2 : nat -> R) (n m : nat) :\n (m < n)%N -> (forall i, (m <= i < n)%N -> 0 <= E1 i < E2 i) ->\n \\prod_(m <= i < n) E1 i < \\prod_(m <= i < n) E2 i.\n\n(*This lemma states that the product of a non-zero real number and another number is real if and only if the other number is also real.*)\nLemma realMr x y : x != 0 -> x \\is real -> (x * y \\is real) = (y \\is real).\n\n(*This lemma states that the product of a first number and a second non-zero real number is real if and only if the first number is real.*)\nLemma realrM x y : y != 0 -> y \\is real -> (x * y \\is real) = (x \\is real).\n\n(*This lemma states that the product of any two real numbers is itself a real number.*)\nLemma realM : {in real &, forall x y, x * y \\is real}.\n\n(*This lemma states that for any non-zero natural number, the repeated sum of a ring element with itself that many times results in a real number if and only if the original ring element is real.*)\nLemma realrMn x n : (n != 0)%N -> (x *+ n \\is real) = (x \\is real).\n\n(*This lemma states that when a number is multiplied by a strictly positive number, the result is less than or equal to the positive number if and only if the original number is less than or equal to one.*)\nLemma ger_pMl x y : 0 < y -> (x * y <= y) = (x <= 1).\n\n(*This lemma states that when a number is multiplied by a strictly positive number, the result is strictly less than the positive number if and only if the original number is strictly less than one.*)\nLemma gtr_pMl x y : 0 < y -> (x * y < y) = (x < 1).\n\n(*This lemma states that when a strictly positive number is multiplied by another number, the result is less than or equal to the positive number if and only if the other number is less than or equal to one.*)\nLemma ger_pMr x y : 0 < y -> (y * x <= y) = (x <= 1).\n\n(*This lemma states that when a strictly positive number is multiplied by another number, the result is strictly less than the positive number if and only if the other number is strictly less than one.*)\nLemma gtr_pMr x y : 0 < y -> (y * x < y) = (x < 1).\n\n(*This lemma states that for a strictly positive number, it is less than or equal to its product with another number if and only if one is less than or equal to that other number.*)\nLemma ler_pMl x y : 0 < y -> (y <= x * y) = (1 <= x).\n\n(*This lemma states that for a strictly positive number, it is strictly less than its product with another number if and only if one is strictly less than that other number.*)\nLemma ltr_pMl x y : 0 < y -> (y < x * y) = (1 < x).\n\n(*This lemma states that a strictly positive number is less than or equal to its product with another number if and only if one is less than or equal to that other number.*)\nLemma ler_pMr x y : 0 < y -> (y <= y * x) = (1 <= x).\n\n(*This lemma states that a strictly positive number is strictly less than its product with another number if and only if one is strictly less than that other number.*)\nLemma ltr_pMr x y : 0 < y -> (y < y * x) = (1 < x).\n\n(*This lemma states that when a number is multiplied by a strictly negative number, the result is less than or equal to the negative number if and only if one is less than or equal to the original number.*)\nLemma ger_nMl x y : y < 0 -> (x * y <= y) = (1 <= x).\n\n(*This lemma states that when a number is multiplied by a strictly negative number, the result is strictly less than the negative number if and only if one is strictly less than the original number.*)\nLemma gtr_nMl x y : y < 0 -> (x * y < y) = (1 < x).\n\n(*This lemma states that when a strictly negative number is multiplied by another number, the result is less than or equal to the negative number if and only if one is less than or equal to the other number.*)\nLemma ger_nMr x y : y < 0 -> (y * x <= y) = (1 <= x).\n\n(*This lemma states that when a strictly negative number is multiplied by another number, the result is strictly less than the negative number if and only if one is strictly less than the other number.*)\nLemma gtr_nMr x y : y < 0 -> (y * x < y) = (1 < x).\n\n(*This lemma states that for a strictly negative number, it is less than or equal to its product with another number if and only if that other number is less than or equal to one.*)\nLemma ler_nMl x y : y < 0 -> (y <= x * y) = (x <= 1).\n\n(*This lemma states that for a strictly negative number, it is strictly less than its product with another number if and only if that other number is strictly less than one.*)\nLemma ltr_nMl x y : y < 0 -> (y < x * y) = (x < 1).\n\n(*This lemma states that a strictly negative number is less than or equal to its product with another number if and only if that other number is less than or equal to one.*)\nLemma ler_nMr x y : y < 0 -> (y <= y * x) = (x <= 1).\n\n(*This lemma states that a strictly negative number is strictly less than its product with another number if and only if that other number is strictly less than one.*)\nLemma ltr_nMr x y : y < 0 -> (y < y * x) = (x < 1).\n\n(*This lemma states that multiplying a non-negative number by a number greater than or equal to one yields a product that is at least as large as the original non-negative number.*)\nLemma ler_peMl x y : 0 <= y -> 1 <= x -> y <= x * y.\n\n(*This lemma states that multiplying a non-positive number on the left by a number greater than or equal to one yields a result that is less than or equal to the original non-positive number.*)\nLemma ler_neMl x y : y <= 0 -> 1 <= x -> x * y <= y.\n\n(*This lemma states that multiplying a non-negative number on the right by a number greater than or equal to one yields a result that is greater than or equal to the original non-negative number.*)\nLemma ler_peMr x y : 0 <= y -> 1 <= x -> y <= y * x.\n\n(*This lemma states that multiplying a non-positive number on the right by a number greater than or equal to one yields a result that is less than or equal to the original non-positive number.*)\nLemma ler_neMr x y : y <= 0 -> 1 <= x -> y * x <= y.\n\n(*This lemma states that multiplying a non-negative number on the left by a number less than or equal to one yields a result that is less than or equal to the original non-negative number.*)\nLemma ler_piMl x y : 0 <= y -> x <= 1 -> x * y <= y.\n\n(*This lemma states that multiplying a non-positive number on the left by a number less than or equal to one yields a result that is greater than or equal to the original non-positive number.*)\nLemma ler_niMl x y : y <= 0 -> x <= 1 -> y <= x * y.\n\n(*This lemma states that multiplying a non-negative number on the right by a number less than or equal to one yields a result that is less than or equal to the original non-negative number.*)\nLemma ler_piMr x y : 0 <= y -> x <= 1 -> y * x <= y.\n\n(*This lemma states that multiplying a non-positive number on the right by a number less than or equal to one yields a result that is greater than or equal to the original non-positive number.*)\nLemma ler_niMr x y : y <= 0 -> x <= 1 -> y <= y * x.\n\n(*This lemma states that the product of two numbers that are both between zero and one, inclusive, is also less than or equal to one.*)\nLemma mulr_ile1 x y : 0 <= x -> 0 <= y -> x <= 1 -> y <= 1 -> x * y <= 1.\n\n(*This lemma states that the product of two non-negative numbers that are both strictly less than one is also strictly less than one.*)\nLemma mulr_ilt1 x y : 0 <= x -> 0 <= y -> x < 1 -> y < 1 -> x * y < 1.\n\n(*This definition packages two lemmas together: one stating that the product of two numbers between zero and one inclusive is at most one, and another stating that the product of two non-negative numbers strictly less than one is also strictly less than one.*)\nDefinition mulr_ilte1 := (mulr_ile1, mulr_ilt1).\n\n(*This lemma states that the product of two numbers, both greater than or equal to one, is also greater than or equal to one.*)\nLemma mulr_ege1 x y : 1 <= x -> 1 <= y -> 1 <= x * y.\n\n(*This lemma states that the product of two numbers, both strictly greater than one, is also strictly greater than one.*)\nLemma mulr_egt1 x y : 1 < x -> 1 < y -> 1 < x * y.\n\n(*This definition packages two lemmas together: one stating that the product of two numbers greater than or equal to one is also greater than or equal to one, and another stating that the product of two numbers strictly greater than one is also strictly greater than one.*)\nDefinition mulr_egte1 := (mulr_ege1, mulr_egt1).\n(*This definition packages two collections of lemmas regarding multiplication and the value one: the first concerns numbers less than or equal to one, and the second concerns numbers greater than or equal to one.*)\nDefinition mulr_cp1 := (mulr_ilte1, mulr_egte1).\n\n(*This lemma states that the multiplicative inverse of a number is strictly greater than zero if and only if the number itself is strictly greater than zero.*)\nLemma invr_gt0 x : (0 < x^-1) = (0 < x).\n\n(*This lemma states that the multiplicative inverse of a number is greater than or equal to zero if and only if the number itself is greater than or equal to zero.*)\nLemma invr_ge0 x : (0 <= x^-1) = (0 <= x).\n\n(*This lemma states that the multiplicative inverse of a number is strictly less than zero if and only if the number itself is strictly less than zero.*)\nLemma invr_lt0 x : (x^-1 < 0) = (x < 0).\n\n(*This lemma states that the multiplicative inverse of a number is less than or equal to zero if and only if the number itself is less than or equal to zero.*)\nLemma invr_le0 x : (x^-1 <= 0) = (x <= 0).\n\n(*This definition packages two lemmas asserting that the multiplicative inverse of a number is greater than or equal to zero, or strictly greater than zero, if and only if the original number satisfies the same respective property.*)\nDefinition invr_gte0 := (invr_ge0, invr_gt0).\n(*This definition packages two lemmas asserting that the multiplicative inverse of a number is less than or equal to zero, or strictly less than zero, if and only if the original number satisfies the same respective property.*)\nDefinition invr_lte0 := (invr_le0, invr_lt0).\n\n(*This lemma states that the division of a non-negative number by another non-negative number results in a non-negative value.*)\nLemma divr_ge0 x y : 0 <= x -> 0 <= y -> 0 <= x / y.\n\n(*This lemma states that the division of a strictly positive number by another strictly positive number results in a strictly positive value.*)\nLemma divr_gt0 x y : 0 < x -> 0 < y -> 0 < x / y.\n\n(*This lemma establishes that dividing a number by itself results in a value that is considered a member of the real numbers type structure.*)\nLemma realV : {mono (@GRing.inv R) : x / x \\is real}.\n\n(*This lemma states that raising a non-negative number to the power of any natural number results in a non-negative number.*)\nLemma exprn_ge0 n x : 0 <= x -> 0 <= x ^+ n.\n\n(*This lemma establishes that raising a real number to the power of a natural number results in a value that is a member of the real numbers type structure, ensuring closure of exponentiation.*)\nLemma realX n : {in real, forall x, x ^+ n \\is real}.\n\n(*This lemma states that raising a strictly positive number to the power of any natural number results in a strictly positive number.*)\nLemma exprn_gt0 n x : 0 < x -> 0 < x ^+ n.\n\n(*This definition packages two lemmas concerning exponentiation of non-negative numbers: one stating that the result is non-negative, and another stating that if the base is strictly positive, the result is also strictly positive.*)\nDefinition exprn_gte0 := (exprn_ge0, exprn_gt0).\n\n(*This lemma states that if a non-negative number is less than or equal to one, then raising it to any natural number power results in a number that is also less than or equal to one.*)\nLemma exprn_ile1 n x : 0 <= x -> x <= 1 -> x ^+ n <= 1.\n\n(*This lemma states that for a non-negative number strictly less than one, raising it to a natural number power results in a number strictly less than one if and only if the exponent is non-zero.*)\nLemma exprn_ilt1 n x : 0 <= x -> x < 1 -> x ^+ n < 1 = (n != 0).\n\n(*This definition bundles two lemmas that compare the result of exponentiation to one when the base is a non-negative number less than or equal to one.*)\nDefinition exprn_ilte1 := (exprn_ile1, exprn_ilt1).\n\n(*This lemma states that if a number is greater than or equal to one, then raising it to any natural number power results in a number that is also greater than or equal to one.*)\nLemma exprn_ege1 n x : 1 <= x -> 1 <= x ^+ n.\n\n(*This lemma states that for a number strictly greater than one, raising it to a natural number power results in a number strictly greater than one if and only if the exponent is non-zero.*)\nLemma exprn_egt1 n x : 1 < x -> 1 < x ^+ n = (n != 0).\n\n(*This definition bundles two lemmas that compare the result of exponentiation to one when the base is a number greater than or equal to one.*)\nDefinition exprn_egte1 := (exprn_ege1, exprn_egt1).\n(*This definition combines lemmas that describe the relationship between a number raised to a power and the value one, depending on whether the base is less than, equal to, or greater than one.*)\nDefinition exprn_cp1 := (exprn_ilte1, exprn_egte1).\n\n(*This lemma states that for a non-negative number less than or equal to one, raising it to a positive natural number power results in a value less than or equal to the original number.*)\nLemma ler_iXnr x n : (0 < n)%N -> 0 <= x -> x <= 1 -> x ^+ n <= x.\n\n(*This lemma states that for a number strictly between zero and one, raising it to a natural number power results in a value strictly less than the original number if and only if the exponent is strictly greater than one.*)\nLemma ltr_iXnr x n : 0 < x -> x < 1 -> (x ^+ n < x) = (1 < n)%N.\n\n(*This definition bundles two lemmas that compare a number raised to a power with the original number itself, for bases between zero and one.*)\nDefinition lter_iXnr := (ler_iXnr, ltr_iXnr).\n\n(*This lemma states that for a number greater than or equal to one, raising it to a positive natural number power results in a value greater than or equal to the original number.*)\nLemma ler_eXnr x n : (0 < n)%N -> 1 <= x -> x <= x ^+ n.\n\n(*This lemma states that for a number strictly greater than one, raising it to a natural number power results in a value strictly greater than the original number if and only if the exponent is strictly greater than one.*)\nLemma ltr_eXnr x n : 1 < x -> (x < x ^+ n) = (1 < n)%N.\n\n(*This definition bundles two lemmas that compare a number raised to a power with the original number itself, for bases greater than or equal to one.*)\nDefinition lter_eXnr := (ler_eXnr, ltr_eXnr).\n(*This definition combines lemmas that compare a number raised to a power with the original number, covering cases where the base is either less than or greater than one.*)\nDefinition lter_Xnr := (lter_iXnr, lter_eXnr).\n\n(*This lemma states that for a number between zero and one inclusive, the function that raises it to a natural number power is order-reversing, meaning a larger or equal exponent yields a smaller or equal result.*)\nLemma ler_wiXn2l x :\n 0 <= x -> x <= 1 -> {homo GRing.exp x : m n / (n <= m)%N >-> m <= n}.\n\n(*This lemma states that for a number greater than or equal to one, the function that raises it to a natural number power is order-preserving, meaning a larger or equal exponent yields a larger or equal result.*)\nLemma ler_weXn2l x : 1 <= x -> {homo GRing.exp x : m n / (m <= n)%N >-> m <= n}.\n\n(*This lemma states that for a non-negative number, raising it to a natural number power equals one if and only if the exponent is zero or the base number itself is one.*)\nLemma ieexprn_weq1 x n : 0 <= x -> (x ^+ n == 1) = ((n == 0) || (x == 1)).\n\n(*This lemma states that for a positive number that is not equal to one, the function that raises this number to a natural number power is injective.*)\nLemma ieexprIn x : 0 < x -> x != 1 -> injective (GRing.exp x).\n\n(*This lemma establishes a strict order-reversing equivalence for exponentiation with a base strictly between zero and one: one exponent is less than or equal to another if and only if the resulting power for the second exponent is less than or equal to the resulting power for the first.*)\nLemma ler_iXn2l x :\n 0 < x -> x < 1 -> {mono GRing.exp x : m n / (n <= m)%N >-> m <= n}.\n\n(*This lemma establishes a strict order-reversing equivalence for exponentiation with a base strictly between zero and one using strict inequalities: one exponent is strictly less than another if and only if the resulting power for the second exponent is strictly less than the resulting power for the first.*)\nLemma ltr_iXn2l x :\n 0 < x -> x < 1 -> {mono GRing.exp x : m n / (n < m)%N >-> m < n}.\n\n(*This definition bundles two lemmas that establish the strict order-reversing properties of exponentiation, for both weak and strict inequalities, when the base is strictly between zero and one.*)\nDefinition lter_iXn2l := (ler_iXn2l, ltr_iXn2l).\n\n(*This lemma establishes a strict order-preserving equivalence for exponentiation with a base strictly greater than one: one exponent is less than or equal to another if and only if the resulting power for the first exponent is less than or equal to the resulting power for the second.*)\nLemma ler_eXn2l x :\n 1 < x -> {mono GRing.exp x : m n / (m <= n)%N >-> m <= n}.\n\n(*This lemma establishes a strict order-preserving equivalence for exponentiation with a base strictly greater than one using strict inequalities: one exponent is strictly less than another if and only if the resulting power for the first exponent is strictly less than the resulting power for the second.*)\nLemma ltr_eXn2l x :\n 1 < x -> {mono (GRing.exp x) : m n / (m < n)%N >-> m < n}.\n\n(*This definition bundles two lemmas that establish the strict order-preserving properties of exponentiation, for both weak and strict inequalities, when the base is strictly greater than one.*)\nDefinition lter_eXn2l := (ler_eXn2l, ltr_eXn2l).\n\n(*This lemma states that for two non-negative numbers where the first is strictly less than the second, raising them to the same natural number power preserves the strict inequality if and only if the exponent is non-zero.*)\nLemma ltrXn2r n x y : 0 <= x -> x < y -> x ^+ n < y ^+ n = (n != 0).\n\n(*This lemma states that for any given natural number exponent, the function that raises a non-negative number to that exponent is order-preserving.*)\nLemma lerXn2r n : {in nneg & , {homo (@GRing.exp R)^~ n : x y / x <= y}}.\n\n(*This definition bundles two lemmas concerning the order-preserving properties of the function that raises a non-negative number to a fixed natural number power.*)\nDefinition lterXn2r := (lerXn2r, ltrXn2r).\n\n(*This lemma states that for any positive natural number exponent, if one non-negative number is strictly less than another, then its power is also strictly less than the other's power.*)\nLemma ltr_wpXn2r n :\n (0 < n)%N -> {in nneg & , {homo (@GRing.exp R)^~ n : x y / x < y}}.\n\n(*This lemma states that for any positive natural number exponent, a non-negative number is less than or equal to another if and only if their respective powers are also less than or equal to each other.*)\nLemma ler_pXn2r n :\n (0 < n)%N -> {in nneg & , {mono (@GRing.exp R)^~ n : x y / x <= y}}.\n\n(*This lemma states that for any positive natural number exponent, a non-negative number is strictly less than another if and only if their respective powers are also strictly less than each other.*)\nLemma ltr_pXn2r n :\n (0 < n)%N -> {in nneg & , {mono (@GRing.exp R)^~ n : x y / x < y}}.\n\n(*This definition packages two lemmas: the first states that for a positive natural number exponent, the real power function is non-decreasing on non-negative real numbers, and the second states that it is strictly increasing.*)\nDefinition lter_pXn2r := (ler_pXn2r, ltr_pXn2r).\n\n(*This lemma states that for any positive natural number exponent, the function that raises a non-negative real number to that power is injective.*)\nLemma pexpIrn n : (0 < n)%N -> {in nneg &, injective ((@GRing.exp R)^~ n)}.\n\n(*This lemma states that for a positive natural number exponent and a non-negative real number base, the base raised to the exponent is less than or equal to one if and only if the base itself is less than or equal to one.*)\nLemma expr_le1 n x : (0 < n)%N -> 0 <= x -> (x ^+ n <= 1) = (x <= 1).\n\n(*This lemma states that for a positive natural number exponent and a non-negative real number base, the base raised to the exponent is strictly less than one if and only if the base itself is strictly less than one.*)\nLemma expr_lt1 n x : (0 < n)%N -> 0 <= x -> (x ^+ n < 1) = (x < 1).\n\n(*This definition packages two lemmas establishing the equivalence between a non-negative real number being less than or equal to one, or strictly less than one, and its positive integer power being less than or equal to one, or strictly less than one, respectively.*)\nDefinition expr_lte1 := (expr_le1, expr_lt1).\n\n(*This lemma states that for a positive natural number exponent and a non-negative real number base, one is less than or equal to the base raised to the exponent if and only if one is less than or equal to the base itself.*)\nLemma expr_ge1 n x : (0 < n)%N -> 0 <= x -> (1 <= x ^+ n) = (1 <= x).\n\n(*This lemma states that for a positive natural number exponent and a non-negative real number base, one is strictly less than the base raised to the exponent if and only if one is strictly less than the base itself.*)\nLemma expr_gt1 n x : (0 < n)%N -> 0 <= x -> (1 < x ^+ n) = (1 < x).\n\n(*This definition packages two lemmas establishing the equivalence between a non-negative real number being greater than or equal to one, or strictly greater than one, and its positive integer power being greater than or equal to one, or strictly greater than one, respectively.*)\nDefinition expr_gte1 := (expr_ge1, expr_gt1).\n\n(*This lemma states that for a positive natural number exponent and a non-negative real number base, the base raised to that exponent equals one if and only if the base itself equals one.*)\nLemma pexpr_eq1 x n : (0 < n)%N -> 0 <= x -> (x ^+ n == 1) = (x == 1).\n\n(*This lemma states that for a non-negative real number base and a natural number exponent, the base raised to the exponent equals one if and only if the exponent is zero or the base is one.*)\nLemma pexprn_eq1 x n : 0 <= x -> (x ^+ n == 1) = (n == 0) || (x == 1).\n\n(*This lemma states that for any two non-negative real numbers and a positive natural number exponent, their powers are equal if and only if the numbers themselves are equal.*)\nLemma eqrXn2 n x y :\n (0 < n)%N -> 0 <= x -> 0 <= y -> (x ^+ n == y ^+ n) = (x == y).\n\n(*This lemma states that for a non-negative real number, its square equals one if and only if the number itself is one.*)\nLemma sqrp_eq1 x : 0 <= x -> (x ^+ 2 == 1) = (x == 1).\n\n(*This lemma states that for a non-positive real number, its square equals one if and only if the number itself is negative one.*)\nLemma sqrn_eq1 x : x <= 0 -> (x ^+ 2 == 1) = (x == -1).\n\n(*This lemma states that the squaring function is non-decreasing over the set of non-negative real numbers.*)\nLemma ler_sqr : {in nneg &, {mono (fun x => x ^+ 2) : x y / x <= y}}.\n\n(*This lemma states that the squaring function is strictly increasing over the set of non-negative real numbers.*)\nLemma ltr_sqr : {in nneg &, {mono (fun x => x ^+ 2) : x y / x < y}}.\n\n(*This lemma states that the multiplicative inverse function is non-increasing when applied to positive, invertible real numbers.*)\nLemma ler_pV2 :\n {in [pred x in GRing.unit | 0 < x] &, {mono (@GRing.inv R) : x y /~ x <= y}}.\n\n(*This lemma states that the multiplicative inverse function is non-increasing when applied to negative, invertible real numbers.*)\nLemma ler_nV2 :\n {in [pred x in GRing.unit | x < 0] &, {mono (@GRing.inv R) : x y /~ x <= y}}.\n\n(*This lemma states that the multiplicative inverse function is strictly decreasing when applied to positive, invertible real numbers.*)\nLemma ltr_pV2 :\n {in [pred x in GRing.unit | 0 < x] &, {mono (@GRing.inv R) : x y /~ x < y}}.\n\n(*This lemma states that the multiplicative inverse function is strictly decreasing when applied to negative, invertible real numbers.*)\nLemma ltr_nV2 :\n {in [pred x in GRing.unit | x < 0] &, {mono (@GRing.inv R) : x y /~ x < y}}.\n\n(*This lemma states that for a positive, invertible real number, its multiplicative inverse is strictly greater than one if and only if the number itself is strictly less than one.*)\nLemma invr_gt1 x : x \\is a GRing.unit -> 0 < x -> (1 < x^-1) = (x < 1).\n\n(*This lemma states that for a positive, invertible real number, its multiplicative inverse is greater than or equal to one if and only if the number itself is less than or equal to one.*)\nLemma invr_ge1 x : x \\is a GRing.unit -> 0 < x -> (1 <= x^-1) = (x <= 1).\n\n(*This definition packages two lemmas establishing the equivalence between a positive, invertible real number being less than or equal to one, or strictly less than one, and its multiplicative inverse being greater than or equal to one, or strictly greater than one, respectively.*)\nDefinition invr_gte1 := (invr_ge1, invr_gt1).\n\n(*This lemma states that for a positive, invertible real number, its multiplicative inverse is less than or equal to one if and only if the number itself is greater than or equal to one.*)\nLemma invr_le1 x (ux : x \\is a GRing.unit) (hx : 0 < x) :\n (x^-1 <= 1) = (1 <= x).\n\n(*This lemma states that for a positive, invertible real number, its multiplicative inverse is strictly less than one if and only if the number itself is strictly greater than one.*)\nLemma invr_lt1 x (ux : x \\is a GRing.unit) (hx : 0 < x) : (x^-1 < 1) = (1 < x).\n\n(*This definition packages two lemmas establishing the equivalence between a positive, invertible real number being greater than or equal to one, or strictly greater than one, and its multiplicative inverse being less than or equal to one, or strictly less than one, respectively.*)\nDefinition invr_lte1 := (invr_le1, invr_lt1).\n(*This definition packages four lemmas that relate the comparison of a positive, invertible real number with one to the comparison of its multiplicative inverse with one.*)\nDefinition invr_cp1 := (invr_gte1, invr_lte1).\n\n(*This lemma states that the real number representation of the minimum of two natural numbers is equal to the minimum of their individual real number representations.*)\nLemma natr_min (m n : nat) : (Order.min m n)%:R = Order.min m%:R n%:R :> R.\n\n(*This lemma states that the real number representation of the maximum of two natural numbers is equal to the maximum of their individual real number representations.*)\nLemma natr_max (m n : nat) : (Order.max m n)%:R = Order.max m%:R n%:R :> R.\n\n(*This lemma states that for any two real numbers, the sum of their minimum and their maximum is equal to the sum of the two numbers.*)\nLemma addr_min_max x y : min x y + max x y = x + y.\n\n(*This lemma states that for any two real numbers, the sum of their maximum and their minimum is equal to the sum of the two numbers.*)\nLemma addr_max_min x y : max x y + min x y = x + y.\n\n(*This lemma states that the minimum of two numbers is equal to their sum minus their maximum.*)\nLemma minr_to_max x y : min x y = x + y - max x y.\n\n(*This lemma states that the maximum of two numbers is equal to their sum minus their minimum.*)\nLemma maxr_to_min x y : max x y = x + y - min x y.\n\n(*This lemma states that the unary negation function on real numbers acts as an order-reversing morphism that transforms the maximum of two numbers into the minimum of their negations.*)\nLemma real_oppr_max : {in real &, {morph -%R : x y / max x y >-> min x y : R}}.\n\n(*This lemma states that the unary negation function on real numbers acts as an order-reversing morphism that transforms the minimum of two numbers into the maximum of their negations.*)\nLemma real_oppr_min : {in real &, {morph -%R : x y / min x y >-> max x y : R}}.\n\n(*This lemma states that addition on real numbers distributes on the left over the minimum operation.*)\nLemma real_addr_minl : {in real & real & real, @left_distributive R R +%R min}.\n\n(*This lemma states that addition on real numbers distributes on the right over the minimum operation.*)\nLemma real_addr_minr : {in real & real & real, @right_distributive R R +%R min}.\n\n(*This lemma states that addition on real numbers distributes on the left over the maximum operation.*)\nLemma real_addr_maxl : {in real & real & real, @left_distributive R R +%R max}.\n\n(*This lemma states that addition on real numbers distributes on the right over the maximum operation.*)\nLemma real_addr_maxr : {in real & real & real, @right_distributive R R +%R max}.\n\n(*This lemma states that multiplying the minimum of two numbers by a non-negative number is equivalent to taking the minimum of the products of the non-negative number with each of the two numbers.*)\nLemma minr_pMr x y z : 0 <= x -> x * min y z = min (x * y) (x * z).\n\n(*This lemma states that multiplying the maximum of two numbers by a non-negative number is equivalent to taking the maximum of the products of the non-negative number with each of the two numbers.*)\nLemma maxr_pMr x y z : 0 <= x -> x * max y z = max (x * y) (x * z).\n\n(*This lemma states that for real numbers, multiplying the maximum of two numbers by a non-positive number is equivalent to taking the minimum of the products of the non-positive number with each of the two numbers.*)\nLemma real_maxr_nMr x y z : x <= 0 -> y \\is real -> z \\is real ->\n x * max y z = min (x * y) (x * z).\n\n(*This lemma states that for real numbers, multiplying the minimum of two numbers by a non-positive number is equivalent to taking the maximum of the products of the non-positive number with each of the two numbers.*)\nLemma real_minr_nMr x y z : x <= 0 -> y \\is real -> z \\is real ->\n x * min y z = max (x * y) (x * z).\n\n(*This lemma states that the product of the minimum of two numbers and a non-negative number is equal to the minimum of the products of each of the two numbers with the non-negative number.*)\nLemma minr_pMl x y z : 0 <= x -> min y z * x = min (y * x) (z * x).\n\n(*This lemma states that the product of the maximum of two numbers and a non-negative number is equal to the maximum of the products of each of the two numbers with the non-negative number.*)\nLemma maxr_pMl x y z : 0 <= x -> max y z * x = max (y * x) (z * x).\n\n(*This lemma states that for real numbers, the product of the minimum of two numbers and a non-positive number is equal to the maximum of the products of each of the two numbers with the non-positive number.*)\nLemma real_minr_nMl x y z : x <= 0 -> y \\is real -> z \\is real ->\n min y z * x = max (y * x) (z * x).\n\n(*This lemma states that for real numbers, the product of the maximum of two numbers and a non-positive number is equal to the minimum of the products of each of the two numbers with the non-positive number.*)\nLemma real_maxr_nMl x y z : x <= 0 -> y \\is real -> z \\is real ->\n max y z * x = min (y * x) (z * x).\n\n(*This lemma states that the maximum of a real number and its additive inverse is equal to its absolute value.*)\nLemma real_maxrN x : x \\is real -> max x (- x) = `|x|.\n\n(*This lemma states that the maximum of the additive inverse of a real number and the number itself is equal to its absolute value.*)\nLemma real_maxNr x : x \\is real -> max (- x) x = `|x|.\n\n(*This lemma states that the minimum of a real number and its additive inverse is equal to the additive inverse of its absolute value.*)\nLemma real_minrN x : x \\is real -> min x (- x) = - `|x|.\n\n(*This lemma states that the minimum of the additive inverse of a real number and the number itself is equal to the additive inverse of its absolute value.*)\nLemma real_minNr x : x \\is real -> min (- x) x = - `|x|.\n\nSection RealDomainArgExtremum.\n\nContext {I : finType} (i0 : I).\nContext (P : pred I) (F : I -> R) (Pi0 : P i0).\nHypothesis F_real : {in P, forall i, F i \\is real}.\n\n(*This lemma states that the argument that minimizes a real-valued function over a domain satisfying a given predicate indeed produces a value that is less than or equal to all other function values over that domain.*)\nLemma real_arg_minP : extremum_spec <=%R P F [arg min_(i < i0 | P i) F i].\n\n(*This lemma states that the argument that maximizes a real-valued function over a domain satisfying a given predicate indeed produces a value that is greater than or equal to all other function values over that domain.*)\nLemma real_arg_maxP : extremum_spec >=%R P F [arg max_(i > i0 | P i) F i].\n\nEnd RealDomainArgExtremum.\n\n(*This lemma states that any real number is less than or equal to its absolute value.*)\nLemma real_ler_norm x : x \\is real -> x <= `|x|.\n\nSection NormedZmoduleTheory.\n\nVariable V : semiNormedZmodType R.\nImplicit Types (u v w : V).\n\n(*This lemma states that the norm of an element in a semi-normed module over the real numbers is itself a real number.*)\nLemma normr_real v : `|v| \\is real. \nHint Resolve normr_real : core.\n\n(*This lemma states the triangle inequality for a finite sum of vectors, asserting that the norm of the sum is less than or equal to the sum of the norms of the individual vectors.*)\nLemma ler_norm_sum I r (G : I -> V) (P : pred I):\n `|\\sum_(i <- r | P i) G i| <= \\sum_(i <- r | P i) `|G i|.\n\n(*This lemma states that the norm of the difference of two vectors is less than or equal to the sum of their individual norms.*)\nLemma ler_normB v w : `|v - w| <= `|v| + `|w|.\n\n(*This lemma states the triangle inequality for the distance metric, asserting that the distance between two vectors is less than or equal to the sum of the distances from each vector to a third, intermediate vector.*)\nLemma ler_distD u v w : `|v - w| <= `|v - u| + `|u - w|.\n\n(*This lemma states a variant of the reverse triangle inequality, asserting that the difference between the norms of two vectors is less than or equal to the norm of their sum.*)\nLemma lerB_normD v w : `|v| - `|w| <= `|v + w|.\n\n(*This lemma states a variant of the reverse triangle inequality, asserting that the difference of the norms of two vectors is less than or equal to the norm of their difference.*)\nLemma lerB_dist v w : `|v| - `|w| <= `|v - w|.\n\n(*This lemma states the reverse triangle inequality, asserting that the absolute value of the difference between the norms of two vectors is less than or equal to the norm of their difference.*)\nLemma ler_dist_dist v w : `| `|v| - `|w| | <= `|v - w|.\n\n(*This lemma asserts that for any two elements of a normed module, the absolute value of the difference between their norms is less than or equal to the norm of their sum.*)\nLemma ler_dist_normD v w : `| `|v| - `|w| | <= `|v + w|.\n\n(*This lemma asserts that the norm of any element in a normed module cannot be less than or equal to a negative number.*)\nLemma ler_nnorml v x : x < 0 -> `|v| <= x = false.\n\n(*This lemma asserts that the norm of any element in a normed module cannot be strictly less than a non-positive number.*)\nLemma ltr_nnorml v x : x <= 0 -> `|v| < x = false.\n\n(*This definition creates a pair of lemmas, packaging the proofs that the norm of an element cannot be less than or equal to a negative number and cannot be strictly less than a non-positive number.*)\nDefinition lter_nnormr := (ler_nnorml, ltr_nnorml).\n\nEnd NormedZmoduleTheory.\n\nHint Extern 0 (is_true (norm _ \\is real)) => apply: normr_real : core.\n\n(*This lemma states that for a real number, the proposition that its absolute value is less than or equal to another number is equivalent to the proposition that the real number is between the negation of the other number and the other number, inclusive.*)\nLemma real_ler_norml x y : x \\is real -> (`|x| <= y) = (- y <= x <= y).\n\n(*This lemma provides a reflection property, showing that for a real number, the boolean statement that its absolute value is less than or equal to another number is logically equivalent to the conjunction of two inequalities: the negation of the real number is less than or equal to the other number, and the real number itself is less than or equal to the other number.*)\nLemma real_ler_normlP x y :\n x \\is real -> reflect ((-x <= y) * (x <= y)) (`|x| <= y).\n\nArguments real_ler_normlP {x y}.\n\n(*This lemma states that for a real number, the assertion that its absolute value is equal to another number is equivalent to the conjunction of two conditions: the other number is non-negative, and the real number is equal to either the other number or its negation.*)\nLemma real_eqr_norml x y :\n x \\is real -> (`|x| == y) = ((x == y) || (x == -y)) && (0 <= y).\n\n(*This lemma states that for any two real numbers, the equality of their absolute values is equivalent to the condition that the two numbers are either equal or are negations of each other.*)\nLemma real_eqr_norm2 x y :\n x \\is real -> y \\is real -> (`|x| == `|y|) = (x == y) || (x == -y).\n\n(*This lemma states that for a real number, the proposition that its absolute value is strictly less than another number is equivalent to the proposition that the real number is strictly between the negation of the other number and the other number.*)\nLemma real_ltr_norml x y : x \\is real -> (`|x| < y) = (- y < x < y).\n\n(*This definition combines two lemmas that characterize inequalities involving the absolute value of a real number on the left-hand side. It packages the equivalences for both the less-than-or-equal-to and the strictly-less-than comparisons with an interval representation.*)\nDefinition real_lter_norml := (real_ler_norml, real_ltr_norml).\n\n(*This lemma provides a reflection property, showing that for a real number, the boolean statement that its absolute value is strictly less than another number is logically equivalent to the conjunction of two strict inequalities: the negation of the real number is strictly less than the other number, and the real number itself is strictly less than the other number.*)\nLemma real_ltr_normlP x y :\n x \\is real -> reflect ((-x < y) * (x < y)) (`|x| < y).\n\nArguments real_ltr_normlP {x y}.\n\n(*This lemma states that for a real number, the proposition that another number is less than or equal to its absolute value is equivalent to the disjunction of two conditions: the other number is less than or equal to the real number itself, or the other number is less than or equal to the negation of the real number.*)\nLemma real_ler_normr x y : y \\is real -> (x <= `|y|) = (x <= y) || (x <= - y).\n\n(*This lemma states that for a real number, the proposition that another number is strictly less than its absolute value is equivalent to the disjunction of two conditions: the other number is strictly less than the real number itself, or the other number is strictly less than the negation of the real number.*)\nLemma real_ltr_normr x y : y \\is real -> (x < `|y|) = (x < y) || (x < - y).\n\n(*This definition combines two lemmas that characterize an inequality where a number is compared to the absolute value of a real number on the right-hand side. It packages the equivalences for both the less-than-or-equal-to and the strictly-less-than comparisons.*)\nDefinition real_lter_normr := (real_ler_normr, real_ltr_normr).\n\n(*This lemma asserts that if the absolute value of a real number is strictly less than another number, then the real number itself must also be strictly less than that other number.*)\nLemma real_ltr_normlW x y : x \\is real -> `|x| < y -> x < y.\n\n(*This lemma asserts that if the absolute value of a real number is strictly less than another number, then the negation of that other number must be strictly less than the real number.*)\nLemma real_ltrNnormlW x y : x \\is real -> `|x| < y -> - y < x.\n\n(*This lemma asserts that if the absolute value of a real number is less than or equal to another number, then the real number itself must also be less than or equal to that other number.*)\nLemma real_ler_normlW x y : x \\is real -> `|x| <= y -> x <= y.\n\n(*This lemma asserts that if the absolute value of a real number is less than or equal to another number, then the negation of that other number must be less than or equal to the real number.*)\nLemma real_lerNnormlW x y : x \\is real -> `|x| <= y -> - y <= x.\n\n(*This lemma states that for two real numbers and a third number representing a radius, the proposition that the absolute value of their difference is less than or equal to the radius is equivalent to stating that the first number lies within the closed interval centered at the second number with that radius.*)\nLemma real_ler_distl x y e :\n x - y \\is real -> (`|x - y| <= e) = (y - e <= x <= y + e).\n\n(*This lemma states that for two real numbers and a third number representing a radius, the proposition that the absolute value of their difference is strictly less than the radius is equivalent to stating that the first number lies within the open interval centered at the second number with that radius.*)\nLemma real_ltr_distl x y e :\n x - y \\is real -> (`|x - y| < e) = (y - e < x < y + e).\n\n(*This definition combines two lemmas that characterize distance inequalities for real numbers. It packages the equivalences for both non-strict and strict comparisons of the absolute difference with a radius, relating them to closed and open intervals respectively.*)\nDefinition real_lter_distl := (real_ler_distl, real_ltr_distl).\n\n(*This lemma asserts that if the absolute value of the difference between two real numbers is strictly less than a third number, then the first number is strictly less than the sum of the second and third numbers.*)\nLemma real_ltr_distlDr x y e : x - y \\is real -> `|x - y| < e -> x < y + e.\n\n(*This lemma asserts that if the absolute value of the difference between two real numbers is less than or equal to a third number, then the first number is less than or equal to the sum of the second and third numbers.*)\nLemma real_ler_distlDr x y e : x - y \\is real -> `|x - y| <= e -> x <= y + e.\n\n(*This lemma asserts that if the absolute value of the difference between two real numbers is strictly less than a third number, then the second number is strictly less than the sum of the first and third numbers.*)\nLemma real_ltr_distlCDr x y e : x - y \\is real -> `|x - y| < e -> y < x + e.\n\n(*This lemma asserts that if the absolute value of the difference between two real numbers is less than or equal to a third number, then the second number is less than or equal to the sum of the first and third numbers.*)\nLemma real_ler_distlCDr x y e : x - y \\is real -> `|x - y| <= e -> y <= x + e.\n\n(*This lemma asserts that if the absolute value of the difference between two real numbers is strictly less than a third number, then the difference between the first and third numbers is strictly less than the second number.*)\nLemma real_ltr_distlBl x y e : x - y \\is real -> `|x - y| < e -> x - e < y.\n\n(*This lemma asserts that if the absolute value of the difference between two real numbers is less than or equal to a third number, then the difference between the first and third numbers is less than or equal to the second number.*)\nLemma real_ler_distlBl x y e : x - y \\is real -> `|x - y| <= e -> x - e <= y.\n\n(*This lemma asserts that if the absolute value of the difference between two real numbers is strictly less than a third number, then the difference between the second and third numbers is strictly less than the first number.*)\nLemma real_ltr_distlCBl x y e : x - y \\is real -> `|x - y| < e -> y - e < x.\n\n(*This lemma asserts that if the absolute value of the difference between two real numbers is less than or equal to a third number, then the difference between the second and third numbers is less than or equal to the first number.*)\nLemma real_ler_distlCBl x y e : x - y \\is real -> `|x - y| <= e -> y - e <= x.\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"use `ger0_def` instead\")]\n(*This lemma states that for any number in a normed structure, the condition that its absolute value is equal to itself is equivalent to the condition that the number is greater than or equal to zero.*)\nLemma eqr_norm_id x : (`|x| == x) = (0 <= x). \n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"use `ler0_def` instead\")]\n(*This lemma states that the absolute value of a real number is equal to its additive inverse if and only if the number is less than or equal to zero.*)\nLemma eqr_normN x : (`|x| == - x) = (x <= 0). \n\n(*This definition provides a canonical rewrite rule based on the definitions of a real number being greater than or equal to zero and less than or equal to zero.*)\nDefinition eqr_norm_idVN := =^~ (ger0_def, ler0_def).\n\n(*This lemma states that raising a real number to an even natural number power always results in a value that is greater than or equal to zero.*)\nLemma real_exprn_even_ge0 n x : x \\is real -> ~~ odd n -> 0 <= x ^+ n.\n\n(*This lemma states that for a real number raised to an even natural number power, the result is strictly greater than zero if and only if the exponent is zero or the base is not zero.*)\nLemma real_exprn_even_gt0 n x :\n x \\is real -> ~~ odd n -> (0 < x ^+ n) = (n == 0)%N || (x != 0).\n\n(*This lemma states that for a real number raised to an even natural number power, the result is less than or equal to zero if and only if the exponent is not zero and the base is zero.*)\nLemma real_exprn_even_le0 n x :\n x \\is real -> ~~ odd n -> (x ^+ n <= 0) = (n != 0) && (x == 0).\n\n(*This lemma states that the proposition that a real number raised to an even natural number power is strictly less than zero is always false.*)\nLemma real_exprn_even_lt0 n x :\n x \\is real -> ~~ odd n -> (x ^+ n < 0) = false.\n\n(*This lemma states that for a real number raised to an odd natural number power, the result is greater than or equal to zero if and only if the base number is greater than or equal to zero.*)\nLemma real_exprn_odd_ge0 n x :\n x \\is real -> odd n -> (0 <= x ^+ n) = (0 <= x).\n\n(*This lemma states that for a real number raised to an odd natural number power, the result is strictly greater than zero if and only if the base number is strictly greater than zero.*)\nLemma real_exprn_odd_gt0 n x : x \\is real -> odd n -> (0 < x ^+ n) = (0 < x).\n\n(*This lemma states that for a real number raised to an odd natural number power, the result is less than or equal to zero if and only if the base number is less than or equal to zero.*)\nLemma real_exprn_odd_le0 n x : x \\is real -> odd n -> (x ^+ n <= 0) = (x <= 0).\n\n(*This lemma states that for a real number raised to an odd natural number power, the result is strictly less than zero if and only if the base number is strictly less than zero.*)\nLemma real_exprn_odd_lt0 n x : x \\is real -> odd n -> (x ^+ n < 0) = (x < 0).\n\n(*This lemma states that a number is a real number if and only if its square is greater than or equal to zero.*)\nLemma realEsqr x : (x \\is real) = (0 <= x ^+ 2).\n\n(*This lemma states that for any real number, the square of its absolute value is equal to its square.*)\nLemma real_normK x : x \\is real -> `|x| ^+ 2 = x ^+ 2.\n\n(*This lemma states that for any boolean value, the absolute value of negative one raised to a power corresponding to that boolean is always equal to one.*)\nLemma normr_sign s : `|(-1) ^+ s : R| = 1.\n\n(*This lemma states that for any boolean value and any real number, the absolute value of the product of the number with negative one raised to a power corresponding to the boolean is equal to the absolute value of the number itself.*)\nLemma normrMsign s x : `|(-1) ^+ s * x| = `|x|.\n\n(*This lemma states that for a boolean value, the real number representation of negative one raised to a power corresponding to that boolean is strictly greater than zero if and only if the boolean is false.*)\nLemma signr_gt0 (b : bool) : (0 < (-1) ^+ b :> R) = ~~ b.\n\n(*This lemma states that for a boolean value, the real number representation of negative one raised to a power corresponding to that boolean is strictly less than zero if and only if the boolean is true.*)\nLemma signr_lt0 (b : bool) : ((-1) ^+ b < 0 :> R) = b.\n\n(*This lemma states that for a boolean value, the real number representation of negative one raised to a power corresponding to that boolean is greater than or equal to zero if and only if the boolean is false.*)\nLemma signr_ge0 (b : bool) : (0 <= (-1) ^+ b :> R) = ~~ b.\n\n(*This lemma states that for a boolean value, the real number representation of negative one raised to a power corresponding to that boolean is less than or equal to zero if and only if the boolean is true.*)\nLemma signr_le0 (b : bool) : ((-1) ^+ b <= 0 :> R) = b.\n\n(*This lemma states that the function mapping a boolean value to the real number representation of negative one raised to a power corresponding to that boolean is injective.*)\nLemma signr_inj : injective (fun b : bool => (-1) ^+ b : R).\n\n(*This lemma provides a definition for the sign of a real number. It states that the sign is the product of two terms: the first is negative one raised to the power of the boolean indicating whether the number is less than zero, and the second is the numeric value of the boolean indicating whether the number is non-zero.*)\nLemma sgr_def x : sg x = (-1) ^+ (x < 0)%R *+ (x != 0).\n\n(*This lemma states that for any non-zero real number, its sign is equal to negative one raised to the power of the boolean indicating whether the number is less than zero.*)\nLemma neqr0_sign x : x != 0 -> (-1) ^+ (x < 0)%R = sgr x.\n\n(*This lemma states that the sign of any real number strictly greater than zero is one.*)\nLemma gtr0_sg x : 0 < x -> sg x = 1.\n\n(*This lemma states that the sign of any real number strictly less than zero is negative one.*)\nLemma ltr0_sg x : x < 0 -> sg x = -1.\n\n(*This lemma states that the sign of zero is zero.*)\nLemma sgr0 : sg 0 = 0 :> R. \n(*This lemma states that the sign of one is one.*)\nLemma sgr1 : sg 1 = 1 :> R. \n(*This lemma states that the sign of negative one is negative one.*)\nLemma sgrN1 : sg (-1) = -1 :> R. \n(*This definition groups three lemmas regarding the sign of zero, one, and negative one into a single collection, typically for use with proof automation tactics.*)\nDefinition sgrE := (sgr0, sgr1, sgrN1).\n\n(*This lemma states that the square of the sign of a real number is equal to one if the number is non-zero, and zero if the number is zero.*)\nLemma sqr_sg x : sg x ^+ 2 = (x != 0)%:R.\n\n(*This lemma states that the product of the sign of a first real number and a second real number is equal to one if and only if the first number is non-zero and the second number is equal to the sign of the first number.*)\nLemma mulr_sg_eq1 x y : (sg x * y == 1) = (x != 0) && (sg x == y).\n\n(*This lemma states that the product of the signs of two real numbers is equal to negative one if and only if the first number is non-zero and its sign is the additive inverse of the sign of the second number.*)\nLemma mulr_sg_eqN1 x y : (sg x * sg y == -1) = (x != 0) && (sg x == - sg y).\n\n(*This lemma states that the sign of a real number is equal to zero if and only if the real number itself is equal to zero.*)\nLemma sgr_eq0 x : (sg x == 0) = (x == 0).\n\n(*This lemma states that for any non-zero real number, raising its sign to the power of a natural number yields the same result as raising its sign to a power determined by the parity of that natural number, namely one for an odd exponent and zero for an even exponent.*)\nLemma sgr_odd n x : x != 0 -> (sg x) ^+ n = (sg x) ^+ (odd n).\n\n(*This lemma states that the sign of the result of repeatedly adding a real number to itself a specified number of times is equal to the sign of the original real number if the count is non-zero, and zero otherwise.*)\nLemma sgrMn x n : sg (x *+ n) = (n != 0)%:R * sg x.\n\n(*This lemma states that the sign of a natural number, when interpreted as a real number, is one if the natural number is not zero, and zero if it is zero.*)\nLemma sgr_nat n : sg n%:R = (n != 0)%:R :> R.\n\n(*This lemma states that the sign function is idempotent, meaning that applying the sign function to the sign of a real number results in the sign of the original number.*)\nLemma sgr_id x : sg (sg x) = sg x.\n\n(*This lemma states that the sign of a real number is less than zero if and only if the real number itself is less than zero.*)\nLemma sgr_lt0 x : (sg x < 0) = (x < 0).\n\n(*This lemma states that the sign of a real number is less than or equal to zero if and only if the real number itself is less than or equal to zero.*)\nLemma sgr_le0 x : (sgr x <= 0) = (x <= 0).\n\n(*This lemma states that any real number is equal to its absolute value multiplied by a sign factor, where the factor is negative one if the number is less than zero, and one otherwise.*)\nLemma realEsign x : x \\is real -> x = (-1) ^+ (x < 0)%R * `|x|.\n\n(*This lemma states that the additive inverse of a real number is equal to its absolute value multiplied by a sign factor, where the factor is negative one if the number is greater than zero, and one otherwise.*)\nLemma realNEsign x : x \\is real -> - x = (-1) ^+ (0 < x)%R * `|x|.\n\n(*This lemma states that the absolute value of a real number is equal to the number itself multiplied by a sign factor, where the factor is negative one if the number is less than zero, and one otherwise.*)\nLemma real_normrEsign (x : R) (xR : x \\is real) : `|x| = (-1) ^+ (x < 0)%R * x.\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"use `realEsign` instead\")]\n(*This lemma states that for a real number, the product of its absolute value and a sign factor, where the factor is negative one if the number is negative and one otherwise, is equal to the number itself.*)\nLemma real_mulr_sign_norm x : x \\is real -> (-1) ^+ (x < 0)%R * `|x| = x.\n\n(*This lemma states that for a real number, the product of its absolute value and a sign factor, where the factor is negative one if the number is positive and one otherwise, is equal to the additive inverse of the number.*)\nLemma real_mulr_Nsign_norm x : x \\is real -> (-1) ^+ (0 < x)%R * `|x| = - x.\n\n(*This lemma states that any real number is equal to the product of its sign and its absolute value.*)\nLemma realEsg x : x \\is real -> x = sgr x * `|x|.\n\n(*This lemma states that the absolute value of the sign of a real number is one if the number is not zero, and zero if the number is zero.*)\nLemma normr_sg x : `|sg x| = (x != 0)%:R.\n\n(*This lemma states that the sign of the absolute value of a real number is one if the number is not zero, and zero if the number is zero.*)\nLemma sgr_norm x : sg `|x| = (x != 0)%:R.\n\n(*This lemma states that the boolean result of a conditional inequality check, which compares two natural numbers interpreted as real numbers, is identical to the result of the same conditional inequality check performed directly on the natural numbers.*)\nLemma leif_nat_r m n C : (m%:R <= n%:R ?= iff C :> R) = (m <= n ?= iff C)%N.\n\n(*This lemma provides a rewrite rule for conditional inequalities, stating that checking if the difference of two real numbers is less than or equal to a third real number is equivalent to checking if the first number is less than or equal to the sum of the second and third.*)\nLemma leifBLR x y z C : (x - y <= z ?= iff C) = (x <= z + y ?= iff C).\n\n(*This lemma provides a rewrite rule for conditional inequalities, stating that checking if a first real number is less than or equal to the difference of a second and third real number is equivalent to checking if the sum of the first and third numbers is less than or equal to the second.*)\nLemma leifBRL x y z C : (x <= y - z ?= iff C) = (x + z <= y ?= iff C).\n\n(*This lemma states that if a first conditional inequality holds between two real numbers, and a second conditional inequality holds between another pair of real numbers, then the sum of the smaller numbers is conditionally less than or equal to the sum of the larger numbers, with the new condition being the logical conjunction of the original two conditions.*)\nLemma leifD x1 y1 C1 x2 y2 C2 :\n x1 <= y1 ?= iff C1 -> x2 <= y2 ?= iff C2 ->\n x1 + x2 <= y1 + y2 ?= iff C1 && C2.\n\n(*This lemma states that if, for every element in a given finite collection, a conditional inequality holds between the values of two real-valued functions at that element, then the sum of the values of the first function over the collection is conditionally less than or equal to the sum of the values of the second function, with the new condition being the universal conjunction of all original conditions.*)\nLemma leif_sum (I : finType) (P C : pred I) (E1 E2 : I -> R) :\n (forall i, P i -> E1 i <= E2 i ?= iff C i) ->\n \\sum_(i | P i) E1 i <= \\sum_(i | P i) E2 i ?= iff [forall (i | P i), C i].\n\n(*This lemma states that if, for every element in a given finite collection, a real-valued function is conditionally greater than or equal to zero, then the sum of the function's values over that collection is also conditionally greater than or equal to zero, with the new condition being the universal conjunction of all original conditions.*)\nLemma leif_0_sum (I : finType) (P C : pred I) (E : I -> R) :\n (forall i, P i -> 0 <= E i ?= iff C i) ->\n 0 <= \\sum_(i | P i) E i ?= iff [forall (i | P i), C i].\n\n(*This lemma states that for any real number, the proposition that the number is greater than or equal to zero implies that the number is less than or equal to its absolute value.*)\nLemma real_leif_norm x : x \\is real -> x <= `|x| ?= iff (0 <= x).\n\n(*This lemma concerns the multiplication of conditional inequalities for non-negative real numbers. It states that if two conditional inequalities hold for pairs of real numbers, where the smaller numbers in each pair are non-negative, then their product inequality also holds under a new combined condition. This new condition is true if the product of the larger numbers is zero, or if both original conditions are true.*)\nLemma leif_pM x1 x2 y1 y2 C1 C2 :\n 0 <= x1 -> 0 <= x2 -> x1 <= y1 ?= iff C1 -> x2 <= y2 ?= iff C2 ->\n x1 * x2 <= y1 * y2 ?= iff (y1 * y2 == 0) || C1 && C2.\n\n(*This lemma concerns the multiplication of conditional inequalities where the larger numbers are non-positive. It states that if two conditional inequalities hold, and the upper bounds of these inequalities are both non-positive, then the product of these upper bounds is conditionally less than or equal to the product of the lower bounds. The condition for this reversed inequality is true if the product of the lower bounds is zero, or if both original conditions hold.*)\nLemma leif_nM x1 x2 y1 y2 C1 C2 :\n y1 <= 0 -> y2 <= 0 -> x1 <= y1 ?= iff C1 -> x2 <= y2 ?= iff C2 ->\n y1 * y2 <= x1 * x2 ?= iff (x1 * x2 == 0) || C1 && C2.\n\n(*This lemma generalizes the multiplication of conditional inequalities to finite products. It asserts that if for every element in a finite collection, a first real-valued function is non-negative and is conditionally less than or equal to a second real-valued function, then the product of the values of the first function is conditionally less than or equal to the product of the values of the second function. The new condition holds if the product of the second function is zero, or if all original elementary conditions hold.*)\nLemma leif_pprod (I : finType) (P C : pred I) (E1 E2 : I -> R) :\n (forall i, P i -> 0 <= E1 i) ->\n (forall i, P i -> E1 i <= E2 i ?= iff C i) ->\n let pi E := \\prod_(i | P i) E i in\n pi E1 <= pi E2 ?= iff (pi E2 == 0) || [forall (i | P i), C i].\n\n(*This lemma states that for a given boolean condition, the conditional proposition that the difference of two real numbers is less than zero is equivalent to the conditional proposition that the first number is less than the second.*)\nLemma subr_lteifr0 C x y : (y - x < 0 ?<= if C) = (y < x ?<= if C).\n\n(*This lemma states that for a given boolean condition, the conditional proposition that zero is less than the difference of two real numbers is equivalent to the conditional proposition that the first number is less than the second.*)\nLemma subr_lteif0r C x y : (0 < y - x ?<= if C) = (x < y ?<= if C).\n\n(*This definition groups two lemmas, `subr_lteifr0` and `subr_lteif0r`, into a single term, typically for use in automated proof tactics that rewrite expressions involving conditional comparisons with zero.*)\nDefinition subr_lteif0 := (subr_lteifr0, subr_lteif0r).\n\n(*This lemma states that for any boolean condition, the conditional proposition that zero is less than one holds true.*)\nLemma lteif01 C : 0 < 1 ?<= if C :> R.\n\n(*This lemma states that for any given boolean condition, the conditional proposition that the additive inverse of a first real number is less than a second real number is equivalent to the conditional proposition that the additive inverse of the second number is less than the first.*)\nLemma lteifNl C x y : - x < y ?<= if C = (- y < x ?<= if C).\n\n(*This lemma states that for any two values and a boolean condition, the conditional comparison between the first value and the opposite of the second is equivalent to the conditional comparison between the second value and the opposite of the first, under the same condition.*)\nLemma lteifNr C x y : x < - y ?<= if C = (y < - x ?<= if C).\n\n(*This lemma states that for a given value and a boolean condition, the conditional comparison between zero and the opposite of the value is equivalent to the conditional comparison between the value and zero.*)\nLemma lteif0Nr C x : 0 < - x ?<= if C = (x < 0 ?<= if C).\n\n(*This lemma states that for a given value and a boolean condition, the conditional comparison between the opposite of the value and zero is equivalent to the conditional comparison between zero and the value.*)\nLemma lteifNr0 C x : - x < 0 ?<= if C = (0 < x ?<= if C).\n\n(*This lemma states that the unary negation operation is anti-monotone with respect to the conditional less-than-or-equal relation. If a first value is conditionally less than or equal to a second, then the opposite of the second value is conditionally less than or equal to the opposite of the first.*)\nLemma lteifN2 C : {mono -%R : x y /~ x < y ?<= if C :> R}.\n\n(*This definition aggregates three lemmas concerning the interaction between the conditional less-than-or-equal comparison and the additive opposite operation into a single tuple, likely for automated proof tactics.*)\nDefinition lteif_oppE := (lteif0Nr, lteifNr0, lteifN2).\n\n(*This lemma asserts that adding a fixed value to the left of both terms in a conditional less-than-or-equal comparison preserves the relation, establishing the monotonicity of left addition.*)\nLemma lteifD2l C x : {mono +%R x : y z / y < z ?<= if C}.\n\n(*This lemma asserts that adding a fixed value to the right of both terms in a conditional less-than-or-equal comparison preserves the relation, establishing the monotonicity of right addition.*)\nLemma lteifD2r C x : {mono +%R^~ x : y z / y < z ?<= if C}.\n\n(*This definition aggregates two lemmas regarding the monotonicity of left and right addition with respect to the conditional less-than-or-equal comparison into a single tuple.*)\nDefinition lteifD2 := (lteifD2l, lteifD2r).\n\n(*This lemma provides a rule for rewriting a conditional inequality, stating that a comparison involving a subtraction on the left side is equivalent to one where the subtracted term has been moved to the right side as an added term.*)\nLemma lteifBlDr C x y z : (x - y < z ?<= if C) = (x < z + y ?<= if C).\n\n(*This lemma provides a rule for rewriting a conditional inequality, stating that a comparison involving a subtraction on the right side is equivalent to one where the subtracted term has been moved to the left side as an added term.*)\nLemma lteifBrDr C x y z : (x < y - z ?<= if C) = (x + z < y ?<= if C).\n\n(*This definition aggregates two lemmas that provide rules for rewriting conditional inequalities by moving a subtracted term from one side of the comparison to the other as an added term.*)\nDefinition lteifBDr := (lteifBlDr, lteifBrDr).\n\n(*This lemma provides a rule for rewriting a conditional inequality, stating that a comparison involving a subtraction on the left side is equivalent to one where the subtracted term is added to the right side, using a specific commutated order of addition.*)\nLemma lteifBlDl C x y z : (x - y < z ?<= if C) = (x < y + z ?<= if C).\n\n(*This lemma provides a rule for rewriting a conditional inequality, stating that a comparison involving a subtraction on the right side is equivalent to one where the subtracted term is added to the left side, using a specific commutated order of addition.*)\nLemma lteifBrDl C x y z : (x < y - z ?<= if C) = (z + x < y ?<= if C).\n\n(*This definition aggregates two lemmas that provide alternative rules for rewriting conditional inequalities by moving a subtracted term from one side to the other, with a specific ordering for the resulting addition.*)\nDefinition lteifBDl := (lteifBlDl, lteifBrDl).\n\n(*This lemma states that multiplying both sides of a conditional less-than-or-equal comparison on the left by a positive value preserves the relation, establishing the monotonicity of left multiplication by a positive factor.*)\nLemma lteif_pM2l C x : 0 < x -> {mono *%R x : y z / y < z ?<= if C}.\n\n(*This lemma states that multiplying both sides of a conditional less-than-or-equal comparison on the right by a positive value preserves the relation, establishing the monotonicity of right multiplication by a positive factor.*)\nLemma lteif_pM2r C x : 0 < x -> {mono *%R^~ x : y z / y < z ?<= if C}.\n\n(*This lemma states that multiplying both sides of a conditional less-than-or-equal comparison on the left by a negative value reverses the relation, establishing the anti-monotonicity of left multiplication by a negative factor.*)\nLemma lteif_nM2l C x : x < 0 -> {mono *%R x : y z /~ y < z ?<= if C}.\n\n(*This lemma states that multiplying both sides of a conditional less-than-or-equal comparison on the right by a negative value reverses the relation, establishing the anti-monotonicity of right multiplication by a negative factor.*)\nLemma lteif_nM2r C x : x < 0 -> {mono *%R^~ x : y z /~ y < z ?<= if C}.\n\n(*This lemma states that under a condition implying a value is non-positive, it is false to assert that the absolute value of another number is conditionally less than or equal to that value.*)\nLemma lteif_nnormr C x y : y < 0 ?<= if ~~ C -> (`|x| < y ?<= if C) = false.\n\n(*This lemma states that for two real numbers, a conditional less-than-or-equal comparison under a negated boolean condition is equivalent to the boolean negation of the same comparison with the numbers swapped, under the original condition.*)\nLemma real_lteifNE x y C : x \\is Num.real -> y \\is Num.real ->\n x < y ?<= if ~~ C = ~~ (y < x ?<= if C).\n\n(*This lemma for real numbers states that a conditional comparison between the absolute value of a number and a second number is equivalent to the conjunction of two conditional comparisons, checking if the first number is between the opposite of the second and the second itself.*)\nLemma real_lteif_norml C x y :\n x \\is Num.real ->\n (`|x| < y ?<= if C) = ((- y < x ?<= if C) && (x < y ?<= if C)).\n\n(*This lemma for real numbers states that a conditional comparison between a number and the absolute value of a second number is equivalent to the disjunction of two conditional comparisons: one between the first number and the second, and one between the first number and the opposite of the second.*)\nLemma real_lteif_normr C x y :\n y \\is Num.real ->\n (x < `|y| ?<= if C) = ((x < y ?<= if C) || (x < - y ?<= if C)).\n\n(*This lemma for real numbers expands a conditional comparison involving the absolute value of a difference. It equates the comparison between the absolute difference of two values and a third value to a conjunction of two conditional comparisons, effectively describing a closed interval.*)\nLemma real_lteif_distl C x y e :\n x - y \\is real ->\n (`|x - y| < e ?<= if C) = (y - e < x ?<= if C) && (x < y + e ?<= if C).\n\n(*This lemma states an inequality between the product and squares of two real numbers, asserting that twice their product is less than or equal to the sum of their squares, with equality holding if and only if the numbers are equal.*)\nLemma real_leif_mean_square_scaled x y :\n x \\is real -> y \\is real -> x * y *+ 2 <= x ^+ 2 + y ^+ 2 ?= iff (x == y).\n\n(*This lemma states a scaled version of the AM-GM inequality for two real numbers, asserting that four times their product is less than or equal to the square of their sum, with equality holding if and only if the numbers are equal.*)\nLemma real_leif_AGM2_scaled x y :\n x \\is real -> y \\is real -> x * y *+ 4 <= (x + y) ^+ 2 ?= iff (x == y).\n\n(*This lemma states the scaled version of the AM-GM inequality for a family of values indexed by a finite set. Under a non-negativity condition on the scaled values, it asserts that the product of these scaled values is less than or equal to the sum of the original values raised to the power of the family's size. Equality holds if and only if all values in the family are identical.*)\nLemma leif_AGM_scaled (I : finType) (A : {pred I}) (E : I -> R) (n := #|A|) :\n {in A, forall i, 0 <= E i *+ n} ->\n \\prod_(i in A) (E i *+ n) <= (\\sum_(i in A) E i) ^+ n\n ?= iff [forall i in A, forall j in A, E i == E j].\n\nImplicit Type p : {poly R}.\n\n(*This lemma asserts the existence of an upper bound for the magnitude of a polynomial's evaluation within a specified disk. For any polynomial and a given radius, there exists a value that is greater than or equal to the absolute value of the polynomial at any point within that radius from the origin.*)\nLemma poly_disk_bound p b : {ub | forall x, `|x| <= b -> `|p.[x]| <= ub}.\n\nEnd NumDomainOperationTheory.\n\n#[global] Hint Resolve lerN2 ltrN2 normr_real : core.\n#[global] Hint Extern 0 (is_true (_%:R \\is real)) => apply: realn : core.\n#[global] Hint Extern 0 (is_true (0 \\is real)) => apply: real0 : core.\n#[global] Hint Extern 0 (is_true (1 \\is real)) => apply: real1 : core.\n\nArguments ler_sqr {R} [x y].\nArguments ltr_sqr {R} [x y].\nArguments signr_inj {R} [x1 x2].\nArguments real_ler_normlP {R x y}.\nArguments real_ltr_normlP {R x y}.\n\nSection NumDomainMonotonyTheoryForReals.\nLocal Open Scope order_scope.\n\nVariables (R R' : numDomainType) (D : pred R) (f : R -> R') (f' : R -> nat).\nImplicit Types (m n p : nat) (x y z : R) (u v w : R').\n\n(*This lemma states that any function on a real-like domain that is strictly increasing (preserving the strict less-than relation) is also non-decreasing (preserving the less-than-or-equal relation).*)\nLemma real_mono :\n {homo f : x y / x < y} -> {in real &, {mono f : x y / x <= y}}.\n\n(*This lemma states that any function on a real-like domain that is strictly decreasing (reversing the strict less-than relation) is also non-increasing (reversing the less-than-or-equal relation).*)\nLemma real_nmono :\n {homo f : x y /~ x < y} -> {in real &, {mono f : x y /~ x <= y}}.\n\n(*This lemma states that if a function is strictly monotone with respect to the less-than relation when restricted to a specific subset of its real-like domain, then it is also monotone with respect to the less-than-or-equal relation on that same subset.*)\nLemma real_mono_in :\n {in D &, {homo f : x y / x < y}} ->\n {in [pred x in D | x \\is real] &, {mono f : x y / x <= y}}.\n\n(*This lemma states that a function which is non-increasing with respect to the strict less-than order on a given domain is also non-increasing with respect to the less-than-or-equal-to order on the subset of that domain containing only real numbers.*)\nLemma real_nmono_in :\n {in D &, {homo f : x y /~ x < y}} ->\n {in [pred x in D | x \\is real] &, {mono f : x y /~ x <= y}}.\n\n(*This lemma states that a function which is strictly increasing with respect to the strict less-than order is also non-decreasing with respect to the less-than-or-equal-to order when its domain is restricted to real numbers.*)\nLemma realn_mono : {homo f' : x y / x < y >-> (x < y)} ->\n {in real &, {mono f' : x y / x <= y >-> (x <= y)}}.\n\n(*This lemma states that a function which is strictly decreasing with respect to the strict less-than order is also non-increasing with respect to the less-than-or-equal-to order when its domain is restricted to real numbers.*)\nLemma realn_nmono : {homo f' : x y / y < x >-> (x < y)} ->\n {in real &, {mono f' : x y / y <= x >-> (x <= y)}}.\n\n(*This lemma states that if a function is strictly increasing with respect to the strict less-than order over a given domain, it is also non-decreasing with respect to the less-than-or-equal-to order on the subset of that domain containing only real numbers.*)\nLemma realn_mono_in : {in D &, {homo f' : x y / x < y >-> (x < y)}} ->\n {in [pred x in D | x \\is real] &, {mono f' : x y / x <= y >-> (x <= y)}}.\n\n(*This lemma states that if a function is strictly decreasing with respect to the strict less-than order over a given domain, it is also non-increasing with respect to the less-than-or-equal-to order on the subset of that domain containing only real numbers.*)\nLemma realn_nmono_in : {in D &, {homo f' : x y / y < x >-> (x < y)}} ->\n {in [pred x in D | x \\is real] &, {mono f' : x y / y <= x >-> (x <= y)}}.\n\nEnd NumDomainMonotonyTheoryForReals.\n\nSection FinGroup.\n\nVariables (R : numDomainType) (gT : finGroupType).\nImplicit Types G : {group gT}.\n\n(*This lemma states that the order of any finite group, when converted to an element of a numerical domain, is strictly greater than zero.*)\nLemma natrG_gt0 G : #|G|%:R > 0 :> R.\n\n(*This lemma states that the order of any finite group, when converted to an element of a numerical domain, is not equal to zero.*)\nLemma natrG_neq0 G : #|G|%:R != 0 :> R.\n\n(*This lemma states that the index of any subgroup within a finite group, when converted to an element of a numerical domain, is strictly greater than zero.*)\nLemma natr_indexg_gt0 G B : #|G : B|%:R > 0 :> R.\n\n(*This lemma states that the index of any subgroup within a finite group, when converted to an element of a numerical domain, is not equal to zero.*)\nLemma natr_indexg_neq0 G B : #|G : B|%:R != 0 :> R.\n\nEnd FinGroup.\n\nSection RealDomainTheory.\n\nVariable R : realDomainType.\nImplicit Types x y z t : R.\n\n(*This lemma states that any element of a real domain type satisfies the property of being a real number.*)\nLemma num_real x : x \\is real. \nHint Resolve num_real : core.\n\n(*This lemma provides a comprehensive case analysis for the less-than-or-equal-to relation between two real numbers. It establishes that either the first number is less than or equal to the second, or the second is strictly less than the first, and provides expressions for the minimum, maximum, and absolute difference in each case.*)\nLemma lerP x y : ler_xor_gt x y (min y x) (min x y) (max y x) (max x y)\n `|x - y| `|y - x| (x <= y) (y < x).\n\n(*This lemma provides a comprehensive case analysis for the strict less-than relation between two real numbers. It establishes that either the first number is strictly less than the second, or the second is less than or equal to the first, and provides expressions for the minimum, maximum, and absolute difference in each case.*)\nLemma ltrP x y : ltr_xor_ge x y (min y x) (min x y) (max y x) (max x y)\n `|x - y| `|y - x| (y <= x) (x < y).\n\n(*This lemma provides a full trichotomy case analysis for comparing two real numbers. It distinguishes between the cases where the first number is less than, equal to, or greater than the second, and provides expressions for the minimum, maximum, and absolute difference.*)\nLemma ltrgtP x y :\n comparer x y (min y x) (min x y) (max y x) (max x y)\n `|x - y| `|y - x| (y == x) (x == y)\n (x >= y) (x <= y) (x > y) (x < y) .\n\n(*This lemma provides a case analysis for the greater-than-or-equal-to-zero relation for a real number. It establishes that a number is either greater than or equal to zero, or it is strictly less than zero, and provides expressions for the minimum, maximum, and absolute value in each case.*)\nLemma ger0P x : ger0_xor_lt0 x (min 0 x) (min x 0) (max 0 x) (max x 0)\n `|x| (x < 0) (0 <= x).\n\n(*This lemma provides a case analysis for the less-than-or-equal-to-zero relation for a real number. It establishes that a number is either less than or equal to zero, or it is strictly greater than zero, and provides expressions for the minimum, maximum, and absolute value in each case.*)\nLemma ler0P x : ler0_xor_gt0 x (min 0 x) (min x 0) (max 0 x) (max x 0)\n `|x| (0 < x) (x <= 0).\n\n(*This lemma provides a full trichotomy case analysis for comparing a real number with zero. It distinguishes between the cases where the number is less than, equal to, or greater than zero, and provides expressions for the minimum, maximum, and absolute value.*)\nLemma ltrgt0P x : comparer0 x (min 0 x) (min x 0) (max 0 x) (max x 0)\n `|x| (0 == x) (x == 0) (x <= 0) (0 <= x) (x < 0) (x > 0).\n\n(*This lemma states that the product of two real numbers is negative if and only if both numbers are non-zero and exactly one of the two numbers is negative.*)\nLemma mulr_lt0 x y :\n (x * y < 0) = [&& x != 0, y != 0 & (x < 0) (+) (y < 0)].\n\n(*This lemma states that for any two non-zero real numbers, their product is negative if and only if exactly one of the two numbers is negative.*)\nLemma neq0_mulr_lt0 x y :\n x != 0 -> y != 0 -> (x * y < 0) = (x < 0) (+) (y < 0).\n\n(*This lemma states that multiplying a real number by a sign factor, represented by a boolean, results in a negative value if and only if the real number is non-zero and the boolean indicating the sign factor is different from the boolean indicating whether the number is negative.*)\nLemma mulr_sign_lt0 (b : bool) x :\n ((-1) ^+ b * x < 0) = (x != 0) && (b (+) (x < 0)%R).\n\n(*This lemma states that a real number can be reconstructed by multiplying its absolute value by a sign factor, which is negative one if the number is negative and positive one otherwise.*)\nLemma mulr_sign_norm x : (-1) ^+ (x < 0)%R * `|x| = x.\n\n(*This lemma states that the additive inverse of a real number is equal to its absolute value multiplied by a sign factor, which is negative one if the number is positive and positive one otherwise.*)\nLemma mulr_Nsign_norm x : (-1) ^+ (0 < x)%R * `|x| = - x.\n\n(*This lemma states that any real number is equal to the product of its absolute value and a sign factor, where the factor is negative one if the number is negative and positive one otherwise.*)\nLemma numEsign x : x = (-1) ^+ (x < 0)%R * `|x|.\n\n(*This lemma states that the additive inverse of a real number is equal to the product of the number's absolute value and a sign factor, where the factor is negative one if the number is positive and positive one otherwise.*)\nLemma numNEsign x : -x = (-1) ^+ (0 < x)%R * `|x|.\n\n(*This lemma states that the absolute value of a real number is obtained by multiplying the number by a sign factor, which is negative one if the number is negative and positive one otherwise.*)\nLemma normrEsign x : `|x| = (-1) ^+ (x < 0)%R * x.\n\nEnd RealDomainTheory.\n\n#[global] Hint Resolve num_real : core.\n\nSection RealDomainOperations.\n\n(*This notation represents the argument `i` that minimizes a given function `F` over all natural numbers `i` less than a given bound `i0` and satisfying a predicate `P`. The minimization is performed with respect to the standard order on a ring.*)\nNotation \"[ 'arg' 'min_' ( i < i0 | P ) F ]\" :=\n (Order.arg_min (disp := ring_display) i0 (fun i => P%B) (fun i => F)) :\n ring_scope.\n\n(*This notation is a specialized form for finding the argument `i` that minimizes a function `F`. It searches over all natural numbers `i` less than a given bound `i0` that are also members of a given set `A`.*)\nNotation \"[ 'arg' 'min_' ( i < i0 'in' A ) F ]\" :=\n [arg min_(i < i0 | i \\in A) F] : ring_scope.\n\n(*This notation is a simplified form for finding the argument `i` that minimizes a function `F`. It searches over all natural numbers `i` less than a given bound `i0`, without any additional conditions.*)\nNotation \"[ 'arg' 'min_' ( i < i0 ) F ]\" := [arg min_(i < i0 | true) F] :\n ring_scope.\n\n(*This notation represents the argument `i` that maximizes a given function `F` over all natural numbers `i` less than a given bound `i0` and satisfying a predicate `P`. The maximization is performed with respect to the standard order on a ring.*)\nNotation \"[ 'arg' 'max_' ( i > i0 | P ) F ]\" :=\n (Order.arg_max (disp := ring_display) i0 (fun i => P%B) (fun i => F)) :\n ring_scope.\n\n(*This notation is a specialized form for finding the argument `i` that maximizes a function `F`. It searches over all natural numbers `i` less than a given bound `i0` that are also members of a given set `A`.*)\nNotation \"[ 'arg' 'max_' ( i > i0 'in' A ) F ]\" :=\n [arg max_(i > i0 | i \\in A) F] : ring_scope.\n\n(*This notation is a simplified form for finding the argument `i` that maximizes a function `F`. It searches over all natural numbers `i` less than a given bound `i0`, without any additional conditions.*)\nNotation \"[ 'arg' 'max_' ( i > i0 ) F ]\" := [arg max_(i > i0 | true) F] :\n ring_scope.\n\nVariable R : realDomainType.\nImplicit Types x y z t : R.\n(*This is a hint for Coq's typeclass inference, which registers the fact that the embedding of natural numbers into the real domain is a ring morphism.*)\nLet numR_real := @num_real R.\nHint Resolve numR_real : core.\n\n(*This lemma states that for any real number, its sign is one if and only if the number is positive, its sign is negative one if and only if the number is negative, and its sign is zero if and only if the number is zero.*)\nLemma sgr_cp0 x :\n ((sg x == 1) = (0 < x)) *\n ((sg x == -1) = (x < 0)) *\n ((sg x == 0) = (x == 0)).\n\n(*This inductive type provides a structured proof of the properties of a real number based on its sign, encapsulating different cases for whether the number is zero, positive, or negative, and bundling related boolean facts and values like its absolute value and sign.*)\nVariant sgr_val x : R -> bool -> bool -> bool -> bool -> bool -> bool\n -> bool -> bool -> bool -> bool -> bool -> bool -> R -> Set :=\n(*This lemma states that the sign of an element is zero if and only if the element itself is zero.*)\n | SgrNull of x = 0 : sgr_val x 0 true true true true false false\n true false false true false false 0\n(*This lemma states that the sign of an element is one if and only if the element is strictly greater than zero.*)\n | SgrPos of x > 0 : sgr_val x x false false true false false true\n false false true false false true 1\n(*This lemma states that the sign of an element is negative one if and only if the element is strictly less than zero.*)\n | SgrNeg of x < 0 : sgr_val x (- x) false true false false true false\n false true false false true false (-1).\n\n(*This lemma provides a constructive proof that bundles properties of a real number related to its sign, enabling case analysis on whether the number is positive, negative, or zero.*)\nLemma sgrP x :\n sgr_val x `|x| (0 == x) (x <= 0) (0 <= x) (x == 0) (x < 0) (0 < x)\n (0 == sg x) (-1 == sg x) (1 == sg x)\n (sg x == 0) (sg x == -1) (sg x == 1) (sg x).\n\n(*This lemma states that the absolute value of a real number is equal to the product of its sign and the number itself.*)\nLemma normrEsg x : `|x| = sg x * x.\n\n(*This lemma states that any real number can be expressed as the product of its sign and its absolute value.*)\nLemma numEsg x : x = sg x * `|x|.\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"use `numEsg` instead\")]\n(*This lemma states that the product of the sign of a real number and its absolute value is equal to the number itself.*)\nLemma mulr_sg_norm x : sg x * `|x| = x. \n\n(*This lemma states that the sign of the product of two real numbers is equal to the product of their individual signs.*)\nLemma sgrM x y : sg (x * y) = sg x * sg y.\n\n(*This lemma states that the sign of the negation of a real number is equal to the negation of its sign.*)\nLemma sgrN x : sg (- x) = - sg x.\n\n(*This lemma states that for a real number and a natural number exponent, the sign of the number raised to the exponent is equal to the sign of the number raised to the same exponent.*)\nLemma sgrX n x : sg (x ^+ n) = (sg x) ^+ n.\n\n(*This lemma states that the sign of the product of the sign of a first real number and a second real number is equal to the product of the signs of the two numbers.*)\nLemma sgr_smul x y : sg (sg x * y) = sg x * sg y.\n\n(*This lemma states that the sign of a real number is positive if and only if the number itself is positive.*)\nLemma sgr_gt0 x : (sg x > 0) = (x > 0).\n\n(*This lemma states that the sign of a real number is non-negative if and only if the number itself is non-negative.*)\nLemma sgr_ge0 x : (sgr x >= 0) = (x >= 0).\n\n(*This lemma states that any real number is less than or equal to its own absolute value.*)\nLemma ler_norm x : (x <= `|x|).\n\n(*This lemma states that the absolute value of a real number is less than or equal to another real number if and only if the first number lies in the closed interval from the negation of the second number to the second number.*)\nLemma ler_norml x y : (`|x| <= y) = (- y <= x <= y).\n\n(*This lemma provides a boolean reflection, stating that the absolute value of a first real number is less than or equal to a second real number if and only if both the first number and its negation are less than or equal to the second number.*)\nLemma ler_normlP x y : reflect ((- x <= y) * (x <= y)) (`|x| <= y).\n\nArguments ler_normlP {x y}.\n\n(*This lemma states that the absolute value of a first real number equals a second real number if and only if the second number is non-negative and the first number is equal to either the second number or its negation.*)\nLemma eqr_norml x y : (`|x| == y) = ((x == y) || (x == -y)) && (0 <= y).\n\n(*This lemma states that the absolute values of two real numbers are equal if and only if the two numbers are equal to each other or one is the negation of the other.*)\nLemma eqr_norm2 x y : (`|x| == `|y|) = (x == y) || (x == -y).\n\n(*This lemma states that the absolute value of a real number is strictly less than another real number if and only if the first number lies in the open interval from the negation of the second number to the second number.*)\nLemma ltr_norml x y : (`|x| < y) = (- y < x < y).\n\n(*This definition pairs two lemmas, one for non-strict inequality and one for strict inequality, which relate the absolute value of a number being less than or equal to, or strictly less than, another number to an interval condition.*)\nDefinition lter_norml := (ler_norml, ltr_norml).\n\n(*This lemma provides a boolean reflection, stating that the absolute value of a first real number is strictly less than a second real number if and only if both the first number and its negation are strictly less than the second number.*)\nLemma ltr_normlP x y : reflect ((-x < y) * (x < y)) (`|x| < y).\n\nArguments ltr_normlP {x y}.\n\n(*This lemma states that if the absolute value of a real number is strictly less than another real number, then the first number is also strictly less than the second number.*)\nLemma ltr_normlW x y : `|x| < y -> x < y. \n\n(*This lemma states that if the absolute value of a real number is strictly less than another real number, then the first number is strictly greater than the negation of the second number.*)\nLemma ltrNnormlW x y : `|x| < y -> - y < x. \n\n(*This lemma states that if the absolute value of a real number is less than or equal to another real number, then the first number is also less than or equal to the second number.*)\nLemma ler_normlW x y : `|x| <= y -> x <= y. \n\n(*This lemma states that if the absolute value of a real number is less than or equal to another real number, then the first number is greater than or equal to the negation of the second number.*)\nLemma lerNnormlW x y : `|x| <= y -> - y <= x. \n\n(*This lemma states that a first real number is less than or equal to the absolute value of a second real number if and only if the first number is less than or equal to the second number or it is less than or equal to the negation of the second number.*)\nLemma ler_normr x y : (x <= `|y|) = (x <= y) || (x <= - y).\n\n(*This lemma states that a first real number is strictly less than the absolute value of a second real number if and only if the first number is strictly less than the second number or it is strictly less than the negation of the second number.*)\nLemma ltr_normr x y : (x < `|y|) = (x < y) || (x < - y).\n\n(*This definition pairs two lemmas, one for non-strict inequality and one for strict inequality, which characterize when a real number is less than or equal to, or strictly less than, the absolute value of another real number.*)\nDefinition lter_normr := (ler_normr, ltr_normr).\n\n(*This lemma states that the absolute value of the difference between two real numbers `x` and `y` is less than or equal to a third real number `e` if and only if `x` lies in the closed interval from `y` minus `e` to `y` plus `e`.*)\nLemma ler_distl x y e : (`|x - y| <= e) = (y - e <= x <= y + e).\n\n(*This lemma states that the absolute value of the difference between two real numbers `x` and `y` is strictly less than a third real number `e` if and only if `x` lies in the open interval from `y` minus `e` to `y` plus `e`.*)\nLemma ltr_distl x y e : (`|x - y| < e) = (y - e < x < y + e).\n\n(*This definition provides a pair of lemmas relating the absolute value of a difference between two numbers to an upper bound. One lemma handles the case of a strict inequality, and the other handles a non-strict inequality.*)\nDefinition lter_distl := (ler_distl, ltr_distl).\n\n(*This lemma states that the absolute value of the difference between two ring elements is strictly less than a third ring element if and only if the second ring element lies strictly between the first element minus the third and the first element plus the third.*)\nLemma ltr_distlC x y e : (`|x - y| < e) = (x - e < y < x + e).\n\n(*This lemma states that the absolute value of the difference between two ring elements is less than or equal to a third ring element if and only if the second ring element lies between the first element minus the third and the first element plus the third, inclusively.*)\nLemma ler_distlC x y e : (`|x - y| <= e) = (x - e <= y <= x + e).\n\n(*This definition creates a pair of lemmas that characterize the inequality on the absolute value of a difference between two ring elements in terms of an interval around one of the elements.*)\nDefinition lter_distlC := (ler_distlC, ltr_distlC).\n\n(*This lemma states that if the absolute value of the difference between two ring elements is strictly less than a third ring element, then the first ring element is strictly less than the sum of the second and third ring elements.*)\nLemma ltr_distlDr x y e : `|x - y| < e -> x < y + e.\n\n(*This lemma states that if the absolute value of the difference between two ring elements is less than or equal to a third ring element, then the first ring element is less than or equal to the sum of the second and third ring elements.*)\nLemma ler_distlDr x y e : `|x - y| <= e -> x <= y + e.\n\n(*This lemma states that if the absolute value of the difference between two ring elements is strictly less than a third ring element, then the second ring element is strictly less than the sum of the first and third ring elements.*)\nLemma ltr_distlCDr x y e : `|x - y| < e -> y < x + e.\n\n(*This lemma states that if the absolute value of the difference between two ring elements is less than or equal to a third ring element, then the second ring element is less than or equal to the sum of the first and third ring elements.*)\nLemma ler_distlCDr x y e : `|x - y| <= e -> y <= x + e.\n\n(*This lemma states that if the absolute value of the difference between two ring elements is strictly less than a third ring element, then the difference between the first and third ring elements is strictly less than the second ring element.*)\nLemma ltr_distlBl x y e : `|x - y| < e -> x - e < y.\n\n(*This lemma states that if the absolute value of the difference between two ring elements is less than or equal to a third ring element, then the difference between the first and third ring elements is less than or equal to the second ring element.*)\nLemma ler_distlBl x y e : `|x - y| <= e -> x - e <= y.\n\n(*This lemma states that if the absolute value of the difference between two ring elements is strictly less than a third ring element, then the difference between the second and third ring elements is strictly less than the first ring element.*)\nLemma ltr_distlCBl x y e : `|x - y| < e -> y - e < x.\n\n(*This lemma states that if the absolute value of the difference between two ring elements is less than or equal to a third ring element, then the difference between the second and third ring elements is less than or equal to the first ring element.*)\nLemma ler_distlCBl x y e : `|x - y| <= e -> y - e <= x.\n\n(*This lemma states that for a ring element raised to the power of an even natural number, the result is always greater than or equal to zero.*)\nLemma exprn_even_ge0 n x : ~~ odd n -> 0 <= x ^+ n.\n\n(*This lemma states that for a ring element raised to the power of an even natural number, the result is strictly greater than zero if and only if the exponent is zero or the base is nonzero.*)\nLemma exprn_even_gt0 n x : ~~ odd n -> (0 < x ^+ n) = (n == 0)%N || (x != 0).\n\n(*This lemma states that for a ring element raised to the power of an even natural number, the result is less than or equal to zero if and only if the exponent is nonzero and the base is zero.*)\nLemma exprn_even_le0 n x : ~~ odd n -> (x ^+ n <= 0) = (n != 0) && (x == 0).\n\n(*This lemma states that a ring element raised to the power of an even natural number can never be strictly less than zero.*)\nLemma exprn_even_lt0 n x : ~~ odd n -> (x ^+ n < 0) = false.\n\n(*This lemma states that for a ring element raised to the power of an odd natural number, the result is greater than or equal to zero if and only if the base is greater than or equal to zero.*)\nLemma exprn_odd_ge0 n x : odd n -> (0 <= x ^+ n) = (0 <= x).\n\n(*This lemma states that for a ring element raised to the power of an odd natural number, the result is strictly greater than zero if and only if the base is strictly greater than zero.*)\nLemma exprn_odd_gt0 n x : odd n -> (0 < x ^+ n) = (0 < x).\n\n(*This lemma states that for a ring element raised to the power of an odd natural number, the result is less than or equal to zero if and only if the base is less than or equal to zero.*)\nLemma exprn_odd_le0 n x : odd n -> (x ^+ n <= 0) = (x <= 0).\n\n(*This lemma states that for a ring element raised to the power of an odd natural number, the result is strictly less than zero if and only if the base is strictly less than zero.*)\nLemma exprn_odd_lt0 n x : odd n -> (x ^+ n < 0) = (x < 0).\n\n(*This lemma characterizes a conditional inequality involving the absolute value of a ring element. It asserts that the absolute value of a first ring element is conditionally less than a second ring element if and only if the first element is both conditionally greater than the negation of the second and conditionally less than the second.*)\nLemma lteif_norml C x y :\n (`|x| < y ?<= if C) = (- y < x ?<= if C) && (x < y ?<= if C).\n\n(*This lemma provides a characterization for a conditional inequality where a ring element is compared to the absolute value of another. It states that a first ring element is conditionally less than the absolute value of a second ring element if and only if the first element is conditionally less than the second element, or the first element is conditionally less than the negation of the second element.*)\nLemma lteif_normr C x y :\n (x < `|y| ?<= if C) = (x < y ?<= if C) || (x < - y ?<= if C).\n\n(*This lemma provides a characterization for a conditional inequality involving the absolute value of a difference between two ring elements. It states that the absolute value of this difference is conditionally less than a third ring element if and only if the first element is conditionally greater than the difference of the second and third elements, and also conditionally less than the sum of the second and third elements.*)\nLemma lteif_distl C x y e :\n (`|x - y| < e ?<= if C) = (y - e < x ?<= if C) && (x < y + e ?<= if C).\n\n(*This lemma states that the square of any ring element is always greater than or equal to zero.*)\nLemma sqr_ge0 x : 0 <= x ^+ 2. \n\n(*This lemma states that the square of a ring element is equal to one if and only if the absolute value of that element is equal to one.*)\nLemma sqr_norm_eq1 x : (x ^+ 2 == 1) = (`|x| == 1).\n\n(*This lemma states that twice the product of two ring elements is less than or equal to the sum of their squares, where equality holds if and only if the two elements are equal.*)\nLemma leif_mean_square_scaled x y :\n x * y *+ 2 <= x ^+ 2 + y ^+ 2 ?= iff (x == y).\n\n(*This lemma states a scaled version of the arithmetic-geometric mean inequality for two ring elements. It asserts that four times the product of two ring elements is less than or equal to the square of their sum, with equality holding if and only if the two elements are equal.*)\nLemma leif_AGM2_scaled x y : x * y *+ 4 <= (x + y) ^+ 2 ?= iff (x == y).\n\nSection MinMax.\n\n(*This lemma states that the additive inverse operation is a morphism that maps the maximum of two ring elements to the minimum of their additive inverses.*)\nLemma oppr_max : {morph -%R : x y / max x y >-> min x y : R}.\n\n(*This lemma states that the additive inverse operation is a morphism that maps the minimum of two ring elements to the maximum of their additive inverses.*)\nLemma oppr_min : {morph -%R : x y / min x y >-> max x y : R}.\n\n(*This lemma states that addition on a ring is left-distributive over the minimum operation.*)\nLemma addr_minl : @left_distributive R R +%R min.\n\n(*This lemma states that addition distributes over the minimum operation from the right, meaning the result of adding a ring element to the minimum of two others is the same as taking the minimum of the individual sums of that element with each of the other two.*)\nLemma addr_minr : @right_distributive R R +%R min.\n\n(*This lemma states that addition distributes over the maximum operation from the left, meaning the result of adding a ring element to the maximum of two others is the same as taking the maximum of the individual sums of that element with each of the other two.*)\nLemma addr_maxl : @left_distributive R R +%R max.\n\n(*This lemma states that addition distributes over the maximum operation from the right, meaning the result of adding a ring element to the maximum of two others is the same as taking the maximum of the individual sums of that element with each of the other two.*)\nLemma addr_maxr : @right_distributive R R +%R max.\n\n(*This lemma states that for any three ring elements, if the first element is less than or equal to zero, multiplying it by the minimum of the other two is equivalent to taking the maximum of the products of the first element with each of the other two.*)\nLemma minr_nMr x y z : x <= 0 -> x * min y z = max (x * y) (x * z).\n\n(*This lemma states that for any three ring elements, if the first element is less than or equal to zero, multiplying it by the maximum of the other two is equivalent to taking the minimum of the products of the first element with each of the other two.*)\nLemma maxr_nMr x y z : x <= 0 -> x * max y z = min (x * y) (x * z).\n\n(*This lemma states that for any three ring elements, if the third element is less than or equal to zero, multiplying the minimum of the first two by the third is equivalent to taking the maximum of the products of each of the first two elements with the third.*)\nLemma minr_nMl x y z : x <= 0 -> min y z * x = max (y * x) (z * x).\n\n(*This lemma states that for any three ring elements, if the third element is less than or equal to zero, multiplying the maximum of the first two by the third is equivalent to taking the minimum of the products of each of the first two elements with the third.*)\nLemma maxr_nMl x y z : x <= 0 -> max y z * x = min (y * x) (z * x).\n\n(*This lemma states that the maximum of a ring element and its additive inverse is equal to its absolute value.*)\nLemma maxrN x : max x (- x) = `|x|. \n(*This lemma states that the maximum of the additive inverse of a ring element and the element itself is equal to its absolute value.*)\nLemma maxNr x : max (- x) x = `|x|. \n(*This lemma states that the minimum of a ring element and its additive inverse is equal to the additive inverse of its absolute value.*)\nLemma minrN x : min x (- x) = - `|x|. \n(*This lemma states that the minimum of the additive inverse of a ring element and the element itself is equal to the additive inverse of its absolute value.*)\nLemma minNr x : min (- x) x = - `|x|. \n\nEnd MinMax.\n\nSection PolyBounds.\n\nVariable p : {poly R}.\n\n(*This lemma states that for a given polynomial over a ring and two ring elements defining a closed interval, there exists an upper bound for the absolute value of the polynomial when evaluated at any point within that interval.*)\nLemma poly_itv_bound a b : {ub | forall x, a <= x <= b -> `|p.[x]| <= ub}.\n\n(*This lemma states that for any monic polynomial, there exists a lower bound such that for all inputs greater than or equal to this bound, the polynomial's value is strictly positive.*)\nLemma monic_Cauchy_bound : p \\is monic -> {b | forall x, x >= b -> p.[x] > 0}.\n\nEnd PolyBounds.\n\nEnd RealDomainOperations.\n\nEnd Theory.\n\n(*This factory defines a numerical ring structure on an integral domain by providing a less-than-or-equal relation, a less-than relation, a norm function, and axioms that connect these concepts with the ring's arithmetic, such as the triangle inequality for the norm and the totality of the order on non-negative elements.*)\nHB.factory Record IntegralDomain_isNumRing R of GRing.IntegralDomain R := {\n Rle : rel R;\n Rlt : rel R;\n norm : R -> R;\n normD : forall x y, Rle (norm (x + y)) (norm x + norm y);\n addr_gt0 : forall x y, Rlt 0 x -> Rlt 0 y -> Rlt 0 (x + y);\n norm_eq0 : forall x, norm x = 0 -> x = 0;\n ger_total : forall x y, Rle 0 x -> Rle 0 y -> Rle x y || Rle y x;\n normM : {morph norm : x y / x * y};\n le_def : forall x y, (Rle x y) = (norm (y - x) == y - x);\n lt_def : forall x y, (Rlt x y) = (y != x) && (Rle x y)\n}.\n\nHB.builders Context R of IntegralDomain_isNumRing R.\n Local Notation \"x <= y\" := (Rle x y) : ring_scope.\n Local Notation \"x < y\" := (Rlt x y) : ring_scope.\n Local Notation \"`| x |\" := (norm x) : ring_scope.\n\n(*This lemma states that the strict less-than relation is irreflexive, meaning an element is never strictly less than itself.*)\n Lemma ltrr x : x < x = false. \n\n(*This lemma states that an element is greater than or equal to zero if and only if its absolute value is equal to itself.*)\n Lemma ge0_def x : (0 <= x) = (`|x| == x).\n \n\n(*This lemma states that the difference of two elements in a numerical domain is greater than or equal to zero if and only if the second element is less than or equal to the first.*)\n Lemma subr_ge0 x y : (0 <= x - y) = (y <= x).\n \n\n(*This lemma states that the result of subtracting a first element from a second element is strictly positive if and only if the first element is strictly less than the second.*)\n Lemma subr_gt0 x y : (0 < y - x) = (x < y).\n \n\n(*This lemma states that the strict less-than relation is transitive.*)\n Lemma lt_trans : transitive Rlt.\n \n\n(*This lemma states that the zero element is less than or equal to the one element in the ring.*)\n Lemma le01 : 0 <= 1.\n \n\n(*This lemma states that the zero element is strictly less than the one element, which holds in non-trivial rings.*)\n Lemma lt01 : 0 < 1.\n \n\n(*This lemma states that if an element is strictly less than another, it is also less than or equal to it.*)\n Lemma ltW x y : x < y -> x <= y. \n\n(*This lemma states that the less-than-or-equal relation is reflexive, meaning every element is less than or equal to itself.*)\n Lemma lerr x : x <= x.\n \n\n Lemma le_def' x y : (x <= y) = (x == y) || (x < y).\n \n\n(*This lemma states that the less-than-or-equal relation is transitive.*)\n Lemma le_trans : transitive Rle.\n \n\n(*This lemma states that the norm of a ring element multiplied by a natural number, as repeated addition, is equal to the product of the element's norm and that same natural number.*)\n Lemma normrMn x n : `|x *+ n| = `|x| *+ n.\n \n\n(*This lemma states that the norm of the additive inverse of the multiplicative identity is the multiplicative identity.*)\n Lemma normrN1 : `|-1| = 1 :> R.\n \n\n(*This lemma states that the norm of the additive inverse of a ring element is equal to the norm of the original element.*)\n Lemma normrN x : `|- x| = `|x|.\n \n\n HB.instance Definition _ :=\n Order.LtLe_isPOrder.Build ring_display R le_def' ltrr lt_trans.\n\n HB.instance Definition _ :=\n Zmodule_isNormed.Build _ R normD norm_eq0 normrMn normrN.\n\n HB.instance Definition _ :=\n isNumRing.Build R addr_gt0 ger_total normM le_def.\nHB.end.\n\n(*This factory promotes a numerical domain to a real domain by asserting that it satisfies the axioms of real numbers, such as the axiom of completeness.*)\nHB.factory Record NumDomain_isReal R of NumDomain R := {\n real : real_axiom R\n}.\n\nHB.builders Context R of NumDomain_isReal R.\n Lemma le_total : Order.POrder_isTotal ring_display R.\n \n\n HB.instance Definition _ := le_total.\nHB.end.\n\n(*This factory defines a real number-like ordered structure on an integral domain by specifying a less-than-or-equal relation, a strict less-than relation, a norm, and axioms based on a cone of non-negative elements, including closure under addition and multiplication, totality, and compatibility with subtraction.*)\nHB.factory Record IntegralDomain_isLeReal R of GRing.IntegralDomain R := {\n Rle : rel R;\n Rlt : rel R;\n norm : R -> R;\n le0_add : forall x y, Rle 0 x -> Rle 0 y -> Rle 0 (x + y);\n le0_mul : forall x y, Rle 0 x -> Rle 0 y -> Rle 0 (x * y);\n le0_anti : forall x, Rle 0 x -> Rle x 0 -> x = 0;\n sub_ge0 : forall x y, Rle 0 (y - x) = Rle x y;\n le0_total : forall x, Rle 0 x || Rle x 0;\n normN : forall x, norm (- x) = norm x;\n ge0_norm : forall x, Rle 0 x -> norm x = x;\n lt_def : forall x y, Rlt x y = (y != x) && Rle x y;\n}.\n\nHB.builders Context R of IntegralDomain_isLeReal R.\n Local Notation le := Rle.\n Local Notation lt := Rlt.\n\n Local Notation \"x <= y\" := (le x y) : ring_scope.\n Local Notation \"x < y\" := (lt x y) : ring_scope.\n Local Notation \"`| x |\" := (norm x) : ring_scope.\n\n(*This lemma states that the additive inverse of an element is greater than or equal to zero if and only if the original element is less than or equal to zero.*)\n Let le0N x : (0 <= - x) = (x <= 0). \n Let leN_total x : 0 <= x \\/ 0 <= - x.\n \n\n Let le00 : 0 <= 0. \n\n(*This field requires that the sum of two strictly positive ring elements must also be strictly positive.*)\n Fact lt0_add x y : 0 < x -> 0 < y -> 0 < x + y.\n \n\n Fact eq0_norm x : `|x| = 0 -> x = 0.\n \n\n(*This field defines the non-strict less-than-or-equal relation as being equivalent to the disjunction of equality and the strict less-than relation.*)\n Fact le_def x y : (x <= y) = (`|y - x| == y - x).\n \n\n Fact normM : {morph norm : x y / x * y}.\n \n\n Fact le_normD x y : `|x + y| <= `|x| + `|y|.\n \n\n Fact le_total : total le.\n \n\n HB.instance Definition _ := IntegralDomain_isNumRing.Build R\n le_normD lt0_add eq0_norm (in2W le_total) normM le_def lt_def.\n\n HB.instance Definition _ := Order.POrder_isTotal.Build ring_display R\n le_total.\nHB.end.\n\n(*This structure equips an integral domain with a strict less-than relation, a non-strict less-than-or-equal relation, and a norm function, satisfying axioms that characterize it as an ordered ring similar to the real numbers.*)\nHB.factory Record IntegralDomain_isLtReal R of GRing.IntegralDomain R := {\n Rlt : rel R;\n Rle : rel R;\n norm : R -> R;\n lt0_add : forall x y, Rlt 0 x -> Rlt 0 y -> Rlt 0 (x + y);\n lt0_mul : forall x y, Rlt 0 x -> Rlt 0 y -> Rlt 0 (x * y);\n lt0_ngt0 : forall x, Rlt 0 x -> ~~ (Rlt x 0);\n sub_gt0 : forall x y, Rlt 0 (y - x) = Rlt x y;\n lt0_total : forall x, x != 0 -> Rlt 0 x || Rlt x 0;\n normN : forall x, norm (- x) = norm x;\n ge0_norm : forall x, Rle 0 x -> norm x = x;\n le_def : forall x y, Rle x y = (x == y) || Rlt x y;\n}.\n\nHB.builders Context R of IntegralDomain_isLtReal R.\n(*This is a local alias for the less-than-or-equal relation on the ring.*)\n Local Notation le := Rle.\n(*This is a local alias for the strict less-than relation on the ring.*)\n Local Notation lt := Rlt.\n\n(*This notation represents the strict less-than comparison between two ring elements.*)\n Local Notation \"x < y\" := (lt x y) : ring_scope.\n(*This notation represents the non-strict less-than-or-equal comparison between two ring elements.*)\n Local Notation \"x <= y\" := (le x y) : ring_scope.\n(*This notation represents the norm, or absolute value, of a ring element.*)\n Local Notation \"`| x |\" := (norm x) : ring_scope.\n\n(*This lemma states that the additive inverse of a ring element is strictly less than zero if and only if the original element is strictly greater than zero.*)\n Fact lt0N x : (- x < 0) = (0 < x).\n \n(*This lemma asserts that for any given ring element, either the element is greater than or equal to zero, or its additive inverse is greater than or equal to zero.*)\n Let leN_total x : 0 <= x \\/ 0 <= - x.\n \n\n(*This lemma states that zero is less than or equal to itself.*)\n Let le00 : (0 <= 0). \n\n(*This lemma states that the difference of two ring elements is greater than or equal to zero if and only if the first element is less than or equal to the second.*)\n Fact sub_ge0 x y : (0 <= y - x) = (x <= y).\n \n\n(*This lemma states that the sum of two ring elements that are greater than or equal to zero is also greater than or equal to zero.*)\n Fact le0_add x y : 0 <= x -> 0 <= y -> 0 <= x + y.\n \n\n(*This lemma states that the product of two ring elements that are greater than or equal to zero is also greater than or equal to zero.*)\n Fact le0_mul x y : 0 <= x -> 0 <= y -> 0 <= x * y.\n \n\n(*This lemma establishes that the norm function is a multiplicative morphism, meaning the norm of a product of two ring elements is equal to the product of their individual norms.*)\n Fact normM : {morph norm : x y / x * y}.\n \n\n(*This lemma establishes the triangle inequality for the norm function, stating that the norm of the sum of two ring elements is less than or equal to the sum of their individual norms.*)\n Fact le_normD x y : `|x + y| <= `|x| + `|y|.\n \n\n(*This lemma asserts that if the norm of a ring element is zero, then the element itself must be the zero element.*)\n Fact eq0_norm x : `|x| = 0 -> x = 0.\n \n\n(*This lemma states that a ring element is less than or equal to another if and only if the difference of the second element minus the first is equal to its own norm.*)\n Fact le_def' x y : (x <= y) = (`|y - x| == y - x).\n \n\n(*This lemma defines the strict less-than relation between two ring elements as the condition where the first element is less than or equal to the second, and the two elements are not equal.*)\n Fact lt_def x y : (x < y) = (y != x) && (x <= y).\n \n\n(*This lemma states that the less-than-or-equal relation is total, meaning any two ring elements are comparable.*)\n Fact le_total : total le.\n \n\n HB.instance Definition _ := IntegralDomain_isNumRing.Build R\n le_normD lt0_add eq0_norm (in2W le_total) normM le_def' lt_def.", - "algebra.num_theory.ssrnum": "From mathcomp Require Export orderedzmod.\nFrom mathcomp Require Export numdomain.\nFrom mathcomp Require Export numfield.\n\nModule Num.\nExport orderedzmod.Num.\nExport numdomain.Num.\nExport numfield.Num.\n\nModule Theory.\nExport orderedzmod.Num.Theory.\nExport numdomain.Num.Theory.\nExport numfield.Num.Theory.\nEnd Theory.\n\nModule Def.\nExport orderedzmod.Num.Def.\nExport numdomain.Num.Def.\nExport numfield.Num.Def.\nEnd Def.\n\nModule ExtraDef.\n#[deprecated(since=\"mathcomp 2.5.0\", note=\"Use Num.Def.sqrtr instead.\")]\n(*This function computes the principal (non-negative) square root of the positive part of a given real number. For a non-negative input, this corresponds to the standard square root, while for a negative input, the result is zero.*)\nNotation sqrtr := numfield.Num.Def.sqrtr.\nEnd ExtraDef.", - "fingroup.quotient": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype prime finset fingroup morphism.\nFrom mathcomp Require Import automorphism.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection Cosets.\n\nVariables (gT : finGroupType) (Q A : {set gT}).\n\n(*A notation for the subgroup generated by a given set of group elements `A`.*)\nNotation H := <>.\n(*This definition specifies a predicate which is true for any set of group elements that is both a right coset of the subgroup `H` and a subset of the normalizer of the set `A`.*)\nDefinition coset_range := [pred B in rcosets H 'N(A)].\n\n(*This record defines a type for right cosets of a subgroup `H` that are contained within the normalizer of a set `A`. Each element of this type encapsulates a set of group elements along with a proof that it satisfies the required coset properties.*)\nRecord coset_of : Type :=\n Coset { set_of_coset :> GroupSet.sort gT; _ : coset_range set_of_coset }.\n\nHB.instance Definition _ := [isSub for set_of_coset].\n#[hnf] HB.instance Definition _ := [Finite of coset_of by <:].\n\n(*This lemma states that the subgroup `H` itself satisfies the property of being a right coset within the normalizer of a set `A`.*)\nLemma coset_one_proof : coset_range H.\n\n(*This definition establishes the identity element for the group of cosets, which corresponds to the subgroup `H` itself.*)\nDefinition coset_one := Coset coset_one_proof.\n\n(*This is a local proposition asserting that the normalizer of a set of group elements `A` is equal to the normalizer of the subgroup that `A` generates.*)\nLet nNH := subsetP (norm_gen A).\n\n(*This lemma states that the product of two cosets that are in the normalizer of a set `A` is also a coset in the normalizer of `A`.*)\nLemma coset_range_mul (B C : coset_of) : coset_range (B * C).\n\n(*This definition specifies the multiplication operation for the group of cosets, forming a new coset from the set-product of two given cosets.*)\nDefinition coset_mul B C := Coset (coset_range_mul B C).\n\n(*This lemma states that the set-theoretic inverse of a coset that is in the normalizer of a set `A` is also a coset in the normalizer of `A`.*)\nLemma coset_range_inv (B : coset_of) : coset_range B^-1.\n\n(*This definition specifies the inverse operation for the group of cosets, forming a new coset from the set of inverses of the elements of a given coset.*)\nDefinition coset_inv B := Coset (coset_range_inv B).\n\n(*This lemma states that the multiplication operation on cosets is associative.*)\nLemma coset_mulP : associative coset_mul.\n\n(*This lemma states that the identity coset acts as a left identity for coset multiplication.*)\nLemma coset_oneP : left_id coset_one coset_mul.\n\n(*This lemma states that the coset inverse operation provides a left inverse for every coset with respect to coset multiplication.*)\nLemma coset_invP : left_inverse coset_one coset_inv coset_mul.\n\n(*This definition provides a function that maps an element of a group to its corresponding right coset with respect to the subgroup `H`.*)\nDefinition coset x : coset_of := insubd (1 : coset_of) (H :* x).\n\n(*This lemma states that for any group element belonging to the normalizer of set `A`, the `coset` function applied to that element is definitionally equal to the right coset formed by multiplying the subgroup `H` by that element.*)\nLemma val_coset_prim x : x \\in 'N(A) -> coset x :=: H :* x.\n\n(*This lemma asserts that the `coset` function, when restricted to the normalizer of the set `A`, behaves as a group homomorphism.*)\nLemma coset_morphM : {in 'N(A) &, {morph coset : x y / x * y}}.\n\nCanonical coset_morphism := Morphism coset_morphM.\n\n(*This lemma states that the kernel of the `coset` homomorphism consists of the elements that are in both the subgroup `H` and the normalizer of the set `A`.*)\nLemma ker_coset_prim : 'ker coset = 'N_H(A).\n\nImplicit Type xbar : coset_of.\n\n(*This lemma states that if a group element is a member of a certain coset, then applying the `coset` function to that element yields the original coset.*)\nLemma coset_mem y xbar : y \\in xbar -> coset y = xbar.\n\n(*This lemma states that the canonical representative chosen for a coset is an element of that same coset.*)\nLemma mem_repr_coset xbar : repr xbar \\in xbar.\n\n(*This lemma states that the canonical representative of the identity coset is the identity element of the group.*)\nLemma repr_coset1 : repr (1 : coset_of) = 1.\n\n(*This lemma states that applying the `coset` function to the canonical representative of a coset returns that original coset.*)\nLemma coset_reprK : cancel (fun xbar => repr xbar) coset.\n\n(*This lemma asserts the surjectivity of the `coset` map, stating that for any given coset, there exists an element in the normalizer of set `A` that maps to it.*)\nLemma cosetP xbar : {x | x \\in 'N(A) & xbar = coset x}.\n\n(*This lemma states that any element from the set `A`, which generates the subgroup `H`, maps to the identity coset.*)\nLemma coset_id x : x \\in A -> coset x = 1.\n\n(*This lemma states that the image of the normalizer of a set `A` under the `coset` map covers the entire set of valid cosets.*)\nLemma im_coset : coset @* 'N(A) = setT.\n\n(*This lemma states that any set of valid cosets is a subset of the image of the normalizer of a set `A` under the `coset` map.*)\nLemma sub_im_coset (C : {set coset_of}) : C \\subset coset @* 'N(A).\n\n(*This lemma provides an equivalence, stating that the preimage of one set of cosets is a proper subset of the preimage of another if and only if the first set of cosets is a proper subset of the second.*)\nLemma cosetpre_proper C D :\n (coset @*^-1 C \\proper coset @*^-1 D) = (C \\proper D).\n\n(*This definition specifies the quotient of a set of group elements as the image of that set under the `coset` function, which is the set of all cosets that have a representative in the given set.*)\nDefinition quotient : {set coset_of} := coset @* Q.\n\n(*This lemma states that the quotient of a set is definitionally equal to the image of that set under the `coset` function.*)\nLemma quotientE : quotient = coset @* Q. \n\nEnd Cosets.\n\nArguments coset_of {gT} H%_g : rename.\nArguments coset {gT} H%_g x%_g : rename.\nArguments quotient {gT} A%_g H%_g : rename.\nArguments coset_reprK {gT H%_g} xbar%_g : rename.\n\nBind Scope group_scope with coset_of.\n\n(*This notation defines the syntax `A / H` to represent the set of cosets of the subgroup generated by `H` that have a representative in the set `A`.*)\nNotation \"A / H\" := (quotient A H) : group_scope.\n\nSection CosetOfGroupTheory.\n\nVariables (gT : finGroupType) (H : {group gT}).\nImplicit Types (A B : {set gT}) (G K : {group gT}) (xbar yb : coset_of H).\nImplicit Types (C D : {set coset_of H}) (L M : {group coset_of H}).\n\nCanonical quotient_group G A : {group coset_of A} :=\n Eval hnf in [group of G / A].\n\nInfix \"/\" := quotient_group : Group_scope.\n\n(*This lemma states that for a group element `x` in the normalizer of a subgroup `H`, applying the `coset` function to `x` with respect to `H` is definitionally equal to the right coset of `H` by `x`.*)\nLemma val_coset x : x \\in 'N(H) -> coset H x :=: H :* x.\n\n(*This lemma states that if a group element is not in the normalizer of a subgroup, then the coset function maps that element to the identity element of the quotient group.*)\nLemma coset_default x : (x \\in 'N(H)) = false -> coset H x = 1.\n\n(*This lemma states that every coset of a subgroup is a subset of the normalizer of that subgroup.*)\nLemma coset_norm xbar : xbar \\subset 'N(H).\n\n(*This lemma states that the kernel of the coset-forming homomorphism associated with a subgroup is equal to the subgroup itself.*)\nLemma ker_coset : 'ker (coset H) = H.\n\n(*This lemma states that if a group element belonging to the normalizer of a subgroup is mapped to the identity element of the quotient group, then that element must be a member of the subgroup itself.*)\nLemma coset_idr x : x \\in 'N(H) -> coset H x = 1 -> x \\in H.\n\n(*This lemma states that the canonical representative element of any coset of a subgroup is an element of the normalizer of that subgroup.*)\nLemma repr_coset_norm xbar : repr xbar \\in 'N(H).\n\n(*This lemma states that the image of a set of group elements under the coset-forming map is equal to the quotient of that set by the subgroup.*)\nLemma imset_coset G : coset H @: G = G / H.\n\n(*This lemma states that the union of all sets in a quotient set is equal to the set of right cosets whose representatives are drawn from the intersection of the original set and the normalizer of the subgroup.*)\nLemma val_quotient A : val @: (A / H) = rcosets H 'N_A(H).\n\n(*This lemma states that the cardinality of a quotient set is equal to the index of the subgroup within the intersection of the original set and the normalizer of the subgroup.*)\nLemma card_quotient_subnorm A : #|A / H| = #|'N_A(H) : H|.\n\n(*This lemma states that the cardinality of a quotient set is less than or equal to the cardinality of the original set of group elements.*)\nLemma leq_quotient A : #|A / H| <= #|A|.\n\n(*This lemma states that if a subgroup is non-trivial and is contained within a set of group elements, then the cardinality of the corresponding quotient set is strictly less than the cardinality of the original set.*)\nLemma ltn_quotient A : H :!=: 1 -> H \\subset A -> #|A / H| < #|A|.\n\n(*This lemma states that if a set of group elements is a subset of the normalizer of a subgroup, then the cardinality of the quotient of the set by the subgroup is equal to the index of the subgroup in the set.*)\nLemma card_quotient A : A \\subset 'N(H) -> #|A / H| = #|A : H|.\n\n(*This lemma states that for a normal subgroup, the cardinality of the group divided by the cardinality of the subgroup equals the cardinality of the quotient group.*)\nLemma divg_normal G : H <| G -> #|G| %/ #|H| = #|G / H|.\n\n(*This lemma states that the coset generated by the identity element with respect to a subgroup is equal to the subgroup itself.*)\nLemma coset1 : coset H 1 :=: H.\n\n(*This lemma states that the preimage of the identity element of the quotient group under the coset-forming homomorphism is the subgroup itself.*)\nLemma cosetpre1 : coset H @*^-1 1 = H.\n\n(*This lemma states that the quotient of the normalizer of a subgroup by the subgroup itself yields the set of all cosets.*)\nLemma im_quotient : 'N(H) / H = setT.\n\n(*This lemma states that the quotient of the entire group by a subgroup is the set of all cosets.*)\nLemma quotientT : setT / H = setT.\n\n(*This lemma states that the quotient of the intersection of a set and a subgroup's normalizer by that subgroup is equal to the quotient of the original set by the subgroup.*)\nLemma quotientInorm A : 'N_A(H) / H = A / H.\n\n(*This lemma states that the quotient of the intersection of a set of group elements with the preimage of a set of cosets is equal to the intersection of the quotient of the original set and the set of cosets.*)\nLemma quotient_setIpre A D : (A :&: coset H @*^-1 D) / H = A / H :&: D.\n\n(*This lemma states that if an element belongs to a given set of group elements, its corresponding coset belongs to the quotient of that set by the subgroup.*)\nLemma mem_quotient x G : x \\in G -> coset H x \\in G / H.\n\n(*This lemma states that if one set of group elements is a subset of another, then the quotient of the first set by a subgroup is a subset of the quotient of the second set by the same subgroup.*)\nLemma quotientS A B : A \\subset B -> A / H \\subset B / H.\n\n(*This lemma states that the quotient of the empty set by any subgroup is the empty set.*)\nLemma quotient0 : set0 / H = set0.\n\n(*This lemma states that for any element in the normalizer of a subgroup, the quotient of the singleton set containing that element is the singleton set containing its corresponding coset.*)\nLemma quotient_set1 x : x \\in 'N(H) -> [set x] / H = [set coset H x].\n\n(*This lemma states that the quotient of the trivial subgroup by another subgroup is the trivial subgroup in the quotient group.*)\nLemma quotient1 : 1 / H = 1.\n\n(*This lemma states that the quotient of the set of inverses of a set of group elements is equal to the set of inverses of the cosets in the quotient set.*)\nLemma quotientV A : A^-1 / H = (A / H)^-1.\n\n(*This lemma states that if a set of group elements is a subset of a subgroup's normalizer, the quotient of the product of this set with another set is equal to the product of their respective quotients.*)\nLemma quotientMl A B : A \\subset 'N(H) -> A * B / H = (A / H) * (B / H).\n\n(*This lemma states that if a set of group elements is a subset of a subgroup's normalizer, the quotient of the product of another set with this set is equal to the product of their respective quotients.*)\nLemma quotientMr A B : B \\subset 'N(H) -> A * B / H = (A / H) * (B / H).\n\n(*This lemma states that the preimage of the product of two sets of cosets under the coset-forming homomorphism is equal to the product of their individual preimages.*)\nLemma cosetpreM C D : coset H @*^-1 (C * D) = coset H @*^-1 C * coset H @*^-1 D.\n\n(*This lemma states that for an element in the normalizer of a subgroup, the quotient of the conjugation of a set by that element is equal to the conjugation of the quotient of the set by the corresponding coset.*)\nLemma quotientJ A x : x \\in 'N(H) -> A :^ x / H = (A / H) :^ coset H x.\n\n(*This lemma states that the quotient of the union of two sets of group elements is equal to the union of their respective quotients.*)\nLemma quotientU A B : (A :|: B) / H = A / H :|: B / H.\n\n(*This lemma states that the quotient of the intersection of two sets of group elements is a subset of the intersection of their respective quotients.*)\nLemma quotientI A B : (A :&: B) / H \\subset A / H :&: B / H.\n\n(*This lemma states that for two subgroups contained in the normalizer of a third subgroup, the quotient of their product by the third subgroup is equal to the product of their individual quotients.*)\nLemma quotientY A B :\n A \\subset 'N(H) -> B \\subset 'N(H) -> (A <*> B) / H = (A / H) <*> (B / H).\n\n(*This lemma states that if a subgroup is contained in the normalizer of another subgroup, then its quotient is a homomorphic image of the original subgroup.*)\nLemma quotient_homg A : A \\subset 'N(H) -> homg (A / H) A.\n\n(*This lemma states that the left coset generated by the product of two group elements is identical to the left coset generated by the second element, provided the first element belongs to the subgroup defining the coset.*)\nLemma coset_kerl x y : x \\in H -> coset H (x * y) = coset H y.\n\n(*This lemma states that the left coset generated by the product of two group elements is identical to the left coset generated by the first element, provided the second element belongs to the subgroup defining the coset.*)\nLemma coset_kerr x y : y \\in H -> coset H (x * y) = coset H x.\n\n(*This lemma states that for two elements in the normalizer of a subgroup, their corresponding left cosets are equal if and only if the first element is in the right coset of the second element with respect to that subgroup.*)\nLemma rcoset_kercosetP x y :\n x \\in 'N(H) -> y \\in 'N(H) -> reflect (coset H x = coset H y) (x \\in H :* y).\n\n(*This lemma states that if two elements from the normalizer of a subgroup generate the same left coset, then the first element can be expressed as the product of some element from the subgroup and the second element.*)\nLemma kercoset_rcoset x y :\n x \\in 'N(H) -> y \\in 'N(H) ->\n coset H x = coset H y -> exists2 z, z \\in H & x = z * y.\n\n(*This lemma states that if a subgroup is contained in another group, the quotient of their intersection by the subgroup is equal to the intersection of their respective quotients, assuming the necessary normality conditions for the quotients to be well-defined.*)\nLemma quotientGI G A : H \\subset G -> (G :&: A) / H = G / H :&: A / H.\n\n(*This lemma states that if a subgroup is contained in another group, the quotient of their intersection by the subgroup is equal to the intersection of their respective quotients, assuming the necessary normality conditions for the quotients to be well-defined.*)\nLemma quotientIG A G : H \\subset G -> (A :&: G) / H = A / H :&: G / H.\n\n(*This lemma states that the set difference of the quotients of two subgroups by a third subgroup is a subset of the quotient of the set difference of the first two subgroups.*)\nLemma quotientD A B : A / H :\\: B / H \\subset (A :\\: B) / H.\n\n(*This lemma states that the centralizer of the quotient of a subgroup is a subset of the quotient of the centralizer of the original subgroup.*)\nLemma quotientD1 A : (A / H)^# \\subset A^# / H.\n\n(*This lemma states that if a subgroup is contained within a group, the quotient of their set difference is equal to the set difference of their respective quotients.*)\nLemma quotientDG A G : H \\subset G -> (A :\\: G) / H = A / H :\\: G / H.\n\n(*This lemma states that for a subgroup contained in the normalizer of another subgroup, the preimage of its quotient under the canonical projection is the product of the two subgroups.*)\nLemma quotientK A : A \\subset 'N(H) -> coset H @*^-1 (A / H) = H * A.\n\n(*This lemma states that for a subgroup contained in the normalizer of another subgroup, the preimage of its quotient under the canonical projection is equal to the product of the two subgroups.*)\nLemma quotientYK G : G \\subset 'N(H) -> coset H @*^-1 (G / H) = H <*> G.\n\n(*This lemma states that if a subgroup is normal in a group, the preimage of the entire quotient group under the canonical projection is the original group itself.*)\nLemma quotientGK G : H <| G -> coset H @*^-1 (G / H) = G.\n\n(*This lemma states that for an element and a subgroup both contained in the normalizer of another subgroup, the image of the conjugacy class of the element under the subgroup action in the quotient group is equal to the conjugacy class of the element's coset under the action of the subgroup's quotient.*)\nLemma quotient_class x A :\n x \\in 'N(H) -> A \\subset 'N(H) -> x ^: A / H = coset H x ^: (A / H).\n\n(*This lemma states that for a subgroup within the normalizer of another, the set of conjugacy classes of the quotient group is the set of images of the conjugacy classes of the original subgroup under the quotient map.*)\nLemma classes_quotient A :\n A \\subset 'N(H) -> classes (A / H) = [set xA / H | xA in classes A].\n\n(*This lemma states that for an element in the normalizer of a subgroup, the preimage of the singleton set containing its left coset under the quotient map is its right coset.*)\nLemma cosetpre_set1 x :\n x \\in 'N(H) -> coset H @*^-1 [set coset H x] = H :* x.\n\n(*This lemma states that the preimage of a singleton set containing a coset, under the quotient map, is the coset itself, viewed as a set of group elements.*)\nLemma cosetpre_set1_coset xbar : coset H @*^-1 [set xbar] = xbar.\n\n(*This lemma states that for any subgroup of a quotient group, taking its preimage and then applying the quotient map to the result recovers the original subgroup of the quotient group.*)\nLemma cosetpreK C : coset H @*^-1 C / H = C.\n\n(*This lemma states that the quotient of any group by itself results in the trivial group.*)\nLemma trivg_quotient : H / H = 1.\n\n(*This lemma states that if a group is a subgroup of another group, its quotient by the larger group is the trivial group.*)\nLemma quotientS1 G : G \\subset H -> G / H = 1.\n\n(*This lemma states that a subgroup is always a subset of the preimage of any subgroup of its corresponding quotient group.*)\nLemma sub_cosetpre M : H \\subset coset H @*^-1 M.\n\n(*This lemma states that for two groups that both have a common normal subgroup, the quotient of the first group is a proper subgroup of the quotient of the second group if and only if the first group is a proper subgroup of the second.*)\nLemma quotient_proper G K :\n H <| G -> H <| K -> (G / H \\proper K / H) = (G \\proper K).\n\n(*This lemma states that a subgroup is always a normal subgroup of the preimage of any subgroup of the corresponding quotient group.*)\nLemma normal_cosetpre M : H <| coset H @*^-1 M.\n\n(*This lemma states that for two sets of cosets, the preimage of the first set is a subset of the preimage of the second set if and only if the first set is a subset of the second set.*)\nLemma cosetpreSK C D :\n (coset H @*^-1 C \\subset coset H @*^-1 D) = (C \\subset D).\n\n(*This lemma states that for a subgroup contained in the normalizer of another, its quotient is a subset of a given set of cosets if and only if the original subgroup is a subset of the preimage of that set of cosets.*)\nLemma sub_quotient_pre A C :\n A \\subset 'N(H) -> (A / H \\subset C) = (A \\subset coset H @*^-1 C).\n\n(*This lemma states that for a normal subgroup of a group, the preimage of a set of cosets is a subgroup of the group if and only if the set of cosets forms a subgroup of the quotient group.*)\nLemma sub_cosetpre_quo C G :\n H <| G -> (coset H @*^-1 C \\subset G) = (C \\subset G / H).\n\n(*This lemma states that for a subgroup contained in the normalizer of another, its quotient is a subgroup of the trivial group if and only if the original subgroup is contained in the subgroup used for the quotient.*)\nLemma quotient_sub1 A : A \\subset 'N(H) -> (A / H \\subset [1]) = (A \\subset H).\n\n(*This lemma states that for a subgroup contained in the normalizer of another, its quotient is contained in the quotient of a second subgroup if and only if the first subgroup is contained in the group product of the subgroup defining the quotient and the second subgroup.*)\nLemma quotientSK A B :\n A \\subset 'N(H) -> (A / H \\subset B / H) = (A \\subset H * B).\n\n(*This lemma establishes an equivalence between a quotient subgroup inclusion and an original subgroup inclusion, likely under specific normality conditions.*)\nLemma quotientSGK A G :\n A \\subset 'N(H) -> H \\subset G -> (A / H \\subset G / H) = (A \\subset G).\n\n(*This lemma states that the quotient group formation is an injective mapping on the set of groups for which a given subgroup is normal. If two groups `G1` and `G2` both contain `H` as a normal subgroup, and the quotient group `G1 / H` is equal to `G2 / H`, then `G1` and `G2` must be equal.*)\nLemma quotient_injG :\n {in [pred G : {group gT} | H <| G] &, injective (fun G => G / H)}.\n\n(*This lemma states that if two groups both contain a given subgroup as a normal subgroup, and their quotient groups with respect to this subgroup are equal, then the two original groups must be equal.*)\nLemma quotient_inj G1 G2 :\n H <| G1 -> H <| G2 -> G1 / H = G2 / H -> G1 :=: G2.\n\n(*This lemma states that for a group with a normal subgroup, the corresponding quotient group is non-trivial if and only if the normal subgroup is a proper subgroup.*)\nLemma quotient_neq1 A : H <| A -> (A / H != 1) = (H \\proper A).\n\n(*This lemma states that if a set of elements normalizes a subgroup, then the quotient of the subgroup generated by the set is equal to the subgroup generated by the set of cosets of the original elements.*)\nLemma quotient_gen A : A \\subset 'N(H) -> <> / H = <>.\n\n(*This lemma states that if a set of cosets of a normal subgroup contains the identity coset, then the preimage of the subgroup generated by this set is equal to the subgroup generated by the preimage of the set itself.*)\nLemma cosetpre_gen C :\n 1 \\in C -> coset H @*^-1 <> = <>.\n\n(*This lemma states that if two sets of elements both normalize a subgroup, then the set of cosets of their commutators is equal to the set of commutators of their respective cosets.*)\nLemma quotientR A B :\n A \\subset 'N(H) -> B \\subset 'N(H) -> [~: A, B] / H = [~: A / H, B / H].\n\n(*This lemma states that the quotient of the normalizer of a set by a normal subgroup is a subset of the normalizer of the set of cosets of that set.*)\nLemma quotient_norm A : 'N(A) / H \\subset 'N(A / H).\n\n(*This lemma states that if a group normalizes another group, then the quotient of the first group also normalizes the quotient of the second group.*)\nLemma quotient_norms A B : A \\subset 'N(B) -> A / H \\subset 'N(B / H).\n\n(*This lemma states that the quotient of the normalizer of a group `B` within a group `A` by a normal subgroup `H` is a subset of the normalizer of the quotient group `B / H` within the quotient group `A / H`.*)\nLemma quotient_subnorm A B : 'N_A(B) / H \\subset 'N_(A / H)(B / H).\n\n(*This lemma states that the property of a subgroup being normal is preserved under quotients. If a group `A` is a normal subgroup of a group `B`, then the quotient group `A / H` is a normal subgroup of the quotient group `B / H`.*)\nLemma quotient_normal A B : A <| B -> A / H <| B / H.\n\n(*This lemma states that the quotient of the centralizer of an element by a normal subgroup is a subset of the centralizer of the coset of that element.*)\nLemma quotient_cent1 x : 'C[x] / H \\subset 'C[coset H x].\n\n(*This lemma states that if every element of a group commutes with a given element, then every element of the corresponding quotient group commutes with the coset of that element.*)\nLemma quotient_cent1s A x : A \\subset 'C[x] -> A / H \\subset 'C[coset H x].\n\n(*This lemma states that the quotient of the centralizer of an element within a group `A` by a normal subgroup `H` is a subset of the centralizer of the coset of that element within the quotient group `A / H`.*)\nLemma quotient_subcent1 A x : 'C_A[x] / H \\subset 'C_(A / H)[coset H x].\n\n(*This lemma states that the quotient of the centralizer of a set by a normal subgroup is a subset of the centralizer of the set of cosets.*)\nLemma quotient_cent A : 'C(A) / H \\subset 'C(A / H).\n\n(*This lemma states that if a group `A` centralizes a group `B`, meaning every element of `A` commutes with every element of `B`, then the quotient group `A / H` centralizes the quotient group `B / H`.*)\nLemma quotient_cents A B : A \\subset 'C(B) -> A / H \\subset 'C(B / H).\n\n(*This lemma states that any quotient of an abelian group is also an abelian group.*)\nLemma quotient_abelian A : abelian A -> abelian (A / H).\n\n(*This lemma states that the quotient of the centralizer of a group `B` within a group `A` by a normal subgroup `H` is a subset of the centralizer of the quotient group `B / H` within the quotient group `A / H`.*)\nLemma quotient_subcent A B : 'C_A(B) / H \\subset 'C_(A / H)(B / H).\n\n(*This lemma states that if a group `A` normalizes a subgroup `H`, and the quotient group `A / H` normalizes a set of cosets `C`, then `A` must normalize the preimage of `C` under the quotient map.*)\nLemma norm_quotient_pre A C :\n A \\subset 'N(H) -> A / H \\subset 'N(C) -> A \\subset 'N(coset H @*^-1 C).\n\n(*This lemma states that the property of a subgroup being normal is preserved and reflected by the preimage operation of the quotient map. The preimage of a set of cosets `C` is a normal subgroup of the preimage of a set of cosets `D` if and only if `C` is a normal subgroup of `D`.*)\nLemma cosetpre_normal C D : (coset H @*^-1 C <| coset H @*^-1 D) = (C <| D).\n\n(*This lemma states that if `H` is a normal subgroup of a group `G`, then the quotient of the normalizer of `G` by `H` is equal to the normalizer of the quotient group `G / H`.*)\nLemma quotient_normG G : H <| G -> 'N(G) / H = 'N(G / H).\n\n(*This lemma states that if `H` is a normal subgroup of a group `G`, then the quotient of the normalizer of `G` within another group `A` by `H` is equal to the normalizer of the quotient group `G / H` within the quotient group `A / H`.*)\nLemma quotient_subnormG A G : H <| G -> 'N_A(G) / H = 'N_(A / H)(G / H).\n\n(*This lemma states that the centralizer of an element within the normalizer of a subgroup `H` is a subset of the preimage of the centralizer of the coset of that element.*)\nLemma cosetpre_cent1 x : 'C_('N(H))[x] \\subset coset H @*^-1 'C[coset H x].\n\n(*This lemma states that if the preimage of a set of cosets is contained in the centralizer of an element, then the set of cosets is contained in the centralizer of the coset of that element.*)\nLemma cosetpre_cent1s C x :\n coset H @*^-1 C \\subset 'C[x] -> C \\subset 'C[coset H x].\n\n(*This lemma states that the centralizer of an element within the preimage of a set of cosets `C` is a subset of the preimage of the centralizer of the coset of the element within `C`.*)\nLemma cosetpre_subcent1 C x :\n 'C_(coset H @*^-1 C)[x] \\subset coset H @*^-1 'C_C[coset H x].\n\n(*This lemma states that the centralizer of a group `A` within the normalizer of a subgroup `H` is a subset of the preimage of the centralizer of the quotient group `A / H`.*)\nLemma cosetpre_cent A : 'C_('N(H))(A) \\subset coset H @*^-1 'C(A / H).\n\n(*This lemma states that if the preimage of a set of cosets is contained in the centralizer of a group `A`, then the set of cosets is contained in the centralizer of the quotient group `A / H`.*)\nLemma cosetpre_cents A C : coset H @*^-1 C \\subset 'C(A) -> C \\subset 'C(A / H).\n\n(*This lemma states that the centralizer of a group `A` within the preimage of a set of cosets `C` is a subset of the preimage of the centralizer of the quotient group `A / H` within `C`.*)\nLemma cosetpre_subcent C A :\n 'C_(coset H @*^-1 C)(A) \\subset coset H @*^-1 'C_C(A / H).\n\n(*This lemma states that for a subgroup `A` of a group `G` that normalizes `H`, applying the canonical quotient map from `G` to `G / H` to the subgroup `A` yields the set of cosets `A / H`.*)\nLemma restrm_quotientE G A (nHG : G \\subset 'N(H)) :\n A \\subset G -> restrm nHG (coset H) @* A = A / H.\n\nSection InverseImage.\n\nVariables (G : {group gT}) (Kbar : {group coset_of H}).\n\nHypothesis nHG : H <| G.\n\n(*This definition describes a specification for the existence of a subgroup that corresponds to a given group of cosets. It holds if there is a subgroup `K` satisfying a given predicate such that `K` contains the normal subgroup `H` and the quotient group `K / H` is equal to the group of cosets.*)\nVariant inv_quotient_spec (P : pred {group gT}) : Prop :=\n InvQuotientSpec K of Kbar :=: K / H & H \\subset K & P K.\n\n(*This lemma provides a practical characterization for the existence of a subgroup whose quotient is a given group of cosets. It establishes that such a subgroup satisfying a predicate exists if and only if the preimage of the group of cosets under the quotient map satisfies the predicate, assuming the group of cosets is a well-formed subgroup.*)\nLemma inv_quotientS :\n Kbar \\subset G / H -> inv_quotient_spec (fun K => K \\subset G).\n\n(*This lemma states that if a set of cosets forms a normal subgroup of a quotient group, then the union of these cosets also forms a normal subgroup within the original ambient group.*)\nLemma inv_quotientN : Kbar <| G / H -> inv_quotient_spec (fun K => K <| G).\n\nEnd InverseImage.\n\n(*This lemma states that the set of right cosets formed by the product of a set and a subgroup, with respect to that subgroup, is equal to the set of right cosets formed by the original set and subgroup.*)\nLemma quotientMidr A : A * H / H = A / H.\n\n(*This lemma states that the set of right cosets formed by the product of a subgroup and a set, with respect to that subgroup, is equal to the set of right cosets formed by the original set and subgroup.*)\nLemma quotientMidl A : H * A / H = A / H.\n\n(*This lemma states that if a group is contained in the normalizer of a subgroup, then the set of cosets of their group product with respect to that subgroup is the same as the set of cosets with representatives from the first group.*)\nLemma quotientYidr G : G \\subset 'N(H) -> G <*> H / H = G / H.\n\n(*This lemma states that if a group is contained in the normalizer of a subgroup, then the set of cosets of their group product, taken in reverse order, with respect to that subgroup is the same as the set of cosets with representatives from the first group.*)\nLemma quotientYidl G : G \\subset 'N(H) -> H <*> G / H = G / H.\n\nSection Injective.\n\nVariables (G : {group gT}).\nHypotheses (nHG : G \\subset 'N(H)) (tiHG : H :&: G = 1).\n\n(*This lemma states that if a group is a subgroup of the normalizer of another group and their intersection is trivial, then the first group is isomorphic to the set of right cosets of the second group with representatives from the first, via the canonical coset map.*)\nLemma quotient_isom : isom G (G / H) (restrm nHG (coset H)).\n\n(*This lemma states that if a group is a subgroup of the normalizer of another group and their intersection is trivial, then the first group and the set of right cosets of the second group with representatives from the first are isomorphic as groups.*)\nLemma quotient_isog : isog G (G / H).\n\nEnd Injective.\n\nEnd CosetOfGroupTheory.\n\n(*This notation represents the set of right cosets of a subgroup where the representatives are chosen from a given set.*)\nNotation \"A / H\" := (quotient_group A H) : Group_scope.\n\nSection Quotient1.\n\nVariables (gT : finGroupType) (A : {set gT}).\n\n(*This lemma states that the function mapping a group element to its coset with respect to the trivial subgroup is an injective morphism.*)\nLemma coset1_injm : 'injm (@coset gT 1).\n\n(*This lemma states that a set of group elements is isomorphic to the set of its cosets with respect to the trivial subgroup, with the isomorphism given by the canonical coset map.*)\nLemma quotient1_isom : isom A (A / 1) (coset 1).\n\n(*This lemma states that any group is isomorphic to its quotient by the trivial subgroup.*)\nLemma quotient1_isog : isog A (A / 1).\n\nEnd Quotient1.\n\nSection QuotientMorphism.\n\nVariable (gT rT : finGroupType) (G H : {group gT}) (f : {morphism G >-> rT}).\n\nImplicit Types A : {set gT}.\nImplicit Types B : {set (coset_of H)}.\nHypotheses (nsHG : H <| G).\n(*This definition establishes that a subgroup `H` is a subset of group `G`, a fact derived from `H` being a normal subgroup of `G`.*)\nLet sHG : H \\subset G := normal_sub nsHG.\n(*This definition establishes that a group `G` is a subset of the normalizer of its subgroup `H`, a fact derived from `H` being a normal subgroup of `G`.*)\nLet nHG : G \\subset 'N(H) := normal_norm nsHG.\n(*This definition establishes that the image of a group `G` under a group morphism is a subset of the normalizer of the image of a normal subgroup `H` of `G` under the same morphism.*)\nLet nfHfG : f @* G \\subset 'N(f @* H) := morphim_norms f nHG.\n\n(*This notation defines a composite function that first applies a group morphism and then maps the result to its coset with respect to the image of a subgroup.*)\nNotation fH := (coset (f @* H) \\o f).\n\n(*This lemma states that the group `G` is included in the domain of the composite morphism that applies a group morphism `f` and then quotients by the image of a subgroup `H`.*)\nLemma quotm_dom_proof : G \\subset 'dom fH.\n\n(*This notation defines a function that results from restricting the domain of a composite quotient morphism to a specific group.*)\nNotation fH_G := (restrm quotm_dom_proof fH).\n\n(*This lemma states that the kernel of the canonical quotient map by a normal subgroup `H` is a subset of the kernel of the composite morphism that applies `f` and then quotients by the image of `H`.*)\nLemma quotm_ker_proof : 'ker (coset H) \\subset 'ker fH_G.\n\n(*This definition constructs the canonical morphism from a quotient group G by H to another quotient group, as induced by a given group morphism `f` according to the universal property of quotient groups.*)\nDefinition quotm := factm quotm_ker_proof nHG.\n\nCanonical quotm_morphism := [morphism G / H of quotm].\n\n(*This lemma states that applying the induced quotient morphism to a coset yields the coset of the image of the representative, with respect to the image of the original subgroup.*)\nLemma quotmE x : x \\in G -> quotm (coset H x) = coset (f @* H) (f x).\n\n(*This lemma states that the image of a set of cosets under the induced quotient morphism is equal to the set of cosets formed from the image of the original representative set and the image of the subgroup under the original morphism.*)\nLemma morphim_quotm A : quotm @* (A / H) = f @* A / f @* H.\n\n(*This lemma states that the preimage of a set of cosets under the induced quotient morphism is the set of cosets with respect to the original subgroup whose representatives are from the preimage of the new representative set.*)\nLemma morphpre_quotm Abar : quotm @*^-1 (Abar / f @* H) = f @*^-1 Abar / H.\n\n(*This lemma states that the kernel of the induced quotient morphism consists of the cosets of the original subgroup whose representatives belong to the kernel of the original morphism.*)\nLemma ker_quotm : 'ker quotm = 'ker f / H.\n\n(*This lemma states that if a group morphism is injective, then the induced quotient morphism derived from it is also injective.*)\nLemma injm_quotm : 'injm f -> 'injm quotm.\n\nEnd QuotientMorphism.\n\nSection EqIso.\n\nVariables (gT : finGroupType) (G H : {group gT}).\n\nHypothesis (eqGH : G :=: H).\n\n(*This lemma states that if two groups `G` and `H` are equal as sets, then the normalizer of `H` is a subgroup of the normalizer of `G`.*)\nLemma im_qisom_proof : 'N(H) \\subset 'N(G). \n(*This lemma states that if two groups `G` and `H` are equal as sets, then the kernel of the quotient map by `G` is a subset of the kernel of the quotient map by `H`.*)\nLemma qisom_ker_proof : 'ker (coset G) \\subset 'ker (coset H).\n\n(*This lemma provides a technical proof required to define the `qisom` isomorphism by establishing a necessary inclusion relationship between sets of cosets.*)\nLemma qisom_restr_proof : setT \\subset 'N(H) / G.\n\n(*This definition constructs the canonical isomorphism between the quotient of a group by a subgroup `G` and the quotient of the same group by a subgroup `H`, under the condition that `G` and `H` are equal as sets.*)\nDefinition qisom :=\n restrm qisom_restr_proof (factm qisom_ker_proof im_qisom_proof).\n\nCanonical qisom_morphism := Eval hnf in [morphism of qisom].\n\n(*This lemma states that applying the canonical quotient isomorphism to a coset with respect to group `G` yields the corresponding coset with respect to the equal group `H` for the same representative element.*)\nLemma qisomE x : qisom (coset G x) = coset H x.\n\n(*This lemma states that the canonical representative of a coset remains unchanged after being mapped by the canonical quotient isomorphism `qisom`.*)\nLemma val_qisom Gx : val (qisom Gx) = val Gx.\n\n(*This lemma states that a specific group isomorphism, when applied to a coset defined by a set and a group `G`, yields the coset defined by the same set and an equivalent group `H`.*)\nLemma morphim_qisom A : qisom @* (A / G) = A / H.\n\n(*This lemma states that the preimage of a coset defined by a set and a group `H` under a specific group isomorphism is the coset defined by the same set and an equivalent group `G`.*)\nLemma morphpre_qisom A : qisom @*^-1 (A / H) = A / G.\n\n(*This lemma states that the group morphism `qisom` is injective.*)\nLemma injm_qisom : 'injm qisom.\n\n(*This lemma states that the image of the domain under the group morphism `qisom` is the entire codomain.*)\nLemma im_qisom : qisom @* setT = setT.\n\n(*This lemma states that `qisom` is a group isomorphism between its domain and codomain.*)\nLemma qisom_isom : isom setT setT qisom.\n\n(*This lemma states that the quotient group formed by the cosets of a group `G` is isomorphic to the quotient group formed by the cosets of an equivalent group `H`.*)\nLemma qisom_isog : [set: coset_of G] \\isog [set: coset_of H].\n\n(*This lemma states that the function underlying the group morphism `qisom` is injective.*)\nLemma qisom_inj : injective qisom.\n\n(*This lemma states that the function mapping a coset of a group `G` to its image under the `qisom` isomorphism is injective.*)\nLemma morphim_qisom_inj : injective (fun Gx => qisom @* Gx).\n\nEnd EqIso.\n\nArguments qisom_inj {gT G H} eqGH [x1 x2].\nArguments morphim_qisom_inj {gT G H} eqGH [x1 x2].\n\nSection FirstIsomorphism.\n\nVariables aT rT : finGroupType.\n\n(*This theorem, known as the first isomorphism theorem for groups, states that for any group homomorphism `f` defined on a group `G`, there exists an injective homomorphism `g` from the quotient group of `G` by the kernel of `f` to the codomain of `f`. Furthermore, applying `g` to a coset is equivalent to applying `f` to the set representative of that coset.*)\nLemma first_isom (G : {group aT}) (f : {morphism G >-> rT}) :\n {g : {morphism G / 'ker f >-> rT} | 'injm g &\n forall A : {set aT}, g @* (A / 'ker f) = f @* A}.\n\nVariables (G H : {group aT}) (f : {morphism G >-> rT}).\nHypothesis sHG : H \\subset G.\n\n(*This lemma states that the quotient group of a group `G` by the kernel of a homomorphism `f` is isomorphic to the image of `G` under `f`.*)\nLemma first_isog : (G / 'ker f) \\isog (f @* G).\n\n(*This lemma, a localized version of the first isomorphism theorem, states that for a homomorphism `f` and a subgroup `H` of its domain, there exists an injective homomorphism from the quotient group of `H` by its intersection with the kernel of `f`. This new homomorphism, when applied to a coset within `H`, yields the same result as applying `f` to the set representative of that coset.*)\nLemma first_isom_loc : {g : {morphism H / 'ker_H f >-> rT} |\n 'injm g & forall A : {set aT}, A \\subset H -> g @* (A / 'ker_H f) = f @* A}.\n\n(*This lemma, a localized version of the first isomorphism theorem, states that for a subgroup `H` in the domain of a homomorphism `f`, the quotient of `H` by the kernel of `f` restricted to `H` is isomorphic to the image of `H` under `f`.*)\nLemma first_isog_loc : (H / 'ker_H f) \\isog (f @* H).\n\nEnd FirstIsomorphism.\n\nSection SecondIsomorphism.\n\nVariables (gT : finGroupType) (H K : {group gT}).\n\nHypothesis nKH : H \\subset 'N(K).\n\n(*This theorem, known as the second isomorphism theorem for groups, states that for a subgroup `H` and a group `K`, where `H` is contained in the normalizer of `K`, there exists an injective homomorphism from the quotient group of `H` by the intersection of `K` and `H` to the group of cosets of `K`. This homomorphism maps a coset defined by a set `A` to the coset of `K` with respect to `A`.*)\nLemma second_isom : {f : {morphism H / (K :&: H) >-> coset_of K} |\n 'injm f & forall A : {set gT}, A \\subset H -> f @* (A / (K :&: H)) = A / K}.\n\n(*This lemma, a statement of the second isomorphism theorem, asserts that if a subgroup `H` is contained in the normalizer of a group `K`, then the quotient group of `H` by its intersection with `K` is isomorphic to the group formed by the cosets of `K` with representatives from `H`.*)\nLemma second_isog : H / (K :&: H) \\isog H / K.\n\n(*This lemma provides a variant of the second isomorphism theorem, stating that the quotient group of a subgroup `H` by its intersection with a group `K` is isomorphic to the quotient group of the product group `HK` by `K`, assuming `H` is a subset of the normalizer of `K`.*)\nLemma weak_second_isog : H / (K :&: H) \\isog H * K / K.\n\nEnd SecondIsomorphism.\n\nSection ThirdIsomorphism.\n\nVariables (gT : finGroupType) (G H K : {group gT}).\n\n(*This lemma states that if a set `A` normalizes two groups `H` and `K`, and `H` is a subgroup of `K`, then there exists a group homomorphism from the group of cosets of `K` with representatives in `A` to the group of cosets of `H` with representatives in `A`.*)\nLemma homg_quotientS (A : {set gT}) :\n A \\subset 'N(H) -> A \\subset 'N(K) -> H \\subset K -> A / K \\homg A / H.\n\nHypothesis sHK : H \\subset K.\nHypothesis snHG : H <| G.\nHypothesis snKG : K <| G.\n\n(*This theorem, known as the third isomorphism theorem for groups, states that for two normal subgroups `H` and `K` of a group `G` where `H` is a subgroup of `K`, there exists an injective homomorphism from the quotient group `(G/H)/(K/H)` to the group of cosets of `K`. This homomorphism maps a nested coset to the corresponding single coset of `K`.*)\nTheorem third_isom : {f : {morphism (G / H) / (K / H) >-> coset_of K} | 'injm f\n & forall A : {set gT}, A \\subset G -> f @* (A / H / (K / H)) = A / K}.\n\n(*This theorem, a statement of the third isomorphism theorem for groups, asserts that if `H` and `K` are normal subgroups of a group `G` with `H` contained in `K`, then the quotient group of `G/H` by `K/H` is isomorphic to the quotient group `G/K`.*)\nTheorem third_isog : (G / H / (K / H)) \\isog (G / K).\n\nEnd ThirdIsomorphism.\n\n(*This lemma provides a condition for proving a subgroup `K` is characteristic in a group `G`. It states that if a subgroup `H` is normal in `K`, `H` is characteristic in `G`, and the quotient group `K/H` is characteristic in the quotient group `G/H`, then `K` is a characteristic subgroup of `G`.*)\nLemma char_from_quotient (gT : finGroupType) (G H K : {group gT}) :\n H <| K -> H \\char G -> K / H \\char G / H -> K \\char G.\n\nSection CardMorphism.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\nImplicit Types G H : {group aT}.\nImplicit Types L M : {group rT}.\n\n(*This lemma states that for a group homomorphism `f`, the cardinality of the image of a group `G` under `f` is equal to the index of the kernel of `f` within the intersection of `G` and the domain of `f`.*)\nLemma card_morphim G : #|f @* G| = #|D :&: G : 'ker f|.\n\n(*This lemma, a consequence of Lagrange's theorem, states that for any group homomorphism `f`, the cardinality of the image of a group `G` under `f` divides the cardinality of `G`.*)\nLemma dvdn_morphim G : #|f @* G| %| #|G|.\n\n(*This lemma states that for any group homomorphism `f`, prime number `p`, and group `G`, the exponent of `p` in the prime factorization of the cardinality of the image of `G` is less than or equal to the exponent of `p` in the prime factorization of the cardinality of `G`.*)\nLemma logn_morphim p G : logn p #|f @* G| <= logn p #|G|.\n\n(*This lemma states that if the cardinality of a group `G` is coprime to a natural number, then the cardinality of the image of `G` under any homomorphism is also coprime to that number.*)\nLemma coprime_morphl G p : coprime #|G| p -> coprime #|f @* G| p.\n\n(*This lemma states that if a natural number is coprime to the cardinality of a group `G`, then it is also coprime to the cardinality of the image of `G` under any homomorphism.*)\nLemma coprime_morphr G p : coprime p #|G| -> coprime p #|f @* G|.\n\n(*This lemma states that for a group homomorphism `f`, if the cardinalities of two groups `G` and `H` are coprime, then the cardinalities of their images under `f` are also coprime.*)\nLemma coprime_morph G H : coprime #|G| #|H| -> coprime #|f @* G| #|f @* H|.\n\n(*This lemma provides a formula stating that the index of a subgroup `H` in a group `G` is the product of the index of their images under a homomorphism `f` and the index related to the kernel of `f`.*)\nLemma index_morphim_ker G H :\n H \\subset G -> G \\subset D ->\n (#|f @* G : f @* H| * #|'ker_G f : H|)%N = #|G : H|.\n\n(*This lemma states that for a group homomorphism `f`, the index of the image of a subgroup `H` within the image of a group `G` divides the index of `H` within `G`, provided the intersection of `G` and `H` is contained in the domain of `f`.*)\nLemma index_morphim G H : G :&: H \\subset D -> #|f @* G : f @* H| %| #|G : H|.\n\n(*This lemma states that an injective group homomorphism preserves the index of subgroups. Specifically, if `H` is a subgroup of `G` and both are in the domain of an injective homomorphism `f`, then the index of the image of `H` in the image of `G` is equal to the index of `H` in `G`.*)\nLemma index_injm G H : 'injm f -> G \\subset D -> #|f @* G : f @* H| = #|G : H|.\n\n(*This lemma provides the cardinality of the preimage of a set `L` under a group homomorphism `f`. It states that if `L` is a subset of the image of `f`, then the cardinality of its preimage is the product of the cardinality of the kernel of `f` and the cardinality of `L`.*)\nLemma card_morphpre L : L \\subset f @* D -> #|f @*^-1 L| = (#|'ker f| * #|L|)%N.\n\n(*This lemma relates the index of two groups in the codomain of a homomorphism to the index of their preimages in the domain.*)\nLemma index_morphpre L M :\n L \\subset f @* D -> #|f @*^-1 L : f @*^-1 M| = #|L : M|.\n\nEnd CardMorphism.\n\n(*This lemma asserts that if there exists an injective group homomorphism from a first finite group to a second finite group, then the cardinality of the first group divides the cardinality of the second group.*)\nLemma card_homg (aT rT : finGroupType) (G : {group aT}) (R : {group rT}) :\n G \\homg R -> #|G| %| #|R|.\n\nSection CardCosetpre.\n\nVariables (gT : finGroupType) (G H K : {group gT}) (L M : {group coset_of H}).\n\n(*This lemma states that for any finite group and one of its normal subgroups, the cardinality of the resulting quotient group divides the cardinality of the original group.*)\nLemma dvdn_quotient : #|G / H| %| #|G|.\n\n(*This lemma provides a formula relating group indices. For a finite group with a given subgroup and a normal subgroup, it states that the index of the given subgroup is equal to the product of two other indices: the first computed between their corresponding quotient groups, and the second computed between their intersection and the normal subgroup.*)\nLemma index_quotient_ker :\n K \\subset G -> G \\subset 'N(H) ->\n (#|G / H : K / H| * #|G :&: H : K|)%N = #|G : K|.\n\n(*This lemma establishes a divisibility property between generalized group indices. It states that if the intersection of two finite groups normalizes a third group, then the generalized index involving their sets of cosets divides the generalized index of the two groups themselves.*)\nLemma index_quotient : G :&: K \\subset 'N(H) -> #|G / H : K / H| %| #|G : K|.\n\n(*This lemma states an equality of indices involving quotient groups. It asserts that if a subgroup K of a finite group G also contains a normal subgroup H of G, then the index of the quotient group K divided by H within the quotient group G divided by H is equal to the index of K in G.*)\nLemma index_quotient_eq :\n G :&: H \\subset K -> K \\subset G -> G \\subset 'N(H) ->\n #|G / H : K / H| = #|G : K|.\n\n(*This lemma calculates the cardinality of a preimage under the canonical coset map. It states that the number of group elements that map to a given set of cosets of a subgroup is equal to the product of the cardinality of the subgroup and the number of cosets in the set.*)\nLemma card_cosetpre : #|coset H @*^-1 L| = (#|H| * #|L|)%N.\n\n(*This lemma relates the index of preimages under the canonical coset map to the index of the original groups of cosets. It asserts that for two groups of cosets where one is a subgroup of the other, the index of their preimages under the coset map is equal to the index of the subgroup within the larger group of cosets.*)\nLemma index_cosetpre : #|coset H @*^-1 L : coset H @*^-1 M| = #|L : M|.", - "fingroup.morphism": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype finfun bigop finset fingroup.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nReserved Notation \"x \\isog y\" (at level 70).\n\nSection MorphismStructure.\n\nVariables aT rT : finGroupType.\n\n(*This structure defines a group morphism by bundling together a function and a proof that this function preserves the group operation on a specified domain, which is a subset of the source group.*)\nStructure morphism (D : {set aT}) : Type := Morphism {\n(**)\n mfun :> aT -> FinGroup.sort rT;\n _ : {in D &, {morph mfun : x y / x * y}}\n}.\n\n(*This definition provides a convenient way to specify the type of a group morphism from a given domain to a target group, using a phantom type to hold the target group information.*)\nDefinition morphism_for D of phant rT := morphism D.\n\n(*This definition provides a mechanism to reconstruct a group morphism object, which is a technical tool used for adapting the morphism's type representation without changing its underlying function or properties.*)\nDefinition clone_morphism D f :=\n let: Morphism _ fM := f\n return {type of @Morphism D for f} -> morphism_for D (Phant rT)\n in fun k => k fM.\n\nVariables (D A : {set aT}) (R : {set rT}) (x : aT) (y : rT) (f : aT -> rT).\n\n(**)\nVariant morphim_spec : Prop := MorphimSpec z & z \\in D & z \\in A & y = f z.\n\n(*This lemma states that an element belongs to the image of the intersection of a morphism's domain and another set if and only if there exists an element in that intersection that maps to the given element.*)\nLemma morphimP : reflect morphim_spec (y \\in f @: (D :&: A)).\n\n(*This lemma states that an element belongs to the intersection of a morphism's domain and the preimage of a set if and only if the element is in the domain and its image is in the target set.*)\nLemma morphpreP : reflect (x \\in D /\\ f x \\in R) (x \\in D :&: f @^-1: R).\n\nEnd MorphismStructure.\n\n(*This notation specifies the type of group morphisms from a domain, which is a subset of the source group, to a target group.*)\nNotation \"{ 'morphism' D >-> T }\" := (morphism_for D (Phant T))\n (format \"{ 'morphism' D >-> T }\") : type_scope.\n(*This notation constructs a group morphism from a given function and a specified domain, implicitly requiring a proof that the function preserves the group operation on that domain.*)\nNotation \"[ 'morphism' D 'of' f ]\" :=\n (@clone_morphism _ _ D _ (fun fM => @Morphism _ _ D f fM))\n (format \"[ 'morphism' D 'of' f ]\") : form_scope.\n(*This notation constructs a group morphism from a given function, where the domain is inferred to be the entire source group, and requires an implicit proof that the function preserves the group operation.*)\nNotation \"[ 'morphism' 'of' f ]\" := (clone_morphism (@Morphism _ _ _ f))\n (format \"[ 'morphism' 'of' f ]\") : form_scope.\n\nArguments morphimP {aT rT D A y f}.\nArguments morphpreP {aT rT D R x f}.\n\nSection MorphismOps1.\n\nVariables (aT rT : finGroupType) (D : {set aT}) (f : {morphism D >-> rT}).\n\n(*This lemma states that the underlying function of a group morphism preserves the group's multiplication operation for all elements within its specified domain.*)\nLemma morphM : {in D &, {morph f : x y / x * y}}.\n\n(*This notation is a technical definition for a phantom type that wraps a function type, used internally to define generic operations on morphisms.*)\nNotation morPhantom := (phantom (aT -> rT)).\n(*This definition creates a phantom-typed wrapper for a function, enabling the definition of generic operations such as domain and kernel that can be applied to any function that has an associated morphism structure.*)\nDefinition MorPhantom := Phantom (aT -> rT).\n\n(*This definition specifies the domain of a group morphism, which is the subset of the source group on which the morphism is guaranteed to preserve the group operation.*)\nDefinition dom of morPhantom f := D.\n\n(*This definition computes the image of a given set under a group morphism, which consists of all images of elements that are present in both the morphism's domain and the given set.*)\nDefinition morphim of morPhantom f := fun A => f @: (D :&: A).\n\n(*This definition computes the preimage of a given set under a group morphism, which includes all elements from the morphism's domain whose images fall into the given set.*)\nDefinition morphpre of morPhantom f := fun R : {set rT} => D :&: f @^-1: R.\n\n(*This definition specifies the kernel of a group morphism as the set of all elements in its domain that map to the identity element of the target group.*)\nDefinition ker mph := morphpre mph 1.\n\nEnd MorphismOps1.\n\nArguments morphim _ _ _%_g _ _ _%_g.\nArguments morphpre _ _ _%_g _ _ _%_g.\n\n(*This notation provides a shorthand for retrieving the domain of a group morphism, which is the subset of the source group where the morphism property holds.*)\nNotation \"''dom' f\" := (dom (MorPhantom f))\n (at level 10, f at level 8, format \"''dom' f\") : group_scope.\n\n(*This notation provides a shorthand for retrieving the kernel of a group morphism, containing all elements in its domain that map to the identity.*)\nNotation \"''ker' f\" := (ker (MorPhantom f))\n (at level 10, f at level 8, format \"''ker' f\") : group_scope.\n\n(*This notation designates the intersection of a given set with the kernel of a group morphism.*)\nNotation \"''ker_' H f\" := (H :&: 'ker f)\n (at level 10, H at level 2, f at level 8, format \"''ker_' H f\")\n : group_scope.\n\n(*This notation represents the image of a set under a group morphism, considering only the elements of the set that also belong to the morphism's domain.*)\nNotation \"f @* A\" := (morphim (MorPhantom f) A)\n (at level 24, format \"f @* A\") : group_scope.\n\n(*This notation represents the preimage of a set under a group morphism, restricting the result to elements within the morphism's domain.*)\nNotation \"f @*^-1 R\" := (morphpre (MorPhantom f) R)\n (at level 24, format \"f @*^-1 R\") : group_scope.\n\n(*This notation expresses the proposition that a group morphism is injective, which is defined as its kernel being a subset of the singleton set containing the identity element.*)\nNotation \"''injm' f\" := (pred_of_set ('ker f) \\subset pred_of_set 1)\n (at level 10, f at level 8, format \"''injm' f\") : group_scope.\n\nSection MorphismTheory.\n\nVariables aT rT : finGroupType.\nImplicit Types A B : {set aT}.\nImplicit Types G H : {group aT}.\nImplicit Types R S : {set rT}.\nImplicit Types M : {group rT}.\n\nVariables (D : {group aT}) (f : {morphism D >-> rT}).\n\n(*This lemma states that any group morphism maps the identity element of the source group to the identity element of the target group.*)\nLemma morph1 : f 1 = 1.\n\n(*This lemma states that a group morphism preserves finite products, meaning the image of a product of elements from the domain is equal to the product of their individual images.*)\nLemma morph_prod I r (P : pred I) F :\n (forall i, P i -> F i \\in D) ->\n f (\\prod_(i <- r | P i) F i) = \\prod_( i <- r | P i) f (F i).\n\n(*This lemma states that a group morphism preserves the inverse operation, meaning the image of the inverse of an element from the domain is equal to the inverse of its image.*)\nLemma morphV : {in D, {morph f : x / x^-1}}.\n\n(*This lemma states that a group morphism preserves the conjugation operation, meaning the image of one element conjugated by another is equal to the image of the first element conjugated by the image of the second, provided both elements are in the domain.*)\nLemma morphJ : {in D &, {morph f : x y / x ^ y}}.\n\n(*This lemma states that a group morphism preserves integer exponentiation, meaning the image of an element raised to an integer power is equal to the image of the element raised to the same power, provided the base is in the domain.*)\nLemma morphX n : {in D, {morph f : x / x ^+ n}}.\n\n(*This lemma states that a group morphism preserves the commutator operation, meaning the image of the commutator of two elements from the domain is equal to the commutator of their images.*)\nLemma morphR : {in D &, {morph f : x y / [~ x, y]}}.\n\n(*This lemma provides an explicit definition for the morphism image notation, stating that the image of a set under a morphism is equivalent to the function's image of the intersection of the morphism's domain and the given set.*)\nLemma morphimE A : f @* A = f @: (D :&: A). \n(*This lemma states that the preimage of a set under an order morphism is equal to the intersection of the morphism's domain with the standard functional preimage of that set.*)\nLemma morphpreE R : f @*^-1 R = D :&: f @^-1: R. \n(*This lemma defines the kernel of a morphism as the preimage of the singleton set containing the identity element of the codomain.*)\nLemma kerE : 'ker f = f @*^-1 1. \n\n(*This lemma states that for any set that is a subset of the morphism's domain, its image under the order morphism is identical to its image under the underlying function.*)\nLemma morphimEsub A : A \\subset D -> f @* A = f @: A.\n\n(*This lemma states that the image of the entire domain of an order morphism is equal to the image of the domain under the underlying function.*)\nLemma morphimEdom : f @* D = f @: D.\n\n(*This lemma states that the image of the intersection of the morphism's domain with a set is equal to the morphism's image of that set.*)\nLemma morphimIdom A : f @* (D :&: A) = f @* A.\n\n(*This lemma states that the intersection of the morphism's domain with the preimage of a set is equal to the preimage itself, indicating that the preimage is always a subset of the domain.*)\nLemma morphpreIdom R : D :&: f @*^-1 R = f @*^-1 R.\n\n(*This lemma states that the preimage of a set is equivalent to the preimage of the intersection of that set with the image of the morphism's domain.*)\nLemma morphpreIim R : f @*^-1 (f @* D :&: R) = f @*^-1 R.\n\n(*This lemma states that the intersection of the image of the morphism's domain with the image of a set is equal to the image of the set itself, implying the image of the set is a subset of the image of the domain.*)\nLemma morphimIim A : f @* D :&: f @* A = f @* A.\n\n(*This lemma provides the condition for an element to be in the image of a set under a morphism: if an element is in the morphism's domain and belongs to a given set, then its image under the morphism is in the image of that set.*)\nLemma mem_morphim A x : x \\in D -> x \\in A -> f x \\in f @* A.\n\n(*This lemma provides the condition for an element to be in the preimage of a set under a morphism: if an element is in the morphism's domain and its image is in a given set, then the element belongs to the preimage of that set.*)\nLemma mem_morphpre R x : x \\in D -> f x \\in R -> x \\in f @*^-1 R.\n\n(*This lemma states that the image function of a morphism is monotonic with respect to set inclusion; that is, the image of a subset is a subset of the image of the superset.*)\nLemma morphimS A B : A \\subset B -> f @* A \\subset f @* B.\n\n(*This lemma states that the image of any set under an order morphism is a subset of the image of the morphism's entire domain.*)\nLemma morphim_sub A : f @* A \\subset f @* D.\n\n(*This lemma states that the cardinality of the image of a set under a morphism is less than or equal to the cardinality of the original set.*)\nLemma leq_morphim A : #|f @* A| <= #|A|.\n\n(*This lemma states that the preimage function of a morphism is monotonic with respect to set inclusion; that is, the preimage of a subset is a subset of the preimage of the superset.*)\nLemma morphpreS R S : R \\subset S -> f @*^-1 R \\subset f @*^-1 S.\n\n(*This lemma states that the preimage of any set under an order morphism is a subset of the morphism's domain.*)\nLemma morphpre_sub R : f @*^-1 R \\subset D.\n\n(*This lemma states that the image of the intersection of a set with the preimage of another set is equal to the intersection of the image of the first set with the second set.*)\nLemma morphim_setIpre A R : f @* (A :&: f @*^-1 R) = f @* A :&: R.\n\n(*This lemma states that the image of the empty set under an order morphism is the empty set.*)\nLemma morphim0 : f @* set0 = set0.\n\n(*This lemma states that for any set contained within the morphism's domain, the image of that set is empty if and only if the original set is empty.*)\nLemma morphim_eq0 A : A \\subset D -> (f @* A == set0) = (A == set0).\n\n(*This lemma states that for any element in the morphism's domain, the image of the singleton set containing that element is the singleton set containing its image.*)\nLemma morphim_set1 x : x \\in D -> f @* [set x] = [set f x].\n\n(*This lemma states that the image of the trivial substructure under a morphism is the trivial substructure in the codomain.*)\nLemma morphim1 : f @* 1 = 1.\n\n(*This lemma states that the image of the set of inverses of elements in a set is equal to the set of inverses of the elements in the image of that set.*)\nLemma morphimV A : f @* A^-1 = (f @* A)^-1.\n\n(*This lemma states that the preimage of the set of inverses of elements in a set is equal to the set of inverses of the elements in the preimage of that set.*)\nLemma morphpreV R : f @*^-1 R^-1 = (f @*^-1 R)^-1.\n\n(*This lemma states that if a set is contained within a morphism's domain, the image of the product of this set with a second set is equal to the product of their respective images.*)\nLemma morphimMl A B : A \\subset D -> f @* (A * B) = f @* A * f @* B.\n\n(*This lemma states that if a set is contained within a morphism's domain, the image of the product of a second set with this set is equal to the product of their respective images.*)\nLemma morphimMr A B : B \\subset D -> f @* (A * B) = f @* A * f @* B.\n\n(*This lemma states that for a set contained in the image of a morphism's domain, the preimage of its product with a second set is equal to the product of their respective preimages.*)\nLemma morphpreMl R S :\n R \\subset f @* D -> f @*^-1 (R * S) = f @*^-1 R * f @*^-1 S.\n\n(*This lemma states that for an element in a morphism's domain, the image of a set acted upon by this element is equal to the image of the set acted upon by the image of the element.*)\nLemma morphimJ A x : x \\in D -> f @* (A :^ x) = f @* A :^ f x.\n\n(*This lemma states that for an element in a morphism's domain, the preimage of a set acted upon by the image of this element is equal to the preimage of the set acted upon by the original element.*)\nLemma morphpreJ R x : x \\in D -> f @*^-1 (R :^ f x) = f @*^-1 R :^ x.\n\n(*This lemma states that for an element and a set within a morphism's domain, the image of the class generated by the element and the set is equal to the class generated by the image of the element and the image of the set.*)\nLemma morphim_class x A :\n x \\in D -> A \\subset D -> f @* (x ^: A) = f x ^: f @* A.\n\n(*This lemma states that for a set contained in a morphism's domain, the set of equivalence classes of its image is equal to the set of images of its equivalence classes.*)\nLemma classes_morphim A :\n A \\subset D -> classes (f @* A) = [set f @* xA | xA in classes A].\n\n(*This lemma states that the image of the universal set under an order morphism is equal to the image of the morphism's domain.*)\nLemma morphimT : f @* setT = f @* D.\n\n(*This lemma states that for a group morphism, the image of the union of two sets is equal to the union of the images of those sets.*)\nLemma morphimU A B : f @* (A :|: B) = f @* A :|: f @* B.\n\n(*This lemma states that for a group morphism, the image of the intersection of two sets is a subset of the intersection of their images.*)\nLemma morphimI A B : f @* (A :&: B) \\subset f @* A :&: f @* B.\n\n(*This lemma states that the preimage of the empty set under a group morphism is the empty set.*)\nLemma morphpre0 : f @*^-1 set0 = set0.\n\n(*This lemma states that the preimage of the entire target set under a group morphism is equal to the domain of the morphism.*)\nLemma morphpreT : f @*^-1 setT = D.\n\n(*This lemma states that for a group morphism, the preimage of the union of two sets is equal to the union of their respective preimages.*)\nLemma morphpreU R S : f @*^-1 (R :|: S) = f @*^-1 R :|: f @*^-1 S.\n\n(*This lemma states that for a group morphism, the preimage of the intersection of two sets is equal to the intersection of their respective preimages.*)\nLemma morphpreI R S : f @*^-1 (R :&: S) = f @*^-1 R :&: f @*^-1 S.\n\n(*This lemma states that for a group morphism, the preimage of the difference between two sets is equal to the difference between their respective preimages.*)\nLemma morphpreD R S : f @*^-1 (R :\\: S) = f @*^-1 R :\\: f @*^-1 S.\n\n(*This lemma establishes that an element from the domain of a group morphism belongs to the kernel of that morphism if and only if the morphism maps that element to the identity element of the codomain.*)\nLemma kerP x : x \\in D -> reflect (f x = 1) (x \\in 'ker f).\n\n(*This lemma states that the kernel of a group morphism is a subset of the domain of that morphism.*)\nLemma dom_ker : {subset 'ker f <= D}.\n\n(*This lemma states that if an element belongs to the kernel of a group morphism, then the morphism maps that element to the identity element of the codomain.*)\nLemma mker x : x \\in 'ker f -> f x = 1.\n\n(*This lemma states that for a group morphism, if an element from its domain is multiplied on the left by an element from the kernel, the image of the resulting product is equal to the image of the original domain element.*)\nLemma mkerl x y : x \\in 'ker f -> y \\in D -> f (x * y) = f y.\n\n(*This lemma states that for a group morphism, if an element from its domain is multiplied on the right by an element from the kernel, the image of the resulting product is equal to the image of the original domain element.*)\nLemma mkerr x y : x \\in D -> y \\in 'ker f -> f (x * y) = f x.\n\n(*This lemma establishes that two elements in the domain of a group morphism have the same image if and only if the first element belongs to the right coset of the kernel with respect to the second element.*)\nLemma rcoset_kerP x y :\n x \\in D -> y \\in D -> reflect (f x = f y) (x \\in 'ker f :* y).\n\n(*This lemma states that if two elements in the domain of a group morphism map to the same image, then there exists an element in the kernel such that the first element is the product of this kernel element and the second element.*)\nLemma ker_rcoset x y :\n x \\in D -> y \\in D -> f x = f y -> exists2 z, z \\in 'ker f & x = z * y.\n\n(*This lemma states that the domain of a group morphism is a subset of the normalizer of its kernel.*)\nLemma ker_norm : D \\subset 'N('ker f).\n\n(*This lemma states that the kernel of a group morphism is a normal subgroup of its domain group.*)\nLemma ker_normal : 'ker f <| D.\n\n(*This lemma states that for a group morphism, if a subgroup of the domain contains the kernel, then the image of the intersection of that subgroup with another set is equal to the intersection of their individual images.*)\nLemma morphimGI G A : 'ker f \\subset G -> f @* (G :&: A) = f @* G :&: f @* A.\n\n(*This lemma states that for a group morphism, if a subgroup of the domain contains the kernel, then the image of the intersection of a set with that subgroup is equal to the intersection of their individual images.*)\nLemma morphimIG A G : 'ker f \\subset G -> f @* (A :&: G) = f @* A :&: f @* G.\n\n(*This lemma states that for a group morphism, the difference between the images of two sets is a subset of the image of the difference between those two sets.*)\nLemma morphimD A B : f @* A :\\: f @* B \\subset f @* (A :\\: B).\n\n(*This lemma states that for a group morphism, if a subgroup of the domain contains the kernel, then the image of the difference between a set and that subgroup is equal to the difference between their respective images.*)\nLemma morphimDG A G : 'ker f \\subset G -> f @* (A :\\: G) = f @* A :\\: f @* G.\n\n(*This lemma states that for a group morphism, the complement of the image of a set is a subset of the image of the complement of that set.*)\nLemma morphimD1 A : (f @* A)^# \\subset f @* A^#.\n\n(*This lemma states that the preimage of a subgroup under a group morphism is itself a subgroup.*)\nLemma morphpre_groupset M : group_set (f @*^-1 M).\n\n(*This lemma states that the image of a subgroup under a group morphism is itself a subgroup.*)\nLemma morphim_groupset G : group_set (f @* G).\n\nCanonical morphpre_group fPh M :=\n @group _ (morphpre fPh M) (morphpre_groupset M).\nCanonical morphim_group fPh G := @group _ (morphim fPh G) (morphim_groupset G).\nCanonical ker_group fPh : {group aT} := Eval hnf in [group of ker fPh].\n\n(*This lemma states that the image of the entire domain of a group morphism is a subgroup of the codomain.*)\nLemma morph_dom_groupset : group_set (f @: D).\n\nCanonical morph_dom_group := group morph_dom_groupset.\n\n(*This lemma states that for a group morphism, if a set in the codomain is a subset of the image of the domain, then the preimage of the product of this set with another set is equal to the product of their respective preimages.*)\nLemma morphpreMr R S :\n S \\subset f @* D -> f @*^-1 (R * S) = f @*^-1 R * f @*^-1 S.\n\n(*This lemma states that for any subset of the domain of a group morphism, the preimage of its image is equal to the group product of the kernel and the original subset.*)\nLemma morphimK A : A \\subset D -> f @*^-1 (f @* A) = 'ker f * A.\n\n(*This lemma states that for any subgroup of the domain of a group morphism that contains the kernel, the preimage of its image is equal to the original subgroup.*)\nLemma morphimGK G : 'ker f \\subset G -> G \\subset D -> f @*^-1 (f @* G) = G.\n\n(*This lemma states that for any element in the domain of a group morphism, the preimage of the singleton set containing its image is equal to the right coset of the kernel with respect to that element.*)\nLemma morphpre_set1 x : x \\in D -> f @*^-1 [set f x] = 'ker f :* x.\n\n(*This lemma states that for any subset of the image of the domain of a group morphism, the image of its preimage is equal to the original subset.*)\nLemma morphpreK R : R \\subset f @* D -> f @* (f @*^-1 R) = R.\n\n(*This lemma states that the image of the kernel of a group morphism is the trivial subgroup containing only the identity element.*)\nLemma morphim_ker : f @* 'ker f = 1.\n\n(*This lemma states that the kernel of a group morphism is a subset of the preimage of any subgroup of the codomain.*)\nLemma ker_sub_pre M : 'ker f \\subset f @*^-1 M.\n\n(*This lemma states that the kernel of a group morphism is a normal subgroup of the preimage of any subgroup of the codomain.*)\nLemma ker_normal_pre M : 'ker f <| f @*^-1 M.\n\n(*This lemma states that for any two subgroups of the codomain that are contained within the image of a group morphism, the preimage of the first subgroup is a subgroup of the preimage of the second if and only if the first subgroup is a subgroup of the second.*)\nLemma morphpreSK R S :\n R \\subset f @* D -> (f @*^-1 R \\subset f @*^-1 S) = (R \\subset S).\n\n(*This lemma establishes a Galois connection, stating that for any subgroup of the domain of a group morphism, its image is a subgroup of a given codomain subgroup if and only if the domain subgroup is itself a subgroup of the preimage of the codomain subgroup.*)\nLemma sub_morphim_pre A R :\n A \\subset D -> (f @* A \\subset R) = (A \\subset f @*^-1 R).\n\n(*This lemma states that for any two subgroups of the codomain that are contained within the image of a group morphism, the preimage of the first subgroup is a proper subgroup of the preimage of the second if and only if the first subgroup is a proper subgroup of the second.*)\nLemma morphpre_proper R S :\n R \\subset f @* D -> S \\subset f @* D ->\n (f @*^-1 R \\proper f @*^-1 S) = (R \\proper S).\n\n(*This lemma states that for a subgroup of the domain containing the kernel of a group morphism, and a subgroup of the codomain contained in the image of the morphism, the preimage of the codomain subgroup is a subgroup of the domain subgroup if and only if the codomain subgroup is a subgroup of the image of the domain subgroup.*)\nLemma sub_morphpre_im R G :\n 'ker f \\subset G -> G \\subset D -> R \\subset f @* D ->\n (f @*^-1 R \\subset G) = (R \\subset f @* G).\n\n(*This lemma states that a subgroup is contained in the kernel of a group morphism if and only if it is a subgroup of the morphism's domain and its image under the morphism is contained in the trivial subgroup.*)\nLemma ker_trivg_morphim A :\n (A \\subset 'ker f) = (A \\subset D) && (f @* A \\subset [1]).\n\n(*This lemma states that for any two subgroups of the domain of a group morphism, the image of the first subgroup is a subgroup of the image of the second if and only if the first subgroup is contained in the group product of the morphism's kernel and the second subgroup.*)\nLemma morphimSK A B :\n A \\subset D -> (f @* A \\subset f @* B) = (A \\subset 'ker f * B).\n\n(*This lemma states that for two subgroups of the domain of a group morphism, where the second subgroup contains the kernel, the image of the first subgroup is a subgroup of the image of the second if and only if the first subgroup is contained in the second.*)\nLemma morphimSGK A G :\n A \\subset D -> 'ker f \\subset G -> (f @* A \\subset f @* G) = (A \\subset G).\n\n(*This lemma states that if the kernel of a group morphism, when intersected with a given finite subgroup of the domain, is non-trivial, then the size of the image of that subgroup is strictly smaller than the size of the subgroup itself.*)\nLemma ltn_morphim A : [1] \\proper 'ker_A f -> #|f @* A| < #|A|.\n\n(*This lemma asserts that the preimage function of a group morphism is injective when restricted to the set of subgroups contained within the image of the morphism.*)\nLemma morphpre_inj :\n {in [pred R : {set rT} | R \\subset f @* D] &, injective (fun R => f @*^-1 R)}.\n\n(*This lemma asserts that the image function of a group morphism is injective when restricted to the set of subgroups of the domain that contain the kernel of the morphism.*)\nLemma morphim_injG :\n {in [pred G : {group aT} | 'ker f \\subset G & G \\subset D] &,\n injective (fun G => f @* G)}.\n\n(*This lemma states that if two subgroups of the domain of a group morphism both contain the kernel, and their images under the morphism are equal, then the two subgroups must be equal.*)\nLemma morphim_inj G H :\n ('ker f \\subset G) && (G \\subset D) ->\n ('ker f \\subset H) && (H \\subset D) ->\n f @* G = f @* H -> G :=: H.\n\n(*This lemma states that for a group morphism, the image of the subgroup generated by a set of elements is equal to the subgroup generated by the image of that set.*)\nLemma morphim_gen A : A \\subset D -> f @* <> = <>.\n\n(*This lemma states that for a group morphism, the image of the cyclic subgroup generated by an element is equal to the cyclic subgroup generated by the image of that element.*)\nLemma morphim_cycle x : x \\in D -> f @* <[x]> = <[f x]>.\n\n(*This lemma states that for a group morphism, the image of the product of two subgroups of the domain is equal to the product of their respective images.*)\nLemma morphimY A B :\n A \\subset D -> B \\subset D -> f @* (A <*> B) = f @* A <*> f @* B.\n\n(*This lemma states that for a group morphism, the preimage of the subgroup generated by a set of elements is equal to the subgroup generated by the preimage of that set, provided the set contains the identity element and is contained in the image of the morphism.*)\nLemma morphpre_gen R :\n 1 \\in R -> R \\subset f @* D -> f @*^-1 <> = <>.\n\n(*This lemma states that for a group morphism, the image of the commutator of two subgroups of the domain is equal to the commutator of their respective images.*)\nLemma morphimR A B :\n A \\subset D -> B \\subset D -> f @* [~: A, B] = [~: f @* A, f @* B].\n\n(*This lemma states that for a group morphism, the image of the normalizer of a subgroup is contained in the normalizer of the image of that subgroup.*)\nLemma morphim_norm A : f @* 'N(A) \\subset 'N(f @* A).\n\n(*This lemma states that if a subgroup is contained in the normalizer of another subgroup, then the image of the first subgroup under a group morphism is contained in the normalizer of the image of the second subgroup.*)\nLemma morphim_norms A B : A \\subset 'N(B) -> f @* A \\subset 'N(f @* B).\n\n(*This lemma states that for a group morphism, the image of the normalizer of a subgroup within another subgroup is contained in the normalizer of the image of the first subgroup within the image of the second.*)\nLemma morphim_subnorm A B : f @* 'N_A(B) \\subset 'N_(f @* A)(f @* B).\n\n(*This lemma states that group morphisms preserve the normal subgroup relationship; if one subgroup is normal in another, their respective images under the morphism maintain the same normal subgroup relationship.*)\nLemma morphim_normal A B : A <| B -> f @* A <| f @* B.\n\n(*This lemma states that for a group morphism, the image of the centralizer of an element in the domain is contained in the centralizer of the image of that element.*)\nLemma morphim_cent1 x : x \\in D -> f @* 'C[x] \\subset 'C[f x].\n\n(*This lemma states that if a subgroup is contained in the centralizer of an element from the domain of a group morphism, then the image of that subgroup is contained in the centralizer of the image of that element.*)\nLemma morphim_cent1s A x : x \\in D -> A \\subset 'C[x] -> f @* A \\subset 'C[f x].\n\n(*This lemma states that for a group morphism, the image of the centralizer of an element within a subgroup is contained in the centralizer of the image of the element within the image of the subgroup.*)\nLemma morphim_subcent1 A x : x \\in D -> f @* 'C_A[x] \\subset 'C_(f @* A)[f x].\n\n(*This lemma states that for a group morphism, the image of the centralizer of a subgroup is contained in the centralizer of the image of that subgroup.*)\nLemma morphim_cent A : f @* 'C(A) \\subset 'C(f @* A).\n\n(*This lemma states that if a subgroup is contained in the centralizer of another subgroup, then the image of the first subgroup under a group morphism is contained in the centralizer of the image of the second subgroup.*)\nLemma morphim_cents A B : A \\subset 'C(B) -> f @* A \\subset 'C(f @* B).\n\n(*This lemma states that for a group morphism, the image of the centralizer of a subgroup within another subgroup is contained in the centralizer of the image of the first subgroup within the image of the second.*)\nLemma morphim_subcent A B : f @* 'C_A(B) \\subset 'C_(f @* A)(f @* B).\n\n(*This lemma states that the image of an abelian subgroup under a group morphism is also an abelian subgroup.*)\nLemma morphim_abelian A : abelian A -> abelian (f @* A).\n\n(*This lemma states that for a group morphism, the preimage of the normalizer of a subgroup in the codomain is contained in the normalizer of the preimage of that subgroup.*)\nLemma morphpre_norm R : f @*^-1 'N(R) \\subset 'N(f @*^-1 R).\n\n(*This lemma states that if a set is contained in the normalizer of a second set, then the preimage of the first set under a group morphism is contained in the normalizer of the preimage of the second set.*)\nLemma morphpre_norms R S : R \\subset 'N(S) -> f @*^-1 R \\subset 'N(f @*^-1 S).\n\n(*This lemma states that for any two sets contained within the image of a group morphism, the preimage of the first set is a normal subgroup of the preimage of the second set if and only if the first set is a normal subgroup of the second set.*)\nLemma morphpre_normal R S :\n R \\subset f @* D -> S \\subset f @* D -> (f @*^-1 R <| f @*^-1 S) = (R <| S).\n\n(*This lemma states that the preimage under a group morphism of the normalizer of a set within another set is contained in the normalizer of the preimage of the first set within the preimage of the second set.*)\nLemma morphpre_subnorm R S : f @*^-1 'N_R(S) \\subset 'N_(f @*^-1 R)(f @*^-1 S).\n\n(*This lemma states that for a subgroup of the domain of a group morphism that contains the kernel, the image of its normalizer is equal to the normalizer of its image, taken within the image of the domain.*)\nLemma morphim_normG G :\n 'ker f \\subset G -> G \\subset D -> f @* 'N(G) = 'N_(f @* D)(f @* G).\n\n(*This lemma states that for a subgroup of the domain of a group morphism that contains the kernel, the image of its normalizer within another set is equal to the normalizer of its image within the image of that other set.*)\nLemma morphim_subnormG A G :\n 'ker f \\subset G -> G \\subset D -> f @* 'N_A(G) = 'N_(f @* A)(f @* G).\n\n(*This lemma states that for an element in the domain of a group morphism, its centralizer within the domain is a subset of the preimage of the centralizer of its image.*)\nLemma morphpre_cent1 x : x \\in D -> 'C_D[x] \\subset f @*^-1 'C[f x].\n\n(*This lemma states that for an element in the domain of a group morphism and a set in its codomain, if the preimage of the set is contained in the centralizer of the element, then the set itself is contained in the centralizer of the element's image.*)\nLemma morphpre_cent1s R x :\n x \\in D -> R \\subset f @* D -> f @*^-1 R \\subset 'C[x] -> R \\subset 'C[f x].\n\n(*This lemma states that for an element in the domain of a group morphism and a set in its codomain, the centralizer of the element within the preimage of the set is contained in the preimage of the centralizer of the element's image within that set.*)\nLemma morphpre_subcent1 R x :\n x \\in D -> 'C_(f @*^-1 R)[x] \\subset f @*^-1 'C_R[f x].\n\n(*This lemma states that the centralizer of a set within the domain of a group morphism is a subset of the preimage of the centralizer of the set's image.*)\nLemma morphpre_cent A : 'C_D(A) \\subset f @*^-1 'C(f @* A).\n\n(*This lemma states that for two sets, one in the domain and one in the codomain of a group morphism, if the preimage of the codomain set is contained in the centralizer of the domain set, then the codomain set itself is contained in the centralizer of the domain set's image.*)\nLemma morphpre_cents A R :\n R \\subset f @* D -> f @*^-1 R \\subset 'C(A) -> R \\subset 'C(f @* A).\n\n(*This lemma states that for two sets, one in the domain and one in the codomain of a group morphism, the centralizer of the domain set within the preimage of the codomain set is contained in the preimage of the centralizer of the domain set's image within the codomain set.*)\nLemma morphpre_subcent R A : 'C_(f @*^-1 R)(A) \\subset f @*^-1 'C_R(f @* A).\n\n(*This lemma provides a reflection principle, stating that the boolean property of a group morphism being injective on its domain is equivalent to the logical proposition that the function is injective.*)\nLemma injmP : reflect {in D &, injective f} ('injm f).\n\n(*This lemma states that a group morphism is injective on its domain if and only if the cardinality of the image of the domain is equal to the cardinality of the domain itself.*)\nLemma card_im_injm : (#|f @* D| == #|D|) = 'injm f.\n\nSection Injective.\n\nHypothesis injf : 'injm f.\n\n(*This lemma states that the kernel of an injective group morphism is the trivial subgroup containing only the identity element.*)\nLemma ker_injm : 'ker f = 1.\n\n(*This lemma states that for an injective group morphism, the preimage of the image of any subset of the domain is equal to the original subset.*)\nLemma injmK A : A \\subset D -> f @*^-1 (f @* A) = A.\n\n(*This lemma states that if two subsets of the domain of an injective group morphism have the same image, then the two subsets must be identical.*)\nLemma injm_morphim_inj A B :\n A \\subset D -> B \\subset D -> f @* A = f @* B -> A = B.\n\n(*This lemma states that an injective group morphism preserves the cardinality of any subset of its domain, meaning the cardinality of the image of a subset is equal to the cardinality of the subset itself.*)\nLemma card_injm A : A \\subset D -> #|f @* A| = #|A|.\n\n(*This lemma states that an injective group morphism preserves the order of any element in its domain, meaning the order of the image of an element is equal to the order of the element itself.*)\nLemma order_injm x : x \\in D -> #[f x] = #[x].\n\n(*This lemma states that for an injective group morphism, if the image of an element from the domain is the identity element, then the element itself must be the identity.*)\nLemma injm1 x : x \\in D -> f x = 1 -> x = 1.\n\n(*This lemma states that for an element in the domain of an injective group morphism, the boolean statement that its image is the identity element is equivalent to the boolean statement that the element itself is the identity.*)\nLemma morph_injm_eq1 x : x \\in D -> (f x == 1) = (x == 1).\n\n(*This lemma states that for an injective group morphism and any two subsets of its domain, the image of the first subset is contained in the image of the second if and only if the first subset is contained in the second.*)\nLemma injmSK A B :\n A \\subset D -> (f @* A \\subset f @* B) = (A \\subset B).\n\n(*This lemma states that for an injective group morphism, a subset of its domain, and a subset of its codomain, the preimage of the codomain subset is contained in the domain subset if and only if the codomain subset is contained in the image of the domain subset.*)\nLemma sub_morphpre_injm R A :\n A \\subset D -> R \\subset f @* D ->\n (f @*^-1 R \\subset A) = (R \\subset f @* A).\n\n(*This lemma states that for an injective group morphism, the boolean equality between the images of two subsets of the domain is equivalent to the boolean equality between the subsets themselves.*)\nLemma injm_eq A B : A \\subset D -> B \\subset D -> (f @* A == f @* B) = (A == B).\n\n(*This lemma states that for an injective group morphism, the image of a subset of the domain is the trivial group if and only if the subset itself is the trivial group.*)\nLemma morphim_injm_eq1 A : A \\subset D -> (f @* A == 1) = (A == 1).\n\n(*This lemma states that an injective group morphism distributes over set intersection, meaning the image of the intersection of two sets is equal to the intersection of their images.*)\nLemma injmI A B : f @* (A :&: B) = f @* A :&: f @* B.\n\n(*This lemma states that for an injective group morphism, the image of the subgroup generated by a set is equal to the subgroup generated by the image of that set.*)\nLemma injmD1 A : f @* A^# = (f @* A)^#.\n\n(*This lemma states that for a subset of the domain of an injective group morphism, the number of conjugacy classes in its image is equal to the number of conjugacy classes in the subset itself.*)\nLemma nclasses_injm A : A \\subset D -> #|classes (f @* A)| = #|classes A|.\n\n(*This lemma states that for an injective group morphism and a subset of its domain, the image of the normalizer of the subset is equal to the normalizer of the subset's image, taken within the image of the domain.*)\nLemma injm_norm A : A \\subset D -> f @* 'N(A) = 'N_(f @* D)(f @* A).\n\n(*This lemma states that for an injective group morphism and two subsets of its domain, the image of the first subset is contained in the normalizer of the image of the second if and only if the first subset is contained in the normalizer of the second.*)\nLemma injm_norms A B :\n A \\subset D -> B \\subset D -> (f @* A \\subset 'N(f @* B)) = (A \\subset 'N(B)).\n\n(*This lemma states that for an injective group morphism and two subsets of its domain, the image of the first subset is a normal subgroup of the image of the second if and only if the first subset is a normal subgroup of the second.*)\nLemma injm_normal A B :\n A \\subset D -> B \\subset D -> (f @* A <| f @* B) = (A <| B).\n\n(*This lemma states that for an injective group morphism, the image of the normalizer of a set 'B' within a set 'A' is equal to the normalizer of the image of 'B' within the image of 'A', provided 'B' is a subset of the morphism's domain.*)\nLemma injm_subnorm A B : B \\subset D -> f @* 'N_A(B) = 'N_(f @* A)(f @* B).\n\n(*This lemma states that for an injective group morphism, the image of the centralizer of an element from the domain is equal to the centralizer of the image of that element within the image of the domain.*)\nLemma injm_cent1 x : x \\in D -> f @* 'C[x] = 'C_(f @* D)[f x].\n\n(*This lemma states that for an injective group morphism, the image of the centralizer of an element from the morphism's domain within a set 'A' is equal to the centralizer of the image of that element within the image of 'A'.*)\nLemma injm_subcent1 A x : x \\in D -> f @* 'C_A[x] = 'C_(f @* A)[f x].\n\n(*This lemma states that for an injective group morphism, if a set 'A' is a subset of the morphism's domain, then the image of the centralizer of 'A' is equal to the centralizer of the image of 'A' within the image of the domain.*)\nLemma injm_cent A : A \\subset D -> f @* 'C(A) = 'C_(f @* D)(f @* A).\n\n(*This lemma states that for an injective group morphism and two sets 'A' and 'B' within its domain, the inclusion of the image of 'A' in the centralizer of the image of 'B' is equivalent to the inclusion of 'A' in the centralizer of 'B'.*)\nLemma injm_cents A B :\n A \\subset D -> B \\subset D -> (f @* A \\subset 'C(f @* B)) = (A \\subset 'C(B)).\n\n(*This lemma states that for an injective group morphism, the image of the centralizer of a set 'B' within another set 'A' is equal to the centralizer of the image of 'B' within the image of 'A', provided 'B' is a subset of the morphism's domain.*)\nLemma injm_subcent A B : B \\subset D -> f @* 'C_A(B) = 'C_(f @* A)(f @* B).\n\n(*This lemma states that for an injective group morphism, a set within its domain generates an abelian group if and only if its image under the morphism also generates an abelian group.*)\nLemma injm_abelian A : A \\subset D -> abelian (f @* A) = abelian A.\n\nEnd Injective.\n\n(*This lemma states that if two group morphisms are equal on all elements of their common domain, then the image of any given set under the first morphism is equal to its image under the second morphism.*)\nLemma eq_morphim (g : {morphism D >-> rT}):\n {in D, f =1 g} -> forall A, f @* A = g @* A.\n\n(*This lemma states that if two group morphisms are equal on a given set, and their respective domains have the same intersection with that set, then the image of the set under the first morphism is equal to its image under the second morphism.*)\nLemma eq_in_morphim B A (g : {morphism B >-> rT}) :\n D :&: A = B :&: A -> {in A, f =1 g} -> f @* A = g @* A.\n\nEnd MorphismTheory.\n\n(*This notation defines the kernel of a group morphism, which is the subgroup of elements in the domain that are mapped to the identity element of the codomain.*)\nNotation \"''ker' f\" := (ker_group (MorPhantom f)) : Group_scope.\n(*This notation defines the kernel of a group morphism restricted to a given subgroup, which consists of the elements within that subgroup that are mapped to the identity element.*)\nNotation \"''ker_' G f\" := (G :&: 'ker f)%G : Group_scope.\n(*This notation represents the image of a given set under a group morphism, which is the set of all elements in the codomain that are the result of applying the morphism to an element from the given set.*)\nNotation \"f @* G\" := (morphim_group (MorPhantom f) G) : Group_scope.\n(*This notation represents the preimage of a given set under a group morphism, which is the set of all elements in the domain that map to an element within the given set in the codomain.*)\nNotation \"f @*^-1 M\" := (morphpre_group (MorPhantom f) M) : Group_scope.\n(*This notation constructs a group morphism from a given function and a specified domain set.*)\nNotation \"f @: D\" := (morph_dom_group f D) : Group_scope.\n\nArguments injmP {aT rT D f}.\nArguments morphpreK {aT rT D f} [R] sRf.\n\nSection IdentityMorphism.\n\nVariable gT : finGroupType.\nImplicit Types A B : {set gT}.\nImplicit Type G : {group gT}.\n\n(*This definition specifies the identity function on the carrier type of a finite group.*)\nDefinition idm of {set gT} := fun x : gT => x : FinGroup.sort gT.\n\n(*This lemma establishes that the identity function preserves the group operation on any given set, thus qualifying it as a group morphism on that set.*)\nLemma idm_morphM A : {in A & , {morph idm A : x y / x * y}}.\n\nCanonical idm_morphism A := Morphism (@idm_morphM A).\n\n(*This lemma states that the identity morphism on any given group is injective.*)\nLemma injm_idm G : 'injm (idm G).\n\n(*This lemma states that the kernel of the identity morphism on any given group is the trivial subgroup, which contains only the identity element.*)\nLemma ker_idm G : 'ker (idm G) = 1.\n\n(*This lemma states that the image of a set under the identity morphism is the set itself, provided the set is contained within the morphism's domain.*)\nLemma morphim_idm A B : B \\subset A -> idm A @* B = B.\n\n(*This lemma states that the preimage of a set under the identity morphism with a given domain is the intersection of that set with the domain.*)\nLemma morphpre_idm A B : idm A @*^-1 B = A :&: B.\n\n(*This lemma states that the image of the domain of an identity morphism under that same morphism is the domain itself.*)\nLemma im_idm A : idm A @* A = A.\n\nEnd IdentityMorphism.\n\nArguments idm {_} _%_g _%_g.\n\nSection RestrictedMorphism.\n\nVariables aT rT : finGroupType.\nVariables A D : {set aT}.\nImplicit Type B : {set aT}.\nImplicit Type R : {set rT}.\n\n(*This definition provides a mechanism to create a restricted morphism by taking an existing morphism function and considering it over a smaller domain, which is a subset of the original domain.*)\nDefinition restrm of A \\subset D := @id (aT -> FinGroup.sort rT).\n\nSection Props.\n\nHypothesis sAD : A \\subset D.\nVariable f : {morphism D >-> rT}.\n(*This local notation refers to the function of a group morphism 'f' restricted to a smaller domain 'A'.*)\nLocal Notation fA := (restrm sAD (mfun f)).\n\nCanonical restrm_morphism :=\n @Morphism aT rT A fA (sub_in2 (subsetP sAD) (morphM f)).\n\n(*This lemma states that the image of a set under a restricted morphism is equal to the image under the original morphism of the intersection of the set with the restricted domain.*)\nLemma morphim_restrm B : fA @* B = f @* (A :&: B).\n\n(*This lemma states that if a set is a subset of the domain of a restricted morphism, its image under the restricted morphism is the same as its image under the original, unrestricted morphism.*)\nLemma restrmEsub B : B \\subset A -> fA @* B = f @* B.\n\n(*This lemma states that the image of the domain of a restricted morphism is equal to the image of that same domain under the original, unrestricted morphism.*)\nLemma im_restrm : fA @* A = f @* A.\n\n(*This lemma states that the preimage of a set under a restricted morphism is the intersection of the restricted domain with the preimage of the set under the original, unrestricted morphism.*)\nLemma morphpre_restrm R : fA @*^-1 R = A :&: f @*^-1 R.\n\n(*This lemma states that the kernel of a restricted morphism is equal to the intersection of the restricted domain with the kernel of the original, unrestricted morphism.*)\nLemma ker_restrm : 'ker fA = 'ker_A f.\n\n(*This lemma states that if a group morphism is injective, then any restriction of that morphism to a smaller domain is also injective.*)\nLemma injm_restrm : 'injm f -> 'injm fA.\n\nEnd Props.\n\n(*This lemma provides a characteristic property of a restricted morphism, stating that for any element in the restricted domain, applying the restricted morphism is equivalent to applying the original morphism.*)\nLemma restrmP (f : {morphism D >-> rT}) : A \\subset 'dom f ->\n {g : {morphism A >-> rT} | [/\\ g = f :> (aT -> rT), 'ker g = 'ker_A f,\n forall R, g @*^-1 R = A :&: f @*^-1 R\n & forall B, B \\subset A -> g @* B = f @* B]}.\n\n(*This lemma states that if the domain of a group morphism is equal to a given set, then there exists a new morphism defined on that set which is functionally identical to the original morphism, having the same underlying function, kernel, image, and preimage behavior.*)\nLemma domP (f : {morphism D >-> rT}) : 'dom f = A ->\n {g : {morphism A >-> rT} | [/\\ g = f :> (aT -> rT), 'ker g = 'ker f,\n forall R, g @*^-1 R = f @*^-1 R\n & forall B, g @* B = f @* B]}.\n\nEnd RestrictedMorphism.\n\nArguments restrm {_ _ _%_g _%_g} _ _%_g.\nArguments restrmP {aT rT A D}.\nArguments domP {aT rT A D}.\n\nSection TrivMorphism.\n\nVariables aT rT : finGroupType.\n\n(*This definition creates a trivial function that maps any element from a given source finite group to the identity element of a target finite group.*)\nDefinition trivm of {set aT} & aT := 1 : FinGroup.sort rT.\n\n(*This lemma states that the trivial function, which maps all elements to the identity, is a group homomorphism when restricted to any subset of its domain group.*)\nLemma trivm_morphM (A : {set aT}) : {in A &, {morph trivm A : x y / x * y}}.\n\nCanonical triv_morph A := Morphism (@trivm_morphM A).\n\n(*This lemma states that the image of any subgroup under the trivial group morphism is the set containing only the identity element of the target group.*)\nLemma morphim_trivm (G H : {group aT}) : trivm G @* H = 1.\n\n(*This lemma states that the kernel of the trivial group morphism defined on a source group is the entire source group itself.*)\nLemma ker_trivm (G : {group aT}) : 'ker (trivm G) = G.\n\nEnd TrivMorphism.\n\nArguments trivm {aT rT} _%_g _%_g.\n\nSection MorphismComposition.\n\nVariables gT hT rT : finGroupType.\nVariables (G : {group gT}) (H : {group hT}).\n\nVariable f : {morphism G >-> hT}.\nVariable g : {morphism H >-> rT}.\n\n(*A local notation for the function composition of the underlying functions of two group morphisms.*)\nLocal Notation gof := (mfun g \\o mfun f).\n\n(*This lemma states that the composition of two group homomorphisms is itself a group homomorphism on the domain formed by the preimage of the second homomorphism's domain under the first homomorphism.*)\nLemma comp_morphM : {in f @*^-1 H &, {morph gof: x y / x * y}}.\n\nCanonical comp_morphism := Morphism comp_morphM.\n\n(*This lemma states that the kernel of a composite group morphism is the preimage of the kernel of the second morphism under the first morphism.*)\nLemma ker_comp : 'ker gof = f @*^-1 'ker g.\n\n(*This lemma states that the composition of two injective group morphisms is also an injective group morphism.*)\nLemma injm_comp : 'injm f -> 'injm g -> 'injm gof.\n\n(*This lemma states that the image of a set under a composite group morphism is equal to the image under the second morphism of the image of the set under the first morphism.*)\nLemma morphim_comp (A : {set gT}) : gof @* A = g @* (f @* A).\n\n(*This lemma states that the preimage of a set under a composite group morphism is equal to the preimage under the first morphism of the preimage of the set under the second morphism.*)\nLemma morphpre_comp (C : {set rT}) : gof @*^-1 C = f @*^-1 (g @*^-1 C).\n\nEnd MorphismComposition.\n\nSection FactorMorphism.\n\nVariables aT qT rT : finGroupType.\n\nVariables G H : {group aT}.\nVariable f : {morphism G >-> rT}.\nVariable q : {morphism H >-> qT}.\n\n(*This definition constructs a factor morphism, which is a new morphism induced by two existing morphisms, provided that the kernel of the second is included in the kernel of the first. The new morphism maps an element in the target of the second morphism by applying the first morphism to a representative from the element's preimage.*)\nDefinition factm of 'ker q \\subset 'ker f & G \\subset H :=\n fun x => f (repr (q @*^-1 [set x])).\n\nHypothesis sKqKf : 'ker q \\subset 'ker f.\nHypothesis sGH : G \\subset H.\n\n(*A local notation for the factor morphism constructed under specific hypotheses about kernel inclusion and domain inclusion.*)\nNotation ff := (factm sKqKf sGH).\n\n(*This lemma provides the evaluation rule for a factor morphism, stating that applying the factor morphism to the image of an element under the quotienting morphism is equivalent to applying the original morphism to that element.*)\nLemma factmE x : x \\in G -> ff (q x) = f x.\n\n(*This lemma states that a factor morphism is a group homomorphism on its domain, which is the image of the original domain group under the quotienting morphism.*)\nLemma factm_morphM : {in q @* G &, {morph ff : x y / x * y}}.\n\nCanonical factm_morphism := Morphism factm_morphM.\n\n(*This lemma states that the image of a set under a factor morphism, when applied to the image of an initial set under the quotienting morphism, is equal to the image of the initial set under the original morphism.*)\nLemma morphim_factm (A : {set aT}) : ff @* (q @* A) = f @* A.\n\n(*This lemma states that the preimage of a set under a factor morphism is equal to the image under the quotienting morphism of the preimage of that set under the original morphism.*)\nLemma morphpre_factm (C : {set rT}) : ff @*^-1 C = q @* (f @*^-1 C).\n\n(*This lemma states that the kernel of a factor morphism is the image of the kernel of the original morphism under the quotienting morphism.*)\nLemma ker_factm : 'ker ff = q @* 'ker f.\n\n(*This lemma states that if the original morphism used to construct a factor morphism is injective, then the resulting factor morphism is also injective.*)\nLemma injm_factm : 'injm f -> 'injm ff.\n\n(*This lemma provides a biconditional statement, asserting that a factor morphism is injective if and only if the kernel of the original morphism is equal to the kernel of the quotienting morphism.*)\nLemma injm_factmP : reflect ('ker f = 'ker q) ('injm ff).\n\n(*This lemma states that the kernel of a factor morphism, when localized to the image of a subgroup under the quotienting morphism, is equal to the image of the localized kernel of the original morphism under the quotienting morphism.*)\nLemma ker_factm_loc (K : {group aT}) : 'ker_(q @* K) ff = q @* 'ker_K f.\n\nEnd FactorMorphism.\n\nPrenex Implicits factm.\n\nSection InverseMorphism.\n\nVariables aT rT : finGroupType.\nImplicit Types A B : {set aT}.\nImplicit Types C D : {set rT}.\nVariables (G : {group aT}) (f : {morphism G >-> rT}).\nHypothesis injf : 'injm f.\n\n(*This lemma states that the kernel of an injective group morphism is a subset of the kernel of the identity morphism on the same domain group.*)\nLemma invm_subker : 'ker f \\subset 'ker (idm G).\n\n(*This definition constructs the inverse of an injective group morphism. It is defined as a specific factor morphism where the original morphism acts as the quotienting map and the identity morphism acts as the map being factored, resulting in a morphism from the image of the original morphism back to its domain.*)\nDefinition invm := factm invm_subker (subxx _).\n\nCanonical invm_morphism := Eval hnf in [morphism of invm].\n\n(*This lemma states that for any element in the domain of an injective group morphism, applying the morphism and then its inverse yields the original element.*)\nLemma invmE : {in G, cancel f invm}.\n\n(*This lemma states that for any element in the image of an injective group morphism, applying the inverse morphism and then the original morphism yields the original element.*)\nLemma invmK : {in f @* G, cancel invm f}.\n\n(*This lemma states that the preimage of a set under an inverse group morphism is equal to the image of that set under the original injective group morphism.*)\nLemma morphpre_invm A : invm @*^-1 A = f @* A.\n\n(*This lemma states that for any subset of the domain of an injective group morphism, the image under the inverse morphism of the image of the set under the original morphism is the original set itself.*)\nLemma morphim_invm A : A \\subset G -> invm @* (f @* A) = A.\n\n(*This lemma states that the image of a set under an inverse group morphism is equal to the preimage of that set under the original injective group morphism.*)\nLemma morphim_invmE C : invm @* C = f @*^-1 C.\n\n(*This lemma states that an injective group morphism preserves the proper subset relation between two subsets of its domain when mapping them to their images.*)\nLemma injm_proper A B :\n A \\subset G -> B \\subset G -> (f @* A \\proper f @* B) = (A \\proper B).\n\n(*This lemma states that the inverse of an injective group morphism is also an injective group morphism.*)\nLemma injm_invm : 'injm invm.\n\n(*This lemma states that the kernel of the inverse of an injective group morphism is the trivial group containing only the identity element.*)\nLemma ker_invm : 'ker invm = 1.\n\n(*This lemma states that applying the inverse of an injective group morphism to the image of a group under that same morphism yields the original group.*)\nLemma im_invm : invm @* (f @* G) = G.\n\nEnd InverseMorphism.\n\nPrenex Implicits invm.\n\nSection InjFactm.\n\nVariables (gT aT rT : finGroupType) (D G : {group gT}).\nVariables (g : {morphism G >-> rT}) (f : {morphism D >-> aT}) (injf : 'injm f).\n\n(*This definition constructs a new group morphism, called the factorized morphism, by composing a given morphism with the inverse of an injective morphism. This frequently arises in factorization theorems.*)\nDefinition ifactm :=\n tag (domP [morphism of g \\o invm injf] (morphpre_invm injf G)).\n\n(*This lemma asserts that for any element in the domain, applying the factorized morphism to its image under the injective morphism yields the same result as applying the second, non-injective morphism to the original element.*)\nLemma ifactmE : {in D, forall x, ifactm (f x) = g x}.\n\n(*This lemma states that the image of a set under the composition of an injective morphism and the corresponding factorized morphism is equal to the image of that set under the original non-injective morphism.*)\nLemma morphim_ifactm (A : {set gT}) :\n A \\subset D -> ifactm @* (f @* A) = g @* A.\n\n(*This lemma states that the image of a group under the composition of an injective morphism and the corresponding factorized morphism is equal to the image of that group under the original non-injective morphism.*)\nLemma im_ifactm : G \\subset D -> ifactm @* (f @* G) = g @* G.\n\n(*This lemma states that the preimage of a set under the factorized morphism is equal to the image under the injective morphism of the preimage of the set under the original non-injective morphism.*)\nLemma morphpre_ifactm C : ifactm @*^-1 C = f @* (g @*^-1 C).\n\n(*This lemma states that the kernel of the factorized morphism is the image under the injective morphism of the kernel of the original non-injective morphism.*)\nLemma ker_ifactm : 'ker ifactm = f @* 'ker g.\n\n(*This lemma states that if a group morphism is injective, then the corresponding factorized morphism is also injective.*)\nLemma injm_ifactm : 'injm g -> 'injm ifactm.\n\nEnd InjFactm.\n\nSection ReflectProp.\n\nVariables aT rT : finGroupType.\n\nSection Defs.\n\nVariables (A : {set aT}) (B : {set rT}).\n\n(*This definition specifies a property for a function, indicating that it is morphic on a set if it preserves the group multiplication for all pairs of elements within that set.*)\nDefinition morphic (f : aT -> rT) :=\n [forall u in [predX A & A], f (u.1 * u.2) == f u.1 * f u.2].\n\n(*This definition specifies a property for a function between two sets, indicating that the image of the first set under the function is equal to the second set.*)\nDefinition isom f := f @: A^# == B^#.\n\n(*This definition specifies a property for a function, indicating that it is a 'morphic isomorphism' if it is both morphic, meaning it preserves the group operation, and its image is equal to the codomain set.*)\nDefinition misom f := morphic f && isom f.\n\n(*This definition specifies that two structured sets are isomorphic if there exists a function between them that is a surjective homomorphism.*)\nDefinition isog := [exists f : {ffun aT -> rT}, misom f].\n\nSection MorphicProps.\n\nVariable f : aT -> rT.\n\n(*This lemma provides a reflection property, connecting the boolean predicate that a function is morphic to the propositional statement that the function preserves the group operation for all elements in its domain set.*)\nLemma morphicP : reflect {in A &, {morph f : x y / x * y}} (morphic f).\n\n(*This definition constructs a formal group morphism object from a function and a proof that the function is morphic, meaning it preserves the group structure.*)\nDefinition morphm of morphic f := f : aT -> FinGroup.sort rT.\n\n(*This lemma states that extracting the underlying function from a formal group morphism object yields the original function.*)\nLemma morphmE fM : morphm fM = f. \n\nCanonical morphm_morphism fM := @Morphism _ _ A (morphm fM) (morphicP fM).\n\nEnd MorphicProps.\n\n(*This lemma provides a reflection property, connecting the boolean predicate for a function being a 'morphic isomorphism' to the propositional statement that the function is both morphic and its image equals the target set.*)\nLemma misomP f : reflect {fM : morphic f & isom (morphm fM)} (misom f).\n\n(*This lemma states that if a function is a 'morphic isomorphism', which is a surjective homomorphism, then its domain and codomain sets are isomorphic.*)\nLemma misom_isog f : misom f -> isog.\n\n(*This lemma states that if a given group morphism, when restricted to a subset, acts as an isomorphism onto another set, then the two sets are proven to be isomorphic.*)\nLemma isom_isog (D : {group aT}) (f : {morphism D >-> rT}) :\n A \\subset D -> isom f -> isog.\n\n(*This lemma states that if two sets are isomorphic, then there exists a specific group morphism that acts as an isomorphism from the first set onto the second.*)\nLemma isog_isom : isog -> {f : {morphism A >-> rT} | isom f}.\n\nEnd Defs.\n\nInfix \"\\isog\" := isog.\n\nArguments isom_isog [A B D].\n\nSection Main.\n\nVariables (G : {group aT}) (H : {group rT}).\n\n(*This lemma provides a reflection property, connecting the boolean predicate for a morphism being an isomorphism between two groups to the propositional statement that the morphism is both injective and its image is the codomain group.*)\nLemma isomP (f : {morphism G >-> rT}) :\n reflect ('injm f /\\ f @* G = H) (isom G H f).\n\n(*This lemma provides a reflection property, connecting the boolean predicate that two groups are isomorphic to the propositional statement that there exists a morphism between them which is both injective and surjective.*)\nLemma isogP :\n reflect (exists2 f : {morphism G >-> rT}, 'injm f & f @* G = H) (G \\isog H).\n\nVariable f : {morphism G >-> rT}.\nHypothesis isoGH : isom G H f.\n\n(*This lemma states that any group morphism that is an isomorphism between two groups must be injective.*)\nLemma isom_inj : 'injm f. \n(*This lemma states that for any group morphism that is an isomorphism between two groups, the image of the domain group is equal to the codomain group.*)\nLemma isom_im : f @* G = H. \n(*This lemma states that if two finite groups are isomorphic, then they have the same number of elements.*)\nLemma isom_card : #|G| = #|H|.\n\n(*This lemma states that if a morphism is an isomorphism from one group to another, then the codomain group is a subset of the image of the domain group under the morphism.*)\nLemma isom_sub_im : H \\subset f @* G. \n(*This definition constructs the inverse morphism of a given group isomorphism. The resulting morphism maps the codomain group back to the domain group.*)\nDefinition isom_inv := restrm isom_sub_im (invm isom_inj).\n\nEnd Main.\n\nVariables (G : {group aT}) (f : {morphism G >-> rT}).\n\n(*This lemma states that if a morphism acts as an isomorphism from a subgroup to another group, then the image of the subgroup under this morphism is exactly the codomain group.*)\nLemma morphim_isom (H : {group aT}) (K : {group rT}) :\n H \\subset G -> isom H K f -> f @* H = K.\n\n(*This lemma establishes that an injective group morphism acts as an isomorphism between a subset of its domain and another set, provided that the image of the subset under the morphism is exactly the target set.*)\nLemma sub_isom (A : {set aT}) (C : {set rT}) :\n A \\subset G -> f @* A = C -> 'injm f -> isom A C f.\n\n(*This lemma states that if a group morphism is injective, then any subgroup of its domain is isomorphic to its image under the morphism.*)\nLemma sub_isog (A : {set aT}) : A \\subset G -> 'injm f -> isog A (f @* A).\n\n(*This lemma states that if a function is an isomorphism from a first group to a second group, and this function maps a subset of the first group onto a third group, then the restriction of the function to that subset is an isomorphism between the subset, viewed as a group, and the third group.*)\nLemma restr_isom_to (A : {set aT}) (C R : {group rT}) (sAG : A \\subset G) :\n f @* A = C -> isom G R f -> isom A C (restrm sAG f).\n\n(*This lemma states that if a function is an isomorphism from a first group to a second group, then its restriction to any subgroup of the first group is an isomorphism between that subgroup and its image under the function.*)\nLemma restr_isom (A : {group aT}) (R : {group rT}) (sAG : A \\subset G) :\n isom G R f -> isom A (f @* A) (restrm sAG f).\n\nEnd ReflectProp.\n\nArguments isom {_ _} _%_g _%_g _.\nArguments morphic {_ _} _%_g _.\nArguments misom _ _ _%_g _%_g _.\nArguments isog {_ _} _%_g _%_g.\n\nArguments morphicP {aT rT A f}.\nArguments misomP {aT rT A B f}.\nArguments isom_isog [aT rT A B D].\nArguments isomP {aT rT G H f}.\nArguments isogP {aT rT G H}.\nPrenex Implicits morphm.\n(*This notation provides an infix symbol for the predicate indicating that two groups are isomorphic.*)\nNotation \"x \\isog y\":= (isog x y).\n\nSection Isomorphisms.\n\nVariables gT hT kT : finGroupType.\nVariables (G : {group gT}) (H : {group hT}) (K : {group kT}).\n\n(*This lemma states that the identity morphism on any group is an isomorphism from that group to itself.*)\nLemma idm_isom : isom G G (idm G).\n\n(*This lemma states that the group isomorphism relation is reflexive, meaning any group is isomorphic to itself.*)\nLemma isog_refl : G \\isog G. \n\n(*This lemma states that if two finite groups are isomorphic, then their cardinalities are equal.*)\nLemma card_isog : G \\isog H -> #|G| = #|H|.\n\n(*This lemma states that if two groups are isomorphic, then the property of being an abelian group is equivalent for both.*)\nLemma isog_abelian : G \\isog H -> abelian G = abelian H.\n\n(*This lemma states that any two trivial groups are isomorphic.*)\nLemma trivial_isog : G :=: 1 -> H :=: 1 -> G \\isog H.\n\n(*This lemma states that if two groups are isomorphic, then the property of being a trivial group is equivalent for both.*)\nLemma isog_eq1 : G \\isog H -> (G :==: 1) = (H :==: 1).\n\n(*This lemma states that if a function is an isomorphism from a first group to a second group, then its inverse function is an isomorphism from the second group to the first group.*)\nLemma isom_sym (f : {morphism G >-> hT}) (isoGH : isom G H f) :\n isom H G (isom_inv isoGH).\n\n(*This lemma states that the group isomorphism relation is symmetric; if a first group is isomorphic to a second group, then the second group is isomorphic to the first.*)\nLemma isog_symr : G \\isog H -> H \\isog G.\n\n(*This lemma states that the group isomorphism relation is transitive; if a first group is isomorphic to a second, and the second is isomorphic to a third, then the first group is isomorphic to the third.*)\nLemma isog_trans : G \\isog H -> H \\isog K -> G \\isog K.\n\n(*This lemma states that if two finite groups are isomorphic, they have the same number of conjugacy classes.*)\nLemma nclasses_isog : G \\isog H -> #|classes G| = #|classes H|.\n\nEnd Isomorphisms.\n\nSection IsoBoolEquiv.\n\nVariables gT hT kT : finGroupType.\nVariables (G : {group gT}) (H : {group hT}) (K : {group kT}).\n\n(*This lemma states that the boolean value indicating whether a first group is isomorphic to a second group is equal to the boolean value indicating whether the second group is isomorphic to the first.*)\nLemma isog_sym : (G \\isog H) = (H \\isog G).\n\n(*This lemma states that if a first group is isomorphic to a second group, then the boolean value indicating that the first group is isomorphic to a third group is equal to the boolean value indicating that the second group is isomorphic to the third group.*)\nLemma isog_transl : G \\isog H -> (G \\isog K) = (H \\isog K).\n\n(*This lemma states that if a first group is isomorphic to a second group, then the boolean value indicating that a third group is isomorphic to the first group is equal to the boolean value indicating that the third group is isomorphic to the second group.*)\nLemma isog_transr : G \\isog H -> (K \\isog G) = (K \\isog H).\n\nEnd IsoBoolEquiv.\n\nSection Homg.\n\nImplicit Types rT gT aT : finGroupType.\n\n(*This definition introduces a predicate that is true if a given set is the homomorphic image of another given set, where both sets are endowed with a group structure.*)\nDefinition homg rT aT (C : {set rT}) (D : {set aT}) :=\n [exists (f : {ffun aT -> rT} | morphic D f), f @: D == C].\n\n(*This lemma provides a reflection principle, stating that a first set is a homomorphic image of a second set if and only if there exists a group morphism from the second set whose image is equal to the first set.*)\nLemma homgP rT aT (C : {set rT}) (D : {set aT}) : \n reflect (exists f : {morphism D >-> rT}, f @* D = C) (homg C D).\n\n(*This lemma states that for any group morphism defined on a domain, the image of any subset of that domain is a homomorphic image of that subset.*)\nLemma morphim_homg aT rT (A D : {set aT}) (f : {morphism D >-> rT}) :\n A \\subset D -> homg (f @* A) A.\n\n(*This lemma states that if a set is a homomorphic image of a finite group, then the cardinality of the set is less than or equal to the cardinality of the group.*)\nLemma leq_homg rT aT (C : {set rT}) (G : {group aT}) :\n homg C G -> #|C| <= #|G|.\n\n(*This lemma states that the homomorphic image relation is reflexive, meaning any group is a homomorphic image of itself.*)\nLemma homg_refl aT (A : {set aT}) : homg A A.\n\n(*This lemma states that the homomorphic image relation is transitive; if a first group is a homomorphic image of a second group, and the second is a homomorphic image of a third, then the first is a homomorphic image of the third.*)\nLemma homg_trans aT (B : {set aT}) rT (C : {set rT}) gT (G : {group gT}) :\n homg C B -> homg B G -> homg C G.\n\n(*This lemma states that two finite groups are isomorphic if and only if the first group is a homomorphic image of the second, and the cardinality of the second group is less than or equal to the cardinality of the first.*)\nLemma isogEcard rT aT (G : {group rT}) (H : {group aT}) :\n (G \\isog H) = (homg G H) && (#|H| <= #|G|).\n\n(*This lemma states that if a first group is isomorphic to a second group, then the first group is a homomorphic image of the second group.*)\nLemma isog_hom rT aT (G : {group rT}) (H : {group aT}) : G \\isog H -> homg G H.\n\n(*This lemma states that two finite groups are isomorphic if and only if each group is a homomorphic image of the other.*)\nLemma isogEhom rT aT (G : {group rT}) (H : {group aT}) :\n (G \\isog H) = homg G H && homg H G.\n\n(*This lemma states that if a first group is isomorphic to a second group, then the proposition that the first group is a homomorphic image of a third group is equivalent to the proposition that the second group is a homomorphic image of the same third group.*)\nLemma eq_homgl gT aT rT (G : {group gT}) (H : {group aT}) (K : {group rT}) :\n G \\isog H -> homg G K = homg H K.\n\n(*This lemma states that if a first group is isomorphic to a second group, then the proposition that a third group is a homomorphic image of the first group is equivalent to the proposition that the third group is a homomorphic image of the second group.*)\nLemma eq_homgr gT rT aT (G : {group gT}) (H : {group rT}) (K : {group aT}) :\n G \\isog H -> homg K G = homg K H.\n\nEnd Homg.\n\nArguments homg _ _ _%_g _%_g.\n(*This notation provides an infix symbol for the predicate indicating that a first group is a homomorphic image of a second group.*)\nNotation \"G \\homg H\" := (homg G H)\n (at level 70, no associativity) : group_scope.\n\nArguments homgP {rT aT C D}.\n\nSection SubMorphism.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\nCanonical sgval_morphism := Morphism (@sgvalM _ G).\nCanonical subg_morphism := Morphism (@subgM _ G).\n\n(*This lemma states that the function that maps a subgroup to its underlying set of elements is an injective morphism.*)\nLemma injm_sgval : 'injm sgval.\n\n(*This lemma states that the canonical coercion from a subgroup structure to a group structure is an injective morphism.*)\nLemma injm_subg : 'injm (subg G).\n\nHint Resolve injm_sgval injm_subg : core.\n\n(*This lemma states that the kernel of the subgroup evaluation isomorphism, which maps a formal group type to its corresponding subgroup, is the trivial subgroup.*)\nLemma ker_sgval : 'ker sgval = 1. \n(*This lemma states that the kernel of the subgroup constructor isomorphism, which maps a subgroup to its formal group type representation, is the trivial subgroup.*)\nLemma ker_subg : 'ker (subg G) = 1. \n\n(*This lemma states that the image of a subgroup under the subgroup constructor isomorphism is the entire formal group type that represents the subgroup.*)\nLemma im_subg : subg G @* G = [subg G].\n\n(*This lemma states that the image of any subgroup of a formal group type under the subgroup evaluation morphism is a subgroup of the original group structure.*)\nLemma sgval_sub A : sgval @* A \\subset G.\n\n(*This lemma states that for any subgroup of a formal group type, applying the subgroup evaluation morphism followed by the subgroup constructor morphism results in the original subgroup.*)\nLemma sgvalmK A : subg G @* (sgval @* A) = A.\n\n(*This lemma states that for any set of elements that forms a subgroup, the set of elements of the subgroup generated by this set is identical to the original set.*)\nLemma subgmK (A : {set gT}) : A \\subset G -> sgval @* (subg G @* A) = A.\n\n(*This lemma states that the image of a formal group type under the subgroup evaluation isomorphism is the original subgroup from which it was constructed.*)\nLemma im_sgval : sgval @* [subg G] = G.\n\n(*This lemma states that a subgroup is isomorphic to its formal group type representation via the subgroup constructor morphism.*)\nLemma isom_subg : isom G [subg G] (subg G).\n\n(*This lemma states that a formal group type is isomorphic to its originating subgroup via the subgroup evaluation morphism.*)\nLemma isom_sgval : isom [subg G] G sgval.\n\n(*This theorem asserts that a group is isomorphic to its canonical subgroup representation.*)\nLemma isog_subg : isog G [subg G].\n\nEnd SubMorphism.\n\nArguments sgvalmK {gT G} A.\nArguments subgmK {gT G} [A] sAG.", - "fingroup.presentation": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq.\nFrom mathcomp Require Import fintype finset fingroup morphism.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nModule Presentation.\n\nSection Presentation.\n\nImplicit Types gT rT : finGroupType.\nImplicit Type vT : finType. \n\n(*An inductive type representing the syntactic structure of abstract terms in group theory. These terms can represent constants, an identity element, an inverse of another term, a term raised to a natural number power, the product of two terms, the conjugation of one term by another, or the commutator of two terms.*)\nInductive term :=\n | Cst of nat\n | Idx\n | Inv of term\n | Exp of term & nat\n | Mul of term & term\n | Conj of term & term\n | Comm of term & term.\n\n(*This function recursively evaluates a group-theoretic term within a specific finite group. It takes a finite sequence of group elements, which serve as constants, and a term, and computes the corresponding group element by interpreting the term's structure, such as multiplication, inversion, or commutation, as operations within the group.*)\nFixpoint eval {gT} e t : gT :=\n match t with\n | Cst i => nth 1 e i\n | Idx => 1\n | Inv t1 => (eval e t1)^-1\n | Exp t1 n => eval e t1 ^+ n\n | Mul t1 t2 => eval e t1 * eval e t2\n | Conj t1 t2 => eval e t1 ^ eval e t2\n | Comm t1 t2 => [~ eval e t1, eval e t2]\n end.\n\n(*An inductive type for representing logical formulas about group-theoretic terms. A formula can be either an equality between two terms or the logical conjunction of two other formulas.*)\nInductive formula := Eq2 of term & term | And of formula & formula.\n(*This definition constructs a formula asserting that a given group-theoretic term is equal to the identity element.*)\nDefinition Eq1 s := Eq2 s Idx.\n(*This definition constructs a formula that represents the conjunction of two equalities, where two given terms are both asserted to be equal to a third term.*)\nDefinition Eq3 s1 s2 t := And (Eq2 s1 t) (Eq2 s2 t).\n\n(*An inductive type used to accumulate equality constraints during formula evaluation. It can either represent the absence of a relation or a pending relation between two values of some finite type.*)\nInductive rel_type := NoRel | Rel vT of vT & vT.\n\n(*This function converts a relational constraint into a boolean value. If the constraint represents a pending relation between two values, it returns true if the values are equal and false otherwise. If there is no pending relation, it returns true.*)\nDefinition bool_of_rel r := if r is Rel vT v1 v2 then v1 == v2 else true.\nLocal Coercion bool_of_rel : rel_type >-> bool.\n\n(*This function combines a new pair of values with an existing relational constraint. If the existing constraint is empty, it creates a new constraint with the given pair. If the existing constraint already holds a pair of values, it creates a new constraint on pairs of values, combining the new pair with the old one.*)\nDefinition and_rel vT (v1 v2 : vT) r :=\n if r is Rel wT w1 w2 then Rel (v1, w1) (v2, w2) else Rel v1 v2.\n \n(*This function recursively processes a logical formula to build a cumulative relational constraint. It evaluates the terms within the formula using a given sequence of group elements and combines the resulting value pairs into a single relational constraint.*)\nFixpoint rel {gT} (e : seq gT) f r :=\n match f with\n | Eq2 s t => and_rel (eval e s) (eval e t) r\n | And f1 f2 => rel e f1 (rel e f2 r)\n end.\n\n(*An inductive type that describes the structure of a group presentation. A presentation can either terminate with a set of defining relations specified as a formula, or it can introduce a new generator and then continue with a subsequent presentation structure.*)\nInductive type := Generator of term -> type | Formula of formula.\n(*This definition is an identity function for group presentation types, primarily used to assist with type inference or to make type conversions explicit.*)\nDefinition Cast p : type := p. \nLocal Coercion Formula : formula >-> type.\n\n(*An inductive type that represents an evaluation environment for group presentations, consisting of both a finite set and a finite sequence of group elements.*)\nInductive env gT := Env of {set gT} & seq gT.\n(*This definition constructs a basic evaluation environment containing a single group element, represented as both a singleton set and a singleton sequence.*)\nDefinition env1 {gT} (x : gT : finType) := Env <[x]> [:: x].\n\n(*This function recursively defines the satisfaction condition for a group presentation. It checks whether a given family of environments, indexed over a finite type, satisfies the presentation's structure, either by verifying its defining relations or by extending the environment with new generators and checking the subsequent presentation.*)\nFixpoint sat gT vT B n (s : vT -> env gT) p :=\n match p with\n | Formula f =>\n [exists v, let: Env A e := s v in and_rel A B (rel (rev e) f NoRel)]\n | Generator p' =>\n let s' v := let: Env A e := s v.1 in Env (A <*> <[v.2]>) (v.2 :: e) in\n sat B n.+1 s' (p' (Cst n))\n end.\n\n(*This definition expresses the property that a target group is a homomorphic image of the group defined by a given presentation. It is defined by checking if the presentation is satisfied in the target group, starting with a single initial generator.*)\nDefinition hom gT (B : {set gT}) p := sat B 1 env1 (p (Cst 0)).\n(*This definition specifies that a given group is isomorphic to the group defined by a presentation. This is expressed universally, by stating that for any other group, the set of group homomorphisms from that group to the given group is equivalent to the set of ways that group satisfies the presentation.*)\nDefinition iso gT (B : {set gT}) p :=\n forall rT (H : {group rT}), (H \\homg B) = hom H p.\n\nEnd Presentation.\n\nEnd Presentation.\n\nImport Presentation.\n\nCoercion bool_of_rel : rel_type >-> bool.\nCoercion Eq1 : term >-> formula.\nCoercion Formula : formula >-> type.\n\nDeclare Custom Entry group_presentation.\n\n(*A notation for the product of two group-theoretic terms.*)\nNotation \"x * y\" := (Mul x y)\n (in custom group_presentation at level 40, left associativity).\n(*A notation representing a group-theoretic term raised to a natural number power.*)\nNotation \"x ^+ n\" := (Exp x n)\n (in custom group_presentation at level 29, n constr at level 28).\n(*A notation for the conjugation of a first group-theoretic term by a second group-theoretic term.*)\nNotation \"x ^ y\" := (Conj x y)\n (in custom group_presentation at level 30, right associativity).\n(*A postfix notation for the inverse of a group-theoretic term.*)\nNotation \"x ^-1\" := (Inv x) (in custom group_presentation at level 3).\n(*A notation representing the inverse of a group-theoretic term that has been raised to a natural number power.*)\nNotation \"x ^- n\" := (Inv (Exp x n))\n (in custom group_presentation at level 29, n constr at level 28).\n(*This notation defines a left-nested commutator of a sequence of two or more group presentation terms. The expression represents the result of repeatedly applying the commutator operation, where the commutator of the first two terms is taken, then the commutator of that result with the third term is taken, and so on.*)\nNotation \"[ ~ x1 , x2 , .. , xn ]\" := (Comm .. (Comm x1 x2) .. xn)\n (in custom group_presentation, x1, x2, xn at level 100).\n(*A notation for a formula asserting the equality of two group-theoretic terms.*)\nNotation \"x = y\" := (Eq2 x y) (in custom group_presentation at level 70).\n(*This notation defines a chained equality for three elements within a group presentation context, asserting that the first element is equal to the second, and the second is equal to the third.*)\nNotation \"x = y = z\" := (Eq3 x y z) (in custom group_presentation at level 70,\n y at next level).\n(*This notation provides a shorthand for expressing a list of relations within a group presentation, where the relations are separated by commas and together represent their logical conjunction.*)\nNotation \"r1 , r2 , .. , rn\" := (And .. (And r1 r2) .. rn)\n (in custom group_presentation at level 200).\n(*This notation provides a way to group expressions within a group presentation, ensuring that the enclosed expression is parsed with high priority.*)\nNotation \"( p )\" := p (in custom group_presentation, p at level 200).\n(*This notation defines the symbol '1' to represent the identity element within the context of a group presentation.*)\nNotation \"1\" := Idx (in custom group_presentation).\n(*This notation specifies that a single identifier within a group presentation context represents a generator of the group.*)\nNotation \"x\" := x (in custom group_presentation at level 0, x ident).\n\n(*This notation defines a group presentation by specifying a set of generators and a set of relations that these generators must satisfy.*)\nNotation \"x : p\" := (Generator (fun x => Cast p))\n (in custom group_presentation, x ident, p custom group_presentation at level 200).\n\nArguments hom _ _%_group_scope.\nArguments iso _ _%_group_scope.\n\n(*This notation asserts the existence of a group homomorphism from a given source group to the group defined by a presentation.*)\nNotation \"H \\homg 'Grp' p\" := (hom H p)\n (p at level 0, format \"H \\homg 'Grp' p\") : group_scope.\n\n(*This notation asserts the existence of a group isomorphism between a given source group and the group defined by a presentation.*)\nNotation \"H \\isog 'Grp' p\" := (iso H p)\n (p at level 0, format \"H \\isog 'Grp' p\") : group_scope.\n\n(*This notation asserts the existence of a group homomorphism from a given source group to the group defined by a specified set of generators and relations.*)\nNotation \"H \\homg 'Grp' ( x : p )\" := (hom H (fun x => Cast p))\n (x ident, p custom group_presentation at level 200,\n format \"'[hv' H '/ ' \\homg 'Grp' ( x : p ) ']'\") : group_scope.\n\n(*This notation asserts the existence of a group isomorphism between a given source group and the group defined by a specified set of generators and relations.*)\nNotation \"H \\isog 'Grp' ( x : p )\" := (iso H (fun x => Cast p))\n (x ident, p custom group_presentation at level 200,\n format \"'[hv' H '/ ' \\isog 'Grp' ( x : p ) ']'\") : group_scope.\n\nSection PresentationTheory.\n\nImplicit Types gT rT : finGroupType.\n\nImport Presentation.\n\n(*This lemma states that if a source group is isomorphic to the group defined by a given presentation, then there must also exist a group homomorphism from the source group to the presented group.*)\nLemma isoGrp_hom gT (G : {group gT}) p : G \\isog Grp p -> G \\homg Grp p.\n\n(*This lemma provides a criterion for establishing an isomorphism. It states that if a first group is isomorphic to a group defined by a presentation, then a second group is isomorphic to the first group if and only if the two groups have the same size and there exists a group homomorphism from the second group to the group defined by the presentation.*)\nLemma isoGrpP gT (G : {group gT}) p rT (H : {group rT}) :\n G \\isog Grp p -> reflect (#|H| = #|G| /\\ H \\homg Grp p) (H \\isog G).\n\n(*This lemma states that the existence of a group homomorphism is transitive. If there is a homomorphism from a first group to a second group, and a homomorphism from the second group to a group defined by a presentation, then there is also a homomorphism from the first group to the group defined by the presentation.*)\nLemma homGrp_trans rT gT (H : {set rT}) (G : {group gT}) p :\n H \\homg G -> G \\homg Grp p -> H \\homg Grp p.\n\n(*This lemma states that if two groups are isomorphic, then the property of admitting a homomorphism to a group defined by a given presentation is equivalent for both groups.*)\nLemma eq_homGrp gT rT (G : {group gT}) (H : {group rT}) p :\n G \\isog H -> (G \\homg Grp p) = (H \\homg Grp p).\n\n(*This lemma establishes the transitivity of group isomorphisms involving a presented group. It states that if a first group is isomorphic to a second group, and the second group is isomorphic to a group defined by a presentation, then the first group is also isomorphic to the group defined by that presentation.*)\nLemma isoGrp_trans gT rT (G : {group gT}) (H : {group rT}) p :\n G \\isog H -> H \\isog Grp p -> G \\isog Grp p.\n\n(*A tactic for proving that a first finite group is isomorphic to a second finite group, where the second group is known to be isomorphic to a group defined by a presentation. The tactic replaces the isomorphism goal with two subgoals: proving that the two finite groups have the same number of elements, and proving that there exists a group homomorphism from the first group to the presentation of the second group.*)\nLemma intro_isoGrp gT (G : {group gT}) p :\n G \\homg Grp p -> (forall rT (H : {group rT}), H \\homg Grp p -> H \\homg G) ->\n G \\isog Grp p.\n\nEnd PresentationTheory.", - "fingroup.action": "From mathcomp Require Import ssreflect ssrbool ssrfun ssrnotations eqtype.\nFrom mathcomp Require Import ssrnat div seq prime fintype bigop finset.\nFrom mathcomp Require Import fingroup morphism perm automorphism quotient.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope action_scope.\nDeclare Scope groupAction_scope.\n\nImport GroupScope.\n\nSection ActionDef.\n\nVariables (aT : finGroupType) (D : {set aT}) (rT : Type).\nImplicit Types a b : aT.\nImplicit Type x : rT.\n\n(*This definition captures the homomorphism property of a group action for a specific element of the target type. It asserts that acting by the product of two group elements yields the same result as acting by the first element and then successively by the second.*)\nDefinition act_morph to x := forall a b, to x (a * b) = to (to x a) b.\n\n(*This definition specifies the properties for a given function to be a valid partial group action. It requires two conditions: first, the function must be left-injective, meaning different elements of the acted-upon type produce distinct mapping functions. Second, for any element being acted upon, the action homomorphism property must hold for all acting elements within the specified domain of the action.*)\nDefinition is_action to :=\n left_injective to /\\ forall x, {in D &, act_morph to x}.\n\n(*This record bundles a function representing a group action with a proof that it satisfies the properties of being a valid action, such as left-injectivity and the homomorphism property.*)\nRecord action := Action {act :> rT -> aT -> rT; _ : is_action act}.\n\n(*This definition serves as a helper to construct an action record from a function that is already known to satisfy the action properties. It takes the function and its proof of being an action and packages them into the action structure.*)\nDefinition clone_action to :=\n let: Action _ toP := to return {type of Action for to} -> action in\n fun k => k toP.\n\nEnd ActionDef.\n\nDelimit Scope action_scope with act.\nBind Scope action_scope with action.\nArguments act_morph {aT rT%_type} to x%_g.\nArguments is_action {aT} D%_g {rT} to.\nArguments act {aT D%_g rT%_type} to%_act x%_g a%_g : rename.\nArguments clone_action [aT D%_g rT%_type to%_act] _.\n\n(*This notation defines a type for a partial group action of a finite group on a given type. The action is defined for a subset of the group, which is specified as a canonical set associated with the group type.*)\nNotation \"{ 'action' aT &-> T }\" := (action [set: aT] T)\n (format \"{ 'action' aT &-> T }\") : type_scope.\n\n(*This notation provides a convenient way to create an action structure from a function, automatically inferring the proof that the function indeed constitutes a valid action.*)\nNotation \"[ 'action' 'of' to ]\" := (clone_action (@Action _ _ _ to))\n (format \"[ 'action' 'of' to ]\") : form_scope.\n\n(*This definition retrieves the domain of a group action, which is the subset of group elements for which the action is defined.*)\nDefinition act_dom aT D rT of @action aT D rT := D.\n\nSection TotalAction.\n\nVariables (aT : finGroupType) (rT : Type) (to : rT -> aT -> rT).\nHypotheses (to1 : to^~ 1 =1 id) (toM : forall x, act_morph to x).\n\n(*This lemma states that a function from a type to a group of transformations on that type constitutes a valid total group action if acting by the identity element is the identity transformation and the action homomorphism property holds for all elements.*)\nLemma is_total_action : is_action setT to.\n\n(*This definition creates an action structure for a total group action, where the action is defined for all elements of the acting group. It bundles the action function with a proof that it is a valid total action.*)\nDefinition TotalAction := Action is_total_action.\n\nEnd TotalAction.\n\nSection ActionDefs.\n\nVariables (aT aT' : finGroupType) (D : {set aT}) (D' : {set aT'}).\n\n(*This definition specifies the property of a function being a morphism between two group actions. It asserts that for any element of the source type and any element of the acting group, applying the action and then the function is equivalent to first applying the function and then applying the corresponding action in the target structure, mediated by a group homomorphism.*)\nDefinition morph_act rT rT' (to : action D rT) (to' : action D' rT') f fA :=\n forall x a, f (to x a) = to' (f x) (fA a).\n\nVariable rT : finType. \nImplicit Type to : action D rT.\nImplicit Type A : {set aT}.\nImplicit Type S : {set rT}.\n\n(*This definition extends a partial group action to a total function. For a group element within the action's domain, it applies the corresponding transformation; for an element outside the domain, it acts as the identity transformation.*)\nDefinition actm to a := if a \\in D then to^~ a else id.\n\n(*This definition lifts a group action on individual elements to an action on sets of elements. It computes the set of all results obtained by applying the action of a given group element to each element in an input set.*)\nDefinition setact to S a := [set to x a | x in S].\n\n(*This definition computes the orbit of an element under a group action. The orbit is the set of all elements that can be reached from the given starting element by applying the action of any group element from a specified subset of the acting group.*)\nDefinition orbit to A x := to x @: A.\n\n(*This definition identifies the set of group elements from a given subset that transform a specific starting element into a specific target element under the group action.*)\nDefinition amove to A x y := [set a in A | to x a == y].\n\n(*This definition computes the set of fixed points of a group action with respect to a given subset of the acting group. An element is a fixed point if it remains unchanged by the action of every group element in that subset.*)\nDefinition afix to A := [set x | A \\subset [set a | to x a == x]].\n\n(*This definition computes the stabilizer of a set of elements under a group action. The stabilizer is the set of group elements from the action's domain that leave every element of the input set unchanged.*)\nDefinition astab S to := D :&: [set a | S \\subset [set x | to x a == x]].\n\n(*This definition computes the subset of the action's domain that maps a given set into itself. It identifies all group elements in the domain of the action which, when acting on any element of the set, produce a result that is also within that set.*)\nDefinition astabs S to := D :&: [set a | S \\subset to^~ a @^-1: S].\n\n(*This definition determines whether a subset of the acting group stabilizes a given set of elements. It holds true if for every group element in the subset, its action maps the given set to itself, meaning an element is in the set if and only if its transformation by the group element is also in the set.*)\nDefinition acts_on A S to := {in A, forall a x, (to x a \\in S) = (x \\in S)}.\n\n(*This definition checks if a group action, restricted to a subset of the acting group, is transitive on a given set. It holds if there exists an element in the set whose orbit under the action covers the entire set.*)\nDefinition atrans A S to := S \\in orbit to A @: S.\n\n(*This definition checks if a group action is faithful on a given set. An action is faithful if the kernel of the action, restricted to a given subset of the acting group, contains only the identity element.*)\nDefinition faithful A S to := A :&: astab S to \\subset [1].\n\nEnd ActionDefs.\n\nArguments setact {aT D%_g rT} to%_act S%_g a%_g.\nArguments orbit {aT D%_g rT} to%_act A%_g x%_g.\nArguments amove {aT D%_g rT} to%_act A%_g x%_g y%_g.\nArguments afix {aT D%_g rT} to%_act A%_g.\nArguments astab {aT D%_g rT} S%_g to%_act.\nArguments astabs {aT D%_g rT} S%_g to%_act.\nArguments acts_on {aT D%_g rT} A%_g S%_g to%_act.\nArguments atrans {aT D%_g rT} A%_g S%_g to%_act.\nArguments faithful {aT D%_g rT} A%_g S%_g to%_act.\n\n(*This notation represents the lifting of a group action on elements to an action on sets of elements. Applying this notation to an action function results in a new function that takes a set and a group element and returns the set transformed by the action.*)\nNotation \"to ^*\" := (setact to) : function_scope.\n\nPrenex Implicits orbit amove.\n\n(*This notation represents the set of elements that are fixed points for a group action under a given subset of the acting group. An element is a fixed point if it remains unchanged by the action of every group element in the specified subset.*)\nNotation \"''Fix_' to ( A )\" := (afix to A)\n (at level 8, to at level 2, format \"''Fix_' to ( A )\") : group_scope.\n\n(*This is a notation variant for computing the set of fixed points of a group action under a given subset of the acting group, provided for parsing convenience.*)\nNotation \"''Fix_' ( to ) ( A )\" := 'Fix_to(A)\n (at level 8, only parsing) : group_scope.\n\n(*This notation represents the set of elements within a given set that are fixed points of a group action under a subset of the acting group. It computes the intersection of the given set and the set of all fixed points.*)\nNotation \"''Fix_' ( S | to ) ( A )\" := (S :&: 'Fix_to(A))\n (at level 8, format \"''Fix_' ( S | to ) ( A )\") : group_scope.\n\n(*This notation represents the set of fixed points for the action of a single group element. It identifies all elements that remain unchanged when acted upon by the specified group element.*)\nNotation \"''Fix_' to [ a ]\" := ('Fix_to([set a]))\n (at level 8, to at level 2, format \"''Fix_' to [ a ]\") : group_scope.\n\n(*This notation computes the set of elements within a given set that are fixed points for the action of a single group element. It is the intersection of the given set with the fixed points of that element.*)\nNotation \"''Fix_' ( S | to ) [ a ]\" := (S :&: 'Fix_to[a])\n (at level 8, format \"''Fix_' ( S | to ) [ a ]\") : group_scope.\n\n(*This notation represents the stabilizer of a set of elements under a group action. It computes the set of all group elements from the action's domain that leave every element of the input set unchanged.*)\nNotation \"''C' ( S | to )\" := (astab S to)\n (format \"''C' ( S | to )\") : group_scope.\n\n(*This notation computes the intersection of a given subset of the group with the stabilizer of a set. It identifies the elements in the given subset that fix every element of the set.*)\nNotation \"''C_' A ( S | to )\" := (A :&: 'C(S | to))\n (format \"''C_' A ( S | to )\") : group_scope.\n(*This is a notation variant for computing the intersection of a subset of a group with the stabilizer of a set, provided for parsing convenience.*)\nNotation \"''C_' ( A ) ( S | to )\" := 'C_A(S | to) (only parsing) : group_scope.\n\n(*This notation represents the stabilizer of a single element under a group action. It computes the set of all group elements from the action's domain that leave the specified element unchanged.*)\nNotation \"''C' [ x | to ]\" := ('C([set x] | to))\n (format \"''C' [ x | to ]\") : group_scope.\n\n(*This notation defines the set of elements in a given set `A` that fix a specific element `x` under a group action `to`.*)\nNotation \"''C_' A [ x | to ]\" := (A :&: 'C[x | to])\n (format \"''C_' A [ x | to ]\") : group_scope.\n(*This notation, used for parsing, defines the set of elements in a given set `A` that fix a specific element `x` under a group action `to`.*)\nNotation \"''C_' ( A ) [ x | to ]\" := 'C_A[x | to] (only parsing) : group_scope.\n\n(*This notation defines the normalizer of a set `S` under a group action `to`, which is the set of all acting elements that leave the set `S` invariant.*)\nNotation \"''N' ( S | to )\" := (astabs S to)\n (format \"''N' ( S | to )\") : group_scope.\n\n(*This notation defines the set of elements in a given set `A` that leave another set `S` invariant under a group action `to`.*)\nNotation \"''N_' A ( S | to )\" := (A :&: 'N(S | to))\n (format \"''N_' A ( S | to )\") : group_scope.\n\n(*This notation defines a proposition asserting that a set of group elements `A` acts on a set `S` under a group action `to`, which is true if every element of `A` maps `S` to itself.*)\nNotation \"[ 'acts' A , 'on' S | to ]\" := (A \\subset pred_of_set 'N(S | to))\n (format \"[ 'acts' A , 'on' S | to ]\") : form_scope.\n\n(*This notation defines the type of actions of a set of group elements `A` on a set `S` under a group action `to`.*)\nNotation \"{ 'acts' A , 'on' S | to }\" := (acts_on A S to)\n (format \"{ 'acts' A , 'on' S | to }\") : type_scope.\n\n(*This notation defines a proposition asserting that a set of group elements `A` acts transitively on a set `S` under a group action `to`, meaning for any pair of elements in `S`, one can be mapped to the other by an element from `A`.*)\nNotation \"[ 'transitive' A , 'on' S | to ]\" := (atrans A S to)\n (format \"[ 'transitive' A , 'on' S | to ]\") : form_scope.\n\n(*This notation defines a proposition asserting that a set of group elements `A` acts faithfully on a set `S` under a group action `to`, which means that no two distinct elements of `A` produce the same permutation of the elements of `S`.*)\nNotation \"[ 'faithful' A , 'on' S | to ]\" := (faithful A S to)\n (format \"[ 'faithful' A , 'on' S | to ]\") : form_scope.\n\nSection RawAction.\n\nVariables (aT : finGroupType) (D : {set aT}) (rT : finType) (to : action D rT).\n\nImplicit Types (a : aT) (x y : rT) (A B : {set aT}) (S T : {set rT}).\n\n(*This lemma states that a group action is left-injective. This means that if two elements from the acted-upon set are transformed in the same way by every element of the acting group, then those two elements must be identical.*)\nLemma act_inj : left_injective to. \nArguments act_inj : clear implicits.\n\n(*This lemma states that for any given element `x` of the set being acted upon, the function mapping an element of the acting group to the result of its action on `x` is a group morphism.*)\nLemma actMin x : {in D &, act_morph to x}.\n\n(*This lemma states that for any element `a` in the acting group, the action homomorphism applied to `a` is functionally equivalent to the permutation of the acted-upon set induced by `a`.*)\nLemma actmEfun a : a \\in D -> actm to a = to^~ a.\n\n(*This lemma states that for any element `a` in the acting group, the permutation resulting from the action homomorphism applied to `a` is pointwise equal to the permutation induced by the action of `a`.*)\nLemma actmE a : a \\in D -> actm to a =1 to^~ a.\n\n(*This lemma states that the action of a group element `a` on a set `S` results in a new set containing the images of all elements of `S` under the action of `a`.*)\nLemma setactE S a : to^* S a = [set to x a | x in S].\n\n(*This lemma states that if an element `x` belongs to a set `S`, then the element resulting from the action of a group element `a` on `x` will belong to the set resulting from the action of `a` on `S`.*)\nLemma mem_setact S a x : x \\in S -> to x a \\in to^* S a.\n\n(*This lemma states that the action of a group element on a finite set preserves the cardinality of that set.*)\nLemma card_setact S a : #|to^* S a| = #|S|.\n\n(*This lemma states that the induced action on the power set of a given set is a valid group action.*)\nLemma setact_is_action : is_action D to^*.\n\nCanonical set_action := Action setact_is_action.\n\n(*This lemma states that the orbit of an element `x` under the action of a set of group elements `A` is the set of all elements that can be reached from `x` by applying an action from an element in `A`.*)\nLemma orbitE A x : orbit to A x = to x @: A. \n\n(*This lemma provides a criterion for an element `y` to be in the orbit of another element `x` under the action of a set of group elements `A`. It states that `y` is in the orbit if and only if there exists some element in `A` that maps `x` to `y`.*)\nLemma orbitP A x y :\n reflect (exists2 a, a \\in A & to x a = y) (y \\in orbit to A x).\n\n(*This lemma states that for any element `a` in a set of acting group elements `A`, the result of applying the action of `a` to an element `x` is a member of the orbit of `x` under `A`.*)\nLemma mem_orbit A x a : a \\in A -> to x a \\in orbit to A x.\n\n(*This lemma provides a criterion for an element `x` to be a fixed point under the action of a set of group elements `A`. It states that `x` is a fixed point if and only if every element in `A` leaves `x` unchanged.*)\nLemma afixP A x : reflect (forall a, a \\in A -> to x a = x) (x \\in 'Fix_to(A)).\n\n(*This lemma states that if a set of group elements `A` is a subset of another set `B`, then the set of elements fixed by all actions in `B` is a subset of the elements fixed by all actions in `A`.*)\nLemma afixS A B : A \\subset B -> 'Fix_to(B) \\subset 'Fix_to(A).\n\n(*This lemma states that the set of elements fixed by the union of two sets of group elements `A` and `B` is the same as the intersection of the sets of elements fixed individually by `A` and `B`.*)\nLemma afixU A B : 'Fix_to(A :|: B) = 'Fix_to(A) :&: 'Fix_to(B).\n\n(*This lemma provides a criterion for an element `x` to be a fixed point under the action of a single group element `a`. It states that `x` is a fixed point if and only if the action of `a` on `x` leaves `x` unchanged.*)\nLemma afix1P a x : reflect (to x a = x) (x \\in 'Fix_to[a]).\n\n(*This lemma states that the pointwise stabilizer of a set `S` under a group action `to` is defined within the domain `D` of the action, so intersecting this stabilizer with `D` is redundant.*)\nLemma astabIdom S : 'C_D(S | to) = 'C(S | to).\n\n(*This lemma asserts that the set of group elements that fix every element in a given set `S` (the pointwise stabilizer) is a subset of the domain of the group action.*)\nLemma astab_dom S : {subset 'C(S | to) <= D}.\n\n(*This lemma states that if a group element `a` belongs to the pointwise stabilizer of a set `S`, then the action of `a` on any element `x` from `S` will leave `x` unchanged.*)\nLemma astab_act S a x : a \\in 'C(S | to) -> x \\in S -> to x a = x.\n\n(*This lemma states that if a set `S1` is a subset of another set `S2`, then the set of group elements that pointwise-stabilize `S2` is a subset of the group elements that pointwise-stabilize `S1`.*)\nLemma astabS S1 S2 : S1 \\subset S2 -> 'C(S2 | to) \\subset 'C(S1 | to).\n\n(*This lemma states that the setwise stabilizer (or normalizer) of a set `S` under a group action `to` is defined within the domain `D` of the action, so intersecting this stabilizer with `D` is redundant.*)\nLemma astabsIdom S : 'N_D(S | to) = 'N(S | to).\n\n(*This lemma asserts that the set of group elements that leave a given set `S` invariant (the setwise stabilizer) is a subset of the domain of the group action.*)\nLemma astabs_dom S : {subset 'N(S | to) <= D}.\n\n(*This lemma states that if a group element `a` belongs to the setwise stabilizer of a set `S`, then for any element `x`, its image under the action of `a` is in `S` if and only if `x` itself is in `S`.*)\nLemma astabs_act S a x : a \\in 'N(S | to) -> (to x a \\in S) = (x \\in S).\n\n(*This lemma states that the centralizer of a set under a group action is a subset of the stabilizer of that same set.*)\nLemma astab_sub S : 'C(S | to) \\subset 'N(S | to).\n\n(*This lemma states that the stabilizer of the complement of a set under a group action is equal to the stabilizer of the original set.*)\nLemma astabsC S : 'N(~: S | to) = 'N(S | to).\n\n(*This lemma states that the intersection of the stabilizers of two sets under a group action is a subset of the stabilizer of the intersection of those two sets.*)\nLemma astabsI S T : 'N(S | to) :&: 'N(T | to) \\subset 'N(S :&: T | to).\n\n(*This lemma states that if an element belongs to the stabilizer of a set, then the action of that element on the set leaves the set unchanged.*)\nLemma astabs_setact S a : a \\in 'N(S | to) -> to^* S a = S.\n\n(*This lemma states that the pointwise centralizer of a set under the induced set action is equal to the stabilizer of that set under the original point action.*)\nLemma astab1_set S : 'C[S | set_action] = 'N(S | to).\n\n(*This lemma states that the stabilizer of a singleton set containing an element is equal to the pointwise stabilizer of that element.*)\nLemma astabs_set1 x : 'N([set x] | to) = 'C[x | to].\n\n(*This lemma states that if a set of elements acts on another set, then the acting set must be a subset of the domain of the action.*)\nLemma acts_dom A S : [acts A, on S | to] -> A \\subset D.\n\n(*This lemma states that a propositional assertion that a set acts on another set implies the truth of the corresponding boolean predicate.*)\nLemma acts_act A S : [acts A, on S | to] -> {acts A, on S | to}.\n\n(*This lemma states that for a set of actors that is a subset of the action's domain, the condition that this set is a subset of the centralizer of a given set of points is equivalent to the condition that the set of points is a subset of the fixed points of the set of actors.*)\nLemma astabCin A S :\n A \\subset D -> (A \\subset 'C(S | to)) = (S \\subset 'Fix_to(A)).\n\nSection ActsSetop.\n\nVariables (A : {set aT}) (S T : {set rT}).\nHypotheses (AactS : [acts A, on S | to]) (AactT : [acts A, on T | to]).\n\n(*This lemma states that the centralizer of the union of two sets is equal to the intersection of their respective centralizers.*)\nLemma astabU : 'C(S :|: T | to) = 'C(S | to) :&: 'C(T | to).\n\n(*This lemma states that the intersection of the stabilizers of two sets is a subset of the stabilizer of their union.*)\nLemma astabsU : 'N(S | to) :&: 'N(T | to) \\subset 'N(S :|: T | to).\n\n(*This lemma states that the intersection of the stabilizers of two sets is a subset of the stabilizer of their set difference.*)\nLemma astabsD : 'N(S | to) :&: 'N(T | to) \\subset 'N(S :\\: T| to).\n\n(*This lemma states that if a set of actors acts on two separate sets, it also acts on their intersection.*)\nLemma actsI : [acts A, on S :&: T | to].\n\n(*This lemma states that if a set of actors acts on two separate sets, it also acts on their union.*)\nLemma actsU : [acts A, on S :|: T | to].\n\n(*This lemma states that if a set of actors acts on two separate sets, it also acts on their set difference.*)\nLemma actsD : [acts A, on S :\\: T | to].\n\nEnd ActsSetop.\n\n(*This lemma states that if a set is stable under a group action, then any element in the orbit of a point from that set must also belong to the set.*)\nLemma acts_in_orbit A S x y :\n [acts A, on S | to] -> y \\in orbit to A x -> x \\in S -> y \\in S.\n\n(*This lemma states that if a group action on a set is faithful for a given set of actors, it is also faithful for any subset of those actors.*)\nLemma subset_faithful A B S :\n B \\subset A -> [faithful A, on S | to] -> [faithful B, on S | to].\n\nSection Reindex.\n\nVariables (vT : Type) (idx : vT) (op : Monoid.com_law idx) (S : {set rT}).\n\n(*This lemma states that for an element in the stabilizer of a set, a commutative big operator applied to a function over that set remains unchanged if the function's argument is transformed by the action of that element.*)\nLemma reindex_astabs a F : a \\in 'N(S | to) ->\n \\big[op/idx]_(i in S) F i = \\big[op/idx]_(i in S) F (to i a).\n\n(*This lemma states that if a set of actors acts on a given set, then for any actor in that set, a commutative big operator applied to a function over the given set remains unchanged if the function's argument is transformed by the action of that actor.*)\nLemma reindex_acts A a F : [acts A, on S | to] -> a \\in A ->\n \\big[op/idx]_(i in S) F i = \\big[op/idx]_(i in S) F (to i a).\n\nEnd Reindex.\n\nEnd RawAction.\n\nArguments act_inj {aT D rT} to a [x1 x2] : rename.\n\n(*This notation defines a shorthand for the canonical lifting of a point-wise group action to an action on sets of points.*)\nNotation \"to ^*\" := (set_action to) : action_scope.\n\nArguments orbitP {aT D rT to A x y}.\nArguments afixP {aT D rT to A x}.\nArguments afix1P {aT D rT to a x}.\n\nArguments reindex_astabs [aT D rT] to [vT idx op S] a [F].\nArguments reindex_acts [aT D rT] to [vT idx op S A a F].\n\nSection PartialAction.\n\nVariables (aT : finGroupType) (D : {group aT}) (rT : finType).\nVariable to : action D rT.\n\nImplicit Types a : aT.\nImplicit Types x y : rT.\nImplicit Types A B : {set aT}.\nImplicit Types G H : {group aT}.\nImplicit Types S : {set rT}.\n\n(*This lemma states that the action of the identity element of a group on any element of a set leaves that element unchanged.*)\nLemma act1 x : to x 1 = x.\n\n(*This lemma states that for any element in the domain of the action, applying the action followed by the action of its inverse returns the original element.*)\nLemma actKin : {in D, right_loop invg to}.\n\n(*This lemma states that for any element in the domain of the action, applying the action of its inverse followed by the action of the element itself returns the original element.*)\nLemma actKVin : {in D, rev_right_loop invg to}.\n\n(*This lemma states that for any element in the domain of a group action, the action of its inverse on a set is equivalent to taking the preimage of that set under the action of the original element.*)\nLemma setactVin S a : a \\in D -> to^* S a^-1 = to^~ a @^-1: S.\n\n(*This lemma states that acting on an element by the i-th power of a group element is equivalent to iterating the action of that group element i times starting from the original element.*)\nLemma actXin x a i : a \\in D -> to x (a ^+ i) = iter i (to^~ a) x.\n\n(*This lemma states that the set of fixed points under the action of the identity element is the entire set.*)\nLemma afix1 : 'Fix_to(1) = setT.\n\n(*This lemma states that the set of points fixed by all elements of a group is identical to the set of points fixed by all elements of the underlying carrier set of that group.*)\nLemma afixD1 G : 'Fix_to(G^#) = 'Fix_to(G).\n\n(*This lemma states that any element is a member of its own orbit under a group action.*)\nLemma orbit_refl G x : x \\in orbit to G x.\n\nLocal Notation orbit_rel A := (fun x y => x \\in orbit to A y).\n\n(*This lemma states that if an element is not in the orbit of another element, then the two elements are distinct.*)\nLemma contra_orbit G x y : x \\notin orbit to G y -> x != y.\n\n(*This lemma states that the relation of being in the same orbit under a group action is symmetric, provided the acting group is a subset of the action's domain.*)\nLemma orbit_in_sym G : G \\subset D -> symmetric (orbit_rel G).\n\n(*This lemma states that if a set of elements is a subset of the domain of an action, then the relation of being in the orbit of another element under that set is transitive.*)\nLemma orbit_in_trans G : G \\subset D -> transitive (orbit_rel G).\n\n(*This lemma states that for a set of elements that is a subset of the domain of an action, the orbit of a first element is equal to the orbit of a second element if and only if the first element is a member of the orbit of the second element.*)\nLemma orbit_in_eqP G x y :\n G \\subset D -> reflect (orbit to G x = orbit to G y) (x \\in orbit to G y).\n\n(*This lemma states that if a second element is in the orbit of a first element under the action of a set, then the second element is in the orbit of a third element if and only if the first element is also in the orbit of that third element, provided the acting set is a subset of the domain.*)\nLemma orbit_in_transl G x y z :\n G \\subset D -> y \\in orbit to G x ->\n (y \\in orbit to G z) = (x \\in orbit to G z).\n\n(*This lemma states that if a set of elements is a subset of the domain of an action, the orbit of an element resulting from an action on a given point is the same as the orbit of the original point, provided the acting element belongs to the set.*)\nLemma orbit_act_in x a G :\n G \\subset D -> a \\in G -> orbit to G (to x a) = orbit to G x.\n\n(*This lemma states that for an acting set that is a subset of the domain, an element `y` belongs to the orbit of `x` if and only if the element resulting from the action of some `a` from the set on `y` also belongs to the orbit of `x`.*)\nLemma orbit_actr_in x a G y :\n G \\subset D -> a \\in G -> (to y a \\in orbit to G x) = (y \\in orbit to G x).\n\n(*This lemma states that an element `y` is in the orbit of an element `x` under the action of the set of inverses of elements in `A` if and only if `x` is in the orbit of `y` under the action of `A` itself, given `A` is a subset of the domain.*)\nLemma orbit_inv_in A x y :\n A \\subset D -> (y \\in orbit to A^-1 x) = (x \\in orbit to A y).\n\n(*This lemma relates an orbit under a left coset to an orbit under the original set. It states that the orbit of an element `x` under the action of a left coset formed by an element `a` and a set `A` is equal to the orbit under `A` of the element obtained by acting on `x` with `a`, provided both `A` and `a` are within the domain.*)\nLemma orbit_lcoset_in A a x :\n A \\subset D -> a \\in D ->\n orbit to (a *: A) x = orbit to A (to x a).\n\n(*This lemma relates an orbit under a right coset to an orbit under the original set. It states that the element obtained by acting on `y` with `a` is in the orbit of `x` under the right coset of `A` by `a` if and only if `y` is in the orbit of `x` under `A`, given all elements are in the domain.*)\nLemma orbit_rcoset_in A a x y :\n A \\subset D -> a \\in D ->\n (to y a \\in orbit to (A :* a) x) = (y \\in orbit to A x).\n\n(*This lemma describes the relationship between an orbit under a set and the orbit under a conjugated set. It asserts that an element `y` belongs to the orbit of `x` under a set `A` if and only if the element obtained by acting on `y` with an element `a` belongs to the orbit of the element obtained by acting on `x` with `a`, where this latter orbit is taken under the action of the set `A` conjugated by `a`.*)\nLemma orbit_conjsg_in A a x y :\n A \\subset D -> a \\in D ->\n (to y a \\in orbit to (A :^ a) (to x a)) = (y \\in orbit to A x).\n\n(*This lemma provides a reflection property stating that the orbit of an element under a group action is a singleton set containing just that element if and only if the element is a fixed point of the group.*)\nLemma orbit1P G x : reflect (orbit to G x = [set x]) (x \\in 'Fix_to(G)).\n\n(*This lemma states that if the cardinality of the orbit of an element under a group action is one, then the orbit is the singleton set containing only that element.*)\nLemma card_orbit1 G x : #|orbit to G x| = 1%N -> orbit to G x = [set x].\n\n(*This lemma states that if a group acts on a set, then the collection of orbits of all elements within that set forms a partition of the set.*)\nLemma orbit_partition G S :\n [acts G, on S | to] -> partition (orbit to G @: S) S.\n\n(*This definition specifies an orbit transversal for a set `S` under the action of another set `A`, as a set containing exactly one representative from each distinct orbit of the elements in `S`.*)\nDefinition orbit_transversal A S := transversal (orbit to A @: S) S.\n\n(*This lemma details the properties of an orbit transversal for a set `S` under a group action. It asserts that if a group acts on `S`, the corresponding transversal is a subset of `S`, contains exactly one element from each orbit, and every element of `S` can be moved into the transversal by some group action.*)\nLemma orbit_transversalP G S (P := orbit to G @: S)\n (X := orbit_transversal G S) :\n [acts G, on S | to] ->\n [/\\ is_transversal X P S, X \\subset S,\n {in X &, forall x y, (y \\in orbit to G x) = (x == y)}\n & forall x, x \\in S -> exists2 a, a \\in G & to x a \\in X].\n\n(*This lemma states that the pointwise stabilizer of a set, which is the set of all elements that fix every point in that set under a group action, itself forms a group.*)\nLemma group_set_astab S : group_set 'C(S | to).\n\nCanonical astab_group S := group (group_set_astab S).\n\n(*This lemma states that the set of points fixed by every element in a set `A` is identical to the set of points fixed by every element in the subgroup generated by `A`, provided `A` is a subset of the domain of action.*)\nLemma afix_gen_in A : A \\subset D -> 'Fix_to(<>) = 'Fix_to(A).\n\n(*This lemma states that the set of points fixed by the cyclic group generated by an element is the same as the set of points fixed by the element itself, provided the element is in the domain of action.*)\nLemma afix_cycle_in a : a \\in D -> 'Fix_to(<[a]>) = 'Fix_to[a].\n\n(*This lemma states that for two sets that are subsets of the domain of action, the set of points fixed by the subgroup generated by their union is equal to the intersection of their individual sets of fixed points.*)\nLemma afixYin A B :\n A \\subset D -> B \\subset D -> 'Fix_to(A <*> B) = 'Fix_to(A) :&: 'Fix_to(B).\n\n(*This lemma states that for two sets of elements `G` and `H` which are subsets of the domain of action, the set of points fixed by the set-product of `G` and `H` is equal to the intersection of the set of points fixed by `G` and the set of points fixed by `H`.*)\nLemma afixMin G H :\n G \\subset D -> H \\subset D -> 'Fix_to(G * H) = 'Fix_to(G) :&: 'Fix_to(H).\n\n(*This lemma states that a set of elements `A` is a subset of the stabilizer of a point `x` if and only if `x` is a fixed point for all actions by elements of `A`, provided `A` is a subset of the domain of action.*)\nLemma sub_astab1_in A x :\n A \\subset D -> (A \\subset 'C[x | to]) = (x \\in 'Fix_to(A)).\n\n(*This lemma asserts that the setwise stabilizer of a given set `S`, which consists of elements in the domain that map the set to itself under a group action, forms a group.*)\nLemma group_set_astabs S : group_set 'N(S | to).\n\nCanonical astabs_group S := group (group_set_astabs S).\n\n(*This lemma states that the setwise stabilizer of a set `S` is a subset of the normalizer of the pointwise stabilizer of `S`.*)\nLemma astab_norm S : 'N(S | to) \\subset 'N('C(S | to)).\n\n(*This lemma states that the pointwise stabilizer of a set `S` is a normal subgroup of the setwise stabilizer of `S`.*)\nLemma astab_normal S : 'C(S | to) <| 'N(S | to).\n\n(*This lemma states that if a group `G` acts on a set `S`, then the orbit of an element `x` under this action is a subset of `S` if and only if `x` itself is an element of `S`.*)\nLemma acts_sub_orbit G S x :\n [acts G, on S | to] -> (orbit to G x \\subset S) = (x \\in S).\n\n(*This lemma states that if a set `G` is a subset of the domain of action, then `G` acts on the orbit of any element `x`, meaning the orbit is closed under the action of `G`.*)\nLemma acts_orbit G x : G \\subset D -> [acts G, on orbit to G x | to].\n\n(*This lemma states that the normalizer of a set `A` within the domain of action acts on the set of points that are fixed by `A`.*)\nLemma acts_subnorm_fix A : [acts 'N_D(A), on 'Fix_to(D :&: A) | to].\n\n(*This lemma states that the action of a group on the orbit of any of its elements is a transitive action.*)\nLemma atrans_orbit G x : [transitive G, on orbit to G x | to].\n\nSection OrbitStabilizer.\n\nVariables (G : {group aT}) (x : rT).\nHypothesis sGD : G \\subset D.\n(*This local definition establishes a boolean-valued property reflecting the premise that the acting group is a subset of the domain, for convenient use in subsequent proofs.*)\nLet ssGD := subsetP sGD.\n\n(*This lemma characterizes the set of all group elements that map a point `x` to the point obtained by acting on `x` with a given group element `a`. It states that this set is precisely the right coset of the stabilizer of `x` in the group by the element `a`.*)\nLemma amove_act a : a \\in G -> amove to G x (to x a) = 'C_G[x | to] :* a.\n\n(*This lemma embodies a key part of the orbit-stabilizer theorem by relating the orbit of a point to the cosets of its stabilizer. It states that the collection of sets of group elements, where each set corresponds to the agents mapping a point `x` to a specific point `y` in its orbit, is precisely the set of right cosets of the stabilizer of `x` in the group.*)\nLemma amove_orbit : amove to G x @: orbit to G x = rcosets 'C_G[x | to] G.\n\n(*This lemma states that for a given group action, the mapping from an element in an orbit to its corresponding coset representative is a left inverse to the mapping from a coset representative back to the element in the orbit.*)\nLemma amoveK :\n {in orbit to G x, cancel (amove to G x) (fun Ca => to x (repr Ca))}.\n\n(*This lemma establishes a one-to-one correspondence between the elements of an orbit of an element under a group action and the set of right cosets of the stabilizer of that element. It asserts that the orbit is precisely the set of elements obtained by applying a representative from each coset to the original element.*)\nLemma orbit_stabilizer :\n orbit to G x = [set to x (repr Ca) | Ca in rcosets 'C_G[x | to] G].\n\n(*This lemma states that for a given group action, the mapping from a coset representative to the corresponding element in an orbit is a left inverse to the mapping from an orbit element back to its coset representative.*)\nLemma act_reprK :\n {in rcosets 'C_G[x | to] G, cancel (to x \\o repr) (amove to G x)}.\n\nEnd OrbitStabilizer.\n\n(*This lemma, known as the Orbit-Stabilizer Theorem, states that for a group acting on a set, the number of elements in the orbit of any given element is equal to the index of the stabilizer subgroup of that element within the acting group.*)\nLemma card_orbit_in G x : G \\subset D -> #|orbit to G x| = #|G : 'C_G[x | to]|.\n\n(*This lemma states a corollary of the Orbit-Stabilizer Theorem: the product of the number of elements in the orbit of an element and the number of elements in its stabilizer subgroup is equal to the total number of elements in the acting group.*)\nLemma card_orbit_in_stab G x :\n G \\subset D -> (#|orbit to G x| * #|'C_G[x | to]|)%N = #|G|.\n\n(*This lemma states that when a group acts on a set, the total number of elements in the set is equal to the sum of the sizes of all the distinct orbits formed by the action.*)\nLemma acts_sum_card_orbit G S :\n [acts G, on S | to] -> \\sum_(T in orbit to G @: S) #|T| = #|S|.\n\n(*This lemma describes how the stabilizer of a set changes when the set itself is transformed by a group element. It states that the stabilizer of the transformed set is the conjugate of the original set's stabilizer by the transforming group element.*)\nLemma astab_setact_in S a : a \\in D -> 'C(to^* S a | to) = 'C(S | to) :^ a.\n\n(*This lemma specifies how the stabilizer of an element changes when the element is acted upon by another group element. It asserts that the stabilizer of the resulting element is the conjugate of the original element's stabilizer by the acting group element.*)\nLemma astab1_act_in x a : a \\in D -> 'C[to x a | to] = 'C[x | to] :^ a.\n\n(*This theorem, also known as Burnside's Lemma or the Cauchy-Frobenius Lemma, relates the number of orbits to the number of fixed points. It states that the sum, over all elements of the acting group, of the number of points fixed by each element, is equal to the product of the number of orbits and the size of the group.*)\nTheorem Frobenius_Cauchy G S : [acts G, on S | to] ->\n \\sum_(a in G) #|'Fix_(S | to)[a]| = (#|orbit to G @: S| * #|G|)%N.\n\n(*This lemma states that if a group acts transitively on a set, then the size of the set must divide the index of the setwise stabilizer of that set within the group.*)\nLemma atrans_dvd_index_in G S :\n G \\subset D -> [transitive G, on S | to] -> #|S| %| #|G : 'C_G(S | to)|.\n\n(*This lemma states that if a group acts transitively on a set, then the size of the set must divide the size of the acting group.*)\nLemma atrans_dvd_in G S :\n G \\subset D -> [transitive G, on S | to] -> #|S| %| #|G|.\n\n(*This lemma provides a defining property of a transitive group action: if an action is transitive, the orbit of any element in the set is the entire set itself.*)\nLemma atransPin G S :\n G \\subset D -> [transitive G, on S | to] ->\n forall x, x \\in S -> orbit to G x = S.\n\n(*This lemma gives an alternative characterization of a transitive group action. It states that for any two elements in the set, there exists an element in the acting group that maps the first element to the second.*)\nLemma atransP2in G S :\n G \\subset D -> [transitive G, on S | to] ->\n {in S &, forall x y, exists2 a, a \\in G & y = to x a}.\n\n(*This lemma states that a transitive action of a group on a set is, by definition, an action on that set, meaning the action is closed on the set.*)\nLemma atrans_acts_in G S :\n G \\subset D -> [transitive G, on S | to] -> [acts G, on S | to].\n\n(*This lemma, known as the Frattini argument for group actions, provides a condition for a subgroup to act transitively. Assuming the larger group already acts transitively, the subgroup acts transitively if and only if the whole group can be expressed as the product of the subgroup and the stabilizer of any given element.*)\nLemma subgroup_transitivePin G H S x :\n x \\in S -> H \\subset G -> G \\subset D -> [transitive G, on S | to] ->\n reflect ('C_G[x | to] * H = G) [transitive H, on S | to].\n\nEnd PartialAction.\n\nArguments orbit_transversal {aT D%_g rT} to%_act A%_g S%_g.\nArguments orbit_in_eqP {aT D rT to G x y}.\nArguments orbit1P {aT D rT to G x}.\nArguments contra_orbit [aT D rT] to G [x y].\n\n(*This notation defines the pointwise stabilizer of a set, which is the subgroup of all elements in the acting group that leave every single element of the set fixed.*)\nNotation \"''C' ( S | to )\" := (astab_group to S) : Group_scope.\n(*This notation defines the pointwise stabilizer of a set, restricted to a given subset of the acting group. It consists of all elements within the given subset that fix every element of the set.*)\nNotation \"''C_' A ( S | to )\" := (setI_group A 'C(S | to)) : Group_scope.\n(*This notation is a parsing variant for defining the pointwise stabilizer of a set restricted to a given subset of the acting group, allowing for parentheses around the subset.*)\nNotation \"''C_' ( A ) ( S | to )\" := (setI_group A 'C(S | to))\n (only parsing) : Group_scope.\n(*This notation defines the stabilizer of a single element, which is the subgroup of all elements in the acting group that leave that specific element fixed.*)\nNotation \"''C' [ x | to ]\" := (astab_group to [set x%g]) : Group_scope.\n(*This notation defines the stabilizer of a single element, restricted to a given subset of the acting group. It consists of all elements within the given subset that fix the specified element.*)\nNotation \"''C_' A [ x | to ]\" := (setI_group A 'C[x | to]) : Group_scope.\n(*This notation is a parsing variant for defining the stabilizer of a single element restricted to a given subset of the acting group, allowing for parentheses around the subset.*)\nNotation \"''C_' ( A ) [ x | to ]\" := (setI_group A 'C[x | to])\n (only parsing) : Group_scope.\n(*This notation defines the setwise stabilizer of a set, which is the subgroup of all elements in the acting group that map the set to itself.*)\nNotation \"''N' ( S | to )\" := (astabs_group to S) : Group_scope.\n(*This notation defines the setwise stabilizer of a set, restricted to a given subset of the acting group. It consists of all elements within the given subset that map the set to itself.*)\nNotation \"''N_' A ( S | to )\" := (setI_group A 'N(S | to)) : Group_scope.\n\nSection TotalActions.\n\nVariable (aT : finGroupType) (rT : finType).\n\nVariable to : {action aT &-> rT}.\n\nImplicit Types (a b : aT) (x y z : rT) (A B : {set aT}) (G H : {group aT}).\nImplicit Type S : {set rT}.\n\n(*This lemma formalizes the compatibility property of a right group action. It states that the action of a product of two group elements on an element is equivalent to applying the actions of the two group elements sequentially.*)\nLemma actM x a b : to x (a * b) = to (to x a) b.\n\n(*This lemma states that a right group action is cancellable by the group inverse. Applying an action and then the action of the inverse element returns the original element.*)\nLemma actK : right_loop invg to.\n\n(*This lemma states that a right group action is cancellable by the group inverse in reverse order. Applying the action of an inverse element and then the action of the original element returns the original element.*)\nLemma actKV : rev_right_loop invg to.\n\n(*This lemma states that the action of a group element raised to a natural number power is equivalent to iterating the action of that group element that number of times.*)\nLemma actX x a n : to x (a ^+ n) = iter n (to^~ a) x.\n\n(*This lemma provides an identity for reordering group actions using conjugation. It states that applying an action by a first group element, followed by an action by a second, is equivalent to applying the action by the second element first, followed by the action of the conjugate of the first element by the second.*)\nLemma actCJ a b x : to (to x a) b = to (to x b) (a ^ b).\n\n(*This lemma provides an alternative identity for reordering group actions. It states that applying an action by a first group element, followed by an action by a second, is equivalent to applying an action by a specific conjugate first, followed by the action of the first element.*)\nLemma actCJV a b x : to (to x a) b = to (to x (b ^ a^-1)) a.\n\n(*This lemma states that the relation of two elements being in the same orbit is symmetric. If one element can be reached from another via a group action, then the second can also be reached from the first.*)\nLemma orbit_sym G x y : (x \\in orbit to G y) = (y \\in orbit to G x).\n\n(*This lemma states that the relation of being in the orbit of another element under a group action is transitive. If a first element is in the orbit of a second, and the second is in the orbit of a third, then the first element is in the orbit of the third.*)\nLemma orbit_trans G x y z :\n x \\in orbit to G y -> y \\in orbit to G z -> x \\in orbit to G z.\n\n(*This lemma states that the orbits of two elements under a group action are equal if and only if the first element is in the orbit of the second element.*)\nLemma orbit_eqP G x y :\n reflect (orbit to G x = orbit to G y) (x \\in orbit to G y).\n\n(*This lemma states that if a first element is in the orbit of a second element under a group action, then the membership of the first element in the orbit of a third element is equivalent to the membership of the second element in the orbit of that same third element.*)\nLemma orbit_transl G x y z :\n y \\in orbit to G x -> (y \\in orbit to G z) = (x \\in orbit to G z).\n\n(*This lemma states that for any element in a group, the orbit of an element after being acted upon by that group element is equal to the orbit of the original element.*)\nLemma orbit_act G a x: a \\in G -> orbit to G (to x a) = orbit to G x.\n\n \n(*This lemma states that for any element in a group, a first element acted upon by that group element belongs to the orbit of a second element if and only if the first element itself belongs to the orbit of the second element.*)\nLemma orbit_actr G a x y :\n a \\in G -> (to y a \\in orbit to G x) = (y \\in orbit to G x).\n\n(*This lemma states that the boolean equality of the orbits of two elements under a group action is equivalent to the boolean property that the first element is a member of the orbit of the second element.*)\nLemma orbit_eq_mem G x y :\n (orbit to G x == orbit to G y) = (x \\in orbit to G y).\n\n(*This lemma states that a second element is in the orbit of a first element under the action of the set of inverses of a given set of group elements if and only if the first element is in the orbit of the second element under the action of the original set.*)\nLemma orbit_inv A x y : (y \\in orbit to A^-1 x) = (x \\in orbit to A y).\n\n(*This lemma states that the orbit of an element under the action of a left coset is equal to the orbit under the action of the base subgroup, but applied to the element transformed by the coset representative.*)\nLemma orbit_lcoset A a x : orbit to (a *: A) x = orbit to A (to x a).\n\n(*This lemma states an equivalence for orbit membership under a right coset action. It asserts that an element `y` transformed by a group element `a` belongs to the orbit of an element `x` under the coset's action if and only if `y` belongs to the orbit of `x` under the base subgroup's action.*)\nLemma orbit_rcoset A a x y :\n (to y a \\in orbit to (A :* a) x) = (y \\in orbit to A x).\n\n(*This lemma provides a condition for membership in an orbit under a conjugated group action. It asserts that a transformed element belongs to the orbit of another transformed element under the conjugated action if and only if the original element belongs to the orbit of the other original element under the original group action.*)\nLemma orbit_conjsg A a x y :\n (to y a \\in orbit to (A :^ a) (to x a)) = (y \\in orbit to A x).\n\n(*This lemma provides a reflection property for the stabilizer of a set under a group action. It states that an element belongs to the set stabilizer if and only if it fixes every element within that set.*)\nLemma astabP S a : reflect (forall x, x \\in S -> to x a = x) (a \\in 'C(S | to)).\n\n(*This lemma provides a reflection property for the stabilizer of a single element under a group action. It states that a group element belongs to the point stabilizer if and only if it fixes that specific element.*)\nLemma astab1P x a : reflect (to x a = x) (a \\in 'C[x | to]).\n\n(*This lemma states that a given set of group elements is a subset of the stabilizer of a specific element if and only if that element is a fixed point for every element in the given set.*)\nLemma sub_astab1 A x : (A \\subset 'C[x | to]) = (x \\in 'Fix_to(A)).\n\n(*This lemma establishes a connection between stabilizers and fixed points. It states that a first set of group elements is a subset of the stabilizer of a second set of points if and only if the second set of points is a subset of the set of points fixed by all elements in the first set.*)\nLemma astabC A S : (A \\subset 'C(S | to)) = (S \\subset 'Fix_to(A)).\n\n(*This lemma states that the set of fixed points under the action of the cyclic group generated by an element is equal to the set of fixed points of that element itself.*)\nLemma afix_cycle a : 'Fix_to(<[a]>) = 'Fix_to[a].\n\n(*This lemma states that the set of fixed points under the action of the subgroup generated by a set of elements is equal to the set of fixed points of the generating set itself.*)\nLemma afix_gen A : 'Fix_to(<>) = 'Fix_to(A).\n\n(*This lemma states that the set of fixed points under the action of the product of two subgroups is the intersection of their respective sets of fixed points.*)\nLemma afixM G H : 'Fix_to(G * H) = 'Fix_to(G) :&: 'Fix_to(H).\n\n(*This lemma provides a reflection property for the normalizer of a set under a group action. It states that an element belongs to the normalizer of a set if and only if the action of that element preserves the set, meaning an element belongs to the set if and only if its image under the action also belongs to the set.*)\nLemma astabsP S a :\n reflect (forall x, (to x a \\in S) = (x \\in S)) (a \\in 'N(S | to)).\n\n(*This lemma states the Orbit-Stabilizer theorem, asserting that the cardinality of the orbit of an element under a group action is equal to the index of the stabilizer of that element within the group.*)\nLemma card_orbit G x : #|orbit to G x| = #|G : 'C_G[x | to]|.\n\n(*This lemma, a corollary of Lagrange's theorem, states that the cardinality of the orbit of any element under a finite group action divides the cardinality of the group.*)\nLemma dvdn_orbit G x : #|orbit to G x| %| #|G|.\n\n(*This lemma provides a multiplicative form of the Orbit-Stabilizer theorem. It states that the product of the cardinality of an element's orbit and the cardinality of its stabilizer is equal to the cardinality of the acting group.*)\nLemma card_orbit_stab G x : (#|orbit to G x| * #|'C_G[x | to]|)%N = #|G|.\n\n(*This lemma provides a reflection property, stating that a group acts on a set if and only if the corresponding boolean predicate for this property is true.*)\nLemma actsP A S : reflect {acts A, on S | to} [acts A, on S | to].\n\nArguments actsP {A S}.\n\n(*This lemma describes how orbits are transformed under a set action. It states that the action of a group element on the orbit of another element under a group's action results in a new orbit, which is the orbit of the transformed element under the action of the conjugated group.*)\nLemma setact_orbit A x b : to^* (orbit to A x) b = orbit to (A :^ b) (to x b).\n\n(*This lemma describes the relationship between the stabilizer of a transformed set and the stabilizer of the original set. It states that the stabilizer of a set after it is acted upon by a group element is equal to the conjugate of the stabilizer of the original set by that same group element.*)\nLemma astab_setact S a : 'C(to^* S a | to) = 'C(S | to) :^ a.\n\n(*This lemma describes how the stabilizer of an element changes when the element is acted upon. It states that the stabilizer of an element after being acted upon by a group element is equal to the conjugate of the original element's stabilizer by that same group element.*)\nLemma astab1_act x a : 'C[to x a | to] = 'C[x | to] :^ a.\n\n(*This lemma provides a characterization of a transitive group action. It states that if a group acts transitively on a set, then for any element in that set, its orbit under the group action is equal to the entire set.*)\nLemma atransP G S : [transitive G, on S | to] ->\n forall x, x \\in S -> orbit to G x = S.\n\n(*This lemma provides an alternative characterization of a transitive group action on a non-empty set. It states that if a group acts transitively on a set, then for any pair of elements in that set, there exists a group element that maps the first element to the second.*)\nLemma atransP2 G S : [transitive G, on S | to] ->\n {in S &, forall x y, exists2 a, a \\in G & y = to x a}.\n\n(*This lemma states that if a group acts transitively on a set, then it necessarily acts on that set.*)\nLemma atrans_acts G S : [transitive G, on S | to] -> [acts G, on S | to].\n\n(*This lemma states that if a subgroup acts transitively on a set, then its supergroup acts transitively on the same set if and only if the supergroup acts on the set.*)\nLemma atrans_supgroup G H S :\n G \\subset H -> [transitive G, on S | to] ->\n [transitive H, on S | to] = [acts H, on S | to].\n\n(*This lemma states that if a group acts transitively on a finite set, then the cardinality of the set divides the cardinality of the group.*)\nLemma atrans_acts_card G S :\n [transitive G, on S | to] =\n [acts G, on S | to] && (#|orbit to G @: S| == 1%N).\n\n(*This lemma states that if a finite group acts transitively on a finite set, then the size of the set divides the order of the group.*)\nLemma atrans_dvd G S : [transitive G, on S | to] -> #|S| %| #|G|.\n\n(*This lemma states that if a set of group elements is a subset of the normalizer of another set of group elements, then the first set acts on the set of fixed points of the second set under a given action.*)\nLemma acts_fix_norm A B : A \\subset 'N(B) -> [acts A, on 'Fix_to(B) | to].\n\n(*This lemma provides a reflection property for the faithfulness of a group action, stating that a group acts faithfully on a set if and only if the only group element that fixes every element of the set is the identity element.*)\nLemma faithfulP A S :\n reflect (forall a, a \\in A -> {in S, to^~ a =1 id} -> a = 1)\n [faithful A, on S | to].\n\n(*This lemma states that for a transitive group action on a set, the stabilizer of the entire set is equal to the group core of the stabilizer of any single element from that set.*)\nLemma astab_trans_gcore G S u :\n [transitive G, on S | to] -> u \\in S -> 'C(S | to) = gcore 'C[u | to] G.\n\n(*This theorem provides a reflection property asserting that if a group acts transitively on a set, a subgroup also acts transitively if and only if the whole group can be expressed as the product of the subgroup and the stabilizer of any element in the set.*)\nTheorem subgroup_transitiveP G H S x :\n x \\in S -> H \\subset G -> [transitive G, on S | to] ->\n reflect ('C_G[x | to] * H = G) [transitive H, on S | to].\n\n(*This lemma provides a reflection property stating that if a group acts transitively on a set and a subgroup stabilizes a particular element, then the normalizer of that subgroup acts transitively on the set of fixed points of the subgroup if and only if the intersection of the normal closure of the subgroup in the whole group with the stabilizer of the element is equal to the normal closure of the subgroup within that stabilizer.*)\nLemma trans_subnorm_fixP x G H S :\n let C := 'C_G[x | to] in let T := 'Fix_(S | to)(H) in\n [transitive G, on S | to] -> x \\in S -> H \\subset C ->\n reflect ((H :^: G) ::&: C = H :^: C) [transitive 'N_G(H), on T | to].\n\nEnd TotalActions.\n\nArguments astabP {aT rT to S a}.\nArguments orbit_eqP {aT rT to G x y}.\nArguments astab1P {aT rT to x a}.\nArguments astabsP {aT rT to S a}.\nArguments atransP {aT rT to G S}.\nArguments actsP {aT rT to A S}.\nArguments faithfulP {aT rT to A S}.\n\nSection Restrict.\n\nVariables (aT : finGroupType) (D : {set aT}) (rT : Type).\nVariables (to : action D rT) (A : {set aT}).\n\n(*This definition defines a restricted action for a subset of a group by using the original group action.*)\nDefinition ract of A \\subset D := act to.\n\nVariable sAD : A \\subset D.\n\n(*This lemma proves that the restricted action defined by 'ract' is a valid group action.*)\nLemma ract_is_action : is_action A (ract sAD).\n\nCanonical raction := Action ract_is_action.\n\n(*This lemma states that the canonical restricted action is functionally identical to the original action from which it was derived.*)\nLemma ractE : raction =1 to. \n\nEnd Restrict.\n\n(*This notation represents the restriction of a group action to a subgroup, where the second argument is a proof that the new domain is a subset of the original action's domain.*)\nNotation \"to \\ sAD\" := (raction to sAD) (at level 50) : action_scope.\n\nSection ActBy.\n\nVariables (aT : finGroupType) (D : {set aT}) (rT : finType).\n\n(*This definition specifies the condition that a set of group elements acts on a given subset of the action's target type.*)\nDefinition actby_cond (A : {set aT}) R (to : action D rT) : Prop :=\n [acts A, on R | to].\n\n(*This definition creates a new action function that behaves like a given action for elements within a specified subset and group, and acts as the identity function otherwise.*)\nDefinition actby A R to of actby_cond A R to :=\n fun x a => if (x \\in R) && (a \\in A) then to x a else x.\n\nVariables (A : {group aT}) (R : {set rT}) (to : action D rT).\nHypothesis nRA : actby_cond A R to.\n\n(*This lemma proves that the 'actby' function defines a valid group action.*)\nLemma actby_is_action : is_action A (actby nRA).\n\nCanonical action_by := Action actby_is_action.\n(*This local notation refers to the canonical action created from the 'actby' definition, which is conditioned on a proof that the group acts on the specified subset.*)\nLocal Notation \"<[nRA]>\" := action_by : action_scope.\n\n(*This lemma states that the 'actby' action is identical to the original action when applied to an element within the specified subset and an element from the acting group.*)\nLemma actbyE x a : x \\in R -> a \\in A -> <[nRA]>%act x a = to x a.\n\n(*This lemma characterizes the set of fixed points for the 'actby' action. It states that these fixed points are the union of the complement of the restricted subset and the fixed points of the original action within that subset.*)\nLemma afix_actby B : 'Fix_<[nRA]>(B) = ~: R :|: 'Fix_to(A :&: B).\n\n(*This lemma relates the stabilizer of a set under the 'actby' action to the stabilizer under the original action, stating that the former is equal to the stabilizer within the acting group of the intersection of the set and the restricted subset.*)\nLemma astab_actby S : 'C(S | <[nRA]>) = 'C_A(R :&: S | to).\n\n(*This lemma relates the normalizer of a set under the 'actby' action to the normalizer under the original action, stating that the former is equal to the normalizer within the acting group of the intersection of the set and the restricted subset.*)\nLemma astabs_actby S : 'N(S | <[nRA]>) = 'N_A(R :&: S | to).\n\n(*This lemma provides the condition for a set of group elements to act on a given set under the 'actby' action. This is true if and only if the set of group elements is a subset of the main acting group and it also acts on the intersection of the given set and the restricted subset under the original action.*)\nLemma acts_actby (B : {set aT}) S :\n [acts B, on S | <[nRA]>] = (B \\subset A) && [acts B, on R :&: S | to].\n\nEnd ActBy.\n\n(*This notation refers to the canonical action constructed from an action that is restricted to a specific subset of its domain, conditioned on a proof that the group preserves this subset.*)\nNotation \"<[ nRA ] >\" := (action_by nRA) : action_scope.\n\nSection SubAction.\n\nVariables (aT : finGroupType) (D : {group aT}).\nVariables (rT : finType) (sP : pred rT) (sT : subFinType sP) (to : action D rT).\nImplicit Type A : {set aT}.\nImplicit Type u : sT.\nImplicit Type S : {set sT}.\n\n(*This definition specifies the domain for a subaction as the normalizer of the underlying set of a subtype with respect to a given action, which is the largest subgroup that stabilizes this set.*)\nDefinition subact_dom := 'N([set x | sP x] | to).\nCanonical subact_dom_group := [group of subact_dom].\n\nImplicit Type Na : {a | a \\in subact_dom}.\n(*This lemma proves that applying an element from the subaction's domain to an element of the subtype results in an element that still belongs to the subtype.*)\nLemma sub_act_proof u Na : sP (to (val u) (val Na)).\n\n(*This definition constructs a subaction on a subtype. If a group element belongs to the subaction's domain, it applies the original action and wraps the result back into the subtype; otherwise, it acts as the identity.*)\nDefinition subact u a :=\n if insub a is Some Na then Sub _ (sub_act_proof u Na) else u.\n\n(*This lemma states that the underlying value resulting from the subaction is equal to the result of the original action if the group element is in the subaction's domain, and is the original value otherwise.*)\nLemma val_subact u a :\n val (subact u a) = if a \\in subact_dom then to (val u) a else val u.\n\n(*This lemma proves that the 'subact' function defines a valid group action on its specified domain.*)\nLemma subact_is_action : is_action subact_dom subact.\n\nCanonical subaction := Action subact_is_action.\n\n(*This lemma characterizes the stabilizer of a set under the subaction as the intersection of the subaction's domain and the stabilizer of the corresponding set of underlying values under the original action.*)\nLemma astab_subact S : 'C(S | subaction) = subact_dom :&: 'C(val @: S | to).\n\n(*This lemma characterizes the normalizer of a set under the subaction as the intersection of the subaction's domain and the normalizer of the corresponding set of underlying values under the original action.*)\nLemma astabs_subact S : 'N(S | subaction) = subact_dom :&: 'N(val @: S | to).\n\n(*This lemma states that for any group within the subaction's domain, the set of fixed points under the subaction is the preimage of the set of fixed points under the original action.*)\nLemma afix_subact A :\n A \\subset subact_dom -> 'Fix_subaction(A) = val @^-1: 'Fix_to(A).\n\nEnd SubAction.\n\n(*This notation represents the canonical subaction induced by a given action on a subtype, where the acting group is restricted to the largest subgroup that stabilizes the subtype.*)\nNotation \"to ^?\" := (subaction _ to)\n (at level 2, format \"to ^?\") : action_scope.\n\nSection QuotientAction.\n\nVariables (aT : finGroupType) (D : {group aT}) (rT : finGroupType).\nVariables (to : action D rT) (H : {group rT}).\n\n(*This definition specifies the domain for a quotient action as the normalizer of the set of right cosets of a subgroup within its own normalizer, under the induced action on sets.*)\nDefinition qact_dom := 'N(rcosets H 'N(H) | to^.\nCanonical qact_dom_group := [group of qact_dom].\n\n(*This notation defines `subdom` as the domain of a group action when that action is restricted to the range of cosets of a given subgroup.*)\nLocal Notation subdom := (subact_dom (coset_range H) to^.\n(*This fact states that the domain of a group action restricted to the range of cosets of a subgroup is equal to the domain of the corresponding quotient action.*)\nFact qact_subdomE : subdom = qact_dom.\n\n(*This lemma states that the domain of a quotient action is a subset of the domain of the original action restricted to the range of cosets of the given subgroup.*)\nLemma qact_proof : qact_dom \\subset subdom.\n\n(*This definition specifies the quotient action, which describes how an element from a group acts on a coset of a subgroup, resulting in another coset of that subgroup.*)\nDefinition qact : coset_of H -> aT -> coset_of H := act (to^*^? \\ qact_proof).\n\nCanonical quotient_action := [action of qact].\n\n(*This lemma asserts that the domain of the quotient action acts on the normalizer of the given subgroup under the original action.*)\nLemma acts_qact_dom : [acts qact_dom, on 'N(H) | to].\n\n(*This lemma provides a conditional definition for the quotient action, stating that for an element in the normalizer of a subgroup, the action of another element on its coset yields the coset of the original action's result if the acting element is in the quotient action domain, and the original coset otherwise.*)\nLemma qactEcond x a :\n x \\in 'N(H) ->\n quotient_action (coset H x) a\n = coset H (if a \\in qact_dom then to x a else x).\n\n(*This lemma states that for an element in the normalizer of a subgroup and another element in the quotient action domain, the quotient action on the coset is equivalent to the coset of the result of the original action.*)\nLemma qactE x a :\n x \\in 'N(H) -> a \\in qact_dom ->\n quotient_action (coset H x) a = coset H (to x a).\n\n(*This lemma states that if a set of group elements is contained in the stabilizer of another set within the quotient action domain, then the first set acts on the quotient of the second set by the given subgroup via the quotient action.*)\nLemma acts_quotient (A : {set aT}) (B : {set rT}) :\n A \\subset 'N_qact_dom(B | to) -> [acts A, on B / H | quotient_action].\n\n(*This lemma relates the stabilizer of a quotient group to the original stabilizer, asserting that if a subgroup is normal, the stabilizer of the quotient group under the quotient action is equal to the stabilizer of the original group within the quotient action domain.*)\nLemma astabs_quotient (G : {group rT}) :\n H <| G -> 'N(G / H | quotient_action) = 'N_qact_dom(G | to).\n\nEnd QuotientAction.\n\n(*This notation defines a syntax for the quotient action derived from an action `to` and a subgroup `H`.*)\nNotation \"to / H\" := (quotient_action to H) : action_scope.\n\nSection ModAction.\n\nVariables (aT : finGroupType) (D : {group aT}) (rT : finType).\nVariable to : action D rT.\nImplicit Types (G : {group aT}) (S : {set rT}).\n\nSection GenericMod.\n\nVariable H : {group aT}.\n\n(*This notation defines `dom` as the normalizer of a subgroup within another group.*)\nLocal Notation dom := 'N_D(H).\n(*This notation defines `range` as the set of fixed points under a group action for all elements in the intersection of the action domain and a given subgroup.*)\nLocal Notation range := 'Fix_to(D :&: H).\n(*This lemma states that the normalizer of a subgroup within a larger group acts on the set of shared fixed points of the subgroup and the larger group via the original action.*)\nLet acts_dom : {acts dom, on range | to} := acts_act (acts_subnorm_fix to H).\n\n(*This definition introduces the module action, which specifies how a coset acts on an element. If the element belongs to a specific set of fixed points, the action is defined by the original action of a representative of the coset; otherwise, the element remains unchanged.*)\nDefinition modact x (Ha : coset_of H) :=\n if x \\in range then to x (repr (D :&: Ha)) else x.\n\n(*This lemma provides a conditional rule for the module action, specifying that for an element in the normalizer, its coset's action on an element is given by the original action if the element is in the set of fixed points, and is the identity action otherwise.*)\nLemma modactEcond x a :\n a \\in dom -> modact x (coset H a) = (if x \\in range then to x a else x).\n\n(*This lemma states that for an element in the normalizer of a subgroup and an element in the associated set of fixed points, the module action of the coset on the element is equivalent to the original action.*)\nLemma modactE x a :\n a \\in D -> a \\in 'N(H) -> x \\in range -> modact x (coset H a) = to x a.\n\n(*This lemma asserts that the defined module action constitutes a valid group action of the quotient group.*)\nLemma modact_is_action : is_action (D / H) modact.\n\nCanonical mod_action := Action modact_is_action.\n\nSection Stabilizers.\n\nVariable S : {set rT}.\nHypothesis cSH : H \\subset 'C(S | to).\n\n(*This theorem states that if a subgroup centralizes a set under a given action, then every element of that set is a fixed point of the action for any element in the intersection of the action's domain and the subgroup.*)\nLet fixSH : S \\subset 'Fix_to(D :&: H).\n\n(*This lemma establishes a correspondence between stabilizers, stating that the stabilizer of a set under the module action is equal to the quotient of the stabilizer of that set under the original action by the given subgroup.*)\nLemma astabs_mod : 'N(S | mod_action) = 'N(S | to) / H.\n\n(*This lemma establishes a correspondence between centralizers, stating that the centralizer of a set under the module action is equal to the quotient of the centralizer of that set under the original action by the given subgroup.*)\nLemma astab_mod : 'C(S | mod_action) = 'C(S | to) / H.\n\nEnd Stabilizers.\n\n(*This lemma states that under certain conditions, the set of fixed points within a given set under the module action of a quotient group is identical to the set of fixed points within that same set under the original action of the unquotiented group.*)\nLemma afix_mod G S :\n H \\subset 'C(S | to) -> G \\subset 'N_D(H) ->\n 'Fix_(S | mod_action)(G / H) = 'Fix_(S | to)(G).\n\nEnd GenericMod.\n\n(*This lemma asserts that the module action of a group on a set is faithful when the group is quotiented by the centralizer of that set.*)\nLemma modact_faithful G S :\n [faithful G / 'C_G(S | to), on S | mod_action 'C_G(S | to)].\n\nEnd ModAction.\n\n(*This notation defines a syntax for the module action derived from an action `to` and a subgroup `H`.*)\nNotation \"to %% H\" := (mod_action to H) : action_scope.\n\nSection ActPerm.\n\nVariables (aT : finGroupType) (D : {set aT}) (rT : finType).\nVariable to : action D rT.\n\n(*This definition creates a permutation corresponding to the action of a group element by converting the function that maps each element of a set to the result of the group element acting on it.*)\nDefinition actperm a := perm (act_inj to a).\n\n(*This lemma states that the function which maps a group element to its corresponding action permutation is a group homomorphism, preserving the group's multiplicative structure.*)\nLemma actpermM : {in D &, {morph actperm : a b / a * b}}.\n\nCanonical actperm_morphism := Morphism actpermM.\n\n(*This lemma clarifies the definition of the action permutation, stating that applying the permutation associated with a group element to another element is equivalent to the original action of the group element on the other element.*)\nLemma actpermE a x : actperm a x = to x a.\n\n(*This lemma gives an alternative characterization of the action permutation, stating that the result of applying the permutation associated with a group element to another element is equal to the result of the original group action.*)\nLemma actpermK x a : aperm x (actperm a) = to x a.\n\n(*This lemma identifies the kernel of the action permutation homomorphism as the centralizer of the entire set upon which the action is defined.*)\nLemma ker_actperm : 'ker actperm = 'C(setT | to).\n\nEnd ActPerm.\n\nSection RestrictActionTheory.\n\nVariables (aT : finGroupType) (D : {set aT}) (rT : finType).\nVariables (to : action D rT).\n\n(*This lemma, a form of Cayley's theorem, states that if a group acts faithfully on a set, then that group is isomorphic to the group of permutations induced by its action on the set.*)\nLemma faithful_isom (A : {group aT}) S (nSA : actby_cond A S to) :\n [faithful A, on S | to] -> isom A (actperm <[nSA]> @* A) (actperm <[nSA]>).\n\nVariables (A : {set aT}) (sAD : A \\subset D).\n\n(*This lemma states that the action permutation generated from an action restricted to a subset is functionally identical to the action permutation generated from the original, unrestricted action.*)\nLemma ractpermE : actperm (to \\ sAD) =1 actperm to.\n\n(*This lemma states that the set of fixed points of a given set under a restricted action is equal to the set of fixed points of the same set under the original, unrestricted action.*)\nLemma afix_ract B : 'Fix_(to \\ sAD)(B) = 'Fix_to(B). \n\n(*This lemma states that the centralizer of a set under a restricted action is equal to the centralizer within the acting group of the same set under the original, unrestricted action.*)\nLemma astab_ract S : 'C(S | to \\ sAD) = 'C_A(S | to).\n\n(*This lemma states that the normalizer of a set under a restricted action is equal to the normalizer within the acting group of the same set under the original, unrestricted action.*)\nLemma astabs_ract S : 'N(S | to \\ sAD) = 'N_A(S | to).\n\n(*This lemma states that a set of group elements acts on a given set under a restricted action if and only if the set of group elements is a subset of the acting group and it also acts on the given set under the original, unrestricted action.*)\nLemma acts_ract (B : {set aT}) S :\n [acts B, on S | to \\ sAD] = (B \\subset A) && [acts B, on S | to].\n\nEnd RestrictActionTheory.\n\nSection MorphAct.\n\nVariables (aT : finGroupType) (D : {group aT}) (rT : finType).\nVariable phi : {morphism D >-> {perm rT}}.\n\n(*This definition specifies a group action where a group element acts on an element of a finite type by applying the permutation that results from mapping the group element through a given group morphism into a permutation group.*)\nDefinition mact x a := phi a x.\n\n(*This lemma asserts that the application of a permutation obtained via a group morphism constitutes a valid group action.*)\nLemma mact_is_action : is_action D mact.\n\nCanonical morph_action := Action mact_is_action.\n\n(*This lemma provides a computational rule, stating that applying the action derived from a group morphism is equivalent to applying the permutation obtained by mapping the group element through that morphism.*)\nLemma mactE x a : morph_action x a = phi a x. \n\n(*This lemma states that if the underlying group morphism into a permutation group is injective, then the induced group action is faithful on the set of all elements.*)\nLemma injm_faithful : 'injm phi -> [faithful D, on setT | morph_action].\n\n(*This lemma states that the permutation corresponding to a group element under the action induced by a group morphism is precisely the permutation obtained by applying the morphism to that element.*)\nLemma perm_mact a : actperm morph_action a = phi a.\n\nEnd MorphAct.\n\n(*This notation provides a concise way to refer to the group action induced by a group morphism into a permutation group.*)\nNotation \"<< phi >>\" := (morph_action phi) : action_scope.\n\nSection CompAct.\n\nVariables (gT aT : finGroupType) (rT : finType).\nVariables (D : {set aT}) (to : action D rT).\nVariables (B : {set gT}) (f : {morphism B >-> aT}).\n\n(*This definition specifies a group action composed from an existing action and a group morphism. An element from the domain of the morphism acts on an element of a finite type by first applying the morphism to the group element and then using the existing action.*)\nDefinition comp_act x e := to x (f e).\n(*This lemma asserts that the composition of a group action with a group morphism results in a valid group action on the preimage of the original acting group.*)\nLemma comp_is_action : is_action (f @*^-1 D) comp_act.\n\nCanonical comp_action := Action comp_is_action.\n\n(*This lemma provides a computational rule, stating that applying the composed action is equivalent to first mapping the acting element through the group morphism and then applying the original action.*)\nLemma comp_actE x e : comp_action x e = to x (f e). \n\n(*This lemma states that, given a set of elements within the domain of the composing group morphism, the set of fixed points under the composed action is equal to the set of fixed points under the original action when applied to the image of that set under the morphism.*)\nLemma afix_comp (A : {set gT}) :\n A \\subset B -> 'Fix_comp_action(A) = 'Fix_to(f @* A).\n\n(*This lemma states that the centralizer of a set under a composed action is equal to the preimage under the composing group morphism of the centralizer of the same set under the original action.*)\nLemma astab_comp S : 'C(S | comp_action) = f @*^-1 'C(S | to).\n\n(*This lemma states that the normalizer of a set under a composed action is equal to the preimage under the composing group morphism of the normalizer of the same set under the original action.*)\nLemma astabs_comp S : 'N(S | comp_action) = f @*^-1 'N(S | to).\n\nEnd CompAct.\n\n(*This notation provides a concise way to refer to the group action obtained by composing an existing action with a group morphism.*)\nNotation \"to \\o f\" := (comp_action to f) : action_scope.\n\nSection PermAction.\n\nVariable rT : finType.\n(*This notation serves as a local alias for the type of permutations on a given finite type.*)\nLocal Notation gT := {perm rT}.\nImplicit Types a b c : gT.\n\n(*This lemma asserts that the direct application of a permutation to an element of its underlying finite type constitutes a valid group action by the full permutation group.*)\nLemma aperm_is_action : is_action setT (@aperm rT).\n\nCanonical perm_action := Action aperm_is_action.\n\n(*This lemma states that the set of orbits generated by a single permutation acting on its underlying type is identical to the set of orbits generated by the canonical permutation action of the cyclic group generated by that same permutation.*)\nLemma porbitE a : porbit a = orbit perm_action <[a]>%g.\n\n(*This lemma asserts that a permutation fixes every element of its underlying type if and only if that permutation is the identity permutation.*)\nLemma perm_act1P a : reflect (forall x, aperm x a = x) (a == 1).\n\n(*This lemma states that the canonical action of any set of permutations on its underlying type is faithful, meaning only the identity permutation can fix every element.*)\nLemma perm_faithful A : [faithful A, on setT | perm_action].\n\n(*This lemma states that for the canonical permutation action, the permutation associated with a given group element is identical to that group element itself.*)\nLemma actperm_id p : actperm perm_action p = p.\n\nEnd PermAction.\n\nArguments perm_act1P {rT a}.\n\n(*This notation serves as a concise alias for the canonical action of a permutation group on its underlying finite type.*)\nNotation \"'P\" := (perm_action _) (at level 8) : action_scope.\n\nSection ActpermOrbits.\n\nVariables (aT : finGroupType) (D : {group aT}) (rT : finType).\nVariable to : action D rT.\n\n(*This lemma states that for any subset of the acting group, the set of orbits generated by the canonical permutation action of the corresponding permutations is equivalent to the set of orbits generated by the original group action.*)\nLemma orbit_morphim_actperm (A : {set aT}) :\n A \\subset D -> orbit 'P (actperm to @* A) =1 orbit to A.\n\n(*This lemma states that for any element of the acting group, the orbits of the permutation associated with that element are equivalent to the orbits generated by the original action of the cyclic group generated by that same element.*)\nLemma porbit_actperm (a : aT) :\n a \\in D -> porbit (actperm to a) =1 orbit to <[a]>.\n\nEnd ActpermOrbits.\n\nSection RestrictPerm.\n\nVariables (T : finType) (S : {set T}).\n\n(*This definition creates a group morphism that restricts permutations from the normalizer of a given set to permutations on that set itself.*)\nDefinition restr_perm := actperm (<[subxx 'N(S | 'P)]>).\nCanonical restr_perm_morphism := [morphism of restr_perm].\n\n(*This lemma asserts that the permutation resulting from restricting a permutation from the normalizer of a set is indeed a permutation on that set.*)\nLemma restr_perm_on p : perm_on S (restr_perm p).\n\n(*This lemma states that if a permutation does not belong to the normalizer of a given set, its restriction to that set is the identity permutation.*)\nLemma triv_restr_perm p : p \\notin 'N(S | 'P) -> restr_perm p = 1.\n\n(*This lemma states that for any permutation within the normalizer of a given set, its restriction acts identically to the original permutation on all elements of that set.*)\nLemma restr_permE : {in 'N(S | 'P) & S, forall p, restr_perm p =1 p}.\n\n(*This lemma states that the kernel of the permutation restriction morphism is equal to the pointwise centralizer of the subset to which the permutations are restricted.*)\nLemma ker_restr_perm : 'ker restr_perm = 'C(S | 'P).\n\n(*This lemma states that the image of a subset under a permutation restricted to that subset is the subset itself.*)\nLemma im_restr_perm p : restr_perm p @: S = S.\n\n(*This lemma states that any permutation on a subset commutes with its extension to the full type, where the extension acts as the identity outside the subset.*)\nLemma restr_perm_commute s : commute (restr_perm s) s.\n\nEnd RestrictPerm.\n\nSection Symmetry.\n\nVariables (T : finType) (S : {set T}).\n\n(*This lemma states that the symmetric group on a subset is equivalent to the centralizer of the complement of that subset within the group of all permutations.*)\nLemma SymE : Sym S = 'C(~: S | 'P).\n\nEnd Symmetry.\n\nSection AutIn.\n\nVariable gT : finGroupType.\n\n(*This definition specifies the group of automorphisms induced on a given subset by a group of automorphisms. It is constructed as the quotient of the normalizer of the subset within the automorphism group by the centralizer of the subset within the same automorphism group.*)\nDefinition Aut_in A (B : {set gT}) := 'N_A(B | 'P) / 'C_A(B | 'P).\n\nVariables G H : {group gT}.\nHypothesis sHG: H \\subset G.\n\n(*This lemma shows that if an automorphism of a group G stabilizes a given subgroup H, then the permutation resulting from restricting the automorphism to H is itself an automorphism of H.*)\nLemma Aut_restr_perm a : a \\in Aut G -> restr_perm H a \\in Aut H.\n\n(*This lemma states that the set of automorphisms of a subgroup H contains the image of the automorphism group of the parent group G under the restriction map to H.*)\nLemma restr_perm_Aut : restr_perm H @* Aut G \\subset Aut H.\n\n(*This lemma establishes an isomorphism between the group of automorphisms induced on a subgroup H by the automorphism group of G, and the group of restricted automorphisms on H obtained from G.*)\nLemma Aut_in_isog : Aut_in (Aut G) H \\isog restr_perm H @* Aut G.\n\n(*This lemma provides a reflection property, stating that the group of automorphisms induced on a subgroup is isomorphic to the full automorphism group of the subgroup if and only if every automorphism of the subgroup can be extended to an automorphism of the larger group.*)\nLemma Aut_sub_fullP :\n reflect (forall h : {morphism H >-> gT}, 'injm h -> h @* H = H ->\n exists g : {morphism G >-> gT},\n [/\\ 'injm g, g @* G = G & {in H, g =1 h}])\n (Aut_in (Aut G) H \\isog Aut H).\n\nEnd AutIn.\n\nArguments Aut_in {gT} A%_g B%_g.\n\nSection InjmAutIn.\n\nVariables (gT rT : finGroupType) (D G H : {group gT}) (f : {morphism D >-> rT}).\nHypotheses (injf : 'injm f) (sGD : G \\subset D) (sHG : H \\subset G).\n(*This definition establishes that a group H is a subset of a group D by transitivity, given that H is a subset of an intermediate group G and G is a subset of D.*)\nLet sHD := subset_trans sHG sGD.\n(*This notation defines a group isomorphism between the automorphism group of a group G and the automorphism group of the image of G under an injective group morphism.*)\nLocal Notation fGisom := (Aut_isom injf sGD).\n(*This notation defines a group isomorphism between the automorphism group of a group H and the automorphism group of the image of H under an injective group morphism.*)\nLocal Notation fHisom := (Aut_isom injf sHD).\n(*This notation provides a shorthand for the operation that restricts a permutation to a specific subgroup H.*)\nLocal Notation inH := (restr_perm H).\n(*This notation provides a shorthand for the operation that restricts a permutation to the image of a subgroup H under a morphism.*)\nLocal Notation infH := (restr_perm (f @* H)).\n\n(*This lemma states that for an automorphism of a group, the property of being in the normalizer of a subgroup is preserved under an isomorphism. An automorphism stabilizes a subgroup if and only if its isomorphic image stabilizes the image of that subgroup.*)\nLemma astabs_Aut_isom a :\n a \\in Aut G -> (fGisom a \\in 'N(f @* H | 'P)) = (a \\in 'N(H | 'P)).\n\n(*This lemma asserts that for any automorphism of a group, applying an isomorphism after restricting the automorphism to a subgroup yields the same result as restricting the isomorphically mapped automorphism to the image of that subgroup.*)\nLemma isom_restr_perm a : a \\in Aut G -> fHisom (inH a) = infH (fGisom a).\n\n(*This lemma states that an isomorphism can be established between the group of restricted automorphisms on a subgroup and the group of restricted automorphisms on its isomorphic image.*)\nLemma restr_perm_isom : isom (inH @* Aut G) (infH @* Aut (f @* G)) fHisom.\n\n(*This lemma states that the group of automorphisms induced on a subgroup is isomorphic to the group of automorphisms induced on the image of that subgroup under an injective morphism.*)\nLemma injm_Aut_sub : Aut_in (Aut (f @* G)) (f @* H) \\isog Aut_in (Aut G) H.\n\n(*This lemma states that the property of the induced automorphism group on a subgroup being isomorphic to the full automorphism group of that subgroup is equivalent for a group and its image under an injective morphism.*)\nLemma injm_Aut_full :\n (Aut_in (Aut (f @* G)) (f @* H) \\isog Aut (f @* H))\n = (Aut_in (Aut G) H \\isog Aut H).\n\nEnd InjmAutIn.\n\nSection GroupAction.\n\nVariables (aT rT : finGroupType) (D : {set aT}) (R : {set rT}).\n(*This notation provides a shorthand for the type of actions where elements of a set D act on the elements of a finite group type.*)\nLocal Notation actT := (action D rT).\n\n(*This definition specifies the property that an action is a group action, which requires that for every element of the acting set, the corresponding permutation on the target set must be an automorphism of the target group.*)\nDefinition is_groupAction (to : actT) :=\n {in D, forall a, actperm to a \\in Aut R}.\n\n(*This structure defines a group action by bundling an action with a proof that it satisfies the property of being a group action, where each acting element induces an automorphism on the target group.*)\nStructure groupAction := GroupAction {gact :> actT; _ : is_groupAction gact}.\n\n(*This definition provides a mechanism to clone a group action structure, which is mainly used to define related notations.*)\nDefinition clone_groupAction to :=\n let: GroupAction _ toA := to return {type of GroupAction for to} -> _ in\n fun k => k toA : groupAction.\n\nEnd GroupAction.\n\nDelimit Scope groupAction_scope with gact.\nBind Scope groupAction_scope with groupAction.\n\nArguments is_groupAction {aT rT D%_g} R%_g to%_act.\nArguments groupAction {aT rT} D%_g R%_g.\nArguments gact {aT rT D%_g R%_g} to%_gact : rename.\n\n(*This notation constructs a certified group action from a given raw action, requiring a proof that the action's permutations are automorphisms.*)\nNotation \"[ 'groupAction' 'of' to ]\" :=\n (clone_groupAction (@GroupAction _ _ _ _ to))\n (format \"[ 'groupAction' 'of' to ]\") : form_scope.\n\nSection GroupActionDefs.\n\nVariables (aT rT : finGroupType) (D : {set aT}) (R : {set rT}).\nImplicit Type A : {set aT}.\nImplicit Type S : {set rT}.\nImplicit Type to : groupAction D R.\n\n(*This definition specifies the range of a group action, which is the group on which the action is defined.*)\nDefinition gact_range of groupAction D R := R.\n\n(*This definition specifies the centralizer for a group action, which consists of all elements in the target group that are fixed by every acting element from a given subset of the acting group.*)\nDefinition gacent to A := 'Fix_(R | to)(D :&: A).\n\n(*This definition specifies the property that a subset of an acting group acts on a subgroup of the target group, meaning the action stabilizes the subgroup.*)\nDefinition acts_on_group A S to := [acts A, on S | to] /\\ S \\subset R.\n\nCoercion actby_cond_group A S to : acts_on_group A S to -> actby_cond A S to :=\n @proj1 _ _.\n\n(*This definition specifies that an action is irreducible on a given subgroup, meaning that this subgroup is a minimal non-trivial subgroup that is stabilized by the acting set.*)\nDefinition acts_irreducibly A S to :=\n [min S of G | G :!=: 1 & [acts A, on G | to]].\n\nEnd GroupActionDefs.\n\nArguments gacent {aT rT D%_g R%_g} to%_gact A%_g.\nArguments acts_on_group {aT rT D%_g R%_g} A%_g S%_g to%_gact.\nArguments acts_irreducibly {aT rT D%_g R%_g} A%_g S%_g to%_gact.\n\n(*This notation denotes the centralizer of a set with respect to a group action, which is the set of all elements in the target group that are fixed by every element of the acting set.*)\nNotation \"''C_' ( | to ) ( A )\" := (gacent to A)\n (format \"''C_' ( | to ) ( A )\") : group_scope.\n(*This notation denotes the centralizer of a set with respect to a group action, restricted to a specific subgroup. It represents the set of elements within that subgroup that are fixed by every element of the acting set.*)\nNotation \"''C_' ( G | to ) ( A )\" := (G :&: 'C_(|to)(A))\n (format \"''C_' ( G | to ) ( A )\") : group_scope.\n(*This notation represents the centralizer of a single element with respect to a given group action. It expands to the set of all elements in the acting domain that fix the given element.*)\nNotation \"''C_' ( | to ) [ a ]\" := 'C_(|to)([set a])\n (format \"''C_' ( | to ) [ a ]\") : group_scope.\n(*This notation denotes the centralizer of a single element within a given subgroup with respect to a group action. It identifies all elements within the subgroup that fix the specified element under the action.*)\nNotation \"''C_' ( G | to ) [ a ]\" := 'C_(G | to)([set a])\n (format \"''C_' ( G | to ) [ a ]\") : group_scope.\n\n(*This notation asserts that a set acts on a group via a map, meaning that the action of any element from the set on any element of the group results in an element that is also in the group.*)\nNotation \"{ 'acts' A , 'on' 'group' G | to }\" := (acts_on_group A G to)\n (format \"{ 'acts' A , 'on' 'group' G | to }\") : type_scope.\n\nSection RawGroupAction.\n\nVariables (aT rT : finGroupType) (D : {set aT}) (R : {set rT}).\nVariable to : groupAction D R.\n\n(*This lemma states that for any element of the acting domain, its corresponding action map on the target set is a group automorphism.*)\nLemma actperm_Aut : is_groupAction R to. \n\n(*This lemma states that the image of the acting domain, when mapped to its corresponding action permutations, is a subset of the automorphism group of the target set.*)\nLemma im_actperm_Aut : actperm to @* D \\subset Aut R.\n\n(*This lemma states that if an element from the acting domain acts on an element outside the designated target set, the element remains unchanged.*)\nLemma gact_out x a : a \\in D -> x \\notin R -> to x a = x.\n\n(*This lemma states that for any element in the acting domain, the corresponding action map is a group homomorphism on the target set with respect to the group's multiplication operation.*)\nLemma gactM : {in D, forall a, {in R &, {morph to^~ a : x y / x * y}}}.\n\n(*This lemma asserts that for any fixed element in the target set, the function mapping an element from the acting domain to its action on that fixed element is a group homomorphism.*)\nLemma actmM a : {in R &, {morph actm to a : x y / x * y}}.\n\nCanonical act_morphism a := Morphism (actmM a).\n\n(*This lemma states an equality between the image of a set under an action-related map and the image of a set under the group action, connecting two different perspectives on the action's application.*)\nLemma morphim_actm :\n {in D, forall a (S : {set rT}), S \\subset R -> actm to a @* S = to^* S a}.\n\nVariables (a : aT) (A B : {set aT}) (S : {set rT}).\n\n(*This lemma states that the centralizer of the intersection of the acting domain with a given set is equal to the centralizer of that set.*)\nLemma gacentIdom : 'C_(|to)(D :&: A) = 'C_(|to)(A).\n\n(*This lemma states that explicitly restricting the centralizer check to the action's target set does not change the resulting centralizer, as this restriction is already implicit.*)\nLemma gacentIim : 'C_(R | to)(A) = 'C_(|to)(A).\n\n(*This lemma asserts that the centralizer is a contravariant operation with respect to set inclusion; that is, if a set is a subset of another set, then the centralizer of the larger set is a subset of the centralizer of the smaller set.*)\nLemma gacentS : A \\subset B -> 'C_(|to)(B) \\subset 'C_(|to)(A).\n\n(*This lemma states that the centralizer of the union of two sets is equal to the intersection of the centralizers of each set.*)\nLemma gacentU : 'C_(|to)(A :|: B) = 'C_(|to)(A) :&: 'C_(|to)(B).\n\nHypotheses (Da : a \\in D) (sAD : A \\subset D) (sSR : S \\subset R).\n\n(*This lemma provides an alternative characterization of the action centralizer, stating that it is equal to the set of elements in the acting domain that fix every element of the given set.*)\nLemma gacentE : 'C_(|to)(A) = 'Fix_(R | to)(A).\n\n(*This lemma provides an alternative characterization of the action centralizer of a single element, stating that it is equal to the set of elements in the acting domain that fix that element.*)\nLemma gacent1E : 'C_(|to)[a] = 'Fix_(R | to)[a].\n\n(*This lemma provides an alternative characterization of the sub-centralizer relative to a subset of the target, stating it is equal to the set of elements in the acting domain that fix every element of a given set within that subset.*)\nLemma subgacentE : 'C_(S | to)(A) = 'Fix_(S | to)(A).\n\n(*This lemma provides an alternative characterization of the sub-centralizer of a single element, stating it is equal to the set of elements in the acting domain that fix that element within a given subset of the target.*)\nLemma subgacent1E : 'C_(S | to)[a] = 'Fix_(S | to)[a].\n\nEnd RawGroupAction.\n\nSection GroupActionTheory.\n\nVariables aT rT : finGroupType.\nVariables (D : {group aT}) (R : {group rT}) (to : groupAction D R).\nImplicit Type A B : {set aT}.\nImplicit Types G H : {group aT}.\nImplicit Type S : {set rT}.\nImplicit Types M N : {group rT}.\n\n(*This lemma states that the action of the identity element of the acting group on any element of the target type results in the identity element of the target group.*)\nLemma gact1 : {in D, forall a, to 1 a = 1}.\n\n(*This lemma states that for any element of the acting group, the corresponding action map commutes with the group inversion operation on the target group.*)\nLemma gactV : {in D, forall a, {in R, {morph to^~ a : x / x^-1}}}.\n\n(*This lemma states that for any element of the acting group, the corresponding action map commutes with integer exponentiation on the target group.*)\nLemma gactX : {in D, forall a n, {in R, {morph to^~ a : x / x ^+ n}}}.\n\n(*This lemma states that for any element of the acting group, the corresponding action map preserves the conjugation operation on the target group.*)\nLemma gactJ : {in D, forall a, {in R &, {morph to^~ a : x y / x ^ y}}}.\n\n(*This lemma states that for any element of the acting group, the corresponding action map preserves the commutator operation on the target group.*)\nLemma gactR : {in D, forall a, {in R &, {morph to^~ a : x y / [~ x, y]}}}.\n\n(*This lemma asserts that the given group action is stable, meaning that the action of any element from the acting group on an element of the target group results in an element that is also within the target group.*)\nLemma gact_stable : {acts D, on R | to}.\n\n(*This lemma states that the centralizer of any set with respect to a group action forms a subgroup of the acting group.*)\nLemma group_set_gacent A : group_set 'C_(|to)(A).\n\nCanonical gacent_group A := Group (group_set_gacent A).\n\n(*This lemma states that the centralizer of the identity subgroup of the target group with respect to the group action is equal to the entire target group.*)\nLemma gacent1 : 'C_(|to)(1) = R.\n\n(*This lemma states that the centralizer of the subgroup generated by a set of elements is equal to the centralizer of the set of generators itself.*)\nLemma gacent_gen A : A \\subset D -> 'C_(|to)(<>) = 'C_(|to)(A).\n\n(*This lemma states that the centralizer of the conjugate closure of a set is equal to the centralizer of the original set.*)\nLemma gacentD1 A : 'C_(|to)(A^#) = 'C_(|to)(A).\n\n(*This lemma states that the centralizer of the cyclic group generated by an element is equal to the centralizer of that element.*)\nLemma gacent_cycle a : a \\in D -> 'C_(|to)(<[a]>) = 'C_(|to)[a].\n\n(*This lemma states that the centralizer of the subgroup generated by two sets is equal to the intersection of the centralizers of each set.*)\nLemma gacentY A B :\n A \\subset D -> B \\subset D -> 'C_(|to)(A <*> B) = 'C_(|to)(A) :&: 'C_(|to)(B).\n\n(*This lemma states that the centralizer of the subgroup generated by two given subgroups is equal to the intersection of their individual centralizers.*)\nLemma gacentM G H :\n G \\subset D -> H \\subset D -> 'C_(|to)(G * H) = 'C_(|to)(G) :&: 'C_(|to)(H).\n\n(*This lemma states that the centralizer of the trivial subgroup under a group action is equal to the entire domain of that action.*)\nLemma astab1 : 'C(1 | to) = D.\n\n(*This lemma states that the centralizer of the entire acting group under a group action is equal to the set of fixed points of that action.*)\nLemma astab_range : 'C(R | to) = 'C(setT | to).\n\n(*This lemma states a Galois connection property between centralizers: for a subset of the domain and a subset of the acting group, the second subset is included in the centralizer of the first if and only if the first subset is included in the centralizer of the second.*)\nLemma gacentC A S :\n A \\subset D -> S \\subset R ->\n (S \\subset 'C_(|to)(A)) = (A \\subset 'C(S | to)).\n\n(*This lemma states that the centralizer of the subgroup generated by a subset of the acting group is equal to the centralizer of the subset itself.*)\nLemma astab_gen S : S \\subset R -> 'C(<> | to) = 'C(S | to).\n\n(*This lemma states that the centralizer of the product of two subsets of the acting group is equal to the intersection of their individual centralizers.*)\nLemma astabM M N :\n M \\subset R -> N \\subset R -> 'C(M * N | to) = 'C(M | to) :&: 'C(N | to).\n\n(*This lemma states that the normalizer of the trivial subgroup under a group action is equal to the entire domain of that action.*)\nLemma astabs1 : 'N(1 | to) = D.\n\n(*This lemma states that the normalizer of the entire acting group under a group action is equal to the entire domain of that action.*)\nLemma astabs_range : 'N(R | to) = D.\n\n(*This lemma states that the normalizer of the normal closure of a subset of the acting group is equal to the normalizer of the subset itself.*)\nLemma astabsD1 S : 'N(S^# | to) = 'N(S | to).\n\n(*This lemma states that any subgroup of the domain of a group action itself acts on the acting group.*)\nLemma gacts_range A : A \\subset D -> {acts A, on group R | to}.\n\n(*This lemma states that the normalizer of a subgroup of the domain acts on the centralizer of that same subgroup.*)\nLemma acts_subnorm_gacent A : A \\subset D ->\n [acts 'N_D(A), on 'C_(| to)(A) | to].\n\n(*This lemma states that if a subgroup of the acting group stabilizes a subset of the group being acted upon, then for any given subgroup, the normalizer of the given subgroup within the stabilizing subgroup also stabilizes the centralizer of the given subgroup within the stabilized subset.*)\nLemma acts_subnorm_subgacent A B S :\n A \\subset D -> [acts B, on S | to] -> [acts 'N_B(A), on 'C_(S | to)(A) | to].\n\n(*This lemma states that if a group acts on a subset of another group, it also acts on the subgroup generated by that subset.*)\nLemma acts_gen A S :\n S \\subset R -> [acts A, on S | to] -> [acts A, on <> | to].\n\n(*This lemma states that if a group acts on two subgroups, it also acts on the subgroup generated by their union.*)\nLemma acts_joing A M N :\n M \\subset R -> N \\subset R -> [acts A, on M | to] -> [acts A, on N | to] ->\n [acts A, on M <*> N | to].\n\n(*This lemma states that for any element of the acting group, the corresponding action morphism is injective.*)\nLemma injm_actm a : 'injm (actm to a).\n\n(*This lemma states that the image of the acting group under the action morphism corresponding to an element is the entire acting group itself.*)\nLemma im_actm a : actm to a @* R = R.\n\n(*This lemma states that any subgroup of the group defining an action acts on any characteristic subgroup of the group being acted upon.*)\nLemma acts_char G M : G \\subset D -> M \\char R -> [acts G, on M | to].\n\n(*This lemma states that any subgroup of the group defining an action acts on any characteristic subgroup of the group being acted upon by group automorphisms.*)\nLemma gacts_char G M :\n G \\subset D -> M \\char R -> {acts G, on group M | to}.\n\nSection Restrict.\n\nVariables (A : {group aT}) (sAD : A \\subset D).\n\n(*This lemma states that restricting a group action to a subgroup of its domain results in a valid group action.*)\nLemma ract_is_groupAction : is_groupAction R (to \\ sAD).\n\nCanonical ract_groupAction := GroupAction ract_is_groupAction.\n\n(*This lemma states that the set of points fixed by a subset under a restricted action is equal to the set of points fixed by the intersection of the restriction domain and that subset under the original action.*)\nLemma gacent_ract B : 'C_(|ract_groupAction)(B) = 'C_(|to)(A :&: B).\n\nEnd Restrict.\n\nSection ActBy.\n\nVariables (A : {group aT}) (G : {group rT}) (nGAg : {acts A, on group G | to}).\n\n(*This lemma states that a given action of one group on another group is a valid group action.*)\nLemma actby_is_groupAction : is_groupAction G <[nGAg]>.\n\nCanonical actby_groupAction := GroupAction actby_is_groupAction.\n\n(*This lemma states that the set of points in a group fixed by a subset of an acting group is equal to the set of points fixed by the intersection of the acting group and that subset under a more general ambient action.*)\nLemma gacent_actby B :\n 'C_(|actby_groupAction)(B) = 'C_(G | to)(A :&: B).\n\nEnd ActBy.\n\nSection Quotient.\n\nVariable H : {group rT}.\n\n(*This lemma states that the domain of a quotient action with respect to a subgroup acts on the normalizer of that same subgroup.*)\nLemma acts_qact_dom_norm : {acts qact_dom to H, on 'N(H) | to}.\n\n(*This lemma states that a quotient action on a quotient group is a valid group action.*)\nLemma qact_is_groupAction : is_groupAction (R / H) (to / H).\n\nCanonical quotient_groupAction := GroupAction qact_is_groupAction.\n\n(*This lemma states that the domain of a quotient action with respect to a subgroup is equal to the normalizer of that subgroup under the original action.*)\nLemma qact_domE : H \\subset R -> qact_dom to H = 'N(H | to).\n\nEnd Quotient.\n\nSection Mod.\n\nVariable H : {group aT}.\n\n(*This lemma states that the modular action with respect to a subgroup is a valid group action on the centralizer of that subgroup.*)\nLemma modact_is_groupAction : is_groupAction 'C_(|to)(H) (to %% H).\n\nCanonical mod_groupAction := GroupAction modact_is_groupAction.\n\n(*This lemma provides an explicit formula for the modular action, stating that under certain conditions, a group element acting on a coset via the modular action is equivalent to that element acting on the coset representative via the original action.*)\nLemma modgactE x a :\n H \\subset 'C(R | to) -> a \\in 'N_D(H) -> (to %% H)%act x (coset H a) = to x a.\n\n(*This lemma states that under certain conditions on subgroups, the centralizer of a quotient group within a set under the modular action is equal to the centralizer of the original group within that same set under the original action.*)\nLemma gacent_mod G M :\n H \\subset 'C(M | to) -> G \\subset 'N(H) ->\n 'C_(M | mod_groupAction)(G / H) = 'C_(M | to)(G).\n\n(*This lemma states that if a group acts irreducibly on a set under a given action, then under certain conditions, the corresponding quotient group acts irreducibly on the same set under the modular action.*)\nLemma acts_irr_mod G M :\n H \\subset 'C(M | to) -> G \\subset 'N(H) -> acts_irreducibly G M to ->\n acts_irreducibly (G / H) M mod_groupAction.\n\n \nEnd Mod.\n\n(*This lemma provides an explicit formula for the modular action with respect to the centralizer of the acting group, stating that a group element acting on a coset is equivalent to that element acting on the coset representative via the original action.*)\nLemma modact_coset_astab x a :\n a \\in D -> (to %% 'C(R | to))%act x (coset _ a) = to x a.\n\n(*This lemma states that if a group acts irreducibly on a set, then the quotient of that group by its centralizer of the set also acts irreducibly on that set via the corresponding modular action.*)\nLemma acts_irr_mod_astab G M :\n acts_irreducibly G M to ->\n acts_irreducibly (G / 'C_G(M | to)) M (mod_groupAction _).\n\n \nSection CompAct.\n\nVariables (gT : finGroupType) (G : {group gT}) (f : {morphism G >-> aT}).\n\n(*This lemma states that the composite action, formed by applying a group morphism and then an existing group action, is itself a valid group action.*)\nLemma comp_is_groupAction : is_groupAction R (comp_action to f).\n\nCanonical comp_groupAction := GroupAction comp_is_groupAction.\n\n(*This lemma states that the centralizer of a set of elements under a composite group action is equal to the centralizer of the image of that set, under the composing group morphism, with respect to the original group action.*)\nLemma gacent_comp U : 'C_(|comp_groupAction)(U) = 'C_(|to)(f @* U).\n\nEnd CompAct.\n\nEnd GroupActionTheory.\n\n(*This notation denotes the set of elements in the target type that remain fixed under the action of every element from a given set of group elements, with respect to a specific group action.*)\nNotation \"''C_' ( | to ) ( A )\" := (gacent_group to A) : Group_scope.\n(*This notation denotes the subgroup formed by intersecting a given group with the set of elements that are fixed by every element of a given set under a specific group action.*)\nNotation \"''C_' ( G | to ) ( A )\" :=\n (setI_group G 'C_(|to)(A)) : Group_scope.\n(*This notation denotes the set of elements in the target type that remain fixed under the action of a single specified group element, with respect to a specific group action.*)\nNotation \"''C_' ( | to ) [ a ]\" := (gacent_group to [set a%g]) : Group_scope.\n(*This notation denotes the subgroup formed by intersecting a given group with the set of elements that are fixed by a single specified group element under a specific group action.*)\nNotation \"''C_' ( G | to ) [ a ]\" :=\n (setI_group G 'C_(|to)[a]) : Group_scope.\n\n(*This notation denotes the restriction of a group action to a specified subgroup and an invariant subset of the target type.*)\nNotation \"to \\ sAD\" := (ract_groupAction to sAD) : groupAction_scope.\n(*This notation denotes the group action generated by a given set of automorphisms on the target type.*)\nNotation \"<[ nGA ] >\" := (actby_groupAction nGA) : groupAction_scope.\n(*This notation denotes the induced group action on the set of right cosets of a given subgroup.*)\nNotation \"to / H\" := (quotient_groupAction to H) : groupAction_scope.\n(*This notation denotes the induced group action of a quotient group on the original target type, where the quotient is taken by a normal subgroup that is in the kernel of the action.*)\nNotation \"to %% H\" := (mod_groupAction to H) : groupAction_scope.\n(*This notation denotes the composite group action created by first applying a group morphism and then applying a given group action.*)\nNotation \"to \\o f\" := (comp_groupAction to f) : groupAction_scope.\n\nSection MorphAction.\n\nVariables (aT1 aT2 : finGroupType) (rT1 rT2 : finType).\nVariables (D1 : {group aT1}) (D2 : {group aT2}).\nVariables (to1 : action D1 rT1) (to2 : action D2 rT2).\nVariables (A : {set aT1}) (R S : {set rT1}).\nVariables (h : rT1 -> rT2) (f : {morphism D1 >-> aT2}).\nHypotheses (actsDR : {acts D1, on R | to1}) (injh : {in R &, injective h}).\nHypothesis defD2 : f @* D1 = D2.\nHypotheses (sSR : S \\subset R) (sAD1 : A \\subset D1).\nHypothesis hfJ : {in S & D1, morph_act to1 to2 h f}.\n\n(*This lemma states that for two group actions related by a group morphism and a compatible map between the target types, the image of the normalizer of a set under the first action is equal to the normalizer of the image of that set under the second action.*)\nLemma morph_astabs : f @* 'N(S | to1) = 'N(h @: S | to2).\n\n(*This lemma states that for two group actions related by a group morphism and a compatible map between the target types, the image of the centralizer of a set under the first action is equal to the centralizer of the image of that set under the second action.*)\nLemma morph_astab : f @* 'C(S | to1) = 'C(h @: S | to2).\n\n(*This lemma states that for two group actions related by a group morphism and a compatible map between target types, the image of the set of fixed points of a subset under the first action is equal to the set of fixed points of the image of that subset under the second action.*)\nLemma morph_afix : h @: 'Fix_(S | to1)(A) = 'Fix_(h @: S | to2)(f @* A).\n\nEnd MorphAction.\n\nSection MorphGroupAction.\n\nVariables (aT1 aT2 rT1 rT2 : finGroupType).\nVariables (D1 : {group aT1}) (D2 : {group aT2}).\nVariables (R1 : {group rT1}) (R2 : {group rT2}).\nVariables (to1 : groupAction D1 R1) (to2 : groupAction D2 R2).\nVariables (h : {morphism R1 >-> rT2}) (f : {morphism D1 >-> aT2}).\nHypotheses (iso_h : isom R1 R2 h) (iso_f : isom D1 D2 f).\nHypothesis hfJ : {in R1 & D1, morph_act to1 to2 h f}.\nImplicit Types (A : {set aT1}) (S : {set rT1}) (M : {group rT1}).\n\n(*This lemma states that for two group actions related by group isomorphisms, the image of the normalizer subgroup of a given subgroup under the first action is equal to the normalizer subgroup of the image of that subgroup under the second action.*)\nLemma morph_gastabs S : S \\subset R1 -> f @* 'N(S | to1) = 'N(h @* S | to2).\n\n(*This lemma states that for two group actions related by group isomorphisms, the image of the centralizer subgroup of a given subgroup under the first action is equal to the centralizer subgroup of the image of that subgroup under the second action.*)\nLemma morph_gastab S : S \\subset R1 -> f @* 'C(S | to1) = 'C(h @* S | to2).\n\n(*This lemma states that for two group actions related by group isomorphisms, the image of the centralizer subgroup in the target group under the first action is equal to the centralizer subgroup in the target group corresponding to the image of the acting set under the second action.*)\nLemma morph_gacent A : A \\subset D1 -> h @* 'C_(|to1)(A) = 'C_(|to2)(f @* A).\n\n(*This lemma states that for two group actions related by group isomorphisms, the property of a group acting irreducibly on a subgroup is preserved across the actions; that is, one action is irreducible if and only if the corresponding action on the image subgroups is also irreducible.*)\nLemma morph_gact_irr A M :\n A \\subset D1 -> M \\subset R1 ->\n acts_irreducibly (f @* A) (h @* M) to2 = acts_irreducibly A M to1.\n\nEnd MorphGroupAction.\n\nSection InternalActionDefs.\n\nVariable gT : finGroupType.\nImplicit Type A : {set gT}.\nImplicit Type G : {group gT}.\n\n(*This definition specifies the group action of a group on itself by right multiplication.*)\nDefinition mulgr_action := TotalAction (@mulg1 gT) (@mulgA gT).\n\nCanonical conjg_action := TotalAction (@conjg1 gT) (@conjgM gT).\n\n(*This lemma states that the action of a group on its power set, induced by the conjugation action on individual elements, is a valid group action.*)\nLemma conjg_is_groupAction : is_groupAction setT conjg_action.\n\nCanonical conjg_groupAction := GroupAction conjg_is_groupAction.\n\n(*This lemma states that the operation of right multiplication of a subset of a group by a group element constitutes a valid group action on the power set of the group.*)\nLemma rcoset_is_action : is_action setT (@rcoset gT).\n\nCanonical rcoset_action := Action rcoset_is_action.\n\nCanonical conjsg_action := TotalAction (@conjsg1 gT) (@conjsgM gT).\n\n(*This lemma states that the operation of conjugating a subgroup by an element of the ambient group constitutes a valid group action on the set of all subgroups.*)\nLemma conjG_is_action : is_action setT (@conjG_group gT).\n\n(*This definition establishes the formal group action corresponding to the conjugation of subgroups by elements of the ambient group.*)\nDefinition conjG_action := Action conjG_is_action.\n\nEnd InternalActionDefs.\n\n(*This notation denotes the action of a group on itself by right multiplication.*)\nNotation \"'R\" := (@mulgr_action _) (at level 8) : action_scope.\n(*This notation denotes the action of a group on its power set via right multiplication.*)\nNotation \"'Rs\" := (@rcoset_action _) (at level 8) : action_scope.\n(*This notation denotes the action of a group on itself or on its subgroups by conjugation.*)\nNotation \"'J\" := (@conjg_action _) (at level 8) : action_scope.\n(*A notational convention representing a generic group, typically used as the acting group in contexts involving group actions. For example, it is the acting group in the definitions of the orbit set notation 'Q and conjugation actions.*)\nNotation \"'J\" := (@conjg_groupAction _) (at level 8) : groupAction_scope.\n(*A notation representing the conjugation action of a group on its own set of subgroups. In this action, a group element acts on a subgroup to produce a new subgroup by conjugating the original one.*)\nNotation \"'Js\" := (@conjsg_action _) (at level 8) : action_scope.\n(*A notation representing the conjugation action of a group on its own elements. In this action, a group element acts on another element by conjugation, which means multiplying by the acting element on the left and its inverse on the right.*)\nNotation \"'JG\" := (@conjG_action _) (at level 8) : action_scope.\n(*A notation that represents the set of orbits for a group action. It accepts an action performed by a specific, contextually-defined group as an argument and evaluates to the collection of all orbits produced by that action.*)\nNotation \"'Q\" := ('J / _)%act (at level 8) : action_scope.\n(*This notation represents a generic or user-defined group action, used to specify how group elements operate on other mathematical objects.*)\nNotation \"'Q\" := ('J / _)%gact (at level 8) : groupAction_scope.\n\nSection InternalGroupAction.\n\nVariable gT : finGroupType.\nImplicit Types A B : {set gT}.\nImplicit Types G H : {group gT}.\nImplicit Type x : gT.\n\n(*This lemma states that the orbit of a group element under the right regular action of a group is equivalent to the right coset of that element.*)\nLemma orbitR G x : orbit 'R G x = x *: G.\n\n(*This lemma states that the stabilizer of any single group element under the right regular action is the trivial group containing only the identity element.*)\nLemma astab1R x : 'C[x | 'R] = 1.\n\n(*This lemma states that the pointwise stabilizer of a group under the right regular action is the trivial group.*)\nLemma astabR G : 'C(G | 'R) = 1.\n\n(*This lemma states that the setwise stabilizer of a group under its own right regular action is the group itself.*)\nLemma astabsR G : 'N(G | 'R) = G.\n\n(*This lemma states that the right regular action of a group on itself is transitive.*)\nLemma atransR G : [transitive G, on G | 'R].\n\n(*This lemma states that the right regular action of a group on itself is faithful.*)\nLemma faithfulR G : [faithful G, on G | 'R].\n\n(*This definition specifies the Cayley representation of a group as the group of permutations induced by the transitive right regular action of the group on its own elements.*)\nDefinition Cayley_repr G := actperm <[atrans_acts (atransR G)]>.\n\n(*This theorem asserts that the Cayley representation defines a group isomorphism between a given group and the image of that group under the representation.*)\nTheorem Cayley_isom G : isom G (Cayley_repr G @* G) (Cayley_repr G).\n\n(*This theorem asserts that any group is isomorphic to the group of permutations generated by its Cayley representation.*)\nTheorem Cayley_isog G : G \\isog Cayley_repr G @* G.\n\n(*This lemma states that the orbit of a group element under the conjugation action of a group is the conjugacy class of that element within the group.*)\nLemma orbitJ G x : orbit 'J G x = x ^: G. \n\n(*This lemma states that the set of elements that are fixed points under the conjugation action of a given set is the centralizer of that set.*)\nLemma afixJ A : 'Fix_('J)(A) = 'C(A).\n\n(*This lemma states that the pointwise stabilizer of a set of elements under the conjugation action is the centralizer of that set.*)\nLemma astabJ A : 'C(A |'J) = 'C(A).\n\n(*This lemma states that the stabilizer of a single group element under the conjugation action is the centralizer of that element.*)\nLemma astab1J x : 'C[x |'J] = 'C[x].\n\n(*This lemma states that the setwise stabilizer of a set of elements under the conjugation action is the normalizer of that set.*)\nLemma astabsJ A : 'N(A | 'J) = 'N(A).\n\n(*This lemma states that applying the set conjugation action to a set by an element is equivalent to conjugating the set by that element.*)\nLemma setactJ A x : 'J^*%act A x = A :^ x. \n\n(*This lemma states that the kernel of the conjugation action of a group is equal to the centralizer of that group.*)\nLemma gacentJ A : 'C_(|'J)(A) = 'C(A).\n\n(*This lemma states that the orbit of a set under the right multiplication action of a group is the collection of all right cosets of the set.*)\nLemma orbitRs G A : orbit 'Rs G A = rcosets A G. \n\n(*This lemma states that a right coset of a group is a fixed point under the right multiplication action of a given set if and only if the set is a subset of the conjugate of the group by the coset's representative.*)\nLemma sub_afixRs_norms G x A : (G :* x \\in 'Fix_('Rs)(A)) = (A \\subset G :^ x).\n\n(*This lemma states that a right coset of a group is a fixed point under the right multiplication action of the group itself if and only if the coset's representative belongs to the normalizer of the group.*)\nLemma sub_afixRs_norm G x : (G :* x \\in 'Fix_('Rs)(G)) = (x \\in 'N(G)).\n\n(*This lemma states that the set of fixed points of the right multiplication action of a group on the right cosets of a set is the collection of right cosets of the intersection of the set and its normalizer.*)\nLemma afixRs_rcosets A G : 'Fix_(rcosets G A | 'Rs)(G) = rcosets G 'N_A(G).\n\n(*This lemma states that the stabilizer of a group, considered as a single set, under the right multiplication action is the group itself.*)\nLemma astab1Rs G : 'C[G : {set gT} | 'Rs] = G.\n\n(*This lemma states that a group acts on the set of right cosets of its subgroup via right multiplication.*)\nLemma actsRs_rcosets H G : [acts G, on rcosets H G | 'Rs].\n\n(*This lemma states that the action of a group on the set of right cosets of one of its subgroups is transitive.*)\nLemma transRs_rcosets H G : [transitive G, on rcosets H G | 'Rs].\n\n(*This lemma states that the kernel of the action of a group on the set of right cosets of a subgroup is the group core of that subgroup.*)\nLemma astabRs_rcosets H G : 'C(rcosets H G | 'Rs) = gcore H G.\n\n(*This lemma states that the orbit of a set under the conjugation action of a group is the collection of all sets conjugate to the original set.*)\nLemma orbitJs G A : orbit 'Js G A = A :^: G. \n\n(*This lemma states that the stabilizer of a set under the conjugation action is the normalizer of that set.*)\nLemma astab1Js A : 'C[A | 'Js] = 'N(A).\n\n(*This lemma states that the number of distinct conjugates of a set under the action of a group is equal to the index of the set's normalizer within that group.*)\nLemma card_conjugates A G : #|A :^: G| = #|G : 'N_G(A)|.\n\n(*This lemma states that a subgroup is a fixed point under the conjugation action of a set if and only if that set is a subset of the subgroup's normalizer.*)\nLemma afixJG G A : (G \\in 'Fix_('JG)(A)) = (A \\subset 'N(G)).\n\n(*This lemma states that the stabilizer of a subgroup under the conjugation action is the normalizer of that subgroup.*)\nLemma astab1JG G : 'C[G | 'JG] = 'N(G).\n\n(*This lemma states that the domain of the conjugation action on a given subgroup is equal to the normalizer of that subgroup.*)\nLemma dom_qactJ H : qact_dom 'J H = 'N(H).\n\n(*This lemma specifies the result of the quotient group action. For a given coset and a group element, the action results in the conjugation of the coset by the coset containing the element if the element belongs to the normalizer of the underlying subgroup; otherwise, the action leaves the coset unchanged.*)\nLemma qactJ H (Hy : coset_of H) x :\n 'Q%act Hy x = if x \\in 'N(H) then Hy ^ coset H x else Hy.\n\n(*This lemma provides sufficient conditions for a set of group elements to act on the set of cosets of one subgroup within another, via the quotient action. The action is well-defined if the acting set is a subset of the normalizer of both subgroups.*)\nLemma actsQ A B H :\n A \\subset 'N(H) -> A \\subset 'N(B) -> [acts A, on B / H | 'Q].\n\n(*This lemma states that for a normal subgroup of a given group, the normalizer of the corresponding quotient group under the quotient action is equal to the intersection of the normalizer of the subgroup and the normalizer of the parent group.*)\nLemma astabsQ G H : H <| G -> 'N(G / H | 'Q) = 'N(H) :&: 'N(G).\n\n(*This lemma establishes that the centralizer of a set of cosets under the quotient action is equivalent to the preimage of the centralizer of that set of cosets under the canonical projection map from the group to its cosets.*)\nLemma astabQ H Abar : 'C(Abar |'Q) = coset H @*^-1 'C(Abar).\n\n(*This lemma provides an equivalence for a set of group elements being contained in the centralizer of a set of cosets under the quotient action. This containment holds if and only if the set of elements is a subset of the normalizer of the subgroup, and the corresponding set of cosets is a subset of the centralizer of the target set of cosets.*)\nLemma sub_astabQ A H Bbar :\n (A \\subset 'C(Bbar | 'Q)) = (A \\subset 'N(H)) && (A / H \\subset 'C(Bbar)).\n\n(*This lemma states that for two subgroups contained in the normalizer of a third subgroup, the first subgroup centralizes the quotient of the second by the third under the quotient action if and only if the commutator of the first two subgroups is contained in the third subgroup.*)\nLemma sub_astabQR A B H :\n A \\subset 'N(H) -> B \\subset 'N(H) ->\n (A \\subset 'C(B / H | 'Q)) = ([~: A, B] \\subset H).\n\n(*This lemma provides a characterization of the centralizer of a quotient group under the quotient action, given that the numerator subgroup is contained in the normalizer of the denominator subgroup. The centralizer consists of all elements in the normalizer of the denominator whose commutator with the numerator subgroup is contained within the denominator subgroup.*)\nLemma astabQR A H : A \\subset 'N(H) ->\n 'C(A / H | 'Q) = [set x in 'N(H) | [~: [set x], A] \\subset H].\n\n(*This lemma states that the quotient of the centralizer of a set of cosets, under the quotient action, by the base subgroup is equal to the centralizer of that same set of cosets within the quotient group itself.*)\nLemma quotient_astabQ H Abar : 'C(Abar | 'Q) / H = 'C(Abar).\n\n(*This lemma states that for an element in the normalizer of a subgroup, conjugating the centralizer of a quotient group by that element is equivalent to taking the centralizer of the conjugated quotient group.*)\nLemma conj_astabQ A H x :\n x \\in 'N(H) -> 'C(A / H | 'Q) :^ x = 'C(A :^ x / H | 'Q).\n\nSection CardClass.\n\nVariable G : {group gT}.\n\n(*This lemma, an application of the orbit-stabilizer theorem, states that the index of the centralizer of an element in a group is equal to the size of the conjugacy class of that element.*)\nLemma index_cent1 x : #|G : 'C_G[x]| = #|x ^: G|.\n\n(*This lemma states that the set of conjugacy classes of a group forms a partition of the group.*)\nLemma classes_partition : partition (classes G) G.\n\n(*This lemma states that the sum of the cardinalities of all conjugacy classes of a finite group is equal to the cardinality of the group.*)\nLemma sum_card_class : \\sum_(C in classes G) #|C| = #|G|.\n\n(*This lemma presents the class equation for a finite group, stating that the sum of the indices of the centralizers of representatives from each conjugacy class equals the cardinality of the group.*)\nLemma class_formula : \\sum_(C in classes G) #|G : 'C_G[repr C]| = #|G|.\n\n(*This lemma provides a characterization of an abelian group, stating that a group is abelian if and only if the conjugacy class of every element is a singleton set containing only that element.*)\nLemma abelian_classP : reflect {in G, forall x, x ^: G = [set x]} (abelian G).\n\n(*This lemma states that a finite group is abelian if and only if the number of its conjugacy classes is equal to the number of its elements.*)\nLemma card_classes_abelian : abelian G = (#|classes G| == #|G|).\n\nEnd CardClass.\n\nEnd InternalGroupAction.\n\n(*This lemma equates the centralizer of a set of group elements under the quotient action with the centralizer of the corresponding set of cosets within the quotient group.*)\nLemma gacentQ (gT : finGroupType) (H : {group gT}) (A : {set gT}) :\n 'C_(|'Q)(A) = 'C(A / H).\n\nSection AutAct.\n\nVariable (gT : finGroupType) (G : {set gT}).\n\n(*This definition specifies a group action where the acting space is the powerset of the automorphism group of a given group.*)\nDefinition autact := act ('P \\ subsetT (Aut G)).\nCanonical aut_action := [action of autact].\n\n(*This lemma states that for the canonical action of the automorphism group, the permutation corresponding to a given automorphism is the automorphism itself.*)\nLemma autactK a : actperm aut_action a = a.\n\n(*This lemma asserts that the canonical action of the automorphism group on the group itself satisfies the axioms of a group action.*)\nLemma autact_is_groupAction : is_groupAction G aut_action.\n\nCanonical aut_groupAction := GroupAction autact_is_groupAction.\n\nSection perm_prime_orbit.\nVariable (T : finType) (c : {perm T}).\nHypothesis Tp : prime #|T|.\nHypothesis cc : #[c]%g = #|T|.\n(*This local definition provides a proof that the order of a given permutation is a prime number, derived from the assumption that its order equals the prime cardinality of the underlying finite type.*)\nLet cp : prime #[c]%g. \n\n(*This lemma states that the action of the cyclic group generated by a permutation is transitive on the underlying finite type, given that the type's cardinality is a prime number that equals the order of the permutation.*)\nLemma perm_prime_atrans : [transitive <[c]>, on setT | 'P].\n\n(*This lemma states that for any element of a finite type, its orbit under the action of a cyclic group generated by a specific permutation is the entire set, provided the type's cardinality is a prime number equal to the permutation's order.*)\nLemma perm_prime_orbit x : orbit 'P <[c]> x = [set: T].\n\n(*This lemma asserts that the stabilizer of any element under the action of a cyclic group generated by a specific permutation is the trivial group, under the condition that the underlying type has a prime cardinality equal to the order of the permutation.*)\nLemma perm_prime_astab x : 'C_<[c]>[x | 'P]%g = 1%g.\n\nEnd perm_prime_orbit.\n\nEnd AutAct.\n\nArguments autact {gT} G%_g.\nArguments aut_action {gT} G%_g.\nArguments aut_groupAction {gT} G%_g.\n(*This notation provides a concise syntax for referring to the canonical group action of the automorphism group of a given group acting on the group itself. Depending on the scope, it can represent either the basic action structure or the full group action structure with its associated properties.*)\nNotation \"[ 'Aut' G ]\" := (aut_action G) : action_scope.\n(*A notation representing the automorphism group of a given group. The elements of this group are the bijective homomorphisms from the group onto itself, and the group operation is function composition.*)", - "fingroup.gproduct": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype bigop finset fingroup morphism.\nFrom mathcomp Require Import quotient action finfun.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection Defs.\n\nVariables gT : finGroupType.\nImplicit Types A B C : {set gT}.\n\n(*This definition computes a conditional product of two sets of group elements. If either set is the trivial group, it returns the other set. If both are non-trivial subgroups and the second normalizes the first, it returns their group product. Otherwise, it returns the empty set.*)\nDefinition partial_product A B :=\n if A == 1 then B else if B == 1 then A else\n if [&& group_set A, group_set B & B \\subset 'N(A)] then A * B else set0.\n\n(*This definition computes the internal semidirect product of two sets of group elements. It returns their partial product if their intersection is contained within the trivial group, and the empty set otherwise.*)\nDefinition semidirect_product A B :=\n if A :&: B \\subset 1%G then partial_product A B else set0.\n\n(*This definition computes the internal central product of two sets of group elements. It returns their partial product if the second set is a subset of the centralizer of the first set, and the empty set otherwise.*)\nDefinition central_product A B :=\n if B \\subset 'C(A) then partial_product A B else set0.\n\n(*This definition computes the internal direct product of two sets of group elements. It returns their central product if their intersection is contained within the trivial group, and the empty set otherwise.*)\nDefinition direct_product A B :=\n if A :&: B \\subset 1%G then central_product A B else set0.\n\n(*This definition computes the set of all subgroups that are complements to a given first set of group elements within a second set. A subgroup is a complement if its intersection with the first set is the trivial group and their group product equals the second set.*)\nDefinition complements_to_in A B :=\n [set K : {group gT} | A :&: K == 1 & A * K == B].\n\n(*This definition yields a boolean value indicating whether a first given group splits over a second given group. This is true if there exists at least one subgroup that is a complement to the second group within the first group.*)\nDefinition splits_over B A := complements_to_in A B != set0.\n\n(*This definition computes a representative group element from the intersection of a right coset and a set of group elements. The coset is formed by a given first set and a given group element, and the intersection is taken with a second given set.*)\nDefinition remgr A B x := repr (A :* x :&: B).\n(*This definition computes a group element that acts as a quotient. It is calculated by multiplying a given group element by the inverse of its corresponding remainder, where this remainder is defined with respect to two given sets of group elements.*)\nDefinition divgr A B x := x * (remgr A B x)^-1.\n\nEnd Defs.\n\nArguments partial_product _ _%_g _%_g : clear implicits.\nArguments semidirect_product _ _%_g _%_g : clear implicits.\nArguments central_product _ _%_g _%_g : clear implicits.\nArguments complements_to_in _ _%_g _%_g.\nArguments splits_over _ _%_g _%_g.\nArguments remgr _ _%_g _%_g _%_g.\nArguments divgr _ _%_g _%_g _%_g.\nArguments direct_product : clear implicits.\n(*This notation is an alias for the partial product of two subgroups.*)\nNotation pprod := (partial_product _).\n(*This notation is an alias for the internal semidirect product of two subgroups.*)\nNotation sdprod := (semidirect_product _).\n(*This notation is an alias for the internal central product of two subgroups.*)\nNotation cprod := (central_product _).\n(*This notation is an alias for the internal direct product of two subgroups.*)\nNotation dprod := (direct_product _).\n\n(*This notation denotes the internal semidirect product of two sets of group elements.*)\nNotation \"G ><| H\" := (sdprod G H)%g\n (at level 40, left associativity) : group_scope.\n(*This notation denotes the internal central product of two sets of group elements.*)\nNotation \"G \\* H\" := (cprod G H)%g\n (at level 40, left associativity) : group_scope.\n(*This notation denotes the internal direct product of two sets of group elements.*)\nNotation \"G \\x H\" := (dprod G H)%g\n (at level 40, left associativity) : group_scope.\n\n(*This notation represents the set of all subgroups that are complements to a given subgroup within another subgroup.*)\nNotation \"[ 'complements' 'to' A 'in' B ]\" := (complements_to_in A B)\n (format \"[ 'complements' 'to' A 'in' B ]\") : group_scope.\n\n(*This notation expresses the boolean predicate indicating whether a given group splits over a given subgroup.*)\nNotation \"[ 'splits' B , 'over' A ]\" := (splits_over B A)\n (format \"[ 'splits' B , 'over' A ]\") : group_scope.\n\nPrenex Implicits remgr divgr.\n\nSection InternalProd.\n\nVariable gT : finGroupType.\nImplicit Types A B C : {set gT}.\nImplicit Types G H K L M : {group gT}.\n\n(*An operation representing the internal product of two subgroups, which is defined under the condition that the second subgroup normalizes the first.*)\nLocal Notation pprod := (partial_product gT).\n(*A notation that represents the semidirect product of two groups.*)\nLocal Notation sdprod := (semidirect_product gT) (only parsing).\n(*A notation that represents the central product of two groups.*)\nLocal Notation cprod := (central_product gT) (only parsing).\n(*A notation that represents the direct product of two groups.*)\nLocal Notation dprod := (direct_product gT) (only parsing).\n\n(*This lemma states that the internal product of the trivial group with any group results in that group itself.*)\nLemma pprod1g : left_id 1 pprod.\n\n(*This lemma states that the internal product of any group with the trivial group results in that group itself.*)\nLemma pprodg1 : right_id 1 pprod.\n\n(*An inductive proposition that holds for two sets if they are both groups, thereby providing their explicit group structures.*)\nVariant are_groups A B : Prop := AreGroups K H of A = K & B = H.\n\n(*This lemma states that any group is a non-empty set.*)\nLemma group_not0 G : set0 <> G.\n\n(*This lemma states that the set product of any group with the empty set is the empty set.*)\nLemma mulg0 : right_zero (@set0 gT) mulg.\n\n(*This lemma states that the set product of the empty set with any group is the empty set.*)\nLemma mul0g : left_zero (@set0 gT) mulg.\n\n(*This lemma states that if the internal product of two sets equals a group, then those two sets are subgroups, their set product equals the given group, and the second subgroup is contained in the normalizer of the first.*)\nLemma pprodP A B G :\n pprod A B = G -> [/\\ are_groups A B, A * B = G & B \\subset 'N(A)].\n\n(*This lemma states that if a subgroup is contained in the normalizer of another subgroup, their internal product is equal to their set product.*)\nLemma pprodE K H : H \\subset 'N(K) -> pprod K H = K * H.\n\n(*This lemma states that if a subgroup is contained in the normalizer of another subgroup, their internal product is equal to the subgroup generated by their union.*)\nLemma pprodEY K H : H \\subset 'N(K) -> pprod K H = K <*> H.\n\n(*This lemma states that if the internal product of two subgroups is equal to a group, then their set product is also equal to that group.*)\nLemma pprodW A B G : pprod A B = G -> A * B = G. \n\n(*This lemma states that if the internal product of two subgroups equals a group, then their set product is commutative and also equals that group.*)\nLemma pprodWC A B G : pprod A B = G -> B * A = G.\n\n(*This lemma states that if the internal product of two subgroups equals a group, then the subgroup generated by their union also equals that group.*)\nLemma pprodWY A B G : pprod A B = G -> A <*> B = G.\n\n(*This lemma states that the conjugate of an internal product of two subgroups by an element is equal to the internal product of the conjugates of each subgroup by the same element.*)\nLemma pprodJ A B x : pprod A B :^ x = pprod (A :^ x) (B :^ x).\n\n(*This lemma states that the remainder component of an element, relative to two subgroups, is invariant under left multiplication by any element from the first subgroup.*)\nLemma remgrMl K B x y : y \\in K -> remgr K B (y * x) = remgr K B x.\n\n(*This lemma states that an element belongs to the set product of two subgroups if and only if its remainder relative to these subgroups is an element of both the second subgroup and the right coset of the first subgroup determined by the original element.*)\nLemma remgrP K B x : (remgr K B x \\in K :* x :&: B) = (x \\in K * B).\n\n(*This lemma states that the remainder of an element with respect to two subgroups is the identity element if the element is already contained in the first subgroup.*)\nLemma remgr1 K H x : x \\in K -> remgr K H x = 1.\n\n(*This lemma states that any group element is equal to the product of its quotient and remainder, derived from a decomposition relative to two subgroups.*)\nLemma divgr_eq A B x : x = divgr A B x * remgr A B x.\n\n(*This lemma states that for a product of two elements where the first element belongs to a given subgroup, the quotient of this product with respect to that subgroup and another one is the product of the first element and the quotient of the second element.*)\nLemma divgrMl K B x y : x \\in K -> divgr K B (x * y) = x * divgr K B y.\n\n(*This lemma states that the quotient of an element with respect to two subgroups is the element itself if it is a member of the first subgroup.*)\nLemma divgr_id K H x : x \\in K -> divgr K H x = x.\n\n(*This lemma states that if an element belongs to the set product of two subgroups, its remainder from the decomposition with respect to these subgroups is an element of the second subgroup.*)\nLemma mem_remgr K B x : x \\in K * B -> remgr K B x \\in B.\n\n(*This lemma states that if an element belongs to the set product of two subgroups, its quotient from the decomposition with respect to these subgroups is an element of the first subgroup.*)\nLemma mem_divgr K B x : x \\in K * B -> divgr K B x \\in K.\n\nSection DisjointRem.\n\nVariables K H : {group gT}.\n\nHypothesis tiKH : K :&: H = 1.\n\n(*This lemma states that for two subgroups with a trivial intersection, the remainder of an element belonging to the second subgroup is the element itself.*)\nLemma remgr_id x : x \\in H -> remgr K H x = x.\n\n(*This lemma states that for two subgroups with a trivial intersection, the remainder of a product of an element from the first subgroup and an element from the second subgroup is the element from the second subgroup.*)\nLemma remgrMid x y : x \\in K -> y \\in H -> remgr K H (x * y) = y.\n\n(*This lemma states that for two subgroups with a trivial intersection, the quotient of a product of an element from the first subgroup and an element from the second subgroup is the element from the first subgroup.*)\nLemma divgrMid x y : x \\in K -> y \\in H -> divgr K H (x * y) = x.\n\nEnd DisjointRem.\n\n(*This lemma states that for two subgroups with a trivial intersection, if a set normalizes both subgroups, then the set product of the centralizers of the set in each subgroup is equal to the centralizer of the set in the product of the two subgroups.*)\nLemma subcent_TImulg K H A :\n K :&: H = 1 -> A \\subset 'N(K) :&: 'N(H) -> 'C_K(A) * 'C_H(A) = 'C_(K * H)(A).\n\n(*This lemma concerns properties of group complements, asserting a relationship between a group, a subgroup, and another subgroup that acts as its complement, which typically decompose the group and have a trivial intersection.*)\nLemma complP H A B :\n reflect (A :&: H = 1 /\\ A * H = B) (H \\in [complements to A in B]).\n\n(*This lemma states that a group splits over a subgroup if and only if there exists another subgroup that is a complement to the first subgroup within the larger group.*)\nLemma splitsP B A :\n reflect (exists H, H \\in [complements to A in B]) [splits B, over A].\n\n(*This lemma states that for three groups, the property that the first group is a complement to the second in the third group is equivalent to the property that the second group is a complement to the first in the third group.*)\nLemma complgC H K G :\n (H \\in [complements to K in G]) = (K \\in [complements to H in G]).\n\nSection NormalComplement.\n\nVariables K H G : {group gT}.\n\nHypothesis complH_K : H \\in [complements to K in G].\n\n(*This lemma states that if a group contains a normal subgroup and a complement to it, then the remainder map, which projects elements of the group onto the complement subgroup, is a group morphism.*)\nLemma remgrM : K <| G -> {in G &, {morph remgr K H : x y / x * y}}.\n\n(*This lemma states that if two subgroups are complements within a larger group and the second centralizes the first, then the division map, which projects elements of the group onto the first subgroup, is a group morphism.*)\nLemma divgrM : H \\subset 'C(K) -> {in G &, {morph divgr K H : x y / x * y}}.\n\nEnd NormalComplement.\n\n(*This lemma states that the trivial group is a left identity for the semidirect product operation.*)\nLemma sdprod1g : left_id 1 sdprod.\n\n(*This lemma states that the trivial group is a right identity for the semidirect product operation.*)\nLemma sdprodg1 : right_id 1 sdprod.\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then these subgroups have a trivial intersection, their group product equals the larger group, and the second subgroup normalizes the first.*)\nLemma sdprodP A B G :\n A ><| B = G -> [/\\ are_groups A B, A * B = G, B \\subset 'N(A) & A :&: B = 1].\n\n(*This lemma states that the internal semidirect product of two subgroups is equal to their group product, provided that the second subgroup is contained in the normalizer of the first and their intersection is the trivial group.*)\nLemma sdprodE K H : H \\subset 'N(K) -> K :&: H = 1 -> K ><| H = K * H.\n\n(*This lemma states that the internal semidirect product of two subgroups is equal to the subgroup generated by them, provided that the second subgroup is contained in the normalizer of the first and their intersection is the trivial group.*)\nLemma sdprodEY K H : H \\subset 'N(K) -> K :&: H = 1 -> K ><| H = K <*> H.\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then the set product of these two subgroups equals the group.*)\nLemma sdprodWpp A B G : A ><| B = G -> pprod A B = G.\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then their group product also equals the larger group.*)\nLemma sdprodW A B G : A ><| B = G -> A * B = G.\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups in a given order, then their group product in the reverse order also equals the larger group.*)\nLemma sdprodWC A B G : A ><| B = G -> B * A = G.\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then the subgroup generated by these two subgroups equals the larger group.*)\nLemma sdprodWY A B G : A ><| B = G -> A <*> B = G.\n\n(*This lemma states that the conjugate of an internal semidirect product of two subgroups by an element is equal to the internal semidirect product of their respective conjugates by that same element.*)\nLemma sdprodJ A B x : (A ><| B) :^ x = A :^ x ><| B :^ x.\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then the first subgroup is normal in the group, the second is contained in the group, their group product equals the group, the second subgroup is contained in the normalizer of the first, and their intersection is the trivial group.*)\nLemma sdprod_context G K H : K ><| H = G ->\n [/\\ K <| G, H \\subset G, K * H = G, H \\subset 'N(K) & K :&: H = 1].\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then the second subgroup is a complement to the first subgroup within the larger group.*)\nLemma sdprod_compl G K H : K ><| H = G -> H \\in [complements to K in G].\n\n(*This lemma states that for a group and two of its subgroups, if the first subgroup is normal, then the group being the internal semidirect product of these two subgroups is equivalent to them being complements of each other within the group.*)\nLemma sdprod_normal_complP G K H :\n K <| G -> reflect (K ><| H = G) (K \\in [complements to H in G]).\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then the cardinality of the group is equal to the product of the cardinalities of the two subgroups.*)\nLemma sdprod_card G A B : A ><| B = G -> (#|A| * #|B|)%N = #|G|.\n\n(*This lemma states that if a group is the internal semidirect product of two subgroups, then the second subgroup is isomorphic to the quotient group of the whole group by the first subgroup. The isomorphism is given by the restriction of the canonical coset projection map to the second subgroup.*)\nLemma sdprod_isom G A B :\n A ><| B = G ->\n {nAB : B \\subset 'N(A) | isom B (G / A) (restrm nAB (coset A))}.\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then the second subgroup is isomorphic to the quotient group formed by the whole group and its first subgroup.*)\nLemma sdprod_isog G A B : A ><| B = G -> B \\isog G / A.\n\n(*This lemma states that if a group is the internal semidirect product of two subgroups, and there is a third subgroup contained in the second, then the internal semidirect product of the first and third subgroups is equal to the subgroup generated by the first and third subgroups.*)\nLemma sdprod_subr G A B M : A ><| B = G -> M \\subset B -> A ><| M = A <*> M.\n\n(*This lemma states that if a group is the internal semidirect product of two of its subgroups, then the cardinality of the second subgroup is equal to the index of the first subgroup in the larger group.*)\nLemma index_sdprod G A B : A ><| B = G -> #|B| = #|G : A|.\n\n(*This lemma states that if a group is the internal semidirect product of a first and second subgroup, and a third subgroup is contained within the second, then the index of the third subgroup in the second is equal to the index of the subgroup generated by the first and third subgroups within the larger group.*)\nLemma index_sdprodr G A B M :\n A ><| B = G -> M \\subset B -> #|B : M| = #|G : A <*> M|.\n\n(*This lemma establishes an isomorphism, stating that if a group is the internal semidirect product of a first and second subgroup, and a third subgroup is normal in the second, then the quotient of the second subgroup by the third is isomorphic to the quotient of the whole group by the subgroup generated by the first and third subgroups. It further specifies that this isomorphism maps the image of any subgroup of the second to the corresponding image of a subgroup in the larger quotient.*)\nLemma quotient_sdprodr_isom G A B M :\n A ><| B = G -> M <| B ->\n {f : {morphism B / M >-> coset_of (A <*> M)} |\n isom (B / M) (G / (A <*> M)) f\n & forall L, L \\subset B -> f @* (L / M) = A <*> L / (A <*> M)}.\n\n(*This lemma states that if a group is the internal semidirect product of a first and second subgroup, and a third subgroup is normal in the second, then the quotient group of the second subgroup by the third is isomorphic to the quotient of the whole group by the subgroup generated by the first and third subgroups.*)\nLemma quotient_sdprodr_isog G A B M :\n A ><| B = G -> M <| B -> B / M \\isog G / (A <*> M).\n\n(*This lemma provides a modular law for internal semidirect products. It states that if a group is the internal semidirect product of a first and second subgroup, and a third subgroup contains the first, then the intersection of the whole group and the third subgroup is equal to the internal semidirect product of the first subgroup and the intersection of the second and third subgroups.*)\nLemma sdprod_modl A B G H :\n A ><| B = G -> A \\subset H -> A ><| (B :&: H) = G :&: H.\n\n(*This lemma provides another modular law for internal semidirect products. It states that if a group is the internal semidirect product of a first and second subgroup, and a third subgroup contains the second, then the intersection of the third subgroup and the whole group is equal to the internal semidirect product of the intersection of the third and first subgroups, and the second subgroup.*)\nLemma sdprod_modr A B G H :\n A ><| B = G -> B \\subset H -> (H :&: A) ><| B = H :&: G.\n\n(*This lemma states how a centralizer interacts with an internal semidirect product. If a group is the internal semidirect product of two subgroups, and there is a third subgroup which normalizes both factors, then the centralizer of this third subgroup in the whole group is itself an internal semidirect product of the centralizers of that third subgroup within each of the two factor subgroups.*)\nLemma subcent_sdprod B C G A :\n B ><| C = G -> A \\subset 'N(B) :&: 'N(C) -> 'C_B(A) ><| 'C_C(A) = 'C_G(A).\n\n(*This lemma establishes a recursive principle for internal semidirect products, indexed by a natural number. It relates a semidirect product decomposition of a group to a similar decomposition involving its subgroups, facilitating proofs by induction.*)\nLemma sdprod_recl n G K H K1 :\n #|G| <= n -> K ><| H = G -> K1 \\proper K -> H \\subset 'N(K1) ->\n exists G1 : {group gT}, [/\\ #|G1| < n, G1 \\subset G & K1 ><| H = G1].\n\n(*This lemma states that if a group, with an order bounded by a natural number, is the semidirect product of two of its subgroups, and a third subgroup is a proper subgroup of the second factor, then the semidirect product of the first factor and the third subgroup forms a new group that is a subgroup of the original group and has a strictly smaller order.*)\nLemma sdprod_recr n G K H H1 :\n #|G| <= n -> K ><| H = G -> H1 \\proper H ->\n exists G1 : {group gT}, [/\\ #|G1| < n, G1 \\subset G & K ><| H1 = G1].\n\n(*This lemma states that if a group is the semidirect product of two subgroups, then any element in the group can be uniquely decomposed as the product of an element from the first subgroup and an element from the second subgroup.*)\nLemma mem_sdprod G A B x : A ><| B = G -> x \\in G ->\n exists y, exists z,\n [/\\ y \\in A, z \\in B, x = y * z &\n {in A & B, forall u t, x = u * t -> u = y /\\ t = z}].\n\n(*This lemma states that the trivial group serves as the left identity for the central product operation on groups.*)\nLemma cprod1g : left_id 1 cprod.\n\n(*This lemma states that the trivial group serves as the right identity for the central product operation on groups.*)\nLemma cprodg1 : right_id 1 cprod.\n\n(*This lemma states that if a group is the central product of two sets, then both sets must be groups, their standard group product equals the original group, and the second group must be a subgroup of the centralizer of the first group.*)\nLemma cprodP A B G :\n A \\* B = G -> [/\\ are_groups A B, A * B = G & B \\subset 'C(A)].\n\n(*This lemma states that if a subgroup is contained within the centralizer of another group, their central product is equal to their standard group product.*)\nLemma cprodE G H : H \\subset 'C(G) -> G \\* H = G * H.\n\n(*This lemma states that if a subgroup is contained within the centralizer of another group, their central product is equal to the group generated by their union, also known as their join.*)\nLemma cprodEY G H : H \\subset 'C(G) -> G \\* H = G <*> H.\n\n(*This lemma states that if a group is formed by the central product of two subgroups, then it is also equal to the set of products of elements from these two subgroups.*)\nLemma cprodWpp A B G : A \\* B = G -> pprod A B = G.\n\n(*This lemma states that if a group is the central product of two subgroups, then it is also their standard group product.*)\nLemma cprodW A B G : A \\* B = G -> A * B = G.\n\n(*This lemma states that if a group is the central product of two subgroups, then it is also equal to their standard group product taken in the reverse order.*)\nLemma cprodWC A B G : A \\* B = G -> B * A = G.\n\n(*This lemma states that if a group is the central product of two subgroups, then it is also equal to the group generated by their union, known as their join.*)\nLemma cprodWY A B G : A \\* B = G -> A <*> B = G.\n\n(*This lemma states that the conjugate of a central product of two groups by an element is equal to the central product of the conjugates of each group by that same element.*)\nLemma cprodJ A B x : (A \\* B) :^ x = A :^ x \\* B :^ x.\n\n(*This lemma states that if a group is the central product of two subgroups, then both of these subgroups are normal subgroups of the resulting group.*)\nLemma cprod_normal2 A B G : A \\* B = G -> A <| G /\\ B <| G.\n\n(*This lemma states that if a group is the iterated central product of a sequence of groups, then it is also their iterated standard group product.*)\nLemma bigcprodW I (r : seq I) P F G :\n \\big[cprod/1]_(i <- r | P i) F i = G -> \\prod_(i <- r | P i) F i = G.\n\n(*This lemma states that if a group is the iterated central product of a sequence of groups, then it is also equal to the group generated by the union of all groups in the sequence.*)\nLemma bigcprodWY I (r : seq I) P F G :\n \\big[cprod/1]_(i <- r | P i) F i = G -> << \\bigcup_(i <- r | P i) F i >> = G.\n\n(*This lemma states that the central product of two groups is the trivial group if and only if both groups are themselves the trivial group.*)\nLemma triv_cprod A B : (A \\* B == 1) = (A == 1) && (B == 1).\n\n(*This lemma provides a case analysis for the central product of two non-trivial sets: it equals their standard group product if both are groups and the second is a subgroup of the centralizer of the first; otherwise, it is the empty set.*)\nLemma cprod_ntriv A B : A != 1 -> B != 1 ->\n A \\* B =\n if [&& group_set A, group_set B & B \\subset 'C(A)] then A * B else set0.\n\n(*This lemma states that the empty set of group elements is not equal to the trivial group.*)\nLemma trivg0 : (@set0 gT == 1) = false.\n\n(*This lemma states that the empty set of group elements does not form a group.*)\nLemma group0 : group_set (@set0 gT) = false.\n\n(*This lemma states that the central product of the empty set with any other set results in the empty set.*)\nLemma cprod0g A : set0 \\* A = set0.\n\n(*This lemma states that the central product operation for groups is commutative.*)\nLemma cprodC : commutative cprod.\n\n(*This lemma states that the central product operation for groups is associative.*)\nLemma cprodA : associative cprod.\n\nHB.instance Definition _ := Monoid.isComLaw.Build {set gT} 1 cprod\n cprodA cprodC cprod1g.\n\n(*This lemma provides a left modular law for central products. It states that if a group is the central product of two subgroups, and the first subgroup is contained in another group, then the intersection of the original group with this other group is equal to the central product of the first subgroup and the intersection of the second subgroup with this other group.*)\nLemma cprod_modl A B G H :\n A \\* B = G -> A \\subset H -> A \\* (B :&: H) = G :&: H.\n\n(*This lemma provides a right modular law for central products. It states that if a group is the central product of two subgroups, and the second subgroup is contained in another group, then the intersection of this other group with the original group is equal to the central product of the intersection of this other group with the first subgroup and the second subgroup.*)\nLemma cprod_modr A B G H :\n A \\* B = G -> B \\subset H -> (H :&: A) \\* B = H :&: G.\n\n(*This lemma states that for a family of groups indexed over a finite type, their iterated central product is equal to their iterated standard group product if and only if any two distinct groups in the family mutually centralize each other.*)\nLemma bigcprodYP (I : finType) (P : pred I) (H : I -> {group gT}) :\n reflect (forall i j, P i -> P j -> i != j -> H i \\subset 'C(H j))\n (\\big[cprod/1]_(i | P i) H i == (\\prod_(i | P i) H i)%G).\n\n(*This lemma states that for a family of groups that are all subgroups of a given abelian group, their iterated central product is equal to their iterated standard group product.*)\nLemma bigcprodEY I r (P : pred I) (H : I -> {group gT}) G :\n abelian G -> (forall i, P i -> H i \\subset G) ->\n \\big[cprod/1]_(i <- r | P i) H i = (\\prod_(i <- r | P i) H i)%G.\n\n(*This lemma states that if a group is formed by the iterated central product of a sequence of subgroups, and another sequence is a permutation of the first, then the product of elements chosen from each corresponding subgroup is invariant under this permutation of the order of multiplication.*)\nLemma perm_bigcprod (I : eqType) r1 r2 (A : I -> {set gT}) G x :\n \\big[cprod/1]_(i <- r1) A i = G -> {in r1, forall i, x i \\in A i} ->\n perm_eq r1 r2 ->\n \\prod_(i <- r1) x i = \\prod_(i <- r2) x i.\n\n(*This lemma states that if a group is an iterated central product over a given family of subgroups, the product of elements taken from each subgroup is invariant under a bijective re-indexing of the family.*)\nLemma reindex_bigcprod (I J : finType) (h : J -> I) P (A : I -> {set gT}) G x :\n {on SimplPred P, bijective h} -> \\big[cprod/1]_(i | P i) A i = G ->\n {in SimplPred P, forall i, x i \\in A i} ->\n \\prod_(i | P i) x i = \\prod_(j | P (h j)) x (h j).\n\n(*This lemma states that the trivial group serves as the left identity for the direct product operation on groups.*)\nLemma dprod1g : left_id 1 dprod.\n\n(*This lemma states that the trivial group serves as the right identity for the direct product operation on groups.*)\nLemma dprodg1 : right_id 1 dprod.\n\n(*This lemma states that if a group is the internal direct product of two of its subgroups, then both subgroups are indeed groups, their group product equals the larger group, every element of the second subgroup commutes with every element of the first subgroup, and their intersection is the trivial subgroup.*)\nLemma dprodP A B G :\n A \\x B = G -> [/\\ are_groups A B, A * B = G, B \\subset 'C(A) & A :&: B = 1].\n\n(*This lemma states that for two subgroups, if every element of the second subgroup commutes with every element of the first, and their intersection is the trivial subgroup, then their internal direct product is equal to their group product.*)\nLemma dprodE G H : H \\subset 'C(G) -> G :&: H = 1 -> G \\x H = G * H.\n\n(*This lemma states that for two subgroups, if every element of the second subgroup commutes with every element of the first, and their intersection is the trivial subgroup, then their internal direct product is equal to the subgroup generated by their union.*)\nLemma dprodEY G H : H \\subset 'C(G) -> G :&: H = 1 -> G \\x H = G <*> H.\n\n(*This lemma states that for two subgroups with a trivial intersection, their internal direct product is equal to their central product.*)\nLemma dprodEcp A B : A :&: B = 1 -> A \\x B = A \\* B.\n\n(*This lemma states that if every element of a subgroup commutes with every element of another subgroup, their internal direct product is equal to their semidirect product.*)\nLemma dprodEsd A B : B \\subset 'C(A) -> A \\x B = A ><| B.\n\n(*This lemma states that if a group is the internal direct product of two of its subgroups, then it is also their central product.*)\nLemma dprodWcp A B G : A \\x B = G -> A \\* B = G.\n\n(*This lemma states that if a group is the internal direct product of two of its subgroups, then it is also their semidirect product.*)\nLemma dprodWsd A B G : A \\x B = G -> A ><| B = G.\n\n(*This lemma states that if a group is the internal direct product of two of its subgroups, then it is also their group product.*)\nLemma dprodW A B G : A \\x B = G -> A * B = G.\n\n(*This lemma states that if a group is the internal direct product of two subgroups, one named A and the other B, then the group product of B and A is also equal to the group.*)\nLemma dprodWC A B G : A \\x B = G -> B * A = G.\n\n(*This lemma states that if a group is the internal direct product of two of its subgroups, then it is also the subgroup generated by their union.*)\nLemma dprodWY A B G : A \\x B = G -> A <*> B = G.\n\n(*This lemma states that if a group is the central product of two of its finite subgroups, and the product of the cardinalities of the subgroups is less than or equal to the cardinality of the group, then the group is the internal direct product of these subgroups.*)\nLemma cprod_card_dprod G A B :\n A \\* B = G -> #|A| * #|B| <= #|G| -> A \\x B = G.\n\n(*This lemma states that the conjugate of an internal direct product of two subgroups by an element is the internal direct product of the conjugates of each subgroup by that same element.*)\nLemma dprodJ A B x : (A \\x B) :^ x = A :^ x \\x B :^ x.\n\n(*This lemma states that if a group is the internal direct product of two of its subgroups, then both of these subgroups are normal in the group.*)\nLemma dprod_normal2 A B G : A \\x B = G -> A <| G /\\ B <| G.\n\n(*This lemma provides a boolean reflection, stating that the internal direct product of two subgroups is equal to the subgroup generated by their union if and only if one subgroup commutes with the other and their intersection is trivial.*)\nLemma dprodYP K H : reflect (K \\x H = K <*> H) (H \\subset 'C(K) :\\: K^#).\n\n(*This lemma states that the internal direct product operation on subgroups is commutative.*)\nLemma dprodC : commutative dprod.\n\n(*This lemma states that if a group is the internal direct product of a subgroup A and a subgroup B, then it is also equal to the semidirect product of B and A.*)\nLemma dprodWsdC A B G : A \\x B = G -> B ><| A = G.\n\n(*This lemma states that the internal direct product operation on subgroups is associative.*)\nLemma dprodA : associative dprod.\n\n(*This lemma states that if a group is the iterated internal direct product of a family of subgroups over a sequence, then it is also their iterated central product.*)\nLemma bigdprodWcp I (r : seq I) P F G :\n \\big[dprod/1]_(i <- r | P i) F i = G -> \\big[cprod/1]_(i <- r | P i) F i = G.\n\n(*This lemma states that if a group is the iterated internal direct product of a family of subgroups over a sequence, then it is also their iterated group product.*)\nLemma bigdprodW I (r : seq I) P F G :\n \\big[dprod/1]_(i <- r | P i) F i = G -> \\prod_(i <- r | P i) F i = G.\n\n(*This lemma states that if a group is the iterated internal direct product of a family of subgroups over a sequence, then it is also the subgroup generated by their union.*)\nLemma bigdprodWY I (r : seq I) P F G :\n \\big[dprod/1]_(i <- r | P i) F i = G -> << \\bigcup_(i <- r | P i) F i >> = G.\n\n(*This lemma provides a boolean reflection, stating that the iterated internal direct product of a family of subgroups over a finite type is equal to their iterated group product if and only if for each subgroup in the family, it commutes with the product of all other subgroups and its intersection with that product is trivial.*)\nLemma bigdprodYP (I : finType) (P : pred I) (F : I -> {group gT}) :\n reflect (forall i, P i ->\n (\\prod_(j | P j && (j != i)) F j)%G \\subset 'C(F i) :\\: (F i)^#)\n (\\big[dprod/1]_(i | P i) F i == (\\prod_(i | P i) F i)%G).\n\n(*This lemma states a modular property for internal direct products: if a group is the direct product of subgroups A and B, and A is a subgroup of another group H, then the intersection of the whole group with H is the internal direct product of A and the intersection of B with H.*)\nLemma dprod_modl A B G H :\n A \\x B = G -> A \\subset H -> A \\x (B :&: H) = G :&: H.\n\n(*This lemma states a modular property for internal direct products: if a group is the direct product of subgroups A and B, and B is a subgroup of another group H, then the intersection of H with the whole group is the internal direct product of the intersection of H with A and the subgroup B.*)\nLemma dprod_modr A B G H :\n A \\x B = G -> B \\subset H -> (H :&: A) \\x B = H :&: G.\n\n(*This lemma states that if a group is the internal direct product of two subgroups B and C, and another subgroup A normalizes both B and C, then the centralizer of A in the whole group is the internal direct product of the centralizer of A in B and the centralizer of A in C.*)\nLemma subcent_dprod B C G A :\n B \\x C = G -> A \\subset 'N(B) :&: 'N(C) -> 'C_B(A) \\x 'C_C(A) = 'C_G(A).\n\n(*This lemma states that if a group is the internal direct product of two of its finite subgroups, then the cardinality of the group is equal to the product of the cardinalities of the two subgroups.*)\nLemma dprod_card A B G : A \\x B = G -> (#|A| * #|B|)%N = #|G|.\n\n(*This lemma states that if a group is the iterated internal direct product of a family of finite subgroups, the cardinality of the group is the product of the cardinalities of the subgroups in the family.*)\nLemma bigdprod_card I r (P : pred I) E G :\n \\big[dprod/1]_(i <- r | P i) E i = G ->\n (\\prod_(i <- r | P i) #|E i|)%N = #|G|.\n\n(*This lemma states that if a group is the iterated central product of a family of finite subgroups, and the product of the cardinalities of these subgroups is less than or equal to the cardinality of the group, then the group is the iterated internal direct product of this family.*)\nLemma bigcprod_card_dprod I r (P : pred I) (A : I -> {set gT}) G :\n \\big[cprod/1]_(i <- r | P i) A i = G ->\n \\prod_(i <- r | P i) #|A i| <= #|G| ->\n \\big[dprod/1]_(i <- r | P i) A i = G.\n\n(*This lemma states that if a group is the iterated central product of a family of finite subgroups with pairwise coprime cardinalities, then the group is also the iterated internal direct product of that family.*)\nLemma bigcprod_coprime_dprod (I : finType) (P : pred I) (A : I -> {set gT}) G :\n \\big[cprod/1]_(i | P i) A i = G ->\n (forall i j, P i -> P j -> i != j -> coprime #|A i| #|A j|) ->\n \\big[dprod/1]_(i | P i) A i = G.\n\n(*This lemma states that if a group is the internal direct product of two subgroups, then any element of the group can be uniquely decomposed as a product of an element from the first subgroup and an element from the second subgroup.*)\nLemma mem_dprod G A B x : A \\x B = G -> x \\in G ->\n exists y, exists z,\n [/\\ y \\in A, z \\in B, x = y * z &\n {in A & B, forall u t, x = u * t -> u = y /\\ t = z}].\n\n(*This lemma states that if a group is the iterated internal direct product of a family of subgroups, then any element of the group can be uniquely decomposed as a product of elements, with one element drawn from each subgroup in the family.*)\nLemma mem_bigdprod (I : finType) (P : pred I) F G x :\n \\big[dprod/1]_(i | P i) F i = G -> x \\in G ->\n exists c, [/\\ forall i, P i -> c i \\in F i, x = \\prod_(i | P i) c i\n & forall e, (forall i, P i -> e i \\in F i) ->\n x = \\prod_(i | P i) e i ->\n forall i, P i -> e i = c i].\n\n(*This lemma states that for a collection of pairwise commuting subgroups indexed over a finite type, their iterated group product as a group is equal to their iterated product as a set of elements.*)\nLemma comm_prodG I r (G : I -> {group gT}) (P : {pred I}) :\n {in P &, forall i j, commute (G i) (G j)} ->\n (\\prod_(i <- r | P i) G i)%G = \\prod_(i <- r | P i) G i :> {set gT}.\n\nEnd InternalProd.\n\nArguments complP {gT H A B}.\nArguments splitsP {gT B A}.\nArguments sdprod_normal_complP {gT G K H}.\nArguments dprodYP {gT K H}.\nArguments bigdprodYP {gT I P F}.\n\nSection MorphimInternalProd.\n\nVariables (gT rT : finGroupType) (D : {group gT}) (f : {morphism D >-> rT}).\n\nSection OneProd.\n\nVariables G H K : {group gT}.\nHypothesis sGD : G \\subset D.\n\n(*This lemma states that the image of the product set of two subgroups under a group morphism is equal to the product set of the images of those subgroups.*)\nLemma morphim_pprod : pprod K H = G -> pprod (f @* K) (f @* H) = f @* G.\n\n(*This lemma states that if two subgroups form an internal semidirect product and their orders are coprime, then their images under a group morphism also form an internal semidirect product, which is the image of the original product.*)\nLemma morphim_coprime_sdprod :\n K ><| H = G -> coprime #|K| #|H| -> f @* K ><| f @* H = f @* G.\n\n(*This lemma states that the image of an internal semidirect product of two subgroups under an injective group morphism is the internal semidirect product of their images.*)\nLemma injm_sdprod : 'injm f -> K ><| H = G -> f @* K ><| f @* H = f @* G.\n\n(*This lemma states that the image of the internal central product of two subgroups under a group morphism is the internal central product of their images.*)\nLemma morphim_cprod : K \\* H = G -> f @* K \\* f @* H = f @* G.\n\n(*This lemma states that the image of an internal direct product of two subgroups under an injective group morphism is the internal direct product of their images.*)\nLemma injm_dprod : 'injm f -> K \\x H = G -> f @* K \\x f @* H = f @* G.\n\n(*This lemma states that if two subgroups form an internal direct product and their orders are coprime, then their images under a group morphism also form an internal direct product, which is the image of the original product.*)\nLemma morphim_coprime_dprod :\n K \\x H = G -> coprime #|K| #|H| -> f @* K \\x f @* H = f @* G.\n\nEnd OneProd.\n\nImplicit Type G : {group gT}.\n\n(*This lemma states that the image of a large internal central product of a family of subgroups under a group morphism is the large internal central product of their images.*)\nLemma morphim_bigcprod I r (P : pred I) (H : I -> {group gT}) G :\n G \\subset D -> \\big[cprod/1]_(i <- r | P i) H i = G ->\n \\big[cprod/1]_(i <- r | P i) f @* H i = f @* G.\n\n(*This lemma states that the image of a large internal direct product of a family of subgroups under an injective group morphism is the large internal direct product of their images.*)\nLemma injm_bigdprod I r (P : pred I) (H : I -> {group gT}) G :\n G \\subset D -> 'injm f -> \\big[dprod/1]_(i <- r | P i) H i = G ->\n \\big[dprod/1]_(i <- r | P i) f @* H i = f @* G.\n\n(*This lemma states that if a family of subgroups forms a large internal direct product and their orders are pairwise coprime, then their images under a group morphism also form a large internal direct product, which is the image of the original product.*)\nLemma morphim_coprime_bigdprod (I : finType) P (H : I -> {group gT}) G :\n G \\subset D -> \\big[dprod/1]_(i | P i) H i = G ->\n (forall i j, P i -> P j -> i != j -> coprime #|H i| #|H j|) ->\n \\big[dprod/1]_(i | P i) f @* H i = f @* G.\n\nEnd MorphimInternalProd.\n\nSection QuotientInternalProd.\n\nVariables (gT : finGroupType) (G K H M : {group gT}).\n\nHypothesis nMG: G \\subset 'N(M).\n\n(*This lemma states that the product set of the quotient groups of two subgroups by a normal subgroup is equal to the quotient of their original product set by that same normal subgroup.*)\nLemma quotient_pprod : pprod K H = G -> pprod (K / M) (H / M) = G / M.\n\n(*This lemma states that if two subgroups form an internal semidirect product and their orders are coprime, then their quotient groups by a common normal subgroup also form an internal semidirect product, which is the quotient of the original product group.*)\nLemma quotient_coprime_sdprod :\n K ><| H = G -> coprime #|K| #|H| -> (K / M) ><| (H / M) = G / M.\n\n(*This lemma states that the internal central product of the quotient groups of two subgroups by a normal subgroup is equal to the quotient of their original internal central product by that same normal subgroup.*)\nLemma quotient_cprod : K \\* H = G -> (K / M) \\* (H / M) = G / M.\n\n(*This lemma states that if two subgroups form an internal direct product and their orders are coprime, then their quotient groups by a common normal subgroup also form an internal direct product, which is the quotient of the original product group.*)\nLemma quotient_coprime_dprod :\n K \\x H = G -> coprime #|K| #|H| -> (K / M) \\x (H / M) = G / M.\n\nEnd QuotientInternalProd.\n\nSection ExternalDirProd.\n\nVariables gT1 gT2 : finGroupType.\n\n(*This definition specifies the multiplication operation for the external direct product of two groups as the component-wise multiplication of pairs of elements.*)\nDefinition extprod_mulg (x y : gT1 * gT2) := (x.1 * y.1, x.2 * y.2).\n(*This definition specifies the inverse operation for the external direct product of two groups as the component-wise inversion of a pair of elements.*)\nDefinition extprod_invg (x : gT1 * gT2) := (x.1^-1, x.2^-1).\n\n(*This lemma states that the pair of identity elements from two groups acts as the left identity for the external direct product multiplication.*)\nLemma extprod_mul1g : left_id (1, 1) extprod_mulg.\n\n(*This lemma states that the component-wise inverse operation provides a left inverse for any element in the external direct product group.*)\nLemma extprod_mulVg : left_inverse (1, 1) extprod_invg extprod_mulg.\n\n(*This lemma states that the multiplication operation for the external direct product of two groups is associative.*)\nLemma extprod_mulgA : associative extprod_mulg.\n\n(*This lemma asserts that the Cartesian product of the carrier sets of two groups forms a valid group carrier itself.*)\nLemma group_setX (H1 : {group gT1}) (H2 : {group gT2}) : group_set (setX H1 H2).\n\nCanonical setX_group H1 H2 := Group (group_setX H1 H2).\n\n(*This definition describes a function that embeds an element from a first group into a product group by pairing it with the identity element of a second group.*)\nDefinition pairg1 x : gT1 * gT2 := (x, 1).\n(*This definition describes a function that embeds an element from a second group into a product group by pairing it with the identity element of a first group.*)\nDefinition pair1g x : gT1 * gT2 := (1, x).\n\n(*This lemma asserts that the function embedding an element from a first group into a product group by pairing it with the identity of a second group is a group morphism.*)\nLemma pairg1_morphM : {morph pairg1 : x y / x * y}.\n\nCanonical pairg1_morphism := @Morphism _ _ setT _ (in2W pairg1_morphM).\n\n(*This lemma asserts that the function embedding an element from a second group into a product group by pairing it with the identity of a first group is a group morphism.*)\nLemma pair1g_morphM : {morph pair1g : x y / x * y}.\n\nCanonical pair1g_morphism := @Morphism _ _ setT _ (in2W pair1g_morphM).\n\n(*This lemma asserts that the projection function returning the first component of an element from a product group is a group morphism.*)\nLemma fst_morphM : {morph (@fst gT1 gT2) : x y / x * y}.\n\n(*This lemma asserts that the projection function returning the second component of an element from a product group is a group morphism.*)\nLemma snd_morphM : {morph (@snd gT1 gT2) : x y / x * y}.\n\nCanonical fst_morphism := @Morphism _ _ setT _ (in2W fst_morphM).\n\nCanonical snd_morphism := @Morphism _ _ setT _ (in2W snd_morphM).\n\n(*This lemma states that the function embedding an element from a second group into a product group by pairing it with the identity of a first group is injective.*)\nLemma injm_pair1g : 'injm pair1g.\n\n(*This lemma states that the function embedding an element from a first group into a product group by pairing it with the identity of a second group is injective.*)\nLemma injm_pairg1 : 'injm pairg1.\n\n(*This lemma states that the image of a subgroup from a first group under the canonical embedding into a product group is the Cartesian product of that subgroup with the trivial subgroup of the second group.*)\nLemma morphim_pairg1 (H1 : {set gT1}) : pairg1 @* H1 = setX H1 1.\n\n(*This lemma states that the image of a subgroup from a second group under the canonical embedding into a product group is the Cartesian product of the trivial subgroup of the first group with that subgroup.*)\nLemma morphim_pair1g (H2 : {set gT2}) : pair1g @* H2 = setX 1 H2.\n\n(*This lemma states that the image of the external direct product of a set and a group under the first projection morphism is equal to the original set.*)\nLemma morphim_fstX (H1: {set gT1}) (H2 : {group gT2}) :\n [morphism of fun x => x.1] @* setX H1 H2 = H1.\n\n(*This lemma states that the image of the external direct product of a group and a set under the second projection morphism is equal to the original set.*)\nLemma morphim_sndX (H1: {group gT1}) (H2 : {set gT2}) :\n [morphism of fun x => x.2] @* setX H1 H2 = H2.\n\n(*This lemma states that the product of two sets, where the first is the direct product of a given set with a trivial group and the second is the direct product of a trivial group with another given set, is equal to the direct product of the two given sets.*)\nLemma setX_prod (H1 : {set gT1}) (H2 : {set gT2}) :\n setX H1 1 * setX 1 H2 = setX H1 H2.\n\n(*This lemma states that the external direct product of two groups is the internal direct product of two subgroups, where the first subgroup is formed by combining the first group with the identity of the second, and the second subgroup is formed by combining the identity of the first group with the second group.*)\nLemma setX_dprod (H1 : {group gT1}) (H2 : {group gT2}) :\n setX H1 1 \\x setX 1 H2 = setX H1 H2.\n\n(*This lemma states that a group is isomorphic to the external direct product of itself with a trivial group.*)\nLemma isog_setX1 (H1 : {group gT1}) : isog H1 (setX H1 1).\n\n(*This lemma states that a group is isomorphic to the external direct product of a trivial group with the group itself.*)\nLemma isog_set1X (H2 : {group gT2}) : isog H2 (setX 1 H2).\n\n(*This lemma states that if two sets of group elements each contain the identity element, then the subgroup generated by the external direct product of these sets is equal to the external direct product of the subgroups generated by each set.*)\nLemma setX_gen (H1 : {set gT1}) (H2 : {set gT2}) :\n 1 \\in H1 -> 1 \\in H2 -> <> = setX <

> <

>.\n\nEnd ExternalDirProd.\n\nSection ExternalDirDepProd.\n\nVariables (I : finType) (gT : I -> finGroupType).\n(*A notation for the type of dependent functions over a finite index type, where each function maps an index to an element of the corresponding group in a given family of finite groups.*)\nNotation gTn := {dffun forall i, gT i}.\nImplicit Types (H : forall i, {group gT i}) (x y : {dffun forall i, gT i}).\n\n(*This definition specifies the pointwise multiplication operation for elements of a dependent product of groups, where the result at each index is the product of the corresponding elements from the input functions.*)\nDefinition extnprod_mulg (x y : gTn) : gTn := [ffun i => (x i * y i)%g].\n(*This definition specifies the pointwise inversion operation for elements of a dependent product of groups, where the result at each index is the inverse of the corresponding element from the input function.*)\nDefinition extnprod_invg (x : gTn) : gTn := [ffun i => (x i)^-1%g].\n\n(*This lemma states that the function constantly mapping to the identity element acts as a left identity for the pointwise multiplication on a dependent product of groups.*)\nLemma extnprod_mul1g : left_id [ffun=> 1%g] extnprod_mulg.\n\n(*This lemma states that the pointwise inversion operation provides a left inverse for the pointwise multiplication on a dependent product of groups, with the constant identity function serving as the identity element.*)\nLemma extnprod_mulVg : left_inverse [ffun=> 1%g] extnprod_invg extnprod_mulg.\n\n(*This lemma states that the pointwise multiplication operation on a dependent product of groups is associative.*)\nLemma extnprod_mulgA : associative extnprod_mulg.\n\n(*This lemma states that for any given index, the component of the identity element of a dependent product group is the identity element of the corresponding component group.*)\nLemma oneg_ffun i : (1 : gTn) i = 1. \n\n(*This lemma states that the component of a product of two elements in a dependent product group, at any given index, is equal to the product of the components of those two elements at that same index.*)\nLemma mulg_ffun i (x y : gTn) : (x * y) i = x i * y i.\n\n(*This lemma states that the component of the inverse of an element in a dependent product group, at any given index, is equal to the inverse of the component of that element at the same index.*)\nLemma invg_ffun i (x : gTn) : x^-1 i = (x i)^-1.\n\n(*This lemma states that evaluating a finite product of dependent functions at a specific index is equivalent to taking the finite product of the values of each function at that same index.*)\nLemma prodg_ffun T (r : seq T) (F : T -> gTn) (P : {pred T}) i :\n (\\prod_(t <- r | P t) F t) i = \\prod_(t <- r | P t) F t i.\n\n(*This lemma states that the dependent external product of a family of sets forms a group, provided that each set in the family is itself a group.*)\nLemma group_setXn H : group_set (setXn H).\n\nCanonical setXn_group H := Group (group_setXn H).\n\n(*This definition describes a function that embeds an element from a specific component group into the larger dependent product group by creating a function that is the given element at the specified index and the identity element everywhere else.*)\nDefinition dfung1 i (g : gT i) : gTn := finfun (dfwith (fun=> 1 : gT _) g).\n\n(*This lemma states that applying the embedding function to an element from a component group and then projecting back to the original index yields the original element.*)\nLemma dfung1_id i (g : gT i) : dfung1 g i = g.\n\n(*This lemma states that the embedding function, which places a given group element at a specific index, yields the identity element at all other indices.*)\nLemma dfung1_dflt i (g : gT i) j : i != j -> dfung1 g j = 1.\n\n(*This lemma states that for any given index, the function embedding a component group into the dependent product group is a group morphism, meaning it preserves the group multiplication.*)\nLemma dfung1_morphM i : {morph @dfung1 i : g h / g * h}.\n\nCanonical dfung1_morphism i := @Morphism _ _ setT _ (in2W (@dfung1_morphM i)).\n\n(*This lemma states that for any given index, the projection function from a dependent product group to one of its component groups is a group morphism, preserving the group multiplication.*)\nLemma dffunM i : {morph (fun x => x i) : x y / x * y}.\n\nCanonical dffun_morphism i := @Morphism _ _ setT _ (in2W (@dffunM i)).\n\n(*This lemma states that for any given index, the embedding of a component group into the dependent product group is an injective morphism.*)\nLemma injm_dfung1 i : 'injm (@dfung1 i).\n\n(*This lemma states that the dependent external product of a family of sets forms a group, where this family is constructed by taking an existing family of groups and replacing the set at a specific index with a given group.*)\nLemma group_set_dfwith H i (G : {group gT i}) j :\n group_set (dfwith (H : forall k, {set gT k}) (G : {set _}) j).\n\nCanonical group_dfwith H i G j := Group (@group_set_dfwith H i G j).\n\n(*This lemma states that the underlying family of sets of the group structure defined by updating a family of groups at a specific index is identical to the family of sets obtained by that update operation.*)\nLemma group_dfwithE H i G j : @group_dfwith H i G j = dfwith H G j.\n\n(*This fact provides an opaque key used to lock a definition, ensuring that it can only be unfolded by a designated lemma.*)\nFact set1gXn_key : unit. \n(*This definition creates a specific subset of a dependent product group, corresponding to a given subset of a single component group, where all other components are restricted to their respective identity elements. The definition is locked to control its unfolding in proofs.*)\nDefinition set1gXn {i} (H : {set gT i}) : {set {dffun forall i : I, gT i}} :=\n locked_with set1gXn_key (setXn (dfwith (fun i0 : I => [1 gT _]%g) H)).\n\n(*This lemma provides the unfolding rule for the locked definition of an embedded subset, showing that it is equal to the external product built from a family of sets containing mostly trivial groups and the given subset at a specific index.*)\nLemma set1gXnE {i} (H : {set gT i}) :\n set1gXn H = setXn (dfwith (fun i0 : I => [1 gT _]%g) H).\n\n(*This lemma provides the membership criterion for an element to belong to the subset formed by embedding a component set into a dependent product group. An element is a member if and only if its component at the specified index is in the original set and all its other components are identity elements.*)\nLemma set1gXnP {i} (H : {set gT i}) x :\n reflect (exists2 h, h \\in H & x = dfung1 h) (x \\in set1gXn H).\n\n(*This lemma states that the image of a set under the indexed injection function into a direct product group is equal to the corresponding embedded factor set.*)\nLemma morphim_dfung1 i (G : {set gT i}) : @dfung1 i @* G = set1gXn G.\n\n(*This lemma states that the image of a direct product set under an indexed projection morphism is equal to the component set at that same index.*)\nLemma morphim_dffunXn i H : dffun_morphism i @* setXn H = H i.\n\n(*This lemma states that the set representing a factor group embedded within a direct product itself forms a group.*)\nLemma set1gXn_group_set {i} (H : {group gT i}) : group_set (set1gXn H).\n\nCanonical groupXn1 {i} (H : {group gT i}) := Group (set1gXn_group_set H).\n\n(*This lemma states that the internal product, or join, of all the embedded factor subgroups of a direct product is equal to the entire direct product group.*)\nLemma setXn_prod H : \\prod_i set1gXn (H i) = setXn H.\n\n(*This lemma states that any two embedded factor subgroups corresponding to distinct indices in a direct product commute with each other.*)\nLemma set1gXn_commute (H : forall i, {group gT i}) i j :\n commute (set1gXn (H i)) (set1gXn (H j)).\n\n(*This lemma states that the internal direct product of the family of embedded factor subgroups is equal to the full direct product group.*)\nLemma setXn_dprod H : \\big[dprod/1]_i set1gXn (H i) = setXn H.\n\n(*This lemma states that any component group is isomorphic to its canonical embedding within the larger direct product group.*)\nLemma isog_setXn i (G : {group gT i}) : G \\isog set1gXn G.\n\n(*This lemma states that if each component set contains an identity element, then the subgroup generated by the direct product of these sets is equal to the direct product of the subgroups generated by each individual set.*)\nLemma setXn_gen H : (forall i, 1 \\in H i) -> \n <> = setXn (fun i => <>).\n\nEnd ExternalDirDepProd.\n\n(*This lemma states that the direct product of a family of groups over an empty index set results in the trivial group.*)\nLemma groupX0 (gT : 'I_0 -> finGroupType) (G : forall i, {group gT i}) :\n setXn G = 1%g.\n\nSection ExternalSDirProd.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (R : {group rT}).\n\n(*An inductive type that represents the elements of an external semidirect product of two groups. Each element is constructed from a pair of elements, one from each constituent group, and is parameterized by the group action defining the product.*)\nInductive sdprod_by (to : groupAction D R) : predArgType :=\n SdPair (ax : aT * rT) of ax \\in setX D R.\n\nCoercion pair_of_sd to (u : sdprod_by to) := let: SdPair ax _ := u in ax.\n\nVariable to : groupAction D R.\n\n(*A notation that provides a shorthand for the type of elements in a semidirect product, which is parameterized by a defining group action.*)\nNotation sdT := (sdprod_by to).\n(*A coercion that extracts the underlying pair of group elements from an element of the semidirect product type.*)\nNotation sdval := (@pair_of_sd to).\n\nHB.instance Definition _ := [isSub for sdval].\n#[hnf] HB.instance Definition _ := [Finite of sdT by <:].\n\n(*This definition establishes the identity element of the semidirect product group as the pair composed of the identity elements from each of the two constituent groups.*)\nDefinition sdprod_one := SdPair to (group1 _).\n\n(*This lemma proves that the element constructed according to the formula for an inverse in a semidirect product is a valid member of the group's underlying Cartesian product set.*)\nLemma sdprod_inv_proof (u : sdT) : (u.1^-1, to u.2^-1 u.1^-1) \\in setX D R.\n\n(*This definition specifies the inversion operation for the semidirect product group, which computes the inverse of an element using the standard formula involving the group action.*)\nDefinition sdprod_inv u := SdPair to (sdprod_inv_proof u).\n\n(*This lemma proves that the pair resulting from applying the semidirect product multiplication rule to two valid elements is itself a valid element of the group's underlying Cartesian product set.*)\nLemma sdprod_mul_proof (u v : sdT) :\n (u.1 * v.1, to u.2 v.1 * v.2) \\in setX D R.\n\n(*This definition specifies the binary multiplication operation for the semidirect product group, which combines two elements according to the standard formula involving the group laws and the specified group action.*)\nDefinition sdprod_mul u v := SdPair to (sdprod_mul_proof u v).\n\n(*This lemma states that the designated identity element for the semidirect product acts as a left identity with respect to the defined multiplication operation.*)\nLemma sdprod_mul1g : left_id sdprod_one sdprod_mul.\n\n(*This lemma states that for any element in the semidirect product group, its defined inverse acts as a left inverse with respect to the group's multiplication and identity element.*)\nLemma sdprod_mulVg : left_inverse sdprod_one sdprod_inv sdprod_mul.\n\n(*This lemma states that the multiplication operation defined for the semidirect product group is associative.*)\nLemma sdprod_mulgA : associative sdprod_mul.\n\n(*This definition establishes an alias that equips the type of semidirect product elements with the structure of a finite group type.*)\nDefinition sdprod_groupType : finGroupType := sdT.\n\n(*This definition provides a function to embed an element from the second group of a semidirect product construction into the product group by pairing it with the identity of the first group.*)\nDefinition sdpair1 x := insubd sdprod_one (1, x) : sdT.\n(*This definition provides a function to embed an element from the first group of a semidirect product construction into the product group by pairing it with the identity of the second group.*)\nDefinition sdpair2 a := insubd sdprod_one (a, 1) : sdT.\n\n(*This lemma states that the function embedding elements from the second group into the semidirect product group is a group homomorphism.*)\nLemma sdpair1_morphM : {in R &, {morph sdpair1 : x y / x * y}}.\n\n(*This lemma states that the function embedding elements from the first group into the semidirect product group is a group homomorphism.*)\nLemma sdpair2_morphM : {in D &, {morph sdpair2 : a b / a * b}}.\n\nCanonical sdpair1_morphism := Morphism sdpair1_morphM.\n\nCanonical sdpair2_morphism := Morphism sdpair2_morphM.\n\n(*This lemma states that the homomorphism embedding the second group into the semidirect product group is injective.*)\nLemma injm_sdpair1 : 'injm sdpair1.\n\n(*This lemma states that the homomorphism embedding the first group into the semidirect product group is injective.*)\nLemma injm_sdpair2 : 'injm sdpair2.\n\n(*This lemma states that any element of the semidirect product can be expressed as the product of the embedded image of its first component and the embedded image of its second component.*)\nLemma sdpairE (u : sdT) : u = sdpair2 u.1 * sdpair1 u.2.\n\n(*This lemma states that the group action corresponds to conjugation within the semidirect product group. Specifically, embedding the result of the action of an element from the first group on an element from the second group is equivalent to conjugating the embedded second element by the embedded first element.*)\nLemma sdpair_act : {in R & D,\n forall x a, sdpair1 (to x a) = sdpair1 x ^ sdpair2 a}.\n\n(*This lemma relates the action of an element from the first group on a subset of the second group to the conjugation action on the corresponding embedded subset within the semidirect product group.*)\nLemma sdpair_setact (G : {set rT}) a : G \\subset R -> a \\in D ->\n sdpair1 @* (to^~ a @: G) = (sdpair1 @* G) :^ sdpair2 a.\n\n(*This lemma states that the image of the second component group under the second projection of an external semidirect product is a subgroup of the normalizer of the image of the first component group under the first projection.*)\nLemma im_sdpair_norm : sdpair2 @* D \\subset 'N(sdpair1 @* R).\n\n(*This lemma states that the intersection of the image of the first component group and the image of the second component group, under their respective projections from an external semidirect product, is the trivial group.*)\nLemma im_sdpair_TI : (sdpair1 @* R) :&: (sdpair2 @* D) = 1.\n\n(*This lemma states that the group product of the image of the first component group and the image of the second component group, under their respective projections from an external semidirect product, equals the entire carrier set of the product group.*)\nLemma im_sdpair : (sdpair1 @* R) * (sdpair2 @* D) = setT.\n\n(*This lemma states that the image of the first component group and the image of the second component group, under their respective projections, form an internal semidirect product that is equal to the entire carrier set of the product group.*)\nLemma sdprod_sdpair : sdpair1 @* R ><| sdpair2 @* D = setT.\n\nVariables (A : {set aT}) (G : {set rT}).\n\n(*This lemma states that the centralizer of a given set within an external semidirect product group, with respect to the group's action, is equal to the preimage under the first projection of the centralizer of the set's image under the second projection.*)\nLemma gacentEsd : 'C_(|to)(A) = sdpair1 @*^-1 'C(sdpair2 @* A).\n\nHypotheses (sAD : A \\subset D) (sGR : G \\subset R).\n\n(*This lemma states that the stabilizer of a set from the first component group, under the group action, is equal to the preimage under the second projection of the centralizer of the set's image under the first projection within the total semidirect product group.*)\nLemma astabEsd : 'C(G | to) = sdpair2 @*^-1 'C(sdpair1 @* G).\n\n(*This lemma states that the normalizer of a set from the first component group, under the group action, is equal to the preimage under the second projection of the normalizer of the set's image under the first projection within the total semidirect product group.*)\nLemma astabsEsd : 'N(G | to) = sdpair2 @*^-1 'N(sdpair1 @* G).\n\n(*This lemma states that the proposition that a set from the second component group acts on a set from the first component group is equivalent to the proposition that the image of the first set under the second projection is a subset of the normalizer of the image of the second set under the first projection.*)\nLemma actsEsd : [acts A, on G | to] = (sdpair2 @* A \\subset 'N(sdpair1 @* G)).\n\nEnd ExternalSDirProd.\n\nSection ProdMorph.\n\nVariables gT rT : finGroupType.\nImplicit Types A B : {set gT}.\nImplicit Types G H K : {group gT}.\nImplicit Types C D : {set rT}.\nImplicit Type L : {group rT}.\n\nSection defs.\n\nVariables (A B : {set gT}) (fA fB : gT -> FinGroup.sort rT).\n\n(*This definition constructs a function from the product of two sets of a group to a target group. For any element in the product set, it is defined as the product in the target group of the values of two given functions, where each function is applied to the corresponding factor from the unique decomposition of the element.*)\nDefinition pprodm of B \\subset 'N(A) & {in A & B, morph_act 'J 'J fA fB}\n & {in A :&: B, fA =1 fB} :=\n fun x => fA (divgr A B x) * fB (remgr A B x).\n\nEnd defs.\n\nSection Props.\n\nVariables H K : {group gT}.\nVariables (fH : {morphism H >-> rT}) (fK : {morphism K >-> rT}).\nHypothesis nHK : K \\subset 'N(H).\nHypothesis actf : {in H & K, morph_act 'J 'J fH fK}.\nHypothesis eqfHK : {in H :&: K, fH =1 fK}.\n\n(*This notation defines 'f' as a shorthand for the product morphism constructed from two group morphisms, given that their domain groups satisfy specific normalizer, action compatibility, and intersection properties.*)\nLocal Notation f := (pprodm nHK actf eqfHK).\n\n(*This lemma states that for any element from a group H and any element from a group K, the product morphism 'f' applied to their product is equal to the product of the first morphism applied to the element from H and the second morphism applied to the element from K.*)\nLemma pprodmE x a : x \\in H -> a \\in K -> f (x * a) = fH x * fK a.\n\n(*This lemma states that the product morphism 'f' is equal to the first component morphism when restricted to the domain of the first component morphism.*)\nLemma pprodmEl : {in H, f =1 fH}.\n\n(*This lemma states that the product morphism 'f' is equal to the second component morphism when restricted to the domain of the second component morphism.*)\nLemma pprodmEr : {in K, f =1 fK}.\n\n(*This lemma states that the function 'f', constructed as a product morphism, is a group morphism from the group generated by its two domain groups into the target group.*)\nLemma pprodmM : {in H <*> K &, {morph f: x y / x * y}}.\n\nCanonical pprodm_morphism := Morphism pprodmM.\n\n(*This lemma states that for any subset of the first domain group and any subset of the second domain group, the image of their product set under the product morphism is equal to the group product of their individual images under their respective component morphisms.*)\nLemma morphim_pprodm A B :\n A \\subset H -> B \\subset K -> f @* (A * B) = fH @* A * fK @* B.\n\n(*This lemma states that for any subset of the first domain group, its image under the product morphism is identical to its image under the first component morphism.*)\nLemma morphim_pprodml A : A \\subset H -> f @* A = fH @* A.\n\n(*This lemma states that for any subset of the second domain group, its image under the product morphism is identical to its image under the second component morphism.*)\nLemma morphim_pprodmr B : B \\subset K -> f @* B = fK @* B.\n\n(*This lemma states that the kernel of the product morphism consists of all elements that can be written as the product of an element from the first domain group and the inverse of an element from the second, such that the first morphism applied to the first element yields the same value as the second morphism applied to the second element.*)\nLemma ker_pprodm : 'ker f = [set x * a^-1 | x in H, a in K & fH x == fK a].\n\n(*This lemma states that the product morphism is injective if and only if both component morphisms are injective, and the intersection of the images of the two domain groups is equal to the image of their intersection.*)\nLemma injm_pprodm :\n 'injm f = [&& 'injm fH, 'injm fK & fH @* H :&: fK @* K == fH @* K].\n\nEnd Props.\n\nSection Sdprodm.\n\nVariables H K G : {group gT}.\nVariables (fH : {morphism H >-> rT}) (fK : {morphism K >-> rT}).\nHypothesis eqHK_G : H ><| K = G.\nHypothesis actf : {in H & K, morph_act 'J 'J fH fK}.\n\n(*This lemma states that if a group is the internal semidirect product of two subgroups, then the second subgroup is a subgroup of the normalizer of the first.*)\nLemma sdprodm_norm : K \\subset 'N(H).\n\n(*This lemma states that if a group is the internal semidirect product of two subgroups, then it is a subgroup of the group generated by those two subgroups.*)\nLemma sdprodm_sub : G \\subset H <*> K.\n\n(*This lemma states that for two group morphisms defined on subgroups that form an internal semidirect product, the morphisms are equal when restricted to the intersection of those subgroups.*)\nLemma sdprodm_eqf : {in H :&: K, fH =1 fK}.\n\n(*This definition constructs a semidirect product morphism by first creating a general product morphism from two component morphisms and then restricting its domain to the internal semidirect product of the original domains.*)\nDefinition sdprodm :=\n restrm sdprodm_sub (pprodm sdprodm_norm actf sdprodm_eqf).\n\nCanonical sdprodm_morphism := Eval hnf in [morphism of sdprodm].\n\n(*This lemma states that for any element from the first subgroup and any element from the second subgroup of a semidirect product, the semidirect product morphism applied to their product is equal to the product of the first component morphism applied to the first element and the second component morphism applied to the second element.*)\nLemma sdprodmE a b : a \\in H -> b \\in K -> sdprodm (a * b) = fH a * fK b.\n\n(*This lemma states that for any element in the first subgroup of a semidirect product, the semidirect product morphism evaluates to the same value as the first component morphism.*)\nLemma sdprodmEl a : a \\in H -> sdprodm a = fH a.\n\n(*This lemma states that for any element in the second subgroup of a semidirect product, the semidirect product morphism evaluates to the same value as the second component morphism.*)\nLemma sdprodmEr b : b \\in K -> sdprodm b = fK b.\n\n(*This lemma states that for any subset of the first subgroup and any subset of the second subgroup of a semidirect product, the image of their product set under the semidirect product morphism is equal to the group product of their individual images under their respective component morphisms.*)\nLemma morphim_sdprodm A B :\n A \\subset H -> B \\subset K -> sdprodm @* (A * B) = fH @* A * fK @* B.\n\n(*This lemma states that the image of an entire semidirect product group under the semidirect product morphism is equal to the group product of the image of the first subgroup under the first component morphism and the image of the second subgroup under the second component morphism.*)\nLemma im_sdprodm : sdprodm @* G = fH @* H * fK @* K.\n\n(*This lemma states that for any subset of the first subgroup of a semidirect product, its image under the semidirect product morphism is identical to its image under the first component morphism.*)\nLemma morphim_sdprodml A : A \\subset H -> sdprodm @* A = fH @* A.\n\n(*This lemma states that for any subset of the second subgroup of a semidirect product, its image under the semidirect product morphism is identical to its image under the second component morphism.*)\nLemma morphim_sdprodmr B : B \\subset K -> sdprodm @* B = fK @* B.\n\n(*This lemma states that the kernel of the semidirect product morphism consists of all elements that can be expressed as the product of an element from the first subgroup and the inverse of an element from the second subgroup, where the images of these two elements under their respective morphisms are equal.*)\nLemma ker_sdprodm :\n 'ker sdprodm = [set a * b^-1 | a in H, b in K & fH a == fK b].\n\n(*This lemma provides the condition for a semidirect product morphism to be injective. Injectivity holds if and only if both constituent morphisms are injective and the intersection of the images of the subgroups under their respective morphisms is the trivial group.*)\nLemma injm_sdprodm :\n 'injm sdprodm = [&& 'injm fH, 'injm fK & fH @* H :&: fK @* K == 1].\n\nEnd Sdprodm.\n\nSection Cprodm.\n\nVariables H K G : {group gT}.\nVariables (fH : {morphism H >-> rT}) (fK : {morphism K >-> rT}).\nHypothesis eqHK_G : H \\* K = G.\nHypothesis cfHK : fK @* K \\subset 'C(fH @* H).\nHypothesis eqfHK : {in H :&: K, fH =1 fK}.\n\n(*This lemma states that under the hypotheses for a central product, the second subgroup is a subset of the normalizer of the first subgroup.*)\nLemma cprodm_norm : K \\subset 'N(H).\n\n(*This lemma states that under the hypotheses for a central product, the ambient group is a subset of the subgroup generated by the two given subgroups.*)\nLemma cprodm_sub : G \\subset H <*> K.\n\n(*This lemma states that for elements in the intersection of the two subgroups, the group action associated with the first morphism is compatible with the action associated with the second morphism.*)\nLemma cprodm_actf : {in H & K, morph_act 'J 'J fH fK}.\n\n(*This definition constructs a group morphism from a central product of two subgroups to a target group. This morphism is built from two given morphisms on the subgroups, provided they commute on their images and agree on the intersection of the subgroups.*)\nDefinition cprodm := restrm cprodm_sub (pprodm cprodm_norm cprodm_actf eqfHK).\n\nCanonical cprodm_morphism := Eval hnf in [morphism of cprodm].\n\n(*This lemma specifies how the central product morphism acts on an element formed by multiplying an element from the first subgroup and an element from the second. The result is the product of the images of these elements under their respective original morphisms.*)\nLemma cprodmE a b : a \\in H -> b \\in K -> cprodm (a * b) = fH a * fK b.\n\n(*This lemma states that when the central product morphism is applied to an element belonging to the first subgroup, the result is the same as applying the first subgroup's original morphism to that element.*)\nLemma cprodmEl a : a \\in H -> cprodm a = fH a.\n\n(*This lemma states that when the central product morphism is applied to an element belonging to the second subgroup, the result is the same as applying the second subgroup's original morphism to that element.*)\nLemma cprodmEr b : b \\in K -> cprodm b = fK b.\n\n(*This lemma states that the image under the central product morphism of a set product of a subset of the first subgroup and a subset of the second subgroup is equal to the product of the images of these subsets under their respective original morphisms.*)\nLemma morphim_cprodm A B :\n A \\subset H -> B \\subset K -> cprodm @* (A * B) = fH @* A * fK @* B.\n\n(*This lemma states that the image of the entire source group under the central product morphism is equal to the product of the images of the two constituent subgroups under their respective original morphisms.*)\nLemma im_cprodm : cprodm @* G = fH @* H * fK @* K.\n\n(*This lemma states that the image of a subset of the first subgroup under the central product morphism is equal to the image of that same subset under the first subgroup's original morphism.*)\nLemma morphim_cprodml A : A \\subset H -> cprodm @* A = fH @* A.\n\n(*This lemma states that the image of a subset of the second subgroup under the central product morphism is equal to the image of that same subset under the second subgroup's original morphism.*)\nLemma morphim_cprodmr B : B \\subset K -> cprodm @* B = fK @* B.\n\n(*This lemma characterizes the kernel of the central product morphism. It consists of all elements that can be written as the product of an element from the first subgroup and the inverse of an element from the second subgroup, such that the images of these two elements under their respective morphisms are equal.*)\nLemma ker_cprodm : 'ker cprodm = [set a * b^-1 | a in H, b in K & fH a == fK b].\n\n(*This lemma provides the condition for a central product morphism to be injective. It holds if and only if both constituent morphisms are injective and the intersection of the images of the two subgroups equals the image of their intersection.*)\nLemma injm_cprodm :\n 'injm cprodm = [&& 'injm fH, 'injm fK & fH @* H :&: fK @* K == fH @* K].\n\nEnd Cprodm.\n\nSection Dprodm.\n\nVariables G H K : {group gT}.\nVariables (fH : {morphism H >-> rT}) (fK : {morphism K >-> rT}).\nHypothesis eqHK_G : H \\x K = G.\nHypothesis cfHK : fK @* K \\subset 'C(fH @* H).\n\n(*This lemma states that if a group is the internal direct product of two subgroups, then it is also their central product.*)\nLemma dprodm_cprod : H \\* K = G.\n\n(*This lemma establishes that if a group is the internal direct product of two subgroups, then the two morphisms defined on these subgroups agree on their intersection.*)\nLemma dprodm_eqf : {in H :&: K, fH =1 fK}.\n\n(*This definition constructs a group morphism from a direct product of two subgroups to a target group, leveraging the properties of a central product morphism.*)\nDefinition dprodm := cprodm dprodm_cprod cfHK dprodm_eqf.\n\nCanonical dprodm_morphism := Eval hnf in [morphism of dprodm].\n\n(*This lemma specifies how the direct product morphism acts on an element formed by multiplying an element from the first subgroup and an element from the second. The result is the product of the images of these elements under their respective original morphisms.*)\nLemma dprodmE a b : a \\in H -> b \\in K -> dprodm (a * b) = fH a * fK b.\n\n(*This lemma states that when the direct product morphism is applied to an element belonging to the first subgroup, the result is the same as applying the first subgroup's original morphism to that element.*)\nLemma dprodmEl a : a \\in H -> dprodm a = fH a.\n\n(*This lemma states that when the direct product morphism is applied to an element belonging to the second subgroup, the result is the same as applying the second subgroup's original morphism to that element.*)\nLemma dprodmEr b : b \\in K -> dprodm b = fK b.\n\n(*This lemma states that the image under the direct product morphism of a set product of a subset of the first subgroup and a subset of the second subgroup is equal to the product of the images of these subsets under their respective original morphisms.*)\nLemma morphim_dprodm A B :\n A \\subset H -> B \\subset K -> dprodm @* (A * B) = fH @* A * fK @* B.\n\n(*This lemma states that the image of the entire source group under the direct product morphism is equal to the product of the images of the two constituent subgroups under their respective original morphisms.*)\nLemma im_dprodm : dprodm @* G = fH @* H * fK @* K.\n\n(*This lemma states that the image of a subset of the first subgroup under the direct product morphism is equal to the image of that same subset under the first subgroup's original morphism.*)\nLemma morphim_dprodml A : A \\subset H -> dprodm @* A = fH @* A.\n\n(*This lemma states that the image of a subset of the second subgroup under the direct product morphism is equal to the image of that same subset under the second subgroup's original morphism.*)\nLemma morphim_dprodmr B : B \\subset K -> dprodm @* B = fK @* B.\n\n(*This lemma characterizes the kernel of the direct product morphism. It consists of all elements that can be written as the product of an element from the first subgroup and the inverse of an element from the second subgroup, such that the images of these two elements under their respective morphisms are equal.*)\nLemma ker_dprodm : 'ker dprodm = [set a * b^-1 | a in H, b in K & fH a == fK b].\n\n(*This lemma provides the condition for a direct product morphism to be injective. Injectivity holds if and only if both constituent morphisms are injective and the intersection of the images of the subgroups under their respective morphisms is the trivial group.*)\nLemma injm_dprodm :\n 'injm dprodm = [&& 'injm fH, 'injm fK & fH @* H :&: fK @* K == 1].\n\nEnd Dprodm.\n\n(*This lemma states that if a first group is the direct product of two subgroups and a second group is the direct product of two other subgroups, and if the corresponding component subgroups are isomorphic, then the two product groups are also isomorphic.*)\nLemma isog_dprod A B G C D L :\n A \\x B = G -> C \\x D = L -> isog A C -> isog B D -> isog G L.\n\nEnd ProdMorph.\n\nSection ExtSdprodm.\n\nVariables gT aT rT : finGroupType.\nVariables (H : {group gT}) (K : {group aT}) (to : groupAction K H).\nVariables (fH : {morphism H >-> rT}) (fK : {morphism K >-> rT}).\n\nHypothesis actf : {in H & K, morph_act to 'J fH fK}.\n\n(*This notation defines a new group morphism by composing a given morphism on the first component of a semidirect product with the inverse of the canonical injection into that component. It effectively extends the morphism to the entire semidirect product group, acting on the first component.*)\nLocal Notation fsH := (fH \\o invm (injm_sdpair1 to)).\n(*This notation defines a new group morphism by composing a given morphism on the second component of a semidirect product with the inverse of the canonical injection into that component. It effectively extends the morphism to the entire semidirect product group, acting on the second component.*)\nLocal Notation fsK := (fK \\o invm (injm_sdpair2 to)).\n(*This definition denotes the set obtained by taking the image of a given set under the first projection function of a sub-direct pair.*)\nLet DgH := sdpair1 to @* H.\n(*This definition denotes the set obtained by taking the image of a given set under the second projection function of a sub-direct pair.*)\nLet DgK := sdpair2 to @* K.\n\n(*This lemma states that the set obtained by projecting a given set onto its first component is a subset of the domain of a corresponding first function.*)\nLemma xsdprodm_dom1 : DgH \\subset 'dom fsH.\n\n(*This notation introduces a shorthand for the function that results from restricting a given function to the domain corresponding to the first projection of a set.*)\nLocal Notation gH := (restrm xsdprodm_dom1 fsH).\n\n(*This lemma states that the set obtained by projecting a given set onto its second component is a subset of the domain of a corresponding second function.*)\nLemma xsdprodm_dom2 : DgK \\subset 'dom fsK.\n\n(*This notation introduces a shorthand for the function that results from restricting a given function to the domain corresponding to the second projection of a set.*)\nLocal Notation gK := (restrm xsdprodm_dom2 fsK).\n\n(*This lemma states that the image of the first projected set under the first restricted function is equal to the image of the original first set under the original first function.*)\nLemma im_sdprodm1 : gH @* DgH = fH @* H.\n\n(*This lemma states that the image of the second projected set under the second restricted function is equal to the image of the original second set under the original second function.*)\nLemma im_sdprodm2 : gK @* DgK = fK @* K.\n\n(*This lemma asserts that the two restricted functions, acting on their respective projected domains, satisfy the conditions required to form a valid morphism action.*)\nLemma xsdprodm_act : {in DgH & DgK, morph_act 'J 'J gH gK}.\n\n(*This definition creates an extended sub-direct product morphism by combining a sub-direct pair projection with a proof that the component functions constitute a valid morphism action.*)\nDefinition xsdprodm := sdprodm (sdprod_sdpair to) xsdprodm_act.\nCanonical xsdprod_morphism := [morphism of xsdprodm].\n\n(*This lemma states that the image of the domain of the extended sub-direct product morphism is the Cartesian product of the images of the original component sets under their respective original functions.*)\nLemma im_xsdprodm : xsdprodm @* setT = fH @* H * fK @* K.\n\n(*This lemma states that the extended sub-direct product morphism is injective if and only if both of its original component functions are injective and the intersection of the images of their respective domains is a trivial set.*)\nLemma injm_xsdprodm :\n 'injm xsdprodm = [&& 'injm fH, 'injm fK & fH @* H :&: fK @* K == 1].\n\nEnd ExtSdprodm.\n\nSection DirprodIsom.\n\nVariable gT : finGroupType.\nImplicit Types G H : {group gT}.\n\n(*This definition specifies a function that takes a pair of elements from a finite group and returns their group product.*)\nDefinition mulgm : gT * gT -> _ := uncurry mulg.\n\n(*This lemma states that the image of the Cartesian product of two sets of group elements under the group multiplication function is equal to the group-theoretic product of those two sets.*)\nLemma imset_mulgm (A B : {set gT}) : mulgm @: setX A B = A * B.\n\n(*This lemma states that a group is the internal direct product of two of its subgroups if and only if the group multiplication function defines an isomorphism from the Cartesian product of the two subgroups to the group itself.*)\nLemma mulgmP H1 H2 G : reflect (H1 \\x H2 = G) (misom (setX H1 H2) G mulgm).\n\nEnd DirprodIsom.\n\nArguments mulgmP {gT H1 H2 G}.", - "fingroup.fingroup": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype div path tuple bigop prime finset.\nFrom mathcomp Require Export monoid.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope Group_scope.\n\nDelimit Scope Group_scope with G.\n\nModule GroupScope.\nOpen Scope group_scope.\nEnd GroupScope.\nImport GroupScope.\n\nReserved Notation \"[ ~ x1 , x2 , .. , xn ]\"\n (format \"'[ ' [ ~ x1 , '/' x2 , '/' .. , '/' xn ] ']'\").\nReserved Notation \"[ 1 gT ]\" (format \"[ 1 gT ]\").\nReserved Notation \"[ 1 ]\" (format \"[ 1 ]\").\nReserved Notation \"[ 'subg' G ]\" (format \"[ 'subg' G ]\").\nReserved Notation \"A ^#\" (format \"A ^#\").\nReserved Notation \"A :^ x\" (at level 35, right associativity).\nReserved Notation \"x ^: B\" (at level 35, right associativity).\nReserved Notation \"A :^: B\" (at level 35, right associativity).\nReserved Notation \"#| B : A |\" (A at level 99, format \"#| B : A |\").\nReserved Notation \"''N' ( A )\" (format \"''N' ( A )\").\nReserved Notation \"''N_' G ( A )\" (G at level 2, format \"''N_' G ( A )\").\nReserved Notation \"A <| B\" (at level 70, no associativity).\nReserved Notation \"A <*> B\" (at level 40, left associativity).\nReserved Notation \"[ ~: A1 , A2 , .. , An ]\"\n (format \"[ ~: '[' A1 , '/' A2 , '/' .. , '/' An ']' ]\").\nReserved Notation \"[ 'max' A 'of' G | gP ]\"\n (format \"[ '[hv' 'max' A 'of' G '/ ' | gP ']' ]\").\nReserved Notation \"[ 'max' G | gP ]\"\n (format \"[ '[hv' 'max' G '/ ' | gP ']' ]\").\nReserved Notation \"[ 'max' A 'of' G | gP & gQ ]\"\n (format \"[ '[hv' 'max' A 'of' G '/ ' | gP '/ ' & gQ ']' ]\").\nReserved Notation \"[ 'max' G | gP & gQ ]\"\n (format \"[ '[hv' 'max' G '/ ' | gP '/ ' & gQ ']' ]\").\nReserved Notation \"[ 'min' A 'of' G | gP ]\"\n (format \"[ '[hv' 'min' A 'of' G '/ ' | gP ']' ]\").\nReserved Notation \"[ 'min' G | gP ]\"\n (format \"[ '[hv' 'min' G '/ ' | gP ']' ]\").\nReserved Notation \"[ 'min' A 'of' G | gP & gQ ]\"\n (format \"[ '[hv' 'min' A 'of' G '/ ' | gP '/ ' & gQ ']' ]\").\nReserved Notation \"[ 'min' G | gP & gQ ]\"\n (format \"[ '[hv' 'min' G '/ ' | gP '/ ' & gQ ']' ]\").\n\n(*A record packaging the properties of a base multiplicative group. This structure includes a binary operation, a unit element, and an inverse function. It asserts that the operation is associative, that the unit is a left identity, that the inverse is an involution, and that the inverse of a product is the product of the inverses in reverse order.*)\nHB.mixin Record isMulBaseGroup G := {\n mulg_subdef : G -> G -> G;\n oneg_subdef : G;\n invg_subdef : G -> G;\n mulgA_subproof : associative mulg_subdef ;\n mul1g_subproof : left_id oneg_subdef mulg_subdef ;\n invgK_subproof : involutive invg_subdef ;\n invMg_subproof : {morph invg_subdef : x y / mulg_subdef x y >-> mulg_subdef y x}\n}.\n\n#[arg_sort, short(type=\"baseFinGroupType\")]\n(*Defines the structure of a base finite group, which is a finite type equipped with the algebraic properties of a base group. These properties include an associative binary operation, a left identity element, and an inverse function that is both an involution and an anti-morphism with respect to the operation.*)\nHB.structure Definition BaseFinGroup := { G of isMulBaseGroup G & Finite G }.\n\nModule BaseFinGroupExports.\nBind Scope group_scope with BaseFinGroup.arg_sort.\nBind Scope group_scope with BaseFinGroup.sort.\nEnd BaseFinGroupExports.\nHB.export BaseFinGroupExports.\n\nModule Notations.\nSection ElementOps.\n\nVariable T : baseFinGroupType.\n(*A notation that provides a shorthand for the underlying carrier type of a given base finite group structure.*)\nNotation rT := (BaseFinGroup.sort T).\n\n(*This definition provides the identity element, also known as the unit, of a base finite group.*)\nDefinition oneg : rT := Eval unfold oneg_subdef in @oneg_subdef T.\n(*This definition provides the binary multiplication operation of a base finite group.*)\nDefinition mulg : T -> T -> rT := Eval unfold mulg_subdef in @mulg_subdef T.\n(*This definition provides the unary inverse operation of a base finite group.*)\nDefinition invg : T -> rT := Eval unfold invg_subdef in @invg_subdef T.\n(*This function computes the non-negative integer power of a group element. It takes a group element and a natural number, and returns the result of applying the group multiplication to the element with itself that many times. A zero exponent yields the group's identity element.*)\nDefinition expgn (x : T) n : rT := iterop n mulg x oneg.\n\nEnd ElementOps.\nArguments expgn : simpl never.\n\n(*This notation provides the standard symbol for the identity element, or unit, of a group.*)\nNotation \"1\" := (@oneg _) : group_scope.\n(*This notation provides the standard infix symbol for the binary group operation, typically referred to as multiplication.*)\nNotation \"x1 * x2\" := (mulg x1 x2) : group_scope.\n(*This notation provides the standard symbol for the inverse of a group element.*)\nNotation \"x ^-1\" := (invg x) : group_scope.\n(*This notation represents raising a group element to the power of a natural number, which corresponds to repeatedly applying the group multiplication.*)\nNotation \"x ^+ n\" := (expgn x n) : group_scope.\n(*This notation represents raising a group element to a negative integer power. It is defined as the inverse of that element raised to the corresponding positive integer power.*)\nNotation \"x ^- n\" := (x ^+ n)^-1 : group_scope.\nEnd Notations.\nHB.export Notations.\n\n(*A mixin record that adds the left-inverse axiom to a base finite group structure. This axiom asserts that multiplying an element by its inverse on the left yields the identity element, thereby promoting the structure to that of a full group.*)\nHB.mixin Record BaseFinGroup_isGroup G of BaseFinGroup G := {\n mulVg_subproof : left_inverse (@oneg G) (@invg _) (@mulg _)\n}.\n\n#[short(type=\"finGroupType\")]\n(*This structure defines a finite group, which is a finite type equipped with an associative binary operation, a left identity element, and a left inverse for every element.*)\nHB.structure Definition FinGroup :=\n { G of BaseFinGroup_isGroup G & BaseFinGroup G }.\n\nModule FinGroupExports.\nBind Scope group_scope with FinGroup.sort.\nEnd FinGroupExports.\nHB.export FinGroupExports.\n\n(*A factory record used to construct a finite group structure directly from its fundamental components. It requires a finite type, a binary operation, an identity element, an inverse function, and explicit proofs of the group axioms: associativity, left identity, and left inverse.*)\nHB.factory Record isMulGroup G of Finite G := {\n mulg : G -> G -> G;\n oneg : G;\n invg : G -> G;\n mulgA : associative mulg;\n mul1g : left_id oneg mulg;\n mulVg : left_inverse oneg invg mulg;\n}.\n\nHB.builders Context G of isMulGroup G.\n\n(*This notation represents the identity element of the multiplicative group.*)\nNotation \"1\" := oneg.\nInfix \"*\" := mulg.\n(*This notation represents the multiplicative inverse of a group element.*)\nNotation \"x ^-1\" := (invg x).\n\n(*This lemma states that the group inversion operation is an involution, meaning that applying the inverse operation twice to any group element returns the original element.*)\nLemma mk_invgK : involutive invg.\n\n(*This lemma states that the group inversion operation is an anti-morphism for multiplication. This means that the inverse of a product of two group elements is equal to the product of their inverses taken in reverse order.*)\nLemma mk_invMg : {morph invg : x y / x * y >-> y * x}.\n\nHB.instance Definition _ :=\n isMulBaseGroup.Build G mulgA mul1g mk_invgK mk_invMg.\nHB.instance Definition _ := BaseFinGroup_isGroup.Build G mulVg.\n\nHB.end.\n\n#[compress_coercions]\nHB.instance Definition _ (T : baseFinGroupType) :\n Finite (BaseFinGroup.arg_sort T) := Finite.class T.\n\n(*This definition specifies the conjugation of one group element by another. The result is obtained by multiplying the first element on the left by the inverse of the second element and on the right by the second element itself.*)\nDefinition conjg (T : finGroupType) (x y : T) := y^-1 * (x * y).\n(*This notation represents the conjugation of a first group element by a second group element.*)\nNotation \"x1 ^ x2\" := (conjg x1 x2) : group_scope.\n\n(*This definition specifies the commutator of two group elements, defined as the product of the inverse of the first element and the conjugate of the first element by the second.*)\nDefinition commg (T : finGroupType) (x y : T) := x^-1 * x ^ y.\n(*A notation for the left-nested commutator of a sequence of group elements. A commutator of two elements is defined as the product of the inverse of the first, the inverse of the second, the first, and the second. This notation extends this to a sequence of elements by applying the commutator operation iteratively from left to right.*)\nNotation \"[ ~ x1 , x2 , .. , xn ]\" := (commg .. (commg x1 x2) .. xn)\n : group_scope.\n\nPrenex Implicits mulg invg expgn conjg commg.\n\n(*This notation represents the product of a series of group elements, indexed by a variable bound to a finite sequence, where only the elements satisfying a given boolean predicate are included in the product.*)\nNotation \"\\prod_ ( i <- r | P ) F\" :=\n (\\big[mulg/1]_(i <- r | P%B) F%g) : group_scope.\n(*This notation represents the product of a series of group elements, indexed by a variable that iterates over all elements of a given finite sequence.*)\nNotation \"\\prod_ ( i <- r ) F\" :=\n (\\big[mulg/1]_(i <- r) F%g) : group_scope.\n(*This notation represents the product of a series of group elements, indexed by a natural number that ranges from a lower bound (inclusive) to an upper bound (exclusive), where only the elements satisfying a given boolean predicate are included in the product.*)\nNotation \"\\prod_ ( m <= i < n | P ) F\" :=\n (\\big[mulg/1]_(m <= i < n | P%B) F%g) : group_scope.\n(*This notation represents the product of a series of group elements, indexed by a natural number that ranges from a lower bound (inclusive) to an upper bound (exclusive).*)\nNotation \"\\prod_ ( m <= i < n ) F\" :=\n (\\big[mulg/1]_(m <= i < n) F%g) : group_scope.\n(*This notation represents the product of a series of group elements over all elements of an enumerated finite type, where only the elements satisfying a given boolean predicate are included in the product.*)\nNotation \"\\prod_ ( i | P ) F\" :=\n (\\big[mulg/1]_(i | P%B) F%g) : group_scope.\n(*This notation represents the product of a series of group elements over all elements of an enumerated finite type.*)\nNotation \"\\prod_ i F\" :=\n (\\big[mulg/1]_i F%g) : group_scope.\n(*This notation represents the product of a series of group elements over a specified finite type, where only the elements satisfying a given boolean predicate are included in the product. This notation is for parsing only.*)\nNotation \"\\prod_ ( i : t | P ) F\" :=\n (\\big[mulg/1]_(i : t | P%B) F%g) (only parsing) : group_scope.\n(*This notation represents the product of a series of group elements over all elements of a specified finite type. This notation is for parsing only.*)\nNotation \"\\prod_ ( i : t ) F\" :=\n (\\big[mulg/1]_(i : t) F%g) (only parsing) : group_scope.\n(*This notation represents the product of a series of group elements, indexed by a natural number less than a given upper bound, where only the elements satisfying a given boolean predicate are included in the product.*)\nNotation \"\\prod_ ( i < n | P ) F\" :=\n (\\big[mulg/1]_(i < n | P%B) F%g) : group_scope.\n(*This notation represents the product of a series of group elements, indexed by a natural number that is less than a given upper bound.*)\nNotation \"\\prod_ ( i < n ) F\" :=\n (\\big[mulg/1]_(i < n) F%g) : group_scope.\n(*This notation represents the product of a series of group elements, indexed by the members of a given finite set, where only the elements satisfying a given boolean predicate are included in the product.*)\nNotation \"\\prod_ ( i 'in' A | P ) F\" :=\n (\\big[mulg/1]_(i in A | P%B) F%g) : group_scope.\n(*This notation represents the product of a series of group elements, indexed by the members of a given finite set.*)\nNotation \"\\prod_ ( i 'in' A ) F\" :=\n (\\big[mulg/1]_(i in A) F%g) : group_scope.\n\nSection PreGroupIdentities.\n\nVariable T : baseFinGroupType.\nImplicit Types x y z : T.\n(*This notation provides a local alias for the multiplication operation of a specific finite group, which takes two group elements as input and returns their product.*)\nLocal Notation mulgT := (@mulg T).\n\n(*This lemma states that the group multiplication operation is associative, meaning that the order in which consecutive multiplications are performed does not affect the final result.*)\nLemma mulgA : associative mulgT. \n(*This lemma states that the multiplicative identity element acts as a left identity for the group multiplication, meaning that multiplying any group element on the left by the identity returns the original element.*)\nLemma mul1g : left_id 1 mulgT. \n(*This lemma states that the group inversion operation is an involution, meaning that taking the inverse of an inverse of a group element returns the original element.*)\nLemma invgK : @involutive T invg. \n(*This lemma states that the inverse of a product of two group elements is equal to the product of their inverses in the reverse order.*)\nLemma invMg x y : (x * y)^-1 = y^-1 * x^-1. \n\n(*This lemma states that the group inversion operation is injective, meaning that two distinct group elements will have two distinct inverses.*)\nLemma invg_inj : @injective T T invg. \n\n(*This lemma states that the equality between the inverse of a first group element and a second group element is equivalent to the equality between the first group element and the inverse of the second.*)\nLemma eq_invg_sym x y : (x^-1 == y) = (x == y^-1).\n\n(*This lemma states that the multiplicative inverse of the group's identity element is the identity element itself.*)\nLemma invg1 : 1^-1 = 1 :> T.\n\n(*This lemma states that a group element's inverse is equal to the identity element if and only if the element itself is the identity element.*)\nLemma eq_invg1 x : (x^-1 == 1) = (x == 1).\n\n(*This lemma states that the multiplicative identity element acts as a right identity for the group multiplication, meaning that multiplying any group element on the right by the identity returns that same element.*)\nLemma mulg1 : right_id 1 mulgT.\n\n(*This lemma states that raising a group element to the power of a natural number is equivalent to repeatedly applying the group multiplication that many times to the element, starting with the identity element.*)\nLemma expgnE x n : x ^+ n = iterop n mulg x 1. \n\n(*This lemma states that raising any group element to the power of zero yields the identity element of the group.*)\nLemma expg0 x : x ^+ 0 = 1. \n(*This lemma states that raising any group element to the power of one yields the element itself.*)\nLemma expg1 x : x ^+ 1 = x. \n\n(*This lemma states that raising a group element to the power of the successor of a natural number is equivalent to multiplying the element by itself raised to the power of that natural number.*)\nLemma expgS x n : x ^+ n.+1 = x * x ^+ n.\n\n(*This lemma states that raising the identity element of a group to any natural number power results in the identity element.*)\nLemma expg1n n : 1 ^+ n = 1 :> T.\n\n(*This lemma states that for any group element, raising it to the power of the sum of two natural numbers is equivalent to multiplying the element raised to the first number by the element raised to the second number.*)\nLemma expgD x n m : x ^+ (n + m) = x ^+ n * x ^+ m.\n\n(*This lemma states that raising a group element to the power of the successor of a natural number is equivalent to multiplying the element raised to that natural number by the element itself.*)\nLemma expgSr x n : x ^+ n.+1 = x ^+ n * x.\n\n(*This lemma states that raising a group element to the power of a product of two natural numbers is equivalent to raising the element to the power of the first number, and then raising the result to the power of the second number.*)\nLemma expgM x n m : x ^+ (n * m) = x ^+ n ^+ m.\n\n(*This lemma states that for a given group element, the operation of iterated exponentiation by two natural numbers is commutative.*)\nLemma expgAC x m n : x ^+ m ^+ n = x ^+ n ^+ m.\n\n(*This definition specifies that two group elements commute if the result of their multiplication is independent of the order of the elements.*)\nDefinition commute x y := x * y = y * x.\n\n(*This lemma states that any group element commutes with itself.*)\nLemma commute_refl x : commute x x.\n\n(*This lemma states that the commute relation between two group elements is symmetric; if a first element commutes with a second, then the second also commutes with the first.*)\nLemma commute_sym x y : commute x y -> commute y x.\n\n(*This lemma states that any group element commutes with the identity element of the group.*)\nLemma commute1 x : commute x 1.\n\n(*This lemma states that if a group element commutes with two other elements individually, it also commutes with their product.*)\nLemma commuteM x y z : commute x y -> commute x z -> commute x (y * z).\n\n(*This lemma states that if a group element commutes with another element, it also commutes with any natural number power of that other element.*)\nLemma commuteX x y n : commute x y -> commute x (y ^+ n).\n\n(*This lemma states that if two group elements commute, then any natural number power of the first element commutes with any natural number power of the second element.*)\nLemma commuteX2 x y m n : commute x y -> commute (x ^+ m) (y ^+ n).\n\n(*This lemma states that raising the inverse of a group element to a natural number power is equivalent to taking the inverse of the element raised to that same power.*)\nLemma expgVn x n : x^-1 ^+ n = x ^- n.\n\n(*This lemma states that if two group elements commute, then the result of raising their product to a natural number power is the same as the product of each element raised individually to that power.*)\nLemma expgMn x y n : commute x y -> (x * y) ^+ n = x ^+ n * y ^+ n.\n\nEnd PreGroupIdentities.\n\n#[global] Hint Resolve commute1 : core.\nArguments invg_inj {T} [x1 x2].\nPrenex Implicits commute invgK.\n\nSection GroupIdentities.\n\nVariable T : finGroupType.\nImplicit Types x y z : T.\n(*This local notation provides an alias for the group multiplication operation on a specific base finite group type.*)\nLocal Notation mulgT := (@mulg T).\n\n(*This lemma states that the group's inverse operation provides a left inverse for every element with respect to the group's multiplication, meaning multiplying the inverse of an element by the element itself yields the identity element.*)\nLemma mulVg : left_inverse 1 invg mulgT. \n\n(*This lemma states that the group's inverse operation provides a right inverse for every element with respect to the group's multiplication, meaning multiplying an element by its inverse yields the identity element.*)\nLemma mulgV : right_inverse 1 invg mulgT.\n\n(*This lemma states that the group multiplication exhibits a left cancellation property with the inverse operation, where multiplying the inverse of an element with the product of that element and another one results in the second element.*)\nLemma mulKg : left_loop invg mulgT.\n\n(*This lemma states a reversed form of the left cancellation property, where multiplying an element by the product of its inverse and a second element results in the second element.*)\nLemma mulKVg : rev_left_loop invg mulgT.\n\n(*This lemma states that the group multiplication operation is right-injective, meaning that if two elements multiplied by a third element on the right are equal, then the original two elements must be equal.*)\nLemma mulgI : right_injective mulgT.\n\n(*This lemma states that the group multiplication exhibits a right cancellation property with the inverse operation, where multiplying the product of two elements by the inverse of the second element results in the first element.*)\nLemma mulgK : right_loop invg mulgT.\n\n(*This lemma states a reversed form of the right cancellation property, where multiplying the product of an element and the inverse of a second element by that second element results in the first element.*)\nLemma mulgKV : rev_right_loop invg mulgT.\n\n(*This lemma states that the group multiplication operation is left-injective, meaning that if a third element multiplied by two different elements on the left results in equal values, then the two different elements must be equal.*)\nLemma mulIg : left_injective mulgT.\n\n(*This lemma states that an element is equal to the inverse of another element if and only if their product equals the group's identity element.*)\nLemma eq_invg_mul x y : (x^-1 == y :> T) = (x * y == 1 :> T).\n\n(*This lemma states that two group elements are equal if and only if the product of the first element and the inverse of the second element is the identity element.*)\nLemma eq_mulgV1 x y : (x == y) = (x * y^-1 == 1 :> T).\n\n(*This lemma states that two group elements are equal if and only if the product of the inverse of the first element and the second element is the identity element.*)\nLemma eq_mulVg1 x y : (x == y) = (x^-1 * y == 1 :> T).\n\n(*This lemma states that if a first group element commutes with a second group element, then the first element also commutes with the inverse of the second element.*)\nLemma commuteV x y : commute x y -> commute x y^-1.\n\n(*This lemma states that the conjugation of a first group element by a second group element is equal to the product of the inverse of the second element, the first element, and the second element.*)\nLemma conjgE x y : x ^ y = y^-1 * (x * y). \n\n(*This lemma states that the product of a first group element and a second group element is equal to the product of the second element and the conjugation of the first element by the second.*)\nLemma conjgC x y : x * y = y * x ^ y.\n\n(*This lemma states that the product of a first group element and a second group element is equal to the product of the conjugation of the second element by the inverse of the first, and the first element.*)\nLemma conjgCV x y : x * y = y ^ x^-1 * x.\n\n(*This lemma states that conjugating any group element by the identity element results in the original element.*)\nLemma conjg1 x : x ^ 1 = x.\n\n(*This lemma states that conjugating the identity element by any group element results in the identity element.*)\nLemma conj1g x : 1 ^ x = 1.\n\n(*This lemma states that the conjugation of a product of two group elements by a third element is equal to the product of their individual conjugations by the third element.*)\nLemma conjMg x y z : (x * y) ^ z = x ^ z * y ^ z.\n\n(*This lemma states that conjugating a group element by a product of two other elements is equivalent to first conjugating by the first of the two elements and then conjugating the result by the second.*)\nLemma conjgM x y z : x ^ (y * z) = (x ^ y) ^ z.\n\n(*This lemma states that the conjugation of the inverse of a group element is equal to the inverse of its conjugation.*)\nLemma conjVg x y : x^-1 ^ y = (x ^ y)^-1.\n\n(*This lemma states that successively conjugating a group element first by a second and then by a third is equivalent to conjugating the element first by the third, and then conjugating the result by the conjugation of the second by the third.*)\nLemma conjJg x y z : (x ^ y) ^ z = (x ^ z) ^ y ^ z.\n\n(*This lemma states that the conjugation of a natural number power of a group element is equal to that same power of the conjugated element.*)\nLemma conjXg x y n : (x ^+ n) ^ y = (x ^ y) ^+ n.\n\n(*This lemma states that conjugation is a right loop with respect to the group's inverse operation; specifically, conjugating an element by another element and then conjugating the result by the inverse of the second element restores the original element.*)\nLemma conjgK : @right_loop T T invg conjg.\n\n(*This lemma states that conjugation is a reversed right loop with respect to the group's inverse operation; specifically, conjugating an element by the inverse of another element and then conjugating the result by the second element restores the original element.*)\nLemma conjgKV : @rev_right_loop T T invg conjg.\n\n(*This lemma states that for any fixed second element, the operation of conjugating a group element by that second element is injective.*)\nLemma conjg_inj : @left_injective T T T conjg.\n\n(*This lemma states that the conjugation of a group element by another element results in the identity element if and only if the original element is the identity element.*)\nLemma conjg_eq1 x y : (x ^ y == 1) = (x == 1).\n\n(*This lemma states that the conjugation of a finite product of group elements is equal to the finite product of the conjugated elements.*)\nLemma conjg_prod I r (P : pred I) F z :\n (\\prod_(i <- r | P i) F i) ^ z = \\prod_(i <- r | P i) (F i ^ z).\n\n(*This lemma provides a formula for the commutator of two group elements, stating that it is equal to the product of the inverse of the first element and the conjugation of the first element by the second.*)\nLemma commgEl x y : [~ x, y] = x^-1 * x ^ y. \n\n(*This lemma provides an alternative formula for the commutator of two group elements, expressing it as the product of the conjugation of the inverse of the second element by the first, and the second element itself.*)\nLemma commgEr x y : [~ x, y] = y^-1 ^ x * y.\n\n(*This lemma states that the product of two group elements can be expressed as the product of the elements in reverse order, followed by their commutator.*)\nLemma commgC x y : x * y = y * x * [~ x, y].\n\n(*This lemma states that the product of two group elements is equal to the commutator of their inverses multiplied by the product of the elements in reverse order.*)\nLemma commgCV x y : x * y = [~ x^-1, y^-1] * (y * x).\n\n(*This lemma states that the conjugation of the commutator of two group elements is equal to the commutator of their conjugations.*)\nLemma conjRg x y z : [~ x, y] ^ z = [~ x ^ z, y ^ z].\n\n(*This lemma states that the inverse of the commutator of two group elements is equal to the commutator of the same two elements in reversed order.*)\nLemma invg_comm x y : [~ x, y]^-1 = [~ y, x].\n\n(*This lemma states that two group elements commute if and only if their commutator is equal to the identity element.*)\nLemma commgP x y : reflect (commute x y) ([~ x, y] == 1 :> T).\n\n(*This lemma states that a group element is a fixed point under conjugation by a second element if and only if the commutator of the two elements is equal to the identity element.*)\nLemma conjg_fixP x y : reflect (x ^ y = x) ([~ x, y] == 1 :> T).\n\n(*This lemma states that the commutator of two group elements is the identity element if and only if the commutator of the same two elements in reversed order is the identity element.*)\nLemma commg1_sym x y : ([~ x, y] == 1 :> T) = ([~ y, x] == 1 :> T).\n\n(*This lemma states that the commutator of any group element with the identity element is the identity element.*)\nLemma commg1 x : [~ x, 1] = 1.\n\n(*This lemma states that the commutator of the identity element with any group element is the identity element.*)\nLemma comm1g x : [~ 1, x] = 1.\n\n(*This lemma states that the commutator of any group element with itself is the identity element.*)\nLemma commgg x : [~ x, x] = 1.\n\n(*This lemma states that the commutator of a group element with any of its natural number powers is the identity element.*)\nLemma commgXg x n : [~ x, x ^+ n] = 1.\n\n(*This lemma states that the commutator of a group element with its inverse is the identity element.*)\nLemma commgVg x : [~ x, x^-1] = 1.\n\n(*This lemma states that the commutator of any group element with the inverse of that same element raised to any natural number power is equal to the group's identity element.*)\nLemma commgXVg x n : [~ x, x ^- n] = 1.\n\nEnd GroupIdentities.\n\n#[global] Hint Rewrite mulg1 @mul1g invg1 @mulVg mulgV (@invgK) mulgK mulgKV\n @invMg @mulgA : gsimpl.\n\n(*Defines a tactic for simplifying group expressions by repeatedly applying a database of fundamental group identities, such as associativity, multiplication by the identity, and multiplication of an element by its inverse.*)\nLtac gsimpl := autorewrite with gsimpl; try done.\n\n(*This definition provides a collection of fundamental group simplification lemmas, including identities for multiplication by one on the left and right, the identity element's inverse, the involutivity of the inverse operation, and an element's multiplication with its inverse.*)\nDefinition gsimp := (@mulg1, @mul1g, (@invg1, @invgK), (@mulgV, @mulVg)).\n(*This definition provides a comprehensive collection of group normalization lemmas, bundling simpler identities with more complex ones such as associativity, the inverse of a product, and the involutivity of the inverse operation over products.*)\nDefinition gnorm := (gsimp, (@mulgK, @mulgKV, (@mulgA, @invMg))).\n\nArguments mulgI [T].\nArguments mulIg [T].\nArguments conjg_inj {T} x [x1 x2].\nArguments commgP {T x y}.\nArguments conjg_fixP {T x y}.\n\nSection Repr.\n\nVariable gT : baseFinGroupType.\nImplicit Type A : {set gT}.\n\n(*This definition specifies a representative element for a given set of finite group elements. If the identity element is a member of the set, the representative is the identity element; otherwise, it is a default element chosen from the set.*)\nDefinition repr A := if 1 \\in A then 1 else odflt 1 [pick x in A].\n\n(*This lemma states that if a set of finite group elements is non-empty, then its representative element is a member of that set.*)\nLemma mem_repr A x : x \\in A -> repr A \\in A.\n\n(*This lemma states that for any set of finite group elements with a size greater than zero, its representative element is a member of that set.*)\nLemma card_mem_repr A : #|A| > 0 -> repr A \\in A.\n\n(*This lemma states that the representative element of a singleton set is the single element contained within that set.*)\nLemma repr_set1 x : repr [set x] = x.\n\n(*This lemma states that the representative element of the empty set is the group's identity element.*)\nLemma repr_set0 : repr set0 = 1.\n\nEnd Repr.\n\nArguments mem_repr [gT A].\n\nSection BaseSetMulDef.\n\nVariable gT : baseFinGroupType.\nImplicit Types A B : {set gT}.\n\n(*This definition specifies the product of two sets of group elements as the set containing all possible products formed by taking one element from the first set and one element from the second set.*)\nDefinition set_mulg A B := mulg @2: (A, B).\n(*This definition specifies the inverse of a set of group elements as the set containing the group inverse of each element in the original set.*)\nDefinition set_invg A := invg @^-1: A.\n\n(*This lemma states that the singleton set containing the group identity element acts as a left identity for the set multiplication operation.*)\nLemma set_mul1g : left_id [set 1] set_mulg.\n\n(*This lemma states that the multiplication operation defined on sets of group elements is associative.*)\nLemma set_mulgA : associative set_mulg.\n\n(*This lemma states that the set inversion operation is involutive, meaning that applying it twice to any set of group elements returns the original set.*)\nLemma set_invgK : involutive set_invg.\n\n(*This lemma establishes that the set inversion operation is an anti-morphism for set multiplication; specifically, the inverse of a product of two sets is equal to the product of their inverses in reverse order.*)\nLemma set_invgM : {morph set_invg : A B / set_mulg A B >-> set_mulg B A}.\n\n(*This instance declaration formally constructs a base multiplicative group structure on the type of sets of finite group elements, using the previously established properties of set multiplication, the singleton identity set, and set inversion.*)\nHB.instance Definition set_base_group := isMulBaseGroup.Build (set_type gT)\n set_mulgA set_mul1g set_invgK set_invgM.\n(*This definition establishes a type alias for the carrier set of the group structure on sets, specifying it as the type of all finite sets whose elements are drawn from a given finite group.*)\nDefinition sort (gT : baseFinGroupType) := {set gT}.\nEnd GroupSet.\nIdentity Coercion GroupSet_of_sort : GroupSet.sort >-> set_of.\n\nModule Type GroupSetBaseGroupSig.\n(*Refers to the type representing sets of elements from a given finite group.*)\nDefinition sort (gT : baseFinGroupType) := BaseFinGroup.arg_sort {set gT}.\nEnd GroupSetBaseGroupSig.\n\nModule MakeGroupSetBaseGroup (Gset_base : GroupSetBaseGroupSig).\nIdentity Coercion of_sort : Gset_base.sort >-> BaseFinGroup.arg_sort.\nEnd MakeGroupSetBaseGroup.\n\nModule Export GroupSetBaseGroup := MakeGroupSetBaseGroup GroupSet.\n(*This definition denotes the left coset of a given set of group elements with respect to a given group element, which is the set formed by left-multiplying each element of the input set by the given group element.*)\nDefinition lcoset A x := mulg x @: A.\n(*This definition denotes the right coset of a given set of group elements with respect to a given group element, which is the set formed by right-multiplying each element of the input set by the given group element.*)\nDefinition rcoset A x := mulg^~ x @: A.\n(*This definition computes the set of all left cosets of a first set of group elements, using the elements of a second set as the multipliers.*)\nDefinition lcosets A B := lcoset A @: B.\n(*This definition computes the set of all right cosets of a first set of group elements, using the elements of a second set as the multipliers.*)\nDefinition rcosets A B := rcoset A @: B.\n(*This definition gives the number of distinct right cosets of a first set of group elements, where the multipliers are drawn from a second set of group elements.*)\nDefinition indexg B A := #|rcosets A B|.\n\n(*This definition computes the set of conjugates of a single group element, where the conjugation is performed by every element of a given set of group elements.*)\nDefinition conjugate A x := conjg^~ x @: A.\n(*This definition computes a set of sets, where each inner set is the set of conjugates of an element from a second given set, with conjugation performed by every element of a first given set.*)\nDefinition conjugates A B := conjugate A @: B.\n(*This definition computes the conjugate of a set of group elements by a single group element, resulting in the set of elements obtained by conjugating each element of the input set by the single element.*)\nDefinition class x B := conjg x @: B.\n(*This definition computes the set of all conjugates of a given set of group elements, where the conjugation is performed by each element belonging to the given set itself.*)\nDefinition classes A := class^~ A @: A.\n(*This definition computes the set of all possible results from conjugating an element from a second set by an element from a first set.*)\nDefinition class_support A B := conjg @2: (A, B).\n\n(*This definition computes the set of all commutator elements formed by taking one element from a first set and another from a second set.*)\nDefinition commg_set A B := commg @2: (A, B).\n\n(*This definition gives the set of all group elements such that for each one, the set of its conjugates by all elements of a given input set is a subset of that input set.*)\nDefinition normaliser A := [set x | conjugate A x \\subset A].\n(*This definition gives the set of all group elements that commute with every element in a given set of group elements.*)\nDefinition centraliser A := \\bigcap_(x in A) normaliser [set x].\n(*This predicate is true if a given set of group elements is a subset of its own centraliser, meaning any two elements from the set commute with each other.*)\nDefinition abelian A := A \\subset centraliser A.\n(*This predicate is true if a first set of group elements is a subset of a second set, and the second set is itself a subset of the normaliser of the first set.*)\nDefinition normal A B := (A \\subset B) && (B \\subset normaliser A).\n\n(*This predicate is true if, for any element of the group, the set of its conjugates by the elements of a given set is equal to the given set itself.*)\nDefinition normalised A := forall x, conjugate A x = A.\n(*This predicate is true if a given group element commutes with every element in a given set of group elements.*)\nDefinition centralises x A := forall y, y \\in A -> commute x y.\n(*This predicate is true if every element of the group commutes with every element of a given set.*)\nDefinition centralised A := forall x, centralises x A.\n\nEnd GroupSetMulDef.\n\nArguments lcoset _ _%_g _%_g.\nArguments rcoset _ _%_g _%_g.\nArguments rcosets _ _%_g _%_g.\nArguments lcosets _ _%_g _%_g.\nArguments indexg _ _%_g _%_g.\nArguments conjugate _ _%_g _%_g.\nArguments conjugates _ _%_g _%_g.\nArguments class _ _%_g _%_g.\nArguments classes _ _%_g.\nArguments class_support _ _%_g _%_g.\nArguments commg_set _ _%_g _%_g.\nArguments normaliser _ _%_g.\nArguments centraliser _ _%_g.\nArguments abelian _ _%_g.\nArguments normal _ _%_g _%_g.\nArguments normalised _ _%_g.\nArguments centralises _ _%_g _%_g.\nArguments centralised _ _%_g.\n\n(*A notation for the singleton set containing only the identity element of a specified finite group.*)\nNotation \"[ 1 gT ]\" := (1 : {set gT}) : group_scope.\n(*A notation for the singleton set containing the identity element of a finite group, where the specific group is inferred from the context.*)\nNotation \"[ 1 ]\" := [1 FinGroup.sort _] : group_scope.\n\n(*A notation for the set resulting from removing the identity element from a given set of group elements.*)\nNotation \"A ^#\" := (A :\\ 1) : group_scope.\n\n(*A notation for the left coset of a set of group elements, representing the set formed by left-multiplying each element of the set by a single group element.*)\nNotation \"x *: A\" := ([set x%g] * A) : group_scope.\n(*A notation for the right coset of a set of group elements, representing the set formed by right-multiplying each element of the set by a single group element.*)\nNotation \"A :* x\" := (A * [set x%g]) : group_scope.\n(*A notation for the set of conjugates of a single group element formed by conjugating it with every element from a given set.*)\nNotation \"A :^ x\" := (conjugate A x) : group_scope.\n(*A notation representing the conjugate of a set of group elements by a single group element.*)\nNotation \"x ^: B\" := (class x B) : group_scope.\n(*A notation for the set of sets, where each inner set represents the conjugates of an element from a second set by all elements of a first set.*)\nNotation \"A :^: B\" := (conjugates A B) : group_scope.\n\n(*A notation for the index, defined as the number of distinct right cosets of a first set with multipliers chosen from a second set.*)\nNotation \"#| B : A |\" := (indexg B A) : group_scope.\n\n(*This notation denotes the normaliser of a given set of group elements. The normaliser consists of all elements `g` from the ambient group such that left-multiplying the given set by `g` yields the same set as right-multiplying it by `g`.*)\nNotation \"''N' ( A )\" := (normaliser A) : group_scope.\n(*A notation for the normaliser of a set of group elements within a given subgroup, defined as the intersection of that subgroup with the normaliser.*)\nNotation \"''N_' G ( A )\" := (G%g :&: 'N(A)) : group_scope.\n(*This notation defines a binary relation between two sets of group elements, indicating that the first set is a normal subset of the second set.*)\nNotation \"A <| B\" := (normal A B) : group_scope.\n(*This notation represents the centralizer of a given set of group elements, which is the set of all elements in the group that commute with every element in the given set.*)\nNotation \"''C' ( A )\" := (centraliser A) : group_scope.\n(*This notation denotes the centralizer of a set of group elements within another specified group, which is the set of elements in the specified group that commute with every element in the given set.*)\nNotation \"''C_' G ( A )\" := (G%g :&: 'C(A)) : group_scope.\n(*This notation is a parsing-only variant for the centralizer of a set of group elements within another specified group.*)\nNotation \"''C_' ( G ) ( A )\" := 'C_G(A) (only parsing) : group_scope.\n(*This notation represents the centralizer of a single group element, which is the set of all elements in the group that commute with that specific element.*)\nNotation \"''C' [ x ]\" := 'N([set x%g]) : group_scope.\n(*This notation denotes the centralizer of a single group element within a specified group, which is the set of elements in the specified group that commute with the given element.*)\nNotation \"''C_' G [ x ]\" := 'N_G([set x%g]) : group_scope.\n(*This notation is a parsing-only variant for the centralizer of a single group element within another specified group.*)\nNotation \"''C_' ( G ) [ x ]\" := 'C_G[x] (only parsing) : group_scope.\n\nPrenex Implicits repr lcoset rcoset lcosets rcosets normal.\nPrenex Implicits conjugate conjugates class classes class_support.\nPrenex Implicits commg_set normalised centralised abelian.\n\nSection BaseSetMulProp.\n\nVariable gT : baseFinGroupType.\nImplicit Types A B C D : {set gT}.\nImplicit Type x y z : gT.\n\n(*This lemma states that an element is in the product of two sets of group elements if and only if it can be expressed as the group product of an element from the first set and an element from the second set.*)\nLemma mulsgP A B x :\n reflect (imset2_spec mulg (mem A) (fun _ => mem B) x) (x \\in A * B).\n\n(*This lemma states that if a first group element belongs to a first set and a second group element belongs to a second set, then their group product belongs to the product of the two sets.*)\nLemma mem_mulg A B x y : x \\in A -> y \\in B -> x * y \\in A * B.\n\n(*This lemma states that an element belongs to the indexed product of a family of sets of group elements if and only if it can be expressed as the indexed product of a family of elements, where each element in the family belongs to the corresponding set.*)\nLemma prodsgP (I : finType) (P : pred I) (A : I -> {set gT}) x :\n reflect (exists2 c, forall i, P i -> c i \\in A i & x = \\prod_(i | P i) c i)\n (x \\in \\prod_(i | P i) A i).\n\n(*This lemma states that if every element in a family of group elements belongs to the corresponding set in an indexed family of sets, then the indexed product of the family of elements belongs to the indexed product of the family of sets.*)\nLemma mem_prodg (I : finType) (P : pred I) (A : I -> {set gT}) c :\n (forall i, P i -> c i \\in A i) -> \\prod_(i | P i) c i \\in \\prod_(i | P i) A i.\n\n(*This lemma states that the product of two sets of group elements is a subset of the product of a superset of the first set and the second set.*)\nLemma mulSg A B C : A \\subset B -> A * C \\subset B * C.\n\n(*This lemma states that the product of two sets of group elements is a subset of the product of the first set and a superset of the second set.*)\nLemma mulgS A B C : B \\subset C -> A * B \\subset A * C.\n\n(*This lemma states that if a first set of group elements is a subset of a second set, and a third set is a subset of a fourth set, then the product of the first and third sets is a subset of the product of the second and fourth sets.*)\nLemma mulgSS A B C D : A \\subset B -> C \\subset D -> A * C \\subset B * D.\n\n(*This lemma states that if a set of group elements contains the identity element, then any other set is a subset of its product with that set.*)\nLemma mulg_subl A B : 1 \\in B -> A \\subset A * B.\n\n(*This lemma states that if a set of group elements contains the identity element, then any other set is a subset of the product of that set with the other set.*)\nLemma mulg_subr A B : 1 \\in A -> B \\subset A * B.\n\n(*This lemma states that the product of the union of two sets of group elements with a third set is equal to the union of the product of the first set with the third, and the product of the second set with the third.*)\nLemma mulUg A B C : (A :|: B) * C = (A * C) :|: (B * C).\n\n(*This lemma states that the product of a first set of group elements with the union of a second and a third set is equal to the union of the product of the first and second sets, and the product of the first and third sets.*)\nLemma mulgU A B C : A * (B :|: C) = (A * B) :|: (A * C).\n\n(*This lemma states that the set of inverses of the elements in the union of two sets of group elements is equal to the union of the sets of their respective inverses.*)\nLemma invUg A B : (A :|: B)^-1 = A^-1 :|: B^-1.\n\n(*This lemma states that the set of inverses of the elements in the intersection of two sets of group elements is equal to the intersection of the sets of their respective inverses.*)\nLemma invIg A B : (A :&: B)^-1 = A^-1 :&: B^-1.\n\n(*This lemma states that the set of inverses of the elements in the set difference of two sets of group elements is equal to the set difference of their respective sets of inverses.*)\nLemma invDg A B : (A :\\: B)^-1 = A^-1 :\\: B^-1.\n\n(*This lemma states that the set of inverses of the elements in the complement of a set of group elements is equal to the complement of the set of inverses of the elements in that set.*)\nLemma invCg A : (~: A)^-1 = ~: A^-1.\n\n(*This lemma states that the set of inverses of a first set of group elements is a subset of the set of inverses of a second set if and only if the first set is a subset of the second set.*)\nLemma invSg A B : (A^-1 \\subset B^-1) = (A \\subset B).\n\n(*This lemma states that a group element belongs to the set of inverses of a given set of group elements if and only if the inverse of that element belongs to the given set.*)\nLemma mem_invg x A : (x \\in A^-1) = (x^-1 \\in A).\n\n(*This lemma states that the inverse of a group element belongs to the set of inverses of a given set of group elements if and only if the element itself belongs to the given set.*)\nLemma memV_invg x A : (x^-1 \\in A^-1) = (x \\in A).\n\n(*This lemma states that the cardinality of the set of inverses of a set of group elements is equal to the cardinality of the original set.*)\nLemma card_invg A : #|A^-1| = #|A|.\n\n(*This lemma states that the set containing only the identity group element is definitionally equal to the singleton set of the identity element.*)\nLemma set1gE : 1 = [set 1] :> {set gT}. \n(*This lemma states that a group element belongs to the singleton set containing the identity element if and only if that element is the identity element itself.*)\nLemma set1gP x : reflect (x = 1) (x \\in [1 gT]).\n\n(*This lemma states that multiplying the singleton set containing a group element by another group element on the right results in the singleton set containing the product of the two elements.*)\nLemma mulg_set1 x y : [set x] :* y = [set x * y].\n\n(*This lemma states that the set of inverses of the singleton set containing a group element is equal to the singleton set containing the inverse of that element.*)\nLemma invg_set1 x : [set x]^-1 = [set x^-1].\n\nEnd BaseSetMulProp.\n\nArguments set1gP {gT x}.\nArguments mulsgP {gT A B x}.\nArguments prodsgP {gT I P A x}.\n\nSection GroupSetMulProp.\n\nVariable gT : finGroupType.\nImplicit Types A B C D : {set gT}.\nImplicit Type x y z : gT.\n\n(*This lemma states that the left coset of a set of group elements with respect to a given group element is the set obtained by multiplying each element of the original set on the left by the given element.*)\nLemma lcosetE A x : lcoset A x = x *: A.\n\n(*This lemma states that the cardinality of a left coset of a set of group elements is equal to the cardinality of the original set.*)\nLemma card_lcoset A x : #|x *: A| = #|A|.\n\n(*This lemma states that a group element is a member of a left coset if and only if the product of the inverse of the coset representative and the element is a member of the original set.*)\nLemma mem_lcoset A x y : (y \\in x *: A) = (x^-1 * y \\in A).\n\n(*This lemma provides the characteristic property of left coset membership, stating that a group element belongs to a left coset if and only if it can be expressed as the product of the coset representative and some element from the original set.*)\nLemma lcosetP A x y : reflect (exists2 a, a \\in A & y = x * a) (y \\in x *: A).\n\n(*This lemma provides the characteristic property for membership in a set of left cosets, stating that a given set is a member if and only if it is equal to a left coset formed by an element from the set of representatives.*)\nLemma lcosetsP A B C :\n reflect (exists2 x, x \\in B & C = x *: A) (C \\in lcosets A B).\n\n(*This lemma states that forming a left coset of a set with a product of two group elements is equivalent to successively forming left cosets, first with the right element of the product and then with the left element.*)\nLemma lcosetM A x y : (x * y) *: A = x *: (y *: A).\n\n(*This lemma states that the left coset of a set of group elements formed with the group's identity element is the set itself.*)\nLemma lcoset1 A : 1 *: A = A.\n\n(*This lemma establishes a cancellation property for left cosets, stating that forming a left coset with the inverse of an element on a set that is already a left coset by that element yields the original set.*)\nLemma lcosetK : left_loop invg (fun x A => x *: A).\n\n(*This lemma establishes a reverse cancellation property for left cosets, stating that forming a left coset with an element on a set that is already a left coset by that element's inverse yields the original set.*)\nLemma lcosetKV : rev_left_loop invg (fun x A => x *: A).\n\n(*This lemma states that for a fixed group element, the operation of forming a left coset is injective with respect to the set argument; that is, if two sets produce the same left coset with the same element, the sets must be identical.*)\nLemma lcoset_inj : right_injective (fun x A => x *: A).\n\n(*This lemma states that a left coset of one set is a subset of a left coset of another set, both formed with the same element, if and only if the first set is a subset of the second.*)\nLemma lcosetS x A B : (x *: A \\subset x *: B) = (A \\subset B).\n\n(*This lemma states that a set is a subset of a left coset of another set if and only if the left coset of the first set, formed using the inverse of the original coset's representative, is a subset of the second set.*)\nLemma sub_lcoset x A B : (A \\subset x *: B) = (x^-1 *: A \\subset B).\n\n(*This lemma provides a variant of the subset relationship for left cosets, stating that a set is a subset of a left coset formed with the inverse of an element if and only if the left coset of the first set formed with the original element is a subset of the second set.*)\nLemma sub_lcosetV x A B : (A \\subset x^-1 *: B) = (x *: A \\subset B).\n\n(*This lemma states that the right coset of a set of group elements with respect to a given group element is the set obtained by multiplying each element of the original set on the right by the given element.*)\nLemma rcosetE A x : rcoset A x = A :* x.\n\n(*This lemma states that the cardinality of a right coset of a set of group elements is equal to the cardinality of the original set.*)\nLemma card_rcoset A x : #|A :* x| = #|A|.\n\n(*This lemma states that a group element is a member of a right coset if and only if the product of the element and the inverse of the coset representative is a member of the original set.*)\nLemma mem_rcoset A x y : (y \\in A :* x) = (y * x^-1 \\in A).\n\n(*This lemma provides the characteristic property of right coset membership, stating that a group element belongs to a right coset if and only if it can be expressed as the product of some element from the original set and the coset representative.*)\nLemma rcosetP A x y : reflect (exists2 a, a \\in A & y = a * x) (y \\in A :* x).\n\n(*This lemma provides the characteristic property for membership in a set of right cosets, stating that a given set is a member if and only if it is equal to a right coset formed by an element from the set of representatives.*)\nLemma rcosetsP A B C :\n reflect (exists2 x, x \\in B & C = A :* x) (C \\in rcosets A B).\n\n(*This lemma states that forming a right coset of a set with a product of two group elements is equivalent to successively forming right cosets, first with the left element of the product and then with the right element.*)\nLemma rcosetM A x y : A :* (x * y) = A :* x :* y.\n\n(*This lemma states that the right coset of a set of group elements formed with the group's identity element is the set itself.*)\nLemma rcoset1 A : A :* 1 = A.\n\n(*This lemma establishes a cancellation property for right cosets, stating that forming a right coset with the inverse of an element on a set that is already a right coset by that element yields the original set.*)\nLemma rcosetK : right_loop invg (fun A x => A :* x).\n\n(*This lemma establishes a reverse cancellation property for right cosets, stating that forming a right coset with an element on a set that is already a right coset by that element's inverse yields the original set.*)\nLemma rcosetKV : rev_right_loop invg (fun A x => A :* x).\n\n(*This lemma states that for a fixed group element, the operation of forming a right coset is injective with respect to the set argument; that is, if two sets produce the same right coset with the same element, the sets must be identical.*)\nLemma rcoset_inj : left_injective (fun A x => A :* x).\n\n(*This lemma states that a right coset of one set is a subset of a right coset of another set, both formed with the same element, if and only if the first set is a subset of the second.*)\nLemma rcosetS x A B : (A :* x \\subset B :* x) = (A \\subset B).\n\n(*This lemma states that a set is a subset of a right coset of another set if and only if the right coset of the first set, formed using the inverse of the original coset's representative, is a subset of the second set.*)\nLemma sub_rcoset x A B : (A \\subset B :* x) = (A :* x ^-1 \\subset B).\n\n(*This lemma provides a variant of the subset relationship for right cosets, stating that a set is a subset of a right coset formed with the inverse of an element if and only if the right coset of the first set formed with the original element is a subset of the second set.*)\nLemma sub_rcosetV x A B : (A \\subset B :* x^-1) = (A :* x \\subset B).\n\n(*This lemma states that the set of pointwise inverses of a collection of left cosets is equal to the collection of right cosets formed from the pointwise inverse of the base set and the pointwise inverse of the set of representatives.*)\nLemma invg_lcosets A B : (lcosets A B)^-1 = rcosets A^-1 B^-1.\n\n(*This lemma states that the conjugate of a set of group elements by a given group element is equivalent to the preimage of the original set under the map that conjugates elements by the inverse of the given element.*)\nLemma conjg_preim A x : A :^ x = (conjg^~ x^-1) @^-1: A.\n\n(*This lemma states that a group element belongs to the conjugate of a set by another element if and only if the result of conjugating the first element by the inverse of the second is a member of the original set.*)\nLemma mem_conjg A x y : (y \\in A :^ x) = (y ^ x^-1 \\in A).\n\n(*This lemma states that a group element belongs to the conjugate of a set by the inverse of another element if and only if the result of conjugating the first element by the second is a member of the original set.*)\nLemma mem_conjgV A x y : (y \\in A :^ x^-1) = (y ^ x \\in A).\n\n(*This lemma states that an element conjugated by another element is a member of a conjugated set if and only if the original element is a member of the original set.*)\nLemma memJ_conjg A x y : (y ^ x \\in A :^ x) = (y \\in A).\n\n(*This lemma provides an equivalent expression for the conjugation of a set by an element, defining it as the set product of the inverse of the element, the set itself, and the element.*)\nLemma conjsgE A x : A :^ x = x^-1 *: (A :* x).\n\n(*This lemma states that conjugating a set by the identity element leaves the set unchanged.*)\nLemma conjsg1 A : A :^ 1 = A.\n\n(*This lemma states that conjugating a set by a product of two elements is equivalent to successively conjugating the set first by the first element, and then conjugating the result by the second element.*)\nLemma conjsgM A x y : A :^ (x * y) = (A :^ x) :^ y.\n\n(*This lemma states a cancellation property for set conjugation, where applying conjugation by an element and subsequently by its inverse results in the original set.*)\nLemma conjsgK : @right_loop _ gT invg conjugate.\n\n(*This lemma states a cancellation property for set conjugation, where applying conjugation by the inverse of an element and subsequently by the element itself results in the original set.*)\nLemma conjsgKV : @rev_right_loop _ gT invg conjugate.\n\n(*This lemma asserts that for a fixed element, the operation of conjugating a set is injective, meaning that if two sets become equal after being conjugated by the same element, they must have been equal originally.*)\nLemma conjsg_inj : @left_injective _ gT _ conjugate.\n\n(*This lemma states that the cardinality of a set remains invariant under conjugation; a set and its conjugate have the same number of elements.*)\nLemma cardJg A x : #|A :^ x| = #|A|.\n\n(*This lemma states that the subset relationship is preserved under conjugation, meaning a conjugated set is a subset of another conjugated set if and only if the original set was a subset of the other.*)\nLemma conjSg A B x : (A :^ x \\subset B :^ x) = (A \\subset B).\n\n(*This lemma states that the proper subset relationship is preserved under conjugation, meaning a conjugated set is a proper subset of another if and only if the original set was a proper subset of the other.*)\nLemma properJ A B x : (A :^ x \\proper B :^ x) = (A \\proper B).\n\n(*This lemma provides a rule for moving the conjugation operation across a subset relation, stating that a conjugated set is a subset of another set if and only if the original set is a subset of the other set conjugated by the inverse element.*)\nLemma sub_conjg A B x : (A :^ x \\subset B) = (A \\subset B :^ x^-1).\n\n(*This lemma provides a rule for moving the conjugation operation across a subset relation, stating that a set conjugated by an inverse element is a subset of another set if and only if the original set is a subset of the other set conjugated by the original element.*)\nLemma sub_conjgV A B x : (A :^ x^-1 \\subset B) = (A \\subset B :^ x).\n\n(*This lemma states that conjugating a singleton set containing an element is equivalent to creating a new singleton set containing the conjugated element.*)\nLemma conjg_set1 x y : [set x] :^ y = [set x ^ y].\n\n(*This lemma states that the singleton set containing the identity element is a fixed point of the conjugation operation.*)\nLemma conjs1g x : 1 :^ x = 1.\n\n(*This lemma states that a set after conjugation is equal to the singleton set of the identity element if and only if the original set was equal to the singleton set of the identity element.*)\nLemma conjsg_eq1 A x : (A :^ x == 1%g) = (A == 1%g).\n\n(*This lemma states that conjugation distributes over the set product, meaning the conjugate of a product of two sets is equal to the product of their respective conjugates.*)\nLemma conjsMg A B x : (A * B) :^ x = A :^ x * B :^ x.\n\n(*This lemma states that conjugation distributes over set intersection, meaning the conjugate of the intersection of two sets is equal to the intersection of their respective conjugates.*)\nLemma conjIg A B x : (A :&: B) :^ x = A :^ x :&: B :^ x.\n\n(*This lemma states that conjugating the empty set results in the empty set.*)\nLemma conj0g x : set0 :^ x = set0.\n\n(*This lemma states that conjugating the set of all elements in a group results in the same set.*)\nLemma conjTg x : [set: gT] :^ x = [set: gT].\n\n(*This lemma states that conjugation distributes over an indexed intersection of sets, meaning the intersection of a family of conjugated sets is equal to the conjugate of the intersection of the original family of sets.*)\nLemma bigcapJ I r (P : pred I) (B : I -> {set gT}) x :\n \\bigcap_(i <- r | P i) (B i :^ x) = (\\bigcap_(i <- r | P i) B i) :^ x.\n\n(*This lemma states that conjugation distributes over set union, meaning the conjugate of the union of two sets is equal to the union of their respective conjugates.*)\nLemma conjUg A B x : (A :|: B) :^ x = A :^ x :|: B :^ x.\n\n(*This lemma states that conjugation distributes over an indexed union of sets, meaning the union of a family of conjugated sets is equal to the conjugate of the union of the original family of sets.*)\nLemma bigcupJ I r (P : pred I) (B : I -> {set gT}) x :\n \\bigcup_(i <- r | P i) (B i :^ x) = (\\bigcup_(i <- r | P i) B i) :^ x.\n\n(*This lemma states that the conjugation operation commutes with the set complement operation; the conjugate of a set's complement is the complement of the conjugated set.*)\nLemma conjCg A x : (~: A) :^ x = ~: A :^ x.\n\n(*This lemma states that conjugation distributes over set difference; the conjugate of the difference between two sets is the difference between their respective conjugates.*)\nLemma conjDg A B x : (A :\\: B) :^ x = A :^ x :\\: B :^ x.\n\n(*This lemma states that conjugation commutes with the operation of taking the set of inverses of all elements in a set.*)\nLemma conjD1g A x : A^# :^ x = (A :^ x)^#.\n\n(*This lemma establishes a membership rule for a set of conjugates, stating that if an element is a member of a given set, then another element conjugated by that member belongs to the set formed by conjugating the second element by all members of the given set.*)\nLemma memJ_class x y A : y \\in A -> x ^ y \\in x ^: A.\n\n(*This lemma states that the operation of forming a set of conjugates is monotonic with respect to the subset relation.*)\nLemma classS x A B : A \\subset B -> x ^: A \\subset x ^: B.\n\n(*This lemma states that the set of conjugates of an element by the members of a singleton set is equivalent to the singleton set containing that one conjugated element.*)\nLemma class_set1 x y : x ^: [set y] = [set x ^ y].\n\n(*This lemma states that if a set is non-empty, the set of conjugates of the identity element by all members of that set is the singleton set containing the identity element.*)\nLemma class1g x A : x \\in A -> 1 ^: A = 1.\n\n(*This lemma states that forming the set of conjugates of an element's inverse is the same as forming the set of inverses of the conjugates of the original element.*)\nLemma classVg x A : x^-1 ^: A = (x ^: A)^-1.\n\n(*This lemma states that for any element in a given set, the conjugacy class of that element with respect to the set is a member of the set of all conjugacy classes.*)\nLemma mem_classes x A : x \\in A -> x ^: A \\in classes A.\n\n(*This lemma states that if a first element belongs to a first set and a second element belongs to a second set, then the conjugation of the first element by the second element is a member of the class support of the two sets.*)\nLemma memJ_class_support A B x y :\n x \\in A -> y \\in B -> x ^ y \\in class_support A B.\n\n(*This lemma establishes an associativity-like property for the class support operation, stating that the class support of a set with respect to a product of two other sets is equal to the class support of the class support of the first two sets with respect to the third.*)\nLemma class_supportM A B C :\n class_support A (B * C) = class_support (class_support A B) C.\n\n(*This lemma states that the class support of a singleton set and a second set is equal to the class of the single element with respect to the second set.*)\nLemma class_support_set1l A x : class_support [set x] A = x ^: A.\n\n(*This lemma states that the class support of a set and a singleton set is equal to the conjugate of the first set by the single element.*)\nLemma class_support_set1r A x : class_support A [set x] = A :^ x.\n\n(*This lemma states that the class of an element with respect to the product of two sets is equal to the class support of the class of that element with respect to the first set and the second set.*)\nLemma classM x A B : x ^: (A * B) = class_support (x ^: A) B.\n\n(*This lemma states that the class of an element with respect to a left coset is equal to the class of the conjugate of that element with respect to the set defining the coset.*)\nLemma class_lcoset x y A : x ^: (y *: A) = (x ^ y) ^: A.\n\n(*This lemma states that the class of an element with respect to a right coset is equal to the conjugation of that element's class by the element defining the coset.*)\nLemma class_rcoset x A y : x ^: (A :* y) = (x ^: A) :^ y.\n\n(*This lemma states that the operation of forming a set of conjugates is monotonic in its second argument with respect to the subset relation.*)\nLemma conjugatesS A B C : B \\subset C -> A :^: B \\subset A :^: C.\n\n(*This lemma states that the set of conjugates of a given set by the elements of a singleton set is equal to a singleton set containing the conjugate of the given set by the single element.*)\nLemma conjugates_set1 A x : A :^: [set x] = [set A :^ x].\n\n(*This lemma states that the set of conjugates of a conjugated set is equal to the set of conjugates of the original set by the corresponding left coset.*)\nLemma conjugates_conj A x B : (A :^ x) :^: B = A :^: (x *: B).\n\n(*This lemma defines the class support of two sets as the union of the classes of each element from the first set with respect to the second set.*)\nLemma class_supportEl A B : class_support A B = \\bigcup_(x in A) x ^: B.\n\n(*This lemma provides an alternative definition for the class support of two sets as the union of the conjugates of the first set by each element of the second set.*)\nLemma class_supportEr A B : class_support A B = \\bigcup_(x in B) A :^ x.\n\n(*This definition specifies the property of a set being a group set, which holds if the set contains the identity element and is closed under the multiplication operation.*)\nDefinition group_set A := (1 \\in A) && (A * A \\subset A).\n\n(*This lemma provides a reflection principle for the group set property, asserting that a set is a group set if and only if it contains the identity element and is closed under multiplication.*)\nLemma group_setP A :\n reflect (1 \\in A /\\ {in A & A, forall x y, x * y \\in A}) (group_set A).\n\n(*This definition introduces a structure for group types, bundling an underlying set with a proof that this set contains the identity element and is closed under the group operation.*)\nStructure group_type : Type := Group {\n(**)\n gval :> GroupSet.sort gT;\n _ : group_set gval\n}.\n\n(*This definition provides an alias for the group type, intended for use in contexts that expect a predicate argument type.*)\nDefinition group_of : predArgType := group_type.\n(*This notation serves as a local alias for the group type.*)\nLocal Notation groupT := group_of.\nIdentity Coercion type_of_group : group_of >-> group_type.\n\nHB.instance Definition _ := [isSub for gval].\n#[hnf] HB.instance Definition _ := [Finite of group_type by <:].\n\n(*This definition provides a constructor for creating a group type value from a given set and a proof that this set satisfies the group properties.*)\nDefinition group (A : {set gT}) gA : groupT := @Group A gA.\n\n(*This definition provides a mechanism to create a new group structure by applying a given constructor function to the proof component of an existing group, which is useful for creating canonical structures on types that are definitionally equal to the carrier of an existing group.*)\nDefinition clone_group G :=\n let: Group _ gP := G return {type of Group for G} -> groupT in fun k => k gP.\n\n(*This lemma states that the function which retrieves the underlying set from a group structure is injective, implying that two group structures are equal if their underlying sets are equal.*)\nLemma group_inj : injective gval. \n(*This lemma asserts that the underlying set of any value of group type satisfies the group set property, namely that it contains the identity element and is closed under multiplication.*)\nLemma groupP (G : groupT) : group_set G. \n\n(*This lemma establishes a congruence property for groups, stating that if two group structures are propositionally equal, then their underlying sets are also equal.*)\nLemma congr_group (H K : groupT) : H = K -> H :=: K.\n\n(*This lemma provides a reflection principle, asserting that a set satisfies the group set property if and only if there exists a formal group structure whose underlying set is that set.*)\nLemma isgroupP A : reflect (exists G : groupT, A = G) (group_set A).\n\n(*This lemma states that the singleton set containing only the identity element satisfies the properties of a group set.*)\nLemma group_set_one : group_set 1.\n\nCanonical one_group := group group_set_one.\nCanonical set1_group := @group [set 1] group_set_one.\n\n(*This lemma states that the set of all elements of the carrier type forms a group set.*)\nLemma group_setT : group_set (setTfor gT).\n\nCanonical setT_group := group group_setT.\n\nEnd GroupSetMulProp.\n\nArguments group_of gT%_type.\nArguments lcosetP {gT A x y}.\nArguments lcosetsP {gT A B C}.\nArguments rcosetP {gT A x y}.\nArguments rcosetsP {gT A B C}.\nArguments group_setP {gT A}.\nArguments setT_group gT%_type.\nPrenex Implicits group_set mulsgP set1gP.\n\n(*This notation provides a syntax for specifying the type of all group structures that can be defined on a given underlying carrier type.*)\nNotation \"{ 'group' gT }\" := (group_of gT)\n (format \"{ 'group' gT }\") : type_scope.\n\n(*This notation provides a syntax for constructing a group structure from a given set, returning a function that awaits a proof of the group properties to yield the final group type.*)\nNotation \"[ 'group' 'of' G ]\" := (clone_group (@group _ G))\n (format \"[ 'group' 'of' G ]\") : form_scope.\n\nBind Scope Group_scope with group_type.\nBind Scope Group_scope with group_of.\n(*This notation, within the group scope, represents the trivial group structure which consists of only the identity element.*)\nNotation \"1\" := (one_group _) : Group_scope.\n(*This notation represents the trivial group structure defined specifically on a given carrier type.*)\nNotation \"[ 1 gT ]\" := (1%G : {group gT}) : Group_scope.\n(*This notation provides a shorthand for the type of sets whose elements are drawn from a given finite group.*)\nNotation \"[ 'set' : gT ]\" := (setT_group gT) : Group_scope.\n\nHB.lock\n(*This definition specifies the subgroup generated by a given set of elements from a finite group as the smallest subgroup that contains all elements of the given set.*)\nDefinition generated (gT : finGroupType) (A : {set gT}) :=\n \\bigcap_(G : {group gT} | A \\subset G) G.\nCanonical generated_unlockable := Unlockable generated.unlock.\n\n(*This definition specifies the core of a first set of group elements with respect to a second set of group elements as the intersection of all conjugates of the first set by elements from the second set.*)\nDefinition gcore (gT : finGroupType) (A B : {set gT}) := \\bigcap_(x in B) A :^ x.\n(*This definition specifies the join of two sets of elements from a finite group as the subgroup generated by the union of these two sets.*)\nDefinition joing (gT : finGroupType) (A B : {set gT}) := generated (A :|: B).\n(*This definition specifies the commutator subgroup of two sets of elements from a finite group as the subgroup generated by the set of all commutators formed by taking one element from the first set and one from the second.*)\nDefinition commutator (gT : finGroupType) (A B : {set gT}) := generated (commg_set A B).\n(*This definition specifies the cyclic subgroup generated by a single element of a finite group as the smallest subgroup that contains that element.*)\nDefinition cycle (gT : finGroupType) (x : gT) := generated [set x].\n(*This definition specifies the order of an element in a finite group as the number of elements in the cyclic subgroup generated by that element.*)\nDefinition order (gT : finGroupType) (x : gT) := #|cycle x|.\n\nArguments commutator _ _%_g _%_g.\nArguments joing _ _%_g _%_g.\nArguments generated _ _%_g.\n\nNotation gsort gT := (BaseFinGroup.arg_sort gT%type) (only parsing).\n(*This notation represents the subgroup generated by a given set of elements from a finite group.*)\nNotation \"<< A >>\" := (generated A) : group_scope.\n(*This notation represents the cyclic subgroup generated by a single element of a finite group.*)\nNotation \"<[ x ] >\" := (cycle x) : group_scope.\n(*This notation represents the order of an element in a finite group.*)\nNotation \"#[ x ]\" := (order x) : group_scope.\n(*This notation represents the join of two sets of group elements, which is the subgroup generated by their union.*)\nNotation \"A <*> B\" := (joing A B) : group_scope.\n(*This notation represents a left-associated nested sequence of commutator subgroups, formed by repeatedly taking the commutator of the result with the next set in the sequence.*)\nNotation \"[ ~: A1 , A2 , .. , An ]\" :=\n (commutator .. (commutator A1 A2) .. An) : group_scope.\n\nPrenex Implicits order cycle gcore.\n\nSection GroupProp.\n\nVariable gT : finGroupType.\n(*This notation serves as a convenient shorthand for the type of sets whose elements are drawn from a given finite group.*)\nNotation sT := {set gT}.\nImplicit Types A B C D : sT.\nImplicit Types x y z : gT.\nImplicit Types G H K : {group gT}.\n\nSection OneGroup.\n\nVariable G : {group gT}.\n\n(*This lemma states that the underlying set of elements of a subgroup is identical to the set representing the subgroup itself.*)\nLemma valG : val G = G. \n\n(*This lemma states that the identity element of a finite group is an element of any of its subgroups.*)\nLemma group1 : 1 \\in G. \n#[local] Hint Resolve group1 : core.\n\n(*This lemma states that if an element is not a member of a given subgroup, then that element cannot be the identity element of the group.*)\nLemma group1_contra x : x \\notin G -> x != 1.\n\n(*This lemma states that the trivial subgroup, which consists solely of the identity element, is a subset of any subgroup of a finite group.*)\nLemma sub1G : [1 gT] \\subset G. \n(*This lemma states that a subgroup is a subset of the trivial subgroup if and only if that subgroup is itself the trivial subgroup.*)\nLemma subG1 : (G \\subset [1]) = (G :==: 1).\n\n(*This lemma states that the intersection of the trivial subgroup and any other subgroup results in the trivial subgroup.*)\nLemma setI1g : 1 :&: G = 1. \n(*This lemma states that the intersection of any subgroup with the trivial subgroup results in the trivial subgroup.*)\nLemma setIg1 : G :&: 1 = 1. \n\n(*This lemma states that if a non-trivial subgroup is a subset of another subgroup, then that other subgroup must also be non-trivial.*)\nLemma subG1_contra H : G \\subset H -> G :!=: 1 -> H :!=: 1.\n\n(*This lemma states that the canonical representative element of any subgroup is the identity element of the group.*)\nLemma repr_group : repr G = 1. \n\n(*This lemma states that the number of elements in any subgroup is strictly greater than zero.*)\nLemma cardG_gt0 : 0 < #|G|.\n\n(*This lemma states that the index of any subset within a subgroup is strictly greater than zero.*)\nLemma indexg_gt0 A : 0 < #|G : A|.\n\n(*This lemma provides a boolean reflection, stating that a subgroup is identical to the trivial subgroup if and only if it is a subset of the trivial subgroup.*)\nLemma trivgP : reflect (G :=: 1) (G \\subset [1]).\n\n(*This lemma provides a boolean reflection, stating that a subgroup is equal to the trivial subgroup if and only if it is a subset of the set containing only the identity element.*)\nLemma trivGP : reflect (G = 1%G) (G \\subset [1]).\n\n(*This lemma states that the trivial subgroup is a proper subset of another subgroup if and only if that other subgroup is not itself the trivial subgroup.*)\nLemma proper1G : ([1] \\proper G) = (G :!=: 1).\n\n(*This lemma states that an element belongs to the trivial subgroup if and only if that element is the identity element of the group.*)\nLemma in_one_group x : (x \\in 1%G) = (x == 1).\n\n(*This definition provides a rewriting rule for case analysis, stating that an element's membership in the trivial subgroup is equivalent to it being the identity element.*)\nDefinition inE := (in_one_group, inE).\n\n(*This lemma provides a boolean reflection, stating that a subgroup is non-trivial if and only if it contains at least one element that is not the identity element.*)\nLemma trivgPn : reflect (exists2 x, x \\in G & x != 1) (G :!=: 1).\n\n(*This lemma states that a subgroup is the trivial group if and only if its cardinality is less than or equal to one.*)\nLemma trivg_card_le1 : (G :==: 1) = (#|G| <= 1).\n\n(*This lemma states that a subgroup is the trivial group if and only if its cardinality is equal to one.*)\nLemma trivg_card1 : (G :==: 1) = (#|G| == 1%N).\n\n(*This lemma states that the cardinality of a subgroup is greater than one if and only if the subgroup is not the trivial group.*)\nLemma cardG_gt1 : (#|G| > 1) = (G :!=: 1).\n\n(*This lemma states that if the cardinality of a subgroup is less than or equal to one, then the subgroup is the trivial group.*)\nLemma card_le1_trivg : #|G| <= 1 -> G :=: 1.\n\n(*This lemma states that if the cardinality of a subgroup\u538b\u529b to one, then the subgroup is the trivial group.*)\nLemma card1_trivg : #|G| = 1%N -> G :=: 1.\n\n(*This lemma states that any set of group elements is a subset of the product of that set with a subgroup.*)\nLemma mulG_subl A : A \\subset A * G.\n\n(*This lemma states that any set of group elements is a subset of the product of a subgroup with that set.*)\nLemma mulG_subr A : A \\subset ((G : {set gT}) * A ).\n\n(*This lemma states that the product of a subgroup with itself is equal to the subgroup itself.*)\nLemma mulGid : (G : {set gT}) * G = G.\n\n(*This lemma states that the product of a subgroup and a first set being a subset of the product of the same subgroup and a second set is equivalent to the first set being a subset of the product of the subgroup and the second set.*)\nLemma mulGS A B : (G * A \\subset G * B) = (A \\subset G * B).\n\n(*This lemma states that the product of a first set and a subgroup being a subset of the product of a second set and the same subgroup is equivalent to the first set being a subset of the product of the second set and the subgroup.*)\nLemma mulSG A B : (A * G \\subset B * G) = (A \\subset B * G).\n\n(*This lemma states that if two sets of group elements are both subsets of a subgroup, then their set product is also a subset of that subgroup.*)\nLemma mul_subG A B : A \\subset G -> B \\subset G -> A * B \\subset G.\n\n(*This lemma states that if every set in a family of sets, indexed over a sequence and filtered by a predicate, is a subset of a given subgroup, then the iterated product of these sets is also a subset of that subgroup.*)\nLemma prod_subG (I : Type) (r : seq I) (P : {pred I}) (F : I -> {set gT}) :\n (forall i, P i -> F i \\subset G) -> \\prod_(i <- r | P i) F i \\subset G.\n\n(*This lemma states that if two elements are members of a subgroup, their product is also a member of that subgroup.*)\nLemma groupM x y : x \\in G -> y \\in G -> x * y \\in G.\n\n(*This lemma states that if an element is a member of a subgroup, then any of its positive integer powers is also a member of that subgroup.*)\nLemma groupX x n : x \\in G -> x ^+ n \\in G.\n\n(*This lemma states that if an element is a member of a subgroup, its inverse is also a member of that subgroup.*)\nLemma groupVr x : x \\in G -> x^-1 \\in G.\n\n(*This lemma states that if the inverse of an element is a member of a subgroup, then the element itself is also a member of that subgroup.*)\nLemma groupVl x : x^-1 \\in G -> x \\in G.\n\n(*This lemma states that an element is a member of a subgroup if and only if its inverse is a member of that subgroup.*)\nLemma groupV x : (x^-1 \\in G) = (x \\in G).\n\n(*This lemma states that for any element belonging to a subgroup, the product of this element with a second element is in the subgroup if and only if the second element is also in the subgroup.*)\nLemma groupMl x y : x \\in G -> (x * y \\in G) = (y \\in G).\n\n(*This lemma states that for any element belonging to a subgroup, the product of a second element with this first element is in the subgroup if and only if the second element is also in the subgroup.*)\nLemma groupMr x y : x \\in G -> (y * x \\in G) = (y \\in G).\n\n(*This definition bundles together the proofs that a set of group elements contains the identity, is closed under inverses, is closed under left multiplication by its members, and is closed under positive integer powers, collectively demonstrating that it forms a subgroup.*)\nDefinition in_group := (group1, groupV, (groupMl, groupX)).\n\n(*This lemma states that if two elements are members of a subgroup, then the conjugation of the first element by the second is also a member of that subgroup.*)\nLemma groupJ x y : x \\in G -> y \\in G -> x ^ y \\in G.\n\n(*This lemma states that for any element belonging to a subgroup, the conjugation of a second element by this first element is in the subgroup if and only if the second element is also in the subgroup.*)\nLemma groupJr x y : y \\in G -> (x ^ y \\in G) = (x \\in G).\n\n(*This lemma states that if two elements are members of a subgroup, then their commutator is also a member of that subgroup.*)\nLemma groupR x y : x \\in G -> y \\in G -> [~ x, y] \\in G.\n\n(*This lemma states that if every element in a family of elements, indexed over a sequence and filtered by a predicate, is a member of a given subgroup, then the iterated product of these elements is also a member of that subgroup.*)\nLemma group_prod I r (P : pred I) F :\n (forall i, P i -> F i \\in G) -> \\prod_(i <- r | P i) F i \\in G.\n\n(*This lemma states that the set of inverses of the elements of a subgroup is equal to the subgroup itself.*)\nLemma invGid : G^-1 = G. \n\n(*This lemma states that the set of inverses of elements from a given set is a subset of a subgroup if and only if the given set is itself a subset of that subgroup.*)\nLemma inv_subG A : (A^-1 \\subset G) = (A \\subset G).\n\n(*This lemma states that the set of inverses of elements in a left coset of a subgroup is equal to the right coset of the same subgroup formed with the inverse of the original coset's representative.*)\nLemma invg_lcoset x : (x *: G)^-1 = G :* x^-1.\n\n(*This lemma states that the set of inverses of elements in a right coset of a subgroup is equal to the left coset of the same subgroup formed with the inverse of the original coset's representative.*)\nLemma invg_rcoset x : (G :* x)^-1 = x^-1 *: G.\n\n(*This lemma states that the inverse of a first element belongs to the left coset generated by the inverse of a second element if and only if the first element belongs to the right coset generated by the second element.*)\nLemma memV_lcosetV x y : (y^-1 \\in x^-1 *: G) = (y \\in G :* x).\n\n(*This lemma states that the inverse of a first element belongs to the right coset generated by the inverse of a second element if and only if the first element belongs to the left coset generated by the second element.*)\nLemma memV_rcosetV x y : (y^-1 \\in G :* x^-1) = (y \\in x *: G).\n\n(*This lemma states that the product of a non-empty subset of a group with the group itself is equal to the group.*)\nLemma mulSgGid A x : x \\in A -> A \\subset G -> A * G = G.\n\n(*This lemma states that the product of a group with a non-empty subset of that group is equal to the group itself.*)\nLemma mulGSgid A x : x \\in A -> A \\subset G -> G * A = G.\n\n(*This lemma states that any element is a member of its own left coset.*)\nLemma lcoset_refl x : x \\in x *: G.\n\n(*This lemma states that the membership of a first element in the left coset of a second element is equivalent to the membership of the second element in the left coset of the first.*)\nLemma lcoset_sym x y : (x \\in y *: G) = (y \\in x *: G).\n\n(*This lemma states that two left cosets are equal if and only if the representative of the first coset is an element of the second coset.*)\nLemma lcoset_eqP {x y} : reflect (x *: G = y *: G) (x \\in y *: G).\n\n(*This lemma states that if a first element is in the left coset of a second element, then the membership of the first element in a third element's left coset is equivalent to the membership of the second element in that same third element's left coset.*)\nLemma lcoset_transl x y z : x \\in y *: G -> (x \\in z *: G) = (y \\in z *: G).\n\n(*This lemma states that the left coset membership relation is transitive: if a first element is in the left coset of a second, and the second is in the left coset of a third, then the first is in the left coset of the third.*)\nLemma lcoset_trans x y z : x \\in y *: G -> y \\in z *: G -> x \\in z *: G.\n\n(*This lemma states that the left coset of a subgroup with respect to one of its own elements is equal to the subgroup itself.*)\nLemma lcoset_id x : x \\in G -> x *: G = G.\n\n(*This lemma states that any element is a member of its own right coset.*)\nLemma rcoset_refl x : x \\in G :* x.\n\n(*This lemma states that the membership of a first element in the right coset of a second element is equivalent to the membership of the second element in the right coset of the first.*)\nLemma rcoset_sym x y : (x \\in G :* y) = (y \\in G :* x).\n\n(*This lemma states that two right cosets are equal if and only if the representative of one coset is an element of the other.*)\nLemma rcoset_eqP {x y} : reflect (G :* x = G :* y) (x \\in G :* y).\n\n(*This lemma states that if a first element is in the right coset of a second element, then the membership of the first element in a third element's right coset is equivalent to the membership of the second element in that same third element's right coset.*)\nLemma rcoset_transl x y z : x \\in G :* y -> (x \\in G :* z) = (y \\in G :* z).\n\n(*This lemma states that the right coset membership relation is transitive: if a first element is in the right coset of a second, and the second is in the right coset of a third, then the first is in the right coset of the third.*)\nLemma rcoset_trans x y z : x \\in G :* y -> y \\in G :* z -> x \\in G :* z.\n\n(*This lemma states that the right coset of a subgroup with respect to one of its own elements is equal to the subgroup itself.*)\nLemma rcoset_id x : x \\in G -> G :* x = G.\n\n(*This inductive type defines a specification for an element to be a member of the right coset defined by another element. A value of this type serves as a proof that the second element is in the right coset of the first.*)\nVariant rcoset_repr_spec x : gT -> Type :=\n RcosetReprSpec g : g \\in G -> rcoset_repr_spec x (g * x).\n\n(*This lemma states that the canonical representative chosen for a right coset is guaranteed to be a member of that coset.*)\nLemma mem_repr_rcoset x : repr (G :* x) \\in G :* x.\n\n(*This lemma states that the canonical representative of a right coset satisfies the constructive specification of belonging to that coset.*)\nLemma repr_rcosetP x : rcoset_repr_spec x (repr (G :* x)).\n\n(*This lemma states that the right coset generated by the canonical representative of another right coset is identical to the original coset.*)\nLemma rcoset_repr x : G :* (repr (G :* x)) = G :* x.\n\n(*This lemma states that a right coset belongs to the set of right cosets formed from representatives in a given set if and only if its own representative belongs to the product of the subgroup and the given set.*)\nLemma mem_rcosets A x : (G :* x \\in rcosets G A) = (x \\in G * A).\n\n(*This lemma states that a left coset belongs to the set of left cosets formed from representatives in a given set if and only if its own representative belongs to the product of the given set and the subgroup.*)\nLemma mem_lcosets A x : (x *: G \\in lcosets G A) = (x \\in A * G).\n\n(*This lemma states that a set forms a subgroup if and only if its conjugate by any element also forms a subgroup.*)\nLemma group_setJ A x : group_set (A :^ x) = group_set A.\n\n(*This lemma states that the conjugate of a subgroup by any element is also a subgroup.*)\nLemma group_set_conjG x : group_set (G :^ x).\n\nCanonical conjG_group x := group (group_set_conjG x).\n\n(*This lemma states that every element of a group normalizes the group itself.*)\nLemma conjGid : {in G, normalised G}.\n\n(*This lemma states that if a subset of a group is conjugated by an element from that same group, the resulting set is also a subset of the group.*)\nLemma conj_subG x A : x \\in G -> A \\subset G -> A :^ x \\subset G.\n\n(*This lemma states that the conjugacy class of the identity element contains only the identity element itself.*)\nLemma class1G : 1 ^: G = 1. \n\n(*This lemma states that the singleton set containing the identity element is a member of the set of all conjugacy classes of the group.*)\nLemma classes1 : [1] \\in classes G. \n\n(*This lemma states that the conjugacy class of an element that has been conjugated by a group element is identical to the conjugacy class of the original element.*)\nLemma classGidl x y : y \\in G -> (x ^ y) ^: G = x ^: G.\n\n(*This lemma states that every element of a group normalizes the conjugacy class of any given element within that group.*)\nLemma classGidr x : {in G, normalised (x ^: G)}.\n\n(*This lemma states that any element is a member of its own conjugacy class.*)\nLemma class_refl x : x \\in x ^: G.\n\n#[local] Hint Resolve class_refl : core.\n\n(*This lemma states that two conjugacy classes are equal if and only if the representative of the first class is an element of the second class.*)\nLemma class_eqP x y : reflect (x ^: G = y ^: G) (x \\in y ^: G).\n\n(*This lemma states that the conjugacy class relation is symmetric; an element belongs to the conjugacy class of a second element if and only if the second element belongs to the conjugacy class of the first.*)\nLemma class_sym x y : (x \\in y ^: G) = (y \\in x ^: G).\n\n(*This lemma states that if a first element is in the conjugacy class of a second element, then the first element belongs to the conjugacy class of a third element if and only if the second element also belongs to the conjugacy class of that third element.*)\nLemma class_transl x y z : x \\in y ^: G -> (x \\in z ^: G) = (y \\in z ^: G).\n\n(*This lemma states that the conjugacy class relation is transitive; if a first element is in the conjugacy class of a second, and the second is in the conjugacy class of a third, then the first is in the conjugacy class of the third.*)\nLemma class_trans x y z : x \\in y ^: G -> y \\in z ^: G -> x \\in z ^: G.\n\n(*This lemma asserts that for any group element, the canonical representative of its conjugacy class can be expressed as the original element conjugated by some element of the group.*)\nLemma repr_class x : {y | y \\in G & repr (x ^: G) = x ^ y}.\n\n(*This lemma states that the conjugacy class of an element is the singleton set containing the group identity if and only if the element itself is the group identity.*)\nLemma classG_eq1 x : (x ^: G == 1) = (x == 1).\n\n(*This lemma states that if an element is in a group and a set is a subset of that group, then the set formed by conjugating the element by every member of the set is also a subset of the group.*)\nLemma class_subG x A : x \\in G -> A \\subset G -> x ^: A \\subset G.\n\n(*This lemma provides a reflection property, stating that a given set is a conjugacy class of a group if and only if the canonical representative of the set is an element of the group and the set itself is equal to the conjugacy class of that representative.*)\nLemma repr_classesP xG :\n reflect (repr xG \\in G /\\ xG = repr xG ^: G) (xG \\in classes G).\n\n(*This lemma states that if a set is a conjugacy class of a group, then the canonical representative of that set is an element of the set.*)\nLemma mem_repr_classes xG : xG \\in classes G -> repr xG \\in xG.\n\n(*This lemma states that the number of conjugacy classes in any group is strictly positive.*)\nLemma classes_gt0 : 0 < #|classes G|.\n\n(*This lemma states that the number of conjugacy classes in a group is greater than one if and only if the group is not the trivial group containing only the identity element.*)\nLemma classes_gt1 : (#|classes G| > 1) = (G :!=: 1).\n\n(*This lemma states that any element belonging to a given set also belongs to the class support of that set within a group.*)\nLemma mem_class_support A x : x \\in A -> x \\in class_support A G.\n\n(*This lemma states that conjugating a set by an element of a group does not change its class support within that group.*)\nLemma class_supportGidl A x :\n x \\in G -> class_support (A :^ x) G = class_support A G.\n\n(*This lemma states that the class support of any set within a group is a normal subset of that group.*)\nLemma class_supportGidr A : {in G, normalised (class_support A G)}.\n\n(*This lemma states that if a set is a subset of a group, then its class support is also a subset of that group.*)\nLemma class_support_subG A : A \\subset G -> class_support A G \\subset G.\n\n(*This lemma states that any set is a subset of its class support within a group.*)\nLemma sub_class_support A : A \\subset class_support A G.\n\n(*This lemma states that the class support of a group within itself is the group itself.*)\nLemma class_support_id : class_support G G = G.\n\n(*This lemma states that the subgroup generated by the class support of a given set is equal to the normal closure of the subgroup generated by that set.*)\nLemma class_supportD1 A : (class_support A G)^# = cover (A^# :^: G).\n\n(*A boolean predicate that determines whether a first given subgroup is contained within a second given subgroup. It returns true if every element of the first subgroup is also an element of the second, and false otherwise.*)\nInductive subg_of : predArgType := Subg x & x \\in G.\n(*This definition specifies a function that retrieves the underlying group element from a structure that pairs the element with a proof of its membership in the group.*)\nDefinition sgval u := let: Subg x _ := u in x.\n(*This definition establishes a subtype relationship for the type of elements packaged with a proof of group membership, where the function that extracts the element is designated as the coercion to the parent group type.*)\nDefinition subg_of_Sub := Eval hnf in [isSub for sgval].\nHB.instance Definition _ := subg_of_Sub.\n#[hnf] HB.instance Definition _ := [Finite of subg_of by <:].\n\n(*This lemma states that the element extracted from a structure representing a group element with its membership proof is indeed a member of the group.*)\nLemma subgP u : sgval u \\in G.\n\n(*This lemma states that the function for extracting the underlying group element from its structured representation is injective.*)\nLemma subg_inj : injective sgval.\n\n(*This lemma states that if two structured representations of group elements are equal, then their underlying group elements are also equal.*)\nLemma congr_subg u v : u = v -> sgval u = sgval v.\n\n(*This definition provides the identity element for the subtype of group elements, constructed by packaging the group's identity element with its membership proof.*)\nDefinition subg_one := Subg group1.\n(*This definition provides the inversion operation for the subtype of group elements, which computes the inverse of the underlying element and packages it with a proof of membership.*)\nDefinition subg_inv u := Subg (groupVr (subgP u)).\n(*This definition provides the multiplication operation for the subtype of group elements, which multiplies the underlying elements of two inputs and packages the result with a proof of membership.*)\nDefinition subg_mul u v := Subg (groupM (subgP u) (subgP v)).\n(*This lemma states that the defined identity element for the group subtype acts as a left identity for the subtype's multiplication operation.*)\nLemma subg_oneP : left_id subg_one subg_mul.\n\n(*This lemma states that the defined inversion operation for the group subtype provides a left inverse with respect to the subtype's multiplication and identity element.*)\nLemma subg_invP : left_inverse subg_one subg_inv subg_mul.\n\n(*This lemma states that the defined multiplication operation on the group subtype is associative.*)\nLemma subg_mulP : associative subg_mul.\n\n(*This lemma establishes that the function extracting an element from the structure that pairs it with a membership proof is a group homomorphism from the group structure on the subtype to the original group.*)\nLemma sgvalM : {in setT &, {morph sgval : x y / x * y}}. \n(*This lemma establishes that the canonical coercion from the group subtype to the parent group's carrier type is an injective group homomorphism.*)\nLemma valgM : {in setT &, {morph val : x y / (x : subg_of) * y >-> x * y}}.\n\n(*This definition defines a function that maps an element from an ambient group to an element of a given subgroup. If the input element is a member of the subgroup, the function returns that element; otherwise, it returns the identity element of the subgroup.*)\nDefinition subg : gT -> subg_of := insubd (1 : subg_of).\n(*This lemma states that for any element that is a member of a given subgroup, applying the `subg` function and then coercing the result back to the ambient group's type yields the original element.*)\nLemma subgK x : x \\in G -> val (subg x) = x.\n\n(*This lemma states that the function `subg`, which maps an element of the ambient group to a subgroup, acts as a left inverse to the coercion from the subgroup to the ambient group. Specifically, taking an element of the subgroup, coercing it to the ambient group, and then applying `subg` returns the original subgroup element.*)\nLemma sgvalK : cancel sgval subg.\n\n(*This lemma states that if an element from an ambient group is not a member of a given subgroup, then applying the `subg` function and extracting its value yields the identity element of the group.*)\nLemma subg_default x : (x \\in G) = false -> val (subg x) = 1.\n\n(*This lemma asserts that the `subg` function is a group homomorphism when restricted to elements of the given subgroup. That is, for any two elements within the subgroup, applying `subg` to their product is equivalent to multiplying the results of applying `subg` to each element individually.*)\nLemma subgM : {in G &, {morph subg : x y / x * y}}.\n\nEnd OneGroup.\n\n#[local] Hint Resolve group1 : core.\n\n(*This lemma states that if two subgroups have the same underlying set of elements, then they are canonically equal as group structures.*)\nLemma groupD1_inj G H : G^# = H^# -> G :=: H.\n\n(*This lemma states that for any two subgroups, the set of inverses of all elements in their set product is equal to the set product of the subgroups in the reverse order.*)\nLemma invMG G H : (G * H)^-1 = H * G.\n\n(*This lemma states that if a subgroup `H` is contained within a subgroup `G`, then the set product of `H` and `G` is equal to the set representing `G`.*)\nLemma mulSGid G H : H \\subset G -> H * G = G.\n\n(*This lemma states that if a subgroup `H` is contained within a subgroup `G`, then the set product of `G` and `H` is equal to the set representing `G`.*)\nLemma mulGSid G H : H \\subset G -> G * H = G.\n\n(*This lemma provides a reflection, stating that the set product of a subgroup `G` with a subgroup `H` is equal to `G` if and only if `H` is a subgroup of `G`.*)\nLemma mulGidPl G H : reflect (G * H = G) (H \\subset G).\n\n(*This lemma provides a reflection, stating that the set product of a subgroup `G` with a subgroup `H` is equal to `H` if and only if `G` is a subgroup of `H`.*)\nLemma mulGidPr G H : reflect (G * H = H) (G \\subset H).\n\n(*This lemma provides a reflection, asserting that two subgroups commute, meaning their set products are equal regardless of order, if and only if their set product itself forms a subgroup.*)\nLemma comm_group_setP G H : reflect (commute G H) (group_set (G * H)).\n\n(*This lemma states that the cardinality of the set of left cosets of a subgroup `H` within a group `G` is equal to the index of `H` in `G`.*)\nLemma card_lcosets G H : #|lcosets H G| = #|G : H|.\n\n(*This lemma states a modular property for subgroup products and intersections. For three subgroups `A`, `B`, and `G`, if `A` is a subgroup of `G`, then the set product of `A` with the intersection of `B` and `G` is equal to the intersection of the set product `A` times `B` with `G`.*)\nLemma group_modl A B G : A \\subset G -> A * (B :&: G) = A * B :&: G.\n\n(*This lemma states a right-sided modular property for subgroup products and intersections. For three subgroups `A`, `B`, and `G`, if `B` is a subgroup of `G`, then the set product of the intersection of `G` and `A` with `B` is equal to the intersection of `G` with the set product `A` times `B`.*)\nLemma group_modr A B G : B \\subset G -> (G :&: A) * B = G :&: A * B.\n\nEnd GroupProp.\n\n#[global] Hint Extern 0 (is_true (1%g \\in _)) => apply: group1 : core.\n#[global] Hint Extern 0 (is_true (0 < #|_|)) => apply: cardG_gt0 : core.\n#[global] Hint Extern 0 (is_true (0 < #|_ : _|)) => apply: indexg_gt0 : core.\n\n(*This notation defines the conjugation of a subgroup by a group element, resulting in a new subgroup. The elements of the new subgroup are obtained by taking each element of the original subgroup, multiplying it on the left by the given group element, and on the right by the inverse of that element.*)\nNotation \"G :^ x\" := (conjG_group G x) : Group_scope.\n\n(*This notation provides a way to refer to a subgroup `G`. In a type context, it denotes the type whose values are elements of the ambient group bundled with a proof of their membership in `G`. In a group context, it denotes the set of all such bundled values.*)\nNotation \"[ 'subg' G ]\" := (subg_of G) : type_scope.\n(*This notation represents the type whose elements are all the subgroups of a given group.*)\nNotation \"[ 'subg' G ]\" := [set: subg_of G] : group_scope.\n(*This represents the coercion of a group into its underlying set of elements.*)\nNotation \"[ 'subg' G ]\" := [set: subg_of G]%G : Group_scope.\n\nPrenex Implicits subg sgval subg_of.\nBind Scope group_scope with subg_of.\nArguments subgK {gT G}.\nArguments sgvalK {gT G}.\nArguments subg_inj {gT G} [u1 u2] eq_u12 : rename.\n\nArguments trivgP {gT G}.\nArguments trivGP {gT G}.\nArguments lcoset_eqP {gT G x y}.\nArguments rcoset_eqP {gT G x y}.\nArguments mulGidPl {gT G H}.\nArguments mulGidPr {gT G H}.\nArguments comm_group_setP {gT G H}.\nArguments class_eqP {gT G x y}.\nArguments repr_classesP {gT G xG}.\n\nSection GroupInter.\n\nVariable gT : finGroupType.\nImplicit Types A B : {set gT}.\nImplicit Types G H : {group gT}.\n\n(*This lemma states that the intersection of the carrier sets of two groups itself constitutes a group.*)\nLemma group_setI G H : group_set (G :&: H).\n\nCanonical setI_group G H := group (group_setI G H).\n\nSection Nary.\n\nVariables (I : finType) (P : pred I) (F : I -> {group gT}).\n\n(*This lemma states that the intersection of the carrier sets of an indexed family of groups itself constitutes a group.*)\nLemma group_set_bigcap : group_set (\\bigcap_(i | P i) F i).\n\nCanonical bigcap_group := group group_set_bigcap.\n\nEnd Nary.\n\n(*This lemma states that the structure generated by a given subset of a group's elements is itself a group.*)\nLemma group_set_generated (A : {set gT}) : group_set <>.\n\nCanonical generated_group A := group (group_set_generated A).\nCanonical gcore_group G A : {group _} := Eval hnf in [group of gcore G A].\nCanonical commutator_group A B : {group _} := Eval hnf in [group of [~: A, B]].\nCanonical joing_group A B : {group _} := Eval hnf in [group of A <*> B].\nCanonical cycle_group x : {group _} := Eval hnf in [group of <[x]>].\n\n(*This definition provides an alias for the join of two groups, defined as the smallest subgroup containing both.*)\nDefinition joinG G H := joing_group G H.\n\n(*This definition specifies the set of all subgroups of a given group.*)\nDefinition subgroups A := [set G : {group gT} | G \\subset A].\n\n(*This lemma states that the order of any element in a finite group is a natural number strictly greater than zero.*)\nLemma order_gt0 (x : gT) : 0 < #[x].\n\nEnd GroupInter.\n\n#[global] Hint Resolve order_gt0 : core.\n\nArguments generated_group _ _%_g.\nArguments joing_group _ _%_g _%_g.\nArguments subgroups _ _%_g.\n\n(*This notation represents the group formed by the intersection of two groups G and H.*)\nNotation \"G :&: H\" := (setI_group G H) : Group_scope.\n(*This notation represents the subgroup generated by a given set of elements.*)\nNotation \"<< A >>\" := (generated_group A) : Group_scope.\n(*This notation represents the cyclic subgroup generated by a single element.*)\nNotation \"<[ x ] >\" := (cycle_group x) : Group_scope.\n(*This notation denotes the iterated commutator subgroup, formed by repeatedly taking the commutator of the previous result with the next group in the sequence.*)\nNotation \"[ ~: A1 , A2 , .. , An ]\" :=\n (commutator_group .. (commutator_group A1 A2) .. An) : Group_scope.\n(*This notation represents the join of two subgroups, which is the smallest subgroup that contains both of them.*)\nNotation \"A <*> B\" := (joing_group A B) : Group_scope.\n(*This notation represents the join of two subgroups, defined as the smallest subgroup containing both.*)\nNotation \"G * H\" := (joinG G H) : Group_scope.\nPrenex Implicits joinG subgroups.\n\n(*This notation represents the iterated join of a family of subgroups, indexed by elements from a given sequence that satisfy a specific predicate.*)\nNotation \"\\prod_ ( i <- r | P ) F\" :=\n (\\big[joinG/1%G]_(i <- r | P%B) F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by all elements from a given sequence.*)\nNotation \"\\prod_ ( i <- r ) F\" :=\n (\\big[joinG/1%G]_(i <- r) F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by natural numbers within a specific range that satisfy a given predicate.*)\nNotation \"\\prod_ ( m <= i < n | P ) F\" :=\n (\\big[joinG/1%G]_(m <= i < n | P%B) F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by all natural numbers within a specific range.*)\nNotation \"\\prod_ ( m <= i < n ) F\" :=\n (\\big[joinG/1%G]_(m <= i < n) F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed over a finite type, including only those indices that satisfy a given predicate.*)\nNotation \"\\prod_ ( i | P ) F\" :=\n (\\big[joinG/1%G]_(i | P%B) F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed over all elements of a finite type.*)\nNotation \"\\prod_ i F\" :=\n (\\big[joinG/1%G]_i F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by elements of a specified finite type that satisfy a given predicate.*)\nNotation \"\\prod_ ( i : t | P ) F\" :=\n (\\big[joinG/1%G]_(i : t | P%B) F%G) (only parsing) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by all elements of a specified finite type.*)\nNotation \"\\prod_ ( i : t ) F\" :=\n (\\big[joinG/1%G]_(i : t) F%G) (only parsing) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by natural numbers less than a given bound that satisfy a specific predicate.*)\nNotation \"\\prod_ ( i < n | P ) F\" :=\n (\\big[joinG/1%G]_(i < n | P%B) F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by all natural numbers less than a given bound.*)\nNotation \"\\prod_ ( i < n ) F\" :=\n (\\big[joinG/1%G]_(i < n) F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by elements from a given finite set that satisfy a specific predicate.*)\nNotation \"\\prod_ ( i 'in' A | P ) F\" :=\n (\\big[joinG/1%G]_(i in A | P%B) F%G) : Group_scope.\n(*This notation represents the iterated join of a family of subgroups, indexed by all elements from a given finite set.*)\nNotation \"\\prod_ ( i 'in' A ) F\" :=\n (\\big[joinG/1%G]_(i in A) F%G) : Group_scope.\n\nSection Lagrange.\n\nVariable gT : finGroupType.\nImplicit Types G H K : {group gT}.\n\n(*This lemma states that for any two finite groups G and H, the order of group G is equal to the product of the order of their intersection and the index of this intersection subgroup within G.*)\nLemma LagrangeI G H : (#|G :&: H| * #|G : H|)%N = #|G|.\n\n(*This lemma states that for any two finite groups G and H, the index of their intersection subgroup within G is equal to the order of G divided by the order of their intersection.*)\nLemma divgI G H : #|G| %/ #|G :&: H| = #|G : H|.\n\n(*This lemma states that for any two finite groups G and H, the order of their intersection is equal to the order of G divided by the index of the intersection subgroup within G.*)\nLemma divg_index G H : #|G| %/ #|G : H| = #|G :&: H|.\n\n(*This lemma states that for any two finite groups G and H, the index of their intersection subgroup within G divides the order of G.*)\nLemma dvdn_indexg G H : #|G : H| %| #|G|.\n\n(*This theorem states that if a group H is a subgroup of a finite group G, then the order of G is equal to the product of the order of H and the index of H in G.*)\nTheorem Lagrange G H : H \\subset G -> (#|H| * #|G : H|)%N = #|G|.\n\n(*This lemma states that if a finite group is a subgroup of another finite group, then the order of the subgroup divides the order of the larger group.*)\nLemma cardSg G H : H \\subset G -> #|H| %| #|G|.\n\n(*This lemma states that if a group is a subgroup of another group, then for any prime number, the exponent of that prime in the prime factorization of the subgroup's order is less than or equal to the exponent of the same prime in the prime factorization of the larger group's order.*)\nLemma lognSg p G H : G \\subset H -> logn p #|G| <= logn p #|H|.\n\n(*This lemma states that if a group is a subgroup of another group, then the set of prime numbers that divide the order of at least one element in the subgroup is a subset of the corresponding set of primes for the larger group.*)\nLemma piSg G H : G \\subset H -> {subset \\pi(gval G) <= \\pi(gval H)}.\n\n(*This lemma states that for a subgroup of a finite group, the index of the subgroup is equal to the order of the group divided by the order of the subgroup.*)\nLemma divgS G H : H \\subset G -> #|G| %/ #|H| = #|G : H|.\n\n(*This lemma states that for a subgroup of a finite group, the order of the subgroup is equal to the order of the group divided by the index of the subgroup.*)\nLemma divg_indexS G H : H \\subset G -> #|G| %/ #|G : H| = #|H|.\n\n(*This lemma states that if a group is a subgroup of another group, and the order of the larger group is coprime to a given natural number, then the order of the subgroup is also coprime to that number.*)\nLemma coprimeSg G H p : H \\subset G -> coprime #|G| p -> coprime #|H| p.\n\n(*This lemma states that if a group is a subgroup of another group, and a given natural number is coprime to the order of the larger group, then that number is also coprime to the order of the subgroup.*)\nLemma coprimegS G H p : H \\subset G -> coprime p #|G| -> coprime p #|H|.\n\n(*This lemma states that the index of a subgroup within a group is equal to the index of the conjugated subgroup within the conjugated group, for any conjugating element.*)\nLemma indexJg G H x : #|G :^ x : H :^ x| = #|G : H|.\n\n(*This lemma states that the index of any group in itself is equal to one.*)\nLemma indexgg G : #|G : G| = 1%N.\n\n(*This lemma states that the set of right cosets of a group in itself is a singleton set containing only the set of elements of the group itself.*)\nLemma rcosets_id G : rcosets G G = [set G : {set gT}].\n\n(*This lemma states that for a chain of subgroups, where a first group is a subgroup of a second, and the second is a subgroup of a third, the index of the second group in the third, multiplied by the index of the first group in the second, equals the index of the first group in the third.*)\nLemma Lagrange_index G H K :\n H \\subset G -> K \\subset H -> (#|G : H| * #|H : K|)%N = #|G : K|.\n\n(*This lemma states that the index of the intersection of two groups within the first group is equal to the index of the second group in the first group.*)\nLemma indexgI G H : #|G : G :&: H| = #|G : H|.\n\n(*This lemma states that if a first group is a subgroup of a second group, then the index of the second group in a third group divides the index of the first group in that same third group.*)\nLemma indexgS G H K : H \\subset K -> #|G : K| %| #|G : H|.\n\n(*This lemma states that for a chain of subgroups, where a first group is a subgroup of a second and the second is a subgroup of a third, the index of the first group in the second divides the index of the first group in the third.*)\nLemma indexSg G H K : H \\subset K -> K \\subset G -> #|K : H| %| #|G : H|.\n\n(*This lemma states that the boolean indicating whether the index of a second group in a first group is equal to one is the same as the boolean indicating whether the first group is a subgroup of the second group.*)\nLemma indexg_eq1 G H : (#|G : H| == 1%N) = (G \\subset H).\n\n(*This lemma states that the boolean indicating whether the index of a second group in a first group is greater than one is the same as the boolean indicating that the first group is not a subgroup of the second group.*)\nLemma indexg_gt1 G H : (#|G : H| > 1) = ~~ (G \\subset H).\n\n(*This lemma states that if a group is a subgroup of another group and its index is one, then the two groups are equal.*)\nLemma index1g G H : H \\subset G -> #|G : H| = 1%N -> H :=: G.\n\n(*This lemma states that the index of the trivial group in any given group is equal to the order of that group.*)\nLemma indexg1 G : #|G : 1| = #|G|.\n\n(*This lemma states that the index of a first group in the product of that group with a second group is equal to the index of the first group in the second group.*)\nLemma indexMg G A : #|G * A : G| = #|A : G|.\n\n(*This lemma states that the set of right cosets of a first group, with representatives from a second group, forms a partition of the product of the two groups.*)\nLemma rcosets_partition_mul G H : partition (rcosets H G) (H * G).\n\n(*This lemma states that for a subgroup of a group, the set of right cosets of the subgroup forms a partition of the larger group.*)\nLemma rcosets_partition G H : H \\subset G -> partition (rcosets H G) G.\n\n(*This lemma states that the order of a first group, multiplied by the index of that group in a second group, is equal to the order of the product of the two groups.*)\nLemma LagrangeMl G H : (#|G| * #|H : G|)%N = #|G * H|.\n\n(*This lemma states that the index of a second group in a first group, multiplied by the order of the second group, is equal to the order of the product of the two groups.*)\nLemma LagrangeMr G H : (#|G : H| * #|H|)%N = #|G * H|.\n\n(*This lemma states that the product of the orders of two groups is equal to the product of the order of their group product and the order of their intersection.*)\nLemma mul_cardG G H : (#|G| * #|H| = #|G * H|%g * #|G :&: H|)%N.\n\n(*This lemma states that the order of the product of two groups divides the product of their individual orders.*)\nLemma dvdn_cardMg G H : #|G * H| %| #|G| * #|H|.\n\n(*This lemma states that the order of the product of two groups is equal to the product of their individual orders divided by the order of their intersection.*)\nLemma cardMg_divn G H : #|G * H| = (#|G| * #|H|) %/ #|G :&: H|.\n\n(*This lemma states that the order of the intersection of two groups is equal to the product of their individual orders divided by the order of their product.*)\nLemma cardIg_divn G H : #|G :&: H| = (#|G| * #|H|) %/ #|G * H|.\n\n(*This lemma states that if the intersection of two groups is the trivial group, then the order of their product is equal to the product of their individual orders.*)\nLemma TI_cardMg G H : G :&: H = 1 -> #|G * H| = (#|G| * #|H|)%N.\n\n(*This lemma states that if the product of the orders of two groups is less than or equal to the order of their product, then the intersection of the two groups must be the trivial group.*)\nLemma cardMg_TI G H : #|G| * #|H| <= #|G * H| -> G :&: H = 1.\n\n(*This lemma states that if the orders of two groups are coprime natural numbers, then their intersection is the trivial group.*)\nLemma coprime_TIg G H : coprime #|G| #|H| -> G :&: H = 1.\n\n(*This lemma states that if a group has a prime order and is not a subgroup of a second group, then the intersection of the two groups is the trivial group.*)\nLemma prime_TIg G H : prime #|G| -> ~~ (G \\subset H) -> G :&: H = 1.\n\n(*This lemma states that if a group has a prime order and its intersection with a second group is non-trivial, then the first group is a subgroup of the second group.*)\nLemma prime_meetG G H : prime #|G| -> G :&: H != 1 -> G \\subset H.\n\n(*This lemma states that if the orders of two groups are coprime natural numbers, then the cardinality of the product of the two groups is equal to the product of their individual cardinalities.*)\nLemma coprime_cardMg G H : coprime #|G| #|H| -> #|G * H| = (#|G| * #|H|)%N.\n\n(*This lemma states that for two subgroups of a given group, if their respective indices in the parent group are coprime natural numbers, then the product of the two subgroups is equal to the parent group.*)\nLemma coprime_index_mulG G H K :\n H \\subset G -> K \\subset G -> coprime #|G : H| #|G : K| -> H * K = G.\n\nEnd Lagrange.\n\nSection GeneratedGroup.\n\nVariable gT : finGroupType.\nImplicit Types x y z : gT.\nImplicit Types A B C D : {set gT}.\nImplicit Types G H K : {group gT}.\n\n(*This lemma states that any set of group elements is a subset of the subgroup generated by that set.*)\nLemma subset_gen A : A \\subset <>.\n\n(*This lemma states that if a set of group elements is a subset of a second set, then the first set is also a subset of the subgroup generated by the second set.*)\nLemma sub_gen A B : A \\subset B -> A \\subset <>.\n\n(*This lemma states that if an element belongs to a set of group elements, then that element also belongs to the subgroup generated by that set.*)\nLemma mem_gen x A : x \\in A -> x \\in <>.\n\n(*This lemma provides a predicate for membership in a generated subgroup, stating that an element belongs to the subgroup generated by a set if and only if that element is a member of every subgroup that contains the given set.*)\nLemma generatedP x A : reflect (forall G, A \\subset G -> x \\in G) (x \\in <>).\n\n(*This lemma states that the subgroup generated by a set of elements is a subgroup of a given group if and only if the generating set itself is a subset of that group.*)\nLemma gen_subG A G : (<> \\subset G) = (A \\subset G).\n\n(*This lemma states that the subgroup generated by the set of elements of a given group is identical to that group.*)\nLemma genGid G : <> = G.\n\n(*This lemma states that the subgroup generated by a given group, considered as a set of elements, is equal to the group itself.*)\nLemma genGidG G : <>%G = G.\n\n(*This lemma states that if a set of elements already forms a group, then the subgroup generated by that set is the set itself.*)\nLemma gen_set_id A : group_set A -> <> = A.\n\n(*This lemma states that if a set of group elements is a subset of a second set, then the subgroup generated by the first set is a subgroup of the subgroup generated by the second set.*)\nLemma genS A B : A \\subset B -> <> \\subset <>.\n\n(*This lemma states that the subgroup generated by the empty set is the trivial group.*)\nLemma gen0 : <> = 1 :> {set gT}.\n\n(*This lemma states that for any generating set of elements in a finite group, there exists a natural number such that the generated subgroup consists of all elements that can be expressed as a product of that many elements taken from the union of the generating set and the identity element.*)\nLemma gen_expgs A : {n | <> = (1 |: A) ^+ n}.\n\n(*This lemma provides a characterization for membership in a generated subgroup: an element belongs to the subgroup generated by a set if and only if there exists a finite sequence of elements from the generating set whose product equals that element.*)\nLemma gen_prodgP A x :\n reflect (exists n, exists2 c, forall i : 'I_n, c i \\in A & x = \\prod_i c i)\n (x \\in <>).\n\n(*This lemma states that if a set of elements is contained within the subgroup generated by the set difference of itself and a second set, then the subgroup generated by this set difference is equal to the subgroup generated by the original set.*)\nLemma genD A B : A \\subset <> -> <> = <>.\n\n(*This lemma states that the subgroup generated by the set of inverses of a given set of elements is identical to the subgroup generated by the original set.*)\nLemma genV A : <> = <>.\n\n(*This lemma states that the subgroup generated by a set of conjugated elements is equal to the conjugate of the subgroup generated by the original set.*)\nLemma genJ A z : <> = <> :^ z.\n\n(*This lemma states that the conjugate of the join of two generated subgroups is equal to the join of their respective conjugates.*)\nLemma conjYg A B z : (A <*> B) :^z = A :^ z <*> B :^ z.\n\n(*This lemma states that if an element is contained in the subgroup generated by a set from which that same element has been removed, then the subgroup generated without the element is equal to the subgroup generated by the original set.*)\nLemma genD1 A x : x \\in <> -> <> = <>.\n\n(*This lemma states that the subgroup generated by the non-identity elements of a set is equal to the subgroup generated by the full set.*)\nLemma genD1id A : <> = <>.\n\n(*This notation defines 'joingT' as a parsing-only alias for the join operation on sets of elements within a finite group, which computes the subgroup generated by the union of the two sets.*)\nNotation joingT := (@joing gT) (only parsing).\n(*This notation defines 'joinGT' as a parsing-only alias for the join operation on subgroups within a finite group, which computes the smallest subgroup containing both subgroups.*)\nNotation joinGT := (@joinG gT) (only parsing).\n\n(*This lemma states that the join of two sets of group elements is equal to the subgroup generated by the union of those two sets.*)\nLemma joingE A B : A <*> B = <>. \n\n(*This lemma states that the join of two subgroups is equivalent to the join of the underlying sets of elements of those subgroups.*)\nLemma joinGE G H : (G * H)%G = (G <*> H)%G. \n\n(*This lemma states that the join operation for sets of group elements is commutative.*)\nLemma joingC : commutative joingT.\n\n(*This lemma states that the join of a set of elements with the subgroup generated by a second set is equal to the join of the two original sets.*)\nLemma joing_idr A B : A <*> <> = A <*> B.\n\n(*This lemma states that the join of the subgroup generated by a set of elements with a second set is equal to the join of the two original sets.*)\nLemma joing_idl A B : <> <*> B = A <*> B.\n\n(*This lemma states that any set of group elements is a subset of the join of itself with any other set of elements.*)\nLemma joing_subl A B : A \\subset A <*> B.\n\n(*This lemma states that for any two subgroups, the second subgroup is a subgroup of their join.*)\nLemma joing_subr A B : B \\subset A <*> B.\n\n(*This lemma states that the join of two subgroups is a subgroup of a third subgroup if and only if each of the two subgroups is individually a subgroup of the third.*)\nLemma join_subG A B G : (A <*> B \\subset G) = (A \\subset G) && (B \\subset G).\n\n(*This lemma states that the join of a first subgroup with a second subgroup is equal to the first subgroup if and only if the second subgroup is a subset of the first.*)\nLemma joing_idPl G A : reflect (G <*> A = G) (A \\subset G).\n\n(*This lemma states that the join of a first subgroup with a second subgroup is equal to the second subgroup if and only if the first subgroup is a subset of the second.*)\nLemma joing_idPr A G : reflect (A <*> G = G) (A \\subset G).\n\n(*This lemma provides the logical equivalence between the proposition that two subgroups are subsets of a third subgroup and the proposition that their join is a subset of that third subgroup.*)\nLemma joing_subP A B G :\n reflect (A \\subset G /\\ B \\subset G) (A <*> B \\subset G).\n\n(*This lemma states that if the join of two subgroups is equal to a third subgroup, then both of the original subgroups are subsets of that third subgroup.*)\nLemma joing_sub A B C : A <*> B = C -> A \\subset C /\\ B \\subset C.\n\n(*This lemma, related to Dedekind's modular law, states that if a first set of group elements is a subset of a third set, and the subgroup generated by the set difference of the third and first sets is equal to the subgroup generated by a second set, then the subgroup generated by the union of the first and second sets is equal to the subgroup generated by the third set.*)\nLemma genDU A B C : A \\subset C -> <> = <> -> <> = <>.\n\n(*This lemma states that the subgroup join operation is associative.*)\nLemma joingA : associative joingT.\n\n(*This lemma states that the join of the trivial subgroup with any other subgroup results in that other subgroup.*)\nLemma joing1G G : 1 <*> G = G.\n\n(*This lemma states that the join of any subgroup with the trivial subgroup results in the original subgroup.*)\nLemma joingG1 G : G <*> 1 = G.\n\n(*This lemma states that the subgroup generated by the set product of two subgroups is equal to the join of those subgroups.*)\nLemma genM_join G H : <> = G <*> H.\n\n(*This lemma states that the set product of two subgroups is a subset of a third subgroup if and only if each of the two original subgroups is individually a subset of the third.*)\nLemma mulG_subG G H K : (G * H \\subset K) = (G \\subset K) && (H \\subset K).\n\n(*This lemma provides the logical equivalence between the proposition that two subgroups are subsets of a third subgroup and the proposition that their set product is a subset of that third subgroup.*)\nLemma mulGsubP K H G : reflect (K \\subset G /\\ H \\subset G) (K * H \\subset G).\n\n(*This lemma states that if the set product of two subgroups equals a given set, then both subgroups are subsets of that set.*)\nLemma mulG_sub K H A : K * H = A -> K \\subset A /\\ H \\subset A.\n\n(*This lemma states that the set product of two subgroups is the trivial subgroup if and only if both subgroups are themselves the trivial subgroup.*)\nLemma trivMg G H : (G * H == 1) = (G :==: 1) && (H :==: 1).\n\n(*This lemma states that if two subgroups commute, their join is equal to their set product.*)\nLemma comm_joingE G H : commute G H -> G <*> H = G * H.\n\n(*This lemma states that the subgroup join operation is commutative.*)\nLemma joinGC : commutative joinGT.\n\n(*This lemma states that the subgroup join operation is associative.*)\nLemma joinGA : associative joinGT.\n\n(*This lemma states that the trivial subgroup is the left identity for the subgroup join operation.*)\nLemma join1G : left_id 1%G joinGT.\n\n(*This lemma states that the trivial subgroup is the right identity for the subgroup join operation.*)\nLemma joinG1 : right_id 1%G joinGT.\n\n(*This lemma states that the iterated join of a family of subgroups, where each subgroup is generated by a set from a corresponding family of sets of group elements, is equal to the subgroup generated by the union of all those sets.*)\nLemma bigprodGEgen I r (P : pred I) (F : I -> {set gT}) :\n (\\prod_(i <- r | P i) <>)%G :=: << \\bigcup_(i <- r | P i) F i >>.\n\n(*This lemma states that the iterated join of a family of subgroups is equal to the subgroup generated by the union of the sets of elements from all subgroups in the family.*)\nLemma bigprodGE I r (P : pred I) (F : I -> {group gT}) :\n (\\prod_(i <- r | P i) F i)%G :=: << \\bigcup_(i <- r | P i) F i >>.\n\n(*This lemma states that if an element belongs to a first set of group elements and another element belongs to a second set, then their commutator belongs to the commutator subgroup generated by the two sets.*)\nLemma mem_commg A B x y : x \\in A -> y \\in B -> [~ x, y] \\in [~: A, B].\n\n(*This lemma states that if a first subgroup is a subset of a second subgroup, then the commutator subgroup of the first subgroup and a third subgroup is a subset of the commutator subgroup of the second subgroup and the third subgroup.*)\nLemma commSg A B C : A \\subset B -> [~: A, C] \\subset [~: B, C].\n\n(*This lemma states that if a second subgroup is a subset of a third subgroup, then the commutator subgroup of a first subgroup and the second subgroup is a subset of the commutator subgroup of the first subgroup and the third subgroup.*)\nLemma commgS A B C : B \\subset C -> [~: A, B] \\subset [~: A, C].\n\n(*This lemma states that if a first subgroup is a subset of a second, and a third subgroup is a subset of a fourth, then the commutator subgroup of the first and third subgroups is a subset of the commutator subgroup of the second and fourth subgroups.*)\nLemma commgSS A B C D :\n A \\subset B -> C \\subset D -> [~: A, C] \\subset [~: B, D].\n\n(*This lemma states that the derived subgroup of any given subgroup is a subset of that original subgroup.*)\nLemma der1_subG G : [~: G, G] \\subset G.\n\n(*This lemma states that if two subgroups are subsets of a third subgroup, then their commutator subgroup is also a subset of that third subgroup.*)\nLemma comm_subG A B G : A \\subset G -> B \\subset G -> [~: A, B] \\subset G.\n\n(*This lemma states that the commutator subgroup of a first subgroup with a second subgroup is equal to the commutator subgroup of the second subgroup with the first.*)\nLemma commGC A B : [~: A, B] = [~: B, A].\n\n(*This lemma states that the conjugate of a commutator subgroup by a group element is equal to the commutator of the conjugates of the original subgroups by that same element.*)\nLemma conjsRg A B x : [~: A, B] :^ x = [~: A :^ x, B :^ x].\n\nEnd GeneratedGroup.\n\nArguments gen_prodgP {gT A x}.\nArguments joing_idPl {gT G A}.\nArguments joing_idPr {gT A G}.\nArguments mulGsubP {gT K H G}.\nArguments joing_subP {gT A B G}.\n\nSection Cycles.\n\nVariable gT : finGroupType.\nImplicit Types x y : gT.\nImplicit Types G : {group gT}.\n\nImport Monoid.Theory.\n\n(*This lemma states that the cyclic group generated by the identity element is the trivial group, which contains only the identity element.*)\nLemma cycle1 : <[1]> = [1 gT].\n\n(*This lemma states that the order of the identity element of a group is the natural number one.*)\nLemma order1 : #[1 : gT] = 1%N.\n\n(*This lemma states that any group element is a member of the cyclic group it generates.*)\nLemma cycle_id x : x \\in <[x]>.\n\n(*This lemma states that any integer power of a group element belongs to the cyclic group generated by that element.*)\nLemma mem_cycle x i : x ^+ i \\in <[x]>.\n\n(*This lemma states that the cyclic group generated by an element is a subgroup of a given group if and only if the generating element is a member of that group.*)\nLemma cycle_subG x G : (<[x]> \\subset G) = (x \\in G).\n\n(*This lemma states that the cyclic group generated by an element is the trivial group if and only if the element itself is the identity element.*)\nLemma cycle_eq1 x : (<[x]> == 1) = (x == 1).\n\n(*This lemma states that the order of a group element is equal to the number of elements in the cyclic group it generates.*)\nLemma orderE x : #[x] = #|<[x]>|. \n\n(*This lemma states that the order of a group element is the natural number one if and only if the element is the identity element.*)\nLemma order_eq1 x : (#[x] == 1%N) = (x == 1).\n\n(*This lemma states that the order of a group element is greater than one if and only if the element is not the identity element.*)\nLemma order_gt1 x : (#[x] > 1) = (x != 1).\n\n(*This lemma states that the set of elements in a cyclic group generated by a group element is identical to the set of that element's powers, from the zeroth power up to the power one less than its order.*)\nLemma cycle_traject x : <[x]> =i traject (mulg x) 1 #[x].\n\n(*This lemma states that if a group element has an order of two, then the cyclic group it generates consists precisely of the identity element and the element itself.*)\nLemma cycle2g x : #[x] = 2 -> <[x]> = [set 1; x].\n\n(*This lemma states that if an element is a member of a cyclic group, then it can be expressed as a power of the generator, where the exponent is a natural number smaller than the order of the generator.*)\nLemma cyclePmin x y : y \\in <[x]> -> {i | i < #[x] & y = x ^+ i}.\n\n(*This lemma provides the definition of membership in a cyclic group, stating that an element belongs to the cyclic group generated by another element if and only if it can be expressed as an integer power of the generator.*)\nLemma cycleP x y : reflect (exists i, y = x ^+ i) (y \\in <[x]>).\n\n(*This lemma states that raising a group element to the power of its own order results in the identity element.*)\nLemma expg_order x : x ^+ #[x] = 1.\n\n(*This lemma states that if a power of a group element equals the identity, then exponents of that element can be reduced modulo that power without changing the result.*)\nLemma expg_mod p k x : x ^+ p = 1 -> x ^+ (k %% p) = x ^+ k.\n\n(*This lemma states that the exponent of a group element can be reduced modulo the order of that element without changing the resulting value.*)\nLemma expg_mod_order x i : x ^+ (i %% #[x]) = x ^+ i.\n\n(*This lemma provides a formula for the inverse of a group element, stating that it is equal to the element raised to the power of its order minus one.*)\nLemma invg_expg x : x^-1 = x ^+ #[x].-1.\n\n(*This lemma states that if a group element has an order of two, then it is its own inverse.*)\nLemma invg2id x : #[x] = 2 -> x^-1 = x.\n\n(*This lemma states that clamping a value to a specified range results in the lower bound if the value is less than the lower bound, the upper bound if the value is greater than the upper bound, and the value itself if it is within the range.*)\nLemma cycleX x i : <[x ^+ i]> \\subset <[x]>.\n\n(*This lemma states that an element and its inverse generate the same cyclic group.*)\nLemma cycleV x : <[x^-1]> = <[x]>.\n\n(*This lemma states that a group element and its inverse have the same order.*)\nLemma orderV x : #[x^-1] = #[x].\n\n(*This lemma states that the cyclic group generated by the conjugate of an element is equal to the conjugate of the cyclic group generated by the original element.*)\nLemma cycleJ x y : <[x ^ y]> = <[x]> :^ y.\n\n(*This lemma states that conjugation preserves the order of a group element.*)\nLemma orderJ x y : #[x ^ y] = #[x].\n\nEnd Cycles.\n\nSection Normaliser.\n\nVariable gT : finGroupType.\nImplicit Types x y z : gT.\nImplicit Types A B C D : {set gT}.\nImplicit Type G H K : {group gT}.\n\n(*This lemma provides the definition of the normalizer of a set, stating that an element belongs to the normalizer of a set if and only if conjugating the set by that element leaves the set unchanged.*)\nLemma normP x A : reflect (A :^ x = A) (x \\in 'N(A)).\n\nArguments normP {x A}.\n\n(*This lemma states that the normalizer of any set of group elements is itself a group.*)\nLemma group_set_normaliser A : group_set 'N(A).\n\nCanonical normaliser_group A := group (group_set_normaliser A).\n\n(*This lemma states that a set of group elements is a subset of the normalizer of another set if and only if every element in the first set normalizes the second set.*)\nLemma normsP A B : reflect {in A, normalised B} (A \\subset 'N(B)).\n\nArguments normsP {A B}.\n\n(*This lemma states that if a given element normalizes a set, then another element belongs to that set if and only if its conjugate by the normalizing element also belongs to the set.*)\nLemma memJ_norm x y A : x \\in 'N(A) -> (y ^ x \\in A) = (y \\in A).\n\n(*This lemma states that a first cyclic group is a subgroup of the normalizer of a second cyclic group if and only if conjugating the generator of the second group by the generator of the first group yields an element within the second cyclic group.*)\nLemma norms_cycle x y : (<[y]> \\subset 'N(<[x]>)) = (x ^ y \\in <[x]>).\n\n(*This lemma states that the normalizer of the trivial subgroup is the entire group.*)\nLemma norm1 : 'N(1) = setT :> {set gT}.\n\n(*This lemma states that any set of group elements is a subset of the normalizer of the trivial subgroup.*)\nLemma norms1 A : A \\subset 'N(1).\n\n(*This lemma states that the normalizer of a set of group elements is equal to the normalizer of the set containing their inverses.*)\nLemma normCs A : 'N(~: A) = 'N(A).\n\n(*This lemma states that any subgroup is a subset of its own normalizer.*)\nLemma normG G : G \\subset 'N(G).\n\n(*This lemma states that the normalizer of the entire group is the group itself.*)\nLemma normT : 'N([set: gT]) = [set: gT].\n\n(*This lemma states that if a set of group elements is a subset of a given subgroup, then it is also a subset of the normalizer of that subgroup.*)\nLemma normsG A G : A \\subset G -> A \\subset 'N(G).\n\n(*This lemma states that if a set of group elements is included in the normalizer of a second set, then any element of the second set, when conjugated by an element of the first set, remains in the second set.*)\nLemma normC A B : A \\subset 'N(B) -> commute A B.\n\n(*This lemma states that if a subgroup normalizes a second subgroup, then the subgroup generated by their union is equal to their set product.*)\nLemma norm_joinEl G H : G \\subset 'N(H) -> G <*> H = G * H.\n\n(*This lemma states that if a second subgroup normalizes a first subgroup, then the subgroup generated by their union is equal to their set product.*)\nLemma norm_joinEr G H : H \\subset 'N(G) -> G <*> H = G * H.\n\n(*This lemma states that for any subgroup, if an element belongs to the normalizer of that subgroup, then the right coset with respect to that element is equal to the left coset.*)\nLemma norm_rlcoset G x : x \\in 'N(G) -> G :* x = x *: G.\n\n(*This lemma states that if an element normalizes a subgroup, the set product of the right coset with respect to that element and another right coset is equal to the right coset of the product of the elements.*)\nLemma rcoset_mul G x y : x \\in 'N(G) -> (G :* x) * (G :* y) = G :* (x * y).\n\n(*This lemma states that the normalizer of the conjugate of a set of group elements by some element is equal to the conjugate of the normalizer of that set by the same element.*)\nLemma normJ A x : 'N(A :^ x) = 'N(A) :^ x.\n\n(*This lemma states that for any two sets of group elements and a third element, if the third element is in the normalizer of the first set, then the first set is a subset of the normalizer of the conjugate of the second set by the third element if and only if the first set is a subset of the normalizer of the second set.*)\nLemma norm_conj_norm x A B :\n x \\in 'N(A) -> (A \\subset 'N(B :^ x)) = (A \\subset 'N(B)).\n\n(*This lemma states that the normalizer of a set of group elements is a subset of the normalizer of the subgroup generated by that set.*)\nLemma norm_gen A : 'N(A) \\subset 'N(<>).\n\n(*This lemma states that a subgroup is always a subset of the normalizer of the conjugacy class of any element under the action of that subgroup.*)\nLemma class_norm x G : G \\subset 'N(x ^: G).\n\n(*This lemma states that if an element belongs to a subgroup, its conjugacy class under the action of that subgroup is a normal subset of the subgroup.*)\nLemma class_normal x G : x \\in G -> x ^: G <| G.\n\n(*This lemma states that if a subgroup normalizes a set of group elements, then the conjugacy class of an element under the action of that subgroup is a subset of the set if and only if the element itself is in the set.*)\nLemma class_sub_norm G A x : G \\subset 'N(A) -> (x ^: G \\subset A) = (x \\in A).\n\n(*This lemma states that a subgroup is a subset of the normalizer of the class support of any set of elements under the action of that subgroup.*)\nLemma class_support_norm A G : G \\subset 'N(class_support A G).\n\n(*This lemma states that if a first set of elements is a subset of a subgroup, and a second set of elements normalizes this subgroup, then the class support of the first set under the action of the second set is a subset of the subgroup.*)\nLemma class_support_sub_norm A B G :\n A \\subset G -> B \\subset 'N(G) -> class_support A B \\subset G.\n\nSection norm_trans.\n\nVariables (A B C D : {set gT}).\nHypotheses (nBA : A \\subset 'N(B)) (nCA : A \\subset 'N(C)).\n\n(*This lemma states that if a set of group elements normalizes a second set, it also normalizes the subgroup generated by that second set.*)\nLemma norms_gen : A \\subset 'N(<>).\n\n(*This lemma states that if a set of group elements normalizes a second set, it also normalizes the normalizer of that second set.*)\nLemma norms_norm : A \\subset 'N('N(B)).\n\n(*This lemma states that if a set of group elements normalizes two other sets, it also normalizes their intersection.*)\nLemma normsI : A \\subset 'N(B :&: C).\n\n(*This lemma states that if a set of group elements normalizes two other sets, it also normalizes their union.*)\nLemma normsU : A \\subset 'N(B :|: C).\n\n(*This lemma states that if a first set normalizes a second and third set, and the second set normalizes a fourth set, then the intersection of the first and second sets normalizes the intersection of the third and fourth sets.*)\nLemma normsIs : B \\subset 'N(D) -> A :&: B \\subset 'N(C :&: D).\n\n(*This lemma states that if a set of group elements normalizes two other sets, it also normalizes their set difference.*)\nLemma normsD : A \\subset 'N(B :\\: C).\n\n(*This lemma states that if a set of group elements normalizes two other sets, it also normalizes their set product.*)\nLemma normsM : A \\subset 'N(B * C).\n\n(*This lemma states that if a set of group elements normalizes two other sets, it also normalizes the subgroup generated by their union.*)\nLemma normsY : A \\subset 'N(B <*> C).\n\n(*This lemma states that if a set of group elements normalizes two other sets, it also normalizes their commutator set.*)\nLemma normsR : A \\subset 'N([~: B, C]).\n\n(*This lemma states that if a set of group elements normalizes two other sets, it also normalizes the class support of the first of these two sets under the action of the second.*)\nLemma norms_class_support : A \\subset 'N(class_support B C).\n\nEnd norm_trans.\n\n(*This lemma states that if a set of group elements normalizes a second set, then the intersection of the first set with any subgroup also normalizes the intersection of the second set with that subgroup.*)\nLemma normsIG A B G : A \\subset 'N(B) -> A :&: G \\subset 'N(B :&: G).\n\n(*This lemma states that if a set of group elements normalizes a second set, then the intersection of any subgroup with the first set also normalizes the intersection of that subgroup with the second set.*)\nLemma normsGI A B G : A \\subset 'N(B) -> G :&: A \\subset 'N(G :&: B).\n\n(*This lemma states that if a set is a subset of the intersection of the normalizers of a family of sets, then it is also a subset of the normalizer of the intersection of that same family of sets.*)\nLemma norms_bigcap I r (P : pred I) A (B_ : I -> {set gT}) :\n A \\subset \\bigcap_(i <- r | P i) 'N(B_ i) ->\n A \\subset 'N(\\bigcap_(i <- r | P i) B_ i).\n\n(*This lemma states that if a set is a subset of the intersection of the normalizers of a family of sets, then it is also a subset of the normalizer of the union of that same family of sets.*)\nLemma norms_bigcup I r (P : pred I) A (B_ : I -> {set gT}) :\n A \\subset \\bigcap_(i <- r | P i) 'N(B_ i) ->\n A \\subset 'N(\\bigcup_(i <- r | P i) B_ i).\n\n(*This lemma states that if a set is a subset of the normalizer of another set, it is also a subset of the normalizer of the group-theoretic complement of that other set.*)\nLemma normsD1 A B : A \\subset 'N(B) -> A \\subset 'N(B^#).\n\n(*This lemma states that the normalizer of the group-theoretic complement of a set is equal to the normalizer of the set itself.*)\nLemma normD1 A : 'N(A^#) = 'N(A).\n\n(*This lemma provides an equivalence property, stating that a set is a normal subset of another set if and only if it is a subset of that set and is normalized by every element of that set.*)\nLemma normalP A B : reflect (A \\subset B /\\ {in B, normalised A}) (A <| B).\n\n(*This lemma states that if a set is a normal subset of another set, then it is also a subset of that other set.*)\nLemma normal_sub A B : A <| B -> A \\subset B.\n\n(*This lemma states that if a set is a normal subset of another set, then the latter set is contained within the normalizer of the former set.*)\nLemma normal_norm A B : A <| B -> B \\subset 'N(A).\n\n(*This lemma states that for three sets, if the first is a subset of the second, the second is a subset of the third, and the first is a normal subset of the third, then the first is also a normal subset of the second.*)\nLemma normalS G H K : K \\subset H -> H \\subset G -> K <| G -> K <| H.\n\n(*This lemma states that the trivial subgroup containing only the identity element is a normal subgroup of any given group.*)\nLemma normal1 G : 1 <| G.\n\n(*This lemma states that any group is a normal subgroup of itself.*)\nLemma normal_refl G : G <| G.\n\n(*This lemma states that any group is a normal subgroup of its own normalizer.*)\nLemma normalG G : G <| 'N(G).\n\n(*This lemma states that if a set is a subset of a group, then it is a normal subgroup of its normalizer within that group.*)\nLemma normalSG G H : H \\subset G -> H <| 'N_G(H).\n\n(*This lemma states that the property of one set being a normal subset of another is preserved when both sets are conjugated by the same element.*)\nLemma normalJ A B x : (A :^ x <| B :^ x) = (A <| B).\n\n(*This lemma states that if two subgroups are normal in a group, their set product is also a normal subgroup of that group.*)\nLemma normalM G A B : A <| G -> B <| G -> A * B <| G.\n\n(*This lemma states that if two subgroups are normal in a group, their commutator subgroup is also a normal subgroup of that group.*)\nLemma normalY G A B : A <| G -> B <| G -> A <*> B <| G.\n\n(*This lemma provides an equivalence, stating that a subgroup is normal in its commutator with another group if and only if that other group normalizes the subgroup.*)\nLemma normalYl G H : (H <| H <*> G) = (G \\subset 'N(H)).\n\n(*This lemma provides an equivalence, stating that a subgroup is normal in its commutator with another group if and only if that other group normalizes the subgroup.*)\nLemma normalYr G H : (H <| G <*> H) = (G \\subset 'N(H)).\n\n(*This lemma states that the intersection of two normal subgroups of a group is also a normal subgroup of that group.*)\nLemma normalI G A B : A <| G -> B <| G -> A :&: B <| G.\n\n(*This lemma states that if a group normalizes a set, then the intersection of the group and the set is a normal subgroup of the group.*)\nLemma norm_normalI G A : G \\subset 'N(A) -> G :&: A <| G.\n\n(*This lemma states that if a set is a normal subset of a group, its intersection with any subgroup of that group is a normal subset of that subgroup.*)\nLemma normalGI G H A : H \\subset G -> A <| G -> H :&: A <| H.\n\n(*This lemma states that a set is a normal subgroup of its normalizer within a given group if and only if it is a subset of that group.*)\nLemma normal_subnorm G H : (H <| 'N_G(H)) = (H \\subset G).\n\n(*This lemma states that the group-theoretic complement of a set is a normal subgroup of a group if and only if the set itself is a normal subgroup of that group.*)\nLemma normalD1 A G : (A^# <| G) = (A <| G).\n\n(*This lemma states that the core of a set within a group is a subset of that set.*)\nLemma gcore_sub A G : gcore A G \\subset A.\n\n(*This lemma states that a group is contained in the normalizer of the core of any of its subsets.*)\nLemma gcore_norm A G : G \\subset 'N(gcore A G).\n\n(*This lemma states that for any subset of a group, its core within that group is a normal subgroup of the group.*)\nLemma gcore_normal A G : A \\subset G -> gcore A G <| G.\n\n(*This lemma establishes the maximality property of the core, stating that any subset of a given set that is normalized by a group is itself a subset of the core of the given set within that group.*)\nLemma gcore_max A B G : B \\subset A -> G \\subset 'N(B) -> B \\subset gcore A G.\n\n(*This lemma states that for a set normalized by a group, being a subset of the core of another set is equivalent to being a subset of that other set.*)\nLemma sub_gcore A B G :\n G \\subset 'N(B) -> (B \\subset gcore A G) = (B \\subset A).\n\n(*This lemma states that if a subgroup has an index of two within a group, then for any element not in the subgroup, its right coset is equal to the set of all elements in the group that are not in the subgroup.*)\nLemma rcoset_index2 G H x :\n H \\subset G -> #|G : H| = 2 -> x \\in G :\\: H -> H :* x = G :\\: H.\n\n(*This lemma states that any subgroup with an index of two in a group is a normal subgroup.*)\nLemma index2_normal G H : H \\subset G -> #|G : H| = 2 -> H <| G.\n\n(*This lemma provides an equivalence, stating that an element belongs to the centralizer of another element if and only if the two elements commute.*)\nLemma cent1P x y : reflect (commute x y) (x \\in 'C[y]).\n\n(*This lemma states that any group element is a member of its own centralizer.*)\nLemma cent1id x : x \\in 'C[x]. \n\n(*This lemma states that an element is in the centralizer of another element if and only if the two elements commute.*)\nLemma cent1E x y : (x \\in 'C[y]) = (x * y == y * x).\n\n(*This lemma states that the property of an element being in the centralizer of another element is symmetric.*)\nLemma cent1C x y : (x \\in 'C[y]) = (y \\in 'C[x]).\n\nCanonical centraliser_group A : {group _} := Eval hnf in [group of 'C(A)].\n\n(*This lemma states that the centralizer of a singleton set containing an element is equal to the centralizer of that element itself.*)\nLemma cent_set1 x : 'C([set x]) = 'C[x].\n\n(*This lemma states that the centralizer of an element conjugated by another element is equal to the conjugate of the original element's centralizer by that same element.*)\nLemma cent1J x y : 'C[x ^ y] = 'C[x] :^ y.\n\n(*This lemma provides a boolean reflection, stating that an element centralizes a set of elements if and only if it is a member of the centralizer of that set.*)\nLemma centP A x : reflect (centralises x A) (x \\in 'C(A)).\n\n(*This lemma provides a boolean reflection, stating that one set of elements is centralized by another set if and only if the first set is a subset of the centralizer of the second set.*)\nLemma centsP A B : reflect {in A, centralised B} (A \\subset 'C(B)).\n\n(*This lemma states that the property of a set being a subset of the centralizer of another set is symmetric.*)\nLemma centsC A B : (A \\subset 'C(B)) = (B \\subset 'C(A)).\n\n(*This lemma states that any set of group elements is a subset of the centralizer of the identity element.*)\nLemma cents1 A : A \\subset 'C(1).\n\n(*This lemma states that the centralizer of the identity element is equal to the set of all elements in the group.*)\nLemma cent1T : 'C(1) = setT :> {set gT}.\n\n(*This lemma states that the centralizer of the singleton set containing the identity element is equal to the set of all elements in the group.*)\nLemma cent11T : 'C[1] = setT :> {set gT}.\n\n(*This lemma states that the centralizer of a set of group elements is a subset of the normalizer of that same set.*)\nLemma cent_sub A : 'C(A) \\subset 'N(A).\n\n(*This lemma states that if a set of group elements is a subset of the centralizer of another set, then it is also a subset of the normalizer of that same set.*)\nLemma cents_norm A B : A \\subset 'C(B) -> A \\subset 'N(B).\n\n(*This lemma states that if a set of group elements is contained in the centralizer of another set, then every element from the first set commutes with every element from the second set.*)\nLemma centC A B : A \\subset 'C(B) -> commute A B.\n\n(*This lemma states that if a subgroup is contained in the centralizer of another subgroup, then the subgroup generated by their union is equal to their set product.*)\nLemma cent_joinEl G H : G \\subset 'C(H) -> G <*> H = G * H.\n\n(*This lemma states that if a subgroup is centralized by another subgroup, then the subgroup generated by their union is equal to their set product.*)\nLemma cent_joinEr G H : H \\subset 'C(G) -> G <*> H = G * H.\n\n(*This lemma states that the centralizer of a set conjugated by an element is equal to the conjugate of the set's centralizer by that same element.*)\nLemma centJ A x : 'C(A :^ x) = 'C(A) :^ x.\n\n(*This lemma states that the normalizer of a set of group elements is a subset of the normalizer of the centralizer of that set.*)\nLemma cent_norm A : 'N(A) \\subset 'N('C(A)).\n\n(*This lemma states that if a set of group elements is a subset of the normalizer of a second set, then the first set is also a subset of the normalizer of the centralizer of the second set.*)\nLemma norms_cent A B : A \\subset 'N(B) -> A \\subset 'N('C(B)).\n\n(*This lemma states that the centralizer of a set of group elements is a normal subgroup of the normalizer of that set.*)\nLemma cent_normal A : 'C(A) <| 'N(A).\n\n(*This lemma states that if one set is a subset of another, then the centralizer of the larger set is a subset of the centralizer of the smaller set.*)\nLemma centS A B : B \\subset A -> 'C(A) \\subset 'C(B).\n\n(*This lemma states that if a first set is a subset of a second, and a third set is a subset of the centralizer of the second, then the third set is also a subset of the centralizer of the first.*)\nLemma centsS A B C : A \\subset B -> C \\subset 'C(B) -> C \\subset 'C(A).\n\n(*This lemma states that if a first set is a subset of a third set and a second set is a subset of a fourth set, and the third set is contained in the centralizer of the fourth set, then the first set is contained in the centralizer of the second set.*)\nLemma centSS A B C D :\n A \\subset C -> B \\subset D -> C \\subset 'C(D) -> A \\subset 'C(B).\n\n(*This lemma states that the subgroup generated by the union of the centralizers of two sets is a subset of the centralizer of their intersection.*)\nLemma centI A B : 'C(A) <*> 'C(B) \\subset 'C(A :&: B).\n\n(*This lemma states that the centralizer of the union of two sets is equal to the intersection of their individual centralizers.*)\nLemma centU A B : 'C(A :|: B) = 'C(A) :&: 'C(B).\n\n(*This lemma states that the centralizer of the subgroup generated by a set of elements is equal to the centralizer of the set itself.*)\nLemma cent_gen A : 'C(<>) = 'C(A).\n\n(*This lemma states that the centralizer of the cyclic group generated by an element is equal to the centralizer of that element.*)\nLemma cent_cycle x : 'C(<[x]>) = 'C[x].\n\n(*This lemma states that a set of elements is a subset of the centralizer of an element if and only if that element is a member of the centralizer of the set.*)\nLemma sub_cent1 A x : (A \\subset 'C[x]) = (x \\in 'C(A)).\n\n(*This lemma states that if two group elements commute, then the cyclic group generated by the first element is a subset of the centralizer of the cyclic group generated by the second element.*)\nLemma cents_cycle x y : commute x y -> <[x]> \\subset 'C(<[y]>).\n\n(*This lemma states that any cyclic group is abelian.*)\nLemma cycle_abelian x : abelian <[x]>.\n\n(*This lemma states that the centraliser of the group generated by the union of two sets is equal to the intersection of the centralisers of each set.*)\nLemma centY A B : 'C(A <*> B) = 'C(A) :&: 'C(B).\n\n(*This lemma states that the centraliser of the direct product of two subgroups is equal to the intersection of their individual centralisers.*)\nLemma centM G H : 'C(G * H) = 'C(G) :&: 'C(H).\n\n(*This lemma establishes an equivalence: an element belongs to the centraliser of a group if and only if its conjugacy class under that group consists of only that single element.*)\nLemma cent_classP x G : reflect (x ^: G = [set x]) (x \\in 'C(G)).\n\n(*This lemma establishes an equivalence: a first set is a subset of the centraliser of a second set if and only if the commutator subgroup of the two sets is the trivial group.*)\nLemma commG1P A B : reflect ([~: A, B] = 1) (A \\subset 'C(B)).\n\n(*This lemma states that a set of group elements constitutes an abelian structure if and only if the set is a subset of its own centraliser.*)\nLemma abelianE A : abelian A = (A \\subset 'C(A)). \n\n(*This lemma states that the trivial group, which contains only the identity element, is an abelian group.*)\nLemma abelian1 : abelian [1 gT]. \n\n(*This lemma states that if a first set of group elements is a subset of a second set that is known to be abelian, then the first set is also abelian.*)\nLemma abelianS A B : A \\subset B -> abelian B -> abelian A.\n\n(*This lemma states that a set of group elements is abelian if and only if its conjugate by any group element is also abelian.*)\nLemma abelianJ A x : abelian (A :^ x) = abelian A.\n\n(*This lemma states that the subgroup generated by a set of elements is abelian if and only if the original set of elements is itself abelian.*)\nLemma abelian_gen A : abelian <> = abelian A.\n\n(*This lemma states that the group generated by the union of two sets is abelian if and only if both original sets are abelian and the second set is a subset of the centraliser of the first set.*)\nLemma abelianY A B :\n abelian (A <*> B) = [&& abelian A, abelian B & B \\subset 'C(A)].\n\n(*This lemma states that the direct product of two subgroups is abelian if and only if both subgroups are individually abelian and the second subgroup is a subset of the centraliser of the first.*)\nLemma abelianM G H :\n abelian (G * H) = [&& abelian G, abelian H & H \\subset 'C(G)].\n\nSection SubAbelian.\n\nVariable A B C : {set gT}.\nHypothesis cAA : abelian A.\n\n(*This lemma, under the hypothesis that a given set is abelian, states that if a second set is a subset of the first, then the first set is contained within the centraliser of the second set.*)\nLemma sub_abelian_cent : C \\subset A -> A \\subset 'C(C).\n\n(*This lemma, under the hypothesis that a given set is abelian, states that if two other sets are both subsets of the abelian set, then the first of these two is a subset of the centraliser of the second.*)\nLemma sub_abelian_cent2 : B \\subset A -> C \\subset A -> B \\subset 'C(C).\n\n(*This lemma, under the hypothesis that a given set is abelian, states that if a second set is a subset of the abelian set, then the abelian set is itself a subset of the normaliser of the second set.*)\nLemma sub_abelian_norm : C \\subset A -> A \\subset 'N(C).\n\n(*This lemma, under the hypothesis that a given group is abelian, states that a second group is a subgroup of the first if and only if it is a normal subgroup of the first.*)\nLemma sub_abelian_normal : (C \\subset A) = (C <| A).\n\nEnd SubAbelian.\n\nEnd Normaliser.\n\nArguments normP {gT x A}.\nArguments centP {gT A x}.\nArguments normsP {gT A B}.\nArguments cent1P {gT x y}.\nArguments normalP {gT A B}.\nArguments centsP {gT A B}.\nArguments commG1P {gT A B}.\n\nArguments normaliser_group _ _%_g.\nArguments centraliser_group _ _%_g.\n\n(*This notation denotes the normaliser of a given set of group elements, which is the set of all elements in the ambient group that conjugate the given set back to itself.*)\nNotation \"''N' ( A )\" := (normaliser_group A) : Group_scope.\n(*This notation denotes the centraliser of a given set of group elements, which is the set of all elements in the ambient group that commute with every element of the given set.*)\nNotation \"''C' ( A )\" := (centraliser_group A) : Group_scope.\n(*This notation denotes the centraliser of a single group element, defined as the normaliser of the singleton set containing that element.*)\nNotation \"''C' [ x ]\" := (normaliser_group [set x%g]) : Group_scope.\n(*This notation denotes the normaliser of a set within a given group, representing the intersection of that group with the ambient normaliser of the set.*)\nNotation \"''N_' G ( A )\" := (setI_group G 'N(A)) : Group_scope.\n(*This notation denotes the centraliser of a set within a given group, representing the intersection of that group with the ambient centraliser of the set.*)\nNotation \"''C_' G ( A )\" := (setI_group G 'C(A)) : Group_scope.\n(*This notation provides an alternative syntax for denoting the centraliser of a set within a given group, representing the intersection of that group with the ambient centraliser of the set.*)\nNotation \"''C_' ( G ) ( A )\" := (setI_group G 'C(A))\n (only parsing) : Group_scope.\n(*This notation denotes the centraliser of a single element within a given group, representing the intersection of that group with the ambient centraliser of the element.*)\nNotation \"''C_' G [ x ]\" := (setI_group G 'C[x]) : Group_scope.\n(*This notation provides an alternative syntax for denoting the centraliser of a single element within a given group, representing the intersection of that group with the ambient centraliser of the element.*)\nNotation \"''C_' ( G ) [ x ]\" := (setI_group G 'C[x])\n (only parsing) : Group_scope.\n\n#[global] Hint Extern 0 (is_true (_ \\subset _)) => apply: normG : core.\n#[global] Hint Extern 0 (is_true (_ <| _)) => apply: normal_refl : core.\n\nSection MinMaxGroup.\n\nVariable gT : finGroupType.\nImplicit Types gP : pred {group gT}.\n\n(*This definition defines a predicate that is true for a given group if that group satisfies a specific property and is maximal among all subgroups that also satisfy the property, where maximality is defined with respect to the subset relation.*)\nDefinition maxgroup A gP := maxset (fun A => group_set A && gP <>%G) A.\n(*This definition defines a predicate that is true for a given group if that group satisfies a specific property and is minimal among all subgroups that also satisfy the property, where minimality is defined with respect to the subset relation.*)\nDefinition mingroup A gP := minset (fun A => group_set A && gP <>%G) A.\n\nVariable gP : pred {group gT}.\nArguments gP _%_G.\n\n(*This lemma states that if there exists at least one subgroup that satisfies a given property within a finite group, then there must exist a maximal subgroup that satisfies that same property.*)\nLemma ex_maxgroup : (exists G, gP G) -> {G : {group gT} | maxgroup G gP}.\n\n(*This lemma states that if there exists at least one subgroup that satisfies a given property within a finite group, then there must exist a minimal subgroup that satisfies that same property.*)\nLemma ex_mingroup : (exists G, gP G) -> {G : {group gT} | mingroup G gP}.\n\nVariable G : {group gT}.\n\n(*This lemma provides the characteristic property of a minimal group: a group is considered minimal with respect to a given property if and only if it satisfies that property, and any other subgroup that also satisfies the property and is contained within the first group must be equal to it.*)\nLemma mingroupP :\n reflect (gP G /\\ forall H, gP H -> H \\subset G -> H :=: G) (mingroup G gP).\n\n(*This lemma provides the characteristic property of a maximal group: a group is considered maximal with respect to a given property if and only if it satisfies that property, and any other subgroup that also satisfies the property and contains the first group must be equal to it.*)\nLemma maxgroupP :\n reflect (gP G /\\ forall H, gP H -> G \\subset H -> H :=: G) (maxgroup G gP).\n\n(*This lemma states that if a group is a maximal group with respect to a given property, then that group itself must satisfy the given property.*)\nLemma maxgroupp : maxgroup G gP -> gP G. \n\n(*This lemma states that if a group qualifies as a minimal group with respect to a given property, then it must indeed satisfy that property.*)\nLemma mingroupp : mingroup G gP -> gP G. \n\nHypothesis gPG : gP G.\n\n(*This lemma asserts that for any group satisfying a given property, there exists a maximal group that also satisfies that property and contains the original group as a subgroup.*)\nLemma maxgroup_exists : {H : {group gT} | maxgroup H gP & G \\subset H}.\n\n(*This lemma asserts the existence of a minimal group that satisfies a given property and is contained as a subgroup within a larger ambient group.*)\nLemma mingroup_exists : {H : {group gT} | mingroup H gP & H \\subset G}.\n\nEnd MinMaxGroup.\n\nArguments mingroup {gT} A%_g gP.\nArguments maxgroup {gT} A%_g gP.\nArguments mingroupP {gT gP G}.\nArguments maxgroupP {gT gP G}.\n\n(*This notation denotes the maximal subgroup of a given group that contains a specified set of elements and satisfies a given property.*)\nNotation \"[ 'max' A 'of' G | gP ]\" :=\n (maxgroup A (fun G : {group _} => gP)) : group_scope.\n(*This notation denotes the maximal subgroup of a given group that contains all of its own elements and satisfies a given property; this typically resolves to the group itself if it satisfies the property.*)\nNotation \"[ 'max' G | gP ]\" := [max gval G of G | gP] : group_scope.\n(*This notation denotes the maximal subgroup of a given group that contains a specified set of elements and satisfies two given properties.*)\nNotation \"[ 'max' A 'of' G | gP & gQ ]\" :=\n [max A of G | gP && gQ] : group_scope.\n(*This notation denotes the maximal subgroup of a given group that contains all of its own elements and satisfies two given properties; this typically resolves to the group itself if it satisfies both properties.*)\nNotation \"[ 'max' G | gP & gQ ]\" := [max G | gP && gQ] : group_scope.\n(*This notation denotes the minimal subgroup of a given group that contains a specified set of elements and satisfies a given property.*)\nNotation \"[ 'min' A 'of' G | gP ]\" :=\n (mingroup A (fun G : {group _} => gP)) : group_scope.\n(*This notation denotes the minimal subgroup of a given group that contains all of its own elements and satisfies a given property; this typically resolves to the group itself if it satisfies the property.*)\nNotation \"[ 'min' G | gP ]\" := [min gval G of G | gP] : group_scope.\n(*This notation denotes the minimal subgroup of a given group that contains a specified set of elements and satisfies two given properties.*)\nNotation \"[ 'min' A 'of' G | gP & gQ ]\" :=\n [min A of G | gP && gQ] : group_scope.\n(*This notation denotes the minimal subgroup of a given group that contains all of its own elements and satisfies two given properties; this typically resolves to the group itself if it satisfies both properties.*)\nNotation \"[ 'min' G | gP & gQ ]\" := [min G | gP && gQ] : group_scope.", - "fingroup.all_fingroup": "From mathcomp Require Export action.\nFrom mathcomp Require Export automorphism.\nFrom mathcomp Require Export fingroup.\nFrom mathcomp Require Export gproduct.\nFrom mathcomp Require Export morphism.\nFrom mathcomp Require Export perm.\nFrom mathcomp Require Export presentation.", - "fingroup.automorphism": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat fintype.\nFrom mathcomp Require Import finset fingroup perm morphism.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection Automorphism.\n\nVariable gT : finGroupType.\nImplicit Type A : {set gT}.\nImplicit Types a b : {perm gT}.\n\n(*This definition specifies the set of automorphisms of a given set as the collection of all permutations that both map the set onto itself and are group morphisms on that set.*)\nDefinition Aut A := [set a | perm_on A a & morphic A a].\n\n(*This lemma states that any permutation belonging to the set of automorphisms of a given set is necessarily a group morphism on that set.*)\nLemma Aut_morphic A a : a \\in Aut A -> morphic A a.\n\n(*This lemma states that if a permutation is an automorphism of a given set, then it fixes any element that is not a member of that set.*)\nLemma out_Aut A a x : a \\in Aut A -> x \\notin A -> a x = x.\n\n(*This lemma states that two automorphisms of a given set are equal if they agree on all elements within that set.*)\nLemma eq_Aut A : {in Aut A &, forall a b, {in A, a =1 b} -> a = b}.\n\n(*This definition constructs a group morphism structure from a permutation that is known to be an automorphism of a given set.*)\nDefinition autm A a (AutAa : a \\in Aut A) := morphm (Aut_morphic AutAa).\n(*This lemma states that the function underlying the group morphism created from an automorphism is identical to the original automorphism's permutation.*)\nLemma autmE A a (AutAa : a \\in Aut A) : autm AutAa = a.\n\nCanonical autm_morphism A a aM := Eval hnf in [morphism of @autm A a aM].\n\nSection AutGroup.\n\nVariable G : {group gT}.\n\n(*This lemma states that the set of all automorphisms of a given group forms a group under the operation of function composition.*)\nLemma Aut_group_set : group_set (Aut G).\n\nCanonical Aut_group := group Aut_group_set.\n\nVariable (a : {perm gT}) (AutGa : a \\in Aut G).\n(*A local notation for the group morphism constructed from a given automorphism of a group.*)\nNotation f := (autm AutGa).\n(*A local notation for the lemma stating that the function underlying the group morphism constructed from an automorphism is identical to the original automorphism permutation.*)\nNotation fE := (autmE AutGa).\n\n(*This lemma states that any group morphism constructed from an automorphism is an injective function.*)\nLemma injm_autm : 'injm f.\n\n(*This lemma states that the kernel of a group morphism constructed from an automorphism is the trivial group, which contains only the identity element.*)\nLemma ker_autm : 'ker f = 1. \n\n(*This lemma states that the image of a group under a morphism constructed from one of its automorphisms is the group itself.*)\nLemma im_autm : f @* G = G.\n\n(*This lemma states that applying an automorphism of a group to any element of that group yields another element within the same group.*)\nLemma Aut_closed x : x \\in G -> a x \\in G.\n\nEnd AutGroup.\n\n(*This lemma states that the automorphism group of the trivial group is itself the trivial group.*)\nLemma Aut1 : Aut 1 = 1.\n\nEnd Automorphism.\n\nArguments Aut _ _%_g.\n(*A notation for representing the automorphism group of a given group. It is typically used to denote the group structure formed by all automorphisms of the input group under the operation of composition.*)\nNotation \"[ 'Aut' G ]\" := (Aut_group G) (format \"[ 'Aut' G ]\") : Group_scope.\n(*A notation for the set of all automorphisms of a given group.*)\nNotation \"[ 'Aut' G ]\" := (Aut G) (only parsing) : group_scope.\n\nPrenex Implicits Aut autm.\n\nSection PermIn.\n\nVariables (T : finType) (A : {set T}) (f : T -> T).\n\nHypotheses (injf : {in A &, injective f}) (sBf : f @: A \\subset A).\n\n(*This lemma states that a function constructed to apply a given injective-on-a-subset function to elements within that subset and act as the identity elsewhere is injective over its entire domain.*)\nLemma perm_in_inj : injective (fun x => if x \\in A then f x else x).\n\n(*This definition constructs a permutation on a finite type by extending a function that is injective on a given subset and acts as the identity outside of it.*)\nDefinition perm_in := perm perm_in_inj.\n\n(*This lemma states that the permutation constructed by extending an injective-on-a-subset function is a permutation of that specific subset.*)\nLemma perm_in_on : perm_on A perm_in.\n\n(*This lemma states that the permutation constructed by extending a function defined on a subset is equal to the original function for all elements within that subset.*)\nLemma perm_inE : {in A, perm_in =1 f}.\n\nEnd PermIn.\n\nSection MakeAut.\n\nVariables (gT : finGroupType) (G : {group gT}) (f : {morphism G >-> gT}).\nImplicit Type A : {set gT}.\n\nHypothesis injf : 'injm f.\n\n(*This lemma states that for an injective group morphism on a finite group, the image of any subset is equal to the original subset if and only if the image is contained within the original subset.*)\nLemma morphim_fixP A : A \\subset G -> reflect (f @* A = A) (f @* A \\subset A).\n\nHypothesis Gf : f @* G = G.\n\n(*This lemma states that the image of a group under an injective morphism that maps the group to itself is a subset of that same group.*)\nLemma aut_closed : f @: G \\subset G.\n\n(*This definition constructs a permutation on the carrier type of a finite group that corresponds to the action of a given injective group morphism which maps the group onto itself.*)\nDefinition aut := perm_in (injmP injf) aut_closed.\n\n(*This lemma states that the permutation constructed from an injective group morphism is equal to that morphism for all elements within the group.*)\nLemma autE : {in G, aut =1 f}.\n\n(*This lemma states that the permutation constructed from an injective group morphism is itself a group morphism on the given group.*)\nLemma morphic_aut : morphic G aut.\n\n(*This lemma states that the permutation constructed from an injective group morphism that maps a group to itself is an automorphism of that group.*)\nLemma Aut_aut : aut \\in Aut G.\n\n(*This lemma states that for any subset of a group, its image under the automorphism derived from a group morphism is the same as its image under the original morphism.*)\nLemma imset_autE A : A \\subset G -> aut @: A = f @* A.\n\n(*This lemma states that for any subset of a group, its preimage under the automorphism derived from a group morphism is the same as its preimage under the original morphism.*)\nLemma preim_autE A : A \\subset G -> aut @^-1: A = f @*^-1 A.\n\nEnd MakeAut.\n\nArguments morphim_fixP {gT G f}.\nPrenex Implicits aut.\n\nSection AutIsom.\n\nVariables (gT rT : finGroupType) (G D : {group gT}) (f : {morphism D >-> rT}).\n\nHypotheses (injf : 'injm f) (sGD : G \\subset D).\n(*This definition establishes a boolean predicate that determines membership in the underlying set of a given group. The predicate evaluates to true if an element is a member of the group, and false otherwise.*)\nLet domG := subsetP sGD.\n\n(*This lemma provides a constructive proof that for every automorphism on a subgroup, there exists a corresponding automorphism on the image of that subgroup under an injective morphism, and it establishes that the composition of these functions commutes on the subgroup.*)\nLemma Aut_isom_subproof a :\n {a' | a' \\in Aut (f @* G) & a \\in Aut G -> {in G, a' \\o f =1 f \\o a}}.\n\n(*This definition defines a function that maps an automorphism of a subgroup to the corresponding automorphism on the image of that subgroup under an injective morphism.*)\nDefinition Aut_isom a := s2val (Aut_isom_subproof a).\n\n(*This lemma states that the function mapping automorphisms of a subgroup to its image group indeed produces a valid automorphism of the image group.*)\nLemma Aut_Aut_isom a : Aut_isom a \\in Aut (f @* G).\n\n(*This lemma states that for any automorphism of a subgroup, the corresponding mapped automorphism on the image group commutes with the original injective morphism.*)\nLemma Aut_isomE a : a \\in Aut G -> {in G, forall x, Aut_isom a (f x) = f (a x)}.\n\n(*This lemma states that the function mapping automorphisms from a subgroup to its image group is a group morphism, meaning it preserves the group operation.*)\nLemma Aut_isomM : {in Aut G &, {morph Aut_isom: x y / x * y}}.\n\nCanonical Aut_isom_morphism := Morphism Aut_isomM.\n\n(*This lemma states that the group morphism which maps automorphisms from a subgroup to its image group is injective.*)\nLemma injm_Aut_isom : 'injm Aut_isom.\n\nEnd AutIsom.\n\nSection InjmAut.\n\nVariables (gT rT : finGroupType) (G D : {group gT}) (f : {morphism D >-> rT}).\n\nHypotheses (injf : 'injm f) (sGD : G \\subset D).\n(*This definition provides a boolean predicate that is true for elements belonging to a given subgroup.*)\nLet domG := subsetP sGD.\n\n(*This lemma states that the image of the automorphism group of a group G under a specific group isomorphism is equal to the automorphism group of the image of G under an injective group morphism.*)\nLemma im_Aut_isom : Aut_isom injf sGD @* Aut G = Aut (f @* G).\n\n(*This lemma asserts that a specific function, constructed from an injective group morphism, is a group isomorphism between the automorphism group of the original group and the automorphism group of its image.*)\nLemma Aut_isomP : isom (Aut G) (Aut (f @* G)) (Aut_isom injf sGD).\n\n(*This lemma states that the automorphism group of a group G is isomorphic to the automorphism group of the image of G under an injective group morphism.*)\nLemma injm_Aut : Aut (f @* G) \\isog Aut G.\n\nEnd InjmAut.\n\nSection ConjugationMorphism.\n\nVariable gT : finGroupType.\nImplicit Type A : {set gT}.\n\n(*This definition specifies a conjugation function that, for a given element, maps any other element to its conjugate by the given element.*)\nDefinition conjgm of {set gT} := fun x y : gT => y ^ x.\n\n(*This lemma provides the explicit definition of the conjugation function, stating that applying it to two elements results in the second element conjugated by the first.*)\nLemma conjgmE A x y : conjgm A x y = y ^ x. \n\nCanonical conjgm_morphism A x :=\n @Morphism _ _ A (conjgm A x) (in2W (fun y z => conjMg y z x)).\n\n(*This lemma states that the image of a set under the conjugation map defined on another set is equal to the conjugation of the intersection of the two sets.*)\nLemma morphim_conj A x B : conjgm A x @* B = (A :&: B) :^ x.\n\nVariable G : {group gT}.\n\n(*This lemma asserts that the conjugation map on a group, for any given element, is an injective group morphism.*)\nLemma injm_conj x : 'injm (conjgm G x).\n\n(*This lemma states that the conjugation map by a given element is a group isomorphism from a group to its conjugate subgroup by that same element.*)\nLemma conj_isom x : isom G (G :^ x) (conjgm G x).\n\n(*This lemma states that any group is isomorphic to any of its conjugate subgroups.*)\nLemma conj_isog x : G \\isog G :^ x.\n\n(*This lemma states that if an element belongs to the normalizer of a group, then the image of the group under conjugation by that element is the group itself.*)\nLemma norm_conjg_im x : x \\in 'N(G) -> conjgm G x @* G = G.\n\n(*This lemma states that for an element in the normalizer of a group, the conjugation map by that element is a group isomorphism from the group to itself.*)\nLemma norm_conj_isom x : x \\in 'N(G) -> isom G G (conjgm G x).\n\n(*This definition constructs the inner automorphism corresponding to conjugation by a given element, which is a group isomorphism from a group to itself.*)\nDefinition conj_aut x := aut (injm_conj _) (norm_conjg_im (subgP (subg _ x))).\n\n(*This lemma specifies the action of an inner automorphism: for an element in the normalizer of a group, the automorphism maps any element of the group to its conjugate.*)\nLemma norm_conj_autE : {in 'N(G) & G, forall x y, conj_aut x y = y ^ x}.\n\n(*This lemma specifies that for any two elements in a group, the inner automorphism associated with the first element maps the second element to its conjugate by the first.*)\nLemma conj_autE : {in G &, forall x y, conj_aut x y = y ^ x}.\n\n(*This lemma states that the function mapping an element from the normalizer of a group to its corresponding inner automorphism is a group morphism, where the group operation in the domain is multiplication and in the codomain is composition of automorphisms.*)\nLemma conj_aut_morphM : {in 'N(G) &, {morph conj_aut : x y / x * y}}.\n\nCanonical conj_aut_morphism := Morphism conj_aut_morphM.\n\n(*This lemma states that the kernel of the group morphism that maps an element to its corresponding inner automorphism is the center of the group.*)\nLemma ker_conj_aut : 'ker conj_aut = 'C(G).\n\n(*This lemma states that the image of any set of elements under the inner automorphism map is a subset of the full automorphism group.*)\nLemma Aut_conj_aut A : conj_aut @* A \\subset Aut G.\n\nEnd ConjugationMorphism.\n\nArguments conjgm _ _%_g.\nPrenex Implicits conjgm conj_aut.\n\nReserved Notation \"G \\char H\" (at level 70).\n\nSection Characteristicity.\n\nVariable gT : finGroupType.\nImplicit Types A B : {set gT}.\nImplicit Types G H K L : {group gT}.\n\n(*This definition specifies that a set is characteristic in another set if it is a subset of the second set and is invariant under all automorphisms of the second set.*)\nDefinition characteristic A B :=\n (A \\subset B) && [forall f in Aut B, f @: A \\subset A].\n\nInfix \"\\char\" := characteristic.\n\n(*This lemma provides an equivalent condition for a group to be a characteristic subgroup of another, stating that it is true if and only if the first group is a subgroup of the second and is fixed by every automorphism of the second group.*)\nLemma charP H G :\n let fixH (f : {morphism G >-> gT}) := 'injm f -> f @* G = G -> f @* H = H in\n reflect [/\\ H \\subset G & forall f, fixH f] (H \\char G).\n\n(*This lemma states that the trivial subgroup is always a characteristic subgroup of any group.*)\nLemma char1 G : 1 \\char G.\n\n(*This lemma states that any group is a characteristic subgroup of itself, demonstrating the reflexive property of the characteristic subgroup relation.*)\nLemma char_refl G : G \\char G.\n\n(*This lemma proves the transitivity of the characteristic subgroup relation, stating that if a group K is characteristic in H, and H is characteristic in G, then K is characteristic in G.*)\nLemma char_trans H G K : K \\char H -> H \\char G -> K \\char G.\n\n(*This lemma states that if a group H is a characteristic subgroup of a group G, then the normalizer of G is a subgroup of the normalizer of H.*)\nLemma char_norms H G : H \\char G -> 'N(G) \\subset 'N(H).\n\n(*This lemma states that if a set is characteristic in another set, then it must be a subset of that set.*)\nLemma char_sub A B : A \\char B -> A \\subset B.\n\n(*This lemma states that if a subgroup H is characteristic in a group G, then any subset of the normalizer of G is also a subset of the normalizer of H.*)\nLemma char_norm_trans H G A : H \\char G -> A \\subset 'N(G) -> A \\subset 'N(H).\n\n(*This lemma establishes a transitivity property for normality, stating that a characteristic subgroup of a normal subgroup is itself a normal subgroup of the larger group.*)\nLemma char_normal_trans H G K : K \\char H -> H <| G -> K <| G.\n\n(*This lemma states that any characteristic subgroup of a group is also a normal subgroup of that group.*)\nLemma char_normal H G : H \\char G -> H <| G.\n\n(*This lemma provides an alternative characterization of normality for characteristic subgroups, stating that if H is a characteristic subgroup of G, then G is contained in the normalizer of H.*)\nLemma char_norm H G : H \\char G -> G \\subset 'N(H).\n\n(*This lemma states that the intersection of two characteristic subgroups of a group is also a characteristic subgroup of that group.*)\nLemma charI G H K : H \\char G -> K \\char G -> H :&: K \\char G.\n\n(*This lemma states that for a given group, if two of its subgroups are characteristic, then the smallest subgroup containing both of them, known as their join, is also a characteristic subgroup.*)\nLemma charY G H K : H \\char G -> K \\char G -> H <*> K \\char G.\n\n(*This lemma states that if two subgroups are characteristic in a given group, then their product, defined as the set of all elements formed by multiplying an element from the first subgroup with one from the second, is also a characteristic subgroup of the given group.*)\nLemma charM G H K : H \\char G -> K \\char G -> H * K \\char G.\n\n(*This lemma states that a subgroup of a given group is characteristic if it contains every other subgroup of the given group that is isomorphic to it.*)\nLemma lone_subgroup_char G H :\n H \\subset G -> (forall K, K \\subset G -> K \\isog H -> K \\subset H) ->\n H \\char G.\n\nEnd Characteristicity.\n\nArguments characteristic _ _%_g _%_g.\n(*A notation that expresses that one group is a characteristic subgroup of another. A subgroup is characteristic if every automorphism of the parent group maps the subgroup to itself.*)\nNotation \"H \\char G\" := (characteristic H G) : group_scope.\n#[global] Hint Resolve char_refl : core.\n\nSection InjmChar.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\n\nHypothesis injf : 'injm f.\n\n(*This lemma states that an injective group morphism preserves the characteristic subgroup relationship. If a subgroup is characteristic in its parent group, and the parent group is within the domain of the morphism, then the image of the subgroup is characteristic in the image of the parent group.*)\nLemma injm_char (G H : {group aT}) :\n G \\subset D -> H \\char G -> f @* H \\char f @* G.\n\nEnd InjmChar.\n\nSection CharInjm.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\nHypothesis injf : 'injm f.\n\n(*This lemma states that an injective group morphism reflects the characteristic subgroup relationship. If the image of a subgroup is characteristic in the image of its parent group under an injective morphism, and the parent group is within the domain of the morphism, then the original subgroup is also characteristic in its parent group.*)\nLemma char_injm (G H : {group aT}) :\n G \\subset D -> H \\subset D -> (f @* H \\char f @* G) = (H \\char G).\n\nEnd CharInjm.", - "fingroup.perm": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path.\nFrom mathcomp Require Import choice fintype tuple finfun bigop finset binomial.\nFrom mathcomp Require Import fingroup morphism.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection PermDefSection.\n\nVariable T : finType.\n\n(**)\nInductive perm_type : predArgType :=\n Perm (pval : {ffun T -> T}) & injectiveb pval.\n(*This definition extracts the underlying finite function from a permutation structure.*)\nDefinition pval p := let: Perm f _ := p in f.\n(*This definition provides a type alias for the structure representing permutations on a given finite type.*)\nDefinition perm_of := perm_type.\nIdentity Coercion type_of_perm : perm_of >-> perm_type.\n\nHB.instance Definition _ := [isSub for pval].\n(*This lemma states that if a function from a finite type to itself is injective, then its finite function representation also satisfies the boolean injectivity predicate.*)\nLemma perm_proof (f : T -> T) : injective f -> injectiveb (finfun f).\n\nEnd PermDefSection.\nArguments perm_of T%_type.\n\n(*This notation represents the type of all permutations on a given finite type.*)\nNotation \"{ 'perm' T }\" := (perm_of T) (format \"{ 'perm' T }\") : type_scope.\n\nArguments pval _ _%_g.\n\nBind Scope group_scope with perm_type.\nBind Scope group_scope with perm_of.\n\n(*This notation represents the symmetric group on a given number of elements, defined as the type of permutations on the finite set of ordinals less than that number.*)\nNotation \"''S_' n\" := {perm 'I_n}\n (at level 8, n at level 2, format \"''S_' n\").\n\n(*This definition constructs a permutation from a function and a proof of its injectivity.*)\nHB.lock Definition perm T f injf := Perm (@perm_proof T f injf).\nCanonical perm_unlock := Unlockable perm.unlock.\n\n(*This definition establishes a coercion that allows a permutation to be treated as its underlying function from a finite type to itself.*)\nHB.lock Definition fun_of_perm T (u : perm_type T) : T -> T := val u.\nCanonical fun_of_perm_unlock := Unlockable fun_of_perm.unlock.\nCoercion fun_of_perm : perm_type >-> Funclass.\n\nSection Theory.\n\nVariable T : finType.\nImplicit Types (x y : T) (s t : {perm T}) (S : {set T}).\n\n(*This lemma states that two permutations are equal as group elements if and only if they are definitionally equal as permutation structures.*)\nLemma permP s t : s =1 t <-> s = t.\n\n(*This lemma states that extracting the underlying function from a permutation yields the same result as coercing the permutation to a function.*)\nLemma pvalE s : pval s = s :> (T -> T).\n\n(*This lemma states that the permutation constructed from an injective function behaves identically to the original function when applied to an element.*)\nLemma permE f f_inj : @perm T f f_inj =1 f.\n\n(*This lemma states that the function underlying any permutation is injective.*)\nLemma perm_inj {s} : injective s.\n\nHint Resolve perm_inj : core.\n\n(*This lemma states that the function underlying any permutation on a finite type is surjective, meaning its image covers the entire type.*)\nLemma perm_onto s : codom s =i predT.\n\n(*This definition provides the identity permutation, which is constructed from the identity function.*)\nDefinition perm_one := perm (@inj_id T).\n\n(*This lemma establishes that for any permutation, the function mapping an element to its unique preimage is a left inverse to the function underlying the permutation.*)\nLemma perm_invK s : cancel (fun x => iinv (perm_onto s x)) s.\n\n(*This definition constructs the inverse of a given permutation by building a new permutation from its inverse function.*)\nDefinition perm_inv s := perm (can_inj (perm_invK s)).\n\n(*This definition specifies the multiplication of two permutations as the permutation formed by the composition of their underlying functions.*)\nDefinition perm_mul s t := perm (inj_comp (@perm_inj t) (@perm_inj s)).\n\n(*This lemma states that the identity permutation acts as a left identity element with respect to permutation multiplication.*)\nLemma perm_oneP : left_id perm_one perm_mul.\n\n(*This lemma states that the inverse of a permutation acts as a left inverse with respect to permutation multiplication, resulting in the identity permutation.*)\nLemma perm_invP : left_inverse perm_one perm_inv perm_mul.\n\n(*This lemma states that permutation multiplication is an associative operation.*)\nLemma perm_mulP : associative perm_mul.\n\n(*This lemma states that the identity permutation maps any element of the underlying finite type to itself.*)\nLemma perm1 x : (1 : {perm T}) x = x.\n\n(*This lemma states that applying the product of two permutations to an element is equivalent to first applying the first permutation, and then applying the second permutation to the result.*)\nLemma permM s t x : (s * t) x = t (s x).\n\n(*This lemma states that applying the inverse of a permutation and then the original permutation to an element restores the original element.*)\nLemma permK s : cancel s s^-1.\n\n(*This lemma states that applying a permutation and then its inverse to an element restores the original element.*)\nLemma permKV s : cancel s^-1 s.\n\n(*This lemma relates the action of a conjugated permutation to the actions of the original permutations. Specifically, applying the conjugate of a permutation by another permutation to the result of the second permutation acting on an element is the same as applying the second permutation to the result of the first permutation acting on that element.*)\nLemma permJ s t x : (s ^ t) (t x) = t (s x).\n\n(*This lemma states that applying the n-th power of a permutation to an element is equivalent to iterating the permutation's underlying function n times on that element.*)\nLemma permX s x n : (s ^+ n) x = iter n s x.\n\n(*This lemma states that if an element is a fixed point of a permutation, it is also a fixed point of any natural number power of that permutation.*)\nLemma permX_fix s x n : s x = x -> (s ^+ n) x = x.\n\n(*This lemma states that the image of a set under the inverse of a permutation is equal to the preimage of that set under the original permutation.*)\nLemma im_permV s S : s^-1 @: S = s @^-1: S.\n\n(*This lemma states that the preimage of a set under the inverse of a permutation is equal to the image of that set under the original permutation.*)\nLemma preim_permV s S : s^-1 @^-1: S = s @: S.\n\n(*This definition introduces a predicate on a permutation, which holds if the set of all elements that are not fixed points of the permutation is a subset of a given set.*)\nDefinition perm_on S : pred {perm T} := fun s => [pred x | s x != x] \\subset S.\n\n(*This lemma states that if a permutation acts on a given set, then an element belongs to that set if and only if the result of applying the permutation to that element also belongs to the set.*)\nLemma perm_closed S s x : perm_on S s -> (s x \\in S) = (x \\in S).\n\n(*This lemma states that the identity permutation acts on any given set.*)\nLemma perm_on1 H : perm_on H 1.\n\n(*This lemma states that if two permutations each act on a given set, then their composition also acts on that set.*)\nLemma perm_onM H s t : perm_on H s -> perm_on H t -> perm_on H (s * t).\n\n(*This lemma states that if a permutation acts on a given set, then its inverse permutation also acts on that set.*)\nLemma perm_onV H s : perm_on H s -> perm_on H s^-1.\n\n(*This lemma states that if a permutation acts on a given set, it leaves any element outside of that set unchanged.*)\nLemma out_perm S u x : perm_on S u -> x \\notin S -> u x = x.\n\n(*This lemma states that if a permutation acts on a given set, the image of that set under the permutation is the set itself.*)\nLemma im_perm_on u S : perm_on S u -> u @: S = S.\n\n(*This lemma states that if a permutation acts on a set with at most one element, then the permutation must be the identity permutation.*)\nLemma perm_on_id u S : perm_on S u -> #|S| <= 1 -> u = 1%g.\n\n(*This lemma states that two permutations commute if they act on disjoint sets.*)\nLemma perm_onC (S1 S2 : {set T}) (u1 u2 : {perm T}) :\n perm_on S1 u1 -> perm_on S2 u2 ->\n [disjoint S1 & S2] ->\n commute u1 u2.\n\n(*This lemma states that the image of any set under the identity permutation is the original set itself.*)\nLemma imset_perm1 (S : {set T}) : [set (1 : {perm T}) x | x in S] = S.\n\n(*This lemma states that a function that swaps two given elements and leaves all other elements unchanged is an involution, meaning applying it twice restores the original input.*)\nLemma tperm_proof x y : involutive [fun z => z with x |-> y, y |-> x].\n\n(*This definition defines the transposition of two elements as the permutation that exchanges them and leaves all other elements fixed.*)\nDefinition tperm x y := perm (can_inj (tperm_proof x y)).\n\n(*This is an inductive type that specifies the behavior of a transposition of two given elements when applied to any element, breaking it down into three cases: the element is the first of the two, the second of the two, or neither.*)\nVariant tperm_spec x y z : T -> Type :=\n(**)\n | TpermFirst of z = x : tperm_spec x y z y\n(**)\n | TpermSecond of z = y : tperm_spec x y z x\n(**)\n | TpermNone of z <> x & z <> y : tperm_spec x y z z.\n\n(*This lemma provides an exhaustive case analysis for the result of applying a transposition of two elements to any given element, based on whether the given element is one of the two being transposed or not.*)\nLemma tpermP x y z : tperm_spec x y z (tperm x y z).\n\n(*This lemma states that transposing two elements maps the first element to the second.*)\nLemma tpermL x y : tperm x y x = y.\n\n(*This lemma states that transposing two elements maps the second element to the first.*)\nLemma tpermR x y : tperm x y y = x.\n\n(*This lemma states that transposing two elements leaves any other element, distinct from the two, unchanged.*)\nLemma tpermD x y z : x != z -> y != z -> tperm x y z = z.\n\n(*This lemma states that a transposition of two elements is commutative; the order of the elements does not change the resulting permutation.*)\nLemma tpermC x y : tperm x y = tperm y x.\n\n(*This lemma states that transposing an element with itself results in the identity permutation.*)\nLemma tperm1 x : tperm x x = 1.\n\n(*This lemma states that any transposition is an involution, meaning composing it with itself yields the identity permutation.*)\nLemma tpermK x y : involutive (tperm x y).\n\n(*This lemma states that the group-theoretic multiplication by a transposition is an involutive operation.*)\nLemma tpermKg x y : involutive (mulg (tperm x y)).\n\n(*This lemma states that any transposition is its own inverse.*)\nLemma tpermV x y : (tperm x y)^-1 = tperm x y.\n\n(*This lemma states that composing a transposition with itself results in the identity permutation.*)\nLemma tperm2 x y : tperm x y * tperm x y = 1.\n\n(*This lemma states that a transposition of two elements acts on the set containing exactly those two elements.*)\nLemma tperm_on x y : perm_on [set x; y] (tperm x y).\n\n(*This lemma states that the cardinality of the set of permutations on a given finite set is equal to the factorial of the cardinality of that set.*)\nLemma card_perm A : #|perm_on A| = (#|A|)`!.\n\nEnd Theory.\n\nPrenex Implicits tperm permK permKV tpermK.\nArguments perm_inj {T s} [x1 x2] eq_sx12.\n\nNotation reindex_perm s := (reindex_inj (@perm_inj _ s)).\n\n(*This lemma states that an injective function respects transpositions, meaning that applying the function to the result of a transposition operating on an element is equivalent to applying a transposition of the function's images to the image of the element.*)\nLemma inj_tperm (T T' : finType) (f : T -> T') x y z :\n injective f -> f (tperm x y z) = tperm (f x) (f y) (f z).\n\nSection tpermJ.\nVariables (T : finType).\nImplicit Types (x y z : T) (s : {perm T}).\n\n(*This lemma states that conjugating a transposition of two elements by a permutation is equivalent to the transposition of the images of those two elements under the same permutation.*)\nLemma tpermJ x y s : (tperm x y) ^ s = tperm (s x) (s y).\n\n(*This lemma states that conjugating the transposition of a first and a third element by the transposition of the first and a second element results in the transposition of the second and third elements, provided the third element is distinct from both the first and second.*)\nLemma tpermJ_tperm x y z :\n x != z -> y != z -> tperm x z ^ tperm x y = tperm y z.\n\nEnd tpermJ.\n\n(*This lemma states that a finite sequence is a permutation of a given tuple if and only if there exists a permutation of the indices that transforms the tuple into the sequence.*)\nLemma tuple_permP {T : eqType} {n} {s : seq T} {t : n.-tuple T} :\n reflect (exists p : 'S_n, s = [tuple tnth t (p i) | i < n]) (perm_eq s t).\n\n(*This definition specifies the action of a permutation on an element, which is equivalent to function application.*)\nDefinition aperm (T : finType) x (s : {perm T}) := s x.\n\nHB.lock\n(*This definition computes the orbit of an element under the action of a permutation, which is the set of all elements that can be reached from the starting element by repeatedly applying the permutation or its inverse.*)\nDefinition porbit (T : finType) (s : {perm T}) x := aperm x @: <[s]>.\nCanonical porbit_unlockable := Unlockable porbit.unlock.\n\n(*This definition establishes the set of all orbits for a given permutation acting on the elements of a finite type.*)\nDefinition porbits (T : finType) (s : {perm T}) := porbit s @: T.\n\nSection PermutationParity.\n\nVariable T : finType.\n\nImplicit Types (s t u v : {perm T}) (x y z a b : T).\n\n(*This definition provides the parity of a permutation on a finite type as a boolean value, which is true if the permutation is odd and false if it is even. The parity is calculated as the exclusive-or of the parity of the size of the type and the parity of the number of orbits of the permutation.*)\nDefinition odd_perm (s : perm_type T) := odd #|T| (+) odd #|porbits s|.\n\n(*This lemma states that an alternative syntax for applying a permutation to an element is equivalent to the direct function application of the permutation to that element.*)\nLemma apermE x s : aperm x s = s x. \n\n(*This lemma states that applying a permutation a given number of times to an element yields an element that belongs to the orbit of the original element under that permutation.*)\nLemma mem_porbit s i x : (s ^+ i) x \\in porbit s x.\n\n(*This lemma states that any element is a member of its own orbit under a given permutation.*)\nLemma porbit_id s x : x \\in porbit s x.\n\n(*This lemma states that the cardinality of the orbit of any element under a permutation is never zero.*)\nLemma card_porbit_neq0 s x : #|porbit s x| != 0.\n\n(*This lemma states that the finite sequence generated by repeatedly applying a permutation to an element for a number of times equal to the cardinality of its orbit contains only unique elements.*)\nLemma uniq_traject_porbit s x : uniq (traject s x #|porbit s x|).\n\n(*This lemma states that the set of elements in the orbit of an element under a permutation is identical to the set of elements in the finite sequence generated by applying the permutation to that element for a number of times equal to the cardinality of the orbit.*)\nLemma porbit_traject s x : porbit s x =i traject s x #|porbit s x|.\n\n(*This lemma states that applying a permutation to an element for a number of times equal to the cardinality of its orbit results in the original element.*)\nLemma iter_porbit s x : iter #|porbit s x| s x = x.\n\n(*This lemma states that the orbits of two elements under a given permutation are equal if and only if the first element is a member of the orbit of the second element.*)\nLemma eq_porbit_mem s x y : (porbit s x == porbit s y) = (x \\in porbit s y).\n\n(*This lemma states that an element belongs to the orbit of another element if and only if the second element belongs to the orbit of the first, establishing symmetry for the orbit membership relation.*)\nLemma porbit_sym s x y : (x \\in porbit s y) = (y \\in porbit s x).\n\n(*This lemma states that for any element in the orbit of a given element, its own orbit under the same permutation is identical to the orbit of the original element.*)\nLemma porbit_perm s i x : porbit s ((s ^+ i) x) = porbit s x.\n\n(*This lemma states that if an element is in the orbit of another element under a permutation, then it can be obtained by applying the permutation a number of times, where this number is strictly less than the order of the permutation.*)\nLemma porbitPmin s x y :\n y \\in porbit s x -> exists2 i, i < #[s] & y = (s ^+ i) x.\n\n(*This lemma provides a reflection between the boolean statement that an element is in the orbit of another and the logical proposition that the first element can be obtained by applying the permutation some number of times to the second element.*)\nLemma porbitP s x y :\n reflect (exists i, y = (s ^+ i) x) (y \\in porbit s x).\n\n(*This lemma states that for any given element, its orbit under the inverse of a permutation is the same as its orbit under the original permutation.*)\nLemma porbitV s : porbit s^-1 =1 porbit s.\n\n(*This lemma states that the set of all orbits for the inverse of a permutation is identical to the set of all orbits for the original permutation.*)\nLemma porbitsV s : porbits s^-1 = porbits s.\n\n(*This lemma states that the orbit of an element under a first permutation is equal as a set to its orbit under a second permutation if and only if the two orbits are definitionally equal.*)\nLemma porbit_setP s t x : porbit s x =i porbit t x <-> porbit s x = porbit t x.\n\n(*This lemma states that composing a permutation with a transposition of two distinct elements will either merge two orbits into one, decreasing the orbit count by one, or split one orbit into two, increasing the orbit count by one, depending on whether the elements were in different orbits or the same orbit, respectively.*)\nLemma porbits_mul_tperm s x y : let t := tperm x y in\n #|porbits (t * s)| + (x \\notin porbit s y).*2 = #|porbits s| + (x != y).\n\n(*This lemma states that the identity permutation is an even permutation, meaning its parity is false.*)\nLemma odd_perm1 : odd_perm 1 = false.\n\n(*This lemma states that the parity of a permutation composed with a transposition is equal to the exclusive-or of its original parity with a boolean indicating whether the two elements of the transposition are distinct.*)\nLemma odd_mul_tperm x y s : odd_perm (tperm x y * s) = (x != y) (+) odd_perm s.\n\n(*This lemma states that a transposition of two distinct elements is an odd permutation, while a transposition of an element with itself is the identity permutation, which is even.*)\nLemma odd_tperm x y : odd_perm (tperm x y) = (x != y).\n\n(*This definition specifies a predicate on pairs of elements from a type with equality. The predicate holds if and only if the first and second components of the pair are not equal to each other.*)\nDefinition dpair (eT : eqType) := [pred t | t.1 != t.2 :> eT].\nArguments dpair {eT}.\n\n(*This lemma asserts that any permutation can be expressed as a composition of a finite sequence of transpositions, where each transposition swaps two distinct elements.*)\nLemma prod_tpermP s :\n {ts : seq (T * T) | s = \\prod_(t <- ts) tperm t.1 t.2 & all dpair ts}.\n\n(*This lemma states that if a permutation is represented as a composition of a sequence of transpositions of distinct elements, then the parity of the permutation is equal to the parity of the length of that sequence.*)\nLemma odd_perm_prod ts :\n all dpair ts -> odd_perm (\\prod_(t <- ts) tperm t.1 t.2) = odd (size ts).\n\n(*This lemma establishes that the parity function is a group homomorphism from the group of permutations under composition to the boolean group under exclusive-or, meaning the parity of the composition of two permutations is the exclusive-or of their individual parities.*)\nLemma odd_permM : {morph odd_perm : s1 s2 / s1 * s2 >-> s1 (+) s2}.\n\n(*This lemma states that the parity of the inverse of a permutation is equal to the parity of the original permutation.*)\nLemma odd_permV s : odd_perm s^-1 = odd_perm s.\n\n(*This lemma states that the parity of a permutation conjugated by another permutation is equal to the parity of the original permutation.*)\nLemma odd_permJ s1 s2 : odd_perm (s1 ^ s2) = odd_perm s1.\n\n(*This lemma asserts that the subgroup generated by the set of all transpositions involving a single fixed element of a finite type is the entire symmetric group of that type, provided the type has at least two elements.*)\nLemma gen_tperm x : <<[set tperm x y | y in T]>>%g = [set: {perm T}].\n\nEnd PermutationParity.\n\nCoercion odd_perm : perm_type >-> bool.\nArguments dpair {eT}.\nPrenex Implicits porbit dpair porbits aperm.\n\nSection Symmetry.\n\nVariables (T : finType) (S : {set T}).\n\n(*This definition introduces the group of permutations on a finite type that act as the identity outside of a specified subset.*)\nDefinition Sym : {set {perm T}} := [set s | perm_on S s].\n\n(*This lemma states that the set of permutations that stabilize a given subset of a finite type forms a group.*)\nLemma Sym_group_set : group_set Sym.\n\nCanonical Sym_group : {group {perm T}} := Group Sym_group_set.\n\n(*This lemma states that the number of permutations on a finite type that fix all elements outside a given subset is equal to the factorial of the size of that subset.*)\nLemma card_Sym : #|Sym| = #|S|`!.\n\nEnd Symmetry.\n\nSection LiftPerm.\n\nVariable n : nat.\nImplicit Types i j : 'I_n.+1.\nImplicit Types s t : 'S_n.\n\n(*This lemma states that the size of the symmetric group on a finite type of size n is equal to the factorial of n.*)\nLemma card_Sn : #|'S_(n)| = n`!.\n\n(*This definition creates a function serving as the basis for a permutation on n plus one elements, constructed from a permutation on n elements. It maps a specified source element to a target element and applies the given n-element permutation to the remaining elements.*)\nDefinition lift_perm_fun i j s k :=\n if unlift i k is Some k' then lift j (s k') else j.\n\n(*This lemma establishes that the function for lifting a permutation is the left inverse of another such function where the source and target indices are swapped and the underlying permutation is inverted.*)\nLemma lift_permK i j s :\n cancel (lift_perm_fun i j s) (lift_perm_fun j i s^-1).\n\n(*This definition constructs a permutation on a finite type of size n plus one from a permutation on a type of size n, by specifying how two distinguished elements are mapped and how the original permutation acts on the rest.*)\nDefinition lift_perm i j s := perm (can_inj (lift_permK i j s)).\n\n(*This lemma states that the lifted permutation maps its first index argument to its second index argument.*)\nLemma lift_perm_id i j s : lift_perm i j s i = j.\n\n(*This lemma describes the action of a lifted permutation on an element that is not the distinguished source element, showing it is equivalent to applying the original permutation and then embedding the result back into the larger type relative to the distinguished target element.*)\nLemma lift_perm_lift i j s k' :\n lift_perm i j s (lift i k') = lift j (s k') :> 'I_n.+1.\n\n(*This lemma states that the product of two lifted permutations, where the target index of the first matches the source index of the second, is another lifted permutation whose source and target indices are the outer indices and whose underlying permutation is the product of the original two.*)\nLemma lift_permM i j k s t :\n lift_perm i j s * lift_perm j k t = lift_perm i k (s * t).\n\n(*This lemma shows that lifting the identity permutation from a smaller symmetric group to a larger one while mapping a distinguished element to itself results in the identity permutation in the larger group.*)\nLemma lift_perm1 i : lift_perm i i 1 = 1.\n\n(*This lemma states that the inverse of a lifted permutation is another lifted permutation with swapped source and target indices and an inverted underlying permutation.*)\nLemma lift_permV i j s : (lift_perm i j s)^-1 = lift_perm j i s^-1.\n\n(*This lemma provides a formula for the parity of a lifted permutation, stating it is the boolean sum of the parities of its two index arguments and the parity of the original permutation.*)\nLemma odd_lift_perm i j s : lift_perm i j s = odd i (+) odd j (+) s :> bool.\n\nEnd LiftPerm.\n\nPrenex Implicits lift_perm lift_permK.\n\n(*This lemma states that the symmetric group on zero elements has only one element, which is the identity permutation.*)\nLemma permS0 : all_equal_to (1 : 'S_0).\n\n(*This lemma asserts that the symmetric group on a single element contains only the identity permutation.*)\nLemma permS1 : all_equal_to (1 : 'S_1).\n\n(*This lemma states that for any natural number less than or equal to one, the corresponding symmetric group contains only the identity permutation.*)\nLemma permS01 n : n <= 1 -> all_equal_to (1 : 'S_n).\n\nSection CastSn.\n\n(*This definition provides a way to transport a permutation from a symmetric group of one size to another, given a proof that the sizes are equal.*)\nDefinition cast_perm m n (eq_mn : m = n) (s : 'S_m) :=\n let: erefl in _ = n := eq_mn return 'S_n in s.\n\n(*This lemma states that transporting a permutation from a symmetric group to itself using a proof of self-equality results in the original permutation.*)\nLemma cast_perm_id n eq_n s : cast_perm eq_n s = s :> 'S_n.\n\n(*This lemma demonstrates that transporting a permuted ordinal is equivalent to applying the transported permutation to the transported ordinal, showing that permutation application commutes with transport based on type equality.*)\nLemma cast_ord_permE m n eq_m_n (s : 'S_m) i :\n @cast_ord m n eq_m_n (s i) = (cast_perm eq_m_n s) (cast_ord eq_m_n i).\n\n(*This lemma provides a computational rule for applying a transported permutation to an ordinal, which involves transporting the ordinal to the original domain, applying the original permutation, and then transporting the result back to the target domain.*)\nLemma cast_permE m n (eq_m_n : m = n) (s : 'S_m) (i : 'I_n) :\n cast_perm eq_m_n s i = cast_ord eq_m_n (s (cast_ord (esym eq_m_n) i)).\n\n(*This lemma shows that composing two permutation transports is equivalent to a single transport using a proof of transitive equality.*)\nLemma cast_perm_comp m n p (eq_m_n : m = n) (eq_n_p : n = p) s :\n cast_perm eq_n_p (cast_perm eq_m_n s) = cast_perm (etrans eq_m_n eq_n_p) s.\n\n(*This lemma states that transporting a permutation to a different type and then immediately transporting it back using the symmetric equality proof yields the original permutation, establishing a left cancellation property.*)\nLemma cast_permK m n eq_m_n :\n cancel (@cast_perm m n eq_m_n) (cast_perm (esym eq_m_n)).\n\n(*This lemma states that transporting a permutation from a type to another and back establishes a right cancellation property, complementing the left cancellation property.*)\nLemma cast_permKV m n eq_m_n :\n cancel (cast_perm (esym eq_m_n)) (@cast_perm m n eq_m_n).\n\n(*This lemma provides a symmetry rule for equality involving a transported permutation, stating that if one permutation is equal to a transported version of another, then the second permutation is equal to the first transported back.*)\nLemma cast_perm_sym m n (eq_m_n : m = n) s t :\n s = cast_perm eq_m_n t -> t = cast_perm (esym eq_m_n) s.\n\n(*This lemma asserts that the function for transporting permutations between symmetric groups of proven equal size is injective.*)\nLemma cast_perm_inj m n eq_m_n : injective (@cast_perm m n eq_m_n).\n\n(*This lemma establishes that the function for transporting permutations between symmetric groups of proven equal size is a group homomorphism, meaning it preserves the group multiplication operation.*)\nLemma cast_perm_morphM m n eq_m_n :\n {morph @cast_perm m n eq_m_n : x y / x * y >-> x * y}.\n\nCanonical morph_of_cast_perm m n eq_m_n :=\n @Morphism _ _ setT (cast_perm eq_m_n) (in2W (@cast_perm_morphM m n eq_m_n)).\n\n(*This statement establishes that the function for transporting permutations between two symmetric groups whose sizes are proven to be equal is a group isomorphism.*)\nLemma isom_cast_perm m n eq_m_n : isom setT setT (@cast_perm m n eq_m_n).", - "solvable.jordanholder": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path.\nFrom mathcomp Require Import choice fintype bigop finset fingroup morphism.\nFrom mathcomp Require Import automorphism quotient action gseries.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope section_scope.\n\nImport GroupScope.\n\n(*This inductive type defines a section as a pair of groups from a given finite group type, intended to represent a quotient group.*)\nInductive section (gT : finGroupType) := GSection of {group gT} * {group gT}.\n\nDelimit Scope section_scope with sec.\nBind Scope section_scope with section.\n\n(*This definition constructs a section from two given groups within the same finite group type.*)\nDefinition mkSec (gT : finGroupType) (G1 G2 : {group gT}) := GSection (G1, G2).\n\nInfix \"/\" := mkSec : section_scope.\n\nCoercion pair_of_section gT (s : section gT) := let: GSection u := s in u.\n\nCoercion quotient_of_section gT (s : section gT) : GroupSet.sort _ := s.1 / s.2.\n\nCoercion section_group gT (s : section gT) : {group (coset_of s.2)} :=\n Eval hnf in [group of s].\n\nSection Sections.\n\nVariables (gT : finGroupType).\nImplicit Types (G : {group gT}) (s : section gT).\n\nHB.instance Definition _ := [isNew for (@pair_of_section gT)].\n(*This definition establishes a relation indicating that two sections are isomorphic, meaning their corresponding quotient groups are isomorphic.*)\nDefinition section_isog := [rel x y : section gT | x \\isog y].\n\n(*This definition selects a canonical representative from the isomorphism class of a given section.*)\nDefinition section_repr s := odflt (1 / 1)%sec (pick (section_isog ^~ s)).\n\n(*This definition computes the canonical representative of the section formed by two given groups.*)\nDefinition mksrepr G1 G2 := section_repr (mkSec G1 G2).\n\n(*This lemma states that the canonical representative of a section is isomorphic to the original section.*)\nLemma section_reprP s : section_repr s \\isog s.\n\n(*This lemma states that two isomorphic sections have the same canonical representative.*)\nLemma section_repr_isog s1 s2 :\n s1 \\isog s2 -> section_repr s1 = section_repr s2.\n\n(*This definition computes a sequence of canonical factor groups from a given group and a sequence of its subgroups, which typically forms a series.*)\nDefinition mkfactors (G : {group gT}) (s : seq {group gT}) :=\n map section_repr (pairmap (@mkSec _) G s).\n\nEnd Sections.\n\nSection CompositionSeries.\n\nVariable gT : finGroupType.\n(*This is a local notation for the type of groups over a given finite group type.*)\nLocal Notation gTg := {group gT}.\nImplicit Types (G : gTg) (s : seq gTg).\n\n(*This is a local notation for the relation where one group is a maximal normal subgroup of another.*)\nLocal Notation compo := [rel x y : {set gT} | maxnormal y x x].\n\n(*This definition specifies the property that a sequence of groups forms a composition series for a given group, requiring that the series terminates with the trivial group and that each subgroup in the sequence is a maximal normal subgroup of its predecessor.*)\nDefinition comps G s := ((last G s) == 1%G) && compo.-series G s.\n\n(*This lemma provides a boolean reflection that shows the equivalence between the computable property of being a composition series and the logical conjunction of two conditions: the series terminates at the trivial group, and it constitutes a valid path where each group is a maximal normal subgroup of the previous one.*)\nLemma compsP G s :\n reflect (last G s = 1%G /\\ path [rel x y : gTg | maxnormal y x x] G s)\n (comps G s).\n\n(*This lemma states that for a group with a given composition series, the group is trivial if and only if the sequence of subgroups in the series is empty.*)\nLemma trivg_comps G s : comps G s -> (G :==: 1) = (s == [::]).\n\n(*This lemma states that if a sequence beginning with a specific subgroup forms a composition series for a group, then the remainder of the sequence forms a composition series for that specific subgroup.*)\nLemma comps_cons G H s : comps G (H :: s) -> comps H s.\n\n(*This lemma states that for a group with a given composition series, the group is simple if and only if the composition series consists of a single element, the trivial group.*)\nLemma simple_compsP G s : comps G s -> reflect (s = [:: 1%G]) (simple G).\n\n(*This lemma asserts the existence of a composition series for any given finite group.*)\nLemma exists_comps (G : gTg) : exists s, comps G s.\n\n(*This lemma states the Jordan-H\u00f6lder theorem: for any two composition series of a given finite group, the corresponding sequences of factor groups are permutations of one another.*)\nLemma JordanHolderUniqueness (G : gTg) (s1 s2 : seq gTg) :\n comps G s1 -> comps G s2 -> perm_eq (mkfactors G s1) (mkfactors G s2).\n\nEnd CompositionSeries.\n\nSection MoreGroupAction.\n\nVariables (aT rT : finGroupType).\nVariables (A : {group aT}) (D : {group rT}).\nVariable to : groupAction A D.\n\n(*This lemma provides a boolean reflection that shows the equivalence between the computable property of a group acting on a set and the corresponding logical proposition.*)\nLemma gactsP (G : {set rT}) : reflect {acts A, on G | to} [acts A, on G | to].\n\n(*This lemma states that if a group acts on two subgroups, both of which are contained within a larger group, then it also acts on the product of these two subgroups.*)\nLemma gactsM (N1 N2 : {set rT}) :\n N1 \\subset D -> N2 \\subset D ->\n [acts A, on N1 | to] -> [acts A, on N2 | to] -> [acts A, on N1 * N2 | to].\n\n(*This lemma states that if a group acts on two sets, it also acts on the intersection of these two sets.*)\nLemma gactsI (N1 N2 : {set rT}) :\n [acts A, on N1 | to] -> [acts A, on N2 | to] -> [acts A, on N1 :&: N2 | to].\n\n(*This lemma provides a boolean reflection for membership in the set-stabilizer of a set under a group action, stating that an element belongs to the stabilizer if and only if its action preserves membership in the set.*)\nLemma gastabsP (S : {set rT}) (a : aT) :\n a \\in A -> reflect (forall x, (to x a \\in S) = (x \\in S)) (a \\in 'N(S | to)).\n\nEnd MoreGroupAction.\n\nSection MoreQuotientAction.\n\nVariables (aT rT : finGroupType).\nVariables (A : {group aT})(D : {group rT}).\nVariable to : groupAction A D.\n\n(*This lemma states that the domain of the induced action on the cosets of a subgroup is itself a subgroup of the acting group.*)\nLemma qact_dom_doms (H : {group rT}) : H \\subset D -> qact_dom to H \\subset A.\n\n(*This lemma states that if a group acts on a subgroup, then the domain of the induced action on the cosets of that subgroup is the entire acting group.*)\nLemma acts_qact_doms (H : {group rT}) :\n H \\subset D -> [acts A, on H | to] -> qact_dom to H :=: A.\n\n(*This lemma states that if an acting group stabilizes a subgroup, and the induced action on the quotient group stabilizes a subgroup of cosets, then the original acting group stabilizes the preimage of that subgroup of cosets.*)\nLemma qacts_cosetpre (H : {group rT}) (K' : {group coset_of H}) :\n H \\subset D -> [acts A, on H | to] ->\n [acts qact_dom to H, on K' | to / H] ->\n [acts A, on coset H @*^-1 K' | to].\n\n(*This lemma states that if a group acts on a second group, then the induced action on the cosets of a third group will act on the image of the second group in the quotient space.*)\nLemma qacts_coset (H K : {group rT}) :\n H \\subset D -> [acts A, on K | to] ->\n [acts qact_dom to H, on (coset H) @* K | to / H].\n\nEnd MoreQuotientAction.\n\nSection StableCompositionSeries.\n\nVariables (aT rT : finGroupType).\nVariables (D : {group rT})(A : {group aT}).\nVariable to : groupAction A D.\n\n(*This definition expresses the property that a given set is a maximal subgroup that is simultaneously a proper normal subgroup of another given group and is stable under a specific group action.*)\nDefinition maxainv (B C : {set rT}) :=\n [max C of H |\n [&& (H <| B), ~~ (B \\subset H) & [acts A, on H | to]]].\n\nSection MaxAinvProps.\n\nVariables K N : {group rT}.\n\n(*This lemma states that any group satisfying the maximal A-invariant property with respect to another group is a normal subgroup of that group.*)\nLemma maxainv_norm : maxainv K N -> N <| K.\n\n(*This lemma states that any group satisfying the maximal A-invariant property with respect to another group is a proper subgroup of that group.*)\nLemma maxainv_proper : maxainv K N -> N \\proper K.\n\n(*This lemma states that any group satisfying the maximal A-invariant property with respect to another group is a subgroup of that group.*)\nLemma maxainv_sub : maxainv K N -> N \\subset K.\n\n(*This lemma states that if a subgroup is maximal among all subgroups of a given group that are invariant under a specific group action, then this subgroup is itself invariant under that action.*)\nLemma maxainv_ainvar : maxainv K N -> A \\subset 'N(N | to).\n\n(*This lemma states that if a group is a maximal A-invariant subgroup of another group, then it is a subgroup of that group.*)\nLemma maxainvS : maxainv K N -> N \\subset K.\n\n(*This lemma states that for any non-trivial finite group, there exists a maximal subgroup within it that is invariant under a given group action.*)\nLemma maxainv_exists : K :!=: 1 -> {N : {group rT} | maxainv K N}.\n\nEnd MaxAinvProps.\n\n(*This lemma states that if two distinct groups are both maximal subgroups of a third group, and both are invariant under a given group action, then the product of these two subgroups is equal to the third group.*)\nLemma maxainvM (G H K : {group rT}) :\n H \\subset D -> K \\subset D -> maxainv G H -> maxainv G K ->\n H :<>: K -> H * K = G.\n\n(*This definition characterizes a group as A-simple if the trivial group is a maximal subgroup within it that is invariant under a given group action.*)\nDefinition asimple (K : {set rT}) := maxainv K 1.\n\nImplicit Types (H K : {group rT}) (s : seq {group rT}).\n\n(*This lemma provides an equivalent characterization of an A-simple group. It states that a group is A-simple if and only if it is non-trivial and its only normal subgroups that are invariant under a given group action are the trivial group and the group itself.*)\nLemma asimpleP K :\n reflect [/\\ K :!=: 1\n & forall H, H <| K -> [acts A, on H | to] -> H :=: 1 \\/ H :=: K]\n (asimple K).\n\n(*This definition specifies that a sequence of groups is an A-composition series for a given starting group if each group in the sequence is a maximal invariant subgroup of its predecessor under a group action, and the series terminates with the trivial group.*)\nDefinition acomps K s :=\n ((last K s) == 1%G) && path [rel x y : {group rT} | maxainv x y] K s.\n\n(*This lemma restates the definition of an A-composition series in propositional form. It asserts that a sequence of groups forms an A-composition series for a starting group if and only if the sequence terminates with the trivial group and each group in the series is a maximal invariant subgroup of the preceding group under a given action.*)\nLemma acompsP K s :\n reflect (last K s = 1%G /\\ path [rel x y : {group rT} | maxainv x y] K s)\n (acomps K s).\n\n(*This lemma states that for any A-composition series of a group, the group is trivial if and only if the corresponding sequence of subgroups is empty.*)\nLemma trivg_acomps K s : acomps K s -> (K :==: 1) = (s == [::]).\n\n(*This lemma states that if a non-empty sequence beginning with a specific group forms an A-composition series for a starting group, then the tail of the sequence, excluding the first element, forms an A-composition series for that specific group.*)\nLemma acomps_cons K H s : acomps K (H :: s) -> acomps H s.\n\n(*This lemma connects A-simple groups with their A-composition series. It states that, given an A-composition series for a group, the group is A-simple if and only if its composition series sequence consists of a single element, which is the trivial group.*)\nLemma asimple_acompsP K s : acomps K s -> reflect (s = [:: 1%G]) (asimple K).\n\n(*This lemma asserts that for any finite group, there exists at least one A-composition series.*)\nLemma exists_acomps K : exists s, acomps K s.\n\nEnd StableCompositionSeries.\n\nArguments maxainv {aT rT D%_G A%_G} to%_gact B%_g C%_g.\nArguments asimple {aT rT D%_G A%_G} to%_gact K%_g.\n\nSection StrongJordanHolder.\n\nSection AuxiliaryLemmas.\n\nVariables aT rT : finGroupType.\nVariables (A : {group aT}) (D : {group rT}) (to : groupAction A D).\n\n(*This lemma states that if a group H is a maximal A-invariant subgroup of another group G under a given action, then the corresponding quotient group of G by H is A-simple under the induced action.*)\nLemma maxainv_asimple_quo (G H : {group rT}) :\n H \\subset D -> maxainv to G H -> asimple (to / H) (G / H).\n\n(*This lemma establishes the converse relationship between maximal invariant subgroups and simple quotients. It states that if H is a normal subgroup of G that is invariant under a given action, and the quotient group of G by H is A-simple under the induced action, then H is a maximal A-invariant subgroup of G.*)\nLemma asimple_quo_maxainv (G H : {group rT}) :\n H \\subset D -> G \\subset D -> [acts A, on G | to] -> [acts A, on H | to] ->\n H <| G -> asimple (to / H) (G / H) ->\n maxainv to G H.\n\n(*This lemma is an introduction rule for A-simplicity, providing conditions on two groups that ensure their product is A-simple. The given premise is that the second group normalizes the first group.*)\nLemma asimpleI (N1 N2 : {group rT}) :\n N2 \\subset 'N(N1) -> N1 \\subset D ->\n [acts A, on N1 | to] -> [acts A, on N2 | to] ->\n asimple (to / N1) (N2 / N1) ->\n asimple (to / (N2 :&: N1)) (N2 / (N2 :&: N1)).\n\nEnd AuxiliaryLemmas.\n\nVariables (aT rT : finGroupType).\nVariables (A : {group aT}) (D : {group rT}) (to : groupAction A D).\n\n(*This theorem establishes the uniqueness of A-composition series, which is an analogue of the Jordan-H\u00f6lder theorem for groups with an operator action. It states that any two A-composition series for a given finite group have the same length, and their corresponding factor groups are isomorphic when viewed as groups with an induced action.*)\nLemma StrongJordanHolderUniqueness (G : {group rT}) (s1 s2 : seq {group rT}) :\n G \\subset D -> acomps to G s1 -> acomps to G s2 ->\n perm_eq (mkfactors G s1) (mkfactors G s2).", - "solvable.extremal": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype bigop finset prime binomial.\nFrom mathcomp Require Import fingroup morphism perm automorphism presentation.\nFrom mathcomp Require Import quotient action commutator gproduct gfunctor.\nFrom mathcomp Require Import ssralg countalg finalg zmodp cyclic pgroup center gseries.\nFrom mathcomp Require Import nilpotent sylow abelian finmodule matrix maximal.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\n(*A notation for coercing a natural number into its corresponding ring element.*)\nLocal Notation \"n %:R\" := (n %:R%R).\nImport GroupScope GRing.Theory.\n\nReserved Notation \"''Mod_' m\" (at level 8, m at level 2, format \"''Mod_' m\").\nReserved Notation \"''D_' m\" (at level 8, m at level 2, format \"''D_' m\").\nReserved Notation \"''SD_' m\" (at level 8, m at level 2, format \"''SD_' m\").\nReserved Notation \"''Q_' m\" (at level 8, m at level 2, format \"''Q_' m\").\n\nModule Extremal.\n\nSection Construction.\n\nVariables q p e : nat.\n\n(*Defines the element `a` as the canonical generator, corresponding to the number one, of a cyclic group of a given prime order.*)\nLet a : 'Z_p := Zp1.\n(*Defines the element `b` as the canonical generator, corresponding to the number one, of a cyclic group of a given order `q`.*)\nLet b : 'Z_q := Zp1.\n(*A notation that represents the cyclic subgroup generated by the element `b`.*)\nLocal Notation B := <[b]>.\n\n(*This definition specifies an automorphism on the cyclic group of order `q`. This automorphism is chosen to have an order that divides the natural number `p` and maps the group's generator to the generator raised to the power of `e`. If no such automorphism exists or if `p` is not greater than one, it defaults to the identity automorphism.*)\nDefinition aut_of :=\n odflt 1 [pick s in Aut B | p > 1 & (#[s] %| p) && (s b == b ^+ e)].\n\n(*This lemma states that the order of the automorphism `aut_of` divides the order of the element `a`.*)\nLemma aut_dvdn : #[aut_of] %| #[a].\n\n(*This definition creates a group homomorphism. The homomorphism maps elements from the cyclic group generated by `a` to the automorphism group of the cyclic group of order `q`, with the generator `a` being mapped to the automorphism `aut_of`.*)\nDefinition act_morphism := eltm_morphism aut_dvdn.\n\n(*This definition constructs a group action of the cyclic group of order `p` on the cyclic group of order `q` by composing the standard action of the automorphism group with the group homomorphism `act_morphism`.*)\nDefinition base_act := ([Aut B] \\o act_morphism)%gact.\n\n(*This lemma states that the cyclic group generated by `a` is a subgroup of the domain of the group action `base_act`.*)\nLemma act_dom : <[a]> \\subset act_dom base_act.\n\n(*This definition formalizes the group action of the cyclic group of order `p` on the cyclic group of order `q` by restricting the `base_act` action to its intended domain.*)\nDefinition gact := (base_act \\ act_dom)%gact.\n\nEnd Construction.\n\n(*This definition constructs a finite group type, parameterized by natural numbers `q`, `p`, and `e`, as the semidirect product of the cyclic group of order `q` and the cyclic group of order `p`, based on the group action `gact`.*)\nHB.lock Definition gtype q p e : finGroupType := sdprod_by (gact q p e).\nCanonical gtype_unlockable := Unlockable gtype.unlock.\n\nSection ConstructionCont.\n\nVariables q p e : nat.\n(*This definition introduces an element `a` as the canonical generator, representing the integer one, of the finite cyclic group of order `p`.*)\nLet a : 'Z_p := Zp1.\n(*This definition introduces an element `b` as the canonical generator, representing the integer one, of the finite cyclic group of order `q`.*)\nLet b : 'Z_q := Zp1.\n(*A notation for the subgroup generated by the element `b`.*)\nLocal Notation B := <[b]>.\n(*This notation refers to a generic group type constructed from three natural number parameters, representing a metacyclic group of a specific order and presentation.*)\nLocal Notation gtype := (gtype q p e) (only parsing).\n(*This notation refers to the group action associated with the generic metacyclic group type constructed from three natural number parameters.*)\nLocal Notation gact := (gact q p e) (only parsing).\n(*This notation refers to the automorphism group associated with the generic metacyclic group type constructed from three natural number parameters.*)\nLocal Notation aut_of := (aut_of q p e) (only parsing).\n\nHypotheses (p_gt1 : p > 1) (q_gt1 : q > 1).\n\n(*This lemma states that the number of elements in the generic group type is equal to the product of its two numeric parameters, p and q.*)\nLemma card : #|[set: gtype]| = (p * q)%N.\n\n(*This lemma states that the generic group type is isomorphic to a group defined by a specific two-generator presentation, provided that an automorphism with certain properties exists. This automorphism must act on a designated cyclic subgroup, have an order that divides the parameter p, and map the subgroup's generator to its e-th power.*)\nLemma Grp : (exists s, [/\\ s \\in Aut B, #[s] %| p & s b = b ^+ e]) ->\n [set: gtype] \\isog Grp (x : y : x ^+ q, y ^+ p, x ^ y = x ^+ e).\n\nEnd ConstructionCont.\n\nEnd Extremal.\n\nSection SpecializeExtremals.\n\nImport Extremal.\n\nVariable m : nat.\n(*This definition sets a natural number p to be the smallest prime divisor of a given natural number m.*)\nLet p := pdiv m.\n(*This definition sets a natural number q to be the integer quotient of a given natural number m by its smallest prime divisor.*)\nLet q := m %/ p.\n\n(*This definition specifies the modular group of order m by instantiating a generic metacyclic group construction using parameters derived from m and its smallest prime factor.*)\nDefinition modular_gtype := gtype q p (q %/ p).+1.\n(*This definition specifies a group belonging to the dihedral family by instantiating a generic group construction. The parameters are determined by a given natural number m, where the order of the cyclic part is m divided by its smallest prime factor, and the exponent is set to define the characteristic inversion of the dihedral group.*)\nDefinition dihedral_gtype := gtype q 2 q.-1.\n(*This definition specifies a group of the semidihedral family by instantiating a generic group construction. Its parameters are derived from a natural number m and its smallest prime factor p. The order of the core cyclic subgroup is m divided by p, and the exponent parameter is calculated based on a further division of this result by p.*)\nDefinition semidihedral_gtype := gtype q 2 (q %/ p).-1.\n(*This definition constructs a subgroup that serves as the kernel for building a quaternion group. It is formed within a larger generic group whose parameters are derived from a natural number m, and is defined via a quotient-like construction involving the subgroup of elements of order two and the subgroup of square elements.*)\nDefinition quaternion_kernel :=\n <<[set u | u ^+ 2 == 1] :\\: [set u ^+ 2 | u in [set: gtype q 4 q.-1]]>>.\n\nEnd SpecializeExtremals.\n\n(*This definition constructs the generalized quaternion group as a finite group type for a given parameter n. It is formed as a quotient group, by dividing an ambient group by the corresponding quaternion kernel subgroup.*)\nHB.lock Definition quaternion_gtype n : finGroupType :=\n coset_of (quaternion_kernel n).\nCanonical quaternion_unlock := Unlockable quaternion_gtype.unlock.\n\n(*This notation provides a shorthand for the modular group associated with a given natural number m. In a type context, it represents the group type itself, while in a group context, it stands for the set of all elements of that group.*)\nNotation \"''Mod_' m\" := (modular_gtype m) : type_scope.\n(*This notation defines the set of elements of the finite cyclic group of a given order, which corresponds to the set of integers modulo that order.*)\nNotation \"''Mod_' m\" := [set: gsort 'Mod_m] : group_scope.\n(*A notation for the ring of integers modulo a given natural number `m`.*)\nNotation \"''Mod_' m\" := [set: gsort 'Mod_m]%G : Group_scope.\n\n(*A notation for the dihedral group of order two times a given natural number `m`, which represents the symmetries of a regular `m`-sided polygon.*)\nNotation \"''D_' m\" := (dihedral_gtype m) : type_scope.\n(*This notation represents the type of the dihedral group of order two times a given natural number, corresponding to the symmetries of a regular polygon with that number of vertices.*)\nNotation \"''D_' m\" := [set: gsort 'D_m] : group_scope.\n(*This notation represents the set of all elements belonging to the dihedral group of order two times `m`.*)\nNotation \"''D_' m\" := [set: gsort 'D_m]%G : Group_scope.\n\n(*This notation represents the set of all elements belonging to the semidihedral group parameterized by the natural number `m`.*)\nNotation \"''SD_' m\" := (semidihedral_gtype m) : type_scope.\n(*A notation for the semidihedral group associated with a natural number parameter `m`. In `type_scope`, this notation refers to the type of elements of the semidihedral group. In `group_scope`, it represents the set of all elements of that group.*)\nNotation \"''SD_' m\" := [set: gsort 'SD_m] : group_scope.\n(*This notation represents the set of elements of the dihedral group of order two times a given natural number.*)\nNotation \"''SD_' m\" := [set: gsort 'SD_m]%G : Group_scope.\n\n(*This notation represents the set of elements of the dicyclic group of order four times a given natural number.*)\nNotation \"''Q_' m\" := (quaternion_gtype m) : type_scope.\n(*A notation for an element in the finite additive group of integers modulo the natural number m. It takes an integer value to produce the corresponding element in this group.*)\nNotation \"''Q_' m\" := [set: gsort 'Q_m] : group_scope.\n(*A notation for the generalized quaternion group, a specific family of non-abelian p-groups.*)\nNotation \"''Q_' m\" := [set: gsort 'Q_m]%G : Group_scope.\n\nSection ExtremalTheory.\n\nImplicit Types (gT : finGroupType) (p q m n : nat).\n\n(*This lemma describes the structure of the automorphism group of a non-trivial cyclic p-group. It asserts the existence of an injective ring homomorphism from the automorphism group to the ring of integers modulo the order of the group. It further details the structure of the automorphism group, including its abelian and cyclic properties, and its decomposition into subgroups, with specific characterizations that depend on whether the prime is odd or two, and on the exponent of the prime in the group's order.*)\nLemma cyclic_pgroup_Aut_structure gT p (G : {group gT}) :\n p.-group G -> cyclic G -> G :!=: 1 ->\n let q := #|G| in let n := (logn p q).-1 in\n let A := Aut G in let P := 'O_p(A) in let F := 'O_p^'(A) in\n exists m : {perm gT} -> 'Z_q,\n [/\\ [/\\ {in A & G, forall a x, x ^+ m a = a x},\n m 1 = 1%R /\\ {in A &, {morph m : a b / a * b >-> (a * b)%R}},\n {in A &, injective m} /\\ image m A =i GRing.unit,\n forall k, {in A, {morph m : a / a ^+ k >-> (a ^+ k)%R}}\n & {in A, {morph m : a / a^-1 >-> (a^-1)%R}}],\n [/\\ abelian A, cyclic F, #|F| = p.-1\n & [faithful F, on 'Ohm_1(G) | [Aut G]]]\n & if n == 0 then A = F else\n exists t, [/\\ t \\in A, #[t] = 2, m t = (- 1)%R\n & if odd p then\n [/\\ cyclic A /\\ cyclic P,\n exists s, [/\\ s \\in A, #[s] = (p ^ n)%N, m s = p.+1%:R & P = <[s]>]\n & exists s0, [/\\ s0 \\in A, #[s0] = p, m s0 = (p ^ n).+1%:R\n & 'Ohm_1(P) = <[s0]>]]\n else if n == 1%N then A = <[t]>\n else exists s,\n [/\\ s \\in A, #[s] = (2 ^ n.-1)%N, m s = 5%:R, <[s]> \\x <[t]> = A\n & exists s0, [/\\ s0 \\in A, #[s0] = 2, m s0 = (2 ^ n).+1%:R,\n m (s0 * t) = (2 ^ n).-1%:R & 'Ohm_1(<[s]>) = <[s0]>]]]].\n\n(*This definition specifies the properties of a pair of elements, called extremal generators, for a set of group elements. It requires the set to have a size equal to a prime number `p` raised to the power of a natural number `n`, the first element to be in the set and have an order of `p` to the power of `n` minus one, and the second element to be in the set but outside the cyclic subgroup generated by the first element.*)\nDefinition extremal_generators gT (A : {set gT}) p n xy :=\n let: (x, y) := xy in\n [/\\ #|A| = (p ^ n)%N, x \\in A, #[x] = (p ^ n.-1)%N & y \\in A :\\: <[x]>].\n\n(*This lemma states several properties that hold for a group given a pair of extremal generators. It asserts that if a prime number and a pair of elements satisfy the extremal generators condition for a group, then the group is a p-group, the subgroup generated by the first element is a maximal normal subgroup, the group is the product of the subgroups generated by each of the two elements, and the subgroup generated by the second element is contained in the normalizer of the subgroup generated by the first.*)\nLemma extremal_generators_facts gT (G : {group gT}) p n x y :\n prime p -> extremal_generators G p n (x, y) ->\n [/\\ p.-group G, maximal <[x]> G, <[x]> <| G,\n <[x]> * <[y]> = G & <[y]> \\subset 'N(<[x]>)].\n\nSection ModularGroup.\n\nVariables p n : nat.\n(*This definition assigns the value of a prime number p raised to the power of a natural number n.*)\nLet m := (p ^ n)%N.\n(*This definition assigns the value of a prime number p raised to the power of n minus one.*)\nLet q := (p ^ n.-1)%N.\n(*This definition assigns the value of a prime number p raised to the power of n minus two.*)\nLet r := (p ^ n.-2)%N.\n\nHypotheses (p_pr : prime p) (n_gt2 : n > 2).\n(*This lemma states that the prime number p is greater than one.*)\nLet p_gt1 := prime_gt1 p_pr.\n(*This lemma states that the prime number p is greater than zero.*)\nLet p_gt0 := ltnW p_gt1.\n(*This lemma provides an equality stating that the natural number n is equal to the sum of two and the result of subtracting two from n, under the condition that n is greater than two.*)\nLet def_n := esym (subnKC n_gt2).\n(*This lemma states that the smallest prime divisor of the number m, which is defined as p to the power of n, is equal to p itself.*)\nLet def_p : pdiv m = p. \n(*This lemma provides an equality stating that m, defined as p to the power of n, when divided by p, equals q, which is defined as p to the power of n minus one.*)\nLet def_q : m %/ p = q. \n(*This lemma provides an equality stating that q, defined as p to the power of n minus one, when divided by p, equals r, which is defined as p to the power of n minus two.*)\nLet def_r : q %/ p = r. \n(*This lemma states that q, which is defined as p to the power of n minus one, is strictly less than m, which is defined as p to the power of n.*)\nLet ltqm : q < m. \n(*This lemma states that r, which is defined as p to the power of n minus two, is strictly less than q, which is defined as p to the power of n minus one.*)\nLet ltrq : r < q. \n(*This lemma states that r, which is defined as p to the power of n minus two, is strictly greater than zero.*)\nLet r_gt0 : 0 < r. \n(*This lemma states that q, which is defined as p to the power of n minus one, is strictly greater than one.*)\nLet q_gt1 : q > 1. \n\n(*This lemma states that the cardinality of the modular group of modulus p to the power of n is equal to p to the power of n.*)\nLemma card_modular_group : #|'Mod_(p ^ n)| = (p ^ n)%N.\n\n(*This lemma states that the modular group of modulus p to the power of n is isomorphic to a group presented by two generators, say x and y, with the relations that x raised to the power q is the identity, y raised to the power p is the identity, and y acting on x by conjugation yields x raised to the power of r plus one.*)\nLemma Grp_modular_group :\n 'Mod_(p ^ n) \\isog Grp (x : y : x ^+ q, y ^+ p, x ^ y = x ^+ r.+1).\n\n(*This definition specifies properties for a pair of elements, x and y, that act as generators for a modular group. It requires that the order of the second element y is equal to the prime p, and that the conjugation of the first element x by y is equivalent to raising x to the power of r plus one.*)\nDefinition modular_group_generators gT (xy : gT * gT) :=\n let: (x, y) := xy in #[y] = p /\\ x ^ y = x ^+ r.+1.\n\n(*This lemma states that for any group that is isomorphic to the modular group of modulus p to the power of n, there exists a pair of elements that simultaneously satisfy the conditions for being extremal generators and the specific relations for modular group generators.*)\nLemma generators_modular_group gT (G : {group gT}) :\n G \\isog 'Mod_m ->\n exists2 xy, extremal_generators G p n xy & modular_group_generators xy.\n\n(*This lemma describes the internal structure of a group characterized as a modular group through its extremal and modular generators. It provides several key properties: the group is a non-abelian semidirect product of two cyclic subgroups with a specific conjugation action; it details the structure of the center, the Frattini subgroup, and the derived subgroup, including their orders and generators; it specifies the nilpotency class of the group; it characterizes the power subgroups; and finally, it describes the subgroups of elements whose order divides a power of p, with a special case for the modular group of order eight.*)\nLemma modular_group_structure gT (G : {group gT}) x y :\n extremal_generators G p n (x, y) ->\n G \\isog 'Mod_m -> modular_group_generators (x, y) ->\n let X := <[x]> in\n [/\\ [/\\ X ><| <[y]> = G, ~~ abelian G\n & {in X, forall z j, z ^ (y ^+ j) = z ^+ (j * r).+1}],\n [/\\ 'Z(G) = <[x ^+ p]>, 'Phi(G) = 'Z(G) & #|'Z(G)| = r],\n [/\\ G^`(1) = <[x ^+ r]>, #|G^`(1)| = p & nil_class G = 2],\n forall k, k > 0 -> 'Mho^k(G) = <[x ^+ (p ^ k)]>\n & if (p, n) == (2, 3) then 'Ohm_1(G) = G else\n forall k, 0 < k < n.-1 ->\n <[x ^+ (p ^ (n - k.+1))]> \\x <[y]> = 'Ohm_k(G)\n /\\ #|'Ohm_k(G)| = (p ^ k.+1)%N].\n\nEnd ModularGroup.\n\nSection DihedralGroup.\n\nVariable q : nat.\nHypothesis q_gt1 : q > 1.\n(*This definition specifies the natural number `m` as two raised to the power of a natural number `n`.*)\nLet m := q.*2.\n\n(*This definition asserts that the smallest prime divisor of a natural number parameter `m` is equal to two.*)\nLet def2 : pdiv m = 2.\n\n(*This definition asserts that a natural number `q` is equal to the quotient of a natural number `m` divided by its smallest prime divisor.*)\nLet def_q : m %/ pdiv m = q. \n\nSection Dihedral_extension.\n\nVariable p : nat.\nHypotheses (p_gt1 : p > 1) (even_p : 2 %| p).\n(*This notation defines `ED` as an abbreviation for a set constructed from an extremal group type, which is parameterized by the natural numbers `q`, `p`, and `q` minus one.*)\nLocal Notation ED := [set: gsort (Extremal.gtype q p q.-1)].\n\n(*This lemma states that the cardinality of the set `ED` is equal to the product of a natural number parameter `m` and half of a natural number parameter `p`.*)\nLemma card_ext_dihedral : #|ED| = (p./2 * m)%N.\n\n(*This lemma states that the group `ED` is isomorphic to a group presented by two generators, say `x` and `y`. The order of `x` is the natural number parameter `q`, the order of `y` is the natural number parameter `p`, and the conjugation of `x` by `y` yields the inverse of `x`.*)\nLemma Grp_ext_dihedral : ED \\isog Grp (x : y : x ^+ q, y ^+ p, x ^ y = x^-1).\n\nEnd Dihedral_extension.\n\n(*This lemma states that the cardinality of the dihedral group of index `m` is equal to the natural number `m`.*)\nLemma card_dihedral : #|'D_m| = m.\n\n(*This lemma states that the dihedral group of index `m` is isomorphic to a group presented by two generators. The first generator has order equal to `m` divided by two, the second generator has order two, and the conjugation of the first generator by the second yields the inverse of the first.*)\nLemma Grp_dihedral : 'D_m \\isog Grp (x : y : x ^+ q, y ^+ 2, x ^ y = x^-1).\n\n(*This lemma states that the dihedral group of index `m` is isomorphic to a group generated by two distinct elements of order two, whose product has order equal to `m` divided by two.*)\nLemma Grp'_dihedral : 'D_m \\isog Grp (x : y : x ^+ 2, y ^+ 2, (x * y) ^+ q).\n\nEnd DihedralGroup.\n\n(*This lemma states that for any group, the subgroup generated by two distinct elements of order two is isomorphic to the dihedral group whose index is the order of that subgroup.*)\nLemma involutions_gen_dihedral gT (x y : gT) :\n let G := <<[set x; y]>> in\n #[x] = 2 -> #[y] = 2 -> x != y -> G \\isog 'D_#|G|.\n\n(*This lemma states that for any natural number `n` greater than one, the dihedral group of index two to the power of `n` is isomorphic to a group presented by two generators. The first generator has order two to the power of `n` minus one, and the second generator has order two. The conjugation of the first by the second yields the inverse of the first.*)\nLemma Grp_2dihedral n : n > 1 ->\n 'D_(2 ^ n) \\isog Grp (x : y : x ^+ (2 ^ n.-1), y ^+ 2, x ^ y = x^-1).\n\n(*This lemma states that for any natural number `n` greater than one, the cardinality of the dihedral group of index two to the power of `n` is equal to two to the power of `n`.*)\nLemma card_2dihedral n : n > 1 -> #|'D_(2 ^ n)| = (2 ^ n)%N.\n\n(*This lemma states that for any natural number `n` greater than three, the cardinality of the semidihedral group of index two to the power of `n` is equal to two to the power of `n`.*)\nLemma card_semidihedral n : n > 3 -> #|'SD_(2 ^ n)| = (2 ^ n)%N.\n\n(*This lemma states that for any natural number `n` greater than three, the semidihedral group of index two to the power of `n` is isomorphic to a group presented by two generators. The first generator has an order of two to the power of `n` minus one, and the second has an order of two. The conjugation of the first generator by the second is equivalent to the first generator raised to the power of the quantity two to the power of `n` minus two, minus one.*)\nLemma Grp_semidihedral n : n > 3 ->\n 'SD_(2 ^ n) \\isog\n Grp (x : y : x ^+ (2 ^ n.-1), y ^+ 2, x ^ y = x ^+ (2 ^ n.-2).-1).\n\nSection Quaternion.\n\nVariable n : nat.\nHypothesis n_gt2 : n > 2.\n(*Defines the natural number `m` as two raised to the power of a natural number `n`, which typically represents the order of a finite 2-group.*)\nLet m := (2 ^ n)%N.\n(*Defines the natural number `q` as two raised to the power of `n` minus one, which often represents the order of a maximal cyclic subgroup within a 2-group of order two to the power of `n`.*)\nLet q := (2 ^ n.-1)%N.\n(*Defines the natural number `r` as two raised to the power of `n` minus two, a value that appears in the defining algebraic relations for some types of extremal 2-groups.*)\nLet r := (2 ^ n.-2)%N.\n(*This definition introduces a proposition asserting that the quaternion group `'Q_m` is isomorphic to a group defined by a presentation with two generators. The relations specify that the first generator raised to the power `q` is the identity, the second generator squared is equal to the first generator raised to the power `r`, and conjugating the first generator by the second results in its inverse.*)\nLet GrpQ := 'Q_m \\isog Grp (x : y : x ^+ q, y ^+ 2 = x ^+ r, x ^ y = x^-1).\n(*This definition introduces a proposition asserting two conjoined properties of the quaternion group `'Q_m`: that its cardinality equals the natural number `m`, and that it is isomorphic to a group presented by two generators with relations specifying that the first generator to the power of `q` is identity, the second generator squared equals the first to the power of `r`, and the second generator conjugates the first to its inverse.*)\nLet defQ : #|'Q_m| = m /\\ GrpQ.\n\n(*This lemma states that the cardinality of the quaternion group `'Q_m` is equal to the natural number `m`.*)\nLemma card_quaternion : #|'Q_m| = m. \n(*This lemma states that the quaternion group `'Q_m` is isomorphic to a group given by a presentation with two generators. The relations specify that the first generator raised to the power `q` is identity, the second generator squared equals the first generator raised to the power `r`, and conjugating the first generator by the second yields its inverse.*)\nLemma Grp_quaternion : GrpQ. \n\nEnd Quaternion.\n\n(*This lemma asserts the equality between two groups, denoted `'Mod_8` and `'D_8`.*)\nLemma eq_Mod8_D8 : 'Mod_8 = 'D_8. \n\nSection ExtremalStructure.\n\nVariables (gT : finGroupType) (G : {group gT}) (n : nat).\nImplicit Type H : {group gT}.\n\n(*This definition introduces `m` as the natural number resulting from raising two to the power of a natural number `n`.*)\nLet m := (2 ^ n)%N.\n(*This definition introduces `q` as the natural number resulting from raising two to the power of the natural number `n` minus one.*)\nLet q := (2 ^ n.-1)%N.\n(*This lemma asserts that the natural number `q` is strictly greater than zero.*)\nLet q_gt0: q > 0. \n(*This definition introduces `r` as the natural number resulting from raising two to the power of the natural number `n` minus two.*)\nLet r := (2 ^ n.-2)%N.\n(*This lemma asserts that the natural number `r` is strictly greater than zero.*)\nLet r_gt0: r > 0. \n\n(*This lemma states that, provided a natural number `n` is greater than one, a set of relationships holds between the natural numbers `m`, `q`, and `r`: twice `q` is equal to `m`, twice `r` is equal to `q`, `q` is strictly less than `m`, and `r` is strictly less than `q`.*)\nLet def2qr : n > 1 -> [/\\ 2 * q = m, 2 * r = q, q < m & r < q]%N.\n\n(*This lemma states that for any group isomorphic to a dihedral 2-group of order `m`, where the exponent `n` is greater than one, there exist two group elements, `x` and `y`, that are extremal generators. Furthermore, the order of element `y` is two, and the conjugation of `x` by `y` results in the inverse of `x`.*)\nLemma generators_2dihedral :\n n > 1 -> G \\isog 'D_m ->\n exists2 xy, extremal_generators G 2 n xy\n & let: (x, y) := xy in #[y] = 2 /\\ x ^ y = x^-1.\n\n(*This lemma states that for any group isomorphic to a semidihedral 2-group of order `m`, where the exponent `n` is greater than three, there exist two group elements, `x` and `y`, that are extremal generators. Additionally, the order of element `y` is two, and the conjugation of `x` by `y` results in `x` raised to the power of the natural number `r` minus one.*)\nLemma generators_semidihedral :\n n > 3 -> G \\isog 'SD_m ->\n exists2 xy, extremal_generators G 2 n xy\n & let: (x, y) := xy in #[y] = 2 /\\ x ^ y = x ^+ r.-1.\n\n(*This lemma states that for any group isomorphic to a generalized quaternion 2-group of order `m`, where the exponent `n` is greater than two, there exist two group elements, `x` and `y`, that are extremal generators. Moreover, the order of element `y` is four, the square of `y` is equal to `x` raised to the power of the natural number `r`, and the conjugation of `x` by `y` results in the inverse of `x`.*)\nLemma generators_quaternion :\n n > 2 -> G \\isog 'Q_m ->\n exists2 xy, extremal_generators G 2 n xy\n & let: (x, y) := xy in [/\\ #[y] = 4, y ^+ 2 = x ^+ r & x ^ y = x^-1].\n\nVariables x y : gT.\nImplicit Type M : {group gT}.\n\n(*This definition specifies `X` as the cyclic subgroup generated by a group element `x`.*)\nLet X := <[x]>.\n(*This definition specifies `Y` as the cyclic subgroup generated by a group element `y`.*)\nLet Y := <[y]>.\n(*This definition specifies `yG` as the set of all elements in a group `G` that are conjugate to a group element `y`.*)\nLet yG := y ^: G.\n(*This definition specifies `xyG` as the set of all elements in a group `G` that are conjugate to the product of two group elements `x` and `y`.*)\nLet xyG := (x * y) ^: G.\n(*This definition specifies `My` as the normal subgroup generated by the set of all elements conjugate to a group element `y`.*)\nLet My := <>.\n(*This definition specifies `Mxy` as the normal subgroup generated by the set of all elements conjugate to the product of two group elements `x` and `y`.*)\nLet Mxy := <>.\n\n(*This theorem provides a detailed structural analysis of a group `G` that is isomorphic to a dihedral 2-group and is defined by a pair of extremal generators `x` and `y`. It asserts that the group is a semidirect product of the cyclic subgroups generated by `x` and `y`, that all elements outside the cyclic subgroup `X` have order two, and that elements of `X` are inverted by conjugation by elements outside `X`. It also characterizes the commutator subgroup, the Frattini subgroup, the nilpotency class, and the subgroups formed by elements of a specific order or by p-th powers. Furthermore, it partitions the complement of the subgroup `X` into two disjoint conjugacy classes, identifies all maximal subgroups, and, for `n` greater than two, specifies the center of the group, the structure of certain normal subgroups, and the uniqueness of the cyclic subgroup of index two.*)\nTheorem dihedral2_structure :\n n > 1 -> extremal_generators G 2 n (x, y) -> G \\isog 'D_m ->\n [/\\ [/\\ X ><| Y = G, {in G :\\: X, forall t, #[t] = 2}\n & {in X & G :\\: X, forall z t, z ^ t = z^-1}],\n [/\\ G ^`(1) = <[x ^+ 2]>, 'Phi(G) = G ^`(1), #|G^`(1)| = r\n & nil_class G = n.-1],\n 'Ohm_1(G) = G /\\ (forall k, k > 0 -> 'Mho^k(G) = <[x ^+ (2 ^ k)]>),\n [/\\ yG :|: xyG = G :\\: X, [disjoint yG & xyG]\n & forall M, maximal M G = pred3 X My Mxy M]\n & if n == 2 then (2.-abelem G : Prop) else\n [/\\ 'Z(G) = <[x ^+ r]>, #|'Z(G)| = 2,\n My \\isog 'D_q, Mxy \\isog 'D_q\n & forall U, cyclic U -> U \\subset G -> #|G : U| = 2 -> U = X]].\n\n(*This theorem describes the structure of a group `G` that is isomorphic to a generalized quaternion group and is given by a pair of extremal generators `x` and `y`. It states that `G` is the central product of the cyclic subgroups generated by `x` and `y`, that all elements outside the cyclic subgroup `X` have order four, and that elements of `X` are inverted by conjugation by elements outside `X`. It also identifies the commutator subgroup, the Frattini subgroup, the nilpotency class, the center of the group, and the unique element of order two. Additionally, it characterizes the subgroups formed by elements of specific orders and by p-th powers, partitions the complement of `X` into two conjugacy classes, and identifies all maximal subgroups. For `n` greater than three, it further describes the structure of certain normal subgroups and establishes the uniqueness of the cyclic subgroup of index two.*)\nTheorem quaternion_structure :\n n > 2 -> extremal_generators G 2 n (x, y) -> G \\isog 'Q_m ->\n [/\\ [/\\ pprod X Y = G, {in G :\\: X, forall t, #[t] = 4}\n & {in X & G :\\: X, forall z t, z ^ t = z^-1}],\n [/\\ G ^`(1) = <[x ^+ 2]>, 'Phi(G) = G ^`(1), #|G^`(1)| = r\n & nil_class G = n.-1],\n [/\\ 'Z(G) = <[x ^+ r]>, #|'Z(G)| = 2,\n forall u, u \\in G -> #[u] = 2 -> u = x ^+ r,\n 'Ohm_1(G) = <[x ^+ r]> /\\ 'Ohm_2(G) = G\n & forall k, k > 0 -> 'Mho^k(G) = <[x ^+ (2 ^ k)]>],\n [/\\ yG :|: xyG = G :\\: X /\\ [disjoint yG & xyG]\n & forall M, maximal M G = pred3 X My Mxy M]\n & n > 3 ->\n [/\\ My \\isog 'Q_q, Mxy \\isog 'Q_q\n & forall U, cyclic U -> U \\subset G -> #|G : U| = 2 -> U = X]].\n\n(*This theorem details the structure of a group `G` that is isomorphic to a semidihedral 2-group, is defined by a pair of extremal generators `x` and `y`, and where `y` has order two. It asserts that `G` is a semidirect product of the cyclic subgroups generated by `x` and `y`, the product of `x` and `y` has order four, and elements in the subgroup `X` are conjugated to their `r` minus one power by elements outside `X`. It also specifies the commutator subgroup, the Frattini subgroup, and the nilpotency class. Furthermore, the theorem identifies the group's center, characterizes subgroups of elements with specific orders and those formed by p-th powers, partitions the complement of `X` into disjoint conjugacy classes, and identifies all maximal subgroups. Finally, it describes the structure of certain normal subgroups and establishes the uniqueness of the cyclic subgroup of index two.*)\nTheorem semidihedral_structure :\n n > 3 -> extremal_generators G 2 n (x, y) -> G \\isog 'SD_m -> #[y] = 2 ->\n [/\\ [/\\ X ><| Y = G, #[x * y] = 4\n & {in X & G :\\: X, forall z t, z ^ t = z ^+ r.-1}],\n [/\\ G ^`(1) = <[x ^+ 2]>, 'Phi(G) = G ^`(1), #|G^`(1)| = r\n & nil_class G = n.-1],\n [/\\ 'Z(G) = <[x ^+ r]>, #|'Z(G)| = 2,\n 'Ohm_1(G) = My /\\ 'Ohm_2(G) = G\n & forall k, k > 0 -> 'Mho^k(G) = <[x ^+ (2 ^ k)]>],\n [/\\ yG :|: xyG = G :\\: X /\\ [disjoint yG & xyG]\n & forall H, maximal H G = pred3 X My Mxy H]\n & [/\\ My \\isog 'D_q, Mxy \\isog 'Q_q\n & forall U, cyclic U -> U \\subset G -> #|G : U| = 2 -> U = X]].\n\nEnd ExtremalStructure.\n\nSection ExtremalClass.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This inductive type defines a set of categories for classifying certain finite groups, known as extremal groups. These categories include modular, dihedral, semi-dihedral, and quaternion groups, along with a category for groups that are not extremal.*)\nInductive extremal_group_type :=\n ModularGroup | Dihedral | SemiDihedral | Quaternion | NotExtremal.\n\n(*This definition assigns a unique natural number index to each category of extremal group. It maps ModularGroup to 0, Dihedral to 1, SemiDihedral to 2, Quaternion to 3, and NotExtremal to 4.*)\nDefinition index_extremal_group_type c : nat :=\n match c with\n | ModularGroup => 0\n | Dihedral => 1\n | SemiDihedral => 2\n | Quaternion => 3\n | NotExtremal => 4\n end.\n\n(*This definition provides a finite sequence containing the specific classifications for extremal groups: ModularGroup, Dihedral, SemiDihedral, and Quaternion.*)\nDefinition enum_extremal_groups :=\n [:: ModularGroup; Dihedral; SemiDihedral; Quaternion].\n\n(*This lemma states that the function mapping an extremal group type to its natural number index and the function mapping a natural number index back to an extremal group type are inverse operations of each other, establishing a bijection.*)\nLemma cancel_index_extremal_groups :\n cancel index_extremal_group_type (nth NotExtremal enum_extremal_groups).\n\n(*This notation provides a local shorthand for the proof establishing the bijective correspondence between extremal group types and their numerical indices.*)\nLocal Notation extgK := cancel_index_extremal_groups.\n\n#[export]\n(*This lemma states that the natural number representation of any given extremal group type is strictly less than six.*)\nLemma bound_extremal_groups (c : extremal_group_type) : pickle c < 6.\n\n(*This definition classifies a given finite group by determining if it is isomorphic to a specific known family of groups. It checks, in order, if the group is a dihedral group, a quaternion group, a semi-dihedral group, or a modular group meeting certain size constraints, and returns the corresponding classification. If the group does not match any of these families, it is classified as not extremal.*)\nDefinition extremal_class (A : {set gT}) :=\n let m := #|A| in let p := pdiv m in let n := logn p m in\n if (n > 1) && (A \\isog 'D_(2 ^ n)) then Dihedral else\n if (n > 2) && (A \\isog 'Q_(2 ^ n)) then Quaternion else\n if (n > 3) && (A \\isog 'SD_(2 ^ n)) then SemiDihedral else\n if (n > 2) && (A \\isog 'Mod_(p ^ n)) then ModularGroup else\n NotExtremal.\n\n(*This definition provides a boolean predicate that is true if a given finite group is classifiable as an extremal 2-group of dihedral, quaternion, or semi-dihedral type.*)\nDefinition extremal2 A := extremal_class A \\in behead enum_extremal_groups.\n\n(*This lemma states that a finite group has the extremal classification 'Dihedral' if and only if it is isomorphic to a dihedral group of order two to the power of some natural number n, where n is strictly greater than one.*)\nLemma dihedral_classP :\n extremal_class G = Dihedral <-> (exists2 n, n > 1 & G \\isog 'D_(2 ^ n)).\n\n(*This lemma states that a finite group has the extremal classification 'Quaternion' if and only if it is isomorphic to a quaternion group of order two to the power of some natural number n, where n is strictly greater than two.*)\nLemma quaternion_classP :\n extremal_class G = Quaternion <-> (exists2 n, n > 2 & G \\isog 'Q_(2 ^ n)).\n\n(*This lemma states that a finite group has the extremal classification 'SemiDihedral' if and only if it is isomorphic to a semi-dihedral group of order two to the power of some natural number n, where n is strictly greater than three.*)\nLemma semidihedral_classP :\n extremal_class G = SemiDihedral <-> (exists2 n, n > 3 & G \\isog 'SD_(2 ^ n)).\n\n(*This lemma states that any finite group with an odd number of elements will not be classified as an extremal 2-group of dihedral, quaternion, or semi-dihedral type.*)\nLemma odd_not_extremal2 : odd #|G| -> ~~ extremal2 G.\n\n(*This lemma states that a finite group has the extremal classification 'ModularGroup' if and only if it is isomorphic to a modular p-group of order p to the power of n, for some prime number p and some natural number n. The value of n must be at least three if p is an odd prime, and at least four if p is two.*)\nLemma modular_group_classP :\n extremal_class G = ModularGroup\n <-> (exists2 p, prime p &\n exists2 n, n >= (p == 2) + 3 & G \\isog 'Mod_(p ^ n)).\n\nEnd ExtremalClass.\n\n(*This theorem provides a comprehensive structural description of finite 2-groups that are classified as dihedral, quaternion, or semi-dihedral. Assuming such a group is generated by two specific elements under certain conditions, the theorem details numerous properties, including how the group decomposes with respect to its generators, the orders of its elements, the structure of its key characteristic subgroups like the center and commutator subgroup, its nilpotency class, and the nature of its maximal subgroups. The specific properties often depend on whether the group is dihedral, quaternion, or semi-dihedral.*)\nTheorem extremal2_structure (gT : finGroupType) (G : {group gT}) n x y :\n let cG := extremal_class G in\n let m := (2 ^ n)%N in let q := (2 ^ n.-1)%N in let r := (2 ^ n.-2)%N in\n let X := <[x]> in let yG := y ^: G in let xyG := (x * y) ^: G in\n let My := <> in let Mxy := <> in\n extremal_generators G 2 n (x, y) ->\n extremal2 G -> (cG == SemiDihedral) ==> (#[y] == 2) ->\n [/\\ [/\\ (if cG == Quaternion then pprod X <[y]> else X ><| <[y]>) = G,\n if cG == SemiDihedral then #[x * y] = 4 else\n {in G :\\: X, forall z, #[z] = (if cG == Dihedral then 2 else 4)},\n if cG != Quaternion then True else\n {in G, forall z, #[z] = 2 -> z = x ^+ r}\n & {in X & G :\\: X, forall t z,\n t ^ z = (if cG == SemiDihedral then t ^+ r.-1 else t^-1)}],\n [/\\ G ^`(1) = <[x ^+ 2]>, 'Phi(G) = G ^`(1), #|G^`(1)| = r\n & nil_class G = n.-1],\n [/\\ if n > 2 then 'Z(G) = <[x ^+ r]> /\\ #|'Z(G)| = 2 else 2.-abelem G,\n 'Ohm_1(G) = (if cG == Quaternion then <[x ^+ r]> else\n if cG == SemiDihedral then My else G),\n 'Ohm_2(G) = G\n & forall k, k > 0 -> 'Mho^k(G) = <[x ^+ (2 ^ k)]>],\n [/\\ yG :|: xyG = G :\\: X, [disjoint yG & xyG]\n & forall H : {group gT}, maximal H G = (gval H \\in pred3 X My Mxy)]\n & if n <= (cG == Quaternion) + 2 then True else\n [/\\ forall U, cyclic U -> U \\subset G -> #|G : U| = 2 -> U = X,\n if cG == Quaternion then My \\isog 'Q_q else My \\isog 'D_q,\n extremal_class My = (if cG == Quaternion then cG else Dihedral),\n if cG == Dihedral then Mxy \\isog 'D_q else Mxy \\isog 'Q_q\n & extremal_class Mxy = (if cG == Dihedral then cG else Quaternion)]].\n\n(*This lemma states that if a non-abelian finite p-group contains a cyclic subgroup whose index in the group is equal to the prime p, then the group must be an extremal group. Specifically, the group is either classified as a modular group, or p must be two and the group is classified as a dihedral, quaternion, or semi-dihedral group.*)\nLemma maximal_cycle_extremal gT p (G X : {group gT}) :\n p.-group G -> ~~ abelian G -> cyclic X -> X \\subset G -> #|G : X| = p ->\n (extremal_class G == ModularGroup) || (p == 2) && extremal2 G.\n\n(*This lemma states that for any non-abelian p-group containing a cyclic subnormal component, one of two structural properties must hold. The first possibility is that the prime number is two, the group is an extremal 2-group, and the index of the subnormal component in the group is two. The second possibility is the existence of a specific subgroup, defined as the centralizer of the subgroup of all p-th powers of elements from the subnormal component. This subgroup must have an index equal to the prime over the subnormal component, must be of modular extremal class, and its own subgroup generated by elements of prime order must be an elementary abelian p-subgroup of rank two that is also characteristic in the larger group.*)\nLemma cyclic_SCN gT p (G U : {group gT}) :\n p.-group G -> U \\in 'SCN(G) -> ~~ abelian G -> cyclic U ->\n [/\\ p = 2, #|G : U| = 2 & extremal2 G]\n\\/ exists M : {group gT},\n [/\\ M :=: 'C_G('Mho^1(U)), #|M : U| = p, extremal_class M = ModularGroup,\n 'Ohm_1(M)%G \\in 'E_p^2(G) & 'Ohm_1(M) \\char G].\n\n(*This lemma states that a p-group in which every normal abelian subgroup is cyclic must itself be cyclic, or it must be a specific kind of 2-group. The latter case applies only if the prime is two, and the group is either an extremal 2-group with an order of at least sixteen, or it is isomorphic to the quaternion group of order eight.*)\nLemma normal_rank1_structure gT p (G : {group gT}) :\n p.-group G -> (forall X : {group gT}, X <| G -> abelian X -> cyclic X) ->\n cyclic G \\/ [&& p == 2, extremal2 G & (#|G| >= 16) || (G \\isog 'Q_8)].\n\n(*This lemma states that for a p-group of odd order, being cyclic is equivalent to its p-rank being at most one.*)\nLemma odd_pgroup_rank1_cyclic gT p (G : {group gT}) :\n p.-group G -> odd #|G| -> cyclic G = ('r_p(G) <= 1).\n\n(*This lemma establishes an equivalence for a non-trivial p-group. It states that the order of the subgroup generated by elements of order p is equal to the prime p, if and only if one of two conditions holds: either the group is cyclic, or the prime is two and the group's extremal class is Quaternion.*)\nLemma prime_Ohm1P gT p (G : {group gT}) :\n p.-group G -> G :!=: 1 ->\n reflect (#|'Ohm_1(G)| = p)\n (cyclic G || (p == 2) && (extremal_class G == Quaternion)).\n\n(*This theorem states that any non-abelian p-group in which every characteristic abelian subgroup is cyclic has a center with specific properties. Specifically, the center of the group has an index equal to the prime squared. Furthermore, if the prime is two, then the square of every element of the group is contained within its center.*)\nTheorem symplectic_type_group_structure gT p (G : {group gT}) :\n p.-group G -> (forall X : {group gT}, X \\char G -> abelian X -> cyclic X) ->\n exists2 E : {group gT}, E :=: 1 \\/ extraspecial E\n & exists R : {group gT},\n [/\\ cyclic R \\/ [/\\ p = 2, extremal2 R & #|R| >= 16],\n E \\* R = G\n & E :&: R = 'Z(E)].", - "solvable.frobenius": "From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat div.\nFrom mathcomp Require Import fintype bigop prime finset fingroup morphism.\nFrom mathcomp Require Import perm action quotient gproduct cyclic center.\nFrom mathcomp Require Import pgroup nilpotent sylow hall abelian.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection Definitions.\n\nVariable gT : finGroupType.\nImplicit Types A G K H L : {set gT}.\n\n(*This definition states that a first group acts semiregularly on a second group if for every non-identity element in the second group, its centralizer in the first group is the trivial group.*)\nDefinition semiregular K H := {in H^#, forall x, 'C_K[x] = 1}.\n\n(*This definition states that a first group and a second group are semiprime to each other if for every non-identity element in the second group, its centralizer in the first group is equal to the centralizer of the entire second group in the first group.*)\nDefinition semiprime K H := {in H^#, forall x, 'C_K[x] = 'C_K(H)}.\n\n(*This definition specifies a property for a set of group elements within a group. It holds if the set is non-empty, intersects trivially with all of its distinct conjugates in the group, and the normalizer of the set in the group is a specific given group.*)\nDefinition normedTI A G L := [&& A != set0, trivIset (A :^: G) & 'N_G(A) == L].\n\n(*This definition characterizes a group as a Frobenius group with a specific complement. This holds if the complement is a proper subgroup and the set of its non-identity elements is a non-empty trivial intersection set in the group whose normalizer is the complement itself.*)\nDefinition Frobenius_group_with_complement G H := (H != G) && normedTI H^# G H.\n\n(*This definition classifies a group as a Frobenius group if there exists a subgroup that serves as its Frobenius complement.*)\nDefinition Frobenius_group G :=\n [exists H : {group gT}, Frobenius_group_with_complement G H].\n\n(*This definition characterizes a group as a Frobenius group with a specific kernel and complement. This is true if the group is the semidirect product of the normal kernel subgroup and the complement subgroup, and the group is also a Frobenius group with that complement.*)\nDefinition Frobenius_group_with_kernel_and_complement G K H :=\n (K ><| H == G) && Frobenius_group_with_complement G H.\n\n(*This definition classifies a group as a Frobenius group with a specific kernel if there exists a complement subgroup such that the group is the semidirect product of the kernel and the complement, and that complement is a Frobenius complement of the group.*)\nDefinition Frobenius_group_with_kernel G K :=\n [exists H : {group gT}, Frobenius_group_with_kernel_and_complement G K H].\n\nSection FrobeniusAction.\n\nVariables G H : {set gT}.\nVariables (sT : finType) (S : {set sT}) (to : {action gT &-> sT}).\n\n(*This definition specifies the properties of a Frobenius action of a group on a set. The action must be faithful and transitive, every non-identity element of the group must fix at most one element of the set, and there must exist a non-trivial subgroup that is the stabilizer of some element in the set.*)\nDefinition Frobenius_action :=\n [/\\ [faithful G, on S | to],\n [transitive G, on S | to],\n {in G^#, forall x, #|'Fix_(S | to)[x]| <= 1},\n H != 1\n & exists2 u, u \\in S & H = 'C_G[u | to]].\n\nEnd FrobeniusAction.\n\n(*This proposition asserts that a group has a Frobenius action with a point-stabilizer subgroup. This is true if there exist a set and a corresponding group action that satisfy the conditions for being a Frobenius action.*)\nVariant has_Frobenius_action G H : Prop :=\n hasFrobeniusAction sT S to of @Frobenius_action G H sT S to.\n\nEnd Definitions.\n\nArguments semiregular {gT} K%_g H%_g.\nArguments semiprime {gT} K%_g H%_g.\nArguments normedTI {gT} A%_g G%_g L%_g.\nArguments Frobenius_group_with_complement {gT} G%_g H%_g.\nArguments Frobenius_group {gT} G%_g.\nArguments Frobenius_group_with_kernel {gT} G%_g K%_g.\nArguments Frobenius_group_with_kernel_and_complement {gT} G%_g K%_g H%_g.\nArguments Frobenius_action {gT} G%_g H%_g {sT} S%_g to%_act.\nArguments has_Frobenius_action {gT} G%_g H%_g.\n\n(*This notation provides syntax for expressing that a group G is a Frobenius group with H as its Frobenius complement.*)\nNotation \"[ 'Frobenius' G 'with' 'complement' H ]\" :=\n (Frobenius_group_with_complement G H)\n (G at level 50, H at level 35,\n format \"[ 'Frobenius' G 'with' 'complement' H ]\") : group_scope.\n\n(*This notation provides syntax for expressing that a group G is a Frobenius group with K as its Frobenius kernel.*)\nNotation \"[ 'Frobenius' G 'with' 'kernel' K ]\" :=\n (Frobenius_group_with_kernel G K)\n (K at level 35,\n format \"[ 'Frobenius' G 'with' 'kernel' K ]\") : group_scope.\n\n(*This notation provides syntax for asserting that a given group G is a Frobenius group.*)\nNotation \"[ 'Frobenius' G ]\" := (Frobenius_group G)\n (format \"[ 'Frobenius' G ]\") : group_scope.\n\n(*This notation provides syntax for expressing that a group G is a Frobenius group which is the semidirect product of its kernel K and complement H.*)\nNotation \"[ 'Frobenius' G = K ><| H ]\" :=\n (Frobenius_group_with_kernel_and_complement G K H)\n (K, H at level 35,\n format \"[ 'Frobenius' G = K ><| H ]\") : group_scope.\n\nSection FrobeniusBasics.\n\nVariable gT : finGroupType.\nImplicit Types (A B : {set gT}) (G H K L R X : {group gT}).\n\n(*This lemma states that the trivial group acts semiregularly on any other group.*)\nLemma semiregular1l H : semiregular 1 H.\n\n(*This lemma states that any group acts semiregularly on the trivial group.*)\nLemma semiregular1r K : semiregular K 1.\n\n(*This lemma states that the semiregular property between two groups is symmetric; if a first group acts semiregularly on a second, then the second also acts semiregularly on the first.*)\nLemma semiregular_sym H K : semiregular K H -> semiregular H K.\n\n(*This lemma states that the semiregularity property is inherited by subgroups. If a group acts semiregularly on another group, then any subgroup of the first also acts semiregularly on any subgroup of the second.*)\nLemma semiregularS K1 K2 A1 A2 :\n K1 \\subset K2 -> A1 \\subset A2 -> semiregular K2 A2 -> semiregular K1 A1.\n\n(*This lemma states that if a first group acts semiregularly on a second group, then the two groups are semiprime to each other.*)\nLemma semiregular_prime H K : semiregular K H -> semiprime K H.\n\n(*This lemma states that if two groups are semiprime to each other and the centralizer of the second group in the first is trivial, then the first group acts semiregularly on the second.*)\nLemma semiprime_regular H K : semiprime K H -> 'C_K(H) = 1 -> semiregular K H.\n\n(*This lemma states that the semiprime property is inherited by subgroups. If two groups are semiprime, then any subgroup of the first and any subgroup of the second are also semiprime.*)\nLemma semiprimeS K1 K2 A1 A2 :\n K1 \\subset K2 -> A1 \\subset A2 -> semiprime K2 A2 -> semiprime K1 A1.\n\n(*This lemma states that if two groups are semiprime, then the centralizer in the first group of any non-trivial subgroup of the second is equal to the centralizer in the first group of the entire second group.*)\nLemma cent_semiprime H K X :\n semiprime K H -> X \\subset H -> X :!=: 1 -> 'C_K(X) = 'C_K(H).\n\n(*This lemma states that if two groups are semiprime, and a subgroup of the first group has a non-trivial centralizer in the second group, then that centralizer must be the entire second group.*)\nLemma stab_semiprime H K X :\n semiprime K H -> X \\subset K -> 'C_H(X) != 1 -> 'C_H(X) = H.\n\n(*This lemma states that if a first group acts semiregularly on a second group, then the centralizer in the first group of any non-trivial subgroup of the second is the trivial group.*)\nLemma cent_semiregular H K X :\n semiregular K H -> X \\subset H -> X :!=: 1 -> 'C_K(X) = 1.\n\n(*This lemma states that if a group H is a subgroup of the normalizer of another group K and acts semiregularly on K, then the order of H must divide the predecessor of the order of K.*)\nLemma regular_norm_dvd_pred K H :\n H \\subset 'N(K) -> semiregular K H -> #|H| %| #|K|.-1.\n\n(*This lemma states that if a group H is a subgroup of the normalizer of another group K and acts semiregularly on K, then the orders of K and H are coprime.*)\nLemma regular_norm_coprime K H :\n H \\subset 'N(K) -> semiregular K H -> coprime #|K| #|H|.\n\n(*This lemma states that the semiregularity property is invariant under conjugation. If a group K acts semiregularly on a group H, then the conjugate of K by any element also acts semiregularly on the conjugate of H by that same element.*)\nLemma semiregularJ K H x : semiregular K H -> semiregular (K :^ x) (H :^ x).\n\n(*This lemma states that the semiprime property is invariant under conjugation. If two groups are semiprime, then their respective conjugates by any element are also semiprime.*)\nLemma semiprimeJ K H x : semiprime K H -> semiprime (K :^ x) (H :^ x).\n\n(*This lemma provides the logical expansion of the boolean definition of a normed trivial intersection set, stating that it is equivalent to the conjunction of three properties: the set is non-empty, it intersects trivially with its distinct conjugates, and its normalizer is a specific given group.*)\nLemma normedTI_P A G L : \n reflect [/\\ A != set0, L \\subset 'N_G(A)\n & {in G, forall g, ~~ [disjoint A & A :^ g] -> g \\in L}]\n (normedTI A G L).\n\nArguments normedTI_P {A G L}.\n\n(*This lemma gives an alternative characterization of a normed trivial intersection set, stating that a non-empty set A is a normed trivial intersection subset of a group G with respect to a set L if and only if L is a subset of G and for any element a in A and any element g in G, the conjugate of a by g belongs to A precisely when g belongs to L.*)\nLemma normedTI_memJ_P A G L :\n reflect [/\\ A != set0, L \\subset G\n & {in A & G, forall a g, (a ^ g \\in A) = (g \\in L)}]\n (normedTI A G L).\n\n(*This lemma states that if a non-empty subset of a group has the trivial intersection property, then the set of its conjugates forms a partition of its class support.*)\nLemma partition_class_support A G :\n A != set0 -> trivIset (A :^: G) -> partition (A :^: G) (class_support A G).\n\n(*This lemma states that if a set is a normed trivial intersection subset of a group, then the set of its conjugates forms a partition of its class support.*)\nLemma partition_normedTI A G L :\n normedTI A G L -> partition (A :^: G) (class_support A G).\n\n(*This lemma states that for a normed trivial intersection subset A of a group G with respect to a subgroup L, the cardinality of the class support of A is equal to the product of the cardinality of A and the index of L in G.*)\nLemma card_support_normedTI A G L :\n normedTI A G L -> #|class_support A G| = (#|A| * #|G : L|)%N.\n\n(*This lemma states that if a set B is a normed trivial intersection subset of a group G with respect to a subgroup L, and A is a non-empty subset of B whose normalizer contains L, then A is also a normed trivial intersection subset of G with respect to L.*)\nLemma normedTI_S A B G L : \n A != set0 -> L \\subset 'N(A) -> A \\subset B -> normedTI B G L ->\n normedTI A G L.\n\n(*This lemma states that if a set is a normed trivial intersection subset of a group G with respect to a subgroup L, then the centralizer in G of any non-identity element of the set is a subset of L.*)\nLemma cent1_normedTI A G L :\n normedTI A G L -> {in A, forall x, 'C_G[x] \\subset L}.\n\n(*This lemma provides a reflection, stating that a group G has a Frobenius action on another group H if and only if G is a Frobenius group with H as its complement.*)\nLemma Frobenius_actionP G H :\n reflect (has_Frobenius_action G H) [Frobenius G with complement H].\n\nSection FrobeniusProperties.\n\nVariables G H K : {group gT}.\nHypothesis frobG : [Frobenius G = K ><| H].\n\n(*This lemma states that if a group G is a Frobenius group formed by the semidirect product of a kernel K and a complement H, then G is a Frobenius group with kernel K.*)\nLemma FrobeniusWker : [Frobenius G with kernel K].\n\n(*This lemma states that if a group G is a Frobenius group formed by the semidirect product of a kernel K and a complement H, then G is a Frobenius group with complement H.*)\nLemma FrobeniusWcompl : [Frobenius G with complement H].\n\n(*This lemma states that if a group G is defined as the semidirect product of a kernel and a complement that form a Frobenius structure, then G itself is a Frobenius group.*)\nLemma FrobeniusW : [Frobenius G].\n\n(*This lemma asserts the defining properties of a Frobenius group structure, stating that the group is a semidirect product of a kernel and a complement, both of which are non-trivial and proper subgroups.*)\nLemma Frobenius_context :\n [/\\ K ><| H = G, K :!=: 1, H :!=: 1, K \\proper G & H \\proper G].\n\n(*This lemma states that for a Frobenius group G with kernel K and complement H, the collection of sets containing K and all conjugates of the non-identity elements of H by elements of K forms a partition of G.*)\nLemma Frobenius_partition : partition (gval K |: (H^# :^: K)) G.\n\n(*This lemma states that for any non-identity element in the kernel of a Frobenius group, its centralizer within the larger group is a subset of the kernel.*)\nLemma Frobenius_cent1_ker : {in K^#, forall x, 'C_G[x] \\subset K}.\n\n(*This lemma states that in a Frobenius group, the kernel subgroup acts semiregularly on the complement subgroup.*)\nLemma Frobenius_reg_ker : semiregular K H.\n\n(*This lemma states that in a Frobenius group, the complement subgroup acts semiregularly on the kernel subgroup.*)\nLemma Frobenius_reg_compl : semiregular H K.\n\n(*This lemma states that in a Frobenius group, the order of the complement subgroup divides the quantity of the order of the kernel subgroup minus one.*)\nLemma Frobenius_dvd_ker1 : #|H| %| #|K|.-1.\n\n(*This lemma states that if a Frobenius group has an odd order, then twice the order of its complement subgroup is strictly less than the order of its kernel subgroup.*)\nLemma ltn_odd_Frobenius_ker : odd #|G| -> #|H|.*2 < #|K|.\n\n(*This lemma states that in a Frobenius group, the index of the kernel subgroup divides the quantity of the order of the kernel subgroup minus one.*)\nLemma Frobenius_index_dvd_ker1 : #|G : K| %| #|K|.-1.\n\n(*This lemma states that in a Frobenius group, the order of the kernel subgroup and the order of the complement subgroup are coprime.*)\nLemma Frobenius_coprime : coprime #|K| #|H|.\n\n(*This lemma states that in a Frobenius group, the centralizer of the complement subgroup within the kernel subgroup is the trivial group.*)\nLemma Frobenius_trivg_cent : 'C_K(H) = 1.\n\n(*This lemma states that in a Frobenius group, the order of the kernel subgroup and its index in the group are coprime.*)\nLemma Frobenius_index_coprime : coprime #|K| #|G : K|.\n\n(*This lemma states that the kernel of a Frobenius group is a Hall subgroup.*)\nLemma Frobenius_ker_Hall : Hall G K.\n\n(*This lemma states that the complement of a Frobenius group is a Hall subgroup.*)\nLemma Frobenius_compl_Hall : Hall G H.\n\nEnd FrobeniusProperties.\n\n(*This lemma states that the property of being a normed trivial intersection set is preserved under conjugation of the set, the ambient group, and the normalizer.*)\nLemma normedTI_J x A G L : normedTI (A :^ x) (G :^ x) (L :^ x) = normedTI A G L.\n\n(*This lemma states that for a group G to be a Frobenius group with a given complement H is equivalent to its conjugate being a Frobenius group with the conjugate of H as its complement.*)\nLemma FrobeniusJcompl x G H :\n [Frobenius G :^ x with complement H :^ x] = [Frobenius G with complement H].\n\n(*This lemma states that the structure of a group G as a Frobenius group formed by the semidirect product of a kernel K and a complement H is invariant under conjugation.*)\nLemma FrobeniusJ x G K H :\n [Frobenius G :^ x = K :^ x ><| H :^ x] = [Frobenius G = K ><| H].\n\n(*This lemma states that for a group G to be a Frobenius group with a given kernel K is equivalent to its conjugate being a Frobenius group with the conjugate of K as its kernel.*)\nLemma FrobeniusJker x G K :\n [Frobenius G :^ x with kernel K :^ x] = [Frobenius G with kernel K].\n\n(*This lemma states that a group is a Frobenius group if and only if its conjugate is also a Frobenius group.*)\nLemma FrobeniusJgroup x G : [Frobenius G :^ x] = [Frobenius G].\n\n(*This lemma states that if a group is a Frobenius group with a given kernel, then the index of the kernel in the group divides the quantity of the order of the kernel minus one.*)\nLemma Frobenius_ker_dvd_ker1 G K :\n [Frobenius G with kernel K] -> #|G : K| %| #|K|.-1.\n\n(*This lemma states that if a group is a Frobenius group with a given kernel, then the order of the kernel and its index in the group are coprime.*)\nLemma Frobenius_ker_coprime G K :\n [Frobenius G with kernel K] -> coprime #|K| #|G : K|.\n\n(*This lemma states that for a group formed by the semidirect product of two non-trivial subgroups, that group is a Frobenius group with a given kernel and complement if and only if the conjugation action of the kernel on the complement is semiregular.*)\nLemma Frobenius_semiregularP G K H :\n K ><| H = G -> K :!=: 1 -> H :!=: 1 ->\n reflect (semiregular K H) [Frobenius G = K ><| H].\n\n(*This lemma states that for two subgroups of a group, where one is non-trivial and the other has a prime order, the containing group is a Frobenius group with a specified kernel and complement if and only if the group is their semidirect product and the centralizer of the complement within the kernel is the trivial group.*)\nLemma prime_FrobeniusP G K H :\n K :!=: 1 -> prime #|H| ->\n reflect (K ><| H = G /\\ 'C_K(H) = 1) [Frobenius G = K ><| H].\n\n(*This lemma states that if a group is a Frobenius group with a given kernel and complement, and there is a non-trivial subgroup of the kernel that is normalized by the complement, then the group generated by this subgroup and the complement is also a Frobenius group with the subgroup as its kernel.*)\nLemma Frobenius_subl G K K1 H :\n K1 :!=: 1 -> K1 \\subset K -> H \\subset 'N(K1) -> [Frobenius G = K ><| H] ->\n [Frobenius K1 <*> H = K1 ><| H].\n\n \n(*This lemma states that if a group is a Frobenius group with a given kernel and complement, then for any non-trivial subgroup of the complement, the group generated by the original kernel and this subgroup is also a Frobenius group, with the original kernel as its kernel and the subgroup as its complement.*)\nLemma Frobenius_subr G K H H1 :\n H1 :!=: 1 -> H1 \\subset H -> [Frobenius G = K ><| H] ->\n [Frobenius K <*> H1 = K ><| H1].\n\n(*This lemma provides an equivalent characterization of a Frobenius kernel, stating that a subgroup of a group is a Frobenius kernel if and only if it is a proper, non-trivial, normal subgroup, and the centralizer within the larger group of any of its non-identity elements is contained entirely within the subgroup itself.*)\nLemma Frobenius_kerP G K :\n reflect [/\\ K :!=: 1, K \\proper G, K <| G\n & {in K^#, forall x, 'C_G[x] \\subset K}]\n [Frobenius G with kernel K].\n\n(*This lemma states that if a group is a Frobenius group with a given kernel, and another subgroup exists such that their semidirect product reconstructs the original group, then this second subgroup is a valid Frobenius complement.*)\nLemma set_Frobenius_compl G K H :\n K ><| H = G -> [Frobenius G with kernel K] -> [Frobenius G = K ><| H].\n\n(*This lemma states that if a group is a Frobenius group with a specific kernel, then any subgroup of that group that properly contains the kernel is also a Frobenius group with the same kernel.*)\nLemma Frobenius_kerS G K G1 :\n G1 \\subset G -> K \\proper G1 ->\n [Frobenius G with kernel K] -> [Frobenius G1 with kernel K].\n\n(*This lemma provides a definition of the Frobenius kernel in the context of a group action. For a group that is a semidirect product of two subgroups and has a Frobenius action on a set, the lemma identifies one subgroup as the kernel by equating it to the set containing the identity element and all group elements that fix no points in the set.*)\nLemma Frobenius_action_kernel_def G H K sT S to :\n K ><| H = G -> @Frobenius_action _ G H sT S to ->\n K :=: 1 :|: [set x in G | 'Fix_(S | to)[x] == set0].\n\nEnd FrobeniusBasics.\n\nArguments normedTI_P {gT A G L}.\nArguments normedTI_memJ_P {gT A G L}.\nArguments Frobenius_kerP {gT G K}.\n\n(*This lemma describes how the Frobenius property behaves with respect to quotients. It states that for a Frobenius group that is a semidirect product of a kernel and a complement with coprime orders, if a quotient is taken by a normal subgroup that is properly contained in the kernel and satisfies an additional centralizer condition, then the resulting quotient group is also a Frobenius group, with its kernel and complement being the corresponding quotient groups.*)\nLemma Frobenius_coprime_quotient (gT : finGroupType) (G K H N : {group gT}) :\n K ><| H = G -> N <| G -> coprime #|K| #|H| /\\ H :!=: 1%g ->\n N \\proper K /\\ {in H^#, forall x, 'C_K[x] \\subset N} ->\n [Frobenius G / N = (K / N) ><| (H / N)]%g.\n\nSection InjmFrobenius.\n\nVariables (gT rT : finGroupType) (D G : {group gT}) (f : {morphism D >-> rT}).\nImplicit Types (H K : {group gT}) (sGD : G \\subset D) (injf : 'injm f).\n\n(*This lemma states that the property of a group being a Frobenius group with a specified complement is preserved under an injective group homomorphism; the image of the group is also a Frobenius group, where the image of the original complement serves as the new complement.*)\nLemma injm_Frobenius_compl H sGD injf : \n [Frobenius G with complement H] -> [Frobenius f @* G with complement f @* H].\n\n(*This lemma states that the full structure of a Frobenius group, including its kernel and complement, is preserved under an injective group homomorphism. The image group is also a Frobenius group, with its kernel and complement being the respective images of the original kernel and complement.*)\nLemma injm_Frobenius H K sGD injf : \n [Frobenius G = K ><| H] -> [Frobenius f @* G = f @* K ><| f @* H].\n\n(*This lemma states that the property of a group being a Frobenius group with a specified kernel is preserved under an injective group homomorphism; the image of the group is also a Frobenius group, where the image of the original kernel serves as the new kernel.*)\nLemma injm_Frobenius_ker K sGD injf : \n [Frobenius G with kernel K] -> [Frobenius f @* G with kernel f @* K].\n\n(*This lemma states that the property of a group being a Frobenius group is preserved under injective group homomorphisms, meaning the image of any Frobenius group is also a Frobenius group.*)\nLemma injm_Frobenius_group sGD injf : [Frobenius G] -> [Frobenius f @* G].\n\nEnd InjmFrobenius.\n\n(*This theorem states that for a given finite group and a natural number, if the number divides the order of the group, then it also divides the count of elements in the group that, when raised to the power of that number, result in the identity element.*)\nTheorem Frobenius_Ldiv (gT : finGroupType) (G : {group gT}) n :\n n %| #|G| -> n %| #|'Ldiv_n(G)|.", - "solvable.center": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import fintype bigop finset fingroup morphism perm.\nFrom mathcomp Require Import automorphism quotient action gproduct gfunctor.\nFrom mathcomp Require Import cyclic.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection Defs.\n\nVariable gT : finGroupType.\n\n(*This definition specifies the center of a set of group elements as the subset containing all elements within that set which commute with every other element in the set.*)\nDefinition center (A : {set gT}) := 'C_A(A).\n\nCanonical center_group (G : {group gT}) : {group gT} :=\n Eval hnf in [group of center G].\n\nEnd Defs.\n\nArguments center {gT} A%_g.\n(*A notation for the center of a set of group elements.*)\nNotation \"''Z' ( A )\" := (center A) : group_scope.\n(*A notation for the center of a group, which is itself a group.*)\nNotation \"''Z' ( H )\" := (center_group H) : Group_scope.\n\n(*This lemma states that the center construction is continuous with respect to group morphisms, meaning that the image of the center of a group under a group morphism is a subset of the center of the image of that group.*)\nLemma morphim_center : GFunctor.pcontinuous (@center).\n\nCanonical center_igFun := [igFun by fun _ _ => subsetIl _ _ & morphim_center].\nCanonical center_gFun := [gFun by morphim_center].\nCanonical center_pgFun := [pgFun by morphim_center].\n\nSection Center.\n\nVariables gT : finGroupType.\nImplicit Type rT : finGroupType.\nImplicit Types (x y : gT) (A B : {set gT}) (G H K D : {group gT}).\n\n(*This lemma provides a boolean reflection that an element belongs to the centralizer of a set of group elements within another set if and only if the element is in the second set and it commutes with every element of the first set.*)\nLemma subcentP A B x : reflect (x \\in A /\\ centralises x B) (x \\in 'C_A(B)).\n\n(*This lemma states that the centralizer of a set of group elements within another set is a subset of the normalizer of the first set within the second.*)\nLemma subcent_sub A B : 'C_A(B) \\subset 'N_A(B).\n\n(*This lemma states that the normalizer of a set of group elements within a group is a subgroup of the normalizer of the centralizer of that set within the same group.*)\nLemma subcent_norm G B : 'N_G(B) \\subset 'N('C_G(B)).\n\n(*This lemma states that the centralizer of a set of group elements within a group is a normal subgroup of the normalizer of that set within the same group.*)\nLemma subcent_normal G B : 'C_G(B) <| 'N_G(B).\n\n(*This lemma states that if two subgroups are characteristic in a group, then the centralizer of the second subgroup within the first is also a characteristic subgroup of the main group.*)\nLemma subcent_char G H K : H \\char G -> K \\char G -> 'C_H(K) \\char G.\n\n(*This lemma provides a boolean reflection stating that an element belongs to the center of a set of group elements if and only if the element is in the set and commutes with every element of the set.*)\nLemma centerP A x : reflect (x \\in A /\\ centralises x A) (x \\in 'Z(A)).\n\n(*This lemma states that the center of a set of group elements is a subset of that set.*)\nLemma center_sub A : 'Z(A) \\subset A.\n\n(*This lemma states that the center of the trivial group, which contains only the identity element, is the trivial group itself.*)\nLemma center1 : 'Z(1) = 1 :> {set gT}.\n\n(*This lemma states that every element in a given set of group elements commutes with every element in the center of that set.*)\nLemma centerC A : {in A, centralised 'Z(A)}.\n\n(*This lemma states that the center of a group is a normal subgroup of that group.*)\nLemma center_normal G : 'Z(G) <| G.\n\n(*This lemma states that any subgroup contained within the center of a larger group is a normal subgroup of that larger group.*)\nLemma sub_center_normal H G : H \\subset 'Z(G) -> H <| G.\n\n(*This lemma states that the center of any group is an abelian group.*)\nLemma center_abelian G : abelian 'Z(G).\n\n(*This lemma states that the center of a group is a characteristic subgroup of that group.*)\nLemma center_char G : 'Z(G) \\char G.\n\n(*This lemma provides a boolean reflection stating that a set of group elements is equal to its center if and only if the set is abelian.*)\nLemma center_idP A : reflect ('Z(A) = A) (abelian A).\n\n(*This lemma states the class formula for a finite group, expressing the order of the group as the sum of the order of its center and the sum of the sizes of all non-trivial conjugacy classes.*)\nLemma center_class_formula G :\n #|G| = #|'Z(G)| + \\sum_(xG in [set x ^: G | x in G :\\: 'C(G)]) #|xG|.\n\n(*This lemma provides a boolean reflection that a group element belongs to the centralizer of another element within a set if and only if the first element is in the set and commutes with the second element.*)\nLemma subcent1P A x y : reflect (y \\in A /\\ commute x y) (y \\in 'C_A[x]).\n\n(*This lemma states that any element of a group belongs to its own centralizer within that group.*)\nLemma subcent1_id x G : x \\in G -> x \\in 'C_G[x].\n\n(*This lemma states that the centralizer of an element within a group is a subgroup of that group.*)\nLemma subcent1_sub x G : 'C_G[x] \\subset G.\n\n(*This lemma states that if an element from a group is in the centralizer of another element from the same group, then the second element is also in the centralizer of the first.*)\nLemma subcent1C x y G : x \\in G -> y \\in 'C_G[x] -> x \\in 'C_G[y].\n\n(*This lemma states that the cyclic subgroup generated by an element of a group is a subgroup of the centralizer of that element.*)\nLemma subcent1_cycle_sub x G : x \\in G -> <[x]> \\subset 'C_G[x].\n\n(*This lemma states that the centralizer of a group element is a subgroup of the normalizer of the cyclic subgroup generated by that element.*)\nLemma subcent1_cycle_norm x G : 'C_G[x] \\subset 'N(<[x]>).\n\n(*This lemma states that the cyclic subgroup generated by an element of a group is a normal subgroup of the centralizer of that element.*)\nLemma subcent1_cycle_normal x G : x \\in G -> <[x]> <| 'C_G[x].\n\n(*This lemma states that if the quotient of a group by its center is a cyclic group, then the group itself must be abelian.*)\nLemma cyclic_center_factor_abelian G : cyclic (G / 'Z(G)) -> abelian G.\n\n(*This lemma states that if a group has a subgroup that is contained in its center, and the corresponding quotient group is cyclic, then the original group must be abelian.*)\nLemma cyclic_factor_abelian H G :\n H \\subset 'Z(G) -> cyclic (G / H) -> abelian G.\n\nSection Injm.\n\nVariables (rT : finGroupType) (D : {group gT}) (f : {morphism D >-> rT}).\n\nHypothesis injf : 'injm f.\n\n(*This lemma states that for any subgroup of a given group, an injective group morphism maps the center of the subgroup to the center of the image of the subgroup.*)\nLemma injm_center G : G \\subset D -> f @* 'Z(G) = 'Z(f @* G).\n\nEnd Injm.\n\nEnd Center.\n\nArguments center_idP {gT A}.\n\n(*This lemma states that if two groups are isomorphic, then their respective centers are also isomorphic.*)\nLemma isog_center (aT rT : finGroupType) (G : {group aT}) (H : {group rT}) :\n G \\isog H -> 'Z(G) \\isog 'Z(H).\n\nSection Product.\n\nVariable gT : finGroupType.\nImplicit Types (A B C : {set gT}) (G H K : {group gT}).\n\n(*This lemma states that if a group K is a subgroup of the centralizer of another group H, then the group product of the center of H and the center of K is equal to the center of the group product of H and K.*)\nLemma center_prod H K : K \\subset 'C(H) -> 'Z(H) * 'Z(K) = 'Z(H * K).\n\n(*This lemma states that if the central product of two sets of group elements A and B equals a group G, then the central product of the centers of A and B is equal to the center of G.*)\nLemma center_cprod A B G : A \\* B = G -> 'Z(A) \\* 'Z(B) = 'Z(G).\n\n(*This lemma states that if the big central product of an indexed family of sets of group elements equals a group G, then the big central product of the centers of those sets is equal to the center of G.*)\nLemma center_bigcprod I r P (F : I -> {set gT}) G :\n \\big[cprod/1]_(i <- r | P i) F i = G ->\n \\big[cprod/1]_(i <- r | P i) 'Z(F i) = 'Z(G).\n\n(*This lemma states that the central product of a group with its own center results in the group itself.*)\nLemma cprod_center_id G : G \\* 'Z(G) = G.\n\n(*This lemma states that if the direct product of two sets of group elements A and B is equal to a group G, then the direct product of the centers of A and B is equal to the center of G.*)\nLemma center_dprod A B G : A \\x B = G -> 'Z(A) \\x 'Z(B) = 'Z(G).\n\n(*This lemma states that if the big direct product of an indexed family of sets of group elements equals a group G, then the big direct product of the centers of those sets is equal to the center of G.*)\nLemma center_bigdprod I r P (F: I -> {set gT}) G :\n \\big[dprod/1]_(i <- r | P i) F i = G ->\n \\big[dprod/1]_(i <- r | P i) 'Z(F i) = 'Z(G).\n\n(*This lemma states that if a group G is the central product of groups H and K, their centers are equal, and for both H and K the subgroup of automorphisms fixing their respective centers is isomorphic to the automorphism group of their centers, then the subgroup of automorphisms of G fixing its center is also isomorphic to the automorphism group of its center.*)\nLemma Aut_cprod_full G H K :\n H \\* K = G -> 'Z(H) = 'Z(K) ->\n Aut_in (Aut H) 'Z(H) \\isog Aut 'Z(H) ->\n Aut_in (Aut K) 'Z(K) \\isog Aut 'Z(K) ->\n Aut_in (Aut G) 'Z(G) \\isog Aut 'Z(G).\n\nEnd Product.\n\nSection CprodBy.\n\nVariables gTH gTK : finGroupType.\nVariables (H : {group gTH}) (K : {group gTK}) (gz : {morphism 'Z(H) >-> gTK}).\n\n(*This definition specifies a set of pairs of group elements, constructed from an isomorphism between the centers of two groups. The set consists of pairs where the first element is from the center of the first group, and the second element is the inverse of the image of the first element under the given isomorphism.*)\nDefinition ker_cprod_by of isom 'Z(H) 'Z(K) gz :=\n [set xy | let: (x, y) := xy in (x \\in 'Z(H)) && (y == (gz x)^-1)].\n\nHypothesis isoZ : isom 'Z(H) 'Z(K) gz.\n(*This term is an alias for the specific kernel set constructed using the assumed isomorphism between the centers of two groups.*)\nLet kerHK := ker_cprod_by isoZ.\n\n(*This term is an alias for the proof object asserting that the given group morphism between centers is injective.*)\nLet injgz : 'injm gz. \n(*This term is an alias for the equality stating that the image of the center of the first group under the given morphism is equal to the center of the second group.*)\nLet gzZ : gz @* 'Z(H) = 'Z(K). \n(*This term is an alias for the property that the image of the center of the first group under the given morphism is a characteristic subgroup of the center of the second group.*)\nLet gzZchar : gz @* 'Z(H) \\char 'Z(K). \n(*This term is an alias for the property that the image of the center of the first group under the given morphism is a subgroup of the center of the second group.*)\nLet sgzZZ : gz @* 'Z(H) \\subset 'Z(K) := char_sub gzZchar.\n(*This term is an alias for the property that the center of the first group is a subgroup of that group.*)\nLet sZH := center_sub H.\n(*This term is an alias for the property that the center of the second group is a subgroup of that group.*)\nLet sZK := center_sub K.\n(*This term is an alias, derived by transitivity, for the property that the image of the center of the first group under the given morphism is a subgroup of the second group.*)\nLet sgzZG : gz @* 'Z(H) \\subset K := subset_trans sgzZZ sZK.\n\n(*This lemma states that the kernel set, defined for the central product construction, forms a group.*)\nLemma ker_cprod_by_is_group : group_set kerHK.\n\nCanonical ker_cprod_by_group := Group ker_cprod_by_is_group.\n\n(*This lemma states that the kernel for the central product construction is a subgroup of the center of the direct product of the two underlying groups.*)\nLemma ker_cprod_by_central : kerHK \\subset 'Z(setX H K).\n\n(*This fact provides an opaque key used to lock the definition of the central product type, ensuring that its internal representation is not revealed.*)\nFact cprod_by_key : unit. \n(*This definition provides the underlying finite group structure for the central product, which is constructed as the quotient of the direct product of two groups by a specific kernel subgroup.*)\nDefinition cprod_by_def : finGroupType := subg_of (setX H K / kerHK).\n(*This definition creates the sealed finite group type representing the central product of two groups, constructed via a specified isomorphism between their centers.*)\nDefinition cprod_by := locked_with cprod_by_key cprod_by_def.\n(*This local notation provides a shorthand for the underlying carrier set of the central product group.*)\nLocal Notation C := [set: FinGroup.sort cprod_by].\n\n(*This definition specifies the canonical projection map from the direct product of two groups into their central product, which sends a pair of elements to its corresponding coset in the quotient group.*)\nDefinition in_cprod : gTH * gTK -> cprod_by :=\n let: tt as k := cprod_by_key return _ -> locked_with k cprod_by_def in\n subg _ \\o coset kerHK.\n\n(*This lemma states that the canonical projection from the direct product to the central product is a group homomorphism.*)\nLemma in_cprodM : {in setX H K &, {morph in_cprod : u v / u * v}}.\n\nCanonical in_cprod_morphism := Morphism in_cprodM.\n\n(*This lemma states that the kernel of the canonical projection morphism into the central product group is equal to the kernel subgroup used to define the quotient.*)\nLemma ker_in_cprod : 'ker in_cprod = kerHK.\n\n(*This lemma establishes that the first group is included in the domain of the composite function that injects elements from the first group into the direct product and then projects them into the central product.*)\nLemma cpairg1_dom : H \\subset 'dom (in_cprod \\o @pairg1 gTH gTK).\n\n(*This lemma establishes that the second group is included in the domain of the composite function that injects elements from the second group into the direct product and then projects them into the central product.*)\nLemma cpair1g_dom : K \\subset 'dom (in_cprod \\o @pair1g gTH gTK).\n\n(*This definition constructs a group morphism from the first group into the central product by restricting the canonical injection to the domain of the first group.*)\nDefinition cpairg1 := tag (restrmP _ cpairg1_dom).\n(*This definition constructs a group morphism from the second group into the central product by restricting the canonical injection to the domain of the second group.*)\nDefinition cpair1g := tag (restrmP _ cpair1g_dom).\n\n(*This local notation defines an alias for the image of the first group within the central product group, obtained via the canonical injection morphism.*)\nLocal Notation CH := (mfun cpairg1 @* gval H).\n(*This notation defines CK as the image of the group K under its canonical embedding into the direct product group C. This corresponds to the subgroup of pairs where the first component is the identity element of H.*)\nLocal Notation CK := (mfun cpair1g @* gval K).\n\n(*This lemma states that the canonical group morphism embedding the group H into the direct product H times K is injective.*)\nLemma injm_cpairg1 : 'injm cpairg1.\n\n(*This definition provides an alias for the proof that the canonical embedding of the group H into the product group is an injective morphism.*)\nLet injH := injm_cpairg1.\n\n(*This lemma states that the canonical group morphism embedding the group K into the direct product H times K is injective.*)\nLemma injm_cpair1g : 'injm cpair1g.\n\n(*This definition provides an alias for the proof that the canonical embedding of the group K into the product group is an injective morphism.*)\nLet injK := injm_cpair1g.\n\n(*This lemma states that in a direct product group, the image of the second group K is contained within the centralizer of the image of the first group H.*)\nLemma im_cpair_cent : CK \\subset 'C(CH).\n\nHint Resolve im_cpair_cent : core.\n\n(*This lemma states that the product of the image of group H and the image of group K under their canonical embeddings spans the entire direct product group C.*)\nLemma im_cpair : CH * CK = C.\n\n(*This lemma states that the direct product group C is the internal direct product of the subgroups formed by the images of H and K under their canonical embeddings.*)\nLemma im_cpair_cprod : CH \\* CK = C. \n\n(*This lemma establishes the key commuting property for the central product construction, stating that for any element in the center of group H, its canonical embedding into the product group is equal to the composition of the central isomorphism followed by the canonical embedding of the corresponding element from group K.*)\nLemma eq_cpairZ : {in 'Z(H), cpairg1 =1 cpair1g \\o gz}.\n\n(*This lemma states that the intersection of the image of group H and the image of group K within their direct product is equal to the center of the image of H.*)\nLemma setI_im_cpair : CH :&: CK = 'Z(CH).\n\n(*This lemma states that the image of the center of group K under its canonical embedding into the central product group C is equal to the center of C.*)\nLemma cpair1g_center : cpair1g @* 'Z(K) = 'Z(C).\n\n(*This lemma states that the center of the image of group H and the center of the image of group K are equal as subgroups within the central product group.*)\nLemma cpair_center_id : 'Z(CH) = 'Z(CK).\n\n(*This lemma states that the image of the center of group H under its canonical embedding into the central product group C is equal to the center of C.*)\nLemma cpairg1_center : cpairg1 @* 'Z(H) = 'Z(C).\n\nSection ExtCprodm.\n\nVariable rT : finGroupType.\nVariables (fH : {morphism H >-> rT}) (fK : {morphism K >-> rT}).\nHypothesis cfHK : fK @* K \\subset 'C(fH @* H).\nHypothesis eq_fHK : {in 'Z(H), fH =1 fK \\o gz}.\n\n(*This definition constructs a group morphism from the image of H in the central product to a target group, obtained by factoring a given morphism from H through the canonical injective embedding of H.*)\nLet gH := ifactm fH injm_cpairg1.\n(*This definition constructs a group morphism from the image of K in the central product to a target group, obtained by factoring a given morphism from K through the canonical injective embedding of K.*)\nLet gK := ifactm fK injm_cpair1g.\n\n(*This lemma states that the image of the embedded group CK under the induced morphism gK lies within the centralizer of the image of the embedded group CH under the induced morphism gH.*)\nLemma xcprodm_cent : gK @* CK \\subset 'C(gH @* CH).\n\n(*This lemma states that the two induced group morphisms, gH and gK, are equal when restricted to the intersection of their domains, which are the images of groups H and K respectively.*)\nLemma xcprodmI : {in CH :&: CK, gH =1 gK}.\n\n(*This definition constructs a unique group morphism from the central product group C to a target group, determined by two compatible morphisms originating from the factor groups H and K.*)\nDefinition xcprodm := cprodm im_cpair_cprod xcprodm_cent xcprodmI.\nCanonical xcprod_morphism := [morphism of xcprodm].\n\n(*This lemma states that for any element in the group H, the value of the combined external central product morphism applied to the canonical embedding of this element is equal to the value of the original morphism from H on that element.*)\nLemma xcprodmEl : {in H, forall x, xcprodm (cpairg1 x) = fH x}.\n\n(*This lemma states that for any element in the group K, the value of the combined external central product morphism applied to the canonical embedding of this element is equal to the value of the original morphism from K on that element.*)\nLemma xcprodmEr : {in K, forall y, xcprodm (cpair1g y) = fK y}.\n\n(*This lemma provides the evaluation rule for the external central product morphism on a general element, stating that the morphism applied to a product of an embedded element from H and an embedded element from K equals the product of the original morphisms applied to those elements.*)\nLemma xcprodmE :\n {in H & K, forall x y, xcprodm (cpairg1 x * cpair1g y) = fH x * fK y}.\n\n(*This lemma states that the image of the entire central product group C under the external central product morphism is equal to the group product of the image of H under its original morphism and the image of K under its original morphism.*)\nLemma im_xcprodm : xcprodm @* C = fH @* H * fK @* K.\n\n(*This lemma states that for any subset of the group H, its image under the composition of the canonical embedding and the external central product morphism is equal to its image under the original morphism from H.*)\nLemma im_xcprodml A : xcprodm @* (cpairg1 @* A) = fH @* A.\n\n(*This lemma states that for any subset of the group K, its image under the composition of the canonical embedding and the external central product morphism is equal to its image under the original morphism from K.*)\nLemma im_xcprodmr A : xcprodm @* (cpair1g @* A) = fK @* A.\n\n(*This lemma states that the external central product morphism is injective if and only if both of the original morphisms, from H and K respectively, are injective.*)\nLemma injm_xcprodm : 'injm xcprodm = 'injm fH && 'injm fK.\n\nEnd ExtCprodm.\n\n(*This lemma states that if the automorphisms of group H that globally stabilize its center induce the full automorphism group of the center, and the same property holds for group K, then the corresponding property also holds for the central product group C.*)\nLemma Aut_cprod_by_full :\n Aut_in (Aut H) 'Z(H) \\isog Aut 'Z(H) ->\n Aut_in (Aut K) 'Z(K) \\isog Aut 'Z(K) ->\n Aut_in (Aut C) 'Z(C) \\isog Aut 'Z(C).\n\nSection Isomorphism.\n\n(*This definition establishes a uniqueness property, stating that if a subgroup is contained within the center of group K and is isomorphic to the image of the center of group H under the central isomorphism, then that subgroup must be equal to that image.*)\nLet gzZ_lone (Y : {group gTK}) :\n Y \\subset 'Z(K) -> gz @* 'Z(H) \\isog Y -> gz @* 'Z(H) = Y.\n\nVariables (rT : finGroupType) (GH GK G : {group rT}).\nHypotheses (defG : GH \\* GK = G) (ziGHK : GH :&: GK = 'Z(GH)).\nHypothesis AutZHfull : Aut_in (Aut H) 'Z(H) \\isog Aut 'Z(H).\nHypotheses (isoGH : GH \\isog H) (isoGK : GK \\isog K).\n\n(*This lemma asserts the existence and uniqueness of the central product structure, stating that a group G, which is the internal central product of its subgroups GH and GK, is isomorphic to the canonical external central product C via a morphism that maps GH and GK to their canonical counterparts in C.*)\nLemma cprod_by_uniq :\n exists f : {morphism G >-> cprod_by},\n [/\\ isom G C f, f @* GH = CH & f @* GK = CK].\n\n(*This lemma states that a group formed as an internal central product is isomorphic to the corresponding abstractly-defined external central product group.*)\nLemma isog_cprod_by : G \\isog C.\n\nEnd Isomorphism.\n\nEnd CprodBy.\n\nSection ExtCprod.\nImport finfun.\n\nVariables gTH gTK : finGroupType.\nVariables (H : {group gTH}) (K : {group gTK}).\n\n(*This definition provides a way to select one of two given finite group types based on a boolean input, returning the second group type if the boolean is true, and the first otherwise.*)\nLet gt_ b := if b then gTK else gTH.\n(*A local notation, used only for parsing, that represents the proposition that the center of a group H is isomorphic to the center of a group K.*)\nLocal Notation isob := ('Z(H) \\isog 'Z(K)) (only parsing).\n(*This definition selects a group, returning group K if a given proposition is true and group H otherwise.*)\nLet G_ b := if b as b' return {group gt_ b'} then K else H.\n\n(*This lemma asserts the existence of an isomorphism from the center of group H to the center of group K, which is used to construct their external central product.*)\nLemma xcprod_subproof :\n {gz : {morphism 'Z(H) >-> gt_ isob} | isom 'Z(H) 'Z(G_ isob) gz}.\n\n(*This definition constructs the external central product of two groups, H and K, by using a predefined isomorphism between their centers.*)\nDefinition xcprod := cprod_by (svalP xcprod_subproof).\n\n(*A record that defines the external central product of two groups, which can be constructed if an isomorphism between their centers is proven to exist. The record bundles the resulting central product group with the specific, canonically chosen isomorphism used in its construction.*)\nInductive xcprod_spec : finGroupType -> Prop :=\n XcprodSpec gz isoZ : xcprod_spec (@cprod_by gTH gTK H K gz isoZ).\n\n(*This lemma states that if the centers of two groups H and K are isomorphic, then their external central product satisfies the defining specification of a central product.*)\nLemma xcprodP : 'Z(H) \\isog 'Z(K) -> xcprod_spec xcprod.\n\n(*This lemma states that a group is isomorphic to the external central product of groups H and K if it is formed by an internal central product of subgroups that are respectively isomorphic to H and K, subject to a condition on the automorphisms of H.*)\nLemma isog_xcprod (rT : finGroupType) (GH GK G : {group rT}) :\n Aut_in (Aut H) 'Z(H) \\isog Aut 'Z(H) ->\n GH \\isog H -> GK \\isog K -> GH \\* GK = G -> 'Z(GH) = 'Z(GK) ->\n G \\isog [set: xcprod].\n\nEnd ExtCprod.\n\nSection IterCprod.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This fixpoint recursively defines the n-th iterated central product of a group G. The base case for zero iterations is the center of G, while the recursive step constructs the external central product of G and the previous iteration's result.*)\nFixpoint ncprod_def n : finGroupType :=\n if n is n'.+1 then xcprod G [set: ncprod_def n']\n else subg_of 'Z(G).\n(*This fact provides a key for creating an opaque definition of the iterated central product, which prevents its automatic expansion by the proof assistant.*)\nFact ncprod_key : unit. \n(*This definition provides an opaque representation of the n-th iterated central product of a group G. It is computationally equivalent to its recursive definition but does not unfold automatically in proofs.*)\nDefinition ncprod := locked_with ncprod_key ncprod_def.\n\nLocal Notation G_ n := [set: gsort (ncprod n)].\n\n(*This lemma states that the zeroth iterated central product of a group G is isomorphic to the center of G.*)\nLemma ncprod0 : G_ 0 \\isog 'Z(G).\n\n(*This lemma states that the zeroth iterated central product of a group G is an abelian group.*)\nLemma center_ncprod0 : 'Z(G_ 0) = G_ 0.\n\n(*This lemma states that for any natural number n, the center of the n-th iterated central product of a group G is isomorphic to the center of the original group G.*)\nLemma center_ncprod n : 'Z(G_ n) \\isog 'Z(G).\n\n(*This lemma states that for any natural number n, the group resulting from n plus one iterations of the central product construction is a central product of the original group G and the group from n iterations.*)\nLemma ncprodS n : xcprod_spec G [set: ncprod n] (ncprod n.+1).\n\n(*This lemma states that the first iterated central product of a group G is isomorphic to G itself.*)\nLemma ncprod1 : G_ 1 \\isog G.\n\n(*This lemma states that if the group of automorphisms of a group G that stabilize its center is isomorphic to the full automorphism group of its center, then this property also holds for any of its n-th iterated central products.*)\nLemma Aut_ncprod_full n :\n Aut_in (Aut G) 'Z(G) \\isog Aut 'Z(G) ->\n Aut_in (Aut (G_ n)) 'Z(G_ n) \\isog Aut 'Z(G_ n).", - "solvable.burnside_app": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype tuple finfun bigop finset fingroup.\nFrom mathcomp Require Import action perm primitive_action ssrAC.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\n(*This lemma states that for any finite group acting on a finite set, the product of the number of orbits and the order of the group equals the sum of the sizes of the fixed-point sets over all elements of the group.*)\nLemma burnside_formula : forall (gT : finGroupType) s (G : {group gT}),\n uniq s -> s =i G ->\n forall (sT : finType) (to : {action gT &-> sT}),\n (#|orbit to G @: setT| * size s)%N = \\sum_(p <- s) #|'Fix_to[p]|.\n\nArguments burnside_formula {gT}.\n\nSection colouring.\n\nVariable n : nat.\n(*This definition introduces the type of colors, which is represented as the finite set of natural numbers strictly less than a given natural number n.*)\nDefinition colors := 'I_n.\n(*This definition introduces the type representing the four vertices of a square, which is defined as the finite set of natural numbers strictly less than four.*)\nDefinition square := 'I_4.\nHB.instance Definition _ := SubType.on square.\n(*This function constructs an element representing a vertex of a square from a given natural number by taking the input number modulo four.*)\nDefinition mksquare i : square := Sub (i %% _) (ltn_mod i 4).\n(*This definition establishes a constant representing the first vertex of a square, corresponding to the natural number zero.*)\nDefinition c0 := mksquare 0.\n(*This definition establishes a constant representing the second vertex of a square, corresponding to the natural number one.*)\nDefinition c1 := mksquare 1.\n(*This definition establishes a constant representing the third vertex of a square, corresponding to the natural number two.*)\nDefinition c2 := mksquare 2.\n(*This definition establishes a constant representing the fourth vertex of a square, corresponding to the natural number three.*)\nDefinition c3 := mksquare 3.\n\n(*This function defines a 90-degree clockwise rotation of the vertices of a square. It maps each vertex to the next one in sequence, wrapping around from the last to the first.*)\nDefinition R1 (sc : square) : square := tnth [tuple c1; c2; c3; c0] sc.\n\n(*This function defines a 180-degree rotation of the vertices of a square. It maps each vertex to the one diagonally opposite to it.*)\nDefinition R2 (sc : square) : square := tnth [tuple c2; c3; c0; c1] sc.\n\n(*This function defines a 270-degree clockwise rotation of the vertices of a square. It maps each vertex to the previous one in sequence, wrapping around from the first to the last.*)\nDefinition R3 (sc : square) : square := tnth [tuple c3; c0; c1; c2] sc.\n\n(*This is a custom tactic that recursively searches a nested pair structure for a given element in the first position of a pair and returns the corresponding second element of that pair.*)\nLtac get_inv elt l :=\n match l with\n | (_, (elt, ?x)) => x\n | (elt, ?x) => x\n | (?x, _) => get_inv elt x\n end.\n\n(*This definition provides a data structure containing pairs of rotations on a square and their corresponding inverse rotations. It pairs the 90-degree rotation with the 270-degree rotation, the 180-degree rotation with itself, and the 270-degree rotation with the 90-degree rotation.*)\nDefinition rot_inv := ((R1, R3), (R2, R2), (R3, R1)).\n\n(*This is a custom tactic designed to automatically prove that a rotation function on a square is injective. It works by finding the inverse of the given rotation from a predefined data structure and applying a general lemma that states a function with a left inverse is injective.*)\nLtac inj_tac :=\n move: (erefl rot_inv); unfold rot_inv;\n match goal with |- ?X = _ -> injective ?Y =>\n move=> _; let x := get_inv Y X in\n apply: (can_inj (g:=x)); move=> [val H1]\n end.\n\n(*This lemma states that the 90-degree clockwise rotation function on the vertices of a square is injective.*)\nLemma R1_inj : injective R1.\n\n(*This lemma states that the 180-degree rotation function on the vertices of a square is injective.*)\nLemma R2_inj : injective R2.\n\n(*This lemma states that the 270-degree clockwise rotation function on the vertices of a square is injective.*)\nLemma R3_inj : injective R3.\n\n(*This definition constructs a permutation representing the 90-degree clockwise rotation on the vertices of a square, based on its corresponding injective function.*)\nDefinition r1 := (perm R1_inj).\n(*This definition constructs a permutation representing the 180-degree rotation on the vertices of a square, based on its corresponding injective function.*)\nDefinition r2 := (perm R2_inj).\n(*This definition constructs a permutation representing the 270-degree clockwise rotation on the vertices of a square, based on its corresponding injective function.*)\nDefinition r3 := (perm R3_inj).\n(*This definition establishes the identity permutation on the vertices of a square, which leaves every vertex unchanged.*)\nDefinition id1 := (1 : {perm square}).\n\n(*This definition specifies a predicate to identify if a given permutation on the vertices of a square is a rotation. A permutation is considered a rotation if it commutes with the 90-degree clockwise rotation permutation.*)\nDefinition is_rot (r : {perm _}) := (r * r1 == r1 * r).\n(*This definition establishes the set of all rotational symmetries of a square, defined as the collection of all permutations on the square's vertices that commute with the 90-degree clockwise rotation.*)\nDefinition rot := [set r | is_rot r].\n\n(*This lemma states that the set of rotations of a square forms a group under the operation of permutation composition.*)\nLemma group_set_rot : group_set rot.\n\nCanonical rot_group := Group group_set_rot.\n\n(*This definition provides an explicit enumeration of the set of rotational symmetries of a square, consisting of the identity permutation, the 90-degree rotation, the 180-degree rotation, and the 270-degree rotation.*)\nDefinition rotations := [set id1; r1; r2; r3].\n\n(*This lemma states that any two rotations of a square are equal if they map the first vertex to the same location.*)\nLemma rot_eq_c0 : forall r s : {perm square},\n is_rot r -> is_rot s -> r c0 = s c0 -> r = s.\n\n(*This lemma states that any rotation of a square can be represented as a power of the fundamental 90-degree clockwise rotation. The specific power is determined by the vertex to which the given rotation maps the first vertex.*)\nLemma rot_r1 : forall r, is_rot r -> r = r1 ^+ (r c0).\n\n(*This lemma states that every permutation in the explicitly enumerated set of rotations is a valid rotation, meaning it satisfies the property of commuting with the 90-degree clockwise rotation.*)\nLemma rotations_is_rot : forall r, r \\in rotations -> is_rot r.\n\n(*This lemma states that the set of permutations that commute with the 90-degree clockwise rotation is exactly equal to the explicitly enumerated set containing the identity, 90-degree, 180-degree, and 270-degree rotations.*)\nLemma rot_is_rot : rot = rotations.\n\n(*This function defines a reflection symmetry of a square's vertices. It acts by swapping the first vertex with the second and the third vertex with the fourth.*)\nDefinition Sh (sc : square) : square := tnth [tuple c1; c0; c3; c2] sc.\n\n(*This lemma states that the function `Sh`, representing a horizontal reflection of a square, is injective, meaning it maps distinct corners to distinct corners.*)\nLemma Sh_inj : injective Sh.\n\n(*This definition introduces `sh` as the permutation corresponding to the injective horizontal reflection function `Sh` on a square.*)\nDefinition sh := (perm Sh_inj).\n\n(*This lemma states that the inverse of the permutation `sh` is equal to `sh` itself, implying that it is an involution.*)\nLemma sh_inv : sh^-1 = sh.\n\n(*This definition introduces `Sv` as a function that performs a vertical reflection on the corners of a square.*)\nDefinition Sv (sc : square) : square := tnth [tuple c3; c2; c1; c0] sc.\n\n(*This lemma states that the vertical reflection function `Sv` is injective, meaning it maps distinct corners of a square to distinct corners.*)\nLemma Sv_inj : injective Sv.\n\n(*This definition introduces `sv` as the permutation corresponding to the injective vertical reflection function `Sv` on a square.*)\nDefinition sv := (perm Sv_inj).\n\n(*This lemma states that the inverse of the permutation `sv` is equal to `sv` itself, implying that it is an involution.*)\nLemma sv_inv : sv^-1 = sv.\n\n(*This definition introduces `Sd1` as a function that performs a reflection across one of the diagonals of a square.*)\nDefinition Sd1 (sc : square) : square := tnth [tuple c0; c3; c2; c1] sc.\n\n(*This lemma states that the diagonal reflection function `Sd1` is injective, meaning it maps distinct corners of a square to distinct corners.*)\nLemma Sd1_inj : injective Sd1.\n\n(*This definition introduces `sd1` as the permutation corresponding to the injective diagonal reflection function `Sd1` on a square.*)\nDefinition sd1 := (perm Sd1_inj).\n\n(*This lemma states that the inverse of the permutation `sd1` is equal to `sd1` itself, implying that it is an involution.*)\nLemma sd1_inv : sd1^-1 = sd1.\n\n(*This definition introduces `Sd2` as a function that performs a reflection across the second diagonal of a square.*)\nDefinition Sd2 (sc : square) : square := tnth [tuple c2; c1; c0; c3] sc.\n\n(*This lemma states that the diagonal reflection function `Sd2` is injective, meaning it maps distinct corners of a square to distinct corners.*)\nLemma Sd2_inj : injective Sd2.\n\n(*This definition introduces `sd2` as the permutation corresponding to the injective diagonal reflection function `Sd2` on a square.*)\nDefinition sd2 := (perm Sd2_inj).\n\n(*This lemma states that the inverse of the permutation `sd2` is equal to `sd2` itself, implying that it is an involution.*)\nLemma sd2_inv : sd2^-1 = sd2.\n\n(*This lemma states that the canonical enumeration of the finite type with four elements is a sequence of the labels `c0`, `c1`, `c2`, and `c3`.*)\nLemma ord_enum4 : enum 'I_4 = [:: c0; c1; c2; c3].\n\n(*This lemma states that the permutation `sh` is not equal to the identity permutation.*)\nLemma diff_id_sh : 1 != sh.\n\n(*This definition introduces `isometries2` as a set containing the identity permutation and the horizontal reflection permutation `sh`.*)\nDefinition isometries2 := [set 1; sh].\n\n(*This lemma states that the cardinality of the set `isometries2` is two.*)\nLemma card_iso2 : #|isometries2| = 2.\n\n(*This lemma states that the set `isometries2` forms a group under permutation composition.*)\nLemma group_set_iso2 : group_set isometries2.\n\nCanonical iso2_group := Group group_set_iso2.\n\n(*This definition introduces `isometries` as the set of eight permutations that represent the full group of symmetries of a square, including rotations and reflections.*)\nDefinition isometries :=\n [set p | [|| p == 1, p == r1, p == r2, p == r3,\n p == sh, p == sv, p == sd1 | p == sd2 ]].\n\n(*This definition introduces `opp` as a function on the corners of a square that maps each corner to its diametrically opposite corner.*)\nDefinition opp (sc : square) := tnth [tuple c2; c3; c0; c1] sc.\n\n(*This definition introduces `is_iso` as a predicate on a permutation that holds if the permutation commutes with the `opp` function, which maps a corner to its opposite.*)\nDefinition is_iso (p : {perm square}) := forall ci, p (opp ci) = opp (p ci).\n\n(*This lemma states that any permutation belonging to the `isometries` set satisfies the `is_iso` predicate.*)\nLemma isometries_iso : forall p, p \\in isometries -> is_iso p.\n\n(*This tactic automates deriving a contradiction from the injectivity of a function, given two distinct inputs that are shown to produce the same output.*)\nLtac non_inj p a1 a2 heq1 heq2 :=\nlet h1:= fresh \"h1\" in\n(absurd (p a1 = p a2); first (by red => - h1; move: (perm_inj h1));\nby rewrite heq1 heq2; apply/eqP).\n\n(*This tactic automates proving that a given permutation is equal to a specified function by checking that their actions on four given elements are identical.*)\nLtac is_isoPtac p f e0 e1 e2 e3 :=\n suff ->: p = f by [rewrite inE eqxx ?orbT];\n let e := fresh \"e\" in apply/permP;\n do 5?[case] => // ?; [move: e0 | move: e1 | move: e2 | move: e3] => e;\n apply: etrans (congr1 p _) (etrans e _); apply/eqP; rewrite // permE.\n\n(*This lemma provides a reflection, stating that a permutation satisfies the `is_iso` predicate if and only if it is a member of the `isometries` set.*)\nLemma is_isoP : forall p, reflect (is_iso p) (p \\in isometries).\n\n(*This lemma states that the set of permutations `isometries` forms a group under the operation of permutation composition.*)\nLemma group_set_iso : group_set isometries.\n\nCanonical iso_group := Group group_set_iso.\n\n(*This lemma states that the cardinality of the set of rotational symmetries of a square is four.*)\nLemma card_rot : #|rot| = 4.\n\n(*This lemma states that the set of rotational symmetries of a square forms a group under the operation of permutation composition.*)\nLemma group_set_rotations : group_set rotations.\n\nCanonical rotations_group := Group group_set_rotations.\n\n(*This notation defines a type for colorings of a square, which are functions that assign a color to each vertex of the square.*)\nNotation col_squares := {ffun square -> colors}.\n\n(*This definition describes the action of a permutation of the square's vertices on a coloring of the square. The action produces a new coloring where the color of any given vertex is determined by the color of the vertex that was moved to its position by the inverse of the permutation.*)\nDefinition act_f (sc : col_squares) (p : {perm square}) : col_squares :=\n [ffun z => sc (p^-1 z)].\n\n(*This lemma states that acting on any coloring of the square with the identity permutation results in the original coloring.*)\nLemma act_f_1 : forall k, act_f k 1 = k.\n\n(*This lemma states that the action of a product of two permutations on a coloring is equivalent to sequentially applying the action of the first permutation and then the action of the second permutation.*)\nLemma act_f_morph : forall k x y, act_f k (x * y) = act_f (act_f k x) y.\n\n(*This definition establishes a total right group action based on the properties that the identity permutation acts trivially and the action of a product of permutations is compositional.*)\nDefinition to := TotalAction act_f_1 act_f_morph.\n\n(*This definition gives the number of distinct colorings of a square, considering two colorings to be the same if one can be transformed into the other by an element of a specific two-element group of isometries.*)\nDefinition square_coloring_number2 := #|orbit to isometries2 @: setT|.\n(*This definition gives the number of distinct colorings of a square when considering two colorings to be equivalent if one can be obtained from the other by a rotation.*)\nDefinition square_coloring_number4 := #|orbit to rotations @: setT|.\n(*This definition gives the number of distinct colorings of a square when considering two colorings to be equivalent if one can be obtained from the other by any isometry of the square, including rotations and reflections.*)\nDefinition square_coloring_number8 := #|orbit to isometries @: setT|.\n\n(*This lemma states that the set of colorings that are left unchanged by the identity permutation is the set of all possible colorings.*)\nLemma Fid : 'Fix_to(1) = setT.\n\n(*This lemma states that the number of colorings fixed by the identity permutation is equal to the total number of colors raised to the fourth power, corresponding to assigning any of the available colors to each of the four vertices.*)\nLemma card_Fid : #|'Fix_to(1)| = (n ^ 4)%N.\n\n(*This definition provides the color assigned to the first corner of the square for a given coloring.*)\nDefinition coin0 (sc : col_squares) : colors := sc c0.\n(*This definition provides the color assigned to the second corner of the square for a given coloring.*)\nDefinition coin1 (sc : col_squares) : colors := sc c1.\n(*This definition provides the color assigned to the third corner of the square for a given coloring.*)\nDefinition coin2 (sc : col_squares) : colors := sc c2.\n(*This definition provides the color assigned to the fourth corner of the square for a given coloring.*)\nDefinition coin3 (sc : col_squares) : colors := sc c3.\n\n(*This lemma states that two colorings of a square are equal if and only if they assign the same color to each of the four corresponding vertices.*)\nLemma eqperm_map : forall p1 p2 : col_squares,\n (p1 == p2) = all (fun s => p1 s == p2 s) [:: c0; c1; c2; c3].\n\n(*This lemma characterizes the set of colorings fixed by a horizontal reflection. A coloring is fixed if and only if the color of its first vertex equals the color of its second vertex, and the color of its third vertex equals the color of its fourth vertex.*)\nLemma F_Sh :\n 'Fix_to[sh] = [set x | (coin0 x == coin1 x) && (coin2 x == coin3 x)].\n\n(*This lemma characterizes the set of colorings fixed by a vertical reflection. A coloring is fixed if and only if the color of its first vertex equals the color of its fourth vertex, and the color of its third vertex equals the color of its second vertex.*)\nLemma F_Sv :\n 'Fix_to[sv] = [set x | (coin0 x == coin3 x) && (coin2 x == coin1 x)].\n\n(*This definition introduces a custom proof tactic designed to automate proving equalities involving the inverse of a permutation. The tactic simplifies the goal by applying properties of group multiplication and permutation equality.*)\nLtac inv_tac :=\n apply: esym (etrans _ (mul1g _)); apply: canRL (mulgK _) _;\n let a := fresh \"a\" in apply/permP => a;\n apply/eqP; rewrite permM !permE; case: a; do 4?case.\n\n(*This lemma states that the inverse of a 90-degree rotation is a 270-degree rotation.*)\nLemma r1_inv : r1^-1 = r3.\n\n(*This lemma states that the 180-degree rotation is its own inverse.*)\nLemma r2_inv : r2^-1 = r2.\n\n(*This lemma states that the inverse of a 270-degree rotation is a 90-degree rotation.*)\nLemma r3_inv : r3^-1 = r1.\n\n(*This lemma characterizes the set of colorings that are invariant under a 180-degree rotation. These are the colorings where the colors of diagonally opposite vertices are equal.*)\nLemma F_r2 :\n 'Fix_to[r2] = [set x | (coin0 x == coin2 x) && (coin1 x == coin3 x)].\n\n(*This lemma characterizes the set of colorings that are invariant under a 90-degree rotation. These are the monochromatic colorings, where all four vertices are assigned the same color.*)\nLemma F_r1 : 'Fix_to[r1] =\n [set x | (coin0 x == coin1 x)&&(coin1 x == coin2 x)&&(coin2 x == coin3 x)].\n\n(*This lemma characterizes the set of colorings that are invariant under a 270-degree rotation. These are the monochromatic colorings, where all four vertices are assigned the same color.*)\nLemma F_r3 : 'Fix_to[r3] =\n [set x | (coin0 x == coin1 x)&&(coin1 x == coin2 x)&&(coin2 x == coin3 x)].\n\n(*This lemma states that for any four distinct vertices of a square, the number of colorings where the first two specified vertices have the same color and the last two specified vertices have the same color is equal to the total number of available colors squared.*)\nLemma card_n2 : forall x y z t : square, uniq [:: x; y; z; t] ->\n #|[set p : col_squares | (p x == p y) && (p z == p t)]| = (n ^ 2)%N.\n\n(*This lemma states that the number of monochromatic colorings, where all four vertices are assigned the same color, is equal to the total number of available colors.*)\nLemma card_n :\n #|[set x | (coin0 x == coin1 x)&&(coin1 x == coin2 x)&& (coin2 x == coin3 x)]|\n = n.\n\n(*This lemma is an application of Burnside's Lemma to count the number of distinct square colorings under a two-element group of isometries. It states that twice the number of distinct colorings equals the sum of the total number of colors raised to the fourth power and the total number of colors squared.*)\nLemma burnside_app2 : (square_coloring_number2 * 2 = n ^ 4 + n ^ 2)%N.\n\n(*This lemma is an application of Burnside's Lemma for the group of rotations of a square. It states that four times the number of rotationally distinct colorings is equal to the sum of the fourth power of the number of colors, the square of the number of colors, and twice the number of colors.*)\nLemma burnside_app_rot :\n (square_coloring_number4 * 4 = n ^ 4 + n ^ 2 + 2 * n)%N.\n\n(*This lemma characterizes the set of colorings that are invariant under a reflection across one of the diagonals. It states that these are precisely the colorings where the colors of the two vertices not on the diagonal axis are equal.*)\nLemma F_Sd1 : 'Fix_to[sd1] = [set x | coin1 x == coin3 x].\n\n(*This lemma states that for any two distinct vertices of a square, the number of colorings that assign the same color to these two vertices is equal to the total number of available colors cubed.*)\nLemma card_n3 : forall x y : square, x != y ->\n #|[set k : col_squares | k x == k y]| = (n ^ 3)%N.\n\n(*This lemma states that the set of square colorings fixed by the group action 'sd2' is identical to the set of colorings where the color of vertex zero is the same as the color of vertex two.*)\nLemma F_Sd2 : 'Fix_to[sd2] = [set x | coin0 x == coin2 x].\n\n(*This lemma applies Burnside's Lemma to count the number of distinct ways to color a square's vertices. It states that eight times the number of distinct colorings equals a polynomial expression in the number of available colors, where this polynomial represents the total count of colorings left unchanged across all eight symmetries of the square.*)\nLemma burnside_app_iso :\n (square_coloring_number8 * 8 = n ^ 4 + 2 * n ^ 3 + 3 * n ^ 2 + 2 * n)%N.\n\nEnd square_colouring.\n\nSection cube_colouring.\n\n(*This definition establishes a type representing the six faces of a cube, formally modeled as the set of natural numbers from zero to five.*)\nDefinition cube := 'I_6.\nHB.instance Definition _ := SubType.on cube.\n(*This definition introduces a function that maps any given natural number to a corresponding face of the cube by taking the number modulo six.*)\nDefinition mkFcube i : cube := Sub (i %% 6) (ltn_mod i 6).\n(*This definition represents the first face of the cube, indexed as zero.*)\nDefinition F0 := mkFcube 0.\n(*This definition represents the second face of the cube, indexed as one.*)\nDefinition F1 := mkFcube 1.\n(*This definition represents the third face of the cube, indexed as two.*)\nDefinition F2 := mkFcube 2.\n(*This definition represents the fourth face of the cube, indexed as three.*)\nDefinition F3 := mkFcube 3.\n(*This definition represents the fifth face of the cube, indexed as four.*)\nDefinition F4 := mkFcube 4.\n(*This definition represents the sixth face of the cube, indexed as five.*)\nDefinition F5 := mkFcube 5.\n\n(*This definition specifies a permutation of the cube's faces as a finite sequence, corresponding to a 180-degree rotation around the axis connecting the centers of opposite faces zero and five.*)\nDefinition S05 := [:: F0; F4; F3; F2; F1; F5].\n(*This definition creates a function that applies the face permutation S05 to a given face of the cube.*)\nDefinition S05f (sc : cube) : cube := tnth [tuple of S05] sc.\n\n(*This definition specifies a permutation of the cube's faces as a finite sequence, corresponding to a 180-degree rotation around the axis connecting the centers of opposite faces one and four.*)\nDefinition S14 := [:: F5; F1; F3; F2; F4; F0].\n(*This definition creates a function that applies the face permutation S14 to a given face of the cube.*)\nDefinition S14f (sc : cube) : cube := tnth [tuple of S14] sc.\n\n(*This definition specifies a permutation of the cube's faces as a finite sequence, corresponding to a 180-degree rotation around the axis connecting the centers of opposite faces two and three.*)\nDefinition S23 := [:: F5; F4; F2; F3; F1; F0].\n(*This definition creates a function that applies the face permutation S23 to a given face of the cube.*)\nDefinition S23f (sc : cube) : cube := tnth [tuple of S23] sc.\n\n(*This definition specifies a permutation of the cube's faces as a finite sequence, representing a 90-degree rotation around the axis passing through the centers of faces zero and five.*)\nDefinition R05 := [:: F0; F2; F4; F1; F3; F5].\n(*This definition creates a function that applies the face permutation R05 to a given face of the cube.*)\nDefinition R05f (sc : cube) : cube := tnth [tuple of R05] sc.\n(*This definition specifies a permutation of the cube's faces as a finite sequence, representing a 270-degree rotation around the axis passing through the centers of faces zero and five.*)\nDefinition R50 := [:: F0; F3; F1; F4; F2; F5].\n(*This definition creates a function that applies the face permutation R50 to a given face of the cube.*)\nDefinition R50f (sc : cube) : cube := tnth [tuple of R50] sc.\n(*This definition specifies a permutation of the cube's faces as a finite sequence, representing a 90-degree rotation around the axis passing through the centers of faces one and four.*)\nDefinition R14 := [:: F3; F1; F0; F5; F4; F2].\n(*This definition creates a function that applies the face permutation R14 to a given face of the cube.*)\nDefinition R14f (sc : cube) : cube := tnth [tuple of R14] sc.\n(*This definition specifies a permutation of the cube's faces as a finite sequence, representing a 270-degree rotation around the axis passing through the centers of faces one and four.*)\nDefinition R41 := [:: F2; F1; F5; F0; F4; F3].\n(*This definition creates a function that applies the face permutation R41 to a given face of the cube.*)\nDefinition R41f (sc : cube) : cube := tnth [tuple of R41] sc.\n(*This definition specifies a permutation of the cube's faces as a finite sequence, representing a 90-degree rotation around the axis passing through the centers of faces two and three.*)\nDefinition R23 := [:: F1; F5; F2; F3; F0; F4].\n(*This definition creates a function that applies the face permutation R23 to a given face of the cube.*)\nDefinition R23f (sc : cube) : cube := tnth [tuple of R23] sc.\n(*This definition specifies a permutation of the cube's faces as a finite sequence, representing a 270-degree rotation around the axis passing through the centers of faces two and three.*)\nDefinition R32 := [:: F4; F0; F2; F3; F5; F1].\n(*This definition creates a function that applies the face permutation R32 to a given face of the cube.*)\nDefinition R32f (sc : cube) : cube := tnth [tuple of R32] sc.\n\n(*This definition specifies a permutation of the cube's faces as a finite sequence, representing a 120-degree rotation around an axis passing through a pair of opposite vertices of the cube.*)\nDefinition R024 := [:: F2; F5; F4; F1; F0; F3].\n(*This definition creates a function that applies the face permutation R024 to a given face of the cube.*)\nDefinition R024f (sc : cube) : cube := tnth [tuple of R024] sc.\n(*This definition specifies a permutation as a finite sequence of six elements, representing a rotational symmetry of a cube.*)\nDefinition R042 := [:: F4; F3; F0; F5; F2; F1].\n(*This definition specifies a function that applies the rotational permutation R042 to a given cube configuration, yielding a new cube configuration.*)\nDefinition R042f (sc : cube) : cube := tnth [tuple of R042] sc.\n(*This definition specifies a permutation as a finite sequence of six elements, representing a rotational symmetry of a cube.*)\nDefinition R012 := [:: F1; F2; F0; F5; F3; F4].\n(*This definition specifies a function that applies the rotational permutation R012 to a given cube configuration, yielding a new cube configuration.*)\nDefinition R012f (sc : cube) : cube := tnth [tuple of R012] sc.\n(*This definition specifies a permutation as a finite sequence of six elements, representing a rotational symmetry of a cube.*)\nDefinition R021 := [:: F2; F0; F1; F4; F5; F3].\n(*This definition specifies a function that applies the rotational permutation R021 to a given cube configuration, yielding a new cube configuration.*)\nDefinition R021f (sc : cube) : cube := tnth [tuple of R021] sc.\n(*This definition specifies a permutation as a finite sequence of six elements, representing a rotational symmetry of a cube.*)\nDefinition R031 := [:: F3; F0; F4; F1; F5; F2].\n(*This definition specifies a function that applies the rotational permutation R031 to a given cube configuration, yielding a new cube configuration.*)\nDefinition R031f (sc : cube) : cube := tnth [tuple of R031] sc.\n(*This definition specifies a permutation as a finite sequence of six elements, representing a rotational symmetry of a cube.*)\nDefinition R013 := [:: F1; F3; F5; F0; F2; F4].\n(*This definition specifies a function that applies the rotational permutation R013 to a given cube configuration, yielding a new cube configuration.*)\nDefinition R013f (sc : cube) : cube := tnth [tuple of R013] sc.\n(*This definition specifies a permutation as a finite sequence of six elements, representing a rotational symmetry of a cube.*)\nDefinition R043 := [:: F4; F2; F5; F0; F3; F1].\n(*This definition specifies a function that applies the rotational permutation R043 to a given cube configuration, yielding a new cube configuration.*)\nDefinition R043f (sc : cube) : cube := tnth [tuple of R043] sc.\n(*This definition specifies a permutation as a finite sequence of six elements, representing a rotational symmetry of a cube.*)\nDefinition R034 := [:: F3; F5; F1; F4; F0; F2].\n(*This definition specifies a function that applies the rotational permutation R034 to a given cube configuration, yielding a new cube configuration.*)\nDefinition R034f (sc : cube) : cube := tnth [tuple of R034] sc.\n\n(*This definition specifies an involutive permutation as a finite sequence of six elements, representing an involutive symmetry of a cube.*)\nDefinition S1 := [:: F5; F2; F1; F4; F3; F0].\n(*This definition specifies a function that applies the involutive permutation S1 to a given cube configuration, yielding a new cube configuration.*)\nDefinition S1f (sc : cube) : cube := tnth [tuple of S1] sc.\n(*This definition specifies an involutive permutation as a finite sequence of six elements, representing an involutive symmetry of a cube.*)\nDefinition S2 := [:: F5; F3; F4; F1; F2; F0].\n(*This definition specifies a function that applies the involutive permutation S2 to a given cube configuration, yielding a new cube configuration.*)\nDefinition S2f (sc : cube) : cube := tnth [tuple of S2] sc.\n(*This definition specifies an involutive permutation as a finite sequence of six elements, representing an involutive symmetry of a cube.*)\nDefinition S3 := [:: F1; F0; F3; F2; F5; F4].\n(*This definition specifies a function that applies the involutive permutation S3 to a given cube configuration, yielding a new cube configuration.*)\nDefinition S3f (sc : cube) : cube := tnth [tuple of S3] sc.\n(*This definition specifies an involutive permutation as a finite sequence of six elements, representing an involutive symmetry of a cube.*)\nDefinition S4 := [:: F4; F5; F3; F2; F0; F1].\n(*This definition specifies a function that applies the involutive permutation S4 to a given cube configuration, yielding a new cube configuration.*)\nDefinition S4f (sc : cube) : cube := tnth [tuple of S4] sc.\n(*This definition specifies an involutive permutation as a finite sequence of six elements, representing an involutive symmetry of a cube.*)\nDefinition S5 := [:: F2; F4; F0; F5; F1; F3].\n(*This definition specifies a function that applies the involutive permutation S5 to a given cube configuration, yielding a new cube configuration.*)\nDefinition S5f (sc : cube) : cube := tnth [tuple of S5] sc.\n(*This definition specifies an involutive permutation as a finite sequence of six elements, representing an involutive symmetry of a cube.*)\nDefinition S6 := [::F3; F4; F5; F0; F1; F2].\n(*This definition specifies a function that applies the involutive permutation S6 to a given cube configuration, yielding a new cube configuration.*)\nDefinition S6f (sc : cube) : cube := tnth [tuple of S6] sc.\n\n(*This lemma states that the cube transformation function S1f is involutive, which means that applying the transformation twice results in the original cube configuration.*)\nLemma S1_inv : involutive S1f.\n\n(*This lemma states that the cube transformation function S2f is involutive, which means that applying the transformation twice results in the original cube configuration.*)\nLemma S2_inv : involutive S2f.\n\n(*This lemma states that the cube transformation function S3f is involutive, which means that applying the transformation twice results in the original cube configuration.*)\nLemma S3_inv : involutive S3f.\n\n(*This lemma states that the cube transformation function S4f is involutive, which means that applying the transformation twice results in the original cube configuration.*)\nLemma S4_inv : involutive S4f.\n\n(*This lemma states that the function S5f is an involution, which means it is its own inverse.*)\nLemma S5_inv : involutive S5f.\n\n(*This lemma states that the function S6f is an involution, meaning that applying it twice is equivalent to the identity function.*)\nLemma S6_inv : involutive S6f.\n\n(*This lemma states that the function S05f is injective, which means it maps distinct inputs to distinct outputs.*)\nLemma S05_inj : injective S05f.\n\n(*This lemma states that the function S14f is injective, ensuring that different inputs are always mapped to different outputs.*)\nLemma S14_inj : injective S14f.\n\n(*This lemma states that the function S23f is an involution, meaning that applying the function twice restores the original input.*)\nLemma S23_inv : involutive S23f.\n\n(*This lemma states that the function R05f is injective, meaning it never maps two different inputs to the same output.*)\nLemma R05_inj : injective R05f.\n\n(*This lemma states that the function R14f is injective, guaranteeing that distinct inputs produce distinct outputs.*)\nLemma R14_inj : injective R14f.\n\n(*This lemma states that the function R23f is injective, which ensures that every output corresponds to a unique input.*)\nLemma R23_inj : injective R23f.\n\n(*This lemma states that the function R50f is injective and maps distinct elements of its domain to distinct elements of its codomain.*)\nLemma R50_inj : injective R50f.\n\n(*This lemma states that the function R41f is an injective function, which means no two distinct inputs are mapped to the same output.*)\nLemma R41_inj : injective R41f.\n\n(*This lemma states that the function R32f is injective, meaning it preserves the distinctness of elements.*)\nLemma R32_inj : injective R32f.\n\n(*This lemma states that the function R024f is injective, so different inputs will always yield different results.*)\nLemma R024_inj : injective R024f.\n\n(*This lemma states that the function R042f is an injective function, meaning that applying it to two different values will produce two different results.*)\nLemma R042_inj : injective R042f.\n\n(*This lemma states that the function R012f is injective, ensuring a one-to-one mapping from its input domain to its output codomain.*)\nLemma R012_inj : injective R012f.\n\n(*This lemma states that the function R021f is injective, which means that two distinct inputs cannot produce the same output.*)\nLemma R021_inj : injective R021f.\n\n(*This lemma states that the function R031f is an injective function that preserves the distinctness of its arguments.*)\nLemma R031_inj : injective R031f.\n\n(*This lemma states that the function R013f is injective, guaranteeing that each output value is associated with at most one input value.*)\nLemma R013_inj : injective R013f.\n\n(*This lemma states that the function R043f is an injective function, meaning that distinct input values are always mapped to distinct output values.*)\nLemma R043_inj : injective R043f.\n\n(*This lemma states that the function R034f is an injective function that maps distinct inputs to distinct outputs.*)\nLemma R034_inj : injective R034f.\n\n(*This definition introduces 'id3' as the identity permutation on the elements of a cube, a transformation that leaves every element unchanged.*)\nDefinition id3 := 1 : {perm cube}.\n\n(*This definition introduces 's05' as a permutation on the elements of a cube, which is constructed from the injective function S05f.*)\nDefinition s05 := (perm S05_inj).\n\n(*This definition declares 's14' as a permutation on the elements of a cube, which represents a specific symmetry transformation.*)\nDefinition s14 : {perm cube}.\n\n(*This definition introduces 's23' as a permutation on the elements of a cube, constructed from the function S23f, whose injectivity is derived from the fact that it is an involution.*)\nDefinition s23 := (perm (inv_inj S23_inv)).\n(*This definition introduces 'r05' as a permutation on the elements of a cube, created from the injective function R05f.*)\nDefinition r05 := (perm R05_inj).\n(*This definition introduces 'r14', a permutation on the elements of a cube, which is based on the injective function R14f.*)\nDefinition r14 := (perm R14_inj).\n(*This definition introduces 'r23' as a permutation on the elements of a cube that is constructed from the injective function R23f.*)\nDefinition r23 := (perm R23_inj).\n(*This definition introduces 'r50' as a permutation on the elements of a cube, which is based on the injective function R50f.*)\nDefinition r50 := (perm R50_inj).\n(*This definition introduces 'r41' as a permutation on the elements of a cube that is constructed using the injective function R41f.*)\nDefinition r41 := (perm R41_inj).\n(*This definition introduces 'r32' as a permutation on the elements of a cube, which is based on the injective function R32f.*)\nDefinition r32 := (perm R32_inj).\n(*This definition introduces 'r024' as a permutation on the elements of a cube, derived from the injective function R024f.*)\nDefinition r024 := (perm R024_inj).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying injective function that defines the mapping.*)\nDefinition r042 := (perm R042_inj).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying injective function that defines the mapping.*)\nDefinition r012 := (perm R012_inj).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying injective function that defines the mapping.*)\nDefinition r021 := (perm R021_inj).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying injective function that defines the mapping.*)\nDefinition r031 := (perm R031_inj).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying injective function that defines the mapping.*)\nDefinition r013 := (perm R013_inj).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying injective function that defines the mapping.*)\nDefinition r043 := (perm R043_inj).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying injective function that defines the mapping.*)\nDefinition r034 := (perm R034_inj).\n\n(*This definition specifies a permutation on the faces of a cube, created from an underlying involutive function that defines the mapping.*)\nDefinition s1 := (perm (inv_inj S1_inv)).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying involutive function that defines the mapping.*)\nDefinition s2 := (perm (inv_inj S2_inv)).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying involutive function that defines the mapping.*)\nDefinition s3 := (perm (inv_inj S3_inv)).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying involutive function that defines the mapping.*)\nDefinition s4 := (perm (inv_inj S4_inv)).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying involutive function that defines the mapping.*)\nDefinition s5 := (perm (inv_inj S5_inv)).\n(*This definition specifies a permutation on the faces of a cube, created from an underlying involutive function that defines the mapping.*)\nDefinition s6 := (perm (inv_inj S6_inv)).\n\n(*This definition specifies the set of all direct isometries of a cube, represented as a finite set of permutations of the cube's faces.*)\nDefinition dir_iso3 := [set p |\n[|| id3 == p, s05 == p, s14 == p, s23 == p, r05 == p, r14 == p, r23 == p,\n r50 == p, r41 == p, r32 == p, r024 == p, r042 == p, r012 == p, r021 == p,\n r031 == p, r013 == p, r043 == p, r034 == p,\n s1 == p, s2 == p, s3 == p, s4 == p, s5 == p | s6 == p]].\n\n(*This definition provides a finite sequence containing all the direct isometries of a cube, with each isometry represented as a permutation of the cube's faces.*)\nDefinition dir_iso3l := [:: id3; s05; s14; s23; r05; r14; r23; r50; r41;\n r32; r024; r042; r012; r021; r031; r013; r043; r034;\n s1; s2; s3; s4; s5; s6].\n\n(*This definition establishes a finite sequence of cube faces that represents a permutation mapping each face to its opposite.*)\nDefinition S0 := [:: F5; F4; F3; F2; F1; F0].\n(*This definition describes a function that maps a given face of a cube to its opposite face.*)\nDefinition S0f (sc : cube) : cube := tnth [tuple of S0] sc.\n\n(*This lemma states that the function which maps each face of a cube to its opposite is an involution, meaning applying it twice yields the original face.*)\nLemma S0_inv : involutive S0f.\n\n(*This definition constructs the permutation of a cube's faces corresponding to the central symmetry, where each face is mapped to its opposite.*)\nDefinition s0 := (perm (inv_inj S0_inv)).\n\n(*This definition provides a predicate to determine if a given permutation of a cube's faces is an isometry, which holds if the permutation commutes with the central symmetry that maps each face to its opposite.*)\nDefinition is_iso3 (p : {perm cube}) := forall fi, p (s0 fi) = s0 (p fi).\n\n(*This lemma states that any permutation belonging to the set of direct isometries of a cube is also an isometry of the cube, meaning it commutes with the central symmetry.*)\nLemma dir_iso_iso3 : forall p, p \\in dir_iso3 -> is_iso3 p.\n\n(*This lemma states that for any permutation that is a direct isometry of a cube, its composition with the central symmetry permutation also results in an isometry of the cube.*)\nLemma iso3_ndir : forall p, p \\in dir_iso3 -> is_iso3 (s0 * p).\n\n(*This definition introduces a function that converts a permutation of a cube's faces into a finite sequence representing its function graph, where the element at each position in the sequence is the image of the corresponding face under the permutation.*)\nDefinition sop (p : {perm cube}) : seq cube := fgraph (val p).\n\n(*This lemma states that the function converting a permutation of a cube's faces into its corresponding function graph sequence is injective, meaning distinct permutations map to distinct sequences.*)\nLemma sop_inj : injective sop.\n\n(*This definition describes a function that computes the composition of two permutations of a cube's faces, where the input permutations are provided as finite sequences representing their function graphs.*)\nDefinition prod_tuple (t1 t2 : seq cube) :=\n map (fun n : 'I_6 => nth F0 t2 n) t1.\n\n(*This lemma states that for any given permutation of a cube's faces, the element at a specific index in its function graph sequence is equal to the result of applying the permutation to the face corresponding to that index.*)\nLemma sop_spec x (n0 : 'I_6): nth F0 (sop x) n0 = x n0.\n\n(*This lemma states that composing two permutations of a cube's faces and then applying the result to a face yields the same outcome as first converting the permutations to their sequence representations, composing these sequences, and then retrieving the element corresponding to that face.*)\nLemma prod_t_correct : forall (x y : {perm cube}) (i : cube),\n (x * y) i = nth F0 (prod_tuple (sop x) (sop y)) i.\n\n(*This declaration establishes that the function converting a permutation to its sequence representation is a morphism, mapping the composition of permutations to the corresponding composition of their sequence representations.*)\nLemma sop_morph : {morph sop : x y / x * y >-> prod_tuple x y}.\n\n(*This definition provides a finite sequence that enumerates the six faces of a cube in a canonical order.*)\nDefinition ecubes : seq cube := [:: F0; F1; F2; F3; F4; F5].\n\n(*This lemma states that the canonical finite sequence of cube faces is equivalent to the complete enumeration of all elements of the cube face type.*)\nLemma ecubes_def : ecubes = enum (@predT cube).\n\n(*This definition provides a concrete list of signed permutations that represents the set of direct isomorphisms of a cube.*)\nDefinition seq_iso_L := [::\n [:: F0; F1; F2; F3; F4; F5];\n S05; S14; S23; R05; R14; R23; R50; R41; R32;\n R024; R042; R012; R021; R031; R013; R043; R034;\n S1; S2; S3; S4; S5; S6].\n\n(*This lemma states that applying the `sop` operator to a permutation is equivalent to mapping that permutation function over the canonical sequence of cube vertices.*)\nLemma seqs1 : forall f injf, sop (@perm _ f injf) = map f ecubes.\n\n(*This lemma states that the sequence `seq_iso_L` is equal to the sequence obtained by applying the `sop` operator to each of the 24 canonical permutations representing the direct isomorphisms of a cube.*)\nLemma Lcorrect : seq_iso_L == map sop [:: id3; s05; s14; s23; r05; r14; r23;\n r50; r41; r32; r024; r042; r012; r021; r031; r013; r043; r034;\n s1; s2; s3; s4; s5; s6].\n\n(*This lemma states that the set of direct cube isomorphisms `dir_iso3` is equivalent to the set `dir_iso3l`.*)\nLemma iso0_1 : dir_iso3 =i dir_iso3l.\n\n(*This lemma states that a permutation belongs to the set of direct cube isomorphisms if and only if its sequence representation, obtained via the `sop` operator, is a member of the list `seq_iso_L`.*)\nLemma L_iso : forall p, (p \\in dir_iso3) = (sop p \\in seq_iso_L).\n\n(*This lemma states that the set of direct cube isomorphisms is closed under composition; the product of any two such isomorphisms is also a direct cube isomorphism.*)\nLemma stable : forall x y,\n x \\in dir_iso3 -> y \\in dir_iso3 -> x * y \\in dir_iso3.\n\n(*This lemma states that two direct cube isomorphisms are equal if they map the canonical elements `F0` and `F1` to the same respective results.*)\nLemma iso_eq_F0_F1 : forall r s : {perm cube}, r \\in dir_iso3 ->\n s \\in dir_iso3 -> r F0 = s F0 -> r F1 = s F1 -> r = s.\n\n(*This lemma states that for any direct cube isomorphism, its composition with the specific permutation `s0` is not a direct cube isomorphism.*)\nLemma ndir_s0p : forall p, p \\in dir_iso3 -> s0 * p \\notin dir_iso3.\n\n(*This definition creates the set of indirect cube isomorphisms by composing each element of the set of direct cube isomorphisms `dir_iso3l` with the specific permutation `s0`.*)\nDefinition indir_iso3l := map (mulg s0) dir_iso3l.\n\n(*This definition creates the list of all cube isomorphisms by concatenating the list of direct isomorphisms with the list of indirect isomorphisms.*)\nDefinition iso3l := dir_iso3l ++ indir_iso3l.\n\n(*This definition creates the sequence representation of all cube isomorphisms by applying the `sop` operator to each element in the list of all isomorphisms `iso3l`.*)\nDefinition seq_iso3_L := map sop iso3l.\n\n(*This lemma states that two cube permutations are equal if and only if they map every element from the canonical set `ecubes` to the same result.*)\nLemma eqperm : forall p1 p2 : {perm cube},\n (p1 == p2) = all (fun s => p1 s == p2 s) ecubes.\n\n(*This lemma states that two cube isomorphisms are equal if they both map the canonical elements `F0`, `F1`, and `F2` to the same respective results.*)\nLemma iso_eq_F0_F1_F2 : forall r s : {perm cube}, is_iso3 r ->\n is_iso3 s -> r F0 = s F0 -> r F1 = s F1 -> r F2 = s F2 -> r = s.\n\n(*This definition introduces a proof tactic named `iso_tac` designed to automatically prove the equality of two permutations by unfolding their definitions and performing case analysis on their arguments.*)\nLtac iso_tac :=\n let a := fresh \"a\" in apply/permP => a;\n apply/eqP; rewrite !permM !permE; case: a; do 6?case.\n\n(*This definition introduces a proof tactic named `inv_tac` for proving properties related to the inverse of a permutation, typically by showing that the product of a permutation and its proposed inverse is the identity element.*)\nLtac inv_tac :=\n apply: esym (etrans _ (mul1g _)); apply: canRL (mulgK _) _; iso_tac.\n\n(*This lemma states that if the composition of a specific permutation `s0` with another permutation `p` results in a direct cube isomorphism, then `p` itself cannot be a direct cube isomorphism.*)\nLemma dir_s0p : forall p, (s0 * p) \\in dir_iso3 -> p \\notin dir_iso3.\n\n(*This definition introduces a boolean predicate that checks if a given permutation commutes with the specific permutation `s0`.*)\nDefinition is_iso3b p := (p * s0 == s0 * p).\n(*This definition establishes the set `iso3` as the collection of all permutations that satisfy the `is_iso3b` predicate, which corresponds to the full group of cube isomorphisms.*)\nDefinition iso3 := [set p | is_iso3b p].\n\n(*This lemma states that the boolean predicate `is_iso3` is provably true for a permutation if and only if that permutation is a member of the set `iso3`.*)\nLemma is_iso3P : forall p, reflect (is_iso3 p) (p \\in iso3).\n\n(*This lemma states that the set of all cube isomorphisms, `iso3`, forms a group under permutation composition.*)\nLemma group_set_iso3 : group_set iso3.\n\nCanonical iso_group3 := Group group_set_iso3.\n\n(*This lemma states that the set of direct cube isomorphisms, `dir_iso3`, forms a group under permutation composition.*)\nLemma group_set_diso3 : group_set dir_iso3.\n\nCanonical diso_group3 := Group group_set_diso3.\n\n(*This lemma states that the group of direct cube isomorphisms is generated by the set containing the two specific rotations `r05` and `r14`.*)\nLemma gen_diso3 : dir_iso3 = <<[set r05; r14]>>.\n\n(*This notation defines `col_cubes` as an abbreviation for the type of finite functions that map cube elements to colors, representing a coloring of the cube.*)\nNotation col_cubes := {ffun cube -> colors}.\n\n(*This definition specifies a group action where a permutation acts on a cube coloring. The resulting coloring at any given location is determined by the original coloring at the location that the inverse of the permutation maps to it.*)\nDefinition act_g (sc : col_cubes) (p : {perm cube}) : col_cubes :=\n [ffun z => sc (p^-1 z)].\n\n(*This lemma states that the action of the identity permutation on any cube coloring results in the original coloring.*)\nLemma act_g_1 : forall k, act_g k 1 = k.\n\n(*This lemma states that the action of a composition of two permutations on a cube coloring is equivalent to applying the action of the first permutation and then applying the action of the second permutation to the resulting coloring.*)\nLemma act_g_morph : forall k x y, act_g k (x * y) = act_g (act_g k x) y.\n\n(*This definition bundles the group action `act_g` with its required properties into a single `TotalAction` structure, formally representing the action of the permutation group on cube colorings.*)\nDefinition to_g := TotalAction act_g_1 act_g_morph.\n\n(*This definition specifies a value representing the number of distinct colorings of a cube under the action of the group of direct isomorphisms, calculated as the number of orbits of the set of all colorings.*)\nDefinition cube_coloring_number24 := #|orbit to_g diso_group3 @: setT|.\n\n(*This lemma states that the set of colorings that are fixed by the identity permutation under the action `to_g` is equal to the set of all possible colorings.*)\nLemma Fid3 : 'Fix_to_g[1] = setT.\n\n(*This lemma states that the number of colorings fixed by the identity permutation is equal to the total number of available colors raised to the power of six.*)\nLemma card_Fid3 : #|'Fix_to_g[1]| = (n ^ 6)%N.\n\n(*This definition retrieves the color associated with face 0 from a given cube coloring.*)\nDefinition col0 (sc : col_cubes) : colors := sc F0.\n(*This definition retrieves the color associated with face 1 from a given cube coloring.*)\nDefinition col1 (sc : col_cubes) : colors := sc F1.\n(*This definition retrieves the color associated with face 2 from a given cube coloring.*)\nDefinition col2 (sc : col_cubes) : colors := sc F2.\n(*This definition retrieves the color associated with face 3 from a given cube coloring.*)\nDefinition col3 (sc : col_cubes) : colors := sc F3.\n(*This definition retrieves the color associated with face 4 from a given cube coloring.*)\nDefinition col4 (sc : col_cubes) : colors := sc F4.\n(*This definition retrieves the color associated with face 5 from a given cube coloring.*)\nDefinition col5 (sc : col_cubes) : colors := sc F5.\n\n(*This lemma states that two cube colorings are equal if and only if they assign the same color to each of the six corresponding faces, from face 0 through face 5.*)\nLemma eqperm_map2 : forall p1 p2 : col_cubes,\n (p1 == p2) = all (fun s => p1 s == p2 s) [:: F0; F1; F2; F3; F4; F5].\n\n(*This notation provides an alias for the property of injectivity. A function is injective if applying it to two arguments yields the same result if and only if the arguments are equal.*)\nNotation infE := (sameP afix1P eqP).\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation s05. A coloring is a fixed point if the color of its face 1 is identical to the color of its face 4, and the color of its face 2 is identical to the color of its face 3.*)\nLemma F_s05 :\n 'Fix_to_g[s05] = [set x | (col1 x == col4 x) && (col2 x == col3 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation s14. A coloring is a fixed point if the color of its face 0 is identical to the color of its face 5, and the color of its face 2 is identical to the color of its face 3.*)\nLemma F_s14 :\n 'Fix_to_g[s14]= [set x | (col0 x == col5 x) && (col2 x == col3 x)].\n\n(*This lemma states that the inverse of the permutation r05 is the permutation r50.*)\nLemma r05_inv : r05^-1 = r50.\n\n(*This lemma states that the inverse of the permutation r50 is the permutation r05.*)\nLemma r50_inv : r50^-1 = r05.\n\n(*This lemma states that the inverse of the permutation r14 is the permutation r41.*)\nLemma r14_inv : r14^-1 = r41.\n\n(*This lemma states that the inverse of the permutation r41 is the permutation r14.*)\nLemma r41_inv : r41^-1 = r14.\n\n(*This lemma states that the permutation s23 is its own inverse.*)\nLemma s23_inv : s23^-1 = s23.\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation s23. A coloring is a fixed point if the color of its face 0 is identical to the color of its face 5, and the color of its face 1 is identical to the color of its face 4.*)\nLemma F_s23 :\n 'Fix_to_g[s23] = [set x | (col0 x == col5 x) && (col1 x == col4 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r05. A coloring is a fixed point if its faces 1, 2, 3, and 4 all have the same color.*)\nLemma F_r05 : 'Fix_to_g[r05]=\n [set x | (col1 x == col2 x) && (col2 x == col3 x)\n && (col3 x == col4 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r50. A coloring is a fixed point if its faces 1, 2, 3, and 4 all have the same color.*)\nLemma F_r50 : 'Fix_to_g[r50]=\n [set x | (col1 x == col2 x) && (col2 x == col3 x)\n && (col3 x == col4 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r23. A coloring is a fixed point if its faces 0, 1, 4, and 5 all have the same color.*)\nLemma F_r23 : 'Fix_to_g[r23] =\n [set x | (col0 x == col1 x) && (col1 x == col4 x)\n && (col4 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r32. A coloring is a fixed point if its faces 0, 1, 4, and 5 all have the same color.*)\nLemma F_r32 : 'Fix_to_g[r32] =\n [set x | (col0 x == col1 x) && (col1 x == col4 x)\n && (col4 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r14. A coloring is a fixed point if its faces 0, 2, 3, and 5 all have the same color.*)\nLemma F_r14 : 'Fix_to_g[r14] =\n [set x | (col0 x == col2 x) && (col2 x == col3 x) && (col3 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r41. A coloring is a fixed point if its faces 0, 2, 3, and 5 all have the same color.*)\nLemma F_r41 : 'Fix_to_g[r41] =\n [set x | (col0 x == col2 x) && (col2 x == col3 x) && (col3 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r024. A coloring is a fixed point if its faces 0, 4, and 2 all have the same color, and its faces 1, 3, and 5 also all have the same color.*)\nLemma F_r024 : 'Fix_to_g[r024] =\n [set x | (col0 x == col4 x) && (col4 x == col2 x) && (col1 x == col3 x)\n && (col3 x == col5 x) ].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r042. A coloring is a fixed point if its faces 0, 4, and 2 all have the same color, and its faces 1, 3, and 5 also all have the same color.*)\nLemma F_r042 : 'Fix_to_g[r042] =\n [set x | (col0 x == col4 x) && (col4 x == col2 x) && (col1 x == col3 x)\n && (col3 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r012. A coloring is a fixed point if its faces 0, 2, and 1 all have the same color, and its faces 3, 4, and 5 also all have the same color.*)\nLemma F_r012 : 'Fix_to_g[r012] =\n [set x | (col0 x == col2 x) && (col2 x == col1 x) && (col3 x == col4 x)\n && (col4 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r021. A coloring is a fixed point if its faces 0, 2, and 1 all have the same color, and its faces 3, 4, and 5 also all have the same color.*)\nLemma F_r021 : 'Fix_to_g[r021] =\n [set x | (col0 x == col2 x) && (col2 x == col1 x) && (col3 x == col4 x)\n && (col4 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r031. A coloring is a fixed point if its faces 0, 3, and 1 all have the same color, and its faces 2, 4, and 5 also all have the same color.*)\nLemma F_r031 : 'Fix_to_g[r031] =\n [set x | (col0 x == col3 x) && (col3 x == col1 x) && (col2 x == col4 x)\n && (col4 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r013. A coloring is a fixed point if its faces 0, 3, and 1 all have the same color, and its faces 2, 4, and 5 also all have the same color.*)\nLemma F_r013 : 'Fix_to_g[r013] =\n [set x | (col0 x == col3 x) && (col3 x == col1 x) && (col2 x == col4 x)\n && (col4 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r043. A coloring is a fixed point if its faces 0, 4, and 3 all have the same color, and its faces 1, 2, and 5 also all have the same color.*)\nLemma F_r043 : 'Fix_to_g[r043] =\n [set x | (col0 x == col4 x) && (col4 x == col3 x) && (col1 x == col2 x)\n && (col2 x == col5 x)].\n\n(*This lemma characterizes the set of cube colorings that are fixed points of the permutation r034. A coloring is a fixed point if its faces 0, 3, and 4 all have one color, and its faces 1, 2, and 5 all have another color.*)\nLemma F_r034 : 'Fix_to_g[r034] =\n [set x | (col0 x == col4 x) && (col4 x == col3 x) && (col1 x == col2 x)\n && (col2 x == col5 x)].\n\n(*This lemma states that the set of fixed points of a cube coloring under the group action s1 consists of all colorings where the color of the zeroth face is identical to the fifth, the first face's color matches the second, and the third face's color matches the fourth.*)\nLemma F_s1 : 'Fix_to_g[s1] =\n [set x | (col0 x == col5 x) && (col1 x == col2 x) && (col3 x == col4 x)].\n\n(*This lemma states that the set of fixed points of a cube coloring under the group action s2 consists of all colorings where the color of the zeroth face is identical to the fifth, the first face's color matches the third, and the second face's color matches the fourth.*)\nLemma F_s2 : 'Fix_to_g[s2] =\n [set x | (col0 x == col5 x) && (col1 x == col3 x) && (col2 x == col4 x)].\n\n(*This lemma states that the set of fixed points of a cube coloring under the group action s3 consists of all colorings where the color of the zeroth face is identical to the first, the second face's color matches the third, and the fourth face's color matches the fifth.*)\nLemma F_s3 : 'Fix_to_g[s3] =\n [set x | (col0 x == col1 x) && (col2 x == col3 x) && (col4 x == col5 x)].\n\n(*This lemma states that the set of fixed points of a cube coloring under the group action s4 consists of all colorings where the color of the zeroth face is identical to the fourth, the first face's color matches the fifth, and the second face's color matches the third.*)\nLemma F_s4 : 'Fix_to_g[s4] =\n [set x | (col0 x == col4 x) && (col1 x == col5 x) && (col2 x == col3 x)].\n\n(*This lemma states that the set of fixed points of a cube coloring under the group action s5 consists of all colorings where the color of the zeroth face is identical to the second, the first face's color matches the fourth, and the third face's color matches the fifth.*)\nLemma F_s5 : 'Fix_to_g[s5] =\n [set x | (col0 x == col2 x) && (col1 x == col4 x) && (col3 x == col5 x)].\n\n(*This lemma states that the set of fixed points of a cube coloring under the group action s6 consists of all colorings where the color of the zeroth face is identical to the third, the first face's color matches the fourth, and the second face's color matches the fifth.*)\nLemma F_s6 : 'Fix_to_g[s6] =\n [set x | (col0 x == col3 x) && (col1 x == col4 x) && (col2 x == col5 x)].\n\n(*This lemma asserts that for any given finite sequence containing four distinct cube configurations, there exist two additional distinct cube configurations that can extend the sequence to a new finite sequence containing six distinct configurations.*)\nLemma uniq4_uniq6 : forall x y z t : cube,\n uniq [:: x; y; z; t] -> exists u, exists v, uniq [:: x; y; z; t; u; v].\n\n(*This lemma states that for any four distinct cube faces, the number of distinct colorings where the first face has the same color as the second and the third face has the same color as the fourth is equal to the fourth power of the number of available colors.*)\nLemma card_n4 : forall x y z t : cube, uniq [:: x; y; z; t] ->\n #|[set p : col_cubes | (p x == p y) && (p z == p t)]| = (n ^ 4)%N.\n\n(*This lemma states that for any four distinct cube faces, the number of distinct colorings where all four faces must have the same color is equal to the third power of the number of available colors.*)\nLemma card_n3_3 : forall x y z t: cube, uniq [:: x; y; z; t] ->\n #|[set p : col_cubes | (p x == p y) && (p y == p z)&& (p z == p t)]|\n = (n ^ 3)%N.\n\n(*This lemma states that for any six distinct cube faces, the number of distinct colorings where the first three faces share a common color and the remaining three faces share another common color is equal to the second power of the number of available colors.*)\nLemma card_n2_3 : forall x y z t u v: cube, uniq [:: x; y; z; t; u; v] ->\n #|[set p : col_cubes | (p x == p y) && (p y == p z)&& (p t == p u )\n && (p u== p v)]| = (n ^ 2)%N.\n\n(*This lemma states that for any six distinct cube faces, the number of distinct colorings where the faces are partitioned into three pairs, with each pair required to have a matching color, is equal to the third power of the number of available colors.*)\nLemma card_n3s : forall x y z t u v: cube, uniq [:: x; y; z; t; u; v] ->\n #|[set p : col_cubes | (p x == p y) && (p z == p t)&& (p u == p v )]|\n = (n ^ 3)%N.\n\n(*This lemma provides the equation from Burnside's Lemma for counting distinct cube colorings with a given number of colors. It states that twenty-four times the number of distinct colorings is equal to a sum of terms: the sixth power of the number of colors, plus six times its third power, plus three times its fourth power, plus eight times its second power, plus another six times its third power.*)\nLemma burnside_app_iso3 :\n (cube_coloring_number24 * 24 =\n n ^ 6 + 6 * n ^ 3 + 3 * n ^ 4 + 8 * (n ^ 2) + 6 * n ^ 3)%N.\n\nEnd cube_colouring.\n\nEnd colouring.\n\n(*This corollary states that the number of distinct ways to color the faces of a cube using exactly three colors, when considering rotational symmetries, is fifty-seven.*)\nCorollary burnside_app_iso_3_3col: cube_coloring_number24 3 = 57.\n\n(*This corollary states that the number of distinct ways to color the faces of a cube using exactly four colors, when considering rotational symmetries, is two hundred and forty.*)\nCorollary burnside_app_iso_2_4col: square_coloring_number8 4 = 55.", - "solvable.primitive_action": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat.\nFrom mathcomp Require Import div seq fintype tuple finset.\nFrom mathcomp Require Import fingroup action gseries.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection PrimitiveDef.\n\nVariables (aT : finGroupType) (sT : finType).\nVariables (A : {set aT}) (S : {set sT}) (to : {action aT &-> sT}).\n\n(*This definition specifies the property of being a system of imprimitivity for a group action. A set of subsets forms a system of imprimitivity if it is a non-trivial partition of the acted-upon set, and the acting group permutes the blocks of this partition.*)\nDefinition imprimitivity_system Q :=\n [&& partition Q S, [acts A, on Q | to^*] & 1 < #|Q| < #|S|].\n\n(*This definition specifies the property of a group action being primitive. An action of a group on a set is primitive if it is transitive and it does not preserve any non-trivial partition of the set.*)\nDefinition primitive :=\n [transitive A, on S | to] && ~~ [exists Q, imprimitivity_system Q].\n\nEnd PrimitiveDef.\n\nArguments imprimitivity_system {aT sT} A%_g S%_g to%_act Q%_g.\nArguments primitive {aT sT} A%_g S%_g to%_act.\n\n(*This notation provides a syntax to express that a given group action is primitive. It takes an acting group, a set on which the group acts, and the action itself, and evaluates to a boolean indicating whether the action is primitive.*)\nNotation \"[ 'primitive' A , 'on' S | to ]\" := (primitive A S to)\n (format \"[ 'primitive' A , 'on' S | to ]\") : form_scope.\n\nSection Primitive.\n\nVariables (aT : finGroupType) (sT : finType).\nVariables (G : {group aT}) (to : {action aT &-> sT}) (S : {set sT}).\n\n(*This lemma states that for a transitive group action on a set, the action is primitive if and only if the stabilizer of any element in the set is a maximal subgroup of the acting group.*)\nLemma trans_prim_astab x :\n x \\in S -> [transitive G, on S | to] ->\n [primitive G, on S | to] = maximal_eq 'C_G[x | to] G.\n\n(*This lemma states that if a group acts primitively on a set, then any normal subgroup of the acting group either acts trivially on the set, which means it fixes every element, or acts transitively on the set.*)\nLemma prim_trans_norm (H : {group aT}) :\n [primitive G, on S | to] -> H <| G ->\n H \\subset 'C_G(S | to) \\/ [transitive H, on S | to].\n\nEnd Primitive.\n\nSection NactionDef.\n\nVariables (gT : finGroupType) (sT : finType).\nVariables (to : {action gT &-> sT}) (n : nat).\n\n(*This definition describes a group action on finite sequences of a given length. This action is derived from an existing action on the elements of the sequence, applying the original action to each element of the sequence component-wise.*)\nDefinition n_act (t : n.-tuple sT) a := [tuple of map (to^~ a) t].\n\n(*This fact asserts that the component-wise application of a group action to finite sequences of a fixed length itself constitutes a valid group action.*)\nFact n_act_is_action : is_action setT n_act.\n\nCanonical n_act_action := Action n_act_is_action.\n\nEnd NactionDef.\n\n(*This notation denotes the induced group action on finite sequences of a specific length, which is derived by applying an original action component-wise to the elements of the sequence.*)\nNotation \"to * n\" := (n_act_action to n) : action_scope.\n\nSection NTransitive.\n\nVariables (gT : finGroupType) (sT : finType).\nVariables (n : nat) (A : {set gT}) (S : {set sT}) (to : {action gT &-> sT}).\n\n(*This definition describes the set of all finite sequences of a specific length whose elements are distinct and belong to a given base set.*)\nDefinition dtuple_on := [set t : n.-tuple sT | uniq t & t \\subset S].\n(*This definition specifies the property of a group action being n-transitive. An action is n-transitive on a set if it acts transitively on the set of all finite sequences of length n containing distinct elements from that set.*)\nDefinition ntransitive := [transitive A, on dtuple_on | to * n].\n\n(*This lemma provides a reflection property, stating that a finite sequence belongs to the set of sequences with distinct elements from a given base set if and only if the elements of the sequence are all distinct and each element is a member of the base set.*)\nLemma dtuple_onP t :\n reflect (injective (tnth t) /\\ forall i, tnth t i \\in S) (t \\in dtuple_on).\n\n(*This lemma states that the set of finite sequences with distinct elements from a given base set is closed under the component-wise group action, provided the group element belongs to the normalizer of the base set.*)\nLemma n_act_dtuple t a :\n a \\in 'N(S | to) -> t \\in dtuple_on -> n_act to t a \\in dtuple_on.\n\nEnd NTransitive.\n\nArguments dtuple_on {sT} n%_N S%_g.\nArguments ntransitive {gT sT} n%_N A%_g S%_g to%_act.\nArguments n_act {gT sT} to {n} t a.\n\n(*This notation represents the set of all finite sequences of a given natural number length, where all elements in each sequence are distinct and belong to a given set.*)\nNotation \"n .-dtuple ( S )\" := (dtuple_on n S)\n (at level 8, format \"n .-dtuple ( S )\") : set_scope.\n\n(*This notation provides a syntax to express that a group action is n-transitive. It takes a natural number n, an acting group, a set on which the group acts, and the action itself, and evaluates to a boolean indicating whether the action is n-transitive.*)\nNotation \"[ 'transitive' ^ n A , 'on' S | to ]\" := (ntransitive n A S to)\n (n at level 8,\n format \"[ 'transitive' ^ n A , 'on' S | to ]\") : form_scope.\n\nSection NTransitveProp.\n\nVariables (gT : finGroupType) (sT : finType).\nVariables (to : {action gT &-> sT}) (G : {group gT}) (S : {set sT}).\n\n(*This lemma states that for any finite sequence with distinct elements, the number of unique elements in the sequence is equal to the length of the sequence.*)\nLemma card_uniq_tuple n (t : n.-tuple sT) : uniq t -> #|t| = n.\n\n(*This lemma states that the component-wise group action applied to the empty finite sequence results in the empty finite sequence, regardless of the group element used.*)\nLemma n_act0 (t : 0.-tuple sT) a : n_act to t a = [tuple].\n\n(*This lemma provides a condition for extending a finite sequence of distinct elements. It states that prepending a new element to such a sequence results in a longer sequence of distinct elements if and only if the new element belongs to the base set, is not already in the original sequence, and the original sequence itself consists of distinct elements from the base set.*)\nLemma dtuple_on_add n x (t : n.-tuple sT) :\n ([tuple of x :: t] \\in n.+1.-dtuple(S)) =\n [&& x \\in S, x \\notin t & t \\in n.-dtuple(S)].\n\n(*This lemma provides an alternative condition for extending a finite sequence of distinct elements from a base set. It states that prepending an element to a sequence creates a valid longer sequence of distinct elements if and only if the prepended element is in the base set and the original sequence consists of distinct elements drawn from the base set excluding the prepended element.*)\nLemma dtuple_on_add_D1 n x (t : n.-tuple sT) :\n ([tuple of x :: t] \\in n.+1.-dtuple(S))\n = (x \\in S) && (t \\in n.-dtuple(S :\\ x)).\n\n(*This lemma states that if one set is a subset of another, then any finite sequence of distinct elements from the smaller set is also a finite sequence of distinct elements from the larger set.*)\nLemma dtuple_on_subset n (S1 S2 : {set sT}) t :\n S1 \\subset S2 -> t \\in n.-dtuple(S1) -> t \\in n.-dtuple(S2).\n\n(*This lemma describes how the component-wise group action behaves with respect to finite sequences constructed by prepending an element. It states that acting on such a sequence is equivalent to prepending the result of the action on the first element to the result of the action on the rest of the sequence.*)\nLemma n_act_add n x (t : n.-tuple sT) a :\n n_act to [tuple of x :: t] a = [tuple of to x a :: n_act to t a].\n\n(*This lemma states that any group action on a set is trivially 0-transitive, because the set of empty sequences with distinct elements contains only one element, which is the empty sequence.*)\nLemma ntransitive0 : [transitive^0 G, on S | to].\n\n(*This lemma states that if a group action is m-transitive, it is also k-transitive for any natural number k that is less than or equal to m.*)\nLemma ntransitive_weak k m :\n k <= m -> [transitive^m G, on S | to] -> [transitive^k G, on S | to].\n\n(*This lemma states that any n-transitive action, where n is a positive number, is also transitive, which is equivalent to 1-transitive.*)\nLemma ntransitive1 m :\n 0 < m -> [transitive^m G, on S | to] -> [transitive G, on S | to].\n\n(*This lemma states that if a group action is n-transitive for any n greater than one, then the action is primitive.*)\nLemma ntransitive_primitive m :\n 1 < m -> [transitive^m G, on S | to] -> [primitive G, on S | to].\n\nEnd NTransitveProp.\n\nSection NTransitveProp1.\n\nVariables (gT : finGroupType) (sT : finType).\nVariables (to : {action gT &-> sT}) (G : {group gT}) (S : {set sT}).\n\n(*This theorem states that if a group acts (m plus 1)-transitively on a set, where m is a positive number, then the stabilizer of any element in the set acts m-transitively on the remaining elements of the set.*)\nTheorem stab_ntransitive m x :\n 0 < m -> x \\in S -> [transitive^m.+1 G, on S | to] ->\n [transitive^m 'C_G[x | to], on S :\\ x | to].\n\n(*This theorem provides an introduction rule for n-transitivity of a stabilizer subgroup. It asserts that if a group acts (m plus 1)-transitively on a set, then for any two sequences of m distinct elements from the set excluding a given point, there exists an element in the stabilizer of that point that maps the first sequence to the second.*)\nTheorem stab_ntransitiveI m x :\n x \\in S -> [transitive G, on S | to] ->\n [transitive^m 'C_G[x | to], on S :\\ x | to] ->\n [transitive^m.+1 G, on S | to].", - "solvable.hall": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div choice.\nFrom mathcomp Require Import fintype finset prime fingroup morphism.\nFrom mathcomp Require Import automorphism quotient action gproduct gfunctor.\nFrom mathcomp Require Import commutator center pgroup finmodule nilpotent.\nFrom mathcomp Require Import sylow abelian maximal.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection Hall.\n\nImplicit Type gT : finGroupType.\n\n(*This theorem states that if a finite group has a normal Hall subgroup, which is a subgroup whose order is coprime to its index, then the group splits over that subgroup, meaning a complement to the subgroup exists.*)\nTheorem SchurZassenhaus_split gT (G H : {group gT}) :\n Hall G H -> H <| G -> [splits G, over H].\n\n(*This theorem states that if a solvable finite group is normalized by another group with a coprime order, then all subgroups of their product that have the same order as the second group are conjugate to the second group by an element from the first, solvable group.*)\nTheorem SchurZassenhaus_trans_sol gT (H K K1 : {group gT}) :\n solvable H -> K \\subset 'N(H) -> K1 \\subset H * K ->\n coprime #|H| #|K| -> #|K1| = #|K| ->\n exists2 x, x \\in H & K1 :=: K :^ x.\n\n(*This lemma asserts that if a solvable finite group `A` normalizes another finite group `G` with a coprime order, then any subgroup of their semidirect product having the same order as `A` is a conjugate of `A` by an element from `G`.*)\nLemma SchurZassenhaus_trans_actsol gT (G A B : {group gT}) :\n solvable A -> A \\subset 'N(G) -> B \\subset A <*> G ->\n coprime #|G| #|A| -> #|A| = #|B| ->\n exists2 x, x \\in G & B :=: A :^ x.\n\n(*This lemma states that for any solvable finite group and any set of prime numbers, there exists a Hall subgroup for that set of primes, and furthermore, every subgroup whose order is composed only of those primes is contained within some conjugate of that Hall subgroup.*)\nLemma Hall_exists_subJ pi gT (G : {group gT}) :\n solvable G -> exists2 H : {group gT}, pi.-Hall(G) H\n & forall K : {group gT}, K \\subset G -> pi.-group K ->\n exists2 x, x \\in G & K \\subset H :^ x.\n\nEnd Hall.\n\nSection HallCorollaries.\n\nVariable gT : finGroupType.\n\n(*This corollary states that for any given set of prime numbers, every solvable finite group possesses a Hall subgroup corresponding to that set of primes.*)\nCorollary Hall_exists pi (G : {group gT}) :\n solvable G -> exists H : {group gT}, pi.-Hall(G) H.\n\n(*This corollary states that in a solvable finite group, any two Hall subgroups corresponding to the same set of prime numbers are conjugate to each other within the parent group.*)\nCorollary Hall_trans pi (G H1 H2 : {group gT}) :\n solvable G -> pi.-Hall(G) H1 -> pi.-Hall(G) H2 ->\n exists2 x, x \\in G & H1 :=: H2 :^ x.\n\n(*This corollary asserts that in a solvable finite group, for any specified set of prime numbers, any subgroup whose order is a product of those primes is contained within some Hall subgroup corresponding to that same set of primes.*)\nCorollary Hall_superset pi (G K : {group gT}) :\n solvable G -> K \\subset G -> pi.-group K ->\n exists2 H : {group gT}, pi.-Hall(G) H & K \\subset H.\n\n(*This corollary states that in a solvable finite group, given a Hall subgroup for a certain set of primes, any other subgroup whose order is composed of those same primes is contained within a conjugate of that Hall subgroup.*)\nCorollary Hall_subJ pi (G H K : {group gT}) :\n solvable G -> pi.-Hall(G) H -> K \\subset G -> pi.-group K ->\n exists2 x, x \\in G & K \\subset H :^ x.\n\n(*This corollary states that in a solvable finite group, given a Hall subgroup for a certain set of primes, any other subgroup whose order is composed of those same primes can be conjugated by some element to become a subgroup of the given Hall subgroup.*)\nCorollary Hall_Jsub pi (G H K : {group gT}) :\n solvable G -> pi.-Hall(G) H -> K \\subset G -> pi.-group K ->\n exists2 x, x \\in G & K :^ x \\subset H.\n\n(*This lemma, a version of the Frattini argument, states that if a solvable normal subgroup of a finite group has a Hall subgroup for a given set of primes, then the entire group is equal to the product of that normal subgroup and the normalizer of its Hall subgroup.*)\nLemma Hall_Frattini_arg pi (G K H : {group gT}) :\n solvable K -> K <| G -> pi.-Hall(K) H -> K * 'N_G(H) = G.\n\nEnd HallCorollaries.\n\nSection InternalAction.\n\nVariables (pi : nat_pred) (gT : finGroupType).\nImplicit Types G H K A X : {group gT}.\n\n(*This lemma states that if a finite group `A` normalizes another finite group `G` and their orders are coprime, then the subgroup of `G` consisting of elements that normalize `A` is equal to the subgroup of `G` consisting of elements that centralize `A`.*)\nLemma coprime_norm_cent A G :\n A \\subset 'N(G) -> coprime #|G| #|A| -> 'N_G(A) = 'C_G(A).\n\n(*This proposition asserts that if a finite group `A` normalizes a solvable finite group `G` and their orders are coprime, then for any set of prime numbers, there exists a Hall subgroup of `G` which is also normalized by `A`.*)\nProposition coprime_Hall_exists A G :\n A \\subset 'N(G) -> coprime #|G| #|A| -> solvable G ->\n exists2 H : {group gT}, pi.-Hall(G) H & A \\subset 'N(H).\n\n(*This proposition states that for a solvable finite group `G` normalized by a group `A` of coprime order, any two Hall subgroups of `G` for a given set of primes that are both normalized by `A` are conjugate to each other by an element from the centralizer of `A` in `G`.*)\nProposition coprime_Hall_trans A G H1 H2 :\n A \\subset 'N(G) -> coprime #|G| #|A| -> solvable G ->\n pi.-Hall(G) H1 -> A \\subset 'N(H1) ->\n pi.-Hall(G) H2 -> A \\subset 'N(H2) ->\n exists2 x, x \\in 'C_G(A) & H1 :=: H2 :^ x.\n\n(*This lemma states that for two finite groups `A` and `G`, if an element commutes with every element of `A`, then the property that `A` normalizes the conjugate of `G` by that element is equivalent to the property that `A` normalizes `G`.*)\nLemma norm_conj_cent A G x : x \\in 'C(A) ->\n (A \\subset 'N(G :^ x)) = (A \\subset 'N(G)).\n\n(*This lemma provides conditions under which a centralizer in a group corresponds to a centralizer in a quotient of that group. It states that if group `A` normalizes subgroup `H` of group `G`, and certain solvability and coprime order conditions hold between `A` and the intersection of `H` with the commutator of `G` and `A`, then the centralizer of `A` in `G` modulo `H` is the same as the centralizer of the image of `A` in `G` modulo `H`.*)\nLemma strongest_coprime_quotient_cent A G H :\n let R := H :&: [~: G, A] in\n A \\subset 'N(H) -> R \\subset G -> coprime #|R| #|A| ->\n solvable R || solvable A ->\n 'C_G(A) / H = 'C_(G / H)(A / H).\n\n(*This lemma states that for three finite groups `A`, `G`, and `H`, if `A` normalizes both `G` and `H`, `H` is solvable, and the order of `H` is coprime to the order of `A`, then the centralizer of `A` in `G` modulo `H` is equal to the centralizer of the image of `A` in `G` modulo `H`.*)\nLemma coprime_norm_quotient_cent A G H :\n A \\subset 'N(G) -> A \\subset 'N(H) -> coprime #|H| #|A| -> solvable H ->\n 'C_G(A) / H = 'C_(G / H)(A / H).\n\n(*This lemma states that the centralizer of a group A in the product of groups H and G is equal to the product of the centralizer of A in H and the centralizer of A in G, provided several conditions are met. These conditions include A normalizing both G and H, G normalizing H, H being a solvable group, and the orders of H and A being coprime.*)\nLemma coprime_cent_mulG A G H :\n A \\subset 'N(G) -> A \\subset 'N(H) -> G \\subset 'N(H) ->\n coprime #|H| #|A| -> solvable H ->\n 'C_(H * G)(A) = 'C_H(A) * 'C_G(A).\n\n(*This lemma relates the centralizer in a quotient group to the quotient of a centralizer. It asserts that the quotient of the centralizer of a group G in a group K by a group H is equal to the centralizer of the quotient group G by H within the quotient group K by H. This holds if G normalizes both K and H, and the intersection of K and H is the trivial group.*)\nLemma quotient_TI_subcent K G H :\n G \\subset 'N(K) -> G \\subset 'N(H) -> K :&: H = 1 ->\n 'C_K(G) / H = 'C_(K / H)(G / H).\n\n(*This proposition states that under certain conditions, the quotient of the centralizer of a group A in a group G by a subgroup H is equal to the centralizer of A in the quotient group G by H under the induced action. The conditions are that H is a subgroup of G normalized by A, G is a solvable group, and the orders of G and A are coprime.*)\nProposition coprime_quotient_cent A G H :\n H \\subset G -> A \\subset 'N(H) -> coprime #|G| #|A| -> solvable G ->\n 'C_G(A) / H = 'C_(G / H)(A / H).\n\n(*This proposition asserts that the commutator subgroup of G and A is contained within the pi-core of G. This holds if A normalizes G, G is solvable, the orders of G and A are coprime, and a pi-complement Hall subgroup of G is contained within the centralizer of A in G.*)\nProposition coprime_comm_pcore A G K :\n A \\subset 'N(G) -> coprime #|G| #|A| -> solvable G ->\n pi^'.-Hall(G) K -> K \\subset 'C_G(A) ->\n [~: G, A] \\subset 'O_pi(G).\n\nEnd InternalAction.\n\n(*This proposition states that for a solvable group G acted upon by a group A with coprime order, any A-invariant pi-subgroup X of G is contained in some A-invariant pi-Hall subgroup of G.*)\nProposition coprime_Hall_subset pi (gT : finGroupType) (A G X : {group gT}) :\n A \\subset 'N(G) -> coprime #|G| #|A| -> solvable G ->\n X \\subset G -> pi.-group X -> A \\subset 'N(X) ->\n exists H : {group gT}, [/\\ pi.-Hall(G) H, A \\subset 'N(H) & X \\subset H].\n\nSection ExternalAction.\n\nVariables (pi : nat_pred) (aT gT : finGroupType).\nVariables (A : {group aT}) (G : {group gT}) (to : groupAction A G).\n\nSection FullExtension.\n\n(*A local notation for the canonical injection of the acting group A into the semidirect product group formed by the action of A on G.*)\nLocal Notation inA := (sdpair2 to).\n(*A local notation for the canonical injection of the group G into the semidirect product group formed by the action of group A on G.*)\nLocal Notation inG := (sdpair1 to).\n(*A local notation for the image of the acting group A under its canonical injection into the semidirect product group. This represents the subgroup isomorphic to A within the larger group.*)\nLocal Notation A' := (inA @* gval A).\n(*A local notation for the image of the group G under its canonical injection into the semidirect product group. This represents the subgroup isomorphic to G within the larger group.*)\nLocal Notation G' := (inG @* gval G).\n(*A definition establishing that the canonical map from the group G into the semidirect product is an injective group morphism.*)\nLet injG : 'injm inG := injm_sdpair1 _.\n(*A definition establishing that the canonical map from the acting group A into the semidirect product is an injective group morphism.*)\nLet injA : 'injm inA := injm_sdpair2 _.\n\nHypotheses (coGA : coprime #|G| #|A|) (solG : solvable G).\n\n(*This lemma states that the orders of the image subgroups corresponding to G and A within the semidirect product are coprime.*)\nLemma external_action_im_coprime : coprime #|G'| #|A'|.\n\n(*A definition aliasing the proof that the orders of the image subgroups G' and A' in the semidirect product are coprime.*)\nLet coGA' := external_action_im_coprime.\n\n(*A definition establishing that the image subgroup G' in the semidirect product is solvable, which follows from the solvability of the original group G.*)\nLet solG' : solvable G' := morphim_sol _ solG.\n\n(*A definition establishing that the image subgroup G' is a normal subgroup of the semidirect product formed by the images of A and G.*)\nLet nGA' := im_sdpair_norm to.\n\n(*This lemma states that for a solvable group G acted upon by a group A with coprime order, there exists a pi-Hall subgroup H of G that is invariant under the action of A.*)\nLemma ext_coprime_Hall_exists :\n exists2 H : {group gT}, pi.-Hall(G) H & [acts A, on H | to].\n\n(*This lemma states that under an action by a group A with coprime order on a solvable group G, any two A-invariant pi-Hall subgroups of G are conjugate by an element from the centralizer of A in G.*)\nLemma ext_coprime_Hall_trans (H1 H2 : {group gT}) :\n pi.-Hall(G) H1 -> [acts A, on H1 | to] ->\n pi.-Hall(G) H2 -> [acts A, on H2 | to] ->\n exists2 x, x \\in 'C_(G | to)(A) & H1 :=: H2 :^ x.\n\n(*This lemma states that if a subgroup H is invariant under the action of a group A, then any conjugate of H by an element from the centralizer of A in G is also A-invariant.*)\nLemma ext_norm_conj_cent (H : {group gT}) x :\n H \\subset G -> x \\in 'C_(G | to)(A) ->\n [acts A, on H :^ x | to] = [acts A, on H | to].\n\n(*This lemma states that given a solvable group G acted upon by a group A with coprime order, any A-invariant pi-subgroup X of G is contained within some A-invariant pi-Hall subgroup of G.*)\nLemma ext_coprime_Hall_subset (X : {group gT}) :\n X \\subset G -> pi.-group X -> [acts A, on X | to] ->\n exists H : {group gT},\n [/\\ pi.-Hall(G) H, [acts A, on H | to] & X \\subset H].\n\nEnd FullExtension.\n\n(*This lemma states that for a group G acted upon by a group A, the quotient of the centralizer of A in G by an A-invariant subgroup H is equal to the centralizer of A in the quotient group G divided by H. This holds if H is a solvable group and its order is coprime to the order of A.*)\nLemma ext_coprime_quotient_cent (H : {group gT}) :\n H \\subset G -> [acts A, on H | to] -> coprime #|H| #|A| -> solvable H ->\n 'C_(|to)(A) / H = 'C_(|to / H)(A).\n\nEnd ExternalAction.\n\nSection SylowSolvableAct.\n\nVariables (gT : finGroupType) (p : nat).\nImplicit Types A B G X : {group gT}.\n\n(*This lemma states that if a solvable group A normalizes a group G and their orders are coprime, then there exists a Sylow p-subgroup of G that is normalized by A.*)\nLemma sol_coprime_Sylow_exists A G :\n solvable A -> A \\subset 'N(G) -> coprime #|G| #|A| ->\n exists2 P : {group gT}, p.-Sylow(G) P & A \\subset 'N(P).\n\n(*This lemma states that if a solvable group A normalizes a group G with a coprime order, then any two A-invariant Sylow p-subgroups of G are conjugate by an element from the centralizer of A in G.*)\nLemma sol_coprime_Sylow_trans A G :\n solvable A -> A \\subset 'N(G) -> coprime #|G| #|A| ->\n [transitive 'C_G(A), on [set P in 'Syl_p(G) | A \\subset 'N(P)] | 'JG].\n\n(*This lemma asserts that if a solvable group A normalizes a group G with coprime order, then any A-invariant p-subgroup of G is contained within some A-invariant Sylow p-subgroup of G.*)\nLemma sol_coprime_Sylow_subset A G X :\n A \\subset 'N(G) -> coprime #|G| #|A| -> solvable A ->\n X \\subset G -> p.-group X -> A \\subset 'N(X) ->\n exists P : {group gT}, [/\\ p.-Sylow(G) P, A \\subset 'N(P) & X \\subset P].", - "solvable.nilpotent": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import fintype div bigop prime finset fingroup morphism.\nFrom mathcomp Require Import automorphism quotient commutator gproduct.\nFrom mathcomp Require Import perm gfunctor center gseries cyclic.\nFrom mathcomp Require finfun.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection SeriesDefs.\n\nVariables (n : nat) (gT : finGroupType) (A : {set gT}).\n\n(*This definition specifies the n-th term of the lower central series of a given group. It is computed by iteratively taking the commutator of the previous term with the original group, starting with the group itself as the first term. The index n is one-based.*)\nDefinition lower_central_at := iter n.-1 (fun B => [~: B, A]) A.\n\n(*This definition specifies the n-th term of the upper central series of a given group. It is computed by iteratively finding the preimage of the center of the quotient of the original group by the previous term in the series, starting with the trivial subgroup as the zeroth term.*)\nDefinition upper_central_at := iter n (fun B => coset B @*^-1 'Z(A / B)) 1.\n\nEnd SeriesDefs.\n\nArguments lower_central_at n%_N {gT} A%_g.\nArguments upper_central_at n%_N {gT} A%_g : simpl never.\n\n(*This notation represents the n-th term of the lower central series of a group.*)\nNotation \"''L_' n ( G )\" := (lower_central_at n G)\n (n at level 2, format \"''L_' n ( G )\") : group_scope.\n\n(*This notation represents the n-th term of the upper central series of a group.*)\nNotation \"''Z_' n ( G )\" := (upper_central_at n G)\n (n at level 2, format \"''Z_' n ( G )\") : group_scope.\n\nSection PropertiesDefs.\n\nVariables (gT : finGroupType) (A : {set gT}).\n\n(*This definition specifies the property of a group being nilpotent. A group is defined as nilpotent if its only subgroup that contains the commutator of itself with the whole group is the trivial subgroup.*)\nDefinition nilpotent :=\n [forall (G : {group gT} | G \\subset A :&: [~: G, A]), G :==: 1].\n\n(*This definition specifies the nilpotency class of a nilpotent group. It is defined as the smallest non-negative integer c such that the c+1-th term of the lower central series of the group is the trivial subgroup.*)\nDefinition nil_class := index 1 (mkseq (fun n => 'L_n.+1(A)) #|A|).\n\n(*This definition specifies the property of a group being solvable. A group is defined as solvable if its only perfect subgroup, that is, a subgroup equal to its own derived subgroup, is the trivial subgroup.*)\nDefinition solvable :=\n [forall (G : {group gT} | G \\subset A :&: [~: G, G]), G :==: 1].\n\nEnd PropertiesDefs.\n\nArguments nilpotent {gT} A%_g.\nArguments nil_class {gT} A%_g.\nArguments solvable {gT} A%_g.\n\nSection NilpotentProps.\n\nVariable gT: finGroupType.\nImplicit Types (A B : {set gT}) (G H : {group gT}).\n\n(*This lemma states that the trivial group is always nilpotent.*)\nLemma nilpotent1 : nilpotent [1 gT].\n\n(*This lemma states that any subgroup of a nilpotent group is also nilpotent.*)\nLemma nilpotentS A B : B \\subset A -> nilpotent A -> nilpotent B.\n\n(*This lemma states that for a nilpotent group, the commutator of a non-trivial subgroup with any subset contained in its normalizer is a proper subgroup of that subgroup.*)\nLemma nil_comm_properl G H A :\n nilpotent G -> H \\subset G -> H :!=: 1 -> A \\subset 'N_G(H) ->\n [~: H, A] \\proper H.\n\n(*This lemma states that for a nilpotent group, the commutator of any subset contained in the normalizer of a non-trivial subgroup with that subgroup is a proper subgroup of that subgroup.*)\nLemma nil_comm_properr G A H :\n nilpotent G -> H \\subset G -> H :!=: 1 -> A \\subset 'N_G(H) ->\n [~: A, H] \\proper H.\n\n(*This lemma states that a group is nilpotent if it possesses a central series that starts with the trivial subgroup and ends with the group itself.*)\nLemma centrals_nil (s : seq {group gT}) G :\n G.-central.-series 1%G s -> last 1%G s = G -> nilpotent G.\n\nEnd NilpotentProps.\n\nSection LowerCentral.\n\nVariable gT : finGroupType.\nImplicit Types (A B : {set gT}) (G H : {group gT}).\n\n(*This lemma states that the zeroth term of the lower central series of a group, according to the library's indexing, is the group itself.*)\nLemma lcn0 A : 'L_0(A) = A. \n(*This lemma states that the first term of the lower central series of a group is the group itself.*)\nLemma lcn1 A : 'L_1(A) = A. \n(*This lemma gives the recursive definition of the lower central series, stating that the term at index n+2 is the commutator subgroup of the term at index n+1 with the original group.*)\nLemma lcnSn n A : 'L_n.+2(A) = [~: 'L_n.+1(A), A]. \n(*This lemma states that the commutator of the n-th term of the lower central series with the group itself is a subgroup of the n+1-th term of the lower central series.*)\nLemma lcnSnS n G : [~: 'L_n(G), G] \\subset 'L_n.+1(G).\n\n(*This lemma provides an equivalent definition for the n+1-th term of the lower central series of a group, expressing it as the n-th iteration of taking the commutator with the group, starting from the group itself.*)\nLemma lcnE n A : 'L_n.+1(A) = iter n (fun B => [~: B, A]) A.\n\n(*This lemma states that the second term of the lower central series of a group is equal to its derived subgroup.*)\nLemma lcn2 A : 'L_2(A) = A^`(1). \n\n(*This lemma formally states that every term of the lower central series of a group is itself a group.*)\nLemma lcn_group_set n G : group_set 'L_n(G).\n\nCanonical lower_central_at_group n G := Group (lcn_group_set n G).\n\n(*This lemma states that every term of the lower central series of a group is a characteristic subgroup of that group.*)\nLemma lcn_char n G : 'L_n(G) \\char G.\n\n(*This lemma states that every term of the lower central series of a group is a normal subgroup of that group.*)\nLemma lcn_normal n G : 'L_n(G) <| G.\n\n(*This lemma states that every term of the lower central series of a group is a subgroup of that group.*)\nLemma lcn_sub n G : 'L_n(G) \\subset G.\n\n(*This lemma states that a group is a subgroup of the normalizer of any term of its lower central series, which is equivalent to saying that each term of the lower central series is a normal subgroup.*)\nLemma lcn_norm n G : G \\subset 'N('L_n(G)).\n\n(*This lemma states that each term of the lower central series of a group is a subgroup of the preceding term, forming a descending chain of subgroups.*)\nLemma lcn_subS n G : 'L_n.+1(G) \\subset 'L_n(G).\n\n(*This lemma states that each term of the lower central series of a group is a normal subgroup of the preceding term.*)\nLemma lcn_normalS n G : 'L_n.+1(G) <| 'L_n(G).\n\n(*This lemma states that the quotient of a term in the lower central series by the subsequent term is a subgroup of the center of the quotient of the original group by that subsequent term.*)\nLemma lcn_central n G : 'L_n(G) / 'L_n.+1(G) \\subset 'Z(G / 'L_n.+1(G)).\n\n(*This lemma states that for any two indices m and n where n is less than or equal to m, the m-th term of a group's lower central series is a subgroup of the n-th term.*)\nLemma lcn_sub_leq m n G : n <= m -> 'L_m(G) \\subset 'L_n(G).\n\n(*This lemma states that for any natural number n, if a group A is a subgroup of a group B, then the n-th term of the lower central series of A is a subgroup of the n-th term of the lower central series of B.*)\nLemma lcnS n A B : A \\subset B -> 'L_n(A) \\subset 'L_n(B).\n\n(*This lemma states that for a group that is the central product of two subgroups, the n-th term of its lower central series is equal to the central product of the n-th terms of the lower central series of those two subgroups.*)\nLemma lcn_cprod n A B G : A \\* B = G -> 'L_n(A) \\* 'L_n(B) = 'L_n(G).\n\n(*This lemma states that for a group that is the direct product of two subgroups, the n-th term of its lower central series is equal to the direct product of the n-th terms of the lower central series of those two subgroups.*)\nLemma lcn_dprod n A B G : A \\x B = G -> 'L_n(A) \\x 'L_n(B) = 'L_n(G).\n\n(*This lemma states that if a group is the central product of two subgroups, then its nth derived subgroup is the central product of the nth derived subgroups of those two subgroups.*)\nLemma der_cprod n A B G : A \\* B = G -> A^`(n) \\* B^`(n) = G^`(n).\n\n(*This lemma states that if a group is the direct product of two subgroups, then its nth derived subgroup is the direct product of the nth derived subgroups of those two subgroups.*)\nLemma der_dprod n A B G : A \\x B = G -> A^`(n) \\x B^`(n) = G^`(n).\n\n(*This lemma states that if a group is the iterated central product of a family of subgroups over a given range, then the nth term of its lower central series is the iterated central product of the nth terms of the lower central series of those subgroups.*)\nLemma lcn_bigcprod n I r P (F : I -> {set gT}) G :\n \\big[cprod/1]_(i <- r | P i) F i = G ->\n \\big[cprod/1]_(i <- r | P i) 'L_n(F i) = 'L_n(G).\n\n(*This lemma states that if a group is the iterated direct product of a family of subgroups over a given range, then the nth term of its lower central series is the iterated direct product of the nth terms of the lower central series of those subgroups.*)\nLemma lcn_bigdprod n I r P (F : I -> {set gT}) G :\n \\big[dprod/1]_(i <- r | P i) F i = G ->\n \\big[dprod/1]_(i <- r | P i) 'L_n(F i) = 'L_n(G).\n\n(*This lemma states that if a group is the iterated central product of a family of subgroups over a given range, then its nth derived subgroup is the iterated central product of the nth derived subgroups of those subgroups.*)\nLemma der_bigcprod n I r P (F : I -> {set gT}) G :\n \\big[cprod/1]_(i <- r | P i) F i = G ->\n \\big[cprod/1]_(i <- r | P i) (F i)^`(n) = G^`(n).\n\n(*This lemma states that if a group is the iterated direct product of a family of subgroups over a given range, then its nth derived subgroup is the iterated direct product of the nth derived subgroups of those subgroups.*)\nLemma der_bigdprod n I r P (F : I -> {set gT}) G :\n \\big[dprod/1]_(i <- r | P i) F i = G ->\n \\big[dprod/1]_(i <- r | P i) (F i)^`(n) = G^`(n).\n\n(*This lemma states that a finite group is nilpotent if and only if its nilpotency class is strictly less than the order of the group.*)\nLemma nilpotent_class G : nilpotent G = (nil_class G < #|G|).\n\n(*This lemma states that for a nilpotent group, its nilpotency class is less than or equal to a given natural number if and only if the next term in its lower central series is the trivial group.*)\nLemma lcn_nil_classP n G :\n nilpotent G -> reflect ('L_n.+1(G) = 1) (nil_class G <= n).\n\n(*This lemma states that a group is nilpotent if and only if there exists a natural number such that a term in its lower central series is the trivial group.*)\nLemma lcnP G : reflect (exists n, 'L_n.+1(G) = 1) (nilpotent G).\n\n(*This lemma states that if a group is abelian, then it is also nilpotent.*)\nLemma abelian_nil G : abelian G -> nilpotent G.\n\n(*This lemma states that the nilpotency class of a group is zero if and only if the group is the trivial group.*)\nLemma nil_class0 G : (nil_class G == 0) = (G :==: 1).\n\n(*This lemma states that a group has a nilpotency class less than or equal to one if and only if the group is abelian.*)\nLemma nil_class1 G : (nil_class G <= 1) = abelian G.\n\n(*This lemma states that if a group is the central product of two subgroups, then it is nilpotent if and only if both subgroups are nilpotent.*)\nLemma cprod_nil A B G : A \\* B = G -> nilpotent G = nilpotent A && nilpotent B.\n\n(*This lemma states that if a subgroup is contained in the center of a group, then the product of the group and the subgroup is nilpotent if and only if both the group and the subgroup are nilpotent.*)\nLemma mulg_nil G H :\n H \\subset 'C(G) -> nilpotent (G * H) = nilpotent G && nilpotent H.\n\n(*This lemma states that if a group is the direct product of two subgroups, then it is nilpotent if and only if both subgroups are nilpotent.*)\nLemma dprod_nil A B G : A \\x B = G -> nilpotent G = nilpotent A && nilpotent B.\n\n(*This lemma states that if a group is the iterated direct product of a family of subgroups and each of these subgroups is nilpotent, then the group is also nilpotent.*)\nLemma bigdprod_nil I r (P : pred I) (A_ : I -> {set gT}) G :\n \\big[dprod/1]_(i <- r | P i) A_ i = G\n -> (forall i, P i -> nilpotent (A_ i)) -> nilpotent G.\n\nEnd LowerCentral.\n\n(*This notation represents the nth term of the lower central series of a given group.*)\nNotation \"''L_' n ( G )\" := (lower_central_at_group n G) : Group_scope.\n\n(*This lemma states that for any natural number, the operation that maps a group to the nth term of its lower central series is a continuous group functor.*)\nLemma lcn_cont n : GFunctor.continuous (@lower_central_at n).\n\nCanonical lcn_igFun n := [igFun by lcn_sub^~ n & lcn_cont n].\nCanonical lcn_gFun n := [gFun by lcn_cont n].\nCanonical lcn_mgFun n := [mgFun by fun _ G H => @lcnS _ n G H].\n\nSection UpperCentralFunctor.\n\nVariable n : nat.\nImplicit Type gT : finGroupType.\n\n(*This lemma states that for any natural number, the operation that maps a group to the nth term of its upper central series corresponds to a pre-morphism map in the group functor framework.*)\nLemma ucn_pmap : exists hZ : GFunctor.pmap, @upper_central_at n = hZ.\n\n(*This lemma states that for any natural number, the nth term of the upper central series of a group is itself a group.*)\nLemma ucn_group_set gT (G : {group gT}) : group_set 'Z_n(G).\n\nCanonical upper_central_at_group gT G := Group (@ucn_group_set gT G).\n\n(*This lemma states that for any natural number, the nth term of the upper central series of a group is a subgroup of that group.*)\nLemma ucn_sub gT (G : {group gT}) : 'Z_n(G) \\subset G.\n\n(*This lemma states that for any natural number, the operation that maps a group to the nth term of its upper central series is a p-continuous group functor.*)\nLemma morphim_ucn : GFunctor.pcontinuous (@upper_central_at n).\n\nCanonical ucn_igFun := [igFun by ucn_sub & morphim_ucn].\nCanonical ucn_gFun := [gFun by morphim_ucn].\nCanonical ucn_pgFun := [pgFun by morphim_ucn].\n\nVariable (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that for any natural number, the nth term of the upper central series of a group is a characteristic subgroup of that group.*)\nLemma ucn_char : 'Z_n(G) \\char G. \n(*This lemma states that a group is a subgroup of the normalizer of the nth term of its upper central series, which implies that the nth term is a normal subgroup.*)\nLemma ucn_norm : G \\subset 'N('Z_n(G)). \n(*This lemma states that for any natural number, the nth term of the upper central series of a group is a normal subgroup of that group.*)\nLemma ucn_normal : 'Z_n(G) <| G. \n\nEnd UpperCentralFunctor.\n\n(*This notation represents the nth term of the upper central series of a given group.*)\nNotation \"''Z_' n ( G )\" := (upper_central_at_group n G) : Group_scope.\n\nSection UpperCentral.\n\nVariable gT : finGroupType.\nImplicit Types (A B : {set gT}) (G H : {group gT}).\n\n(*This lemma states that the zeroth term of the upper central series of a group is the trivial group.*)\nLemma ucn0 A : 'Z_0(A) = 1.\n\n(*This lemma provides the recursive definition of the upper central series, stating that the successor term is the pullback of the center of the quotient group formed by the group and the current term of the series.*)\nLemma ucnSn n A : 'Z_n.+1(A) = coset 'Z_n(A) @*^-1 'Z(A / 'Z_n(A)).\n\n(*This lemma provides an iterative definition of the upper central series, stating that the nth term is obtained by iterating a function n times, starting from the trivial group, where the function computes the pullback of the center of a quotient group.*)\nLemma ucnE n A : 'Z_n(A) = iter n (fun B => coset B @*^-1 'Z(A / B)) 1.\n\n(*This lemma states that each term of the upper central series of a group is a subgroup of the next term in the series, forming an ascending chain of subgroups.*)\nLemma ucn_subS n G : 'Z_n(G) \\subset 'Z_n.+1(G).\n\n(*This lemma states that for any two natural numbers where the second is greater than or equal to the first, the term of the upper central series of a group corresponding to the first number is a subset of the term corresponding to the second number.*)\nLemma ucn_sub_geq m n G : n >= m -> 'Z_m(G) \\subset 'Z_n(G).\n\n(*This lemma states that for any natural number, the quotient of the next term in the upper central series of a group by the current term is equal to the center of the quotient of the group by that same current term of the upper central series.*)\nLemma ucn_central n G : 'Z_n.+1(G) / 'Z_n(G) = 'Z(G / 'Z_n(G)).\n\n(*This lemma states that for any natural number, a term in the upper central series of a group is a normal subgroup of the subsequent term in the series.*)\nLemma ucn_normalS n G : 'Z_n(G) <| 'Z_n.+1(G).\n\n(*This lemma states that for any natural number, the commutator of the next term in the upper central series of a group with the group itself is a subset of the current term in the upper central series.*)\nLemma ucn_comm n G : [~: 'Z_n.+1(G), G] \\subset 'Z_n(G).\n\n(*This lemma states that the first term in the upper central series of a group is equal to the center of that group.*)\nLemma ucn1 G : 'Z_1(G) = 'Z(G).\n\n(*This lemma provides a recursive characterization of the upper central series, stating that the next term in the series is the set of all elements in the group whose commutator with the entire group is a subset of the current term in the series.*)\nLemma ucnSnR n G : 'Z_n.+1(G) = [set x in G | [~: [set x], G] \\subset 'Z_n(G)].\n\n(*This lemma states that if a group is a central product of two subgroups, then for any natural number, the term of its upper central series corresponding to that number is the central product of the corresponding terms of the upper central series of the two subgroups.*)\nLemma ucn_cprod n A B G : A \\* B = G -> 'Z_n(A) \\* 'Z_n(B) = 'Z_n(G).\n\n(*This lemma states that if a group is a direct product of two subgroups, then for any natural number, the term of its upper central series corresponding to that number is the direct product of the corresponding terms of the upper central series of the two subgroups.*)\nLemma ucn_dprod n A B G : A \\x B = G -> 'Z_n(A) \\x 'Z_n(B) = 'Z_n(G).\n\n(*This lemma states that if a group is a central product of a family of subgroups, then for any natural number, the term of its upper central series corresponding to that number is the central product of the corresponding terms of the upper central series of the subgroups in the family.*)\nLemma ucn_bigcprod n I r P (F : I -> {set gT}) G :\n \\big[cprod/1]_(i <- r | P i) F i = G ->\n \\big[cprod/1]_(i <- r | P i) 'Z_n(F i) = 'Z_n(G).\n\n(*This lemma states that if a group is a direct product of a family of subgroups, then for any natural number, the term of its upper central series corresponding to that number is the direct product of the corresponding terms of the upper central series of the subgroups in the family.*)\nLemma ucn_bigdprod n I r P (F : I -> {set gT}) G :\n \\big[dprod/1]_(i <- r | P i) F i = G ->\n \\big[dprod/1]_(i <- r | P i) 'Z_n(F i) = 'Z_n(G).\n\n(*This lemma states that for any natural number, the property that the next term in the lower central series of a group is the trivial subgroup is equivalent to the property that the current term of the upper central series is the entire group.*)\nLemma ucn_lcnP n G : ('L_n.+1(G) == 1) = ('Z_n(G) == G).\n\n(*This lemma provides a characterization of a nilpotent group, stating that a group is nilpotent if and only if there exists a natural number for which the corresponding term of the upper central series is equal to the entire group.*)\nLemma ucnP G : reflect (exists n, 'Z_n(G) = G) (nilpotent G).\n\n(*This lemma states that for a nilpotent group and a natural number, the condition that the term of the upper central series corresponding to that number is equal to the entire group is equivalent to the nilpotency class of the group being less than or equal to that number.*)\nLemma ucn_nil_classP n G :\n nilpotent G -> reflect ('Z_n(G) = G) (nil_class G <= n).\n\n(*This lemma states that for any natural number, applying the operation that computes the term of the upper central series twice to a group results in the same subgroup as applying it once.*)\nLemma ucn_id n G : 'Z_n('Z_n(G)) = 'Z_n(G).\n\n(*This lemma states that for any natural number, the corresponding term in the upper central series of a group is itself a nilpotent group.*)\nLemma ucn_nilpotent n G : nilpotent 'Z_n(G).\n\n(*This lemma states that for any natural number, the nilpotency class of the corresponding term in the upper central series of a group is less than or equal to that number.*)\nLemma nil_class_ucn n G : nil_class 'Z_n(G) <= n.\n\nEnd UpperCentral.\n\nSection MorphNil.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\nImplicit Type G : {group aT}.\n\n(*This lemma states that a group morphism preserves the lower central series; the image of a term in the lower central series of a subgroup under the morphism is equal to the corresponding term in the lower central series of the image of that subgroup.*)\nLemma morphim_lcn n G : G \\subset D -> f @* 'L_n(G) = 'L_n(f @* G).\n\n(*This lemma states that an injective group morphism preserves the upper central series; the image of a term in the upper central series of a subgroup under the morphism is equal to the corresponding term in the upper central series of the image of that subgroup.*)\nLemma injm_ucn n G : 'injm f -> G \\subset D -> f @* 'Z_n(G) = 'Z_n(f @* G).\n\n(*This lemma states that the homomorphic image of a nilpotent group is also a nilpotent group.*)\nLemma morphim_nil G : nilpotent G -> nilpotent (f @* G).\n\n(*This lemma states that for an injective group morphism, a subgroup is nilpotent if and only if its image under the morphism is nilpotent.*)\nLemma injm_nil G : 'injm f -> G \\subset D -> nilpotent (f @* G) = nilpotent G.\n\n(*This lemma states that for a nilpotent group, the nilpotency class of its image under a group morphism is less than or equal to the nilpotency class of the original group.*)\nLemma nil_class_morphim G : nilpotent G -> nil_class (f @* G) <= nil_class G.\n\n(*This lemma states that for an injective group morphism and a subgroup in its domain, the nilpotency class of the image of the subgroup is equal to the nilpotency class of the subgroup itself.*)\nLemma nil_class_injm G :\n 'injm f -> G \\subset D -> nil_class (f @* G) = nil_class G.\n\nEnd MorphNil.\n\nSection QuotientNil.\n\nVariables gT : finGroupType.\nImplicit Types (rT : finGroupType) (G H : {group gT}).\n\n(*This lemma states that for two natural numbers, the quotient of the upper central series term at their sum by the term at the second number is equal to the upper central series term at the first number of the quotient group formed by dividing the original group by its upper central series term at the second number.*)\nLemma quotient_ucn_add m n G : 'Z_(m + n)(G) / 'Z_n(G) = 'Z_m(G / 'Z_n(G)).\n\n(*This lemma states that nilpotency is an isomorphism invariant; if two groups are isomorphic, then one group is nilpotent if and only if the other group is also nilpotent.*)\nLemma isog_nil rT G (L : {group rT}) : G \\isog L -> nilpotent G = nilpotent L.\n\n(*This lemma states that the nilpotency class is an isomorphism invariant; if two groups are isomorphic, then their nilpotency classes are equal.*)\nLemma isog_nil_class rT G (L : {group rT}) :\n G \\isog L -> nil_class G = nil_class L.\n\n(*This lemma states that if a group is nilpotent, then any of its quotient groups is also nilpotent.*)\nLemma quotient_nil G H : nilpotent G -> nilpotent (G / H).\n\n(*This lemma states that a group is nilpotent if and only if the quotient of the group by its center is also nilpotent.*)\nLemma quotient_center_nil G : nilpotent (G / 'Z(G)) = nilpotent G.\n\n(*This lemma states that for a nilpotent group, the nilpotency class of the quotient of the group by its center is equal to the nilpotency class of the original group decremented by one.*)\nLemma nil_class_quotient_center G :\n nilpotent (G) -> nil_class (G / 'Z(G)) = (nil_class G).-1.\n\n(*This lemma states that if a subgroup of a nilpotent group is equal to its own normalizer, then that subgroup must be equal to the entire group.*)\nLemma nilpotent_sub_norm G H :\n nilpotent G -> H \\subset G -> 'N_G(H) \\subset H -> G :=: H.\n\n(*This lemma states that any proper subgroup of a nilpotent group is also a proper subgroup of its normalizer within that group.*)\nLemma nilpotent_proper_norm G H :\n nilpotent G -> H \\proper G -> H \\proper 'N_G(H).\n\n(*This lemma states that for a nilpotent finite group, any of its subgroups is a subnormal subgroup.*)\nLemma nilpotent_subnormal G H : nilpotent G -> H \\subset G -> H <|<| G.\n\n(*This lemma states that if a normal subgroup of a nilpotent finite group has a trivial intersection with the center of the group, then that normal subgroup must be the trivial group.*)\nLemma TI_center_nil G H : nilpotent G -> H <| G -> H :&: 'Z(G) = 1 -> H :=: 1.\n\n(*This lemma states that for any non-trivial normal subgroup of a nilpotent finite group, its intersection with the center of the group is also non-trivial.*)\nLemma meet_center_nil G H :\n nilpotent G -> H <| G -> H :!=: 1 -> H :&: 'Z(G) != 1.\n\n(*This lemma states that for a nilpotent finite group, its center is the trivial group if and only if the group itself is the trivial group.*)\nLemma center_nil_eq1 G : nilpotent G -> ('Z(G) == 1) = (G :==: 1).\n\n(*This lemma states that if a nilpotent finite group has a cyclic abelianization, meaning its quotient by the commutator subgroup is cyclic, then the group itself must be cyclic.*)\nLemma cyclic_nilpotent_quo_der1_cyclic G :\n nilpotent G -> cyclic (G / G^`(1)) -> cyclic G.\n\nEnd QuotientNil.\n\nSection Solvable.\n\nVariable gT : finGroupType.\nImplicit Types G H : {group gT}.\n\n(*This lemma states that any nilpotent finite group is also solvable.*)\nLemma nilpotent_sol G : nilpotent G -> solvable G.\n\n(*This lemma states that any abelian finite group is solvable.*)\nLemma abelian_sol G : abelian G -> solvable G.\n\n(*This lemma states that the trivial group is solvable.*)\nLemma solvable1 : solvable [1 gT]. \n\n(*This lemma states that any subgroup of a solvable finite group is also solvable.*)\nLemma solvableS G H : H \\subset G -> solvable G -> solvable H.\n\n(*This lemma states that for any non-trivial subgroup of a solvable finite group, its derived subgroup is a proper subgroup of it.*)\nLemma sol_der1_proper G H :\n solvable G -> H \\subset G -> H :!=: 1 -> H^`(1) \\proper H.\n\n(*This lemma states that a finite group is solvable if and only if its derived series, which is a sequence of subgroups obtained by repeatedly taking the commutator subgroup, eventually reaches the trivial group.*)\nLemma derivedP G : reflect (exists n, G^`(n) = 1) (solvable G).\n\nEnd Solvable.\n\nSection MorphSol.\n\nVariables (gT rT : finGroupType) (D : {group gT}) (f : {morphism D >-> rT}).\nVariable G : {group gT}.\n\n(*This lemma states that the image of a solvable finite group under a group homomorphism is also a solvable group.*)\nLemma morphim_sol : solvable G -> solvable (f @* G).\n\n(*This lemma states that for an injective group homomorphism, the image of a subgroup is solvable if and only if the original subgroup is solvable.*)\nLemma injm_sol : 'injm f -> G \\subset D -> solvable (f @* G) = solvable G.\n\nEnd MorphSol.\n\nSection QuotientSol.\n\nVariables gT rT : finGroupType.\nImplicit Types G H K : {group gT}.\n\n(*This lemma states that if two finite groups are isomorphic, then one is solvable if and only if the other is also solvable.*)\nLemma isog_sol G (L : {group rT}) : G \\isog L -> solvable G = solvable L.\n\n(*This lemma states that any quotient group of a solvable finite group is also solvable.*)\nLemma quotient_sol G H : solvable G -> solvable (G / H).\n\n(*This lemma states that for a normal subgroup of a finite group, the group is solvable if and only if both the subgroup and the corresponding quotient group are solvable.*)\nLemma series_sol G H : H <| G -> solvable G = solvable H && solvable (G / H).\n\n(*This lemma states that any metacyclic finite group is solvable.*)\nLemma metacyclic_sol G : metacyclic G -> solvable G.\n\nEnd QuotientSol.\n\nSection setXn.\nImport finfun.\n\n(*This lemma states that for any finite group and any natural number, the corresponding term in the upper central series of that group is a solvable group.*)\nLemma setXn_sol n (gT : 'I_n -> finGroupType) (G : forall i, {group gT i}) :\n (forall i, solvable (G i)) -> solvable (setXn G).", - "solvable.finmodule": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype bigop ssralg finset fingroup.\nFrom mathcomp Require Import morphism perm finalg action gproduct commutator .\nFrom mathcomp Require Import cyclic.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope GRing.Theory FinRing.Theory.\nLocal Open Scope ring_scope.\n\nModule FiniteModule.\n\nReserved Notation \"u ^@ x\" (at level 31, left associativity).\n\n(*An inductive type that encapsulates an element of an abelian subgroup, forming the basis for a finite Z-module structure.*)\nInductive fmod_of (gT : finGroupType) (A : {group gT}) (abelA : abelian A) :=\n Fmod x & x \\in A.\n\nBind Scope ring_scope with fmod_of.\n\nSection OneFinMod.\n\n(*A coercion that converts an element of a finite module type into its corresponding subgroup element representation.*)\nLet f2sub (gT : finGroupType) (A : {group gT}) (abA : abelian A) :=\n fun u : fmod_of abA => let : Fmod x Ax := u in Subg Ax : BaseFinGroup.arg_sort _.\nLocal Coercion f2sub : fmod_of >-> BaseFinGroup.arg_sort.\n\nVariables (gT : finGroupType) (A : {group gT}) (abelA : abelian A).\n(*A local notation for the finite module type constructed from a specific abelian subgroup.*)\nLocal Notation fmodA := (fmod_of abelA).\nImplicit Types (x y z : gT) (u v w : fmodA).\n\n(*A function that converts a subgroup element into its corresponding finite module type representation.*)\nLet sub2f (s : [subg A]) := Fmod abelA (valP s).\n\n(*This definition provides a function to extract the underlying group element from an element of the finite module type.*)\nDefinition fmval u := val (f2sub u).\n#[export]\nHB.instance Definition _ := [isSub for fmval].\n(*A local notation for the function that unwraps a finite module element to retrieve its underlying group element.*)\nLocal Notation valA := (val: fmodA -> gT) (only parsing).\n#[export]\nHB.instance Definition _ := [Finite of fmodA by <:].\n\n(*This definition provides a function that maps an element from the ambient group to its corresponding element in the finite module. If the element is not in the underlying abelian subgroup, it is mapped to the module's zero element.*)\nDefinition fmod x := sub2f (subg A x).\n\n(*This definition specifies a right action on a finite module element by an element from the ambient group. The action is conjugation if the group element belongs to the normalizer of the underlying abelian subgroup; otherwise, it is the identity action.*)\nDefinition actr u x := if x \\in 'N(A) then fmod (fmval u ^ x) else u.\n\n(*This definition specifies the additive inverse of a finite module element, which corresponds to the multiplicative inverse of the underlying subgroup element.*)\nDefinition fmod_opp u := sub2f u^-1.\n(*This definition specifies the addition operation for two finite module elements, which corresponds to the multiplicative product of the underlying subgroup elements.*)\nDefinition fmod_add u v := sub2f (u * v).\n\n(*This fact establishes that the zero element of the finite module, corresponding to the group identity, acts as a left identity for the module's addition operation.*)\nFact fmod_add0r : left_id (sub2f 1) fmod_add.\n\n(*This fact establishes that the addition operation defined on the finite module is associative.*)\nFact fmod_addrA : associative fmod_add.\n\n(*This fact establishes that for any element in the finite module, its additive inverse is a left inverse with respect to the module's addition, yielding the zero element.*)\nFact fmod_addNr : left_inverse (sub2f 1) fmod_opp fmod_add.\n\n(*This fact establishes that the addition operation defined on the finite module is commutative, which follows from the commutativity of the underlying abelian subgroup.*)\nFact fmod_addrC : commutative fmod_add.\n\n#[export]\nHB.instance Definition _ :=\n GRing.isZmodule.Build fmodA fmod_addrA fmod_addrC fmod_add0r fmod_addNr.\n\n#[export]\n(*This lemma states that the underlying group element corresponding to any element of the finite module is guaranteed to be a member of the abelian subgroup from which the module is constructed.*)\nLemma fmodP u : val u \\in A. \n(*This lemma states that the function mapping a finite module element to its underlying group element is injective.*)\nLemma fmod_inj : injective fmval. \n(*This lemma states that if two finite module elements are equal, then their corresponding underlying group elements are also equal.*)\nLemma congr_fmod u v : u = v -> fmval u = fmval v.\n\n(*This lemma states that the function unwrapping a finite module element to its group representation is a morphism, mapping module addition to group multiplication.*)\nLemma fmvalA : {morph valA : x y / x + y >-> (x * y)%g}. \n(*This lemma states that the function unwrapping a finite module element to its group representation is a morphism, mapping the additive inverse in the module to the multiplicative inverse in the group.*)\nLemma fmvalN : {morph valA : x / - x >-> x^-1%g}. \n(*This lemma states that the function unwrapping a finite module element maps the zero element of the module to the identity element of the group.*)\nLemma fmval0 : valA 0 = 1%g. \nCanonical fmval_morphism := @Morphism _ _ setT fmval (in2W fmvalA).\n\n(*This definition provides a proof that the unwrapping function from the finite module to the group preserves indexed sums, mapping them to indexed products.*)\nDefinition fmval_sum := big_morph fmval fmvalA fmval0.\n\n(*This lemma states that the function unwrapping a finite module element is a morphism with respect to scalar multiplication, mapping multiplication by an integer in the module to exponentiation by that integer in the group.*)\nLemma fmvalZ n : {morph valA : x / x *+ n >-> (x ^+ n)%g}.\n\n(*This lemma states that applying the lifting function from the group to the module, followed by the unwrapping function back to the group, yields the original element if it was in the underlying subgroup, and the group identity element otherwise.*)\nLemma fmodKcond x : val (fmod x) = if x \\in A then x else 1%g.\n\n(*This lemma states that for any element belonging to the defining abelian subgroup, lifting it to the finite module and then unwrapping it back to a group element results in the original group element.*)\nLemma fmodK : {in A, cancel fmod val}. \n(*This lemma states that for any element of the finite module, extracting its underlying group element and then lifting it back to the finite module yields the original module element.*)\nLemma fmvalK : cancel val fmod.\n\n(*This lemma states that lifting the group's identity element to the finite module results in the module's zero element.*)\nLemma fmod1 : fmod 1 = 0. \n(*This lemma states that the function lifting a group element to the module, when restricted to the underlying abelian subgroup, is a group morphism that maps group multiplication to module addition.*)\nLemma fmodM : {in A &, {morph fmod : x y / (x * y)%g >-> x + y}}.\n\nCanonical fmod_morphism := Morphism fmodM.\n(*This lemma states that the function lifting a group element to the module, when restricted to the underlying abelian subgroup, is a morphism that maps integer exponentiation in the group to scalar multiplication by that integer in the module.*)\nLemma fmodX n : {in A, {morph fmod : x / (x ^+ n)%g >-> x *+ n}}.\n\n(*This lemma states a property of the `fmod` function, asserting that applying `fmod` to the square of a group element yields the additive inverse of the result of applying `fmod` to that same element.*)\nLemma fmodV : {morph fmod : x / x^-1%g >-> - x}.\n\n(*This lemma states that `fmod` is an injective morphism, a type of function that both preserves algebraic structure and maps distinct inputs to distinct outputs.*)\nLemma injm_fmod : 'injm fmod.\n\n(**)\nNotation \"u ^@ x\" := (actr u x) : ring_scope.\n\n(*This lemma provides a conditional rule for computing the value of an element after being acted upon by another element. The resulting value is the original value raised to the power of the acting element if that element belongs to the normalizer of a given set, and it is the original value otherwise.*)\nLemma fmvalJcond u x :\n val (u ^@ x) = if x \\in 'N(A) then val u ^ x else val u.\n\n(*This lemma states that if an element belongs to the normalizer of a given set, then the value of another element acted upon by the first is equal to the original value raised to the power of the acting element.*)\nLemma fmvalJ u x : x \\in 'N(A) -> val (u ^@ x) = val u ^ x.\n\n(*This lemma connects the `fmod` function with an exponentiation-like action. It asserts that if an element belongs to the normalizer of a given set, applying `fmod` to another element raised to the power of the first is equivalent to applying the `fmod` function first and then applying the action on the result.*)\nLemma fmodJ x y : y \\in 'N(A) -> fmod (x ^ y) = fmod x ^@ y.\n\n(*This fact asserts that the binary operation `actr` satisfies the properties of a group action, specifically the action of the normalizer of a given set on another structure.*)\nFact actr_is_action : is_action 'N(A) actr.\n\nCanonical actr_action := Action actr_is_action.\n(**)\nNotation \"''M'\" := actr_action (at level 8) : action_scope.\n\n(*This lemma states that the action of any group element on the zero element of the target structure results in the zero element, meaning zero is a fixed point of the action.*)\nLemma act0r x : 0 ^@ x = 0.\n\n(*This lemma states that for any fixed group element, the action operation distributes over the addition of elements in the target structure, meaning the action on a sum is the sum of the actions.*)\nLemma actAr x : {morph actr^~ x : u v / u + v}.\n\n(*This definition establishes that the action operation commutes with finite sums by packaging the properties that the action distributes over addition and preserves the zero element.*)\nDefinition actr_sum x := big_morph _ (actAr x) (act0r x).\n\n(*This lemma states that for any fixed group element, the action operation commutes with taking the additive inverse in the target structure.*)\nLemma actNr x : {morph actr^~ x : u / - u}.\n\n(*This lemma states that for any fixed group element, the action operation commutes with scalar multiplication by an integer, meaning the action on a scaled element is the same as scaling the result of the action.*)\nLemma actZr x n : {morph actr^~ x : u / u *+ n}.\n\n(*This fact asserts that the `actr` operation defines a group action that is compatible with the additive group structure of the target set, satisfying the necessary linearity properties.*)\nFact actr_is_groupAction : is_groupAction setT 'M.\n\nCanonical actr_groupAction := GroupAction actr_is_groupAction.\n(*This notation provides a symbolic representation for the canonical action of a ring on a module.*)\nNotation \"''M'\" := actr_groupAction (at level 8) : groupAction_scope.\n\n(*This lemma states that the action of the multiplicative identity element of the ring on any module element results in that same module element.*)\nLemma actr1 u : u ^@ 1 = u.\n\n(*This lemma states that the action of a product of two ring elements on a module element is equivalent to first applying the action of the first element, and then applying the action of the second element to the result.*)\nLemma actrM : {in 'N(A) &, forall x y u, u ^@ (x * y) = u ^@ x ^@ y}.\n\n(*This lemma states that for any invertible ring element, applying the action of its group inverse and then the action of the element itself leaves any module element unchanged.*)\nLemma actrK x : cancel (actr^~ x) (actr^~ x^-1%g).\n\n(*This lemma states that for any invertible ring element, applying the action of the element itself and then the action of its group inverse leaves any module element unchanged.*)\nLemma actrKV x : cancel (actr^~ x^-1%g) (actr^~ x).\n\nEnd OneFinMod.\n\nBind Scope ring_scope with fmod_of.\nPrenex Implicits fmval fmod actr.\n(*A notation for the action of a ring element on a module element, producing a new module element.*)\nNotation \"u ^@ x\" := (actr u x) : ring_scope.\n(*This notation provides a shorthand to refer to the canonical action structure built from the `actr` operation, allowing for this specific action to be referenced concisely.*)\nNotation \"''M'\" := actr_action (at level 8) : action_scope.\n(*This is a notation for a module structure, often associated with an abelian group when it serves as the target of a group morphism like the transfer homomorphism.*)\nNotation \"''M'\" := actr_groupAction : groupAction_scope.\n\nModule Exports.\nHB.reexport FiniteModule.\nEnd Exports.\n\nEnd FiniteModule.\n\nHB.export FiniteModule.Exports.\n\nArguments FiniteModule.fmodK {gT A} abelA [x] Ax.\nArguments FiniteModule.fmvalK {gT A abelA} x.\nArguments FiniteModule.actrK {gT A abelA} x.\nArguments FiniteModule.actrKV {gT A abelA} x.\n\nImport FiniteModule GroupScope.\n\nSection Gaschutz.\n\nVariables (gT : finGroupType) (G H P : {group gT}).\nImplicit Types K L : {group gT}.\n\nHypotheses (nsHG : H <| G) (sHP : H \\subset P) (sPG : P \\subset G).\nHypotheses (abelH : abelian H) (coHiPG : coprime #|H| #|G : P|).\n\n(*This definition provides a proof that a group H is a subgroup of a group G, derived from the premise that H is a normal subgroup of G.*)\nLet sHG := normal_sub nsHG.\n(*This definition establishes a membership predicate for the group G, based on the fact that G is contained within the normalizer of its normal subgroup H.*)\nLet nHG := subsetP (normal_norm nsHG).\n\n(*This definition creates a group automorphism on an abelian group H, which maps each element to itself raised to the power of the modular inverse of the index of a subgroup P in a larger group G, modulo the order of H.*)\nLet m := (expg_invn H #|G : P|).\n\nImplicit Types a b : fmod_of abelH.\n(*This notation defines a canonical type for the finite module structure over the integers, derived from the abelian group H.*)\nLocal Notation fmod := (fmod abelH).\n\n(*This theorem states that, for a normal abelian subgroup H of a finite group G, and an intermediate subgroup P containing H, the group G splits over H if and only if the subgroup P splits over H, provided the order of H and the index of P in G are coprime.*)\nTheorem Gaschutz_split : [splits G, over H] = [splits P, over H].\n\n(*This theorem asserts that for any two complements to a normal abelian subgroup H within a finite group G, if their intersections with an intermediate subgroup P are identical, then the two complements are conjugate to one another by an element of H.*)\nTheorem Gaschutz_transitive : {in [complements to H in G] &,\n forall K L, K :&: P = L :&: P -> exists2 x, x \\in H & L :=: K :^ x}.\n\nEnd Gaschutz.\n\n(*This lemma states that if a subgroup A normalizes an abelian subgroup G, and their orders are coprime, then the centralizer of A in G is the trivial subgroup.*)\nLemma coprime_abel_cent_TI (gT : finGroupType) (A G : {group gT}) :\n A \\subset 'N(G) -> coprime #|G| #|A| -> abelian G -> 'C_[~: G, A](A) = 1.\n\nSection Transfer.\n\nVariables (gT aT : finGroupType) (G H : {group gT}).\nVariable alpha : {morphism H >-> aT}.\n\nHypotheses (sHG : H \\subset G) (abelA : abelian (alpha @* H)).\n\n(*This notation represents the set of all right cosets of a subgroup H within a group G.*)\nLocal Notation HG := (rcosets (gval H) (gval G)).\n\n(*This fact states that a subgroup H is contained within the preimage under a group morphism alpha of the image of H itself.*)\nFact transfer_morph_subproof : H \\subset alpha @*^-1 (alpha @* H).\n\n(*This definition constructs a group morphism from a subgroup H into a Z-module. The morphism is created by composing the given group morphism alpha with a coercion that views its codomain as a Z-module.*)\nLet fmalpha := restrm transfer_morph_subproof (fmod abelA \\o alpha).\n\n(*This definition specifies a function that computes a sum in a target Z-module for a given group element. The sum is taken over all right cosets of a subgroup H, where each term is the image under a morphism of a specific element constructed from the given element and a choice of coset representatives.*)\nLet V (rX : {set gT} -> gT) g :=\n \\sum_(Hx in rcosets H G) fmalpha (rX Hx * g * (rX (Hx :* g))^-1).\n\n(*This definition specifies the transfer homomorphism from a group G to an abelian group. It is defined for a given group element as the sum, in the target group, of images of elements constructed from a canonical choice of coset representatives of a subgroup H.*)\nDefinition transfer g := V repr g.\n\n(*This lemma asserts that the transfer map is a group homomorphism from the group G to the target abelian group, meaning it preserves the group structure by mapping products in G to sums in the target group.*)\nLemma transferM : {in G &, {morph transfer : x y / (x * y)%g >-> x + y}}.\n\nCanonical transfer_morphism := Morphism transferM.\n\n(*This lemma states that the transfer homomorphism is independent of the choice of coset representatives, showing that its value is the same for any valid set of representatives of the cosets of a subgroup H in a group G.*)\nLemma transfer_indep X (rX := transversal_repr 1 X) :\n is_transversal X HG G -> {in G, transfer =1 V rX}.\n\nSection FactorTransfer.\n\nVariable g : gT.\nHypothesis Gg : g \\in G.\n\n(*This definition provides a proof that the cyclic subgroup generated by an element g is a subgroup of the group G.*)\nLet sgG : <[g]> \\subset G. \n(*This definition specifies a function that, for a given element x, computes the orbit of the coset Hx under the right multiplicative action of the cyclic group generated by g.*)\nLet H_g_rcosets x : {set {set gT}} := rcosets (H :* x) <[g]>.\n(*This definition denotes a function that computes the size of the orbit of the coset Hx under the action of the cyclic group generated by g.*)\nLet n_ x := #|<[g]> : H :* x|.\n\n(*This lemma asserts that for any element x, multiplying x by g raised to the power of the size of the orbit of the coset Hx results in an element that belongs to the same coset Hx.*)\nLemma mulg_exp_card_rcosets x : x * (g ^+ n_ x) \\in H :* x.\n\n(*This definition represents the set of orbits formed by the action of the cyclic group generated by g on the set of right cosets of H in G. The action is right multiplication.*)\nLet HGg : {set {set {set gT}}} := orbit 'Rs <[g]> @: HG.\n\n(*This definition establishes that the set of right cosets of a subgroup H in a group G forms a partition of the set G.*)\nLet partHG : partition HG G := rcosets_partition sHG.\n(*This definition establishes that the cyclic group generated by an element g acts on the set of right cosets of H in G via right multiplication.*)\nLet actsgHG : [acts <[g]>, on HG | 'Rs].\n\n(*This definition establishes that the set of orbits, resulting from the action of the cyclic group generated by g on the right cosets of H, forms a partition of the set of all right cosets of H.*)\nLet partHGg : partition HGg HG := orbit_partition actsgHG.\n\n(*This lemma asserts that the orbits formed by the action of the cyclic group generated by g on the right cosets of H are pairwise disjoint.*)\nLet injHGg : {in HGg &, injective cover}.\n\n(*This lemma provides a definition for the notation representing the set of all right cosets of H under the action of the cyclic group of g, equating it to the union of all orbits.*)\nLet defHGg : HG :* <[g]> = cover @: HGg.\n\n(*This lemma asserts that the collection of sets, where each set is the union of all cosets belonging to a single orbit under the action of the cyclic group of g, forms a partition of the group G.*)\nLemma rcosets_cycle_partition : partition (HG :* <[g]>) G.\n\nVariable X : {set gT}.\nHypothesis trX : is_transversal X (HG :* <[g]>) G.\n\n(*This definition provides a proof that the transversal set X is a subset of the group G.*)\nLet sXG : {subset X <= G}. \n\n(*This lemma states that applying the orbit-computing function `H_g_rcosets` to every element in the transversal X generates the complete set of all orbits.*)\nLemma rcosets_cycle_transversal : H_g_rcosets @: X = HGg.\n\n(*This notation provides a local alias for the lemma `rcosets_cycle_transversal`, which relates a transversal set to the orbits of cosets under a cyclic group action.*)\nLocal Notation defHgX := rcosets_cycle_transversal.\n\n(*This lemma asserts that the orbit-computing function `H_g_rcosets` is injective when restricted to the transversal set X, as each element of X represents a distinct orbit.*)\nLet injHg: {in X &, injective H_g_rcosets}.\n\n(*This lemma states that for a given group element acting on the right cosets of a subgroup, the sum of the lengths of the disjoint cycles of the induced permutation equals the index of the subgroup.*)\nLemma sum_index_rcosets_cycle : (\\sum_(x in X) n_ x)%N = #|G : H|.\n\n(*This lemma provides a formula, known as the cycle expansion, for the transfer homomorphism from a group to a subgroup. It states that the transfer of a group element is a product, where each factor corresponds to a disjoint cycle from the permutation of right cosets induced by that element. Each factor is calculated by taking the group element raised to the power of the cycle's length, and then conjugating this result by an element representing a coset within that cycle.*)\nLemma transfer_cycle_expansion :\n transfer g = \\sum_(x in X) fmalpha ((g ^+ n_ x) ^ (x^-1)).\n\nEnd FactorTransfer.", - "solvable.gfunctor": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat fintype.\nFrom mathcomp Require Import bigop finset fingroup morphism automorphism.\nFrom mathcomp Require Import quotient gproduct.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope gFun_scope.\n\nImport GroupScope.\n\nDelimit Scope gFun_scope with gF.\n\nModule GFunctor.\n\n(*This definition represents a type of function that takes a finite group and a set of its elements as input, and returns another set of elements from the same finite group.*)\nDefinition object_map := forall gT : finGroupType, {set gT} -> {set gT}.\n\nBind Scope gFun_scope with object_map.\n\nSection Definitions.\n\nImplicit Types gT hT : finGroupType.\n\nVariable F : object_map.\n\n(*This definition describes a property of an object map asserting that for any given input group, the resulting set of elements itself forms a group.*)\nDefinition group_valued := forall gT (G : {group gT}), group_set (F G).\n\n(*This definition describes a property of an object map asserting that the set of elements it produces for any given group is always a subset of that original group.*)\nDefinition closed := forall gT (G : {group gT}), F G \\subset G.\n\n(*This definition describes a continuity property for an object map, requiring that for any group morphism, the image of the map's output is a subset of the output produced by applying the map to the image of the original group.*)\nDefinition continuous :=\n forall gT hT (G : {group gT}) (phi : {morphism G >-> hT}),\n phi @* F G \\subset F (phi @* G).\n\n(*This definition describes a continuity property for an object map that is restricted to injective group morphisms, requiring that the image of the map's output is a subset of the output produced by a pplying the map to the image of the original group.*)\nDefinition iso_continuous :=\n forall gT hT (G : {group gT}) (phi : {morphism G >-> hT}),\n 'injm phi -> phi @* F G \\subset F (phi @* G).\n\n(*This lemma states that any object map satisfying the continuity property with respect to all group morphisms also satisfies the continuity property when restricted to only injective group morphisms.*)\nLemma continuous_is_iso_continuous : continuous -> iso_continuous.\n\n(*This definition describes a strong continuity property for an object map, requiring that for any pair of subgroups in the same ambient group and a morphism on one, the image of the map's output on the other subgroup is contained within the map's output on the image of the first subgroup.*)\nDefinition pcontinuous :=\n forall gT hT (G D : {group gT}) (phi : {morphism D >-> hT}),\n phi @* F G \\subset F (phi @* G).\n\n(*This lemma states that any object map satisfying the strong p-continuity property also satisfies the standard continuity property.*)\nLemma pcontinuous_is_continuous : pcontinuous -> continuous.\n\n(*This definition describes the hereditary property for an object map, which holds if for any group and its subgroup, the intersection of the map's output on the larger group with the subgroup is contained within the map's output on the smaller subgroup.*)\nDefinition hereditary :=\n forall gT (H G : {group gT}), H \\subset G -> F G :&: H \\subset F H.\n\n(*This lemma states that any object map satisfying the strong p-continuity property also satisfies the hereditary property.*)\nLemma pcontinuous_is_hereditary : pcontinuous -> hereditary.\n\n(*This definition describes the monotonic property for an object map, which holds if the map preserves the subgroup inclusion relation, meaning the output for a subgroup is always a subset of the output for a larger group containing it.*)\nDefinition monotonic :=\n forall gT (H G : {group gT}), H \\subset G -> F H \\subset F G.\n\nVariables (F1 F2 : object_map).\n\n(*This definition creates a new object map by composing two existing object maps, where the new map is the result of applying the second map and then applying the first map to that result.*)\nDefinition comp : object_map := fun gT A => F1 (F2 A).\n\n(*This definition creates a new object map by applying the first map to the quotient of a group by the result of the second map, and then taking the preimage of the final result under the quotient map.*)\nDefinition modulo : object_map :=\n fun gT A => coset (F2 A) @*^-1 (F1 (A / (F2 A))).\n\nEnd Definitions.\n\nSection ClassDefinitions.\n\n(*This structure defines an iso-map as an object map that always transforms a group into one of its own subgroups and exhibits predictable behavior with respect to injective group morphisms.*)\nStructure iso_map := IsoMap {\n(*The apply tactic attempts to resolve the current proof goal by unifying it with the conclusion of a provided lemma, theorem, or hypothesis. If successful, it instantiates any variables in the lemma and replaces the current goal with its premises, which then become new subgoals to be proven.*)\n apply : object_map;\n _ : group_valued apply;\n _ : closed apply;\n _ : iso_continuous apply\n}.\nLocal Coercion apply : iso_map >-> object_map.\n\n(*This structure defines a group functor map as an iso-map that also satisfies the full continuity property, ensuring it behaves predictably with respect to all group morphisms, not just injective ones.*)\nStructure map := Map { iso_of_map : iso_map; _ : continuous iso_of_map }.\nLocal Coercion iso_of_map : map >-> iso_map.\n\n(*This structure defines a p-map as a group functor map that also satisfies the hereditary property, ensuring its behavior on a group is consistent with its behavior on that group's subgroups.*)\nStructure pmap := Pmap { map_of_pmap : map; _ : hereditary map_of_pmap }.\nLocal Coercion map_of_pmap : pmap >-> map.\n\n(*This structure defines a monotonic map as a group functor map that also satisfies the monotonic property, ensuring it preserves the subgroup inclusion relation.*)\nStructure mono_map := MonoMap { map_of_mono : map; _ : monotonic map_of_mono }.\nLocal Coercion map_of_mono : mono_map >-> map.\n\n(*This definition provides a constructor for an iso-map structure by taking an object map along with proofs that it is group-valued, closed, and iso-continuous, and combines them into a single iso-map object.*)\nDefinition pack_iso F Fcont Fgrp Fsub := @IsoMap F Fgrp Fsub Fcont.\n\n(*This definition provides a helper for constructing an iso-map structure from an existing one that shares the same underlying object map, allowing for the replacement of property proofs while maintaining inferential equivalence.*)\nDefinition clone_iso (F : object_map) :=\n fun Fgrp Fsub Fcont (isoF := @IsoMap F Fgrp Fsub Fcont) =>\n fun isoF0 & phant_id (apply isoF0) F & phant_id isoF isoF0 => isoF.\n\n(*This definition provides a helper for constructing a group functor map from an existing one with the same underlying object map, allowing a new proof of continuity to be supplied while maintaining inferential equivalence.*)\nDefinition clone (F : object_map) :=\n fun isoF & phant_id (apply isoF) F =>\n fun (funF0 : map) & phant_id (apply funF0) F =>\n fun Fcont (funF := @Map isoF Fcont) & phant_id funF0 funF => funF.\n\n(*This definition provides a helper for constructing a p-map from an existing one with the same underlying object map, allowing a new proof of the hereditary property to be supplied while maintaining inferential equivalence.*)\nDefinition clone_pmap (F : object_map) :=\n fun (funF : map) & phant_id (apply funF) F =>\n fun (pfunF0 : pmap) & phant_id (apply pfunF0) F =>\n fun Fher (pfunF := @Pmap funF Fher) & phant_id pfunF0 pfunF => pfunF.\n\n(*This definition provides a helper for constructing a monotonic map from an existing one with the same underlying object map, allowing a new proof of the monotonic property to be supplied while maintaining inferential equivalence.*)\nDefinition clone_mono (F : object_map) :=\n fun (funF : map) & phant_id (apply funF) F =>\n fun (mfunF0 : mono_map) & phant_id (apply mfunF0) F =>\n fun Fmon (mfunF := @MonoMap funF Fmon) & phant_id mfunF0 mfunF => mfunF.\n\nEnd ClassDefinitions.\n\nModule Exports.\n\nIdentity Coercion fun_of_object_map : object_map >-> Funclass.\nCoercion apply : iso_map >-> object_map.\nCoercion iso_of_map : map >-> iso_map.\nCoercion map_of_pmap : pmap >-> map.\nCoercion map_of_mono : mono_map >-> map.\nCoercion continuous_is_iso_continuous : continuous >-> iso_continuous.\nCoercion pcontinuous_is_continuous : pcontinuous >-> continuous.\nCoercion pcontinuous_is_hereditary : pcontinuous >-> hereditary.\n\n(*This notation provides a convenient way to construct an iso-map by supplying proofs that the underlying map is closed and continuous, from which the iso-continuity and group-valued properties are automatically inferred.*)\nNotation \"[ 'igFun' 'by' Fsub & Fcont ]\" :=\n (pack_iso (continuous_is_iso_continuous Fcont) (fun gT G => groupP _) Fsub)\n (format \"[ 'igFun' 'by' Fsub & Fcont ]\") : form_scope.\n\n(*This notation provides a convenient way to construct an iso-map by supplying direct proofs that the underlying map is closed and iso-continuous, while the group-valued property is inferred automatically.*)\nNotation \"[ 'igFun' 'by' Fsub & ! Fcont ]\" :=\n (pack_iso Fcont (fun gT G => groupP _) Fsub)\n (format \"[ 'igFun' 'by' Fsub & ! Fcont ]\") : form_scope.\n\n(*This notation retrieves the canonical iso-map structure associated with a given object map, making an existing implicit structure explicit for a proof.*)\nNotation \"[ 'igFun' 'of' F ]\" := (@clone_iso F _ _ _ _ id id)\n (format \"[ 'igFun' 'of' F ]\") : form_scope.\n\n(*This notation constructs a group functor map from an existing iso-map structure by providing an additional proof of continuity.*)\nNotation \"[ 'gFun' 'by' Fcont ]\" := (Map Fcont)\n (format \"[ 'gFun' 'by' Fcont ]\") : form_scope.\n\n(*This notation retrieves the canonical group functor map structure associated with a given object map, making an existing implicit structure explicit for a proof.*)\nNotation \"[ 'gFun' 'of' F ]\" := (@clone F _ id _ id _ id)\n (format \"[ 'gFun' 'of' F ]\") : form_scope.\n\n(*This notation constructs a p-map from an existing group functor map structure by providing an additional proof of the hereditary property.*)\nNotation \"[ 'pgFun' 'by' Fher ]\" := (Pmap Fher)\n (format \"[ 'pgFun' 'by' Fher ]\") : form_scope.\n\n(*This notation retrieves the canonical p-map structure associated with a given object map, making an existing implicit structure explicit for a proof.*)\nNotation \"[ 'pgFun' 'of' F ]\" := (@clone_pmap F _ id _ id _ id)\n (format \"[ 'pgFun' 'of' F ]\") : form_scope.\n\n(*This notation constructs a monotonic map from an existing group functor map structure by providing an additional proof of the monotonic property.*)\nNotation \"[ 'mgFun' 'by' Fmon ]\" := (MonoMap Fmon)\n (format \"[ 'mgFun' 'by' Fmon ]\") : form_scope.\n\n(*This notation constructs a monotonic group functor from a given function, using identity functions for the morphism components.*)\nNotation \"[ 'mgFun' 'of' F ]\" := (@clone_mono F _ id _ id _ id)\n (format \"[ 'mgFun' 'of' F ]\") : form_scope.\n\nEnd Exports.\n\nEnd GFunctor.\nExport GFunctor.Exports.\n\nBind Scope gFun_scope with GFunctor.object_map.\n\nArguments GFunctor.comp F1 F2 _ /.\n(*This notation represents the composition of two group functors, where the output of the second functor is used as the input for the first functor.*)\nNotation \"F1 \\o F2\" := (GFunctor.comp F1 F2) : gFun_scope.\n(*This notation represents the modulo operation between two group functors.*)\nNotation \"F1 %% F2\" := (GFunctor.modulo F1 F2) : gFun_scope.\n\nSection FunctorGroup.\n\nVariables (F : GFunctor.iso_map) (gT : finGroupType) (G : {group gT}).\n(*This lemma states that the image of a finite group under an isomorphic group functor is itself a group.*)\nLemma gFgroupset : group_set (F gT G). \nCanonical gFgroup := Group gFgroupset.\n\nEnd FunctorGroup.\n\nCanonical gFmod_group\n (F1 : GFunctor.iso_map) (F2 : GFunctor.object_map)\n (gT : finGroupType) (G : {group gT}) :=\n [group of (F1 %% F2)%gF gT G].\n\nSection IsoFunctorTheory.\n\nImplicit Types gT rT : finGroupType.\nVariable F : GFunctor.iso_map.\n\n(*This lemma states that the group obtained by applying an isomorphic group functor to a given finite group is a subgroup of the original group.*)\nLemma gFsub gT (G : {group gT}) : F gT G \\subset G.\n\n(*This lemma states that if a finite group is contained in a given set, then its image under an isomorphic group functor is also contained in that set.*)\nLemma gFsub_trans gT (G : {group gT}) (A : {pred gT}) :\n G \\subset A -> F gT G \\subset A.\n\n(*This lemma states that an isomorphic group functor applied to the trivial group yields the trivial group.*)\nLemma gF1 gT : F gT 1 = 1. \n\n(*This lemma states that any isomorphic group functor possesses the property of continuity.*)\nLemma gFiso_cont : GFunctor.iso_continuous F.\n\n(*This lemma states that the group obtained by applying an isomorphic group functor to a given finite group is a characteristic subgroup of the original group.*)\nLemma gFchar gT (G : {group gT}) : F gT G \\char G.\n\n(*This lemma states that any finite group is a subgroup of the normalizer of the group resulting from the application of an isomorphic group functor to it.*)\nLemma gFnorm gT (G : {group gT}) : G \\subset 'N(F gT G).\n\n(*This lemma states that the normalizer of a given finite group is a subgroup of the normalizer of the group obtained by applying an isomorphic group functor to the given group.*)\nLemma gFnorms gT (G : {group gT}) : 'N(G) \\subset 'N(F gT G).\n\n(*This lemma states that the group obtained by applying an isomorphic group functor to a given finite group is a normal subgroup of the original group.*)\nLemma gFnormal gT (G : {group gT}) : F gT G <| G.\n\n(*This lemma states that if a group is a characteristic subgroup of another, then applying an isomorphic group functor to the first group results in a group that is also a characteristic subgroup of the second.*)\nLemma gFchar_trans gT (G H : {group gT}) : H \\char G -> F gT H \\char G.\n\n(*This lemma states that if a group is a normal subgroup of another, then applying an isomorphic group functor to the first group results in a group that is also a normal subgroup of the second.*)\nLemma gFnormal_trans gT (G H : {group gT}) : H <| G -> F gT H <| G.\n\n(*This lemma states that if a set is contained in the normalizer of a given finite group, it is also contained in the normalizer of the group obtained by applying an isomorphic group functor to that group.*)\nLemma gFnorm_trans gT (A : {pred gT}) (G : {group gT}) :\n A \\subset 'N(G) -> A \\subset 'N(F gT G).\n\n(*This lemma states that when applying an injective group morphism to the result of an isomorphic group functor on a group, the resulting group is a subgroup of what is obtained by first taking the image of the group under the morphism and then applying the functor.*)\nLemma injmF_sub gT rT (G D : {group gT}) (f : {morphism D >-> rT}) :\n 'injm f -> G \\subset D -> f @* (F gT G) \\subset F rT (f @* G).\n\n(*This lemma states that an isomorphic group functor commutes with injective group morphisms, meaning applying the morphism to the functor's result on a group is equivalent to applying the functor to the morphism's result on the group.*)\nLemma injmF gT rT (G D : {group gT}) (f : {morphism D >-> rT}) :\n 'injm f -> G \\subset D -> f @* (F gT G) = F rT (f @* G).\n\n(*This lemma states that if a group morphism establishes an isomorphism between two groups, it also establishes an isomorphism between the groups resulting from applying an isomorphic group functor to each of them.*)\nLemma gFisom gT rT (G D : {group gT}) R (f : {morphism D >-> rT}) :\n G \\subset D -> isom G (gval R) f -> isom (F gT G) (F rT R) f.\n\n(*This lemma states that an isomorphic group functor preserves group isomorphisms; if two groups are isomorphic, their images under the functor are also isomorphic.*)\nLemma gFisog gT rT (G : {group gT}) (R : {group rT}) :\n G \\isog R -> F gT G \\isog F rT R.\n\nEnd IsoFunctorTheory.\n\nSection FunctorTheory.\n\nImplicit Types gT rT : finGroupType.\nVariable F : GFunctor.map.\n\n(*This lemma states that any group functor map possesses the property of continuity.*)\nLemma gFcont : GFunctor.continuous F.\n\n(*This lemma states that for any group morphism, applying it to the result of a group functor map on a group yields a subgroup of what is obtained by first taking the image of the original group under the morphism and then applying the functor.*)\nLemma morphimF gT rT (G D : {group gT}) (f : {morphism D >-> rT}) :\n G \\subset D -> f @* (F gT G) \\subset F rT (f @* G).\n\nEnd FunctorTheory.\n\nSection PartialFunctorTheory.\n\nImplicit Types gT rT : finGroupType.\n\nSection BasicTheory.\n\nVariable F : GFunctor.pmap.\n\n(*This lemma states that any partial group functor possesses the hereditary property, meaning that if one group is a subgroup of another, the image of the first group under the functor is a subgroup of the image of the second.*)\nLemma gFhereditary : GFunctor.hereditary F.\n\n(*This lemma gives an absorption-like identity for a partial group functor regarding intersection: intersecting the image of a group with another group is the same as intersecting the image of the first group with the image of the intersection of the two groups.*)\nLemma gFunctorI gT (G H : {group gT}) :\n F gT G :&: H = F gT G :&: F gT (G :&: H).\n\n(*This lemma states that any partial group functor has the property of being partially continuous.*)\nLemma pmorphimF : GFunctor.pcontinuous F.\n\n(*This lemma states that a partial group functor is idempotent, meaning applying the functor twice to a group has the same result as applying it once.*)\nLemma gFid gT (G : {group gT}) : F gT (F gT G) = F gT G.\n\nEnd BasicTheory.\n\nSection Modulo.\n\nVariables (F1 : GFunctor.pmap) (F2 : GFunctor.map).\n\n(*This lemma states that the modulo composition of a partial group functor and a group functor map results in a closed group functor.*)\nLemma gFmod_closed : GFunctor.closed (F1 %% F2).\n\n(*This lemma states that the modulo composition of a partial group functor and a group functor map results in a continuous group functor.*)\nLemma gFmod_cont : GFunctor.continuous (F1 %% F2).\n\nCanonical gFmod_igFun := [igFun by gFmod_closed & gFmod_cont].\nCanonical gFmod_gFun := [gFun by gFmod_cont].\n\nEnd Modulo.\n\nVariables F1 F2 : GFunctor.pmap.\n\n(*This lemma states that the modulo composition of two partial group functors results in a hereditary group functor.*)\nLemma gFmod_hereditary : GFunctor.hereditary (F1 %% F2).\n\nCanonical gFmod_pgFun := [pgFun by gFmod_hereditary].\n\nEnd PartialFunctorTheory.\n\nSection MonotonicFunctorTheory.\n\nImplicit Types gT rT : finGroupType.\n\n(*This lemma states that a monotonic group functor map preserves the subgroup relation, meaning the image of a subgroup under the functor is a subgroup of the image of the containing group.*)\nLemma gFunctorS (F : GFunctor.mono_map) : GFunctor.monotonic F.\n\nSection Composition.\n\nVariables (F1 : GFunctor.mono_map) (F2 : GFunctor.map).\n\n(*This lemma states that the composition of a monotonic GFunctor with another GFunctor resultados in a closed GFunctor, which is one that maps the set of all subgroups of an input group to the set of all subgroups of the output group.*)\nLemma gFcomp_closed : GFunctor.closed (F1 \\o F2).\n\n(*This lemma states that the composition of a monotonic GFunctor with another GFunctor is continuous, meaning it preserves the intersections of subgroups.*)\nLemma gFcomp_cont : GFunctor.continuous (F1 \\o F2).\n\nCanonical gFcomp_igFun := [igFun by gFcomp_closed & gFcomp_cont].\nCanonical gFcomp_gFun :=[gFun by gFcomp_cont].\n\nEnd Composition.\n\nVariables F1 F2 : GFunctor.mono_map.\n\n(*This lemma states that the composition of two monotonic GFunctors is also a monotonic GFunctor, meaning it preserves the subgroup inclusion relation.*)\nLemma gFcompS : GFunctor.monotonic (F1 \\o F2).\n\nCanonical gFcomp_mgFun := [mgFun by gFcompS].\n\nEnd MonotonicFunctorTheory.\n\nSection GFunctorExamples.\n\nImplicit Types gT : finGroupType.\n\n(*This definition specifies the identity GFunctor, which, for any given finite group, acts as the identity function on its collection of subgroups.*)\nDefinition idGfun gT := @id {set gT}.\n\n(*This lemma states that the identity GFunctor is a closed functor, meaning that it maps the collection of all subgroups of a given group to itself.*)\nLemma idGfun_closed : GFunctor.closed idGfun. \n(*This lemma states that the identity GFunctor is continuous, meaning it preserves the intersections of subgroups.*)\nLemma idGfun_cont : GFunctor.continuous idGfun. \n(*This lemma states that the identity GFunctor is monotonic, meaning it preserves the subgroup inclusion relation.*)\nLemma idGfun_monotonic : GFunctor.monotonic idGfun. \n\nCanonical bgFunc_id := [igFun by idGfun_closed & idGfun_cont].\nCanonical gFunc_id := [gFun by idGfun_cont].\nCanonical mgFunc_id := [mgFun by idGfun_monotonic].\n\n(*This definition introduces the trivial GFunctor, which, for any given finite group, maps each of its subgroups to the trivial subgroup containing only the identity element.*)\nDefinition trivGfun gT of {set gT} := [1 gT].\n\n(*This lemma states that the trivial GFunctor is a continuous functor, meaning it preserves the intersections of subgroups.*)\nLemma trivGfun_cont : GFunctor.pcontinuous trivGfun.\n\nCanonical trivGfun_igFun := [igFun by sub1G & trivGfun_cont].\nCanonical trivGfun_gFun := [gFun by trivGfun_cont].\nCanonical trivGfun_pgFun := [pgFun by trivGfun_cont].\n\nEnd GFunctorExamples.", - "solvable.alt": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.\nFrom mathcomp Require Import div fintype tuple tuple bigop prime finset ssralg.\nFrom mathcomp Require Import zmodp fingroup morphism perm automorphism quotient.\nFrom mathcomp Require Import action cyclic pgroup gseries sylow.\nFrom mathcomp Require Import primitive_action nilpotent maximal.\n\nUnset Printing Implicit Defensive.\nSet Implicit Arguments.\nUnset Strict Implicit.\n\nImport GroupScope GRing.\n\n(*This definition establishes `Sym` as the set containing all permutations of a given finite type.*)\nDefinition Sym : {set {perm T}} := setT.\n\nCanonical Sym_group := Eval hnf in [group of Sym].\n\n(*A local notation which serves as an alias for `Sym`, the set of all permutations on a given finite type.*)\nLocal Notation \"'Sym_T\" := Sym.\n\nCanonical sign_morph := @Morphism _ _ 'Sym_T _ (in2W (@odd_permM _)).\n\n(*This definition establishes `Alt` as the alternating group, which is the kernel of the sign morphism, consisting of all even permutations on a given finite type.*)\nDefinition Alt := 'ker (@odd_perm T).\n\nCanonical Alt_group := Eval hnf in [group of Alt].\n\n(*A local notation which serves as an alias for `Alt`, the alternating group of even permutations on a given finite type.*)\nLocal Notation \"'Alt_T\" := Alt.\n\n(*This lemma states that a given permutation is an element of the alternating group if and only if that permutation is even.*)\nLemma Alt_even p : (p \\in 'Alt_T) = ~~ p.\n\n(*This lemma states that the alternating group on a given finite type is a subset of the corresponding symmetric group.*)\nLemma Alt_subset : 'Alt_T \\subset 'Sym_T.\n\n(*This lemma states that the alternating group on a given finite type is a normal subgroup of the corresponding symmetric group.*)\nLemma Alt_normal : 'Alt_T <| 'Sym_T.\n\n(*This lemma states that the symmetric group on a given finite type is a subset of the normalizer of the corresponding alternating group, which implies that every permutation in the symmetric group normalizes the alternating group.*)\nLemma Alt_norm : 'Sym_T \\subset 'N('Alt_T).\n\n(*A local definition for `n` as the cardinality, or number of elements, of the finite type `T`.*)\nLet n := #|T|.\n\n(*This lemma states that the index of the alternating group within the symmetric group is equal to two, provided that the underlying finite type has more than one element.*)\nLemma Alt_index : 1 < n -> #|'Sym_T : 'Alt_T| = 2.\n\n(*This lemma states that the cardinality of the symmetric group is equal to the factorial of the number of elements in the underlying finite type.*)\nLemma card_Sym : #|'Sym_T| = n`!.\n\n(*This lemma states that twice the cardinality of the alternating group equals the factorial of the number of elements in the underlying finite type, provided that the type has more than one element.*)\nLemma card_Alt : 1 < n -> (2 * #|'Alt_T|)%N = n`!.\n\n(*This lemma states that the symmetric group acts n-transitively on its underlying finite type of n elements.*)\nLemma Sym_trans : [transitive^n 'Sym_T, on setT | 'P].\n\n(*This lemma states that the alternating group acts n-minus-two-transitively on its underlying finite type of n elements.*)\nLemma Alt_trans : [transitive^n.-2 'Alt_T, on setT | 'P].\n\n(*This lemma states that any group of permutations on a finite type acts faithfully on that type.*)\nLemma aperm_faithful (A : {group {perm T}}) : [faithful A, on setT | 'P].\n\nEnd SymAltDef.\n\nArguments Sym T%_type.\nArguments Sym_group T%_type.\nArguments Alt T%_type.\nArguments Alt_group T%_type.\n\n(*A notation providing the standard mathematical syntax for the symmetric group on a given type. It resolves to the set of all permutations or to the canonical group structure on this set, depending on the context.*)\nNotation \"''Sym_' T\" := (Sym T)\n (at level 8, T at level 2, format \"''Sym_' T\") : group_scope.\n(*This notation represents the symmetric group on a given finite type. The symmetric group is the group of all permutations of that type, where the group operation is function composition.*)\nNotation \"''Sym_' T\" := (Sym_group T) : Group_scope.\n\n(*This notation represents the alternating group on a given finite type. The alternating group is the subgroup of the symmetric group consisting of all even permutations, with function composition as the group operation.*)\nNotation \"''Alt_' T\" := (Alt T)\n (at level 8, T at level 2, format \"''Alt_' T\") : group_scope.\n(*A notation for the alternating group on a given finite type, which is the subgroup of all even permutations.*)\nNotation \"''Alt_' T\" := (Alt_group T) : Group_scope.\n\n(*This lemma states that for any finite type with a cardinality of at most two, its alternating group is the trivial group, containing only the identity permutation.*)\nLemma trivial_Alt_2 (T : finType) : #|T| <= 2 -> 'Alt_T = 1.\n\n(*This lemma states that for any finite type with a cardinality of exactly three, its corresponding alternating group is a simple group.*)\nLemma simple_Alt_3 (T : finType) : #|T| = 3 -> simple 'Alt_T.\n\n(*This lemma states that for any finite type with a cardinality of exactly four, its corresponding alternating group is not a simple group.*)\nLemma not_simple_Alt_4 (T : finType) : #|T| = 4 -> ~~ simple 'Alt_T.\n\n(*This lemma states that for any finite type with a cardinality of exactly five, its corresponding alternating group is a simple group.*)\nLemma simple_Alt5_base (T : finType) : #|T| = 5 -> simple 'Alt_T.\n\nSection Restrict.\n\nVariables (T : finType) (x : T).\n(*A notation for the subtype of a given finite type that contains all elements except for one specified element.*)\nNotation T' := {y | y != x}.\n\n(*This lemma states that for a given permutation on a finite type and an element of that type, if the permutation is adjusted to be the identity when it does not fix the specified element, then applying this adjusted permutation to any other element will not result in that specified element.*)\nLemma rfd_funP (p : {perm T}) (u : T') :\n let p1 := if p x == x then p else 1 in p1 (val u) != x.\n\n(*This definition constructs a function on a subtype by taking a permutation on a larger finite type and restricting its action to the elements of the subtype.*)\nDefinition rfd_fun p := [fun u => Sub ((_ : {perm T}) _) (rfd_funP p u) : T'].\n\n(*This lemma states that the function created by restricting a permutation from a larger finite type to a subtype is an injective function.*)\nLemma rfdP p : injective (rfd_fun p).\n\n(*This definition creates a permutation on a subtype from a permutation on a larger finite type by leveraging a proof that the corresponding restricted function is injective.*)\nDefinition rfd p := perm (@rfdP p).\n\nHypothesis card_T : 2 < #|T|.\n\n(*This lemma establishes that the function which restricts permutations that fix a specific element of a finite type to permutations on the subtype excluding that element is a group homomorphism.*)\nLemma rfd_morph : {in 'C_('Sym_T)[x | 'P] &, {morph rfd : y z / y * z}}.\n\nCanonical rfd_morphism := Morphism rfd_morph.\n\n(*This definition constructs a function on a finite type by extending a given permutation from a subtype. The new function behaves like the given permutation on elements within the subtype and fixes the single element that was excluded from it.*)\nDefinition rgd_fun (p : {perm T'}) :=\n [fun x1 => if insub x1 is Some u then sval (p u) else x].\n\n(*This lemma states that the function created by extending a permutation from a subtype to a larger finite type is an injective function.*)\nLemma rgdP p : injective (rgd_fun p).\n\n(*This definition creates a permutation on a finite type from a permutation on a subtype by using a proof that the corresponding extended function is injective.*)\nDefinition rgd p := perm (@rgdP p).\n\n(*This lemma states that for a permutation on a finite type that fixes a specific element, the sign of the restricted permutation on the corresponding subtype is identical to the sign of the original permutation.*)\nLemma rfd_odd (p : {perm T}) : p x = x -> rfd p = p :> bool.\n\n(*This lemma states that the subgroup of the alternating group on a finite type, consisting of all even permutations that fix a given element, is isomorphic to the alternating group on the subtype that excludes that element.*)\nLemma rfd_iso : 'C_('Alt_T)[x | 'P] \\isog 'Alt_T'.\n\nEnd Restrict.\n\n(*This lemma states that for any finite type with a cardinality of five or more, its corresponding alternating group is a simple group.*)\nLemma simple_Alt5 (T : finType) : #|T| >= 5 -> simple 'Alt_T.\n\n(*This lemma states that for a finite type whose cardinality is a prime number, the entire symmetric group can be generated by two permutations: any single transposition and any cycle of maximal length.*)\nLemma gen_tperm_circular_shift (X : finType) x y c : prime #|X| ->\n x != y -> #[c]%g = #|X| ->\n <<[set tperm x y; c]>>%g = ('Sym_X)%g.\n\nSection Perm_solvable.\nLocal Open Scope nat_scope.\n\nVariable T : finType.\n\n(*This lemma states that for any finite type with a cardinality greater than four, its corresponding alternating group is not a solvable group.*)\nLemma solvable_AltF : 4 < #|T| -> solvable 'Alt_T = false.\n\n(*This lemma states that for any finite type with a cardinality greater than four, its corresponding symmetric group is not a solvable group.*)\nLemma solvable_SymF : 4 < #|T| -> solvable 'Sym_T = false.", - "solvable.cyclic": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.\nFrom mathcomp Require Import div fintype bigop prime finset fingroup morphism.\nFrom mathcomp Require Import perm automorphism quotient gproduct ssralg.\nFrom mathcomp Require Import finalg zmodp poly.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope GRing.Theory.\n\nSection Cyclic.\n\nVariable gT : finGroupType.\nImplicit Types (a x y : gT) (A B : {set gT}) (G K H : {group gT}).\n\n(*This definition states that a set of group elements is cyclic if it is equal to the subgroup generated by a single element.*)\nDefinition cyclic A := [exists x, A == <[x]>].\n\n(*This lemma establishes a correspondence between the boolean predicate asserting that a set is cyclic and the logical proposition stating the existence of a generator for that set.*)\nLemma cyclicP A : reflect (exists x, A = <[x]>) (cyclic A).\n\n(*This lemma states that any subgroup generated by a single element is cyclic.*)\nLemma cycle_cyclic x : cyclic <[x]>.\n\n(*This lemma states that the trivial subgroup, which contains only the identity element, is a cyclic group.*)\nLemma cyclic1 : cyclic [1 gT].\n\nSection Zpm.\n\nVariable a : gT.\n\n(*This definition defines a function that maps an integer from the cyclic group of integers modulo the order of a group element to that group element raised to the power of the integer.*)\nDefinition Zpm (i : 'Z_#[a]) := a ^+ i.\n\n(*This lemma states that the function mapping an integer to a group element raised to that integer's power is a group morphism from the additive group of integers modulo the element's order to the multiplicative group.*)\nLemma ZpmM : {in Zp #[a] &, {morph Zpm : x y / x * y}}.\n\nCanonical Zpm_morphism := Morphism ZpmM.\n\n(*This lemma states that the image of the exponentiation morphism based on a group element is precisely the cyclic subgroup generated by that element.*)\nLemma im_Zpm : Zpm @* Zp #[a] = <[a]>.\n\n(*This lemma states that the exponentiation morphism, which maps an integer from the cyclic group of integers modulo an element's order to that element raised to the integer's power, is injective.*)\nLemma injm_Zpm : 'injm Zpm.\n\n(*This lemma states that two powers of a group element are equal if and only if their integer exponents are congruent modulo the order of the element.*)\nLemma eq_expg_mod_order m n : (a ^+ m == a ^+ n) = (m == n %[mod #[a]]).\n\n(*This lemma states that for two integer exponents within a range smaller than or equal to the order of a group element, the powers of the element are equal if and only if the exponents themselves are equal.*)\nLemma eq_expg_ord d (m n : 'I_d) :\n d <= #[a]%g -> (a ^+ m == a ^+ n) = (m == n).\n\n(*This lemma states that if the order of a group element divides a positive natural number, then raising the element to the sum of two integers modulo that number is equivalent to the product of the powers of the element with those integers as exponents.*)\nLemma expgD_Zp d (n m : 'Z_d) : (d > 0)%N ->\n #[a]%g %| d -> a ^+ (n + m)%R = a ^+ n * a ^+ m.\n\n(*This lemma states that the additive group of integers modulo the order of a group element is isomorphic to the cyclic subgroup generated by that element, with the exponentiation map serving as the isomorphism.*)\nLemma Zp_isom : isom (Zp #[a]) <[a]> Zpm.\n\n(*This lemma states that the additive group of integers modulo the order of a group element is isomorphic to the cyclic subgroup generated by that element.*)\nLemma Zp_isog : isog (Zp #[a]) <[a]>.\n\nEnd Zpm.\n\n(*This lemma states that every cyclic group is an abelian group.*)\nLemma cyclic_abelian A : cyclic A -> abelian A.\n\n(*This lemma states that if two group elements commute and their orders are coprime, then the cyclic subgroup generated by the first element is a subgroup of the cyclic subgroup generated by their product.*)\nLemma cycleMsub a b :\n commute a b -> coprime #[a] #[b] -> <[a]> \\subset <[a * b]>.\n\n(*This lemma states that if two group elements commute and their orders are coprime, then the cyclic subgroup generated by their product is equal to the group product of the cyclic subgroups they each generate.*)\nLemma cycleM a b :\n commute a b -> coprime #[a] #[b] -> <[a * b]> = <[a]> * <[b]>.\n\n(*This lemma states that the product of two cyclic subgroups is cyclic, provided that one subgroup is contained in the centralizer of the other and their orders are coprime.*)\nLemma cyclicM A B :\n cyclic A -> cyclic B -> B \\subset 'C(A) -> coprime #|A| #|B| ->\n cyclic (A * B).\n\n(*This lemma states that the join of two cyclic subgroups is cyclic if one subgroup is contained in the centralizer of the other and their orders are coprime.*)\nLemma cyclicY K H :\n cyclic K -> cyclic H -> H \\subset 'C(K) -> coprime #|K| #|H| ->\n cyclic (K <*> H).\n\n(*This lemma states that the order of a group element divides a given natural number if and only if the element raised to the power of that number equals the identity element.*)\nLemma order_dvdn a n : #[a] %| n = (a ^+ n == 1).\n\n(*This lemma states that if a group element raised to a positive natural number power equals the identity, then the order of the element is less than or equal to that number.*)\nLemma order_inf a n : a ^+ n.+1 == 1 -> #[a] <= n.+1.\n\n(*This lemma, a corollary of Lagrange's theorem, states that for any element of a finite group, the order of the element divides the order of the group.*)\nLemma order_dvdG G a : a \\in G -> #[a] %| #|G|.\n\n(*This lemma states that any element of a finite group, when raised to the power of the order of the group, results in the identity element.*)\nLemma expg_cardG G a : a \\in G -> a ^+ #|G| = 1.\n\n(*This lemma states that raising an element of a finite group to an integer power is equivalent to raising it to the power of that integer reduced modulo the order of the group.*)\nLemma expg_znat G x k : x \\in G -> x ^+ (k%:R : 'Z_(#|G|))%R = x ^+ k.\n\n(*This lemma states that for an element in a finite group, raising it to the power of a negative integer is equivalent to taking the group inverse of the element raised to the corresponding positive integer.*)\nLemma expg_zneg G x (k : 'Z_(#|G|)) : x \\in G -> x ^+ (- k)%R = x ^- k.\n\n(*This lemma states that in a group of prime order, any non-identity element is a generator of the entire group.*)\nLemma nt_gen_prime G x : prime #|G| -> x \\in G^# -> G :=: <[x]>.\n\n(*This lemma states that if a non-identity group element raised to a prime number power equals the identity, then the order of the element is that prime number.*)\nLemma nt_prime_order p x : prime p -> x ^+ p = 1 -> x != 1 -> #[x] = p.\n\n(*This lemma states that the order of an integer power of a group element always divides the order of the original element.*)\nLemma orderXdvd a n : #[a ^+ n] %| #[a].\n\n(*This lemma provides a formula for the order of a power of a group element, stating that it is equal to the order of the original element divided by the greatest common divisor of the element's order and the natural number exponent.*)\nLemma orderXgcd a n : #[a ^+ n] = #[a] %/ gcdn #[a] n.\n\n(*This lemma states that if a natural number exponent divides the order of a group element, the order of the element raised to that exponent is the original order divided by the exponent.*)\nLemma orderXdiv a n : n %| #[a] -> #[a ^+ n] = #[a] %/ n.\n\n(*This lemma states that if a group element has an order that is a power of a prime number, then the order of that element raised to a power of the same prime is given by a specific power of that prime determined by the difference of the exponents.*)\nLemma orderXexp p m n x : #[x] = (p ^ n)%N -> #[x ^+ (p ^ m)] = (p ^ (n - m))%N.\n\n(*This lemma specifies the order of a group element when the order of one of its prime-power-exponentiated forms is known. It states that if raising an element to a power, where the base is a prime and the exponent is a natural number, results in a new element of a given order, and the prime divides that order, then the order of the original element is the product of the prime power and the given order.*)\nLemma orderXpfactor p k n x :\n #[x ^+ (p ^ k)] = n -> prime p -> p %| n -> #[x] = (p ^ k * n)%N.\n\n(*This lemma states that if raising a group element to a prime power results in an element of a given order, and that prime divides the given order, then the order of the original group element is the product of the prime and the given order.*)\nLemma orderXprime p n x :\n #[x ^+ p] = n -> prime p -> p %| n -> #[x] = (p * n)%N.\n\n(*This lemma states that if raising a group element to a power of a given natural number yields a new element with a certain order, and if all prime factors of the exponent are also prime factors of that order, then the order of the original group element is the product of the exponent and the order of the new element.*)\nLemma orderXpnat m n x : #[x ^+ m] = n -> \\pi(n).-nat m -> #[x] = (m * n)%N.\n\n(*This lemma states that if two group elements commute and their orders are coprime natural numbers, then the order of their product is equal to the product of their individual orders.*)\nLemma orderM a b :\n commute a b -> coprime #[a] #[b] -> #[a * b] = (#[a] * #[b])%N.\n\n(*This definition provides a number that acts as an exponentiative inverse for a given natural number with respect to the order of a finite group, computed using the extended Euclidean algorithm.*)\nDefinition expg_invn A k := (egcdn k #|A|).1.\n\n(*This lemma states that for any element in a finite group, exponentiation by a natural number can be inverted by exponentiation with another number, provided that the initial exponent is coprime to the order of the group.*)\nLemma expgK G k :\n coprime #|G| k -> {in G, cancel (expgn^~ k) (expgn^~ (expg_invn G k))}.\n\n(*This lemma states that the direct product of two cyclic groups is itself cyclic if and only if the orders of the two groups are coprime natural numbers.*)\nLemma cyclic_dprod K H G :\n K \\x H = G -> cyclic K -> cyclic H -> cyclic G = coprime #|K| #|H| .\n\n(*This definition specifies that a group element is a generator of a given group if the cyclic subgroup formed by that element is identical to the given group.*)\nDefinition generator (A : {set gT}) a := A == <[a]>.\n\n(*This lemma states that any group element is a generator of the cyclic subgroup it generates.*)\nLemma generator_cycle a : generator <[a]> a.\n\n(*This lemma states that any generator of a cyclic group must be an element of that group.*)\nLemma cycle_generator a x : generator <[a]> x -> x \\in <[a]>.\n\n(*This lemma states that if two elements generate the same cyclic group, then their orders are equal.*)\nLemma generator_order a b : generator <[a]> b -> #[a] = #[b].\n\nEnd Cyclic.\n\nArguments cyclic {gT} A%_g.\nArguments generator {gT} A%_g a%_g.\nArguments expg_invn {gT} A%_g k%_N.\nArguments cyclicP {gT A}.\nPrenex Implicits cyclic Zpm.\n\n(*This theorem, known as Euler's totient theorem, states that if a natural number is coprime to another natural number n, then raising the first number to the power of the totient of n results in a value that is congruent to one modulo n.*)\nTheorem Euler_exp_totient a n : coprime a n -> a ^ totient n = 1 %[mod n].\n\nSection Eltm.\n\nVariables (aT rT : finGroupType) (x : aT) (y : rT).\n\n(*This definition constructs a function between two finite groups which maps powers of a specific element in the source group to the corresponding powers of a specific element in the target group, provided that the order of the target element divides the order of the source element.*)\nDefinition eltm of #[y] %| #[x] := fun x_i => y ^+ invm (injm_Zpm x) x_i.\n\nHypothesis dvd_y_x : #[y] %| #[x].\n\n(*This lemma specifies the behavior of the `eltm` function, stating that it maps an element from the source group raised to a given power to the target element raised to the same power.*)\nLemma eltmE i : eltm dvd_y_x (x ^+ i) = y ^+ i.\n\n(*This lemma states that the `eltm` function maps the specified source element to the specified target element.*)\nLemma eltm_id : eltm dvd_y_x x = y. \n\n(*This lemma states that the `eltm` function acts as a group homomorphism on the cyclic subgroup generated by its source element.*)\nLemma eltmM : {in <[x]> &, {morph eltm dvd_y_x : x_i x_j / x_i * x_j}}.\n\nCanonical eltm_morphism := Morphism eltmM.\n\n(*This lemma states that the image of the cyclic group generated by the source element under the `eltm` homomorphism is precisely the cyclic group generated by the target element.*)\nLemma im_eltm : eltm dvd_y_x @* <[x]> = <[y]>.\n\n(*This lemma identifies the kernel of the `eltm` homomorphism as the cyclic subgroup generated by the source element raised to the power of the order of the target element.*)\nLemma ker_eltm : 'ker (eltm dvd_y_x) = <[x ^+ #[y]]>.\n\n(*This lemma provides the condition for injectivity of the `eltm` homomorphism, stating that it is injective if and only if the order of the source element divides the order of the target element.*)\nLemma injm_eltm : 'injm (eltm dvd_y_x) = (#[x] %| #[y]).\n\nEnd Eltm.\n\nSection CycleSubGroup.\n\nVariable gT : finGroupType.\n\n(*This lemma states that for any cyclic group, and for any natural number that divides the order of that group, there exists a unique subgroup of that order, which is itself a cyclic group generated by a specific power of the original generator.*)\nLemma cycle_sub_group (a : gT) m :\n m %| #[a] ->\n [set H : {group gT} | H \\subset <[a]> & #|H| == m]\n = [set <[a ^+ (#[a] %/ m)]>%G].\n\n(*This lemma states that any subgroup of a cyclic group is a characteristic subgroup of that cyclic group.*)\nLemma cycle_subgroup_char a (H : {group gT}) : H \\subset <[a]> -> H \\char <[a]>.\n\nEnd CycleSubGroup.\n\nSection MorphicImage.\n\nVariables aT rT : finGroupType.\nVariables (D : {group aT}) (f : {morphism D >-> rT}) (x : aT).\nHypothesis Dx : x \\in D.\n\n(*This lemma states that for any group homomorphism, the order of the image of an element divides the order of the original element.*)\nLemma morph_order : #[f x] %| #[x].\n\n(*This lemma states that if an element is a generator for a given group, then its image under a group homomorphism is a generator for the image of that group.*)\nLemma morph_generator A : generator A x -> generator (f @* A) (f x).\n\nEnd MorphicImage.\n\nSection CyclicProps.\n\nVariables gT : finGroupType.\nImplicit Types (aT rT : finGroupType) (G H K : {group gT}).\n\n(*This lemma states that any subgroup of a cyclic group is also a cyclic group.*)\nLemma cyclicS G H : H \\subset G -> cyclic G -> cyclic H.\n\n(*This lemma states that a group is cyclic if and only if its conjugate by any element is also cyclic.*)\nLemma cyclicJ G x : cyclic (G :^ x) = cyclic G.\n\n(*This lemma states that within a given cyclic group, two of its subgroups are equal if and only if their orders are equal.*)\nLemma eq_subG_cyclic G H K :\n cyclic G -> H \\subset G -> K \\subset G -> (H :==: K) = (#|H| == #|K|).\n\n(*This lemma states that for any two subgroups of a cyclic group, one is a subset of the other if and only if the order of the first divides the order of the second.*)\nLemma cardSg_cyclic G H K :\n cyclic G -> H \\subset G -> K \\subset G -> (#|H| %| #|K|) = (H \\subset K).\n\n(*This lemma asserts that for a cyclic group, any of its subgroups is necessarily a characteristic subgroup.*)\nLemma sub_cyclic_char G H : cyclic G -> (H \\char G) = (H \\subset G).\n\n(*This lemma states that the image of a cyclic group under a group homomorphism is also a cyclic group.*)\nLemma morphim_cyclic rT G H (f : {morphism G >-> rT}) :\n cyclic H -> cyclic (f @* H).\n\n(*This lemma describes the structure of a specific quotient group. It states that if an element normalizes a subgroup, the quotient of the cyclic group generated by that element with respect to the subgroup is itself a cyclic group, generated by the coset of the original element.*)\nLemma quotient_cycle x H : x \\in 'N(H) -> <[x]> / H = <[coset H x]>.\n\n(*This lemma states that the quotient of a cyclic group by any of its subgroups is also a cyclic group.*)\nLemma quotient_cyclic G H : cyclic G -> cyclic (G / H).\n\n(*This lemma states that if an element is a generator of a group and belongs to the normalizer of a subgroup, then its corresponding coset is a generator of the quotient group.*)\nLemma quotient_generator x G H :\n x \\in 'N(H) -> generator G x -> generator (G / H) (coset H x).\n\n(*This lemma states that any finite group whose order is a prime number is a cyclic group.*)\nLemma prime_cyclic G : prime #|G| -> cyclic G.\n\n(*This lemma states that if the order of a finite group divides a prime number, then the group is cyclic.*)\nLemma dvdn_prime_cyclic G p : prime p -> #|G| %| p -> cyclic G.\n\n(*This lemma states that any finite group with an order less than or equal to three is a cyclic group.*)\nLemma cyclic_small G : #|G| <= 3 -> cyclic G.\n\nEnd CyclicProps.\n\nSection IsoCyclic.\n\nVariables gT rT : finGroupType.\nImplicit Types (G H : {group gT}) (M : {group rT}).\n\n(*This lemma states that for an injective group morphism, the image of a subgroup is cyclic if and only if the original subgroup is cyclic.*)\nLemma injm_cyclic G H (f : {morphism G >-> rT}) :\n 'injm f -> H \\subset G -> cyclic (f @* H) = cyclic H.\n\n(*This lemma states that if two groups are isomorphic, then one group is cyclic if and only if the other group is also cyclic.*)\nLemma isog_cyclic G M : G \\isog M -> cyclic G = cyclic M.\n\n(*This lemma states that for a cyclic group, being isomorphic to another group is equivalent to the other group also being cyclic and having the same order.*)\nLemma isog_cyclic_card G M : cyclic G -> isog G M = cyclic M && (#|M| == #|G|).\n\n(*This lemma states that for an injective group morphism and a subgroup, the image of an element is a generator for the image of the subgroup if and only if the original element is a generator for the original subgroup.*)\nLemma injm_generator G H (f : {morphism G >-> rT}) x :\n 'injm f -> x \\in G -> H \\subset G ->\n generator (f @* H) (f x) = generator H x.\n\nEnd IsoCyclic.\n\nSection Metacyclic.\n\nVariable gT : finGroupType.\nImplicit Types (A : {set gT}) (G H : {group gT}).\n\n(*This definition describes a group as being metacyclic if it possesses a normal subgroup that is cyclic, and its corresponding quotient group is also cyclic.*)\nDefinition metacyclic A :=\n [exists H : {group gT}, [&& cyclic H, H <| A & cyclic (A / H)]].\n\n(*This lemma provides the logical equivalence for a group being metacyclic, stating that it holds if and only if there exists a normal subgroup that is cyclic and for which the corresponding quotient group is also cyclic.*)\nLemma metacyclicP A : \n reflect (exists H : {group gT}, [/\\ cyclic H, H <| A & cyclic (A / H)]) \n (metacyclic A).\n\n(*This lemma states that the trivial group is a metacyclic group.*)\nLemma metacyclic1 : metacyclic 1.\n\n(*This lemma states that any cyclic group is also metacyclic.*)\nLemma cyclic_metacyclic A : cyclic A -> metacyclic A.\n\n(*This lemma states that any subgroup of a metacyclic group is also metacyclic.*)\nLemma metacyclicS G H : H \\subset G -> metacyclic G -> metacyclic H.\n\nEnd Metacyclic.\n\nArguments metacyclic {gT} A%_g.\nArguments metacyclicP {gT A}.\n\nSection CyclicAutomorphism.\n\nVariable gT : finGroupType.\n\nSection CycleAutomorphism.\n\nVariable a : gT.\n\nSection CycleMorphism.\n\nVariable n : nat.\n\n(*This definition specifies a function that maps an element of a group to that element raised to the power of a given natural number.*)\nDefinition cyclem of gT := fun x : gT => x ^+ n.\n\n(*This lemma establishes that the function which raises an element to a fixed natural number power is a group endomorphism on the cyclic group generated by a given element.*)\nLemma cyclemM : {in <[a]> & , {morph cyclem a : x y / x * y}}.\n\nCanonical cyclem_morphism := Morphism cyclemM.\n\nEnd CycleMorphism.\n\nSection ZpUnitMorphism.\n\nVariable u : {unit 'Z_#[a]}.\n\n(*This lemma states that the endomorphism that raises elements of a cyclic group to a power is injective if the exponent is a unit in the ring of integers modulo the order of the group's generator.*)\nLemma injm_cyclem : 'injm (cyclem (val u) a).\n\n(*This lemma states that the image of the endomorphism that raises elements of a cyclic group to a power, where the exponent is a unit modulo the group's order, is the entire cyclic group itself, implying the mapping is surjective.*)\nLemma im_cyclem : cyclem (val u) a @* <[a]> = <[a]>.\n\n(*This definition constructs an automorphism on a cyclic group from the power-raising endomorphism, given a unit from the ring of integers modulo the order of the group's generator.*)\nDefinition Zp_unitm := aut injm_cyclem im_cyclem.\n\nEnd ZpUnitMorphism.\n\n(*This lemma establishes that the mapping from the group of units of integers modulo the order of a generator to the automorphism group of the generated cyclic group is a group morphism.*)\nLemma Zp_unitmM : {in units_Zp #[a] &, {morph Zp_unitm : u v / u * v}}.\n\nCanonical Zp_unit_morphism := Morphism Zp_unitmM.\n\n(*This lemma states that the group morphism from the group of units of integers modulo a generator's order to the automorphism group of the generated cyclic group is injective.*)\nLemma injm_Zp_unitm : 'injm Zp_unitm.\n\n(*This lemma states that an element of a cyclic group obtained by raising its generator to a certain power is also a generator of the group if and only if that power is coprime to the order of the group.*)\nLemma generator_coprime m : generator <[a]> (a ^+ m) = coprime #[a] m.\n\n(*This lemma states that the image of the group morphism from the group of units of integers modulo a generator's order covers the entire automorphism group of the generated cyclic group, indicating the morphism is surjective.*)\nLemma im_Zp_unitm : Zp_unitm @* units_Zp #[a] = Aut <[a]>.\n\n(*This lemma establishes that the group morphism from the group of units of integers modulo a generator's order to the automorphism group of the generated cyclic group is a group isomorphism.*)\nLemma Zp_unit_isom : isom (units_Zp #[a]) (Aut <[a]>) Zp_unitm.\n\n(*This lemma states that the group of units of integers modulo the order of a generator is isomorphic to the automorphism group of the generated cyclic group.*)\nLemma Zp_unit_isog : isog (units_Zp #[a]) (Aut <[a]>).\n\n(*This lemma states that the order of the automorphism group of a cyclic group is equal to the value of Euler's totient function applied to the order of the group.*)\nLemma card_Aut_cycle : #|Aut <[a]>| = totient #[a].\n\n(*This lemma states that the value of Euler's totient function applied to the order of a cyclic group is equal to the number of elements that can generate that group.*)\nLemma totient_gen : totient #[a] = #|[set x | generator <[a]> x]|.\n\n(*This lemma states that the automorphism group of any cyclic group is an abelian group.*)\nLemma Aut_cycle_abelian : abelian (Aut <[a]>).\n\nEnd CycleAutomorphism.\n\nVariable G : {group gT}.\n\n(*This lemma states that if a group is cyclic, then its automorphism group is an abelian group.*)\nLemma Aut_cyclic_abelian : cyclic G -> abelian (Aut G).\n\n(*This lemma states that for any cyclic group, the order of its automorphism group is equal to the value of Euler's totient function applied to the order of the group.*)\nLemma card_Aut_cyclic : cyclic G -> #|Aut G| = totient #|G|.\n\n(*This lemma states that for any finite group, its order equals the sum, over all positive integers d, of the product of the number of cyclic subgroups of order d and the value of Euler's totient function at d.*)\nLemma sum_ncycle_totient :\n \\sum_(d < #|G|.+1) #|[set <[x]> | x in G & #[x] == d]| * totient d = #|G|.\n\nEnd CyclicAutomorphism.\n\n(*This lemma states that for any positive natural number, the sum of the values of Euler's totient function over all its positive divisors is equal to the number itself.*)\nLemma sum_totient_dvd n : \\sum_(d < n.+1 | d %| n) totient d = n.\n\nSection FieldMulCyclic.\n\nImport GRing.Theory.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that a finite group is cyclic if any two elements of the same order generate the same cyclic subgroup.*)\nLemma order_inj_cyclic :\n {in G &, forall x y, #[x] = #[y] -> <[x]> = <[y]>} -> cyclic G.\n\n(*This lemma states that a finite abelian group is cyclic if there exists a function from the group to a unit ring that satisfies several properties. These properties are: the function maps the group identity to the ring's multiplicative identity; the function is a homomorphism from the group's operation to the ring's multiplication; and for any non-identity group element, the result of subtracting one from its image under the function is a unit in the ring.*)\nLemma div_ring_mul_group_cyclic (R : unitRingType) (f : gT -> R) :\n f 1 = 1%R -> {in G &, {morph f : u v / u * v >-> (u * v)%R}} ->\n {in G^#, forall x, f x - 1 \\in GRing.unit}%R ->\n abelian G -> cyclic G.\n\n(*This lemma states that a finite group is cyclic if there exists an injective homomorphism from it into the multiplicative group of a field.*)\nLemma field_mul_group_cyclic (F : fieldType) (f : gT -> F) :\n {in G &, {morph f : u v / u * v >-> (u * v)%R}} ->\n {in G, forall x, f x = 1%R <-> x = 1} ->\n cyclic G.\n\nEnd FieldMulCyclic.\n\n(*This lemma states that the multiplicative group of units of any finite field is a cyclic group.*)\nLemma field_unit_group_cyclic (F : finFieldType) (G : {group {unit F}}) :\n cyclic G.\n\n(*This lemma states that for any prime number, the multiplicative group of integers modulo that prime is cyclic.*)\nLemma units_Zp_cyclic p : prime p -> cyclic (units_Zp p).\n\nSection PrimitiveRoots.\n\nOpen Scope ring_scope.\nImport GRing.Theory.\n\n(*This lemma is a technical subproof which states that a sequence of field elements contains an n-th primitive root of unity, given a collection of detailed properties and constructions that collectively establish that the elements of the sequence form a group of n-th roots of unity of size n.*)\nLemma has_prim_root_subproof (F : fieldType) (n : nat) (rs : seq F)\n (n_gt0 : n > 0)\n (rsn1 : all n.-unity_root rs)\n (Urs : uniq rs)\n (sz_rs : size rs = n)\n (r := fun s => val (s : seq_sub rs))\n (rn1 : forall x : seq_sub rs, r x ^+ n = 1)\n (prim_r : forall z : F, z ^+ n = 1 -> z \\in rs)\n (r' := (fun s (e : s ^+ n = 1) => {| ssval := s; ssvalP := prim_r s e |})\n : forall s : F, s ^+ n = 1 -> seq_sub rs)\n (sG_1 := r' 1 (expr1n F n) : seq_sub rs)\n (sG_VP : forall s : seq_sub rs, r s ^+ n.-1 ^+ n = 1)\n (sG_MP : forall s s0 : seq_sub rs, (r s * r s0) ^+ n = 1)\n (sG_V := (fun s : seq_sub rs => r' (r s ^+ n.-1) (sG_VP s))\n : seq_sub rs -> seq_sub rs)\n (sG_M := (fun s s0 : seq_sub rs => r' (r s * r s0) (sG_MP s s0))\n : seq_sub rs -> seq_sub rs -> seq_sub rs)\n (sG_Ag : associative sG_M)\n (sG_1g : left_id sG_1 sG_M)\n (sG_Vg : left_inverse sG_1 sG_V sG_M) :\n has n.-primitive_root rs.\n\n(*This lemma states that if a sequence of elements from a field contains at least n distinct n-th roots of unity, where n is a positive number, then the given sequence must contain a primitive n-th root of unity.*)\nLemma has_prim_root (F : fieldType) (n : nat) (rs : seq F) :\n n > 0 -> all n.-unity_root rs -> uniq rs -> size rs >= n ->\n has n.-primitive_root rs.\n\nEnd PrimitiveRoots.\n\nSection AutPrime.\n\nVariable gT : finGroupType.\n\n(*This lemma states that if an element of a finite group has an order that is a prime number, then the automorphism group of the cyclic subgroup generated by that element is itself a cyclic group.*)\nLemma Aut_prime_cycle_cyclic (a : gT) : prime #[a] -> cyclic (Aut <[a]>).\n\n(*This lemma states that if the order of a finite group is a prime number, then its automorphism group is cyclic.*)\nLemma Aut_prime_cyclic (G : {group gT}) : prime #|G| -> cyclic (Aut G).", - "solvable.gseries": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import fintype bigop finset fingroup morphism.\nFrom mathcomp Require Import automorphism quotient action commutator center.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope group_rel_scope.\n\nImport GroupScope.\n\nSection GroupDefs.\n\nVariable gT : finGroupType.\nImplicit Types A B U V : {set gT}.\n\n(*This notation serves as a local alias for the type of groups within a given finite group structure.*)\nLocal Notation groupT := (group_of gT).\n\n(*This definition states that a group A is subnormal in a group B if A is a subgroup of B and there exists a finite chain of subgroups from A to B such that each group in the chain is normal in the subsequent one.*)\nDefinition subnormal A B :=\n (A \\subset B) && (iter #|B| (fun N => generated (class_support A N)) B == A).\n\n(*This definition establishes a relation between three groups A, B, and C, holding when B is a normal subgroup of C, and both B and C are normalized by A.*)\nDefinition invariant_factor A B C :=\n [&& A \\subset 'N(B), A \\subset 'N(C) & B <| C].\n\n(*This definition lifts a given binary relation between sets of group elements to a binary relation between groups, by restricting the domain of the original relation to sets that form a group.*)\nDefinition group_rel_of (r : rel {set gT}) := [rel H G : groupT | r H G].\n\n(*This definition describes a relation between three groups A, V, and U, which holds if V is a normal subgroup of U and the commutator subgroup of U and A is a subset of V.*)\nDefinition stable_factor A V U :=\n ([~: U, A] \\subset V) && (V <| U). \n\n(*This definition specifies a relation between three groups A, V, and U. It holds when the commutator of U and A is a subset of V, V is a subset of U, and U is a subset of A.*)\nDefinition central_factor A V U :=\n [&& [~: U, A] \\subset V, V \\subset U & U \\subset A].\n\n(*This definition asserts that a group A is a maximal subgroup of a group B if A is a proper subgroup of B and there is no other proper subgroup of B that strictly contains A.*)\nDefinition maximal A B := [max A of G | G \\proper B].\n\n(*This definition states that a group A has a maximal-or-equal relationship with a group B if A is either equal to B or is a maximal subgroup of B.*)\nDefinition maximal_eq A B := (A == B) || maximal A B.\n\n(*This definition asserts that a group A is a maximal subgroup of B among those normalized by U. This means A is a proper subgroup of B which is normalized by U, and there exists no other proper subgroup of B that is also normalized by U and strictly contains A.*)\nDefinition maxnormal A B U := [max A of G | G \\proper B & U \\subset 'N(G)].\n\n(*This definition asserts that a group A is a minimal subgroup among its non-trivial subgroups that are normalized by B. This means A is a non-trivial group normalized by B, and A does not contain any smaller non-trivial subgroup that is also normalized by B.*)\nDefinition minnormal A B := [min A of G | G :!=: 1 & B \\subset 'N(G)].\n\n(*This definition states that a group A is simple if it is a non-trivial group whose only normal subgroups are the trivial group and the group A itself.*)\nDefinition simple A := minnormal A A.\n\n(*This definition characterizes a pair of groups V and U as a chief factor of a group A. This holds if U is a normal subgroup of A, and V is a maximal subgroup of U that is also normal in A.*)\nDefinition chief_factor A V U := maxnormal V U A && (U <| A).\nEnd GroupDefs.\n\nArguments subnormal {gT} A%_g B%_g.\nArguments invariant_factor {gT} A%_g B%_g C%_g.\nArguments stable_factor {gT} A%_g V%_g U%_g.\nArguments central_factor {gT} A%_g V%_g U%_g.\nArguments maximal {gT} A%_g B%_g.\nArguments maximal_eq {gT} A%_g B%_g.\nArguments maxnormal {gT} A%_g B%_g U%_g.\nArguments minnormal {gT} A%_g B%_g.\nArguments simple {gT} A%_g.\nArguments chief_factor {gT} A%_g V%_g U%_g.\n\n(*This notation represents that a group H is a subnormal subgroup of a group G.*)\nNotation \"H <|<| G\" := (subnormal H G)\n (at level 70, no associativity) : group_scope.\n\n(*A notation for a binary relation between two subgroups, parameterized by a set of group elements `A`. The relation holds if the first subgroup is a normal subgroup of the second, and the set `A` normalizes both of them.*)\nNotation \"A .-invariant\" := (invariant_factor A)\n (at level 2, format \"A .-invariant\") : group_rel_scope.\n(*A notation for a binary relation between two subgroups, parameterized by a set of group elements `A`. The relation holds if the first subgroup is a normal subgroup of the second, and the subgroup generated by all commutators of elements from the second subgroup with elements from the set `A` is contained within the first subgroup.*)\nNotation \"A .-stable\" := (stable_factor A)\n (at level 2, format \"A .-stable\") : group_rel_scope.\n(*A notation for a binary relation between two subgroups, parameterized by a set of group elements `A`. The relation holds if the second subgroup is a subset of the set `A`, the first subgroup is a subset of the second, and the subgroup generated by all commutators of elements from the second subgroup with elements from `A` is contained within the first subgroup.*)\nNotation \"A .-central\" := (central_factor A)\n (at level 2, format \"A .-central\") : group_rel_scope.\n(*A notation for a binary relation between two subgroups, parameterized by a larger group `G`. The relation holds if the second subgroup is a normal subgroup of `G`, and the first subgroup is a maximal subgroup among all proper subgroups of the second that are also normalized by `G`. Such a pair of subgroups constitutes a chief factor of the group `G`.*)\nNotation \"G .-chief\" := (chief_factor G)\n (at level 2, format \"G .-chief\") : group_rel_scope.\n\nArguments group_rel_of {gT} r%_group_rel_scope _%_G _%_G : extra scopes.\n\n(*A notation that defines the type of all series of subgroups with respect to a given binary relation `r`. A series of this type is a finite sequence of subgroups where each subgroup is related to the subsequent one by the relation `r`.*)\nNotation \"r .-series\" := (path (rel_of_simpl (group_rel_of r)))\n (at level 2, format \"r .-series\") : group_scope.\n\nSection Subnormal.\n\nVariable gT : finGroupType.\nImplicit Types (A B C D : {set gT}) (G H K : {group gT}).\n\n(*This definition represents the intersection of two groups H and G, resulting in another group.*)\nLet setIgr H G := (G :&: H)%G.\n(*This lemma states that if a group G is a subgroup of another group H, then the intersection of G and H is equal to G.*)\nLet sub_setIgr G H : G \\subset H -> G = setIgr H G.\n\n(*This lemma states that intersecting a normal series with a fixed group preserves the normal series structure. If a sequence of groups forms a normal series that begins with group H, then the sequence formed by intersecting each group in the series with a group G will form a new normal series that begins with the intersection of H and G.*)\nLet path_setIgr H G s :\n normal.-series H s -> normal.-series (setIgr G H) (map (setIgr G) s).\n\n(*This lemma provides an equivalence for subnormality. It states that a group H is subnormal in a group G if and only if there exists a sequence of groups that forms a normal series starting with H and ending with G.*)\nLemma subnormalP H G :\n reflect (exists2 s, normal.-series H s & last H s = G) (H <|<| G).\n\n(*This lemma states that the subnormal relation is reflexive, meaning any group G is subnormal in itself.*)\nLemma subnormal_refl G : G <|<| G.\n\n(*This lemma states that the subnormal relation is transitive. If a group H is subnormal in a group K, and K is subnormal in a group G, then H is subnormal in G.*)\nLemma subnormal_trans K H G : H <|<| K -> K <|<| G -> H <|<| G.\n\n(*This lemma states that if a group H is a normal subgroup of a group G, then H is also a subnormal subgroup of G.*)\nLemma normal_subnormal H G : H <| G -> H <|<| G.\n\n(*This lemma states that the property of subnormality is preserved under intersection with a subgroup. If a group H is subnormal in a group G, and K is any subgroup of G, then the intersection of H and K is subnormal in K.*)\nLemma setI_subnormal G H K : K \\subset G -> H <|<| G -> H :&: K <|<| K.\n\n(*This lemma states that if a group H is subnormal in a group G, then H must be a subgroup of G.*)\nLemma subnormal_sub G H : H <|<| G -> H \\subset G.\n\n(*This lemma states that if a group H is subnormal in a group G, and another group A normalizes both H and G, then there exists a series of groups from H to G where each step is an A-invariant factor. This means for any two consecutive groups B and C in the series, B is normal in C, and both are normalized by A.*)\nLemma invariant_subnormal A G H :\n A \\subset 'N(G) -> A \\subset 'N(H) -> H <|<| G ->\n exists2 s, (A.-invariant).-series H s & last H s = G.\n\n(*This lemma describes a property of subnormal subgroups. It states that if a group H is subnormal in a group G, then either H is equal to G, or the normal closure of H within G is a proper subgroup of G.*)\nLemma subnormalEsupport G H :\n H <|<| G -> H :=: G \\/ <> \\proper G.\n\n(*This lemma provides a key property for subnormal subgroups in finite groups. It states that if a group H is subnormal in a group G, then either H is equal to G, or H is a proper subgroup of its normalizer within G.*)\nLemma subnormalEr G H : H <|<| G -> \n H :=: G \\/ (exists K : {group gT}, [/\\ H <|<| K, K <| G & K \\proper G]).\n\n(*This lemma states that if a subgroup is subnormal in a larger group, then it is either equal to the larger group or it is a proper normal subgroup of some intermediate group that is itself subnormal in the larger group.*)\nLemma subnormalEl G H : H <|<| G ->\n H :=: G \\/ (exists K : {group gT}, [/\\ H <| K, K <|<| G & H \\proper K]).\n\nEnd Subnormal.\n\nArguments subnormalP {gT H G}.\n\nSection MorphSubNormal.\n\nVariable gT : finGroupType.\nImplicit Type G H K : {group gT}.\n\n(*This lemma states that the image of a subnormal subgroup under a group morphism is a subnormal subgroup of the image of the larger group.*)\nLemma morphim_subnormal (rT : finGroupType) G (f : {morphism G >-> rT}) H K :\n H <|<| K -> f @* H <|<| f @* K.\n\n(*This lemma states that if a group is subnormal in another group, their respective quotient groups by a common normal subgroup preserve the subnormality relation.*)\nLemma quotient_subnormal H G K : G <|<| K -> G / H <|<| K / H.\n\nEnd MorphSubNormal.\n\nSection MaxProps.\n\nVariable gT : finGroupType.\nImplicit Types G H M : {group gT}.\n\n(*This lemma states that a subgroup is a maximal subgroup of a larger group if and only if it is a proper subgroup and there are no other subgroups strictly between the two.*)\nLemma maximal_eqP M G :\n reflect (M \\subset G /\\\n forall H, M \\subset H -> H \\subset G -> H :=: M \\/ H :=: G)\n (maximal_eq M G).\n\n(*This lemma states that for any proper subgroup of a given finite group, there exists a maximal subgroup of the given group which contains it.*)\nLemma maximal_exists H G :\n H \\subset G ->\n H :=: G \\/ (exists2 M : {group gT}, maximal M G & H \\subset M).\n\n(*This lemma states that if a subgroup is a maximal normal subgroup of a group, then its product with any subgroup not contained within it results in the entire group.*)\nLemma mulg_normal_maximal G M H :\n M <| G -> maximal M G -> H \\subset G -> ~~ (H \\subset M) -> (M * H = G)%g.\n\nEnd MaxProps.\n\nSection MinProps.\n\nVariable gT : finGroupType.\nImplicit Types G H M : {group gT}.\n\n(*This lemma states that any non-trivial normal subgroup of a group contains a minimal normal subgroup of that same group.*)\nLemma minnormal_exists G H : H :!=: 1 -> G \\subset 'N(H) ->\n {M : {group gT} | minnormal M G & M \\subset H}.\n\nEnd MinProps.\n\nSection MorphPreMax.\n\nVariables (gT rT : finGroupType) (D : {group gT}) (f : {morphism D >-> rT}).\nVariables (M G : {group rT}).\nHypotheses (dM : M \\subset f @* D) (dG : G \\subset f @* D).\n\n(*This lemma states that under a surjective group morphism, the preimage of a subgroup is a maximal subgroup of the preimage of a larger group if and only if the original subgroup is a maximal subgroup of the larger group.*)\nLemma morphpre_maximal : maximal (f @*^-1 M) (f @*^-1 G) = maximal M G.\n\n(*This lemma states that under a surjective group morphism, a subgroup's preimage is maximal in or equal to another subgroup's preimage if and only if the original subgroup is maximal in or equal to the other.*)\nLemma morphpre_maximal_eq : maximal_eq (f @*^-1 M) (f @*^-1 G) = maximal_eq M G.\n\nEnd MorphPreMax.\n\nSection InjmMax.\n\nVariables (gT rT : finGroupType) (D : {group gT}) (f : {morphism D >-> rT}).\nVariables M G L : {group gT}.\n\nHypothesis injf : 'injm f.\nHypotheses (dM : M \\subset D) (dG : G \\subset D) (dL : L \\subset D).\n\n(*This lemma states that for an injective group morphism, the image of a subgroup is maximal in the image of a larger group if and only if the original subgroup is maximal in the larger group.*)\nLemma injm_maximal : maximal (f @* M) (f @* G) = maximal M G.\n\n(*This lemma states that for an injective group morphism, the image of a subgroup is maximal in or equal to the image of a larger group if and only if the original subgroup is maximal in or equal to the larger group.*)\nLemma injm_maximal_eq : maximal_eq (f @* M) (f @* G) = maximal_eq M G.\n\n(*This lemma states that under an injective group morphism, a subgroup's image is a maximal normal subgroup in the image of another group, within the context of a third group's image, if and only if the same relationship holds for the original groups.*)\nLemma injm_maxnormal : maxnormal (f @* M) (f @* G) (f @* L) = maxnormal M G L.\n\n(*This lemma states that under an injective group morphism, the image of a subgroup is a minimal normal subgroup of the image of a larger group if and only if the original subgroup is a minimal normal subgroup of the larger group.*)\nLemma injm_minnormal : minnormal (f @* M) (f @* G) = minnormal M G.\n\nEnd InjmMax.\n\nSection QuoMax.\n\nVariables (gT : finGroupType) (K G H : {group gT}).\n\n(*This lemma states that a subgroup in a quotient group is maximal in another subgroup if and only if their preimages under the canonical quotient map are maximal relative to each other.*)\nLemma cosetpre_maximal (Q R : {group coset_of K}) :\n maximal (coset K @*^-1 Q) (coset K @*^-1 R) = maximal Q R.\n\n(*This lemma states that a subgroup in a quotient group is maximal in or equal to another subgroup if and only if their preimages under the canonical quotient map have the same relationship.*)\nLemma cosetpre_maximal_eq (Q R : {group coset_of K}) :\n maximal_eq (coset K @*^-1 Q) (coset K @*^-1 R) = maximal_eq Q R.\n\n(*This lemma states that, given two groups and a common normal subgroup, the quotient of the first group is a maximal subgroup of the quotient of the second group if and only if the first group is a maximal subgroup of the second group.*)\nLemma quotient_maximal :\n K <| G -> K <| H -> maximal (G / K) (H / K) = maximal G H.\n\n(*This lemma states that, given two groups and a common normal subgroup, the quotient of the first group is maximal in or equal to the quotient of the second group if and only if the first group is maximal in or equal to the second group.*)\nLemma quotient_maximal_eq :\n K <| G -> K <| H -> maximal_eq (G / K) (H / K) = maximal_eq G H.\n\n(*This lemma states that a group is a maximal subgroup of another group if and only if the conjugate of the first group by some element is a maximal subgroup of the conjugate of the second group by the same element.*)\nLemma maximalJ x : maximal (G :^ x) (H :^ x) = maximal G H.\n\n(*This lemma states that a group is a maximal subgroup of or equal to another group if and only if the conjugate of the first group by some element is a maximal subgroup of or equal to the conjugate of the second group by the same element.*)\nLemma maximal_eqJ x : maximal_eq (G :^ x) (H :^ x) = maximal_eq G H.\n\nEnd QuoMax.\n\nSection MaxNormalProps.\n\nVariables (gT : finGroupType).\nImplicit Types (A B C : {set gT}) (G H K L M : {group gT}).\n\n(*This lemma states that if a group is a maximal normal subgroup of another group, then it is a normal subgroup of that group.*)\nLemma maxnormal_normal A B : maxnormal A B B -> A <| B.\n\n(*This lemma states that a group that is defined as a maximal normal subgroup of another group is always a proper subgroup of that group.*)\nLemma maxnormal_proper A B C : maxnormal A B C -> A \\proper B.\n\n(*This lemma states that a group that is defined as a maximal normal subgroup of another group is a subgroup of that group.*)\nLemma maxnormal_sub A B C : maxnormal A B C -> A \\subset B.\n\n(*This lemma states that any non-trivial finite group possesses at least one maximal normal subgroup.*)\nLemma ex_maxnormal_ntrivg G : G :!=: 1-> {N : {group gT} | maxnormal N G G}.\n\n(*This lemma states that the product of two distinct maximal normal subgroups of a group is equal to the group itself.*)\nLemma maxnormalM G H K :\n maxnormal H G G -> maxnormal K G G -> H :<>: K -> H * K = G.\n\n(*This lemma establishes a correspondence, stating that under certain normality conditions, if one group is a maximal normal subgroup of another within a third group, then their respective quotients form a minimal normal subgroup relationship.*)\nLemma maxnormal_minnormal G L M :\n G \\subset 'N(M) -> L \\subset 'N(G) -> maxnormal M G L ->\n minnormal (G / M) (L / M).\n\n(*This lemma establishes a correspondence, stating that under certain normality conditions, if a quotient group is a minimal normal subgroup of another, then the original groups from which they were formed exhibit a maximal normal subgroup relationship.*)\nLemma minnormal_maxnormal G L M :\n M <| G -> L \\subset 'N(M) -> minnormal (G / M) (L / M) -> maxnormal M G L.\n\nEnd MaxNormalProps.\n\nSection Simple.\n\nImplicit Types gT rT : finGroupType.\n\n(*This lemma states that a group is simple if and only if it is non-trivial and its only normal subgroups are the trivial group and the group itself.*)\nLemma simpleP gT (G : {group gT}) :\n reflect (G :!=: 1 /\\ forall H : {group gT}, H <| G -> H :=: 1 \\/ H :=: G)\n (simple G).\n\n(*This lemma states that for a group and its normal subgroup, the corresponding quotient group is simple if and only if the normal subgroup is a maximal normal subgroup of the original group.*)\nLemma quotient_simple gT (G H : {group gT}) :\n H <| G -> simple (G / H) = maxnormal H G G.\n\n(*This lemma states that if two groups are isomorphic, then one is simple if and only if the other is also simple.*)\nLemma isog_simple gT rT (G : {group gT}) (M : {group rT}) :\n G \\isog M -> simple G = simple M.\n\n(*This lemma states that a group is simple if and only if its trivial subgroup is a maximal normal subgroup.*)\nLemma simple_maxnormal gT (G : {group gT}) : simple G = maxnormal 1 G G.\n\nEnd Simple.\n\nSection Chiefs.\n\nVariable gT : finGroupType.\nImplicit Types G H U V : {group gT}.\n\n(*This lemma states that if a pair of groups, V and U, forms a chief factor within a group G, then the quotient group of U by V is a minimal normal subgroup of the quotient group of G by V.*)\nLemma chief_factor_minnormal G V U :\n chief_factor G V U -> minnormal (U / V) (G / V).\n\n(*This lemma states that, for groups G, U, and V, where G normalizes V and V is a normal subgroup of U, the property that G acts irreducibly by conjugation on the quotient group U by V is equivalent to the property that the quotient group U by V is a minimal normal subgroup of the quotient group G by V.*)\nLemma acts_irrQ G U V :\n G \\subset 'N(V) -> V <| U ->\n acts_irreducibly G (U / V) 'Q = minnormal (U / V) (G / V).\n\n(*This lemma asserts the existence of a chief series for a group G that terminates at any given normal subgroup H of G.*)\nLemma chief_series_exists H G :\n H <| G -> {s | (G.-chief).-series 1%G s & last 1%G s = H}.\n\nEnd Chiefs.\n\nSection Central.\n\nVariables (gT : finGroupType) (G : {group gT}).\nImplicit Types H K : {group gT}.\n\n(*This lemma states that if a pair of groups, H and K, forms a central factor of a group G, then the quotient group of K by H is a subgroup of the center of the quotient group of G by H.*)\nLemma central_factor_central H K :\n central_factor G H K -> (K / H) \\subset 'Z(G / H).\n\n(*This lemma states that if a pair of groups forms a central factor of another group, then their quotient group is a subgroup of the center of the corresponding quotient of the larger group.*)\nLemma central_central_factor H K :\n (K / H) \\subset 'Z(G / H) -> H <| K -> H <| G -> central_factor G H K.", - "solvable.abelian": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import choice div fintype finfun bigop finset prime.\nFrom mathcomp Require Import binomial fingroup morphism perm automorphism.\nFrom mathcomp Require Import action quotient gfunctor gproduct ssralg countalg.\nFrom mathcomp Require Import finalg zmodp cyclic pgroup gseries nilpotent sylow.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection AbelianDefs.\n\nVariable gT : finGroupType.\nImplicit Types (x : gT) (A B : {set gT}) (pi : nat_pred) (p n : nat).\n\n(*This definition constructs the set of all elements in a finite group such that raising an element to the power of a given natural number n results in the identity element.*)\nDefinition Ldiv n := [set x : gT | x ^+ n == 1].\n\n(*This definition computes the exponent of a set of elements from a finite group, which is the least common multiple of the orders of all elements in the set.*)\nDefinition exponent A := \\big[lcmn/1%N]_(x in A) #[x].\n\n(*This definition returns a boolean value indicating whether a given set of elements from a finite group forms an elementary abelian p-group for a given natural number p. This holds if the set forms an abelian p-group and its exponent divides p.*)\nDefinition abelem p A := [&& p.-group A, abelian A & exponent A %| p].\n\n(*This definition returns a boolean value indicating whether a given set of elements from a finite group is an elementary abelian p-group, where p is the largest prime divisor of the order of the set.*)\nDefinition is_abelem A := abelem (pdiv #|A|) A.\n\n(*This definition constructs the set of all elementary abelian p-subgroups of a finite group that are contained within a given subset A, where p is a given natural number.*)\nDefinition pElem p A := [set E : {group gT} | E \\subset A & abelem p E].\n\n(*This definition constructs the set of all elementary abelian p-subgroups contained in a given subset A whose order is equal to a given natural number p raised to the power of a second natural number n.*)\nDefinition pnElem p n A := [set E in pElem p A | logn p #|E| == n].\n\n(*This definition constructs the set of all elementary abelian subgroups contained in a given subset A that have an order of p to the power of n for some prime number p, where n is a given natural number.*)\nDefinition nElem n A := \\bigcup_(0 <= p < #|A|.+1) pnElem p n A.\n\n(*This definition constructs the set of all elementary abelian p-subgroups contained within a given subset A that are maximal with respect to set inclusion, where p is a given natural number.*)\nDefinition pmaxElem p A := [set E | [max E | E \\in pElem p A]].\n\n(*This definition computes the p-rank of a subset A of a finite group for a given natural number p. This rank is the maximum integer k such that an elementary abelian p-subgroup of order p to the power of k is contained in A.*)\nDefinition p_rank p A := \\max_(E in pElem p A) logn p #|E|.\n\n(*This definition computes the rank of a subset A of a finite group, which is defined as the maximum p-rank over all possible prime numbers p.*)\nDefinition rank A := \\max_(0 <= p < #|A|.+1) p_rank p A.\n\n(*This definition computes the generator rank of a group A, which is the minimum number of elements required to generate A.*)\nDefinition gen_rank A := #|[arg min_(B < A | <> == A) #|B|]|.\n\nEnd AbelianDefs.\n\nArguments exponent {gT} A%_g.\nArguments abelem {gT} p%_N A%_g.\nArguments is_abelem {gT} A%_g.\nArguments pElem {gT} p%_N A%_g.\nArguments pnElem {gT} p%_N n%_N A%_g.\nArguments nElem {gT} n%_N A%_g.\nArguments pmaxElem {gT} p%_N A%_g.\nArguments p_rank {gT} p%_N A%_g.\nArguments rank {gT} A%_g.\nArguments gen_rank {gT} A%_g.\n\n(*This notation represents the set of all elements in the ambient finite group that equal the identity when raised to the power of a given natural number n.*)\nNotation \"''Ldiv_' n ()\" := (Ldiv _ n)\n (n at level 2, format \"''Ldiv_' n ()\") : group_scope.\n\n(*This notation represents the set of elements within a given group G that equal the identity when raised to the power of a given natural number n.*)\nNotation \"''Ldiv_' n ( G )\" := (G :&: 'Ldiv_n())\n (format \"''Ldiv_' n ( G )\") : group_scope.\n\nPrenex Implicits exponent.\n\n(*This notation represents a predicate, parameterized by a natural number p. When applied to a set of finite group elements, the predicate holds if the set forms an abelian p-group and its exponent divides p. The exponent of the set is the least common multiple of the orders of all its elements.*)\nNotation \"p .-abelem\" := (abelem p)\n (at level 2, format \"p .-abelem\") : group_scope.\n\n(*This notation represents the set of all elementary abelian p-subgroups that are contained within a given group G, for a given natural number p.*)\nNotation \"''E_' p ( G )\" := (pElem p G)\n (at level 8, p at level 2, format \"''E_' p ( G )\") : group_scope.\n\n(*This notation represents the set of all elementary abelian p-subgroups contained in a given group G whose order is equal to p raised to the power of n, for given natural numbers p and n.*)\nNotation \"''E_' p ^ n ( G )\" := (pnElem p n G)\n (n at level 2, format \"''E_' p ^ n ( G )\") : group_scope.\n\n(*This notation represents the set of all elementary abelian subgroups contained in a given group G whose order is p to the power of n for some prime number p, where n is a given natural number.*)\nNotation \"''E' ^ n ( G )\" := (nElem n G)\n (at level 8, n at level 2, format \"''E' ^ n ( G )\") : group_scope.\n\n(*This notation represents the set of all maximal elementary abelian p-subgroups that are contained within a given group G, for a given natural number p.*)\nNotation \"''E*_' p ( G )\" := (pmaxElem p G)\n (at level 8, p at level 2, format \"''E*_' p ( G )\") : group_scope.\n\n(*This notation represents the generator rank of a group A, which is the minimum number of elements required to generate A.*)\nNotation \"''m' ( A )\" := (gen_rank A)\n (at level 8, format \"''m' ( A )\") : group_scope.\n\n(*This notation represents the rank of a group A, defined as the maximum p-rank over all possible prime numbers p.*)\nNotation \"''r' ( A )\" := (rank A)\n (at level 8, format \"''r' ( A )\") : group_scope.\n\n(*This notation represents the p-rank of a group A for a given natural number p. The p-rank is the largest integer k for which A contains an elementary abelian subgroup of order p to the power of k.*)\nNotation \"''r_' p ( A )\" := (p_rank p A)\n (at level 8, p at level 2, format \"''r_' p ( A )\") : group_scope.\n\nSection Functors.\n\nVariables (n : nat) (gT : finGroupType) (A : {set gT}).\n\n(*This definition constructs the Ohm subgroup for a given set of elements A and a natural number n. This subgroup is generated by all elements x from A for which there exists some prime number p such that x raised to the power of p to the power of n is equal to the identity element.*)\nDefinition Ohm := <<[set x in A | x ^+ (pdiv #[x] ^ n) == 1]>>.\n\n(*This definition constructs the Mho subgroup for a given set of elements A and a natural number n. It is the subgroup generated by the set of elements of the form x raised to the power of p to the power of n, where x is any element from A whose order is a power of some prime p.*)\nDefinition Mho := <<[set x ^+ (pdiv #[x] ^ n) | x in A & (pdiv #[x]).-elt x]>>.\n\nCanonical Ohm_group : {group gT} := Eval hnf in [group of Ohm].\nCanonical Mho_group : {group gT} := Eval hnf in [group of Mho].\n\n(*This lemma states that for any non-identity element of a finite group whose order is a power of a prime number p, the largest prime divisor of that element's order is equal to p.*)\nLemma pdiv_p_elt (p : nat) (x : gT) : p.-elt x -> x != 1 -> pdiv #[x] = p.\n\n(*This lemma states that for any element of a finite group and a natural number n, the assertion that the element raised to the power of d to the power of n is the identity, where d is the largest prime divisor of the element's order, is logically equivalent to the existence of some prime number p for which the element raised to the power of p to the power of n is the identity.*)\nLemma OhmPredP (x : gT) :\n reflect (exists2 p, prime p & x ^+ (p ^ n) = 1) (x ^+ (pdiv #[x] ^ n) == 1).\n\n(*This lemma states that for a given prime number p and a natural number n, if an element x belongs to a set A and has an order that is a power of p, then the element x raised to the power of p to the power of n is a member of the corresponding Mho subgroup of A.*)\nLemma Mho_p_elt (p : nat) x : x \\in A -> p.-elt x -> x ^+ (p ^ n) \\in Mho.\n\nEnd Functors.\n\nArguments Ohm n%_N {gT} A%_g.\nArguments Ohm_group n%_N {gT} A%_g.\nArguments Mho n%_N {gT} A%_g.\nArguments Mho_group n%_N {gT} A%_g.\nArguments OhmPredP {n gT x}.\n\n(*This notation represents the Ohm subgroup for a given group G and a natural number n. This subgroup is generated by all elements x from G for which there exists a prime number p such that x raised to the power of p to the power of n is the identity.*)\nNotation \"''Ohm_' n ( G )\" := (Ohm n G)\n (at level 8, n at level 2, format \"''Ohm_' n ( G )\") : group_scope.\n(*A notation for the subgroup of a given group containing all elements that result in the identity element when raised to a specified natural number power.*)\nNotation \"''Ohm_' n ( G )\" := (Ohm_group n G) : Group_scope.\n\n(*A notation for the subgroup of a given group that is generated by the collection of elements obtained by raising every element of the original group to a specified natural number power.*)\nNotation \"''Mho^' n ( G )\" := (Mho n G)\n (at level 8, n at level 2, format \"''Mho^' n ( G )\") : group_scope.\n(*A notation for the n-th agemo subgroup of a group, which is the subgroup generated by the n-th powers of all elements in that group.*)\nNotation \"''Mho^' n ( G )\" := (Mho_group n G) : Group_scope.\n\nSection ExponentAbelem.\n\nVariable gT : finGroupType.\nImplicit Types (p n : nat) (pi : nat_pred) (x : gT) (A B C : {set gT}).\nImplicit Types E G H K P X Y : {group gT}.\n\n(*This lemma provides a boolean reflection property, stating that an element belongs to the set of elements in a given set whose n-th power is the identity, if and only if the element is in the original set and its n-th power is indeed the identity element.*)\nLemma LdivP A n x : reflect (x \\in A /\\ x ^+ n = 1) (x \\in 'Ldiv_n(A)).\n\n(*This lemma states that for any element in a given set of group elements, the order of that element divides the exponent of the set.*)\nLemma dvdn_exponent x A : x \\in A -> #[x] %| exponent A.\n\n(*This lemma states that any element of a given set of group elements, when raised to the power of the exponent of that set, results in the identity element.*)\nLemma expg_exponent x A : x \\in A -> x ^+ exponent A = 1.\n\n(*This lemma states that if a set of group elements is a subset of another, then the exponent of the first set divides the exponent of the second set.*)\nLemma exponentS A B : A \\subset B -> exponent A %| exponent B.\n\n(*This lemma provides a boolean reflection property, stating that the exponent of a set of group elements divides a given natural number if and only if every element in the set, when raised to the power of that natural number, results in the identity element.*)\nLemma exponentP A n :\n reflect (forall x, x \\in A -> x ^+ n = 1) (exponent A %| n).\n\nArguments exponentP {A n}.\n\n(*This lemma establishes an equivalence for a group being trivial. It states that a group is the trivial group containing only the identity element if and only if its exponent divides one.*)\nLemma trivg_exponent G : (G :==: 1) = (exponent G %| 1).\n\n(*This lemma states that the exponent of the singleton set containing only the identity element of a group is equal to one.*)\nLemma exponent1 : exponent [1 gT] = 1%N.\n\n(*This lemma states that the exponent of a finite group always divides the order of that group.*)\nLemma exponent_dvdn G : exponent G %| #|G|.\n\n(*This lemma states that the exponent of any group is a positive natural number, specifically greater than zero.*)\nLemma exponent_gt0 G : 0 < exponent G.\n\nHint Resolve exponent_gt0 : core.\n\n(*This lemma connects the prime factors of a group's exponent to the group's structure. It states that for a given set of prime numbers, all prime factors of the group's exponent belong to that set if and only if the group is a pi-group, meaning the order of every element has prime factors only from that set.*)\nLemma pnat_exponent pi G : pi.-nat (exponent G) = pi.-group G.\n\n(*This lemma states that the exponent of a set of group elements is invariant under conjugation; that is, the exponent of a set is equal to the exponent of its conjugate by any group element.*)\nLemma exponentJ A x : exponent (A :^ x) = exponent A.\n\n(*This lemma states that for any nilpotent finite group, there exists an element within the group whose order is equal to the exponent of the group.*)\nLemma exponent_witness G : nilpotent G -> {x | x \\in G & exponent G = #[x]}.\n\n(*This lemma states that the exponent of a cyclic subgroup generated by a given element is equal to the order of that element.*)\nLemma exponent_cycle x : exponent <[x]> = #[x].\n\n(*This lemma states that if a group is cyclic, then its exponent is equal to its order.*)\nLemma exponent_cyclic X : cyclic X -> exponent X = #|X|.\n\n(*This lemma states that the set of prime numbers that divide the exponent of a finite group is identical to the set of prime numbers that divide the order of that group.*)\nLemma primes_exponent G : primes (exponent G) = primes (#|G|).\n\n(*This lemma states that the set of prime divisors of the exponent of a group is equal to the set of prime divisors of the order of the group.*)\nLemma pi_of_exponent G : \\pi(exponent G) = \\pi(G).\n\n(*This lemma relates the exponents of a group and a subgroup with respect to a set of primes. It states that if a subgroup's order is divisible by the pi-part of the supergroup's order, where pi is a set of primes, then the pi-part of the subgroup's exponent is equal to the pi-part of the supergroup's exponent.*)\nLemma partn_exponentS pi H G :\n H \\subset G -> #|G|`_pi %| #|H| -> (exponent H)`_pi = (exponent G)`_pi.\n\n(*This lemma states that for any pi-Hall subgroup of a group, where pi is a set of primes, the exponent of the Hall subgroup is equal to the pi-part of the exponent of the larger group.*)\nLemma exponent_Hall pi G H : pi.-Hall(G) H -> exponent H = (exponent G)`_pi.\n\n(*This lemma states that if a group is a Z-group, meaning all of its Sylow subgroups are cyclic, then the exponent of the group is equal to its order.*)\nLemma exponent_Zgroup G : Zgroup G -> exponent G = #|G|.\n\n(*This lemma states that if a group is the central product of two of its subgroups, then the exponent of the group is the least common multiple of the exponents of those two subgroups.*)\nLemma cprod_exponent A B G :\n A \\* B = G -> lcmn (exponent A) (exponent B) = (exponent G).\n\n(*This lemma states that if a group is the internal direct product of two of its subgroups, then the exponent of the group is the least common multiple of the exponents of those two subgroups.*)\nLemma dprod_exponent A B G :\n A \\x B = G -> lcmn (exponent A) (exponent B) = (exponent G).\n\n(*This lemma establishes an equivalence stating that a set of group elements is a subset of the group's n-th power kernel if and only if the exponent of the set divides the natural number n.*)\nLemma sub_LdivT A n : (A \\subset 'Ldiv_n()) = (exponent A %| n).\n\n(*This lemma states that the set of all elements in a group whose n-th power is the identity is invariant under conjugation by any element of the group.*)\nLemma LdivT_J n x : 'Ldiv_n() :^ x = 'Ldiv_n().\n\n(*This lemma states that the operation of taking the n-th power kernel of a set of group elements commutes with conjugation. Specifically, the n-th power kernel of a conjugated set is equal to the conjugate of the n-th power kernel of the original set.*)\nLemma LdivJ n A x : 'Ldiv_n(A :^ x) = 'Ldiv_n(A) :^ x.\n\n(*This lemma states that a set of group elements is a subset of its own n-th power kernel if and only if the exponent of the set divides the natural number n.*)\nLemma sub_Ldiv A n : (A \\subset 'Ldiv_n(A)) = (exponent A %| n).\n\n(*This lemma states that for any abelian group, the set of all elements in that group whose n-th power is the identity forms a subgroup.*)\nLemma group_Ldiv G n : abelian G -> group_set 'Ldiv_n(G).\n\n(*This lemma states that if the subgroup generated by a set of group elements is abelian, then the exponent of the generated subgroup is equal to the exponent of the original generating set.*)\nLemma abelian_exponent_gen A : abelian A -> exponent <> = exponent A.\n\n(*This lemma states that any abelian elementary p-group is also a p-group, as every element having order p implies every element has an order that is a power of the prime p.*)\nLemma abelem_pgroup p A : p.-abelem A -> p.-group A.\n\n(*This lemma states that any abelian elementary p-group is, by definition, an abelian group.*)\nLemma abelem_abelian p A : p.-abelem A -> abelian A.\n\n(*This lemma states that for any prime number, the trivial group containing only the identity element is an elementary abelian p-group.*)\nLemma abelem1 p : p.-abelem [1 gT].\n\n(*This lemma states that for a prime number, a group is an elementary abelian p-group if and only if the group is abelian and its exponent divides the prime number.*)\nLemma abelemE p G : prime p -> p.-abelem G = abelian G && (exponent G %| p).\n\n(*This lemma states that for a prime number, a group is an elementary abelian p-group if and only if the group is abelian and every element raised to the power of that prime number equals the identity element.*)\nLemma abelemP p G :\n prime p ->\n reflect (abelian G /\\ forall x, x \\in G -> x ^+ p = 1) (p.-abelem G).\n\n(*This lemma states that in an elementary abelian p-group, any element that is not the identity has an order equal to the prime number p.*)\nLemma abelem_order_p p G x : p.-abelem G -> x \\in G -> x != 1 -> #[x] = p.\n\n(*This lemma states that if a group is cyclic, non-trivial, and an elementary abelian p-group, then its order is equal to the prime number p.*)\nLemma cyclic_abelem_prime p X : p.-abelem X -> cyclic X -> X :!=: 1 -> #|X| = p.\n\n(*This lemma states that if an element is a p-element or if p is a prime number, then the cyclic group generated by that element is an elementary abelian p-group if and only if the order of the element divides p.*)\nLemma cycle_abelem p x : p.-elt x || prime p -> p.-abelem <[x]> = (#[x] %| p).\n\n(*This lemma states that if the exponent of a group divides two, then that group is an elementary abelian 2-group.*)\nLemma exponent2_abelem G : exponent G %| 2 -> 2.-abelem G.\n\n(*This lemma states that if a group has an order equal to a prime number, then the group is an elementary abelian p-group for that prime.*)\nLemma prime_abelem p G : prime p -> #|G| = p -> p.-abelem G.\n\n(*This lemma states that an elementary abelian p-group is cyclic if and only if the base-p logarithm of its order is less than or equal to one.*)\nLemma abelem_cyclic p G : p.-abelem G -> cyclic G = (logn p #|G| <= 1).\n\n(*This lemma states that if a group is an elementary abelian p-group, then any of its subgroups is also an elementary abelian p-group.*)\nLemma abelemS p H G : H \\subset G -> p.-abelem G -> p.-abelem H.\n\n(*This lemma states that a group is an elementary abelian p-group if and only if any of its conjugate subgroups is also an elementary abelian p-group.*)\nLemma abelemJ p G x : p.-abelem (G :^ x) = p.-abelem G.\n\n(*This lemma states that the central product of two groups is an elementary abelian p-group if and only if both factor groups are elementary abelian p-groups.*)\nLemma cprod_abelem p A B G :\n A \\* B = G -> p.-abelem G = p.-abelem A && p.-abelem B.\n\n(*This lemma states that the direct product of two groups is an elementary abelian p-group if and only if both factor groups are elementary abelian p-groups.*)\nLemma dprod_abelem p A B G :\n A \\x B = G -> p.-abelem G = p.-abelem A && p.-abelem B.\n\n(*This lemma states that for a p-group, being an elementary abelian group for some prime is equivalent to being an elementary abelian p-group for that specific prime p.*)\nLemma is_abelem_pgroup p G : p.-group G -> is_abelem G = p.-abelem G.\n\n(*This lemma provides a reflection property, stating that a group is an elementary abelian group if and only if there exists a prime number for which it is an elementary abelian p-group.*)\nLemma is_abelemP G : reflect (exists2 p, prime p & p.-abelem G) (is_abelem G).\n\n(*This lemma provides a reflection property, stating that a subgroup belongs to the set of elementary abelian p-subgroups of a given group if and only if it is a subgroup and is itself an elementary abelian p-group.*)\nLemma pElemP p A E : reflect (E \\subset A /\\ p.-abelem E) (E \\in 'E_p(A)).\n\nArguments pElemP {p A E}.\n\n(*This lemma states that if a group is a subgroup of another group, then the set of its elementary abelian p-subgroups is a subset of the set of elementary abelian p-subgroups of the larger group.*)\nLemma pElemS p A B : A \\subset B -> 'E_p(A) \\subset 'E_p(B).\n\n(*This lemma states that the set of elementary abelian p-subgroups of the intersection of two groups is equal to the intersection of the set of elementary abelian p-subgroups of the first group with the set of all subgroups of the second group.*)\nLemma pElemI p A B : 'E_p(A :&: B) = 'E_p(A) :&: subgroups B.\n\n(*This lemma states that a subgroup's membership in the set of elementary abelian p-subgroups is preserved under conjugation; that is, a subgroup belongs to this set for a given group if and only if its conjugate belongs to the corresponding set for the conjugate of that group.*)\nLemma pElemJ x p A E : ((E :^ x)%G \\in 'E_p(A :^ x)) = (E \\in 'E_p(A)).\n\n(*This lemma provides a reflection property, stating that a subgroup belongs to the set of elementary abelian p-subgroups of rank n of a group if and only if it is a subgroup, is an elementary abelian p-group, and the base-p logarithm of its order equals n.*)\nLemma pnElemP p n A E :\n reflect [/\\ E \\subset A, p.-abelem E & logn p #|E| = n] (E \\in 'E_p^n(A)).\n\nArguments pnElemP {p n A E}.\n\n(*This lemma states that if a subgroup belongs to the set of elementary abelian p-subgroups of rank n of a given group, then it is a subgroup, is an elementary abelian p-group, and its order is equal to the prime p raised to the power of n.*)\nLemma pnElemPcard p n A E :\n E \\in 'E_p^n(A) -> [/\\ E \\subset A, p.-abelem E & #|E| = p ^ n]%N.\n\n(*This lemma states that if a subgroup is an elementary abelian p-subgroup of rank n of a given group, then its order is equal to the prime p raised to the power of n.*)\nLemma card_pnElem p n A E : E \\in 'E_p^n(A) -> #|E| = (p ^ n)%N.\n\n(*This lemma states that the set of elementary abelian p-subgroups of rank zero of any group is the singleton set containing only the trivial subgroup.*)\nLemma pnElem0 p G : 'E_p^0(G) = [set 1%G].\n\n(*This lemma states that if a group contains an elementary abelian p-subgroup of a positive rank, then the number p must be a prime number.*)\nLemma pnElem_prime p n A E : E \\in 'E_p^n.+1(A) -> prime p.\n\n(*This lemma states that for a prime number, the set of elementary abelian p-subgroups of rank n of a group is equal to the set of all its elementary abelian p-subgroups whose order is equal to the prime raised to the power of n.*)\nLemma pnElemE p n A :\n prime p -> 'E_p^n(A) = [set E in 'E_p(A) | #|E| == (p ^ n)%N].\n\n(*This lemma states that if a group is a subgroup of another, then the set of its elementary abelian p-subgroups of a given rank is a subset of the corresponding set for the larger group.*)\nLemma pnElemS p n A B : A \\subset B -> 'E_p^n(A) \\subset 'E_p^n(B).\n\n(*This lemma states that the set of elementary abelian p-subgroups of a given rank of the intersection of two groups is equal to the intersection of the set of such subgroups for the first group with the set of all subgroups of the second group.*)\nLemma pnElemI p n A B : 'E_p^n(A :&: B) = 'E_p^n(A) :&: subgroups B.\n\n(*This lemma states that a subgroup's membership in the set of elementary abelian p-subgroups of a given rank is preserved under conjugation; that is, a subgroup belongs to this set if and only if its conjugate belongs to the corresponding set for the conjugate of the parent group.*)\nLemma pnElemJ x p n A E : ((E :^ x)%G \\in 'E_p^n(A :^ x)) = (E \\in 'E_p^n(A)).\n\n(*This lemma states that for any elementary abelian p-group, and for any natural number less than or equal to the base-p logarithm of the group's order, there exists an elementary abelian p-subgroup of that rank within the group.*)\nLemma abelem_pnElem p n G :\n p.-abelem G -> n <= logn p #|G| -> exists E, E \\in 'E_p^n(G).\n\n(*This lemma states that if a subgroup is an elementary abelian p-subgroup of rank one, its order is equal to the prime number p.*)\nLemma card_p1Elem p A X : X \\in 'E_p^1(A) -> #|X| = p.\n\n(*This lemma states that for a given prime number, the set of elementary abelian p-subgroups of rank one within a group is equivalent to the set of all subgroups of that group whose order is exactly that prime number.*)\nLemma p1ElemE p A : prime p -> 'E_p^1(A) = [set X in subgroups A | #|X| == p].\n\n(*This lemma states that any two distinct elementary abelian p-subgroups of rank one have a trivial intersection, meaning their intersection is the trivial subgroup.*)\nLemma TIp1ElemP p A X Y :\n X \\in 'E_p^1(A) -> Y \\in 'E_p^1(A) -> reflect (X :&: Y = 1) (X :!=: Y).\n\n(*This lemma states that the number of elementary abelian p-subgroups of rank one contained within an elementary abelian p-subgroup of rank n is equal to the sum of powers of the prime p from zero up to, but not including, n.*)\nLemma card_p1Elem_pnElem p n A E :\n E \\in 'E_p^n(A) -> #|'E_p^1(E)| = (\\sum_(i < n) p ^ i)%N.\n\n(*This lemma provides the specific count that an elementary abelian p-subgroup of rank two contains a number of rank-one elementary abelian p-subgroups equal to the prime number plus one.*)\nLemma card_p1Elem_p2Elem p A E : E \\in 'E_p^2(A) -> #|'E_p^1(E)| = p.+1.\n\n(*This lemma states that for an elementary abelian p-subgroup of rank two, the internal direct product of any two of its distinct rank-one elementary abelian p-subgroups is equal to the rank-two subgroup itself.*)\nLemma p2Elem_dprodP p A E X Y :\n E \\in 'E_p^2(A) -> X \\in 'E_p^1(E) -> Y \\in 'E_p^1(E) ->\n reflect (X \\x Y = E) (X :!=: Y).\n\n(*This lemma states that a subgroup is an elementary abelian subgroup of rank n if and only if there exists some prime number for which it is an elementary abelian p-subgroup of that same rank n.*)\nLemma nElemP n G E : reflect (exists p, E \\in 'E_p^n(G)) (E \\in 'E^n(G)).\n\nArguments nElemP {n G E}.\n\n(*This lemma states that the set of elementary abelian subgroups of rank zero within any group consists of only the trivial subgroup.*)\nLemma nElem0 G : 'E^0(G) = [set 1%G].\n\n(*This lemma states that a subgroup is an elementary abelian subgroup of rank one if and only if it is a proper subgroup and there exists a prime number such that the order of the subgroup is equal to that prime.*)\nLemma nElem1P G E :\n reflect (E \\subset G /\\ exists2 p, prime p & #|E| = p) (E \\in 'E^1(G)).\n\n(*This lemma states that if a group is a subgroup of another group, then the set of its elementary abelian subgroups of a given rank is a subset of the corresponding set for the larger group.*)\nLemma nElemS n G H : G \\subset H -> 'E^n(G) \\subset 'E^n(H).\n\n(*This lemma states that the set of elementary abelian subgroups of a given rank for the intersection of two groups is equal to the intersection of the set of such subgroups from the first group with the set of all subgroups of the second group.*)\nLemma nElemI n G H : 'E^n(G :&: H) = 'E^n(G) :&: subgroups H.\n\n(*This lemma states that the set of elementary abelian p-subgroups of a given rank n in a group is defined as the intersection of the set of all elementary abelian p-subgroups and the set of all elementary abelian subgroups of rank n.*)\nLemma def_pnElem p n G : 'E_p^n(G) = 'E_p(G) :&: 'E^n(G).\n\n(*This lemma states that a subgroup is a maximal elementary abelian p-subgroup if and only if it is an elementary abelian p-subgroup and it is not properly contained in any other elementary abelian p-subgroup.*)\nLemma pmaxElemP p A E :\n reflect (E \\in 'E_p(A) /\\ forall H, H \\in 'E_p(A) -> E \\subset H -> H :=: E)\n (E \\in 'E*_p(A)).\n\n(*This lemma guarantees that for any elementary abelian p-subgroup, there exists a maximal elementary abelian p-subgroup that contains it.*)\nLemma pmaxElem_exists p A D :\n D \\in 'E_p(A) -> {E | E \\in 'E*_p(A) & D \\subset E}.\n\n(*This lemma states that for a prime number, a subgroup is a maximal elementary abelian p-subgroup of a group if and only if it is equal to the largest normal p-subgroup of its own centralizer within the group.*)\nLemma pmaxElem_LdivP p G E :\n prime p -> reflect ('Ldiv_p('C_G(E)) = E) (E \\in 'E*_p(G)).\n\n(*This lemma states that if a group is a subgroup of another, then any maximal elementary abelian p-subgroup of the larger group that is also a subgroup of the smaller group is a subset of the set of maximal elementary abelian p-subgroups of the smaller group.*)\nLemma pmaxElemS p A B :\n A \\subset B -> 'E*_p(B) :&: subgroups A \\subset 'E*_p(A).\n\n(*This lemma states that a subgroup is a maximal elementary abelian p-subgroup of another subgroup if and only if its conjugate is a maximal elementary abelian p-subgroup of the conjugate of that other subgroup.*)\nLemma pmaxElemJ p A E x : ((E :^ x)%G \\in 'E*_p(A :^ x)) = (E \\in 'E*_p(A)).\n\n(*This lemma states that the minimum number of generators required for the subgroup generated by a given set of elements is less than or equal to the number of elements in that set.*)\nLemma grank_min B : 'm(<>) <= #|B|.\n\n(*This lemma asserts the existence of a generating set for any given group, such that the size of this set is exactly equal to the group's minimum number of generators.*)\nLemma grank_witness G : {B | <> = G & #|B| = 'm(G)}.\n\n(*This lemma asserts the existence of an elementary abelian p-subgroup whose rank is equal to the p-rank of the group.*)\nLemma p_rank_witness p G : {E | E \\in 'E_p^('r_p(G))(G)}.\n\n(*This lemma states that a natural number is less than or equal to the p-rank of a group if and only if there exists an elementary abelian p-subgroup of that rank within the group.*)\nLemma p_rank_geP p n G : reflect (exists E, E \\in 'E_p^n(G)) (n <= 'r_p(G)).\n\n(*This lemma states that the p-rank of a group is greater than zero if and only if the prime p divides the order of the group.*)\nLemma p_rank_gt0 p H : ('r_p(H) > 0) = (p \\in \\pi(H)).\n\n(*This lemma states that the p-rank of the trivial group is always zero for any prime number.*)\nLemma p_rank1 p : 'r_p([1 gT]) = 0.\n\n(*This lemma states that for any elementary abelian p-subgroup of a group, the base-p logarithm of its order is less than or equal to the p-rank of the group.*)\nLemma logn_le_p_rank p A E : E \\in 'E_p(A) -> logn p #|E| <= 'r_p(A).\n\n(*This lemma states that the p-rank of a group is less than or equal to the base-p logarithm of the group's order.*)\nLemma p_rank_le_logn p G : 'r_p(G) <= logn p #|G|.\n\n(*This lemma states that if a group is p-elementary abelian, then its p-rank is equal to the base-p logarithm of its order.*)\nLemma p_rank_abelem p G : p.-abelem G -> 'r_p(G) = logn p #|G|.\n\n(*This lemma states that if a group is a subgroup of another, its p-rank is less than or equal to the p-rank of the containing group.*)\nLemma p_rankS p A B : A \\subset B -> 'r_p(A) <= 'r_p(B).\n\n(*This lemma states that any elementary abelian p-subgroup whose rank is equal to the p-rank of the ambient group is a maximal elementary abelian p-subgroup of that ambient group.*)\nLemma p_rankElem_max p A : 'E_p^('r_p(A))(A) \\subset 'E*_p(A).\n\n(*This lemma states that the p-rank of a subgroup is equal to the p-rank of any of its conjugates.*)\nLemma p_rankJ p A x : 'r_p(A :^ x) = 'r_p(A).\n\n(*This lemma states that if a subgroup is a Sylow p-subgroup of a group, then its p-rank is equal to the p-rank of the entire group.*)\nLemma p_rank_Sylow p G H : p.-Sylow(G) H -> 'r_p(H) = 'r_p(G).\n\n(*This lemma states that if a subgroup is a Hall pi-subgroup of a group, and a prime p is in the set of primes pi, then the p-rank of the Hall subgroup is equal to the p-rank of the entire group.*)\nLemma p_rank_Hall pi p G H : pi.-Hall(G) H -> p \\in pi -> 'r_p(H) = 'r_p(G).\n\n(*This lemma states that if the p-rank of a finite group for a given prime is greater than or equal to a given natural number, then there exists a maximal elementary abelian p-subgroup whose p-rank is also greater than or equal to that same natural number.*)\nLemma p_rank_pmaxElem_exists p r G :\n 'r_p(G) >= r -> exists2 E, E \\in 'E*_p(G) & 'r_p(E) >= r.\n\n(*This lemma states that the rank of the trivial group is zero.*)\nLemma rank1 : 'r([1 gT]) = 0.\n\n(*This lemma states that for any prime number and any finite group, the p-rank of the group is less than or equal to its rank.*)\nLemma p_rank_le_rank p G : 'r_p(G) <= 'r(G).\n\n(*This lemma states that the rank of a finite group is greater than zero if and only if the group is not the trivial group.*)\nLemma rank_gt0 G : ('r(G) > 0) = (G :!=: 1).\n\n(*This lemma states that for any finite group, there exists a prime number such that the rank of the group is equal to its p-rank for that prime.*)\nLemma rank_witness G : {p | prime p & 'r(G) = 'r_p(G)}.\n\n(*This lemma states that if a finite group is a p-group for a given prime, then its rank is equal to its p-rank for that same prime.*)\nLemma rank_pgroup p G : p.-group G -> 'r(G) = 'r_p(G).\n\n(*This lemma states that if a subgroup is a Sylow p-subgroup of a given finite group, then the rank of the subgroup is equal to the p-rank of the parent group.*)\nLemma rank_Sylow p G P : p.-Sylow(G) P -> 'r(P) = 'r_p(G).\n\n(*This lemma states that for an elementary abelian p-group, its rank is equal to the logarithm in base p of the order of the group.*)\nLemma rank_abelem p G : p.-abelem G -> 'r(G) = logn p #|G|.\n\n(*This lemma states that any elementary abelian p-subgroup with a rank greater than zero is a non-trivial group.*)\nLemma nt_pnElem p n E A : E \\in 'E_p^n(A) -> n > 0 -> E :!=: 1.\n\n(*This lemma states that the rank of a subgroup is equal to the rank of any of its conjugate subgroups.*)\nLemma rankJ A x : 'r(A :^ x) = 'r(A).\n\n(*This lemma states that if a group is a subgroup of another group, its rank is less than or equal to the rank of the larger group.*)\nLemma rankS A B : A \\subset B -> 'r(A) <= 'r(B).\n\n(*This lemma states that for a given natural number, the rank of a finite group is greater than or equal to that number if and only if there exists an elementary abelian subgroup of that rank within the group.*)\nLemma rank_geP n G : reflect (exists E, E \\in 'E^n(G)) (n <= 'r(G)).\n\nEnd ExponentAbelem.\n\nArguments LdivP {gT A n x}.\nArguments exponentP {gT A n}.\nArguments abelemP {gT p G}.\nArguments is_abelemP {gT G}.\nArguments pElemP {gT p A E}.\nArguments pnElemP {gT p n A E}.\nArguments nElemP {gT n G E}.\nArguments nElem1P {gT G E}.\nArguments pmaxElemP {gT p A E}.\nArguments pmaxElem_LdivP {gT p G E}.\nArguments p_rank_geP {gT p n G}.\nArguments rank_geP {gT n G}.\n\nSection MorphAbelem.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\nImplicit Types (G H E : {group aT}) (A B : {set aT}).\n\n(*This lemma states that for a group morphism, the exponent of the image of a subgroup divides the exponent of the original subgroup.*)\nLemma exponent_morphim G : exponent (f @* G) %| exponent G.\n\n(*This lemma states that under a group morphism, the image of the set of elements of the domain whose order divides a given natural number is a subset of the elements of the codomain whose order also divides that same natural number.*)\nLemma morphim_LdivT n : f @* 'Ldiv_n() \\subset 'Ldiv_n().\n\n(*This lemma states that under a group morphism, the image of the set of elements in a subgroup whose order divides a given natural number is a subset of the elements in the image of that subgroup whose order also divides that natural number.*)\nLemma morphim_Ldiv n A : f @* 'Ldiv_n(A) \\subset 'Ldiv_n(f @* A).\n\n(*This lemma states that the image of an elementary abelian p-group under a group morphism is also an elementary abelian p-group for the same prime.*)\nLemma morphim_abelem p G : p.-abelem G -> p.-abelem (f @* G).\n\n(*This lemma states that the image of an elementary abelian p-subgroup under a group morphism is an elementary abelian p-subgroup of the image of the parent group.*)\nLemma morphim_pElem p G E : E \\in 'E_p(G) -> (f @* E)%G \\in 'E_p(f @* G).\n\n(*This lemma states that if a subgroup of a given group is an elementary abelian p-subgroup of a specified rank, then its image under a group morphism is an elementary abelian p-subgroup of the image group, with a rank less than or equal to the original rank.*)\nLemma morphim_pnElem p n G E :\n E \\in 'E_p^n(G) -> {m | m <= n & (f @* E)%G \\in 'E_p^m(f @* G)}.\n\n(*This lemma states that the minimal number of generators for the image of a subgroup under a group morphism is less than or equal to the minimal number of generators of the original subgroup.*)\nLemma morphim_grank G : G \\subset D -> 'm(f @* G) <= 'm(G).\n\nEnd MorphAbelem.\n\nSection InjmAbelem.\n\nVariables (aT rT : finGroupType) (D G : {group aT}) (f : {morphism D >-> rT}).\nHypotheses (injf : 'injm f) (sGD : G \\subset D).\n(*This definition establishes that applying the inverse of an injective group morphism to the image of a subgroup results in the original subgroup.*)\nLet defG : invm injf @* (f @* G) = G := morphim_invm injf sGD.\n\n(*This lemma states that for an injective group morphism, the exponent of the image of a subgroup is equal to the exponent of the original subgroup.*)\nLemma exponent_injm : exponent (f @* G) = exponent G.\n\n(*This lemma states that for an injective group morphism, the image of the set of elements in a subgroup whose order divides a natural number is equal to the set of elements in the image subgroup whose order also divides that number.*)\nLemma injm_Ldiv n A : f @* 'Ldiv_n(A) = 'Ldiv_n(f @* A).\n\n(*This lemma states that for a given prime number, the image of a subgroup under an injective group morphism is an elementary abelian p-group if and only if the original subgroup is an elementary abelian p-group.*)\nLemma injm_abelem p : p.-abelem (f @* G) = p.-abelem G.\n\n(*This lemma states that for an injective group morphism and a given prime, a subgroup of a group is an elementary abelian p-subgroup if and only if its image is an elementary abelian p-subgroup of the image of the parent group.*)\nLemma injm_pElem p (E : {group aT}) :\n E \\subset D -> ((f @* E)%G \\in 'E_p(f @* G)) = (E \\in 'E_p(G)).\n\n(*This lemma states that for an injective group morphism, a subgroup is an elementary abelian p-subgroup of a specific rank if and only if its image is an elementary abelian p-subgroup of the same rank within the image of the parent group.*)\nLemma injm_pnElem p n (E : {group aT}) :\n E \\subset D -> ((f @* E)%G \\in 'E_p^n(f @* G)) = (E \\in 'E_p^n(G)).\n\n(*This lemma states that for an injective group morphism, a subgroup is an elementary abelian subgroup of a specific rank if and only if its image is an elementary abelian subgroup of the same rank within the image of the parent group.*)\nLemma injm_nElem n (E : {group aT}) :\n E \\subset D -> ((f @* E)%G \\in 'E^n(f @* G)) = (E \\in 'E^n(G)).\n\n(*This lemma states that for an injective group morphism and a given prime, a subgroup is a maximal elementary abelian p-subgroup if and only if its image is a maximal elementary abelian p-subgroup of the image of the parent group.*)\nLemma injm_pmaxElem p (E : {group aT}) :\n E \\subset D -> ((f @* E)%G \\in 'E*_p(f @* G)) = (E \\in 'E*_p(G)).\n\n(*This lemma states that the minimal number of generators for the image of a subgroup under an injective group morphism is equal to the minimal number of generators of the original subgroup.*)\nLemma injm_grank : 'm(f @* G) = 'm(G).\n\n(*This lemma states that for an injective group morphism, the p-rank of the image of a subgroup is equal to the p-rank of the original subgroup.*)\nLemma injm_p_rank p : 'r_p(f @* G) = 'r_p(G).\n\n(*This lemma states that the rank of the image of a subgroup under an injective group morphism is equal to the rank of the original subgroup.*)\nLemma injm_rank : 'r(f @* G) = 'r(G).\n\nEnd InjmAbelem.\n\nSection IsogAbelem.\n\nVariables (aT rT : finGroupType) (G : {group aT}) (H : {group rT}).\nHypothesis isoGH : G \\isog H.\n\n(*This lemma states that if two finite groups are isomorphic, then their exponents are equal.*)\nLemma exponent_isog : exponent G = exponent H.\n\n(*This lemma states that for any given prime number, the property of a finite group being an abelian p-group is preserved under group isomorphism.*)\nLemma isog_abelem p : p.-abelem G = p.-abelem H.\n\n(*This lemma states that isomorphic finite groups have the same group rank, which is the minimal number of generators required to generate the group.*)\nLemma isog_grank : 'm(G) = 'm(H).\n\n(*This lemma states that for any given prime number, isomorphic finite groups have the same p-rank.*)\nLemma isog_p_rank p : 'r_p(G) = 'r_p(H).\n\n(*This lemma states that isomorphic finite groups have the same total rank.*)\nLemma isog_rank : 'r(G) = 'r(H).\n\nEnd IsogAbelem.\n\nSection QuotientAbelem.\n\nVariables (gT : finGroupType) (p : nat).\nImplicit Types E G K H : {group gT}.\n\n(*This lemma states that for any finite group and one of its normal subgroups, the exponent of the quotient group divides the exponent of the original group.*)\nLemma exponent_quotient G H : exponent (G / H) %| exponent G.\n\n(*This lemma states that for any natural number and a normal subgroup, the image under the quotient map of the set of all group elements whose order divides that number is contained in the set of elements of the quotient group whose order also divides that number.*)\nLemma quotient_LdivT n H : 'Ldiv_n() / H \\subset 'Ldiv_n().\n\n(*This lemma states that for a given natural number, a set of group elements, and a normal subgroup, taking the quotient of elements from the set whose order divides the number results in a subset of the quotient elements whose order also divides that number.*)\nLemma quotient_Ldiv n A H : 'Ldiv_n(A) / H \\subset 'Ldiv_n(A / H).\n\n(*This lemma states that for any given prime number, if a finite group is an abelian p-group, then any of its quotient groups is also an abelian p-group.*)\nLemma quotient_abelem G H : p.-abelem G -> p.-abelem (G / H).\n\n(*This lemma states that for any prime number, the image of an elementary abelian p-subgroup under a quotient map is also an elementary abelian p-subgroup of the quotient group.*)\nLemma quotient_pElem G H E : E \\in 'E_p(G) -> (E / H)%G \\in 'E_p(G / H).\n\n(*This lemma states that for any prime number, the p-adic valuation of the order of a quotient group is less than or equal to the p-adic valuation of the order of the original group.*)\nLemma logn_quotient G H : logn p #|G / H| <= logn p #|G|.\n\n(*This lemma states that for any prime number and any natural number, if a group contains an elementary abelian p-subgroup of a certain rank, then its image in a quotient group is an elementary abelian p-subgroup of a rank less than or equal to the original rank.*)\nLemma quotient_pnElem G H n E :\n E \\in 'E_p^n(G) -> {m | m <= n & (E / H)%G \\in 'E_p^m(G / H)}.\n\n(*This lemma states that if a subgroup is normal in a given finite group, then the group rank of the quotient group is less than or equal to the group rank of the original group.*)\nLemma quotient_grank G H : G \\subset 'N(H) -> 'm(G / H) <= 'm(G).\n\n(*This lemma states that for a finite group and one of its normal subgroups, the p-rank of the quotient group is greater than or equal to the p-rank of the group minus the p-rank of the normal subgroup.*)\nLemma p_rank_quotient G H : G \\subset 'N(H) -> 'r_p(G) - 'r_p(H) <= 'r_p(G / H).\n\n(*This lemma states that if a finite group is the internal direct product of two subgroups, its p-rank is the sum of the p-ranks of those subgroups.*)\nLemma p_rank_dprod K H G : K \\x H = G -> 'r_p(K) + 'r_p(H) = 'r_p(G).\n\n(*This lemma states that for a given prime number, if a finite group has a normal subgroup whose order is coprime to that prime, then the p-rank of the quotient group is equal to the p-rank of the original group.*)\nLemma p_rank_p'quotient G H :\n (p : nat)^'.-group H -> G \\subset 'N(H) -> 'r_p(G / H) = 'r_p(G).\n\nEnd QuotientAbelem.\n\nSection OhmProps.\n\nSection Generic.\n\nVariables (n : nat) (gT : finGroupType).\nImplicit Types (p : nat) (x : gT) (rT : finGroupType).\nImplicit Types (A B : {set gT}) (D G H : {group gT}).\n\n(*This lemma states that for any natural number, the Omega subgroup of a finite group, which is generated by elements whose orders divide that number, is a subgroup of the original group.*)\nLemma Ohm_sub G : 'Ohm_n(G) \\subset G.\n\n(*This lemma states that for any natural number, the Omega subgroup of the trivial group is the trivial group itself.*)\nLemma Ohm1 : 'Ohm_n([1 gT]) = 1. \n\n(*This lemma states that for any natural number, the Omega subgroup operation is idempotent; applying it twice to a finite group yields the same subgroup as applying it once.*)\nLemma Ohm_id G : 'Ohm_n('Ohm_n(G)) = 'Ohm_n(G).\n\n(*This lemma states that for any group morphism, the image of an Omega subgroup of the domain is a subgroup of the Omega subgroup of the image of the domain.*)\nLemma Ohm_cont rT G (f : {morphism G >-> rT}) :\n f @* 'Ohm_n(G) \\subset 'Ohm_n(f @* G).\n\n(*This lemma states that the Omega subgroup construction is monotonic; if one group is a subgroup of another, its Omega subgroup is a subgroup of the other's Omega subgroup.*)\nLemma OhmS H G : H \\subset G -> 'Ohm_n(H) \\subset 'Ohm_n(G).\n\n(*This lemma provides an alternative characterization of the n-th Omega subgroup of a finite p-group, stating that it is equal to the subgroup generated by all elements whose order divides the n-th power of the prime p.*)\nLemma OhmE p G : p.-group G -> 'Ohm_n(G) = <<'Ldiv_(p ^ n)(G)>>.\n\n(*This lemma states that if the n-th Omega subgroup of a finite p-group is abelian, then it is precisely the set of all elements whose order divides the n-th power of the prime p, not just the subgroup generated by them.*)\nLemma OhmEabelian p G :\n p.-group G -> abelian 'Ohm_n(G) -> 'Ohm_n(G) = 'Ldiv_(p ^ n)(G).\n\n(*This lemma describes the structure of the n-th Omega subgroup of a cyclic group generated by a p-element; it is the cyclic subgroup generated by the element raised to the power of p to the k minus n, where p to the k is the order of the generator.*)\nLemma Ohm_p_cycle p x :\n p.-elt x -> 'Ohm_n(<[x]>) = <[x ^+ (p ^ (logn p #[x] - n))]>.\n\n(*This lemma states that the Omega subgroup construction distributes over internal direct products; the Omega subgroup of a direct product is the direct product of the Omega subgroups of its factors.*)\nLemma Ohm_dprod A B G : A \\x B = G -> 'Ohm_n(A) \\x 'Ohm_n(B) = 'Ohm_n(G).\n\n(*This lemma states that for any natural number, the Agemo subgroup of a finite group, which is generated by the n-th powers of all its elements, is a subgroup of that group.*)\nLemma Mho_sub G : 'Mho^n(G) \\subset G.\n\n(*This lemma states that for any natural number, the Agemo subgroup of the trivial group is the trivial group itself.*)\nLemma Mho1 : 'Mho^n([1 gT]) = 1. \n\n(*This lemma states that group morphisms commute with the Agemo subgroup construction; the image of the n-th Agemo subgroup of a group under a morphism is equal to the n-th Agemo subgroup of the image of the group.*)\nLemma morphim_Mho rT D G (f : {morphism D >-> rT}) :\n G \\subset D -> f @* 'Mho^n(G) = 'Mho^n(f @* G).\n\n(*This lemma states that for any group morphism, the image of the n-th Agemo subgroup of its domain is contained in the n-th Agemo subgroup of the image of the domain.*)\nLemma Mho_cont rT G (f : {morphism G >-> rT}) :\n f @* 'Mho^n(G) \\subset 'Mho^n(f @* G).\n\n(*This lemma states that the Agemo subgroup construction is monotonic; if one group is a subgroup of another, its Agemo subgroup is a subgroup of the other's Agemo subgroup.*)\nLemma MhoS H G : H \\subset G -> 'Mho^n(H) \\subset 'Mho^n(G).\n\n(*This lemma states that for a p-group, its n-th Agemo subgroup is equal to the subgroup generated by the set of elements of the group, where each element is raised to the power of p to the n.*)\nLemma MhoE p G : p.-group G -> 'Mho^n(G) = <<[set x ^+ (p ^ n) | x in G]>>.\n\n(*This lemma states that for an abelian p-group, its n-th Agemo subgroup is the set of elements of the group, where each element is raised to the power of p to the n.*)\nLemma MhoEabelian p G :\n p.-group G -> abelian G -> 'Mho^n(G) = [set x ^+ (p ^ n) | x in G].\n\n(*This lemma states that if the n-th Agemo subgroup of a group is trivial, then the n-th Omega subgroup of that group is the group itself.*)\nLemma trivg_Mho G : 'Mho^n(G) == 1 -> 'Ohm_n(G) == G.\n\n(*This lemma states that for a cyclic group generated by a p-element, its n-th Agemo subgroup is the cyclic group generated by that element raised to the power of p to the n.*)\nLemma Mho_p_cycle p x : p.-elt x -> 'Mho^n(<[x]>) = <[x ^+ (p ^ n)]>.\n\n(*This lemma states that if a group is the product of two of its subgroups, then the n-th Agemo subgroup of the group is the product of the n-th Agemo subgroups of those two subgroups.*)\nLemma Mho_cprod A B G : A \\* B = G -> 'Mho^n(A) \\* 'Mho^n(B) = 'Mho^n(G).\n\n(*This lemma states that if a group is the direct product of two of its subgroups, then the n-th Agemo subgroup of the group is the direct product of the n-th Agemo subgroups of those two subgroups.*)\nLemma Mho_dprod A B G : A \\x B = G -> 'Mho^n(A) \\x 'Mho^n(B) = 'Mho^n(G).\n\nEnd Generic.\n\nCanonical Ohm_igFun i := [igFun by Ohm_sub i & Ohm_cont i].\nCanonical Ohm_gFun i := [gFun by Ohm_cont i].\nCanonical Ohm_mgFun i := [mgFun by OhmS i].\n\nCanonical Mho_igFun i := [igFun by Mho_sub i & Mho_cont i].\nCanonical Mho_gFun i := [gFun by Mho_cont i].\nCanonical Mho_mgFun i := [mgFun by MhoS i].\n\nSection char.\n\nVariables (n : nat) (gT rT : finGroupType) (D G : {group gT}).\n\n(*This lemma states that the n-th Omega subgroup of a group is a characteristic subgroup of that group.*)\nLemma Ohm_char : 'Ohm_n(G) \\char G. \n(*This lemma states that the n-th Omega subgroup of a group is a normal subgroup of that group.*)\nLemma Ohm_normal : 'Ohm_n(G) <| G. \n\n(*This lemma states that the n-th Agemo subgroup of a group is a characteristic subgroup of that group.*)\nLemma Mho_char : 'Mho^n(G) \\char G. \n(*This lemma states that the n-th Agemo subgroup of a group is a normal subgroup of that group.*)\nLemma Mho_normal : 'Mho^n(G) <| G. \n\n(*This lemma states that the image of the n-th Omega subgroup of a group under a group morphism is a subset of the n-th Omega subgroup of the image of the whole group.*)\nLemma morphim_Ohm (f : {morphism D >-> rT}) :\n G \\subset D -> f @* 'Ohm_n(G) \\subset 'Ohm_n(f @* G).\n\n(*This lemma states that for an injective group morphism, the image of the n-th Omega subgroup of a group is equal to the n-th Omega subgroup of the image of the entire group.*)\nLemma injm_Ohm (f : {morphism D >-> rT}) :\n 'injm f -> G \\subset D -> f @* 'Ohm_n(G) = 'Ohm_n(f @* G).\n\n(*This lemma states that if two groups are isomorphic, then their respective n-th Omega subgroups are also isomorphic.*)\nLemma isog_Ohm (H : {group rT}) : G \\isog H -> 'Ohm_n(G) \\isog 'Ohm_n(H).\n\n(*This lemma states that if two groups are isomorphic, then their respective n-th Agemo subgroups are also isomorphic.*)\nLemma isog_Mho (H : {group rT}) : G \\isog H -> 'Mho^n(G) \\isog 'Mho^n(H).\n\nEnd char.\n\nVariable gT : finGroupType.\nImplicit Types (pi : nat_pred) (p : nat).\nImplicit Types (A B C : {set gT}) (D G H E : {group gT}).\n\n(*This lemma states that the 0-th Omega subgroup of any group is the trivial subgroup.*)\nLemma Ohm0 G : 'Ohm_0(G) = 1.\n\n(*This lemma states that for any two natural numbers where one is less than or equal to the other, the Omega subgroup corresponding to the smaller number is a subset of the Omega subgroup corresponding to the larger number.*)\nLemma Ohm_leq m n G : m <= n -> 'Ohm_m(G) \\subset 'Ohm_n(G).\n\n(*This lemma states that the n-th Omega subgroup of the conjugate of a group is equal to the conjugate of the n-th Omega subgroup of that group.*)\nLemma OhmJ n G x : 'Ohm_n(G :^ x) = 'Ohm_n(G) :^ x.\n\n(*This lemma states that the 0-th Agemo subgroup of any group is the group itself.*)\nLemma Mho0 G : 'Mho^0(G) = G.\n\n(*This lemma states that for any two natural numbers where one is less than or equal to the other, the Agemo subgroup corresponding to the larger number is a subset of the Agemo subgroup corresponding to the smaller number.*)\nLemma Mho_leq m n G : m <= n -> 'Mho^n(G) \\subset 'Mho^m(G).\n\n(*This lemma states that the n-th Agemo subgroup of the conjugate of a group is equal to the conjugate of the n-th Agemo subgroup of that group.*)\nLemma MhoJ n G x : 'Mho^n(G :^ x) = 'Mho^n(G) :^ x.\n\n(*This lemma states that for a p-group, if its first Agemo subgroup is cyclic and generated by some element raised to the power p, then for any positive natural number k, the k-th Agemo subgroup is also cyclic and is generated by that same element raised to the power of p to the k.*)\nLemma extend_cyclic_Mho G p x :\n p.-group G -> x \\in G -> 'Mho^1(G) = <[x ^+ p]> -> \n forall k, k > 0 -> 'Mho^k(G) = <[x ^+ (p ^ k)]>.\n\n(*This lemma provides an alternative characterization of the first Omega subgroup of a group, stating that it is the subgroup generated by the set of all elements in the group that have prime order.*)\nLemma Ohm1Eprime G : 'Ohm_1(G) = <<[set x in G | prime #[x]]>>.\n\n(*This lemma states that for a p-group, its first Omega subgroup is a p-abelian group if and only if it is an abelian group.*)\nLemma abelem_Ohm1 p G : p.-group G -> p.-abelem 'Ohm_1(G) = abelian 'Ohm_1(G).\n\n(*This lemma states that if a group is an abelian p-group, then its first Omega subgroup is a p-abelian group.*)\nLemma Ohm1_abelem p G : p.-group G -> abelian G -> p.-abelem ('Ohm_1(G)).\n\n(*This lemma states that if a group is a p-abelian group, then its first Omega subgroup is identical to the group itself.*)\nLemma Ohm1_id p G : p.-abelem G -> 'Ohm_1(G) = G.\n\n(*This lemma states that for an abelian p-group, the condition that its first Omega subgroup is the whole group is logically equivalent to the group being a p-abelian group.*)\nLemma abelem_Ohm1P p G :\n abelian G -> p.-group G -> reflect ('Ohm_1(G) = G) (p.-abelem G).\n\n(*This lemma states that if the intersection of a subgroup with the first Omega subgroup of another group is trivial, then the intersection of that subgroup with the entire other group is also trivial.*)\nLemma TI_Ohm1 G H : H :&: 'Ohm_1(G) = 1 -> H :&: G = 1.\n\n(*This lemma states that the first Omega subgroup of a group is trivial if and only if the group itself is trivial.*)\nLemma Ohm1_eq1 G : ('Ohm_1(G) == 1) = (G :==: 1).\n\n(*This lemma states that if the intersection of two groups is non-trivial, then the intersection of the first group with the first Omega subgroup of the second group is also non-trivial.*)\nLemma meet_Ohm1 G H : G :&: H != 1 -> G :&: 'Ohm_1(H) != 1.\n\n(*This lemma states that for a p-group, if a subgroup is an elementary abelian p-subgroup of maximal rank, then the first Omega subgroup of the centralizer of that subgroup is the subgroup itself.*)\nLemma Ohm1_cent_max G E p : E \\in 'E*_p(G) -> p.-group G -> 'Ohm_1('C_G(E)) = E.\n\n(*This lemma states that for any non-trivial cyclic group that is also a p-group, the size of its subgroup of elements whose order divides the prime p is exactly equal to p.*)\nLemma Ohm1_cyclic_pgroup_prime p G :\n cyclic G -> p.-group G -> G :!=: 1 -> #|'Ohm_1(G)| = p.\n\n(*This lemma states that if a cyclic p-group is expressed as the direct product of two subgroups, then one of those subgroups must be trivial while the other must be the group itself.*)\nLemma cyclic_pgroup_dprod_trivg p A B C :\n p.-group C -> cyclic C -> A \\x B = C ->\n A = 1 /\\ B = C \\/ B = 1 /\\ A = C.\n\n(*This lemma states that the set of prime numbers that divide the order of the subgroup of elements of a group G with prime order is identical to the set of prime numbers that divide the order of group G itself.*)\nLemma piOhm1 G : \\pi('Ohm_1(G)) = \\pi(G).\n\n(*This lemma states that for a given prime number p, if the exponent of the subgroup of elements whose order divides p also divides p, then that subgroup is equal to the subgroup of all elements whose order is a power of p.*)\nLemma Ohm1Eexponent p G :\n prime p -> exponent 'Ohm_1(G) %| p -> 'Ohm_1(G) = 'Ldiv_p(G).\n\n(*This lemma states that the p-rank of the subgroup of elements whose order divides p is equal to the p-rank of the original group.*)\nLemma p_rank_Ohm1 p G : 'r_p('Ohm_1(G)) = 'r_p(G).\n\n(*This lemma states that the rank of the subgroup of elements with prime order is equal to the rank of the original group.*)\nLemma rank_Ohm1 G : 'r('Ohm_1(G)) = 'r(G).\n\n(*This lemma states that for an abelian group, its p-rank is equal to the logarithm in base p of the size of its subgroup of elements whose order divides p.*)\nLemma p_rank_abelian p G : abelian G -> 'r_p(G) = logn p #|'Ohm_1(G)|.\n\n(*This lemma states that for an abelian p-group, its rank is equal to the logarithm in base p of the size of its subgroup of elements whose order divides p.*)\nLemma rank_abelian_pgroup p G :\n p.-group G -> abelian G -> 'r(G) = logn p #|'Ohm_1(G)|.\n\nEnd OhmProps.\n\nSection AbelianStructure.\n\nVariable gT : finGroupType.\nImplicit Types (p : nat) (G H K E : {group gT}).\n\n(*This lemma states that for an abelian group G, if there is an element whose order equals the exponent of the group, then G splits over the cyclic subgroup generated by that element.*)\nLemma abelian_splits x G :\n x \\in G -> #[x] = exponent G -> abelian G -> [splits G, over <[x]>].\n\n(*This lemma states that for any elementary abelian p-group, any of its subgroups is a direct-summand, meaning the group splits over the subgroup.*)\nLemma abelem_splits p G H : p.-abelem G -> H \\subset G -> [splits G, over H].\n\n(*This fact asserts that for any abelian group, there exists a subgroup and an element whose order is the exponent of the group, such that the group is the direct product of that subgroup and the cyclic group generated by the element.*)\nFact abelian_type_subproof G :\n {H : {group gT} & abelian G -> {x | #[x] = exponent G & <[x]> \\x H = G}}.\n\n(*This fixpoint recursively computes the sequence of invariant factors for a finite abelian group. It operates by taking the exponent of the group as the first factor and then recursing on the complementary direct-product factor, with the recursion depth bounded by a given natural number.*)\nFixpoint abelian_type_rec n G :=\n if n is n'.+1 then if abelian G && (G :!=: 1) then\n exponent G :: abelian_type_rec n' (tag (abelian_type_subproof G))\n else [::] else [::].\n\n(*This definition provides the abelian type of a group, which is the list of its invariant factors computed by a recursive process.*)\nDefinition abelian_type (A : {set gT}) := abelian_type_rec #|A| <>.\n\n(*This lemma states that the list of numbers representing the abelian type of a group is sorted such that each number divides the one that precedes it.*)\nLemma abelian_type_dvdn_sorted A : sorted [rel m n | n %| m] (abelian_type A).\n\n(*This lemma states that every number in the list of invariant factors of a group's abelian type is greater than one.*)\nLemma abelian_type_gt1 A : all [pred m | m > 1] (abelian_type A).\n\n(*This lemma states that the list of numbers representing the abelian type of a group is sorted in a non-increasing order.*)\nLemma abelian_type_sorted A : sorted geq (abelian_type A).\n\n(*This theorem states that every finite abelian group can be expressed as an internal direct product of cyclic subgroups, where the orders of these subgroups correspond to the sequence of numbers given by the group's abelian type.*)\nTheorem abelian_structure G :\n abelian G ->\n {b | \\big[dprod/1]_(x <- b) <[x]> = G & map order b = abelian_type G}.\n\n(*This lemma states that if a group is a direct product of cyclic subgroups, the number of generators in this decomposition whose order has a base-p logarithm greater than a number n is equal to the base-p logarithm of the index of the n-th Ohm subgroup in the (n+1)-th Ohm subgroup.*)\nLemma count_logn_dprod_cycle p n b G :\n \\big[dprod/1]_(x <- b) <[x]> = G ->\n count [pred x | logn p #[x] > n] b = logn p #|'Ohm_n.+1(G) : 'Ohm_n(G)|.\n\n(*This lemma states that for an abelian p-group decomposed into a direct product of non-trivial cyclic subgroups, the list of the orders of the generators is a permutation of the group's abelian type.*)\nLemma abelian_type_pgroup p b G :\n p.-group G -> \\big[dprod/1]_(x <- b) <[x]> = G -> 1 \\notin b ->\n perm_eq (abelian_type G) (map order b).\n\n(*This lemma states that for an abelian group, the length of the list of its invariant factors is equal to its rank.*)\nLemma size_abelian_type G : abelian G -> size (abelian_type G) = 'r(G).\n\n(*This lemma states that for any abelian group and a natural number n, the product of the size of the subgroup of elements whose order divides n and the size of the subgroup of n-th powers is equal to the size of the whole group.*)\nLemma mul_card_Ohm_Mho_abelian n G :\n abelian G -> (#|'Ohm_n(G)| * #|'Mho^n(G)|)%N = #|G|.\n\n(*This lemma states that for any abelian group, its m-rank is equal to its rank.*)\nLemma grank_abelian G : abelian G -> 'm(G) = 'r(G).\n\n(*This lemma states that the rank of a cyclic group generated by an element is one if the element is not the identity, and zero otherwise.*)\nLemma rank_cycle (x : gT) : 'r(<[x]>) = (x != 1).\n\n(*This lemma states that an abelian group is cyclic if and only if its rank is less than or equal to one.*)\nLemma abelian_rank1_cyclic G : abelian G -> cyclic G = ('r(G) <= 1).\n\n(*This definition specifies that a group is homocyclic if it is abelian and the sequence of its invariant factors is constant.*)\nDefinition homocyclic A := abelian A && constant (abelian_type A).\n\n(*This lemma states that for a homocyclic p-group, its n-th Ohm subgroup is equal to its k-th Mho subgroup, where k is the difference between the base-p logarithm of the group's exponent and n.*)\nLemma homocyclic_Ohm_Mho n p G :\n p.-group G -> homocyclic G -> 'Ohm_n(G) = 'Mho^(logn p (exponent G) - n)(G).\n\n(*This lemma provides a condition for a group to be homocyclic, stating that if an abelian p-group satisfies a specific equality between its Ohm and Mho subgroups for a certain range of indices, then the group must be homocyclic.*)\nLemma Ohm_Mho_homocyclic (n p : nat) G :\n abelian G -> p.-group G -> 0 < n < logn p (exponent G) ->\n 'Ohm_n(G) = 'Mho^(logn p (exponent G) - n)(G) -> homocyclic G.\n\n(*This lemma states that every elementary abelian p-group is a homocyclic group.*)\nLemma abelem_homocyclic p G : p.-abelem G -> homocyclic G.\n\n(*This lemma states that the trivial group is homocyclic.*)\nLemma homocyclic1 : homocyclic [1 gT].\n\n(*This lemma provides a property that serves as a necessary and sufficient condition for an abelian p-group to be homocyclic, based on its subgroup of elements of order dividing p.*)\nLemma Ohm1_homocyclicP p G : p.-group G -> abelian G ->\n reflect ('Ohm_1(G) = 'Mho^(logn p (exponent G)).-1(G)) (homocyclic G).\n\n(*This lemma states that for any homocyclic finite abelian group, its abelian type is a finite sequence whose length is the rank of the group and whose elements are all equal to the exponent of the group.*)\nLemma abelian_type_homocyclic G :\n homocyclic G -> abelian_type G = nseq 'r(G) (exponent G).\n\n(*This lemma states that for any elementary abelian group where every non-identity element has order equal to a given prime number, its abelian type is a finite sequence whose length is the rank of the group and where every element is that prime number.*)\nLemma abelian_type_abelem p G : p.-abelem G -> abelian_type G = nseq 'r(G) p.\n\n(*This lemma states that for any finite abelian group, its cardinality is less than or equal to its exponent raised to the power of its rank. Furthermore, equality holds if and only if the group is homocyclic.*)\nLemma max_card_abelian G :\n abelian G -> #|G| <= exponent G ^ 'r(G) ?= iff homocyclic G.\n\n(*This lemma states that the cardinality of a homocyclic finite abelian group is equal to its exponent raised to the power of its rank.*)\nLemma card_homocyclic G : homocyclic G -> #|G| = (exponent G ^ 'r(G))%N.\n\n(*This lemma states that if a homocyclic finite abelian group, which is also a p-group for a given prime p, is the direct product of two subgroups, then the abelian type of each subgroup is a finite sequence whose length is the rank of that subgroup and whose elements are all equal to the exponent of the total group.*)\nLemma abelian_type_dprod_homocyclic p K H G :\n K \\x H = G -> p.-group G -> homocyclic G ->\n abelian_type K = nseq 'r(K) (exponent G)\n /\\ abelian_type H = nseq 'r(H) (exponent G).\n\n(*This lemma states that if a homocyclic finite abelian group, which is also a p-group for a given prime p, is the direct product of two subgroups, then both of these subgroups are also homocyclic.*)\nLemma dprod_homocyclic p K H G :\n K \\x H = G -> p.-group G -> homocyclic G -> homocyclic K /\\ homocyclic H.\n\n(*This lemma states that if a homocyclic finite abelian p-group is the direct product of two subgroups, and one of the subgroups is non-trivial, then the exponent of that non-trivial subgroup is equal to the exponent of the total group.*)\nLemma exponent_dprod_homocyclic p K H G :\n K \\x H = G -> p.-group G -> homocyclic G -> K :!=: 1 ->\n exponent K = exponent G.\n\nEnd AbelianStructure.\n\nArguments abelian_type {gT} A%_g.\nArguments homocyclic {gT} A%_g.\n\nSection IsogAbelian.\n\nVariables aT rT : finGroupType.\nImplicit Type (gT : finGroupType) (D G : {group aT}) (H : {group rT}).\n\n(*This lemma states that if two finite abelian groups are isomorphic, then their abelian types are equal.*)\nLemma isog_abelian_type G H : isog G H -> abelian_type G = abelian_type H.\n\n(*This lemma states that two finite abelian groups are isomorphic if and only if their abelian types are equal.*)\nLemma eq_abelian_type_isog G H :\n abelian G -> abelian H -> isog G H = (abelian_type G == abelian_type H).\n\n(*This lemma states that a group is isomorphic to a given elementary abelian group with a specific prime exponent if and only if it is also an elementary abelian group with the same prime exponent and has the same cardinality.*)\nLemma isog_abelem_card p G H :\n p.-abelem G -> isog G H = p.-abelem H && (#|H| == #|G|).\n\nVariables (D : {group aT}) (f : {morphism D >-> rT}).\n\n(*This lemma states that for any finite abelian group, the rank of its image under a group morphism is less than or equal to the rank of the original group.*)\nLemma morphim_rank_abelian G : abelian G -> 'r(f @* G) <= 'r(G).\n\n(*This lemma states that for any finite abelian group and a given prime number, the rank of the Sylow p-subgroup of the group's image under a morphism is less than or equal to the rank of the Sylow p-subgroup of the original group.*)\nLemma morphim_p_rank_abelian p G : abelian G -> 'r_p(f @* G) <= 'r_p(G).\n\n(*This lemma states that if two finite groups are isomorphic, then one is homocyclic if and only if the other is also homocyclic.*)\nLemma isog_homocyclic G H : G \\isog H -> homocyclic G = homocyclic H.\n\nEnd IsogAbelian.\n\nSection QuotientRank.\n\nVariables (gT : finGroupType) (p : nat) (G H : {group gT}).\nHypothesis cGG : abelian G.\n\n(*This lemma states that for a finite abelian group and one of its subgroups, the rank of the resulting quotient group is less than or equal to the rank of the original group.*)\nLemma quotient_rank_abelian : 'r(G / H) <= 'r(G).\n\n(*This lemma states that for a finite abelian group, one of its subgroups, and a given prime number, the rank of the Sylow p-subgroup of the quotient group is less than or equal to the rank of the Sylow p-subgroup of the original group.*)\nLemma quotient_p_rank_abelian : 'r_p(G / H) <= 'r_p(G).\n\nEnd QuotientRank.\n\nSection FimModAbelem.\n\nImport GRing.Theory FinRing.Theory.\n\n(*This lemma states that if a prime number belongs to the set of prime characteristics of a non-zero ring, then the additive group of any finite left module over that ring is an elementary abelian group where every non-identity element has an order equal to that prime number.*)\nLemma fin_lmod_pchar_abelem p (R : nzRingType) (V : finLmodType R):\n p \\in [pchar R]%R -> p.-abelem [set: V].\n\n(*This lemma states that for any prime number, the additive group of any finite left module over the finite field with that number of elements is an elementary abelian group where every non-identity element has an order equal to that prime number.*)\nLemma fin_Fp_lmod_abelem p (V : finLmodType 'F_p) :\n prime p -> p.-abelem [set: V].\n\n(*This lemma states that if a prime number belongs to the set of prime characteristics of a finite non-zero ring, then the additive group of that ring is an elementary abelian group where every non-identity element has an order equal to that prime number.*)\nLemma fin_ring_pchar_abelem p (R : finNzRingType) :\n p \\in [pchar R]%R -> p.-abelem [set: R].\n\nEnd FimModAbelem.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use fin_lmod_pchar_abelem instead.\")]\n(*This notation provides a deprecated alias for a lemma stating that if a prime number is a characteristic of a ring, the additive group of any finite left module over it is an elementary abelian group where every non-identity element's order is that prime. Its use is discouraged in favor of the lemma's current name.*)\nNotation fin_lmod_char_abelem := (fin_lmod_pchar_abelem) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use fin_ring_pchar_abelem instead.\")]\n(*This notation provides a deprecated alias for a lemma stating that if a prime number is a characteristic of a finite non-zero ring, its additive group is an elementary abelian group where every non-identity element's order is that prime. Its use is discouraged in favor of the lemma's current name.*)", - "solvable.maximal": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice.\nFrom mathcomp Require Import div fintype finfun bigop finset prime binomial.\nFrom mathcomp Require Import fingroup morphism perm automorphism quotient.\nFrom mathcomp Require Import action commutator gproduct gfunctor ssralg .\nFrom mathcomp Require Import countalg finalg zmodp cyclic pgroup center gseries.\nFrom mathcomp Require Import nilpotent sylow abelian finmodule.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection Defs.\n\nVariable gT : finGroupType.\nImplicit Types (A B D : {set gT}) (G : {group gT}).\n\n(*This definition identifies a minimal non-trivial characteristic subgroup within a given group.*)\nDefinition charsimple A := [min A of G | G :!=: 1 & G \\char A].\n\n(*This definition constructs the Frattini subgroup of a given group, defined as the intersection of all its maximal subgroups.*)\nDefinition Frattini A := \\bigcap_(G : {group gT} | maximal_eq G A) G.\n\nCanonical Frattini_group A : {group gT} := Eval hnf in [group of Frattini A].\n\n(*This definition constructs the Fitting subgroup of a given finite group as the product of all its p-cores, taken over every prime number that divides the group's order.*)\nDefinition Fitting A := \\big[dprod/1]_(p <- primes #|A|) 'O_p(A).\n\n(*This lemma states that the set of elements defined as the Fitting subgroup of a group indeed forms a subgroup.*)\nLemma Fitting_group_set G : group_set (Fitting G).\n\nCanonical Fitting_group G := group (Fitting_group_set G).\n\n(*This definition specifies the 'critical' property for an ordered pair of groups. The property holds if the first group is a characteristic subgroup of the second, the Frattini subgroup of the first group is contained within its own center, the commutator of the two groups is contained within the center of the first group, and the centralizer of the first group in the second is equal to the center of the first group.*)\nDefinition critical A B :=\n [/\\ A \\char B,\n Frattini A \\subset 'Z(A),\n [~: B, A] \\subset 'Z(A)\n & 'C_B(A) = 'Z(A)].\n\n(*This definition describes the 'special' property of a group, which holds when its Frattini subgroup and its derived subgroup are both equal to its center.*)\nDefinition special A := Frattini A = 'Z(A) /\\ A^`(1) = 'Z(A).\n\n(*This definition describes the 'extraspecial' property of a group, which holds if the group is special and the order of its center is a prime number.*)\nDefinition extraspecial A := special A /\\ prime #|'Z(A)|.\n\n(*This definition constructs a set of subgroups of a given group, containing all of its normal subgroups that are also self-centralizing.*)\nDefinition SCN B := [set A : {group gT} | A <| B & 'C_B(A) == A].\n\n(*This definition constructs a subset of the self-centralizing normal subgroups of a given group, selecting only those subgroups whose rank is greater than or equal to a specified natural number.*)\nDefinition SCN_at n B := [set A in SCN B | n <= 'r(A)].\n\nEnd Defs.\n\nArguments charsimple {gT} A%_g.\nArguments Frattini {gT} A%_g.\nArguments Fitting {gT} A%_g.\nArguments critical {gT} A%_g B%_g.\nArguments special {gT} A%_g.\nArguments extraspecial {gT} A%_g.\nArguments SCN {gT} B%_g.\nArguments SCN_at {gT} n%_N B%_g.\n\n(*A notation for the Frattini subgroup of a group, representing the set of its elements.*)\nNotation \"''Phi' ( A )\" := (Frattini A)\n (at level 8, format \"''Phi' ( A )\") : group_scope.\n(*A notation that refers to the Frattini subgroup of a given group, viewed as a group itself.*)\nNotation \"''Phi' ( G )\" := (Frattini_group G) : Group_scope.\n\n(*A notation for the Fitting subgroup of a group. Depending on the context, this notation can refer to either the set of elements of the Fitting subgroup or to the Fitting subgroup viewed as a group itself.*)\nNotation \"''F' ( G )\" := (Fitting G)\n (at level 8, format \"''F' ( G )\") : group_scope.\n(*A notation for the Fitting subgroup of a given finite group, defined as the group's largest normal nilpotent subgroup.*)\nNotation \"''F' ( G )\" := (Fitting_group G) : Group_scope.\n\n(*A notation for the set of maximal normal subgroups of a given finite group.*)\nNotation \"''SCN' ( B )\" := (SCN B)\n (at level 8, format \"''SCN' ( B )\") : group_scope.\n(*A notation for the set of normal subgroups of a given finite group that have a specified index.*)\nNotation \"''SCN_' n ( B )\" := (SCN_at n B)\n (at level 8, n at level 2, format \"''SCN_' n ( B )\") : group_scope.\n\nSection PMax.\n\nVariables (gT : finGroupType) (p : nat) (P M : {group gT}).\nHypothesis pP : p.-group P.\n\n(*This lemma states that any maximal subgroup of a finite p-group is also a normal subgroup.*)\nLemma p_maximal_normal : maximal M P -> M <| P.\n\n(*This lemma states that for a prime number, any maximal subgroup of a finite p-group has an index equal to that prime number.*)\nLemma p_maximal_index : maximal M P -> #|P : M| = p.\n\n(*This lemma states that if a subgroup of a finite p-group has a prime index, then it is a maximal subgroup.*)\nLemma p_index_maximal : M \\subset P -> prime #|P : M| -> maximal M P.\n\nEnd PMax.\n\nSection Frattini.\n\nVariables gT : finGroupType.\nImplicit Type G M : {group gT}.\n\n(*This lemma states that the Frattini subgroup of a finite group is a subgroup of that group.*)\nLemma Phi_sub G : 'Phi(G) \\subset G.\n\n(*This lemma states that the Frattini subgroup of a finite group is contained in every maximal subgroup of that group.*)\nLemma Phi_sub_max G M : maximal M G -> 'Phi(G) \\subset M.\n\n(*This lemma states that for any non-trivial finite group, its Frattini subgroup is a proper subgroup.*)\nLemma Phi_proper G : G :!=: 1 -> 'Phi(G) \\proper G.\n\n(*This lemma states that if the join of the Frattini subgroup of a finite group with another subgroup equals the entire group, then that other subgroup must be the entire group itself, reflecting the property that elements of the Frattini subgroup are non-generators.*)\nLemma Phi_nongen G X : 'Phi(G) <*> X = G -> <> = G.\n\n(*This lemma states that the image of the Frattini subgroup of a finite group under a group morphism is a subgroup of the Frattini subgroup of the image of the group.*)\nLemma Frattini_continuous (rT : finGroupType) G (f : {morphism G >-> rT}) :\n f @* 'Phi(G) \\subset 'Phi(f @* G).\n\nEnd Frattini.\n\nCanonical Frattini_igFun := [igFun by Phi_sub & Frattini_continuous].\nCanonical Frattini_gFun := [gFun by Frattini_continuous].\n\nSection Frattini0.\n\nVariable gT : finGroupType.\nImplicit Types (rT : finGroupType) (D G : {group gT}).\n\n(*This lemma states that the Frattini subgroup of a finite group is a characteristic subgroup, meaning it is invariant under all automorphisms of the group.*)\nLemma Phi_char G : 'Phi(G) \\char G.\n\n(*This lemma states that the Frattini subgroup of a finite group is a normal subgroup.*)\nLemma Phi_normal G : 'Phi(G) <| G.\n\n(*This lemma states that for an injective group morphism, the image of the Frattini subgroup of any subgroup of the domain is equal to the Frattini subgroup of the image of that subgroup.*)\nLemma injm_Phi rT D G (f : {morphism D >-> rT}) :\n 'injm f -> G \\subset D -> f @* 'Phi(G) = 'Phi(f @* G).\n\n(*This lemma states that if two finite groups are isomorphic, then their Frattini subgroups are also isomorphic.*)\nLemma isog_Phi rT G (H : {group rT}) : G \\isog H -> 'Phi(G) \\isog 'Phi(H).\n\n(*This lemma states that conjugating the Frattini subgroup of a finite group by an element is equivalent to taking the Frattini subgroup of the conjugated group.*)\nLemma PhiJ G x : 'Phi(G :^ x) = 'Phi(G) :^ x.\n\nEnd Frattini0.\n\nSection Frattini2.\n\nVariables gT : finGroupType.\nImplicit Type G : {group gT}.\n\n(*This lemma states that the Frattini subgroup of the quotient of a finite group by its own Frattini subgroup is the trivial subgroup.*)\nLemma Phi_quotient_id G : 'Phi (G / 'Phi(G)) = 1.\n\n(*This lemma states that if the quotient of a finite group by its Frattini subgroup is a cyclic group, then the original group is also cyclic.*)\nLemma Phi_quotient_cyclic G : cyclic (G / 'Phi(G)) -> cyclic G.\n\nVariables (p : nat) (P : {group gT}).\n\n(*This lemma provides an equivalence, stating that the Frattini subgroup of a finite p-group is trivial if and only if the group is an elementary abelian p-group.*)\nLemma trivg_Phi : p.-group P -> ('Phi(P) == 1) = p.-abelem P.\n\nEnd Frattini2.\n\nSection Frattini3.\n\nVariables (gT : finGroupType) (p : nat) (P : {group gT}).\nHypothesis pP : p.-group P.\n\n(*This lemma states that for a finite p-group, the quotient of the group by its Frattini subgroup is an elementary abelian p-group.*)\nLemma Phi_quotient_abelem : p.-abelem (P / 'Phi(P)).\n\n(*This lemma, a key result for finite p-groups, states that the Frattini subgroup is the join of the commutator subgroup and the subgroup generated by all p-th powers of its elements.*)\nLemma Phi_joing : 'Phi(P) = P^`(1) <*> 'Mho^1(P).\n\n(*This lemma states that for a finite abelian p-group, its Frattini subgroup is equal to the subgroup generated by all p-th powers of its elements.*)\nLemma Phi_Mho : abelian P -> 'Phi(P) = 'Mho^1(P).\n\nEnd Frattini3.\n\nSection Frattini4.\n\nVariables (p : nat) (gT : finGroupType).\nImplicit Types (rT : finGroupType) (P G H K D : {group gT}).\n\n(*This lemma states that for a finite p-group, the Frattini subgroup of any of its subgroups is contained within the Frattini subgroup of the p-group itself.*)\nLemma PhiS G H : p.-group H -> G \\subset H -> 'Phi(G) \\subset 'Phi(H).\n\n(*This lemma states that for a group morphism and a subgroup of its domain that is a p-group, the image of the Frattini subgroup of the p-subgroup is equal to the Frattini subgroup of its image.*)\nLemma morphim_Phi rT P D (f : {morphism D >-> rT}) :\n p.-group P -> P \\subset D -> f @* 'Phi(P) = 'Phi(f @* P).\n\n(*This lemma states that for a finite p-group that normalizes a subgroup, the image of the Frattini subgroup in the quotient group is equal to the Frattini subgroup of the quotient group.*)\nLemma quotient_Phi P H :\n p.-group P -> P \\subset 'N(H) -> 'Phi(P) / H = 'Phi(P / H).\n\n(*This lemma states that if a finite p-group normalizes a subgroup and their quotient group is elementary abelian, then the Frattini subgroup of the p-group is contained within the normalized subgroup.*)\nLemma Phi_min G H :\n p.-group G -> G \\subset 'N(H) -> p.-abelem (G / H) -> 'Phi(G) \\subset H.\n\n(*This lemma states that if a finite p-group is the internal direct product of two of its subgroups, then its Frattini subgroup is the internal direct product of the Frattini subgroups of those two subgroups.*)\nLemma Phi_cprod G H K :\n p.-group G -> H \\* K = G -> 'Phi(H) \\* 'Phi(K) = 'Phi(G).\n\n(*This lemma states that for two finite p-groups where one centralizes the other, the Frattini subgroup of their product is the product of their individual Frattini subgroups.*)\nLemma Phi_mulg H K :\n p.-group H -> p.-group K -> K \\subset 'C(H) ->\n 'Phi(H * K) = 'Phi(H) * 'Phi(K).\n\n(*This lemma provides a reflection property, stating that a finite group is characteristically simple if and only if it is non-trivial and its only non-trivial characteristic subgroups are the group itself.*)\nLemma charsimpleP G :\n reflect (G :!=: 1 /\\ forall K, K :!=: 1 -> K \\char G -> K :=: G)\n (charsimple G).\n\nEnd Frattini4.\n\nSection Fitting.\n\nVariable gT : finGroupType.\nImplicit Types (p : nat) (G H : {group gT}).\n\n(*This lemma states that the Fitting subgroup of a finite group is a normal subgroup.*)\nLemma Fitting_normal G : 'F(G) <| G.\n\n(*This lemma states that the Fitting subgroup of a given finite group is a subgroup of that group.*)\nLemma Fitting_sub G : 'F(G) \\subset G.\n\n(*This lemma states that the Fitting subgroup of any finite group is a nilpotent group.*)\nLemma Fitting_nil G : nilpotent 'F(G).\n\n(*This lemma states that any normal nilpotent subgroup of a finite group is contained within that group's Fitting subgroup.*)\nLemma Fitting_max G H : H <| G -> nilpotent H -> H \\subset 'F(G).\n\n(*This lemma states that for any set of prime numbers, the pi-core of the Fitting subgroup of a given finite group is a subgroup of the pi-core of the original group.*)\nLemma pcore_Fitting pi G : 'O_pi('F(G)) \\subset 'O_pi(G).\n\n(*This lemma states that for any prime number, the p-core of the Fitting subgroup of a given finite group is identical to the p-core of the original group.*)\nLemma p_core_Fitting p G : 'O_p('F(G)) = 'O_p(G).\n\n(*This lemma states that if a finite group is nilpotent, then its Fitting subgroup is the group itself.*)\nLemma nilpotent_Fitting G : nilpotent G -> 'F(G) = G.\n\n(*This lemma states that for a prime number, if the largest normal subgroup of a finite group whose order is not divisible by that prime is trivial, then the Fitting subgroup is equal to the p-core of the group.*)\nLemma Fitting_eq_pcore p G : 'O_p^'(G) = 1 -> 'F(G) = 'O_p(G).\n\n(*This lemma states that the Fitting subgroup of a finite group is equal to the subgroup generated by the union of all its p-cores, taken over all prime numbers that divide the order of the group.*)\nLemma FittingEgen G :\n 'F(G) = <<\\bigcup_(p < #|G|.+1 | (p : nat) \\in \\pi(G)) 'O_p(G)>>.\n\nEnd Fitting.\n\nSection FittingFun.\n\nImplicit Types gT rT : finGroupType.\n\n(*This lemma establishes that the operation which maps a finite group to its Fitting subgroup is a p-continuous group functor, ensuring it behaves correctly with respect to group morphisms.*)\nLemma morphim_Fitting : GFunctor.pcontinuous (@Fitting).\n\n(*This lemma states that for any subgroup of a finite group, the intersection of that subgroup with the Fitting subgroup of the larger group is contained within the Fitting subgroup of the subgroup itself.*)\nLemma FittingS gT (G H : {group gT}) : H \\subset G -> H :&: 'F(G) \\subset 'F(H).\n\n(*This lemma states that the Fitting subgroup of a group conjugated by an element is equal to the Fitting subgroup of the original group conjugated by that same element.*)\nLemma FittingJ gT (G : {group gT}) x : 'F(G :^ x) = 'F(G) :^ x.\n\nEnd FittingFun.\n\nCanonical Fitting_igFun := [igFun by Fitting_sub & morphim_Fitting].\nCanonical Fitting_gFun := [gFun by morphim_Fitting].\nCanonical Fitting_pgFun := [pgFun by morphim_Fitting].\n\nSection IsoFitting.\n\nVariables (gT rT : finGroupType) (G D : {group gT}) (f : {morphism D >-> rT}).\n\n(*This lemma states that the Fitting subgroup of a finite group is a characteristic subgroup, meaning it is invariant under all automorphisms of the group.*)\nLemma Fitting_char : 'F(G) \\char G. \n\n(*This lemma states that for an injective group morphism and a subgroup of its domain, the image of the subgroup's Fitting subgroup under the morphism is equal to the Fitting subgroup of the image of the subgroup.*)\nLemma injm_Fitting : 'injm f -> G \\subset D -> f @* 'F(G) = 'F(f @* G).\n\n(*This lemma states that if two finite groups are isomorphic, then their respective Fitting subgroups are also isomorphic.*)\nLemma isog_Fitting (H : {group rT}) : G \\isog H -> 'F(G) \\isog 'F(H).\n\nEnd IsoFitting.\n\nSection CharSimple.\n\nVariable gT : finGroupType.\nImplicit Types (rT : finGroupType) (G H K L : {group gT}) (p : nat).\n\n(*This lemma states that any minimal normal subgroup of a finite group is characteristically simple, meaning it has no proper, non-trivial characteristic subgroups.*)\nLemma minnormal_charsimple G H : minnormal H G -> charsimple H.\n\n(*This lemma states that if a group is normal in another, and we take a maximal normal subgroup of the first group that is also normal in the second, then the resulting quotient group is characteristically simple.*)\nLemma maxnormal_charsimple G H L :\n G <| L -> maxnormal H G L -> charsimple (G / H).\n\n(*This lemma states that for a prime number, any subgroup of an abelian p-group is a direct factor; that is, there exists another subgroup such that the original group is the internal direct product of the two subgroups.*)\nLemma abelem_split_dprod rT p (A B : {group rT}) :\n p.-abelem A -> B \\subset A -> exists C : {group rT}, B \\x C = A.\n\n(*This lemma states that for a prime number and an element in an abelian p-group, the cyclic subgroup generated by that element is a direct factor of the group.*)\nLemma p_abelem_split1 rT p (A : {group rT}) x :\n p.-abelem A -> x \\in A ->\n exists B : {group rT}, [/\\ B \\subset A, #|B| = #|A| %/ #[x] & <[x]> \\x B = A].\n\n(*This lemma states that any non-trivial abelian group whose elements all have orders that are powers of a given prime number is characteristically simple.*)\nLemma abelem_charsimple p G : p.-abelem G -> G :!=: 1 -> charsimple G.\n\n(*This lemma provides a structure theorem for characteristically simple groups, stating that such a group is an internal direct product of isomorphic simple subgroups, which are all automorphic images of one another.*)\nLemma charsimple_dprod G : charsimple G ->\n exists H : {group gT}, [/\\ H \\subset G, simple H\n & exists2 I : {set {perm gT}}, I \\subset Aut G\n & \\big[dprod/1]_(f in I) f @: H = G].\n\n(*This lemma states that a finite group that is both simple and solvable must have an order that is a prime number.*)\nLemma simple_sol_prime G : solvable G -> simple G -> prime #|G|.\n\n(*This lemma states that a finite group that is both characteristically simple and solvable is necessarily an elementary abelian group.*)\nLemma charsimple_solvable G : charsimple G -> solvable G -> is_abelem G.\n\n(*This lemma states that if a minimal normal subgroup of a group is contained within a solvable supergroup, then that minimal normal subgroup must be a non-trivial elementary abelian group.*)\nLemma minnormal_solvable L G H :\n minnormal H L -> H \\subset G -> solvable G ->\n [/\\ L \\subset 'N(H), H :!=: 1 & is_abelem H].\n\n(*This lemma states that any non-trivial solvable group that is normal in a larger group contains a non-trivial elementary abelian subgroup that is also normal in that larger group.*)\nLemma solvable_norm_abelem L G :\n solvable G -> G <| L -> G :!=: 1 ->\n exists H : {group gT}, [/\\ H \\subset G, H <| L, H :!=: 1 & is_abelem H].\n\n(*This lemma states that for a solvable finite group, its Fitting subgroup is trivial if and only if the group itself is trivial.*)\nLemma trivg_Fitting G : solvable G -> ('F(G) == 1) = (G :==: 1).\n\n(*This lemma states that for any set of prime numbers, the operation of taking the Fitting subgroup commutes with the operation of taking the pi-core of a finite group.*)\nLemma Fitting_pcore pi G : 'F('O_pi(G)) = 'O_pi('F(G)).\n\nEnd CharSimple.\n\nSection SolvablePrimeFactor.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that for a solvable finite group, the index of any maximal normal subgroup is a prime number.*)\nLemma index_maxnormal_sol_prime (H : {group gT}) :\n solvable G -> maxnormal H G G -> prime #|G : H|.\n\n(*This lemma states that every non-trivial solvable finite group possesses a normal subgroup whose index in the group is a prime number.*)\nLemma sol_prime_factor_exists :\n solvable G -> G :!=: 1 -> {H : {group gT} | H <| G & prime #|G : H| }.\n\nEnd SolvablePrimeFactor.\n\nSection Special.\n\nVariables (gT : finGroupType) (p : nat) (A G : {group gT}).\n\n(*This lemma states that for a special p-group, its center is an elementary abelian p-group.*)\nLemma center_special_abelem : p.-group G -> special G -> p.-abelem 'Z(G).\n\n(*This lemma states that for a special p-group corresponding to a prime number, the exponent of the group divides the square of that prime number.*)\nLemma exponent_special : p.-group G -> special G -> exponent G %| p ^ 2.\n\n(*This theorem states that a p-group is a special group and its centralizer with respect to another group is its own center, provided that their orders are coprime, their commutator subgroup is the first group, and the union of all abelian characteristic subgroups of the first group is contained in the centralizer of the second group.*)\nTheorem abelian_charsimple_special :\n p.-group G -> coprime #|G| #|A| -> [~: G, A] = G ->\n \\bigcup_(H : {group gT} | (H \\char G) && abelian H) H \\subset 'C(A) ->\n special G /\\ 'C_G(A) = 'Z(G).\n\nEnd Special.\n\nSection Extraspecial.\n\nVariables (p : nat) (gT rT : finGroupType).\nImplicit Types D E F G H K M R S T U : {group gT}.\n\nSection Basic.\n\nVariable S : {group gT}.\nHypotheses (pS : p.-group S) (esS : extraspecial S).\n\n(*This definition establishes that the center of a given p-group is also a p-group.*)\nLet pZ : p.-group 'Z(S) := pgroupS (center_sub S) pS.\n(*This lemma states that for any extraspecial p-group, the associated number p must be a prime number.*)\nLemma extraspecial_prime : prime p.\n\n(*This lemma states that the order of the center of an extraspecial p-group is equal to the prime number associated with the group.*)\nLemma card_center_extraspecial : #|'Z(S)| = p.\n\n(*This lemma states that the order of an extraspecial p-group is greater than or equal to the cube of the associated prime number.*)\nLemma min_card_extraspecial : #|S| >= p ^ 3.\n\nEnd Basic.\n\n(*This lemma states that a group is an extraspecial p-group if a given number is prime, the order of the group is equal to the cube of that number, and the order of its center is equal to that number.*)\nLemma card_p3group_extraspecial E :\n prime p -> #|E| = (p ^ 3)%N -> #|'Z(E)| = p -> extraspecial E.\n\n(*This lemma states that a non-abelian p-group is an extraspecial p-group if the base-p logarithm of its order is less than or equal to three.*)\nLemma p3group_extraspecial G :\n p.-group G -> ~~ abelian G -> logn p #|G| <= 3 -> extraspecial G.\n\n(*This lemma states that any extraspecial group is non-abelian.*)\nLemma extraspecial_nonabelian G : extraspecial G -> ~~ abelian G.\n\n(*This lemma states that the exponent of an extraspecial 2-group is equal to four.*)\nLemma exponent_2extraspecial G : 2.-group G -> extraspecial G -> exponent G = 4.\n\n(*This lemma states that the image of a special group under an injective group homomorphism is also a special group.*)\nLemma injm_special D G (f : {morphism D >-> rT}) :\n 'injm f -> G \\subset D -> special G -> special (f @* G).\n\n(*This lemma states that the image of an extraspecial group under an injective group homomorphism is also an extraspecial group.*)\nLemma injm_extraspecial D G (f : {morphism D >-> rT}) :\n 'injm f -> G \\subset D -> extraspecial G -> extraspecial (f @* G).\n\n(*This lemma states that if a group is special, any group isomorphic to it is also special.*)\nLemma isog_special G (R : {group rT}) :\n G \\isog R -> special G -> special R.\n\n(*This lemma states that if a group is extraspecial, any group isomorphic to it is also extraspecial.*)\nLemma isog_extraspecial G (R : {group rT}) :\n G \\isog R -> extraspecial G -> extraspecial R.\n\n(*This lemma states that a p-group that is the product of two subgroups is an extraspecial group, provided that both subgroups are extraspecial and their intersection is equal to the center of the first subgroup.*)\nLemma cprod_extraspecial G H K :\n p.-group G -> H \\* K = G -> H :&: K = 'Z(H) ->\n extraspecial H -> extraspecial K -> extraspecial G.\n\nSection ExtraspecialFormspace.\n\nVariable G : {group gT}.\nHypotheses (pG : p.-group G) (esG : extraspecial G).\n\n(*This definition provides a proof that the number associated with an extraspecial p-group is a prime number.*)\nLet p_pr := extraspecial_prime pG esG.\n(*This definition provides a proof that the order of the center of an extraspecial p-group is equal to the associated prime number.*)\nLet oZ := card_center_extraspecial pG esG.\n(*This definition provides a proof that the prime number associated with an extraspecial group is greater than one.*)\nLet p_gt1 := prime_gt1 p_pr.\n(*This definition provides a proof that the prime number associated with an extraspecial group is a positive number.*)\nLet p_gt0 := prime_gt0 p_pr.\n\n(*This lemma states that in an extraspecial p-group, the centralizer of any element that is not in the center of the group is a maximal subgroup.*)\nLemma cent1_extraspecial_maximal x :\n x \\in G -> x \\notin 'Z(G) -> maximal 'C_G[x] G.\n\n(*This lemma states that if a subgroup of an extraspecial p-group is given, and an element from the larger group does not commute with every element of the subgroup, then the centralizer of that element within the subgroup is a maximal subgroup of the subgroup.*)\nLemma subcent1_extraspecial_maximal U x :\n U \\subset G -> x \\in G :\\: 'C(U) -> maximal 'C_U[x] U.\n\n(*This lemma states that for any subgroup of an extraspecial p-group, the order of its centralizer in the parent group is equal to the product of the order of its intersection with the center of the parent group and the index of the subgroup.*)\nLemma card_subcent_extraspecial U :\n U \\subset G -> #|'C_G(U)| = (#|'Z(G) :&: U| * #|G : U|)%N.\n\n(*This lemma states that for any element outside the center of an extraspecial p-group, the group can be decomposed into a central product of two subgroups. The first subgroup is an extraspecial group of order equal to the cube of the associated prime and contains the given element. The second subgroup is either also extraspecial or is equal to the center of the original group. Furthermore, the centers of all three groups are identical.*)\nLemma split1_extraspecial x :\n x \\in G :\\: 'Z(G) ->\n {E : {group gT} & {R : {group gT} |\n [/\\ #|E| = (p ^ 3)%N /\\ #|R| = #|G| %/ p ^ 2,\n E \\* R = G /\\ E :&: R = 'Z(E),\n 'Z(E) = 'Z(G) /\\ 'Z(R) = 'Z(G),\n extraspecial E /\\ x \\in E\n & if abelian R then R :=: 'Z(G) else extraspecial R]}}.\n\n(*This lemma states that in an extraspecial p-group, the subgroup generated by all elements of a specific prime order is equal to the subgroup generated by all elementary abelian p-subgroups of maximal rank.*)\nLemma pmaxElem_extraspecial : 'E*_p(G) = 'E_p^('r_p(G))(G).\n\nEnd ExtraspecialFormspace.\n\n(*This lemma states that if a p-group contains an extraspecial subgroup such that the commutator of the subgroup and the parent group is contained within the subgroup's derived subgroup, then the parent group is equal to the product of the subgroup and its centralizer.*)\nLemma critical_extraspecial R S :\n p.-group R -> S \\subset R -> extraspecial S -> [~: S, R] \\subset S^`(1) ->\n S \\* 'C_R(S) = R.\n\n(*This theorem states that any extraspecial p-group can be decomposed into a central product of a sequence of smaller extraspecial groups. Each of these smaller groups has an order equal to the cube of the associated prime number and shares the same center as the original group.*)\nTheorem extraspecial_structure S : p.-group S -> extraspecial S ->\n {Es | all (fun E => (#|E| == p ^ 3)%N && ('Z(E) == 'Z(S))) Es\n & \\big[cprod/1%g]_(E <- Es) E \\* 'Z(S) = S}.\n\nSection StructureCorollaries.\n\nVariable S : {group gT}.\nHypotheses (pS : p.-group S) (esS : extraspecial S).\n\n(*This lemma states that the natural number p is a prime number.*)\nLet p_pr := extraspecial_prime pS esS.\n(*This definition specifies a natural number as the cardinality of the center of a given extraspecial group.*)\nLet oZ := card_center_extraspecial pS esS.\n\n(*This lemma states that for any extraspecial group, its order is equal to a given prime raised to the power of two times some positive natural number plus one.*)\nLemma card_extraspecial : {n | n > 0 & #|S| = (p ^ n.*2.+1)%N}.\n\n(*This lemma states that the subgroup of automorphisms of an extraspecial group that stabilize its center is isomorphic to the group of automorphisms of the center itself.*)\nLemma Aut_extraspecial_full : Aut_in (Aut S) 'Z(S) \\isog Aut 'Z(S).\n\n(*This lemma states that for any natural number that is coprime to a given prime, there exists an automorphism of an extraspecial group such that its action on any element of the center is to raise that element to the power of the given natural number.*)\nLemma center_aut_extraspecial k : coprime k p ->\n exists2 f, f \\in Aut S & forall z, z \\in 'Z(S) -> f z = (z ^+ k)%g.\n\nEnd StructureCorollaries.\n\nEnd Extraspecial.\n\nSection SCN.\n\nVariables (gT : finGroupType) (p : nat) (G : {group gT}).\nImplicit Types A Z H : {group gT}.\n\n(*This lemma provides a logical equivalence, stating that a subgroup belongs to the set of SCN-subgroups of a group if and only if it is a normal subgroup whose centralizer in the group is the subgroup itself.*)\nLemma SCN_P A : reflect (A <| G /\\ 'C_G(A) = A) (A \\in 'SCN(G)).\n\n(*This lemma states that any SCN-subgroup of a group is an abelian group.*)\nLemma SCN_abelian A : A \\in 'SCN(G) -> abelian A.\n\n(*This lemma states that for a p-group with nilpotency class at most two, where the prime p is odd, the exponent of the subgroup generated by its elements of order p divides p.*)\nLemma exponent_Ohm1_class2 H :\n odd p -> p.-group H -> nil_class H <= 2 -> exponent 'Ohm_1(H) %| p.\n\n(*This lemma states that any SCN-subgroup of a group is also a maximal normal abelian subgroup of that group.*)\nLemma SCN_max A : A \\in 'SCN(G) -> [max A | A <| G & abelian A].\n\n(*This lemma states that within a p-group, any subgroup that is maximal among the normal abelian subgroups is also an SCN-subgroup of the group.*)\nLemma max_SCN A :\n p.-group G -> [max A | A <| G & abelian A] -> A \\in 'SCN(G).\n\nSection SCNseries.\n\nVariables A : {group gT}.\nHypothesis SCN_A : A \\in 'SCN(G).\n\n(*This definition specifies a subgroup as the one generated by all elements of order dividing a given prime within another subgroup.*)\nLet Z := 'Ohm_1(A).\n(*This definition establishes the abelian property of a given subgroup, which is known to be an SCN-subgroup.*)\nLet cAA := SCN_abelian SCN_A.\n(*This definition asserts that the subgroup generated by elements of prime order is a subgroup of a given larger subgroup.*)\nLet sZA: Z \\subset A := Ohm_sub 1 A.\n(*This definition asserts that a given abelian subgroup is a subgroup of the normalizer of one of its own subgroups.*)\nLet nZA : A \\subset 'N(Z) := sub_abelian_norm cAA sZA.\n\n(*This lemma states that the derived subgroup of the intersection of two specific centralizing subgroups is contained within a given abelian subgroup.*)\nLemma der1_stab_Ohm1_SCN_series : ('C(Z) :&: 'C_G(A / Z | 'Q))^`(1) \\subset A.\n\n(*This lemma states that for a group that is an odd p-group, the subgroup of elements of order p from the centralizer of a subgroup Z is contained within the stabilizer of the quotient group A over Z.*)\nLemma Ohm1_stab_Ohm1_SCN_series :\n odd p -> p.-group G -> 'Ohm_1('C_G(Z)) \\subset 'C_G(A / Z | 'Q).\n\nEnd SCNseries.\n\n(*This lemma states that for an odd p-group, if a subgroup is a maximal normal elementary abelian p-subgroup, then the subgroup generated by elements of order p within its centralizer is equal to the subgroup itself.*)\nLemma Ohm1_cent_max_normal_abelem Z :\n odd p -> p.-group G -> [max Z | Z <| G & p.-abelem Z] -> 'Ohm_1('C_G(Z)) = Z.\n\n(*This lemma states that any critical subgroup of a given group has a nilpotency class of at most two.*)\nLemma critical_class2 H : critical H G -> nil_class H <= 2.\n\n(*This lemma, known as Thompson's critical subgroup lemma, asserts the existence of a critical subgroup for any given p-group.*)\nLemma Thompson_critical : p.-group G -> {K : {group gT} | critical K G}.\n\n(*This lemma states that a p-subgroup of automorphisms of a critical p-subgroup must stabilize a particular characteristic subgroup within it.*)\nLemma critical_p_stab_Aut H :\n critical H G -> p.-group G -> p.-group 'C(H | [Aut G]).\n\nEnd SCN.", - "solvable.commutator": "From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat fintype.\nFrom mathcomp Require Import bigop finset binomial fingroup morphism.\nFrom mathcomp Require Import automorphism quotient gfunctor.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\n(*This definition computes the n-th derived set for a given set of elements from a finite group. It is defined by iteratively applying the commutator operation, which takes a set and returns the set of all commutators of pairs of its elements, a specified number of times.*)\nDefinition derived_at n (gT : finGroupType) (A : {set gT}) :=\n iter n (fun B => [~: B, B]) A.\nArguments derived_at n%_N {gT} A%_g : simpl never.\n(*A notation for the n-th term of the derived series of a group. When applied to a set of group elements, it yields the n-th derived set. When applied to a group structure, it yields the n-th derived subgroup as a group structure.*)\nNotation \"G ^` ( n )\" := (derived_at n G) : group_scope.\n\nSection DerivedBasics.\n\nVariables gT : finGroupType.\nImplicit Type A : {set gT}.\nImplicit Types G : {group gT}.\n\n(*This lemma states that the zeroth derived set of any given set of group elements is equal to the original set itself.*)\nLemma derg0 A : A^`(0) = A. \n(*This lemma states that the first derived set of any given set of group elements is equal to the commutator set of the original set with itself.*)\nLemma derg1 A : A^`(1) = [~: A, A]. \n(*This lemma provides the recursive step for computing derived sets. It states that for any natural number n, the derived set at step n plus one for a given set of group elements is equal to the commutator set of the n-th derived set with itself.*)\nLemma dergSn n A : A^`(n.+1) = [~: A^`(n), A^`(n)]. \n\n(*This lemma states that for any subgroup of a finite group and any natural number n, the n-th derived set is itself a subgroup.*)\nLemma der_group_set G n : group_set G^`(n).\n\nCanonical derived_at_group G n := Group (der_group_set G n).\n\nEnd DerivedBasics.\n\n(*A notation for the nth term of the derived series of a group, which is defined recursively as the commutator subgroup of the preceding term in the series.*)\nNotation \"G ^` ( n )\" := (derived_at_group G n) : Group_scope.\n\nSection Basic_commutator_properties.\n\nVariable gT : finGroupType.\nImplicit Types x y z : gT.\n\n(*This lemma states that the conjugate of a group element by another group element is equal to the first element multiplied on the right by their commutator.*)\nLemma conjg_mulR x y : x ^ y = x * [~ x, y].\n\n(*This lemma states that the conjugate of a group element by another group element is equal to the commutator of the second element and the inverse of the first, multiplied on the right by the first element.*)\nLemma conjg_Rmul x y : x ^ y = [~ y, x^-1] * x.\n\n(*This lemma provides an expansion for the commutator of a product of two group elements with a third element, stating that it is equal to the product of the commutator of the first and third elements, conjugated by the second element, and the commutator of the second and third elements.*)\nLemma commMgJ x y z : [~ x * y, z] = [~ x, z] ^ y * [~ y, z].\n\n(*This lemma provides an expansion for the commutator of a group element with a product of two other elements, stating that it is equal to the product of the commutator of the first and third elements, and the commutator of the first and second elements, conjugated by the third element.*)\nLemma commgMJ x y z : [~ x, y * z] = [~ x, z] * [~ x, y] ^ z.\n\n(*This lemma states that the commutator of a product of two group elements with a third element is equal to the product of the commutator of the first and third elements, the iterated commutator of the commutator of the first and third elements with the second element, and the commutator of the second and third elements.*)\nLemma commMgR x y z : [~ x * y, z] = [~ x, z] * [~ x, z, y] * [~ y, z].\n\n(*This lemma states that the commutator of a group element with a product of two other elements is equal to the product of the commutator of the first and third elements, the commutator of the first and second elements, and the iterated commutator of the commutator of the first and second elements with the third element.*)\nLemma commgMR x y z : [~ x, y * z] = [~ x, z] * [~ x, y] * [~ x, y, z].\n\n(*This lemma states the Hall-Witt identity for groups, which asserts that a specific product of three conjugated, iterated commutators involving three group elements and their inverses is equal to the identity element.*)\nLemma Hall_Witt_identity x y z :\n [~ x, y^-1, z] ^ y * [~ y, z^-1, x] ^ z * [~ z, x^-1, y] ^ x = 1.\n\nSection LeftComm.\n\nVariables (i : nat) (x y : gT).\nHypothesis cxz : commute x [~ x, y].\n\n(*This lemma states that if a group element commutes with its commutator with a second group element, then the commutator of the inverse of the first element with the second element is equal to the inverse of their original commutator.*)\nLemma commVg : [~ x^-1, y] = [~ x, y]^-1.\n\n(*This lemma states that if a group element commutes with its commutator with a second group element, then for any natural number power, the commutator of that power of the first element with the second element is equal to the same power of their original commutator.*)\nLemma commXg : [~ x ^+ i, y] = [~ x, y] ^+ i.\n\nEnd LeftComm.\n\nSection RightComm.\n\nVariables (i : nat) (x y : gT).\nHypothesis cyz : commute y [~ x, y].\n(*This definition establishes that if a group element commutes with its commutator with another group element, then the commutator also commutes with that group element.*)\nLet cyz' := commuteV cyz.\n\n(*This lemma states that if a second group element commutes with its commutator with a first group element, then the commutator of the first element with the inverse of the second element is equal to the inverse of their original commutator.*)\nLemma commgV : [~ x, y^-1] = [~ x, y]^-1.\n\n(*This lemma states that if a second group element commutes with its commutator with a first group element, then for any natural number power, the commutator of the first element with that power of the second element is equal to the same power of their original commutator.*)\nLemma commgX : [~ x, y ^+ i] = [~ x, y] ^+ i.\n\nEnd RightComm.\n\nSection LeftRightComm.\n\nVariables (i j : nat) (x y : gT).\nHypotheses (cxz : commute x [~ x, y]) (cyz : commute y [~ x, y]).\n\n(*This lemma states that if two group elements both commute with their own commutator, then for any two natural number powers, the commutator of the powered elements is equal to their original commutator raised to the power of the product of the two powers.*)\nLemma commXXg : [~ x ^+ i, y ^+ j] = [~ x, y] ^+ (i * j).\n\n(*This lemma provides a power expansion for a product of two group elements that both commute with their own commutator, stating that the power of their product is equal to the product of their individual powers followed by their commutator raised to a power given by a binomial coefficient.*)\nLemma expMg_Rmul : (y * x) ^+ i = y ^+ i * x ^+ i * [~ x, y] ^+ 'C(i, 2).\n\nEnd LeftRightComm.\n\nEnd Basic_commutator_properties.\n\nSection Commutator_properties.\n\nVariable gT : finGroupType.\nImplicit Type (rT : finGroupType) (A B C : {set gT}) (D G H K : {group gT}).\n\n(*This lemma states that the commutator subgroup generated by a set of group elements and the trivial subgroup containing only the identity element is itself the trivial subgroup.*)\nLemma commG1 A : [~: A, 1] = 1.\n\n(*This lemma states that the commutator subgroup generated by the trivial subgroup containing only the identity element and a set of group elements is itself the trivial subgroup.*)\nLemma comm1G A : [~: 1, A] = 1.\n\n(*This lemma states that the commutator subgroup of two sets of group elements is contained within the subgroup generated by the union of those two sets.*)\nLemma commg_sub A B : [~: A, B] \\subset A <*> B.\n\n(*This lemma states that a subgroup is always contained within the normalizer of the commutator subgroup generated by itself and another set of group elements.*)\nLemma commg_norml G A : G \\subset 'N([~: G, A]).\n\n(*This lemma states that a subgroup is always contained within the normalizer of the commutator subgroup generated by another set of group elements and itself.*)\nLemma commg_normr G A : G \\subset 'N([~: A, G]).\n\n(*This lemma states that the subgroup generated by the union of two subgroups is contained within the normalizer of their commutator subgroup.*)\nLemma commg_norm G H : G <*> H \\subset 'N([~: G, H]).\n\n(*This lemma states that the commutator subgroup of two subgroups is a normal subgroup of the subgroup generated by their union.*)\nLemma commg_normal G H : [~: G, H] <| G <*> H.\n\n(*This lemma states that if a set of group elements is contained within a subgroup, then that set is also contained within the normalizer of the commutator subgroup generated by the subgroup and any other set of group elements.*)\nLemma normsRl A G B : A \\subset G -> A \\subset 'N([~: G, B]).\n\n(*This lemma states that if a set of group elements is contained within a subgroup, then that set is also contained within the normalizer of the commutator subgroup generated by any other set of group elements and that subgroup.*)\nLemma normsRr A G B : A \\subset G -> A \\subset 'N([~: B, G]).\n\n(*This lemma states that the commutator subgroup of two subgroups is contained in the second subgroup if and only if the first subgroup is contained in the normalizer of the second subgroup.*)\nLemma commg_subr G H : ([~: G, H] \\subset H) = (G \\subset 'N(H)).\n\n(*This lemma states that the commutator subgroup of two subgroups is contained in the first subgroup if and only if the second subgroup is contained in the normalizer of the first subgroup.*)\nLemma commg_subl G H : ([~: G, H] \\subset G) = (H \\subset 'N(G)).\n\n(*This lemma states that if a set of group elements from a first subgroup normalizes a second subgroup, and a set of group elements from the second subgroup normalizes the first subgroup, then their commutator subgroup is contained in the intersection of the two subgroups.*)\nLemma commg_subI A B G H :\n A \\subset 'N_G(H) -> B \\subset 'N_H(G) -> [~: A, B] \\subset G :&: H.\n\n(*This lemma establishes an equivalence for two sets of group elements that both normalize a given subgroup. It states that the image of the first set in the quotient group is contained in the centralizer of the image of the second set if and only if the commutator subgroup of the two original sets is contained in the given subgroup.*)\nLemma quotient_cents2 A B K :\n A \\subset 'N(K) -> B \\subset 'N(K) ->\n (A / K \\subset 'C(B / K)) = ([~: A, B] \\subset K).\n\n(*This lemma states that if the commutator subgroup of two sets of group elements is contained in a subgroup, then the image of the first set in the corresponding quotient group is contained in the centralizer of the image of the second set.*)\nLemma quotient_cents2r A B K :\n [~: A, B] \\subset K -> (A / K) \\subset 'C(B / K).\n\n(*This lemma states that if a subgroup of a group contains the derived subgroup of that group, then the containing subgroup is normal in the original group.*)\nLemma sub_der1_norm G H : G^`(1) \\subset H -> H \\subset G -> G \\subset 'N(H).\n\n(*This lemma states that a subgroup of a group is normal if it contains the group's derived subgroup.*)\nLemma sub_der1_normal G H : G^`(1) \\subset H -> H \\subset G -> H <| G.\n\n(*This lemma states that if the derived subgroup of a group is contained within one of its normal subgroups, the corresponding quotient group is abelian.*)\nLemma sub_der1_abelian G H : G^`(1) \\subset H -> abelian (G / H).\n\n(*This lemma provides a condition for the derived subgroup of a group to be contained in another subgroup; specifically, if the first group normalizes the second and their quotient is abelian, then the derived subgroup of the first group is contained in the second.*)\nLemma der1_min G H : G \\subset 'N(H) -> abelian (G / H) -> G^`(1) \\subset H.\n\n(*This lemma states that for any group, the quotient of its n-th derived subgroup by its (n+1)-th derived subgroup is abelian for any natural number n.*)\nLemma der_abelian n G : abelian (G^`(n) / G^`(n.+1)).\n\n(*This lemma states that if a first group normalizes a second group, the commutator of the first and second groups is a subgroup of the normalizer of the commutator of any third group with the second group.*)\nLemma commg_normSl G H K : G \\subset 'N(H) -> [~: G, H] \\subset 'N([~: K, H]).\n\n(*This lemma states that if a first group normalizes a second group, the commutator of the second and first groups is a subgroup of the normalizer of the commutator of the second group with any third group.*)\nLemma commg_normSr G H K : G \\subset 'N(H) -> [~: H, G] \\subset 'N([~: H, K]).\n\n(*This lemma states that the product of the commutator subgroup of a first group and a third group, with the commutator subgroup of a second group and the third group, is a subgroup of the commutator subgroup of the group generated by the first two groups with the third group.*)\nLemma commMGr G H K : [~: G, K] * [~: H, K] \\subset [~: G * H , K].\n\n(*This lemma states that if a second group normalizes the commutator of a first and a third group, then the commutator of the group generated by the first two and the third group equals the product of their individual commutators with the third group.*)\nLemma commMG G H K :\n H \\subset 'N([~: G, K]) -> [~: G * H , K] = [~: G, K] * [~: H, K].\n\n(*This lemma establishes the equivalence between the iterated commutator subgroup of three groups being trivial, and the iterated commutator of any three elements taken from each respective group being the identity element.*)\nLemma comm3G1P A B C :\n reflect {in A & B & C, forall h k l, [~ h, k, l] = 1} ([~: A, B, C] :==: 1).\n\n(*This lemma, a form of the Three Subgroups Lemma, states that if for three subgroups, the iterated commutator of the first, second, and third is trivial, and the iterated commutator of the second, third, and first is also trivial, then the iterated commutator of the third, first, and second must also be trivial.*)\nLemma three_subgroup G H K :\n [~: G, H, K] :=: 1 -> [~: H, K, G] :=: 1-> [~: K, G, H] :=: 1.\n\n(*This lemma states that for any two elements in a group, if their commutator is in the center of the subgroup they generate, then the derived subgroup of the generated subgroup is equal to the cyclic group generated by their commutator.*)\nLemma der1_joing_cycles (x y : gT) : \n let XY := <[x]> <*> <[y]> in let xy := [~ x, y] in\n xy \\in 'C(XY) -> XY^`(1) = <[xy]>.\n\n(*This lemma states that for three elements in a group, if the second and third elements commute, and the commutator subgroup formed by the first element's cyclic group and the whole group is abelian, then the iterated commutator of all three elements is invariant under swapping the second and third elements.*)\nLemma commgAC G x y z : x \\in G -> y \\in G -> z \\in G ->\n commute y z -> abelian [~: [set x], G] -> [~ x, y, z] = [~ x, z, y].\n\n(*This lemma states that for three groups, if the first normalizes the second, the first centralizes the third, and the second normalizes the third, then the commutator of the first and second groups centralizes the third group.*)\nLemma comm_norm_cent_cent H G K :\n H \\subset 'N(G) -> H \\subset 'C(K) -> G \\subset 'N(K) ->\n [~: G, H] \\subset 'C(K).\n\n(*This lemma states that the commutator subgroup of two characteristic subgroups of a group is also a characteristic subgroup.*)\nLemma charR H K G : H \\char G -> K \\char G -> [~: H, K] \\char G.\n\n(*This lemma states that for any natural number n, the n-th derived subgroup of a group is a characteristic subgroup of that group.*)\nLemma der_char n G : G^`(n) \\char G.\n\n(*This lemma states that for any natural number n, the n-th derived subgroup of a group is a subgroup of the original group.*)\nLemma der_sub n G : G^`(n) \\subset G.\n\n(*This lemma states that for any natural number n, any group normalizes its n-th derived subgroup.*)\nLemma der_norm n G : G \\subset 'N(G^`(n)).\n\n(*This lemma states that for any natural number n, the n-th derived subgroup of a group is a normal subgroup of that group.*)\nLemma der_normal n G : G^`(n) <| G.\n\n(*This lemma states that for any natural number n, the (n+1)-th derived subgroup of a group is a subgroup of its n-th derived subgroup.*)\nLemma der_subS n G : G^`(n.+1) \\subset G^`(n).\n\n(*This lemma states that for any natural number n, the (n+1)-th derived subgroup of a group is a normal subgroup of its n-th derived subgroup.*)\nLemma der_normalS n G : G^`(n.+1) <| G^`(n).\n\n(*This lemma states that a group morphism preserves the n-th derived subgroups; specifically, the image of the n-th derived subgroup of a group under the morphism is equal to the n-th derived subgroup of the image of the group.*)\nLemma morphim_der rT D (f : {morphism D >-> rT}) n G :\n G \\subset D -> f @* G^`(n) = (f @* G)^`(n).\n\n(*This lemma states that for any natural number n, the operation of taking the n-th derived subgroup is monotonic with respect to the subgroup relation; that is, if one group is a subgroup of another, its n-th derived subgroup is a subgroup of the other's n-th derived subgroup.*)\nLemma dergS n G H : G \\subset H -> G^`(n) \\subset H^`(n).\n\n(*This lemma states that for a group with a normal subgroup, the n-th derived subgroup of the quotient group is the image of the original group's n-th derived subgroup in the quotient.*)\nLemma quotient_der n G H : G \\subset 'N(H) -> G^`(n) / H = (G / H)^`(n).\n\n(*This lemma states that for any group, element, and natural number n, the operation of taking the n-th derived subgroup commutes with conjugation by that element.*)\nLemma derJ G n x : (G :^ x)^`(n) = G^`(n) :^ x.\n\n(*This lemma establishes the equivalence between a group being abelian and its first derived subgroup, also known as the commutator subgroup, being the trivial group.*)\nLemma derG1P G : reflect (G^`(1) = 1) (abelian G).\n\nEnd Commutator_properties.\n\nArguments derG1P {gT G}.\n\n(*This lemma states that for any natural number n, the function mapping a group to its n-th derived subgroup is a continuous group functor, meaning it preserves categorical limits.*)\nLemma der_cont n : GFunctor.continuous (@derived_at n).\n\nCanonical der_igFun n := [igFun by der_sub^~ n & der_cont n].\nCanonical der_gFun n := [gFun by der_cont n].\nCanonical der_mgFun n := [mgFun by dergS^~ n].\n\n(*This lemma states that applying a group isomorphism to a subgroup and computing the n-th derived subgroup are commuting operations. For any subgroup in the domain of a group isomorphism, the image of its n-th derived subgroup under the isomorphism is equal to the n-th derived subgroup of its image.*)\nLemma isog_der (aT rT : finGroupType) n (G : {group aT}) (H : {group rT}) :\n G \\isog H -> G^`(n) \\isog H^`(n).", - "solvable.extraspecial": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype bigop finset prime binomial.\nFrom mathcomp Require Import fingroup morphism perm automorphism presentation.\nFrom mathcomp Require Import quotient action commutator gproduct gfunctor.\nFrom mathcomp Require Import ssralg finalg zmodp cyclic pgroup center gseries.\nFrom mathcomp Require Import nilpotent sylow abelian finmodule matrix maximal.\nFrom mathcomp Require Import extremal.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\n(*A local notation for converting a natural number into its corresponding element in a ring.*)\nLocal Notation \"n %:R\" := (n %:R%R).\nImport GroupScope GRing.Theory.\n\nReserved Notation \"p ^{1+2}\" (format \"p ^{1+2}\").\nReserved Notation \"p ^{1+2* n }\" (n at level 2, format \"p ^{1+2* n }\").\nReserved Notation \"''D^' n\" (at level 0, n at level 2, format \"''D^' n\").\nReserved Notation \"''D^' n * 'Q'\" (format \"''D^' n * 'Q'\").\n\nModule Pextraspecial.\n\nSection Construction.\n\nVariable p : nat.\n\n(*This definition specifies an action of an integer modulo a prime on a pair of integers modulo the same prime, where the action modifies the first component of the pair by adding a multiple of the second component to it, while leaving the second component unchanged.*)\nDefinition act ij (k : 'Z_p) := let: (i, j) := ij in (i + k * j, j)%R.\n(*This lemma states that the 'act' function correctly defines a group action of the integers modulo a prime on the set of pairs of integers modulo that same prime.*)\nLemma actP : is_action [set: 'Z_p] act.\n\nCanonical action := Action actP.\n\n(*This lemma states that the defined action is a valid group action, meaning that acting on the group of pairs of integers modulo a prime corresponds to a group homomorphism into the automorphism group of that group of pairs.*)\nLemma gactP : is_groupAction [set: 'Z_p * 'Z_p] action.\n\n(*This definition encapsulates the established group action and its properties into a canonical structure, which is then used to construct a semidirect product group.*)\nDefinition groupAction := GroupAction gactP.\n\n(*A constant value serving as a key to create an opaque group type, concealing its underlying semidirect product representation from direct access.*)\nFact gtype_key : unit. \n(*This definition establishes an opaque type for an extraspecial group of order p cubed, constructed internally as a semidirect product but with its implementation details hidden.*)\nDefinition gtype := locked_with gtype_key (sdprod_groupType groupAction).\n\n(*This definition represents the central product formed from a sequence of extraspecial groups of order p cubed.*)\nDefinition ngtype := ncprod [set: gtype].\n\nEnd Construction.\n\n(*This definition constructs an extraspecial 2-group as the central product of a given number of copies of the dihedral group of order 8 with the quaternion group of order 8.*)\nDefinition ngtypeQ n := xcprod [set: ngtype 2 n] 'Q_8.\n\nEnd Pextraspecial.\n\n(*A notation for the extraspecial group of order p cubed and exponent p for an odd prime p. It refers to the group as a type or as a set of elements depending on the context.*)\nNotation \"p ^{1+2}\" := (Pextraspecial.gtype p) : type_scope.\n(*This notation provides syntax for raising a group element to the third power, where the exponent is explicitly written as the sum of one and two.*)\nNotation \"p ^{1+2}\" := [set: gsort p^{1+2}] : group_scope.\n(*This notation represents an extraspecial group constructed from a prime number. The group has an order equal to the prime number cubed. Depending on the context, this notation can refer to the type of the group's elements or to the set of the group's elements.*)\nNotation \"p ^{1+2}\" := [set: gsort p^{1+2}]%G : Group_scope.\n\n(*This notation represents an extraspecial group constructed from a prime number and a natural number. The group has an order equal to the prime number raised to the power of the sum of one and two times the natural number. Depending on the context, this notation can refer to the type of the group's elements or to the set of the group's elements.*)\nNotation \"p ^{1+2* n }\" := (Pextraspecial.ngtype p n) : type_scope.\n(*A notation that takes a prime number `p` and a natural number `n`, and represents the type of an extraspecial group of order equal to `p` raised to the power of one plus two times `n`.*)\nNotation \"p ^{1+2* n }\" := [set: gsort p^{1+2*n}] : group_scope.\n(*This notation represents the result of raising a value `p` to the power of an odd positive integer, where the exponent is expressed as one plus two times a natural number `n`.*)\nNotation \"p ^{1+2* n }\" := [set: gsort p^{1+2*n}]%G : Group_scope.\n\n(*This notation represents the set of elements belonging to the dihedral group of order two times a given natural number `n`. This group corresponds to the symmetries of a regular polygon with `n` sides, which includes both rotations and reflections.*)\nNotation \"''D^' n\" := (Pextraspecial.ngtype 2 n) : type_scope.\n(**)\nNotation \"''D^' n\" := [set: gsort 'D^n] : group_scope.\n(*The notation ''D^' n represents an extraspecial 2-group that is constructed from the central product of a specified number of copies of the dihedral group of order 8.*)\nNotation \"''D^' n\" := [set: gsort 'D^n]%G : Group_scope.\n\n(*The notation ''D^' n * 'Q' represents an extraspecial 2-group constructed by taking the central product of a given number of copies of the dihedral group of order 8 and a single copy of the quaternion group of order 8.*)\nNotation \"''D^' n * 'Q'\" := (Pextraspecial.ngtypeQ n) : type_scope.\n(*This notation specifies a product type derived from two component ordered types. The first component type is the dual of an ordered type, which inverts the original less-than-or-equal-to relation. The second component type is another ordered type. The notation itself denotes the Cartesian product of these two types, upon which an order structure, such as a pointwise or lexicographic order, can be defined.*)\nNotation \"''D^' n * 'Q'\" := [set: gsort 'D^n*Q] : group_scope.\n(*This notation represents a group formed by the central product of the group denoted by 'D^' n and the quaternion group.*)\nNotation \"''D^' n * 'Q'\" := [set: gsort 'D^n*Q]%G : Group_scope.\n\nSection ExponentPextraspecialTheory.\n\nVariable p : nat.\nHypothesis p_pr : prime p.\n(*This definition establishes that a given prime natural number is strictly greater than one.*)\nLet p_gt1 := prime_gt1 p_pr.\n(*This definition establishes that a given prime natural number is strictly greater than zero.*)\nLet p_gt0 := ltnW p_gt1.\n\n(*This notation serves as a local alias for the carrier type of an extraspecial p-group.*)\nLocal Notation gtype := Pextraspecial.gtype.\n(*This notation serves as a local alias for the group action associated with a prime natural number in the context of extraspecial p-groups.*)\nLocal Notation actp := (Pextraspecial.groupAction p).\n\n(*This lemma states that the cardinality of the extraspecial group denoted as p to the power of one plus two is equal to the cube of the prime natural number p.*)\nLemma card_pX1p2 : #|p^{1+2}| = (p ^ 3)%N.\n\n(*This lemma states that the extraspecial group denoted as p to the power of one plus two is isomorphic to a concrete group constructed from pairs of elements from the cyclic group of order p, with a specific group multiplication law involving commutators.*)\nLemma Grp_pX1p2 :\n p^{1+2} \\isog Grp (x : y : x ^+ p, y ^+ p, [~ x, y, x], [~ x, y, y]).\n\n(*This lemma states that the group denoted as p to the power of one plus two is a p-group.*)\nLemma pX1p2_pgroup : p.-group p^{1+2}.\n\n(*This lemma states that the group denoted as p to the power of one plus two is an extraspecial group.*)\nLemma pX1p2_extraspecial : extraspecial p^{1+2}.\n\n(*This lemma states that for an odd prime natural number p, the exponent of the extraspecial group denoted as p to the power of one plus two divides p.*)\nLemma exponent_pX1p2 : odd p -> exponent p^{1+2} %| p.\n\n(*This lemma states that any finite group that is extraspecial, has an exponent dividing a prime natural number p, and has a cardinality equal to p cubed, is isomorphic to the extraspecial group denoted as p to the power of one plus two.*)\nLemma isog_pX1p2 (gT : finGroupType) (G : {group gT}) :\n extraspecial G -> exponent G %| p -> #|G| = (p ^ 3)%N -> G \\isog p^{1+2}.\n\nEnd ExponentPextraspecialTheory.\n\nSection GeneralExponentPextraspecialTheory.\n\nVariable p : nat.\n\n(*This lemma states that the extraspecial group denoted as p to the power of one plus two times one is isomorphic to the extraspecial group denoted as p to the power of one plus two.*)\nLemma pX1p2id : p^{1+2*1} \\isog p^{1+2}.\n\n(*This lemma provides an inductive specification for constructing an extraspecial group, defining it as the central product of the group denoted as p to the power of one plus two and the group denoted as p to the power of one plus two times a natural number n.*)\nLemma pX1p2S n : xcprod_spec p^{1+2} p^{1+2*n} p^{1+2*n.+1}%type.\n\n(*This lemma states that for a prime natural number p, the cardinality of the group denoted as p to the power of one plus two times a natural number n is equal to p raised to the power of two times n plus one.*)\nLemma card_pX1p2n n : prime p -> #|p^{1+2*n}| = (p ^ n.*2.+1)%N.\n\n(*This lemma states that for any prime natural number p, the group denoted as p to the power of one plus two times a natural number n is a p-group.*)\nLemma pX1p2n_pgroup n : prime p -> p.-group p^{1+2*n}.\n\n(*This lemma states that for an odd prime natural number p, the exponent of the group denoted as p to the power of one plus two times a natural number n is equal to p.*)\nLemma exponent_pX1p2n n : prime p -> odd p -> exponent p^{1+2*n} = p.\n\n(*This lemma states that for a prime natural number p and a positive natural number n, the group denoted as p to the power of one plus two times n is an extraspecial group.*)\nLemma pX1p2n_extraspecial n : prime p -> n > 0 -> extraspecial p^{1+2*n}.\n\n(*This lemma describes the structure of an odd-order, extraspecial p-group. It asserts that the subgroup of elements whose order divides the prime p has an exponent of p, and its index in the whole group divides p. Furthermore, if this subgroup is not the entire group, the lemma guarantees the existence of a specific decomposition of the group involving another smaller extraspecial or p-group and a group isomorphic to a certain modular p-group.*)\nLemma Ohm1_extraspecial_odd (gT : finGroupType) (G : {group gT}) :\n p.-group G -> extraspecial G -> odd #|G| ->\n let Y := 'Ohm_1(G) in\n [/\\ exponent Y = p, #|G : Y| %| p\n & Y != G ->\n exists E : {group gT},\n [/\\ #|G : Y| = p, #|E| = p \\/ extraspecial E,\n exists2 X : {group gT}, #|X| = p & X \\x E = Y\n & exists M : {group gT},\n [/\\ M \\isog 'Mod_(p ^ 3), M \\* E = G & M :&: E = 'Z(M)]]].\n\n(*This lemma provides a classification for certain extraspecial p-groups, stating that for a prime p, any extraspecial finite group whose cardinality is p raised to the power of two times n plus one and whose exponent divides p, must be isomorphic to the canonical extraspecial group denoted as p to the power of one plus two times n.*)\nLemma isog_pX1p2n n (gT : finGroupType) (G : {group gT}) :\n prime p -> extraspecial G -> #|G| = (p ^ n.*2.+1)%N -> exponent G %| p ->\n G \\isog p^{1+2*n}.\n\nEnd GeneralExponentPextraspecialTheory.\n\n(*This lemma states that the extraspecial group of order eight, denoted as two to the power of one plus two, is isomorphic to the dihedral group of order eight.*)\nLemma isog_2X1p2 : 2^{1+2} \\isog 'D_8.\n\n(*This lemma states that the quaternion group of order eight is an extraspecial group.*)\nLemma Q8_extraspecial : extraspecial 'Q_8.\n\n(*This lemma provides a specification for the central product of the group denoted 'D^' n and the quaternion group of order eight, defining the resulting group type.*)\nLemma DnQ_P n : xcprod_spec 'D^n 'Q_8 ('D^n*Q)%type.\n\n(*This lemma states that the cardinality of the central product group denoted as 'D^' n * 'Q' is equal to two raised to the power of two times the successor of n plus one.*)\nLemma card_DnQ n : #|'D^n*Q| = (2 ^ n.+1.*2.+1)%N.\n\n(*This lemma states that for any natural number n, the group formed by the central product of n copies of the dihedral group of order 8 and one copy of the quaternion group of order 8 is a 2-group, meaning the order of every element is a power of two.*)\nLemma DnQ_pgroup n : 2.-group 'D^n*Q.\n\n(*This lemma states that for any natural number n, the group formed by the central product of n copies of the dihedral group of order 8 and one copy of the quaternion group of order 8 is an extraspecial group.*)\nLemma DnQ_extraspecial n : extraspecial 'D^n*Q.\n\n(*This lemma states that any finite extraspecial group of order 8 must be isomorphic to either the dihedral group of order 8 or the quaternion group of order 8.*)\nLemma card_isog8_extraspecial (gT : finGroupType) (G : {group gT}) :\n #|G| = 8 -> extraspecial G -> (G \\isog 'D_8) || (G \\isog 'Q_8).\n\n(*This lemma states that for any natural number n, an extraspecial 2-group with an order of two raised to the power of (two times n plus one) is isomorphic to either the central product of n copies of the dihedral group of order 8, or the central product of n minus one copies of the dihedral group of order 8 and one copy of the quaternion group of order 8.*)\nLemma isog_2extraspecial (gT : finGroupType) (G : {group gT}) n :\n #|G| = (2 ^ n.*2.+1)%N -> extraspecial G -> G \\isog 'D^n \\/ G \\isog 'D^n.-1*Q.\n\n(*This lemma states that for any natural number n, the 2-rank of the group formed by the central product of n copies of the dihedral group of order 8 is equal to n plus one.*)\nLemma rank_Dn n : 'r_2('D^n) = n.+1.\n\n(*This lemma states that for any natural number n, the 2-rank of the group formed by the central product of n copies of the dihedral group of order 8 and one copy of the quaternion group of order 8 is equal to n plus one.*)\nLemma rank_DnQ n : 'r_2('D^n*Q) = n.+1.\n\n(*This lemma states that for any natural number n, the two distinct families of extraspecial 2-groups of the same order are not isomorphic. Specifically, it asserts that the central product of n plus one copies of the dihedral group of order 8 is not isomorphic to the central product of n copies of the dihedral group of order 8 and one copy of the quaternion group of order 8.*)\nLemma not_isog_Dn_DnQ n : ~~ ('D^n \\isog 'D^n.-1*Q).", - "solvable.sylow": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import fintype prime bigop finset fingroup morphism.\nFrom mathcomp Require Import automorphism quotient action cyclic gproduct .\nFrom mathcomp Require Import gfunctor commutator pgroup center nilpotent.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection ModP.\n\nVariable (aT : finGroupType) (sT : finType) (D : {group aT}).\nVariable to : action D sT.\n\n(*This lemma states that if a finite group, which is a p-group for some natural number p, acts on a finite set, then the size of the finite set is congruent to the size of its subset of fixed points under the group action, modulo p.*)\nLemma pgroup_fix_mod (p : nat) (G : {group aT}) (S : {set sT}) :\n p.-group G -> [acts G, on S | to] -> #|S| = #|'Fix_(S | to)(G)| %[mod p].\n\nEnd ModP.\n\nSection ModularGroupAction.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (R : {group rT}).\nVariables (to : groupAction D R) (p : nat).\nImplicit Types (G H : {group aT}) (M : {group rT}).\n\n(*This lemma states that if a finite p-group acts on a non-trivial finite p-group, then the centralizer of the acting group within the target group is also non-trivial.*)\nLemma nontrivial_gacent_pgroup G M :\n p.-group G -> p.-group M -> {acts G, on group M | to} ->\n M :!=: 1 -> 'C_(M | to)(G) :!=: 1.\n\n(*This lemma states that if a finite group acts irreducibly on one of its p-subgroups, then the p-core of the acting group is a subgroup of the action stabilizer of the p-subgroup.*)\nLemma pcore_sub_astab_irr G M :\n p.-group M -> M \\subset R -> acts_irreducibly G M to ->\n 'O_p(G) \\subset 'C_G(M | to).\n\n(*This lemma states that if a finite group acts faithfully and irreducibly on one of its p-subgroups, then the p-core of the acting group is the trivial group.*)\nLemma pcore_faithful_irr_act G M :\n p.-group M -> M \\subset R -> acts_irreducibly G M to ->\n [faithful G, on M | to] ->\n 'O_p(G) = 1.\n\nEnd ModularGroupAction.\n\nSection Sylow.\n\nVariables (p : nat) (gT : finGroupType) (G : {group gT}).\nImplicit Types P Q H K : {group gT}.\n\n(*This theorem combines the main statements of Sylow's theorems for a finite group and a natural number p. It asserts four properties: first, that a subgroup is a maximal p-subgroup if and only if it is a Sylow p-subgroup; second, that the group acts transitively by conjugation on its set of Sylow p-subgroups; third, that for any Sylow p-subgroup, the total number of Sylow p-subgroups equals the index of its normalizer; and fourth, if p is prime, the number of Sylow p-subgroups is congruent to one, modulo p.*)\nTheorem Sylow's_theorem :\n [/\\ forall P, [max P | p.-subgroup(G) P] = p.-Sylow(G) P,\n [transitive G, on 'Syl_p(G) | 'JG],\n forall P, p.-Sylow(G) P -> #|'Syl_p(G)| = #|G : 'N_G(P)|\n & prime p -> #|'Syl_p(G)| %% p = 1%N].\n\n(*This lemma states that for any subgroup of a given finite group, being a maximal p-subgroup is equivalent to being a Sylow p-subgroup.*)\nLemma max_pgroup_Sylow P : [max P | p.-subgroup(G) P] = p.-Sylow(G) P.\n\n(*This lemma states that any p-subgroup of a given finite group is contained within some Sylow p-subgroup of that finite group.*)\nLemma Sylow_superset Q :\n Q \\subset G -> p.-group Q -> {P : {group gT} | p.-Sylow(G) P & Q \\subset P}.\n\n(*This lemma states that for any given finite group and any natural number p, there exists a Sylow p-subgroup.*)\nLemma Sylow_exists : {P : {group gT} | p.-Sylow(G) P}.\n\n(*This lemma states that a finite group acts transitively by conjugation on its set of Sylow p-subgroups.*)\nLemma Syl_trans : [transitive G, on 'Syl_p(G) | 'JG].\n\n(*This lemma states that any two Sylow p-subgroups of a given finite group are conjugate to each other.*)\nLemma Sylow_trans P Q :\n p.-Sylow(G) P -> p.-Sylow(G) Q -> exists2 x, x \\in G & Q :=: P :^ x.\n\n(*This lemma states that given a Sylow p-subgroup and any other p-subgroup of a finite group, there exists an element in the group such that the second p-subgroup is contained in the conjugate of the first Sylow p-subgroup by that element.*)\nLemma Sylow_subJ P Q :\n p.-Sylow(G) P -> Q \\subset G -> p.-group Q ->\n exists2 x, x \\in G & Q \\subset P :^ x.\n\n(*This lemma states that given a Sylow p-subgroup and any other p-subgroup of a finite group, there exists an element in the group such that the conjugate of the second p-subgroup by that element is contained in the first Sylow p-subgroup.*)\nLemma Sylow_Jsub P Q :\n p.-Sylow(G) P -> Q \\subset G -> p.-group Q ->\n exists2 x, x \\in G & Q :^ x \\subset P.\n\n(*This lemma states that for a Sylow p-subgroup of a finite group, the total number of Sylow p-subgroups is equal to the index of the normalizer of that subgroup.*)\nLemma card_Syl P : p.-Sylow(G) P -> #|'Syl_p(G)| = #|G : 'N_G(P)|.\n\n(*This lemma states that the number of Sylow p-subgroups of a finite group divides the order of that group.*)\nLemma card_Syl_dvd : #|'Syl_p(G)| %| #|G|.\n\n(*This lemma states that if p is a prime number, then the number of Sylow p-subgroups of a finite group is congruent to one, modulo p.*)\nLemma card_Syl_mod : prime p -> #|'Syl_p(G)| %% p = 1%N.\n\n(*This lemma states the Frattini argument: if a group G is a normal subgroup of another group H, and P is a Sylow p-subgroup of G, then H is equal to the product of G and the normalizer of P in H.*)\nLemma Frattini_arg H P : G <| H -> p.-Sylow(G) P -> G * 'N_H(P) = H.\n\nEnd Sylow.\n\nSection MoreSylow.\n\nVariables (gT : finGroupType) (p : nat).\nImplicit Types G H P : {group gT}.\n\n(*This lemma states that if a group G is a normal subgroup of another group H, and P is a Sylow p-subgroup of H, then the intersection of G and P is a Sylow p-subgroup of G.*)\nLemma Sylow_setI_normal G H P :\n G <| H -> p.-Sylow(H) P -> p.-Sylow(G) (G :&: P).\n\n(*This lemma states that there exists a normal Sylow p-subgroup in a finite group if and only if the number of Sylow p-subgroups is exactly one.*)\nLemma normal_sylowP G :\n reflect (exists2 P : {group gT}, p.-Sylow(G) P & P <| G)\n (#|'Syl_p(G)| == 1%N).\n\n(*This lemma states that if a finite p-group has a trivial center, then the group itself must be the trivial group.*)\nLemma trivg_center_pgroup P : p.-group P -> 'Z(P) = 1 -> P :=: 1.\n\n(*This lemma states that any finite p-group whose order is a power of p with exponent at most two is an abelian group.*)\nLemma p2group_abelian P : p.-group P -> logn p #|P| <= 2 -> abelian P.\n\n(*This lemma states that any group whose order is the square of a prime number is an abelian group.*)\nLemma card_p2group_abelian P : prime p -> #|P| = (p ^ 2)%N -> abelian P.\n\n(*This lemma states that a finite group is generated by the union of a set of its subgroups, provided that this set contains one Sylow p-subgroup for each prime p that divides the order of the group.*)\nLemma Sylow_transversal_gen (T : {set {group gT}}) G :\n (forall P, P \\in T -> P \\subset G) ->\n (forall p, p \\in \\pi(G) -> exists2 P, P \\in T & p.-Sylow(G) P) ->\n << \\bigcup_(P in T) P >> = G.\n\n(*This lemma states that any finite group is generated by the union of all its Sylow subgroups for all relevant primes.*)\nLemma Sylow_gen G : <<\\bigcup_(P : {group gT} | Sylow G P) P>> = G.\n\nEnd MoreSylow.\n\nSection SomeHall.\n\nVariable gT : finGroupType.\nImplicit Types (p : nat) (pi : nat_pred) (G H K P R : {group gT}).\n\n(*This lemma states that if H is a pi-Hall subgroup of a finite group G, where pi is a set of prime numbers, and p is a prime in pi, then any p-subgroup of G is conjugate to a subgroup of H.*)\nLemma Hall_pJsub p pi G H P :\n pi.-Hall(G) H -> p \\in pi -> P \\subset G -> p.-group P -> \n exists2 x, x \\in G & P :^ x \\subset H.\n\n(*This lemma states that if H is a pi-Hall subgroup of a finite group G, where pi is a set of prime numbers, and p is a prime in pi, then any p-subgroup of G is a subgroup of some conjugate of H.*)\nLemma Hall_psubJ p pi G H P :\n pi.-Hall(G) H -> p \\in pi -> P \\subset G -> p.-group P -> \n exists2 x, x \\in G & P \\subset H :^ x.\n\n(*This lemma states that if K is a normal subgroup of a finite group G and H is a pi-Hall subgroup of G, where pi is a set of prime numbers, then the intersection of H and K is a pi-Hall subgroup of K.*)\nLemma Hall_setI_normal pi G K H :\n K <| G -> pi.-Hall(G) H -> pi.-Hall(K) (H :&: K).\n\n(*This lemma states that if a finite group G, which normalizes a subgroup H, is the product of two subgroups K and R with coprime orders, then the intersection of G with H is equal to the product of the intersection of K with H and the intersection of R with H.*)\nLemma coprime_mulG_setI_norm H G K R :\n K * R = G -> G \\subset 'N(H) -> coprime #|K| #|R| ->\n (K :&: H) * (R :&: H) = G :&: H.\n\nEnd SomeHall.\n\nSection Nilpotent.\n\nVariable gT : finGroupType.\nImplicit Types (G H K P L : {group gT}) (p q : nat).\n\n(*This lemma states that any finite p-group is a nilpotent group.*)\nLemma pgroup_nil p P : p.-group P -> nilpotent P.\n\n(*This lemma states that any finite p-group is a solvable group.*)\nLemma pgroup_sol p P : p.-group P -> solvable P.\n\n(*This lemma states that if the nilpotency class of a finite group is a finite natural number, then the group is nilpotent.*)\nLemma small_nil_class G : nil_class G <= 5 -> nilpotent G.\n\n(*This lemma states that a group has a nilpotency class of at most two if and only if its derived subgroup is contained within its center.*)\nLemma nil_class2 G : (nil_class G <= 2) = (G^`(1) \\subset 'Z(G)).\n\n(*This lemma states that a group has a nilpotency class of at most three if and only if the third term of its lower central series is contained within its center.*)\nLemma nil_class3 G : (nil_class G <= 3) = ('L_3(G) \\subset 'Z(G)).\n\n(*This lemma states that in a nilpotent group, any maximal pi-subgroup is a normal subgroup, where pi is a given set of prime numbers.*)\nLemma nilpotent_maxp_normal pi G H :\n nilpotent G -> [max H | pi.-subgroup(G) H] -> H <| G.\n\n(*This lemma states that in a nilpotent group, any Hall pi-subgroup is equal to the pi-core of the group, where pi is a given set of prime numbers.*)\nLemma nilpotent_Hall_pcore pi G H :\n nilpotent G -> pi.-Hall(G) H -> H :=: 'O_pi(G).\n\n(*This lemma states that for any nilpotent group, its pi-core is a Hall pi-subgroup, where pi is a given set of prime numbers.*)\nLemma nilpotent_pcore_Hall pi G : nilpotent G -> pi.-Hall(G) 'O_pi(G).\n\n(*This lemma states that a nilpotent group is the internal direct product of its pi-core and its pi-prime-core, where pi is a given set of prime numbers.*)\nLemma nilpotent_pcoreC pi G : nilpotent G -> 'O_pi(G) \\x 'O_pi^'(G) = G.\n\n(*This lemma states that in a nilpotent group, any two subgroups with coprime orders centralize each other.*)\nLemma sub_nilpotent_cent2 H K G :\n nilpotent G -> K \\subset G -> H \\subset G -> coprime #|K| #|H| ->\n H \\subset 'C(K).\n\n(*This lemma states that for any nilpotent group, the set of prime divisors of the order of its center is equal to the set of prime divisors of the order of the group.*)\nLemma pi_center_nilpotent G : nilpotent G -> \\pi('Z(G)) = \\pi(G).\n\n(*This lemma states that a subgroup is a Sylow p-subgroup of a group if and only if it is a Sylow p-subgroup of its own normalizer within that group.*)\nLemma Sylow_subnorm p G P : p.-Sylow('N_G(P)) P = p.-Sylow(G) P.\n\nEnd Nilpotent.\n\n(*This lemma states that the nilpotency class of a p-group is less than or equal to the maximum of one and the base-p logarithm of its order, minus one.*)\nLemma nil_class_pgroup (gT : finGroupType) (p : nat) (P : {group gT}) :\n p.-group P -> nil_class P <= maxn 1 (logn p #|P|).-1.\n\n(*This definition states that a group is a Z-group if all of its Sylow subgroups are cyclic.*)\nDefinition Zgroup (gT : finGroupType) (A : {set gT}) :=\n [forall (V : {group gT} | Sylow A V), cyclic V].\n\nSection Zgroups.\n\nVariables (gT rT : finGroupType) (D : {group gT}) (f : {morphism D >-> rT}).\nImplicit Types G H K : {group gT}.\n\n(*This lemma states that any subgroup of a Z-group is also a Z-group.*)\nLemma ZgroupS G H : H \\subset G -> Zgroup G -> Zgroup H.\n\n(*This lemma states that the homomorphic image of a Z-group is also a Z-group.*)\nLemma morphim_Zgroup G : Zgroup G -> Zgroup (f @* G).\n\n(*This lemma states that a group that is both nilpotent and a Z-group must be cyclic.*)\nLemma nil_Zgroup_cyclic G : Zgroup G -> nilpotent G -> cyclic G.\n\nEnd Zgroups.\n\nArguments Zgroup {gT} A%_g.\n\nSection NilPGroups.\n\nVariables (p : nat) (gT : finGroupType).\nImplicit Type G P N : {group gT}.\n\n(*This lemma states that if a p-group has a normal subgroup, then for any power of the prime `p` that is less than or equal to the order of that normal subgroup, there exists a normal subgroup of the parent group with that exact order, which is contained within the original normal subgroup.*)\nLemma normal_pgroup r P N :\n p.-group P -> N <| P -> r <= logn p #|N| ->\n exists Q : {group gT}, [/\\ Q \\subset N, Q <| P & #|Q| = (p ^ r)%N].\n\n(*This theorem states that for a given finite group and a prime number, if the subgroup generated by a specific element and its conjugate by any element of the group is always a p-group, then that specific element must belong to the p-core of the group.*)\nTheorem Baer_Suzuki x G :\n x \\in G -> (forall y, y \\in G -> p.-group <<[set x; x ^ y]>>) ->\n x \\in 'O_p(G).", - "solvable.all_solvable": "From mathcomp Require Export abelian.\nFrom mathcomp Require Export alt.\nFrom mathcomp Require Export burnside_app.\nFrom mathcomp Require Export center.\nFrom mathcomp Require Export commutator.\nFrom mathcomp Require Export cyclic.\nFrom mathcomp Require Export extraspecial.\nFrom mathcomp Require Export extremal.\nFrom mathcomp Require Export finmodule.\nFrom mathcomp Require Export frobenius.\nFrom mathcomp Require Export gfunctor.\nFrom mathcomp Require Export gseries.\nFrom mathcomp Require Export hall.\nFrom mathcomp Require Export jordanholder.\nFrom mathcomp Require Export maximal.\nFrom mathcomp Require Export nilpotent.\nFrom mathcomp Require Export pgroup.\nFrom mathcomp Require Export primitive_action.", - "solvable.pgroup": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import fintype bigop finset prime fingroup morphism.\nFrom mathcomp Require Import gfunctor automorphism quotient action gproduct.\nFrom mathcomp Require Import cyclic.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope.\n\nSection PgroupDefs.\n\nVariable gT : finGroupType.\nImplicit Type (x : gT) (A B : {set gT}) (pi : nat_pred) (p n : nat).\n\n(*This definition checks if a given set is a pi-group, which holds true if every prime factor of the set's cardinality satisfies a given predicate on natural numbers.*)\nDefinition pgroup pi A := pi.-nat #|A|.\n\n(*This definition checks if a given set is a pi-subgroup of another set, which is true if it is a subset of the second set and all prime factors of its cardinality satisfy a given predicate on natural numbers.*)\nDefinition psubgroup pi A B := (B \\subset A) && pgroup pi B.\n\n(*This definition establishes a property of a set that is always true, asserting that any prime factor of the set's cardinality is a member of the set of all prime divisors of that same cardinality.*)\nDefinition p_group A := pgroup (pdiv #|A|) A.\n\n(*This definition checks if a given group element is a pi-element, which is true if every prime factor of the element's order satisfies a given predicate on natural numbers.*)\nDefinition p_elt pi x := pi.-nat #[x].\n\n(*This definition computes the pi-part of a group element. It does this by calculating an exponent using the Chinese Remainder Theorem on the pi-part and pi-prime-part of the element's order, and then raises the original element to this exponent to isolate its pi-component.*)\nDefinition constt x pi := x ^+ (chinese #[x]`_pi #[x]`_pi^' 1 0).\n\n(*This definition checks if a group is a Hall subgroup of another group. This is true if the first group is a subgroup of the second, and the order of the subgroup is coprime to its index in the supergroup.*)\nDefinition Hall A B := (B \\subset A) && coprime #|B| #|A : B|.\n\n(*This definition checks if a group is a Hall pi-subgroup of another group. This holds if it is a subgroup, its order is a pi-number, meaning all its prime factors satisfy the predicate pi, and its index is a pi-prime-number, meaning all its prime factors fail the predicate pi.*)\nDefinition pHall pi A B := [&& B \\subset A, pgroup pi B & pi^'.-nat #|A : B|].\n\n(*This definition describes the set of all Sylow p-subgroups of a given group for a specified prime p. A subgroup belongs to this set if its order is a power of p and its index in the parent group is not divisible by p.*)\nDefinition Syl p A := [set P : {group gT} | pHall p A P].\n\n(*This definition checks if a group is a Sylow subgroup of another group, which is equivalent to checking if it is a Hall subgroup. A Hall subgroup's order is coprime to its index in the larger group.*)\nDefinition Sylow A B := p_group B && Hall A B.\n\nEnd PgroupDefs.\n\nArguments pgroup {gT} pi%_N A%_g.\nArguments psubgroup {gT} pi%_N A%_g B%_g.\nArguments p_group {gT} A%_g.\nArguments p_elt {gT} pi%_N x.\nArguments constt {gT} x%_g pi%_N.\nArguments Hall {gT} A%_g B%_g.\nArguments pHall {gT} pi%_N A%_g B%_g.\nArguments Syl {gT} p%_N A%_g.\nArguments Sylow {gT} A%_g B%_g.\n\n(*A notation for a boolean predicate that is true if every prime factor of the cardinality of a given finite group satisfies a given predicate on natural numbers.*)\nNotation \"pi .-group\" := (pgroup pi)\n (at level 2, format \"pi .-group\") : group_scope.\n\n(*A notation for a predicate on a finite group that checks if it is a subgroup of a predefined group and if the prime factors of its order all satisfy a given predicate on natural numbers.*)\nNotation \"pi .-subgroup ( A )\" := (psubgroup pi A)\n (at level 8, format \"pi .-subgroup ( A )\") : group_scope.\n\n(*A notation for a boolean predicate that is true if every prime factor of the order of a given group element satisfies a given predicate on natural numbers.*)\nNotation \"pi .-elt\" := (p_elt pi)\n (at level 2, format \"pi .-elt\") : group_scope.\n\n(*A notation that computes the pi-part of a given group element. This operation yields the unique element whose order's prime factors all satisfy a given predicate, and which, when multiplied by a companion element whose order's prime factors do not satisfy the predicate, reconstitutes the original element.*)\nNotation \"x .`_ pi\" := (constt x pi)\n (at level 3, format \"x .`_ pi\") : group_scope.\n\n(*A notation for a predicate that determines if a finite group is a pi-Hall subgroup of another given group. This holds if the subgroup's order has prime factors all satisfying a given predicate, and the index of the subgroup has prime factors that all do not satisfy that predicate.*)\nNotation \"pi .-Hall ( G )\" := (pHall pi G)\n (at level 8, format \"pi .-Hall ( G )\") : group_scope.\n\n(*A notation for a predicate on a finite group that checks if it is a Sylow p-subgroup of a given group. A subgroup is a Sylow p-subgroup if its order is a power of a prime p and its index in the larger group is not divisible by p.*)\nNotation \"p .-Sylow ( G )\" := (nat_pred_of_nat p).-Hall(G)\n (at level 8, format \"p .-Sylow ( G )\") : group_scope.\n\n(*This notation represents the set of all Sylow p-subgroups of a given group G for a specified prime p.*)\nNotation \"''Syl_' p ( G )\" := (Syl p G)\n (at level 8, p at level 2, format \"''Syl_' p ( G )\") : group_scope.\n\nSection PgroupProps.\n\nVariable gT : finGroupType.\nImplicit Types (pi rho : nat_pred) (p : nat).\nImplicit Types (x y z : gT) (A B C D : {set gT}) (G H K P Q R : {group gT}).\n\n(*This lemma states that any finite group is either the trivial group or its order is divisible by at least one prime number.*)\nLemma trivgVpdiv G : G :=: 1 \\/ (exists2 p, prime p & p %| #|G|).\n\n(*This lemma states that for a group G whose order is a prime number, any other subgroup H of the same ambient group either contains G as a subgroup or intersects with G only at the trivial group.*)\nLemma prime_subgroupVti G H : prime #|G| -> G \\subset H \\/ H :&: G = 1.\n\n(*This lemma states that a set is a pi-group if and only if the cardinality of the set is a pi-number, meaning all its prime factors satisfy the predicate pi.*)\nLemma pgroupE pi A : pi.-group A = pi.-nat #|A|. \n\n(*This lemma states that if a predicate pi implies another predicate rho, then any pi-group is also a rho-group.*)\nLemma sub_pgroup pi rho A : {subset pi <= rho} -> pi.-group A -> rho.-group A.\n\n(*This lemma states that if two predicates on natural numbers are equivalent, then the property of being a pi-group is identical to the property of being a rho-group.*)\nLemma eq_pgroup pi rho A : pi =i rho -> pi.-group A = rho.-group A.\n\n(*This lemma states that if two predicates are equivalent, their complementary predicates also define identical group properties; specifically, being a pi-prime-group is the same as being a rho-prime-group.*)\nLemma eq_p'group pi rho A : pi =i rho -> pi^'.-group A = rho^'.-group A.\n\n(*This lemma states that being a pi-prime-prime-group is equivalent to being a pi-group, as the complement of a predicate's complement is the original predicate.*)\nLemma pgroupNK pi A : pi^'^'.-group A = pi.-group A.\n\n(*This lemma states that if a set is a p-group, meaning its cardinality is a power of a prime p, and the predicate pi holds for that prime p, then the set is also a pi-group.*)\nLemma pi_pgroup p pi A : p.-group A -> p \\in pi -> pi.-group A.\n\n(*This lemma states that if a set is a pi-group, and a given prime p does not satisfy the predicate pi, then the set must also be a p-prime-group, which means its cardinality is not divisible by p.*)\nLemma pi_p'group p pi A : pi.-group A -> p \\in pi^' -> p^'.-group A.\n\n(*This lemma states that if a set is a pi-prime-group, and a prime p satisfies the predicate pi, then the set must also be a p-prime-group, meaning its cardinality is not divisible by p.*)\nLemma pi'_p'group p pi A : pi^'.-group A -> p \\in pi -> p^'.-group A.\n\n(*This lemma provides an equivalence for a group being a p-prime-group, stating this is true if and only if the prime p does not divide the group's order.*)\nLemma p'groupEpi p G : p^'.-group G = (p \\notin \\pi(G)).\n\n(*This lemma states the tautological property that any group G is a pi-group when pi is taken to be the predicate identifying the prime divisors of the order of G.*)\nLemma pgroup_pi G : \\pi(G).-group G.\n\n(*This lemma establishes that the pi-part of a group's order is equal to one if and only if the group is a pi-prime-group, meaning none of the prime factors of its order satisfy the predicate pi.*)\nLemma partG_eq1 pi G : (#|G|`_pi == 1%N) = pi^'.-group G.\n\n(*This lemma provides a predicate-based characterization of a pi-group, stating that a group is a pi-group if and only if every prime number that divides the group's order satisfies the predicate pi.*)\nLemma pgroupP pi G :\n reflect (forall p, prime p -> p %| #|G| -> p \\in pi) (pi.-group G).\n\nArguments pgroupP {pi G}.\n\n(*This lemma states that the trivial group is a pi-group for any given set of prime numbers pi.*)\nLemma pgroup1 pi : pi.-group [1 gT].\n\n(*This lemma states that if a finite group is a pi-group for a given set of prime numbers pi, then any of its subgroups is also a pi-group for the same set of primes.*)\nLemma pgroupS pi G H : H \\subset G -> pi.-group G -> pi.-group H.\n\n(*This lemma states that if a finite group has an odd order, then any of its subgroups also has an odd order.*)\nLemma oddSg G H : H \\subset G -> odd #|G| -> odd #|H|.\n\n(*This lemma states that if a finite group is a p-group for an odd prime number p, then the order of the group is also odd.*)\nLemma odd_pgroup_odd p G : odd p -> p.-group G -> odd #|G|.\n\n(*This lemma states that if a finite group is a p-group for a prime number p, its order is equal to p raised to the power of the p-adic logarithm of its order.*)\nLemma card_pgroup p G : p.-group G -> #|G| = (p ^ logn p #|G|)%N.\n\n(*This lemma states that for a finite p-group, the p-adic logarithm of the order of any of its proper subgroups is strictly less than the p-adic logarithm of the order of the group itself.*)\nLemma properG_ltn_log p G H :\n p.-group G -> H \\proper G -> logn p #|H| < logn p #|G|.\n\n(*This lemma states that the direct product of two finite groups is a pi-group for a given set of prime numbers pi if and only if both constituent groups are also pi-groups for the same set of primes.*)\nLemma pgroupM pi G H : pi.-group (G * H) = pi.-group G && pi.-group H.\n\n(*This lemma states that a finite group is a pi-group for a given set of prime numbers pi if and only if any of its conjugate subgroups is also a pi-group for the same set of primes.*)\nLemma pgroupJ pi G x : pi.-group (G :^ x) = pi.-group G.\n\n(*This lemma states that a finite group whose order is a power of a prime number p also satisfies an alternative, equivalent definition of a p-group.*)\nLemma pgroup_p p P : p.-group P -> p_group P.\n\n(*This lemma states that if a finite group is a p-group, then there exists a prime number p such that the group's order is a power of p.*)\nLemma p_groupP P : p_group P -> exists2 p, prime p & p.-group P.\n\n(*This lemma states that for any non-trivial finite p-group, the number p is prime, it divides the order of the group, and the order of the group is equal to p raised to some positive integer power.*)\nLemma pgroup_pdiv p G :\n p.-group G -> G :!=: 1 ->\n [/\\ prime p, p %| #|G| & exists m, #|G| = p ^ m.+1]%N.\n\n(*This lemma states that if the orders of two finite groups are coprime, and the second group is a non-trivial p-group for some prime p, then the first group is a p-prime-group, meaning its order is not divisible by p.*)\nLemma coprime_p'group p K R :\n coprime #|K| #|R| -> p.-group R -> R :!=: 1 -> p^'.-group K.\n\n(*This lemma states that if a subgroup is a pi-Hall subgroup of a finite group for a given set of primes pi, then the order of the subgroup is equal to the pi-part of the order of the larger group.*)\nLemma card_Hall pi G H : pi.-Hall(G) H -> #|H| = #|G|`_pi.\n\n(*This lemma states that if a group is a pi-Hall subgroup of another finite group, it is necessarily a subgroup of that group.*)\nLemma pHall_sub pi A B : pi.-Hall(A) B -> B \\subset A.\n\n(*This lemma states that any pi-Hall subgroup of a finite group is itself a pi-group for the same set of prime numbers pi.*)\nLemma pHall_pgroup pi A B : pi.-Hall(A) B -> pi.-group B.\n\n(*This lemma provides a reflection, stating that a subgroup is a pi-Hall subgroup of a finite group if and only if it is a subgroup whose order equals the pi-part of the order of the larger group.*)\nLemma pHallP pi G H : reflect (H \\subset G /\\ #|H| = #|G|`_pi) (pi.-Hall(G) H).\n\n(*This lemma provides a boolean equality stating that a group is a pi-Hall subgroup of another finite group if and only if it is a subgroup and its order is equal to the pi-part of the order of the ambient group.*)\nLemma pHallE pi G H : pi.-Hall(G) H = (H \\subset G) && (#|H| == #|G|`_pi).\n\n(*This lemma states that if a finite group is the direct product of a pi-group and a pi-prime-group, then the first factor is a pi-Hall subgroup and the second factor is a pi-prime-Hall subgroup of the product group.*)\nLemma coprime_mulpG_Hall pi G K R :\n K * R = G -> pi.-group K -> pi^'.-group R ->\n pi.-Hall(G) K /\\ pi^'.-Hall(G) R.\n\n(*This lemma states that if a finite group is the direct product of a pi-prime-group and a pi-group, then the first factor is a pi-prime-Hall subgroup and the second factor is a pi-Hall subgroup of the product group.*)\nLemma coprime_mulGp_Hall pi G K R :\n K * R = G -> pi^'.-group K -> pi.-group R ->\n pi^'.-Hall(G) K /\\ pi.-Hall(G) R.\n\n(*This lemma asserts that the property of a subgroup being a Hall subgroup is identical for two sets of prime numbers, provided that these two sets are equivalent when considering only the prime divisors of the order of the ambient group.*)\nLemma eq_in_pHall pi rho G H :\n {in \\pi(G), pi =i rho} -> pi.-Hall(G) H = rho.-Hall(G) H.\n\n(*This lemma states that if two sets of prime numbers are equivalent, then the property of a subgroup being a Hall subgroup for the first set is the same as for the second set.*)\nLemma eq_pHall pi rho G H : pi =i rho -> pi.-Hall(G) H = rho.-Hall(G) H.\n\n(*This lemma states that if two sets of prime numbers are equivalent, then the property of a subgroup being a Hall subgroup for the complement of the first set is the same as for the complement of the second set.*)\nLemma eq_p'Hall pi rho G H : pi =i rho -> pi^'.-Hall(G) H = rho^'.-Hall(G) H.\n\n(*This lemma states that being a Hall subgroup with respect to the double complement of a set of primes is equivalent to being a Hall subgroup with respect to the original set of primes.*)\nLemma pHallNK pi G H : pi^'^'.-Hall(G) H = pi.-Hall(G) H.\n\n(*This lemma shows transitivity for Hall subgroups: if a first group is a rho-Hall subgroup of a second, and a third group is a pi-Hall subgroup of the first, where the set of primes pi is a subset of rho, then the third group is a pi-Hall subgroup of the second.*)\nLemma subHall_Hall pi rho G H K :\n rho.-Hall(G) H -> {subset pi <= rho} -> pi.-Hall(H) K -> pi.-Hall(G) K.\n\n(*This lemma states that if a subgroup is a p-Sylow subgroup of a pi-Hall subgroup of a larger group, and the prime p is in the set pi, then that subgroup is also a p-Sylow subgroup of the larger group.*)\nLemma subHall_Sylow pi p G H P :\n pi.-Hall(G) H -> p \\in pi -> p.-Sylow(H) P -> p.-Sylow(G) P.\n\n(*This lemma states that any pi-Hall subgroup of a finite group is also a Hall subgroup, meaning the order of the subgroup and its index in the larger group are coprime.*)\nLemma pHall_Hall pi A B : pi.-Hall(A) B -> Hall A B.\n\n(*This lemma shows that any Hall subgroup of a finite group is also a pi-Hall subgroup, where the set of primes pi is taken to be the set of all prime divisors of the order of the Hall subgroup itself.*)\nLemma Hall_pi G H : Hall G H -> \\pi(H).-Hall(G) H.\n\n(*This lemma states that for any Hall subgroup of a finite group, there exists a set of prime numbers for which it is a pi-Hall subgroup.*)\nLemma HallP G H : Hall G H -> exists pi, pi.-Hall(G) H.\n\n(*This lemma states that if a finite group is the semidirect product of two subgroups, then one subgroup is a Hall subgroup of the group if and only if the other subgroup is also a Hall subgroup.*)\nLemma sdprod_Hall G K H : K ><| H = G -> Hall G K = Hall G H.\n\n(*This lemma provides an equivalence for a group that is a semidirect product: the orders of the two factor subgroups are coprime if and only if the first factor is a Hall subgroup of the product group.*)\nLemma coprime_sdprod_Hall_l G K H : K ><| H = G -> coprime #|K| #|H| = Hall G K.\n\n(*This lemma states that if the semidirect product of two subgroups equals the entire group, then the property that the orders of these subgroups are coprime is equivalent to the second subgroup being a Hall subgroup of the entire group.*)\nLemma coprime_sdprod_Hall_r G K H : K ><| H = G -> coprime #|K| #|H| = Hall G H.\n\n(*This lemma states that if a subgroup K is a pi-Hall subgroup of a group G, then another subgroup H being a complement to K in G is equivalent to H being a pi-complement-Hall subgroup of G.*)\nLemma compl_pHall pi K H G :\n pi.-Hall(G) K -> (H \\in [complements to K in G]) = pi^'.-Hall(G) H.\n\n(*This lemma states that if a subgroup K is a pi-complement-Hall subgroup of a group G, then another subgroup H being a complement to K in G is equivalent to H being a pi-Hall subgroup of G.*)\nLemma compl_p'Hall pi K H G :\n pi^'.-Hall(G) K -> (H \\in [complements to K in G]) = pi.-Hall(G) H.\n\n(*This lemma states that for a normal subgroup K and a pi-complement-Hall subgroup H of a group G, the assertion that their semidirect product equals G is equivalent to the assertion that K is a pi-Hall subgroup of G.*)\nLemma sdprod_normal_p'HallP pi K H G :\n K <| G -> pi^'.-Hall(G) H -> reflect (K ><| H = G) (pi.-Hall(G) K).\n\n(*This lemma states that for a normal subgroup K and a pi-Hall subgroup H of a group G, the assertion that their semidirect product equals G is equivalent to the assertion that K is a pi-complement-Hall subgroup of G.*)\nLemma sdprod_normal_pHallP pi K H G :\n K <| G -> pi.-Hall(G) H -> reflect (K ><| H = G) (pi^'.-Hall(G) K).\n\n(*This lemma states that a subgroup is a pi-Hall subgroup of a group if and only if its conjugate is a pi-Hall subgroup of the conjugated group.*)\nLemma pHallJ2 pi G H x : pi.-Hall(G :^ x) (H :^ x) = pi.-Hall(G) H.\n\n(*This lemma states that if an element belongs to the normalizer of a group, then a subgroup is a pi-Hall subgroup if and only if its conjugate by that element is also a pi-Hall subgroup.*)\nLemma pHallJnorm pi G H x : x \\in 'N(G) -> pi.-Hall(G) (H :^ x) = pi.-Hall(G) H.\n\n(*This lemma states that for any element within a group, the property of a given subgroup being a pi-Hall subgroup is equivalent to its conjugate by that element also being a pi-Hall subgroup.*)\nLemma pHallJ pi G H x : x \\in G -> pi.-Hall(G) (H :^ x) = pi.-Hall(G) H.\n\n(*This lemma states that for any element within a group, a subgroup is a Hall subgroup if and only if its conjugate by that element is also a Hall subgroup.*)\nLemma HallJ G H x : x \\in G -> Hall G (H :^ x) = Hall G H.\n\n(*This lemma states that for any element within a group, a subgroup is a pi-subgroup if and only if its conjugate by that element is also a pi-subgroup.*)\nLemma psubgroupJ pi G H x :\n x \\in G -> pi.-subgroup(G) (H :^ x) = pi.-subgroup(G) H.\n\n(*This lemma states that the property of a group being a p-group is invariant under conjugation.*)\nLemma p_groupJ P x : p_group (P :^ x) = p_group P.\n\n(*This lemma states that for any element within a group, a subgroup is a Sylow subgroup if and only if its conjugate by that element is also a Sylow subgroup.*)\nLemma SylowJ G P x : x \\in G -> Sylow G (P :^ x) = Sylow G P.\n\n(*This lemma states that if a subgroup is a p-Sylow subgroup of a group for some prime number, then it is a Sylow subgroup of that group.*)\nLemma p_Sylow p G P : p.-Sylow(G) P -> Sylow G P.\n\n(*This lemma states that if a subgroup H is a pi-Hall subgroup of a group G and is contained within an intermediate subgroup K, then H is also a pi-Hall subgroup of K.*)\nLemma pHall_subl pi G K H :\n H \\subset K -> K \\subset G -> pi.-Hall(G) H -> pi.-Hall(K) H.\n\n(*This lemma states that the trivial subgroup, containing only the identity element, is always a Hall subgroup of any given group.*)\nLemma Hall1 G : Hall G 1.\n\n(*This lemma states that the trivial subgroup is a p-group for any prime number.*)\nLemma p_group1 : @p_group gT 1.\n\n(*This lemma states that the trivial subgroup is always a Sylow subgroup of any given group.*)\nLemma Sylow1 G : Sylow G 1.\n\n(*This lemma establishes the equivalence between a subgroup being a Sylow subgroup of a group and the existence of a prime number for which it is a corresponding p-Sylow subgroup.*)\nLemma SylowP G P : reflect (exists2 p, prime p & p.-Sylow(G) P) (Sylow G P).\n\n(*This lemma states that an element raised to an integer power is a pi-element if and only if the pi-complement part of the original element's order divides the exponent.*)\nLemma p_elt_exp pi x m : pi.-elt (x ^+ m) = (#[x]`_pi^' %| m).\n\n(*This lemma states that any element belonging to a pi-group is a pi-element.*)\nLemma mem_p_elt pi x G : pi.-group G -> x \\in G -> pi.-elt x.\n\n(*This lemma states that if two elements are pi-elements, and the first element is in the normalizer of the cyclic group generated by the second, then their product is also a pi-element.*)\nLemma p_eltM_norm pi x y :\n x \\in 'N(<[y]>) -> pi.-elt x -> pi.-elt y -> pi.-elt (x * y).\n\n(*This lemma states that if two commuting elements are both pi-elements, their product is also a pi-element.*)\nLemma p_eltM pi x y : commute x y -> pi.-elt x -> pi.-elt y -> pi.-elt (x * y).\n\n(*This lemma states that the identity element of a group is a pi-element for any given set of prime numbers.*)\nLemma p_elt1 pi : pi.-elt (1 : gT).\n\n(*This lemma states that an element is a pi-element if and only if its inverse is also a pi-element.*)\nLemma p_eltV pi x : pi.-elt x^-1 = pi.-elt x.\n\n(*This lemma states that if an element is a pi-element, then any of its integer powers is also a pi-element.*)\nLemma p_eltX pi x n : pi.-elt x -> pi.-elt (x ^+ n).\n\n(*This lemma states that an element is a pi-element if and only if any of its conjugates is also a pi-element.*)\nLemma p_eltJ pi x y : pi.-elt (x ^ y) = pi.-elt x.\n\n(*This lemma states that if an element is a pi-one-element for a given set of primes, it is also a pi-two-element for any superset of those primes.*)\nLemma sub_p_elt pi1 pi2 x : {subset pi1 <= pi2} -> pi1.-elt x -> pi2.-elt x.\n\n(*This lemma states that for two equal sets of prime numbers, the property of an element being a pi-element is the same for both sets.*)\nLemma eq_p_elt pi1 pi2 x : pi1 =i pi2 -> pi1.-elt x = pi2.-elt x.\n\n(*This lemma states that an element is a pi-double-complement-element if and only if it is a pi-element, as the double complement of a set of primes is the set itself.*)\nLemma p_eltNK pi x : pi^'^'.-elt x = pi.-elt x.\n\n(*This lemma states that if two sets of prime numbers are equal, then the pi-part of the order of any given element is the same with respect to both sets.*)\nLemma eq_constt pi1 pi2 x : pi1 =i pi2 -> x.`_pi1 = x.`_pi2.\n\n(*This lemma states that taking the component of a group element with respect to the complement of the complement of a prime predicate is the same as taking the component with respect to the original prime predicate.*)\nLemma consttNK pi x : x.`_pi^'^' = x.`_pi.\n\n(*This lemma states that the pi-component of a group element is a member of the cyclic subgroup generated by that same element.*)\nLemma cycle_constt pi x : x.`_pi \\in <[x]>.\n\n(*This lemma asserts that the pi-component of the inverse of a group element is equal to the inverse of the pi-component of that element.*)\nLemma consttV pi x : (x^-1).`_pi = (x.`_pi)^-1.\n\n(*This lemma states that the pi-component of the identity element of a group is the identity element itself.*)\nLemma constt1 pi : 1.`_pi = 1 :> gT.\n\n(*This lemma states that the pi-component of an element conjugated by another element is equal to the pi-component of the original element, conjugated by that same other element.*)\nLemma consttJ pi x y : (x ^ y).`_pi = x.`_pi ^ y.\n\n(*This lemma asserts that the pi-component of any group element is itself a pi-element, meaning the order of the component is a pi-number.*)\nLemma p_elt_constt pi x : pi.-elt x.`_pi.\n\n(*This lemma states that any group element can be expressed as the product of its pi-component and its pi-prime component.*)\nLemma consttC pi x : x.`_pi * x.`_pi^' = x.\n\n(*This lemma asserts that the product of a group element with the inverse of its pi-component results in a pi-prime element.*)\nLemma p'_elt_constt pi x : pi^'.-elt (x * (x.`_pi)^-1).\n\n(*This lemma states that the order of the pi-component of a group element is equal to the pi-part of the order of the original element.*)\nLemma order_constt pi (x : gT) : #[x.`_pi] = #[x]`_pi.\n\n(*This lemma states that if two group elements commute, the pi-component of their product is the product of their individual pi-components.*)\nLemma consttM pi x y : commute x y -> (x * y).`_pi = x.`_pi * y.`_pi.\n\n(*This lemma states that the pi-component of a group element raised to an integer power is equal to the pi-component of that element raised to the same power.*)\nLemma consttX pi x n : (x ^+ n).`_pi = x.`_pi ^+ n.\n\n(*This lemma provides a reflection property, stating that the pi-component of a group element is the identity element if and only if the element itself is a pi-prime element.*)\nLemma constt1P pi x : reflect (x.`_pi = 1) (pi^'.-elt x).\n\n(*This lemma states that if a group element is a pi-element, then its pi-component is the element itself.*)\nLemma constt_p_elt pi x : pi.-elt x -> x.`_pi = x.\n\n(*This lemma states that if a prime predicate `pi1` is a subset of another prime predicate `pi2` on the set of prime factors of the order of an element, then taking the `pi1`-component of the `pi2`-component of that element is equivalent to just taking the `pi1`-component of the element.*)\nLemma sub_in_constt pi1 pi2 x :\n {in \\pi(#[x]), {subset pi1 <= pi2}} -> x.`_pi2.`_pi1 = x.`_pi1.\n\n(*This lemma states that any group element can be recovered by taking the product of its p-components over all prime numbers `p` that are relevant to its order.*)\nLemma prod_constt x : \\prod_(0 <= p < #[x].+1) x.`_p = x.\n\n(*This lemma states that if `M` is a maximal pi-subgroup of a group `G`, then any conjugate of `M` by an element of `G` is also a maximal pi-subgroup of `G`.*)\nLemma max_pgroupJ pi M G x :\n x \\in G -> [max M | pi.-subgroup(G) M] ->\n [max M :^ x of M | pi.-subgroup(G) M].\n\n(*This lemma states that if `M` is a maximal pi-subgroup of `G` and `H` is any pi-subgroup of `G` that commutes with `M`, then `H` must be contained in `M`.*)\nLemma comm_sub_max_pgroup pi H M G :\n [max M | pi.-subgroup(G) M] -> pi.-group H -> H \\subset G ->\n commute H M -> H \\subset M.\n\n(*This lemma asserts that any normal pi-subgroup of a group `G` is contained within every maximal pi-subgroup of `G`.*)\nLemma normal_sub_max_pgroup pi H M G :\n [max M | pi.-subgroup(G) M] -> pi.-group H -> H <| G -> H \\subset M.\n\n(*This lemma states that if `M` is a maximal pi-subgroup of a group `G`, and `H` is a pi-subgroup of `G` that normalizes `M`, then `H` must be a subgroup of `M`.*)\nLemma norm_sub_max_pgroup pi H M G :\n [max M | pi.-subgroup(G) M] -> pi.-group H -> H \\subset G ->\n H \\subset 'N(M) -> H \\subset M.\n\n(*This lemma asserts that a Hall pi-subgroup is maximal among all pi-subgroups. Specifically, if `H` is a Hall pi-subgroup of `G`, any pi-subgroup `K` of `G` that contains `H` must be equal to `H`.*)\nLemma sub_pHall pi H G K :\n pi.-Hall(G) H -> pi.-group K -> H \\subset K -> K \\subset G -> K :=: H.\n\n(*This lemma states that any Hall pi-subgroup of a group `G` is also a maximal pi-subgroup of `G`.*)\nLemma Hall_max pi H G : pi.-Hall(G) H -> [max H | pi.-subgroup(G) H].\n\n(*This lemma states that if a group `G` is itself a pi-group, then its only Hall pi-subgroup is `G` itself.*)\nLemma pHall_id pi H G : pi.-Hall(G) H -> pi.-group G -> H :=: G.\n\n(*This lemma states that the trivial subgroup, containing only the identity element, is always a pi-subgroup of any given group.*)\nLemma psubgroup1 pi G : pi.-subgroup(G) 1.\n\n(*This lemma states Cauchy's theorem: if a prime number `p` divides the order of a finite group `G`, then there exists an element in `G` of order `p`.*)\nLemma Cauchy p G : prime p -> p %| #|G| -> {x | x \\in G & #[x] = p}.\n\n(*This lemma establishes an equivalence for a normal Hall pi-subgroup `H` of a group `G`: a subgroup `K` of `G` is contained in `H` if and only if `K` is a pi-group.*)\nLemma sub_normal_Hall pi G H K :\n pi.-Hall(G) H -> H <| G -> K \\subset G -> (K \\subset H) = pi.-group K.\n\n(*This lemma states that for a normal Hall pi-subgroup `H` of a group `G`, an element from `G` belongs to `H` if and only if that element is a pi-element.*)\nLemma mem_normal_Hall pi H G x :\n pi.-Hall(G) H -> H <| G -> x \\in G -> (x \\in H) = pi.-elt x.\n\n(*This lemma proves the uniqueness of a normal Hall pi-subgroup: if `H` is a normal Hall pi-subgroup of `G`, then it is the only maximal pi-subgroup of `G`.*)\nLemma uniq_normal_Hall pi H G K :\n pi.-Hall(G) H -> H <| G -> [max K | pi.-subgroup(G) K] -> K :=: H.\n\nEnd PgroupProps.\n\nArguments pgroupP {gT pi G}.\nArguments constt1P {gT pi x}.\n\nSection NormalHall.\n\nVariables (gT : finGroupType) (pi : nat_pred).\nImplicit Types G H K : {group gT}.\n\n(*This lemma states that if a subgroup of a group is both a maximal pi-subgroup and a normal subgroup, then it must be a Hall pi-subgroup.*)\nLemma normal_max_pgroup_Hall G H :\n [max H | pi.-subgroup(G) H] -> H <| G -> pi.-Hall(G) H.\n\n(*This lemma states that if `H` is a normal Hall pi-subgroup of `G`, then for any subgroup `K` of `G`, the intersection of `H` and `K` forms a Hall pi-subgroup within `K`.*)\nLemma setI_normal_Hall G H K :\n H <| G -> pi.-Hall(G) H -> K \\subset G -> pi.-Hall(K) (H :&: K).\n\nEnd NormalHall.\n\nSection Morphim.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\nImplicit Types (pi : nat_pred) (G H P : {group aT}).\n\n(*This lemma asserts that the homomorphic image of a pi-group under a group morphism is also a pi-group.*)\nLemma morphim_pgroup pi G : pi.-group G -> pi.-group (f @* G).\n\n(*This lemma states that if a finite group has an odd number of elements, then the image of that group under a group morphism also has an odd number of elements.*)\nLemma morphim_odd G : odd #|G| -> odd #|f @* G|.\n\n(*This lemma states that for a group morphism, if the kernel of the morphism is a pi-group for a given predicate on natural numbers, then the image of a group is a pi-group if and only if the original group is a pi-group.*)\nLemma pmorphim_pgroup pi G :\n pi.-group ('ker f) -> G \\subset D -> pi.-group (f @* G) = pi.-group G.\n\n(*This lemma states that for a group morphism, if the index of a subgroup within a group is a pi-number for a given predicate on natural numbers, then the index of the image of the subgroup within the image of the group is also a pi-number.*)\nLemma morphim_p_index pi G H :\n H \\subset D -> pi.-nat #|G : H| -> pi.-nat #|f @* G : f @* H|.\n\n(*This lemma states that the image of a pi-Hall subgroup of a given group under a group morphism is a pi-Hall subgroup of the image of that group.*)\nLemma morphim_pHall pi G H :\n H \\subset D -> pi.-Hall(G) H -> pi.-Hall(f @* G) (f @* H).\n\n(*This lemma states that for a group morphism, a subgroup's image is a pi-Hall subgroup of the group's image if and only if the original subgroup is a pi-Hall subgroup of the original group, under the condition that the intersection of the group and the subgroup is a pi-subgroup contained within the kernel of the morphism.*)\nLemma pmorphim_pHall pi G H :\n G \\subset D -> H \\subset D -> pi.-subgroup(H :&: G) ('ker f) ->\n pi.-Hall(f @* G) (f @* H) = pi.-Hall(G) H.\n\n(*This lemma states that the image of a Hall subgroup under a group morphism is a Hall subgroup of the image of the group.*)\nLemma morphim_Hall G H : H \\subset D -> Hall G H -> Hall (f @* G) (f @* H).\n\n(*This lemma states that for a given prime number, the image of a Sylow p-subgroup of a group under a group morphism is a Sylow p-subgroup of the image of the group.*)\nLemma morphim_pSylow p G P :\n P \\subset D -> p.-Sylow(G) P -> p.-Sylow(f @* G) (f @* P).\n\n(*This lemma states that for a given prime number, the image of a p-group under a group morphism is also a p-group.*)\nLemma morphim_p_group P : p_group P -> p_group (f @* P).\n\n(*This lemma states that the image of a Sylow subgroup of a group under a group morphism is a Sylow subgroup of the image of the group.*)\nLemma morphim_Sylow G P : P \\subset D -> Sylow G P -> Sylow (f @* G) (f @* P).\n\n(*This lemma states that for a given predicate on natural numbers, the image of a pi-element under a group morphism is also a pi-element.*)\nLemma morph_p_elt pi x : x \\in D -> pi.-elt x -> pi.-elt (f x).\n\n(*This lemma states that for a group morphism and a predicate on natural numbers, applying the morphism to the pi-part of an element yields the same result as taking the pi-part of the element's image.*)\nLemma morph_constt pi x : x \\in D -> f x.`_pi = (f x).`_pi.\n\nEnd Morphim.\n\nSection Pquotient.\n\nVariables (pi : nat_pred) (gT : finGroupType) (p : nat) (G H K : {group gT}).\nHypothesis piK : pi.-group K.\n\n(*This lemma states that for a given predicate on natural numbers, the quotient of a pi-group by one of its normal subgroups is also a pi-group.*)\nLemma quotient_pgroup : pi.-group (K / H). \n\n(*This lemma states that if a subgroup is a pi-Hall subgroup of a larger group, and it normalizes another subgroup, then its quotient by that other subgroup is a pi-Hall subgroup of the corresponding quotient of the larger group.*)\nLemma quotient_pHall :\n K \\subset 'N(H) -> pi.-Hall(G) K -> pi.-Hall(G / H) (K / H).\n\n(*This lemma states that if a finite group has an odd number of elements, then any of its quotient groups also has an odd number of elements.*)\nLemma quotient_odd : odd #|K| -> odd #|K / H|. \n\n(*This lemma states that for a group and one of its normal subgroups which is a pi-group, the quotient group is a pi-group if and only if the original group is a pi-group.*)\nLemma pquotient_pgroup : G \\subset 'N(K) -> pi.-group (G / K) = pi.-group G.\n\n(*This lemma states that for a group that has a normal pi-subgroup, another subgroup containing the normal pi-subgroup is a pi-Hall subgroup if and only if its corresponding quotient subgroup is a pi-Hall subgroup of the quotient group.*)\nLemma pquotient_pHall :\n K <| G -> K <| H -> pi.-Hall(G / K) (H / K) = pi.-Hall(G) H.\n\n(*This lemma states that for a nontrivial subgroup of a finite p-group, the p-logarithm of the index of the subgroup is strictly smaller than the p-logarithm of the order of the group.*)\nLemma ltn_log_quotient :\n p.-group G -> H :!=: 1 -> H \\subset G -> logn p #|G / H| < logn p #|G|.\n\nEnd Pquotient.\n\nSection InnerAutCyclicPgroup.\n\nVariables (gT : finGroupType) (p : nat) (G C : {group gT}).\nHypothesis nCG : G \\subset 'N(C).\n\n(*This lemma provides an upper bound for the p-logarithm of the order of a quotient group. It states that for a group that normalizes a cyclic p-subgroup, the p-logarithm of the order of the quotient of the group by the centralizer of the cyclic p-subgroup is less than or equal to the p-logarithm of the cyclic subgroup's order, minus one.*)\nLemma logn_quotient_cent_cyclic_pgroup : \n p.-group C -> cyclic C -> logn p #|G / 'C_G(C)| <= (logn p #|C|).-1.\n\n(*This lemma states that if a group normalizes a subgroup of prime order p, then the quotient of the group by the centralizer of that subgroup is a p-prime group, meaning its order is not divisible by p.*)\nLemma p'group_quotient_cent_prime :\n prime p -> #|C| %| p -> p^'.-group (G / 'C_G(C)).\n\nEnd InnerAutCyclicPgroup.\n\nSection PcoreDef.\n\nVariables (pi : nat_pred) (gT : finGroupType) (A : {set gT}).\n\n(*This definition specifies the pi-core of a set as the intersection of all maximal pi-subgroups of that set, where pi is a given predicate on natural numbers.*)\nDefinition pcore := \\bigcap_(G | [max G | pi.-subgroup(A) G]) G.\n\nCanonical pcore_group : {group gT} := Eval hnf in [group of pcore].\n\nEnd PcoreDef.\n\nArguments pcore pi%_N {gT} A%_g.\nArguments pcore_group pi%_N {gT} A%_G.\n(*This notation denotes the pi-core of a group for a given predicate on natural numbers, which is defined as the intersection of all maximal pi-subgroups of the group.*)\nNotation \"''O_' pi ( G )\" := (pcore pi G)\n (at level 8, pi at level 2, format \"''O_' pi ( G )\") : group_scope.\n(*This notation represents the `pi`-core of a group G. The `pi`-core is defined as the largest normal subgroup of G whose order is a `pi`-number. A `pi`-number is an integer whose prime factors all satisfy the given predicate `pi`.*)\nNotation \"''O_' pi ( G )\" := (pcore_group pi G) : Group_scope.\n\nSection PseriesDefs.\n\nVariables (pis : seq nat_pred) (gT : finGroupType) (A : {set gT}).\n\n(*This definition computes a subgroup of a group `A`, determined by a predicate on natural numbers `pi` and a normal subgroup `B` of `A`. The resulting subgroup is the complete preimage in `A` of the `pi`-core of the quotient group `A` divided by `B`.*)\nDefinition pcore_mod pi B := coset B @*^-1 'O_pi(A / B).\nCanonical pcore_mod_group pi B : {group gT} :=\n Eval hnf in [group of pcore_mod pi B].\n\n(*This definition constructs a characteristic subgroup of a given finite group by iteratively building an upper `pi`-series. It takes a finite sequence of predicates on natural numbers and a group. The resulting subgroup is obtained by starting with the trivial subgroup and repeatedly applying the `pcore_mod` construction for each predicate in the reversed input sequence.*)\nDefinition pseries := foldr pcore_mod 1 (rev pis).\n\n(*This lemma states that the set of group elements constructed by the `pseries` function forms a valid subgroup of the ambient finite group.*)\nLemma pseries_group_set : group_set pseries.\n\nCanonical pseries_group : {group gT} := group pseries_group_set.\n\nEnd PseriesDefs.\n\nArguments pseries pis%_SEQ {gT} _%_g.\nLocal Notation ConsPred p := (@Cons nat_pred p%N) (only parsing).\n(*This notation defines a characteristic subgroup of a given finite group `A`, which is constructed using a sequence of predicates on natural numbers, from `p1` to `pn`. The resulting subgroup is built up in steps. The first step identifies the largest normal subgroup of `A` whose order is composed of prime numbers satisfying the first predicate `p1`. The second step finds a larger subgroup such that its quotient by the first subgroup is the largest normal subgroup of the corresponding quotient of `A` whose order is composed of primes satisfying `p2`. This process continues for all predicates in the sequence, and the notation represents the final subgroup obtained after the step for `pn`.*)\nNotation \"''O_{' p1 , .. , pn } ( A )\" :=\n (pseries (ConsPred p1 .. (ConsPred pn [::]) ..) A)\n (at level 8, format \"''O_{' p1 , .. , pn } ( A )\") : group_scope.\n(**)\nNotation \"''O_{' p1 , .. , pn } ( A )\" :=\n (pseries_group (ConsPred p1 .. (ConsPred pn [::]) ..) A) : Group_scope.\n\nSection PCoreProps.\n\nVariables (pi : nat_pred) (gT : finGroupType).\nImplicit Types (A : {set gT}) (G H M K : {group gT}).\n\n(*This lemma states that the pi-core of a given group is a pi-subgroup of that group, meaning its order is a product of primes satisfying the given predicate.*)\nLemma pcore_psubgroup G : pi.-subgroup(G) 'O_pi(G).\n\n(*This lemma states that the pi-core of any group, when considered as a group in its own right, is a pi-group.*)\nLemma pcore_pgroup G : pi.-group 'O_pi(G).\n\n(*This lemma states that the pi-core of a group is a subgroup of that group.*)\nLemma pcore_sub G : 'O_pi(G) \\subset G.\n\n(*This lemma states that for a given group, its pi-core is a subgroup of any of its pi-Hall subgroups.*)\nLemma pcore_sub_Hall G H : pi.-Hall(G) H -> 'O_pi(G) \\subset H.\n\n(*This lemma states that any normal pi-subgroup of a given group is a subgroup of the pi-core of that group, establishing the pi-core as the largest such subgroup.*)\nLemma pcore_max G H : pi.-group H -> H <| G -> H \\subset 'O_pi(G).\n\n(*This lemma states that if a group is a pi-group, then its pi-core is the group itself.*)\nLemma pcore_pgroup_id G : pi.-group G -> 'O_pi(G) = G.\n\n(*This lemma states that the pi-core of a group is a normal subgroup of that group.*)\nLemma pcore_normal G : 'O_pi(G) <| G.\n\n(*This lemma states that a normal pi-Hall subgroup of a group is equal to the pi-core of that group.*)\nLemma normal_Hall_pcore H G : pi.-Hall(G) H -> H <| G -> 'O_pi(G) = H.\n\n(*This lemma states that if the pi-core of a group is a pi-Hall subgroup, then any other pi-Hall subgroup is conjugate to the pi-core.*)\nLemma eq_Hall_pcore G H :\n pi.-Hall(G) 'O_pi(G) -> pi.-Hall(G) H -> H :=: 'O_pi(G).\n\n(*This lemma states that if the pi-core of a group is also a pi-Hall subgroup, then another subgroup is contained in the pi-core if and only if it is a pi-group.*)\nLemma sub_Hall_pcore G K :\n pi.-Hall(G) 'O_pi(G) -> K \\subset G -> (K \\subset 'O_pi(G)) = pi.-group K.\n\n(*This lemma states that if the pi-core of a group is also a pi-Hall subgroup, then an element belongs to the pi-core if and only if it is a pi-element.*)\nLemma mem_Hall_pcore G x :\n pi.-Hall(G) 'O_pi(G) -> x \\in G -> (x \\in 'O_pi(G)) = pi.-elt x.\n\n(*This lemma provides a reflection property stating that if the pi-core of a group is a pi-Hall subgroup, then the group is a semidirect product of its pi-core and another subgroup if and only if that other subgroup is a pi-complement Hall subgroup.*)\nLemma sdprod_Hall_pcoreP H G :\n pi.-Hall(G) 'O_pi(G) -> reflect ('O_pi(G) ><| H = G) (pi^'.-Hall(G) H).\n\n(*This lemma provides a reflection property stating that if a subgroup of a group is a pi-complement Hall subgroup, then the group is a semidirect product of its pi-core and that subgroup if and only if the pi-core is a pi-Hall subgroup.*)\nLemma sdprod_pcore_HallP H G :\n pi^'.-Hall(G) H -> reflect ('O_pi(G) ><| H = G) (pi.-Hall(G) 'O_pi(G)).\n\n(*This lemma states that the pi-core of a conjugate group is the conjugate of the pi-core of the original group.*)\nLemma pcoreJ G x : 'O_pi(G :^ x) = 'O_pi(G) :^ x.\n\nEnd PCoreProps.\n\nSection MorphPcore.\n\nImplicit Types (pi : nat_pred) (gT rT : finGroupType).\n\n(*This lemma states that the pi-core construction is a pcontinuous group functor, meaning the image of the pi-core of a group under a morphism is a subgroup of the pi-core of the image group.*)\nLemma morphim_pcore pi : GFunctor.pcontinuous (@pcore pi).\n\n(*This lemma states that for any subgroup of a given group, the intersection of the subgroup with the pi-core of the larger group is itself a subgroup of the pi-core of the subgroup.*)\nLemma pcoreS pi gT (G H : {group gT}) :\n H \\subset G -> H :&: 'O_pi(G) \\subset 'O_pi(H).\n\nCanonical pcore_igFun pi := [igFun by pcore_sub pi & morphim_pcore pi].\nCanonical pcore_gFun pi := [gFun by morphim_pcore pi].\nCanonical pcore_pgFun pi := [pgFun by morphim_pcore pi].\n\n(*This lemma states that the pi-core of a group is a characteristic subgroup of that group.*)\nLemma pcore_char pi gT (G : {group gT}) : 'O_pi(G) \\char G.\n\nSection PcoreMod.\n\nVariable F : GFunctor.pmap.\n\n(*This lemma states that the modular pi-core of a group with respect to a given subgroup functor is a subgroup of the original group.*)\nLemma pcore_mod_sub pi gT (G : {group gT}) : pcore_mod G pi (F _ G) \\subset G.\n\n(*This lemma states that for a group and a normal subgroup, the quotient of the modular pi-core of the group by that normal subgroup is equal to the pi-core of the corresponding quotient group.*)\nLemma quotient_pcore_mod pi gT (G : {group gT}) (B : {set gT}) :\n pcore_mod G pi B / B = 'O_pi(G / B).\n\n(*This lemma states that the image of a modular pi-core under a group morphism is a subgroup of the modular pi-core of the image group.*)\nLemma morphim_pcore_mod pi gT rT (D G : {group gT}) (f : {morphism D >-> rT}) :\n f @* pcore_mod G pi (F _ G) \\subset pcore_mod (f @* G) pi (F _ (f @* G)).\n\n(*This lemma states that the modular pi-core construction is compatible with group morphisms, such that the image of a modular pi-core is a subgroup of the modular pi-core of the image group.*)\nLemma pcore_mod_res pi gT rT (D : {group gT}) (f : {morphism D >-> rT}) :\n f @* pcore_mod D pi (F _ D) \\subset pcore_mod (f @* D) pi (F _ (f @* D)).\n\n(*This lemma states that the modular pi-core of a group with respect to the trivial subgroup is equal to the standard pi-core of the group.*)\nLemma pcore_mod1 pi gT (G : {group gT}) : pcore_mod G pi 1 = 'O_pi(G).\n\nEnd PcoreMod.\n\n(*This lemma gives the recursive definition of the p-series of a group, where the p-series for a list of prime predicates is defined as the modular pi-core of the group with respect to the p-series generated by the initial predicates, and where pi is the last predicate.*)\nLemma pseries_rcons pi pis gT (A : {set gT}) :\n pseries (rcons pis pi) A = pcore_mod A pi (pseries pis A).\n\n(*This lemma states that for a fixed list of prime predicates, the p-series operator is both a closed and a pcontinuous group functor.*)\nLemma pseries_subfun pis :\n GFunctor.closed (@pseries pis) /\\ GFunctor.pcontinuous (@pseries pis).\n\n(*This lemma states that the p-series operator is a closed group functor, meaning the p-series of a group is always a subgroup of that group.*)\nLemma pseries_sub pis : GFunctor.closed (@pseries pis).\n\n(*This lemma states that the p-series operator is a pcontinuous group functor, meaning it is compatible with group morphisms where the image of a p-series is a subgroup of the p-series of the image group.*)\nLemma morphim_pseries pis : GFunctor.pcontinuous (@pseries pis).\n\n(*This lemma states that the p-series operator is a hereditary group functor, meaning the intersection of a subgroup with the p-series of a larger group is a subgroup of the p-series of the subgroup.*)\nLemma pseriesS pis : GFunctor.hereditary (@pseries pis).\n\nCanonical pseries_igFun pis := [igFun by pseries_sub pis & morphim_pseries pis].\nCanonical pseries_gFun pis := [gFun by morphim_pseries pis].\nCanonical pseries_pgFun pis := [pgFun by morphim_pseries pis].\n\n(*This lemma states that the p-series of a group is a characteristic subgroup of that group.*)\nLemma pseries_char pis gT (G : {group gT}) : pseries pis G \\char G.\n\n(*This lemma states that the p-series of a group is a normal subgroup of that group.*)\nLemma pseries_normal pis gT (G : {group gT}) : pseries pis G <| G.\n\n(*This lemma states that for any group, any list of sets of prime numbers, and any element, computing the p-series of the group after conjugating it by the element yields the same result as first computing the p-series of the original group and then conjugating the resulting subgroup by that same element.*)\nLemma pseriesJ pis gT (G : {group gT}) x :\n pseries pis (G :^ x) = pseries pis G :^ x.\n\n(*This lemma states that the p-series of a group, corresponding to a list containing a single set of prime numbers, is identical to the p-core of that group with respect to the same set of primes.*)\nLemma pseries1 pi gT (G : {group gT}) : 'O_{pi}(G) = 'O_pi(G).\n\n(*This lemma states that for a given group, if its pi-core with respect to a set of prime numbers is trivial, then computing the p-series with a list of prime sets starting with that set 'pi' yields the same subgroup as computing the p-series with the list of prime sets excluding that initial 'pi'.*)\nLemma pseries_pop pi pis gT (G : {group gT}) :\n 'O_pi(G) = 1 -> pseries (pi :: pis) G = pseries pis G.\n\n(*This lemma states that if the pi1-core of a group is the trivial group, then its p-series for the sequence of prime sets [pi1, pi2] is identical to its pi2-core.*)\nLemma pseries_pop2 pi1 pi2 gT (G : {group gT}) :\n 'O_pi1(G) = 1 -> 'O_{pi1, pi2}(G) = 'O_pi2(G).\n\n(*This lemma states that for any group and two lists of sets of prime numbers, the p-series of the group corresponding to the first list is a subgroup of the p-series corresponding to the concatenation of the first list followed by the second list.*)\nLemma pseries_sub_catl pi1s pi2s gT (G : {group gT}) :\n pseries pi1s G \\subset pseries (pi1s ++ pi2s) G.\n\n(*This lemma states that for a group, a list of sets of prime numbers, and an additional set of primes 'pi', the quotient group formed by the p-series for the list extended with 'pi' and the p-series for the original list is equal to the pi-core of the quotient group formed by the original group and the p-series for the original list.*)\nLemma quotient_pseries pis pi gT (G : {group gT}) :\n pseries (rcons pis pi) G / pseries pis G = 'O_pi(G / pseries pis G).\n\n(*This lemma states that for any group and any two lists of sets of prime numbers, the p-series of the group corresponding to the second list is a subgroup of the normalizer of the p-series corresponding to the first list.*)\nLemma pseries_norm2 pi1s pi2s gT (G : {group gT}) :\n pseries pi2s G \\subset 'N(pseries pi1s G).\n\n(*This lemma states that for any group and two lists of sets of prime numbers, the p-series of the group corresponding to the second list is a subgroup of the p-series corresponding to the concatenation of the first list followed by the second list.*)\nLemma pseries_sub_catr pi1s pi2s gT (G : {group gT}) :\n pseries pi2s G \\subset pseries (pi1s ++ pi2s) G.\n\n(*This lemma states that for a group and two sets of prime numbers, pi1 and pi2, the quotient group of the p-series for the sequence [pi1, pi2] by the pi1-core of the group is equal to the pi2-core of the quotient group of the original group by its pi1-core.*)\nLemma quotient_pseries2 pi1 pi2 gT (G : {group gT}) :\n 'O_{pi1, pi2}(G) / 'O_pi1(G) = 'O_pi2(G / 'O_pi1(G)).\n\n(*This lemma states that for a group and two lists of prime sets, the quotient group formed by the p-series for their concatenation and the p-series for the first list is equal to the p-series of the quotient group, where the latter p-series is computed with respect to the second list and the quotient is taken over the p-series of the first list.*)\nLemma quotient_pseries_cat pi1s pi2s gT (G : {group gT}) :\n pseries (pi1s ++ pi2s) G / pseries pi1s G\n = pseries pi2s (G / pseries pi1s G).\n\n(*This lemma states that for a group and two lists of sets of prime numbers, computing the p-series for the first list on the subgroup that is the p-series for the concatenated list yields the same result as computing the p-series for the first list on the original group.*)\nLemma pseries_catl_id pi1s pi2s gT (G : {group gT}) :\n pseries pi1s (pseries (pi1s ++ pi2s) G) = pseries pi1s G.\n\n(*This lemma states that for any group and two lists of sets of prime numbers, the p-series corresponding to the first list is a characteristic subgroup of the p-series corresponding to the concatenation of the two lists.*)\nLemma pseries_char_catl pi1s pi2s gT (G : {group gT}) :\n pseries pi1s G \\char pseries (pi1s ++ pi2s) G.\n\n(*This lemma states that for a group and two lists of sets of prime numbers, computing the p-series for the second list on the subgroup that is the p-series for the concatenated list yields the same result as computing the p-series for the second list on the original group.*)\nLemma pseries_catr_id pi1s pi2s gT (G : {group gT}) :\n pseries pi2s (pseries (pi1s ++ pi2s) G) = pseries pi2s G.\n\n(*This lemma states that for any group and two lists of sets of prime numbers, the p-series corresponding to the second list is a characteristic subgroup of the p-series corresponding to the concatenation of the two lists.*)\nLemma pseries_char_catr pi1s pi2s gT (G : {group gT}) :\n pseries pi2s G \\char pseries (pi1s ++ pi2s) G.\n\n(*This lemma states that for a group G and a normal subgroup H, if H is a pi-group for a given set of primes pi, then the subgroup of G corresponding to the pi-core of the quotient group G by H is equal to the pi-core of G.*)\nLemma pcore_modp pi gT (G H : {group gT}) :\n H <| G -> pi.-group H -> pcore_mod G pi H = 'O_pi(G).\n\n(*This lemma states that if a subgroup H of a group G is normal and is a pi-group for a given set of primes, then the pi-core of the quotient group G by H is equal to the quotient of the pi-core of G by H.*)\nLemma pquotient_pcore pi gT (G H : {group gT}) :\n H <| G -> pi.-group H -> 'O_pi(G / H) = 'O_pi(G) / H.\n\n(*This lemma states that for any group and any set of prime numbers, the pi-core of the quotient group of the group by its own pi-core is the trivial group.*)\nLemma trivg_pcore_quotient pi gT (G : {group gT}) : 'O_pi(G / 'O_pi(G)) = 1.\n\n(*This lemma states an idempotency property for p-series construction: for a list of sets of prime numbers, the p-series of a group remains unchanged if a set of primes is appended to the list when that same set is already the last element of the list.*)\nLemma pseries_rcons_id pis pi gT (G : {group gT}) :\n pseries (rcons (rcons pis pi) pi) G = pseries (rcons pis pi) G.\n\nEnd MorphPcore.\n\nSection EqPcore.\n\nVariables gT : finGroupType.\nImplicit Types (pi rho : nat_pred) (G H : {group gT}).\n\n(*This lemma states that for a finite group, if for every prime number dividing the order of the group, a first predicate on primes implies a second predicate, then the p-core corresponding to the first predicate is a subgroup of the p-core corresponding to the second.*)\nLemma sub_in_pcore pi rho G :\n {in \\pi(G), {subset pi <= rho}} -> 'O_pi(G) \\subset 'O_rho(G).\n\n(*This lemma states that if a first predicate on prime numbers implies a second predicate for all primes, then for any finite group, its p-core with respect to the first predicate is a subgroup of its p-core with respect to the second.*)\nLemma sub_pcore pi rho G : {subset pi <= rho} -> 'O_pi(G) \\subset 'O_rho(G).\n\n(*This lemma states that if two predicates on prime numbers are equivalent for all prime numbers that divide the order of a finite group, then the p-cores of that group with respect to these two predicates are identical.*)\nLemma eq_in_pcore pi rho G : {in \\pi(G), pi =i rho} -> 'O_pi(G) = 'O_rho(G).\n\n(*This lemma states that if two predicates on prime numbers are equivalent, then for any finite group, their corresponding p-cores are identical.*)\nLemma eq_pcore pi rho G : pi =i rho -> 'O_pi(G) = 'O_rho(G).\n\n(*This lemma states that the p-core of a finite group with respect to the double complement of a predicate on prime numbers is identical to the p-core of the group with respect to the original predicate.*)\nLemma pcoreNK pi G : 'O_pi^'^'(G) = 'O_pi(G).\n\n(*This lemma states that if two predicates on prime numbers are equivalent, then for any finite group, the p-cores with respect to their complementary predicates are also identical.*)\nLemma eq_p'core pi rho G : pi =i rho -> 'O_pi^'(G) = 'O_rho^'(G).\n\n(*This lemma states that if the pi-complement-core of a finite group is also a pi-complement-Hall subgroup, then another subgroup is a pi-Hall subgroup if and only if the group can be expressed as the semidirect product of its pi-complement-core and that other subgroup.*)\nLemma sdprod_Hall_p'coreP pi H G :\n pi^'.-Hall(G) 'O_pi^'(G) -> reflect ('O_pi^'(G) ><| H = G) (pi.-Hall(G) H).\n\n(*This lemma states that if a subgroup of a finite group is a pi-Hall subgroup, then the group's pi-complement-core is a pi-complement-Hall subgroup if and only if the group can be expressed as the semidirect product of its pi-complement-core and the given pi-Hall subgroup.*)\nLemma sdprod_p'core_HallP pi H G :\n pi.-Hall(G) H -> reflect ('O_pi^'(G) ><| H = G) (pi^'.-Hall(G) 'O_pi^'(G)).\n\n(*This lemma shows how p-cores interact: the p-core of a finite group with respect to the conjunction of two predicates on primes is equal to the p-core taken with respect to the first predicate, applied to the subgroup that is the p-core with respect to the second predicate.*)\nLemma pcoreI pi rho G : 'O_[predI pi & rho](G) = 'O_pi('O_rho(G)).\n\n(*This lemma states that the pi-complement-core of a finite group is equal to the intersection of all p-complement-cores, where p ranges over all prime numbers that satisfy the predicate pi.*)\nLemma bigcap_p'core pi G :\n G :&: \\bigcap_(p < #|G|.+1 | (p : nat) \\in pi) 'O_p^'(G) = 'O_pi^'(G).\n\n(*This lemma states that for any two finite groups, the order of the pi-core of the first group is coprime to the order of the pi-complement-core of the second group, for any given set of prime numbers pi.*)\nLemma coprime_pcoreC (rT : finGroupType) pi G (R : {group rT}) :\n coprime #|'O_pi(G)| #|'O_pi^'(R)|.\n\n(*This lemma states that for any two subgroups of a common ambient group, the intersection of the pi-core of the first subgroup and the pi-complement-core of the second subgroup is the trivial group.*)\nLemma TI_pcoreC pi G H : 'O_pi(G) :&: 'O_pi^'(H) = 1.\n\n(*This lemma states that for any finite group and one of its normal subgroups, the intersection of the pi-core of the group with the normal subgroup is equal to the pi-core of that normal subgroup.*)\nLemma pcore_setI_normal pi G H : H <| G -> 'O_pi(G) :&: H = 'O_pi(H).\n\nEnd EqPcore.\n\nArguments sdprod_Hall_pcoreP {pi gT H G}.\nArguments sdprod_Hall_p'coreP {gT pi H G}.\n\nSection Injm.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\nHypothesis injf : 'injm f.\nImplicit Types (A : {set aT}) (G H : {group aT}).\n\n(*This lemma states that for an injective group morphism, a subset of its domain generates a pi-group if and only if the image of that subset under the morphism also generates a pi-group.*)\nLemma injm_pgroup pi A : A \\subset D -> pi.-group (f @* A) = pi.-group A.\n\n(*This lemma states that for an injective group morphism, an element in its domain is a pi-element if and only if its image under the morphism is also a pi-element.*)\nLemma injm_pelt pi x : x \\in D -> pi.-elt (f x) = pi.-elt x.\n\n(*This lemma states that for an injective group morphism, if a first group is a subgroup of a second group and both are within the morphism's domain, then the first group is a Hall pi-subgroup of the second if and only if the image of the first group is a Hall pi-subgroup of the image of the second group.*)\nLemma injm_pHall pi G H :\n G \\subset D -> H \\subset D -> pi.-Hall(f @* G) (f @* H) = pi.-Hall(G) H.\n\n(*This lemma states that for an injective group morphism, the image of the pi-core of a subgroup in its domain is equal to the pi-core of the image of that subgroup.*)\nLemma injm_pcore pi G : G \\subset D -> f @* 'O_pi(G) = 'O_pi(f @* G).\n\n(*This lemma states that for an injective group morphism, the image of the pi-series of a subgroup in its domain is equal to the pi-series of the image of that subgroup.*)\nLemma injm_pseries pis G :\n G \\subset D -> f @* pseries pis G = pseries pis (f @* G).\n\nEnd Injm.\n\nSection Isog.\n\nVariables (aT rT : finGroupType) (G : {group aT}) (H : {group rT}).\n\n(*This lemma states that if two finite groups are isomorphic, then one group is a pi-group if and only if the other group is also a pi-group.*)\nLemma isog_pgroup pi : G \\isog H -> pi.-group G = pi.-group H.\n\n(*This lemma states that if two finite groups are isomorphic, then their respective pi-cores are also isomorphic.*)\nLemma isog_pcore pi : G \\isog H -> 'O_pi(G) \\isog 'O_pi(H).\n\n(*This lemma states that if two finite groups are isomorphic, then their respective pi-series are also isomorphic, meaning each subgroup in the pi-series of the first group is isomorphic to the corresponding subgroup in the pi-series of the second group.*)\nLemma isog_pseries pis : G \\isog H -> pseries pis G \\isog pseries pis H.", - "field.closed_field": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype choice ssrnat seq.\nFrom mathcomp Require Import fintype generic_quotient bigop ssralg poly.\nFrom mathcomp Require Import polydiv matrix mxpoly countalg ring_quotient.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GRing.Theory.\nLocal Open Scope ring_scope.\n\nImport Pdiv.Ring.\nImport PreClosedField.\n\nModule ClosedFieldQE.\nSection ClosedFieldQE.\n\nVariables (F : fieldType) (F_closed : GRing.closed_field_axiom F).\n\n(*A notation for a logical formula over a field, which can include polynomial equations and inequalities.*)\nNotation fF := (@GRing.formula F).\n(*A notation for a formal polynomial expression, also known as a term, over a field.*)\nNotation tF := (@GRing.term F).\nNotation qf f := (GRing.qf_form f && GRing.rformula f).\n(*This definition represents a formal polynomial whose coefficients are themselves formal polynomial expressions. It is structured as a sequence of terms.*)\nDefinition polyF := seq tF.\n\n(*This lemma states that a formula possessing the quantifier-free and rational property can be decomposed into two separate properties: that the formula is quantifier-free in structure, and that all terms within it are rational.*)\nLemma qf_simpl (f : fF) :\n (qf f -> GRing.qf_form f) * (qf f -> GRing.rformula f).\n\nNotation cps T := ((T -> fF) -> fF).\n(*This function lifts a given value into a computation in continuation-passing style. The resulting computation simply passes the original value to its continuation.*)\nDefinition ret T1 : T1 -> cps T1 := fun x k => k x.\nArguments ret {T1} x k /.\n\n(*This function composes two computations in continuation-passing style. It runs the first computation, passes its result to a function that produces a second computation, and then executes this second computation.*)\nDefinition bind T1 T2 (x : cps T1) (f : T1 -> cps T2) : cps T2 :=\n fun k => x (fun x => f x k).\nArguments bind {T1 T2} x f k /.\n(*A notation for sequencing two computations in continuation-passing style. It executes the first computation, binds its result to a variable, and then executes the second computation within the scope of that variable.*)\nNotation \"''let' x <- y ; z\" :=\n (bind y (fun x => z)) (at level 99, x at level 0, y at level 0,\n format \"'[hv' ''let' x <- y ; '/' z ']'\").\n\n(*This function creates a conditional computation in continuation-passing style. The resulting computation, when executed, produces a logical 'if-then-else' formula using a given formula as the condition and providing one of two specified values to its continuation based on that condition.*)\nDefinition cpsif T (c : fF) (t : T) (e : T) : cps T :=\n fun k => GRing.If c (k t) (k e).\nArguments cpsif {T} c t e k /.\n(*A notation for a conditional expression within continuation-passing style. It builds a computation that will evaluate to one of two given values based on the truth of a logical formula.*)\nNotation \"''if' c1 'then' c2 'else' c3\" := (cpsif c1%T c2%T c3%T)\n (at level 200, right associativity, format\n\"'[hv ' ''if' c1 '/' '[' 'then' c2 ']' '/' '[' 'else' c3 ']' ']'\").\n\n(*A notation for the function that evaluates a formal term or formula within a given environment, which provides values for any variables.*)\nNotation eval := GRing.eval.\n(*A notation for the property that a formal term is rational, meaning that all of its variable indices are valid within a given context.*)\nNotation rterm := GRing.rterm.\n(*A notation for a function that evaluates a quantifier-free logical formula in a given environment, returning a boolean result.*)\nNotation qf_eval := GRing.qf_eval.\n\n(*This function evaluates a symbolic polynomial, which is represented by a sequence of formal term coefficients. It computes the concrete polynomial over a field by evaluating each coefficient term in a given environment.*)\nFixpoint eval_poly (e : seq F) pf :=\n if pf is c :: q then eval_poly e q * 'X + (eval e c)%:P else 0.\n\n(*This definition specifies the property that a symbolic polynomial is rational, which holds if all of its coefficient terms are rational.*)\nDefinition rpoly (p : polyF) := all (@rterm F) p.\n\n(*This function defines a computation in continuation-passing style that determines the size of a symbolic polynomial, which is a value related to its degree. The result is zero for the zero polynomial.*)\nDefinition sizeT : polyF -> cps nat := (fix loop p :=\n if p isn't c :: q then ret 0\n else 'let n <- loop q;\n if n is m.+1 then ret m.+2 else\n 'if (c == 0) then 0%N else 1%N).\n\n(*This definition specifies a reduction relation for computations in continuation-passing style. It asserts that a computation is semantically equivalent to a given function if their evaluations produce the same boolean result for all environments and continuations.*)\nDefinition qf_red_cps T (x : cps T) (y : _ -> T) :=\n forall e k, qf_eval e (x k) = qf_eval e (k (y e)).\n(*A notation indicating that a computation in continuation-passing style reduces to a specific value. It asserts that the computation is semantically equivalent to producing that value in any evaluation environment.*)\nNotation \"x ->_ e y\" := (qf_red_cps x (fun e => y))\n (e name, at level 90, format \"x ->_ e y\").\n\n(*This definition describes the property of a computation in continuation-passing style being 'quantifier-free preserving'. It holds if the computation produces a quantifier-free and rational formula whenever it is combined with a continuation that also preserves this property.*)\nDefinition qf_cps T D (x : cps T) :=\n forall k, (forall y, D y -> qf (k y)) -> qf (x k).\n\n(*This lemma states that lifting a value into a continuation-passing style computation preserves the 'quantifier-free preserving' property, provided the original value itself satisfies a given predicate.*)\nLemma qf_cps_ret T D (x : T) : D x -> qf_cps D (ret x).\n\nHint Resolve qf_cps_ret : core.\n\n(*This lemma states that composing two 'quantifier-free preserving' computations in continuation-passing style results in a new computation that also has this property.*)\nLemma qf_cps_bind T1 D1 T2 D2 (x : cps T1) (f : T1 -> cps T2) :\n qf_cps D1 x -> (forall x, D1 x -> qf_cps D2 (f x)) -> qf_cps D2 (bind x f).\n\n(*This lemma states that a conditional computation in continuation-passing style is 'quantifier-free preserving', provided the condition is a quantifier-free formula and both the 'then' and 'else' branch values satisfy a given predicate.*)\nLemma qf_cps_if T D (c : fF) (t : T) (e : T) : qf c -> D t -> D e ->\n qf_cps D ('if c then t else e).\n\n(*This lemma states that the symbolic computation for a polynomial's size correctly reduces to the actual size of the polynomial after its coefficient terms have been evaluated in an environment.*)\nLemma sizeTP (pf : polyF) : sizeT pf ->_e size (eval_poly e pf).\n\n(*This lemma states that the computation for the size of a rational symbolic polynomial is 'quantifier-free preserving', ensuring that the generated formula is quantifier-free.*)\nLemma sizeT_qf (p : polyF) : rpoly p -> qf_cps xpredT (sizeT p).\n\n(*This function defines a computation in continuation-passing style that determines whether a symbolic polynomial is the zero polynomial by checking if its computed size is zero.*)\nDefinition isnull (p : polyF) : cps bool :=\n 'let n <- sizeT p; ret (n == 0).\n\n(*This lemma states that the symbolic computation to check if a polynomial is null correctly reduces to a boolean that indicates whether the evaluated polynomial is indeed the zero polynomial.*)\nLemma isnullP (p : polyF) : isnull p ->_e (eval_poly e p == 0).\n\n(*This lemma states that the computation to check if a rational symbolic polynomial is null is 'quantifier-free preserving', ensuring that the generated formula is quantifier-free.*)\nLemma isnull_qf (p : polyF) : rpoly p -> qf_cps xpredT (isnull p).\n\n(*This function defines a computation in continuation-passing style that compares the sizes of two symbolic polynomials and returns a boolean indicating if the first polynomial's size is strictly less than the second's.*)\nDefinition lt_sizeT (p q : polyF) : cps bool :=\n 'let n <- sizeT p; 'let m <- sizeT q; ret (n < m).\n\n(*This function converts a concrete polynomial with coefficients from a field into a symbolic polynomial by mapping each coefficient to a constant formal term.*)\nDefinition lift (p : {poly F}) := map GRing.Const p.\n\n(*This lemma states that evaluating a symbolic polynomial that was created by lifting a concrete polynomial will yield the original concrete polynomial, irrespective of the evaluation environment.*)\nLemma eval_lift (e : seq F) (p : {poly F}) : eval_poly e (lift p) = p.\n\n(*This function defines a recursive computation in continuation-passing style that determines the leading coefficient of a symbolic polynomial, returning it as a formal term.*)\nFixpoint lead_coefT p : cps tF :=\n if p is c :: q then\n 'let l <- lead_coefT q; 'if (l == 0) then c else l\n else ret 0%T.\n\n(*This lemma states that under a certain evaluation-preserving condition for a term constructor function, evaluating a formal polynomial's leading coefficient term is equivalent to applying the term constructor to the leading coefficient of the evaluated polynomial.*)\nLemma lead_coefTP (k : tF -> fF) :\n (forall x e, qf_eval e (k x) = qf_eval e (k (eval e x)%:T%T)) ->\n forall (p : polyF) (e : seq F),\n qf_eval e (lead_coefT p k) = qf_eval e (k (lead_coef (eval_poly e p))%:T%T).\n\n(*This lemma states that if a given formal polynomial is regular, then the term representing its leading coefficient is a well-formed quotable form in continuation-passing style.*)\nLemma lead_coefT_qf (p : polyF) : rpoly p -> qf_cps (@rterm _) (lead_coefT p).\n\n(*This fixpoint definition constructs a formal polynomial representing a monomial, which is formed by multiplying a given term by the indeterminate raised to the power of a given natural number.*)\nFixpoint amulXnT (a : tF) (n : nat) : polyF :=\n if n is n'.+1 then 0%T :: (amulXnT a n') else [:: a].\n\n(*This lemma states that evaluating the formal polynomial created by `amulXnT` with a given term and a natural number yields a standard polynomial equal to the product of the evaluated term and the indeterminate raised to that natural number.*)\nLemma eval_amulXnT (a : tF) (n : nat) (e : seq F) :\n eval_poly e (amulXnT a n) = (eval e a)%:P * 'X^n.\n\n(*This lemma states that for any valid syntactic term and any natural number, the syntactic polynomial representing a monomial, constructed from that term as its coefficient and that natural number as its degree, is itself a valid syntactic polynomial.*)\nLemma ramulXnT: forall a n, rterm a -> rpoly (amulXnT a n).\n\n(*This fixpoint definition computes the sum of two formal polynomials by adding their corresponding coefficients element-wise.*)\nFixpoint sumpT (p q : polyF) :=\n match p, q with a :: p, b :: q => (a + b)%T :: sumpT p q\n | [::], q => q | p, [::] => p end.\nArguments sumpT : simpl nomatch.\n\n(*This lemma states that evaluating the sum of two formal polynomials is equivalent to adding the results of evaluating each polynomial individually.*)\nLemma eval_sumpT (p q : polyF) (e : seq F) :\n eval_poly e (sumpT p q) = (eval_poly e p) + (eval_poly e q).\n\n(*This lemma states that the sum of two regular formal polynomials is itself a regular polynomial.*)\nLemma rsumpT (p q : polyF) : rpoly p -> rpoly q -> rpoly (sumpT p q).\n\n(*This fixpoint definition computes the product of two formal polynomials using a recursive algorithm that multiplies the leading coefficient of the first polynomial with the second polynomial and adds this to the product of the tail of the first polynomial and the second polynomial, shifted by one degree.*)\nFixpoint mulpT (p q : polyF) :=\n if p isn't a :: p then [::]\n else sumpT [seq (a * x)%T | x <- q] (0%T :: mulpT p q).\n\n(*This lemma states that evaluating the product of two formal polynomials is equivalent to multiplying the results of evaluating each polynomial individually.*)\nLemma eval_mulpT (p q : polyF) (e : seq F) :\n eval_poly e (mulpT p q) = (eval_poly e p) * (eval_poly e q).\n\n(*This lemma states that the regularity of a formal polynomial is preserved when all of its coefficient terms are multiplied by a given regular term.*)\nLemma rpoly_map_mul (t : tF) (p : polyF) (rt : rterm t) :\n rpoly [seq (t * x)%T | x <- p] = rpoly p.\n\n(*This lemma states that the product of two regular formal polynomials is itself a regular polynomial.*)\nLemma rmulpT (p q : polyF) : rpoly p -> rpoly q -> rpoly (mulpT p q).\n\n(*This definition computes the additive inverse of a formal polynomial by negating each of its coefficient terms.*)\nDefinition opppT : polyF -> polyF := map (GRing.Mul (- 1%T)%T).\n\n(*This lemma states that evaluating the additive inverse of a formal polynomial is equivalent to taking the additive inverse of the result of evaluating the original polynomial.*)\nLemma eval_opppT (p : polyF) (e : seq F) :\n eval_poly e (opppT p) = - eval_poly e p.\n\n(*This definition computes the scalar product of a formal polynomial and a natural number by multiplying each coefficient term of the polynomial by the ring element corresponding to the natural number.*)\nDefinition natmulpT n : polyF -> polyF := map (GRing.Mul n%:R%T).\n\n(*This lemma states that evaluating a formal polynomial after it has been scaled by a natural number is equivalent to scaling the evaluation of the original polynomial by that same natural number.*)\nLemma eval_natmulpT (p : polyF) (n : nat) (e : seq F) :\n eval_poly e (natmulpT n p) = (eval_poly e p) *+ n.\n\n(*This fixpoint definition implements a bounded recursive loop in continuation-passing style for polynomial division. At each step, it updates the quotient and remainder, decrementing a counter, until the remainder's degree is less than the divisor's degree or the recursion bound is reached. It returns a tuple containing a counter, the final quotient, and the final remainder.*)\nFixpoint redivp_rec_loopT (q : polyF) sq cq (c : nat) (qq r : polyF)\n (n : nat) {struct n} : cps (nat * polyF * polyF) :=\n 'let sr <- sizeT r;\n if sr < sq then ret (c, qq, r) else\n 'let lr <- lead_coefT r;\n let m := amulXnT lr (sr - sq) in\n let qq1 := sumpT (mulpT qq [::cq]) m in\n let r1 := sumpT (mulpT r ([::cq])) (opppT (mulpT m q)) in\n if n is n1.+1 then redivp_rec_loopT q sq cq c.+1 qq1 r1 n1\n else ret (c.+1, qq1, r1).\n\n(*This fixpoint definition implements a bounded recursive loop for polynomial division on standard polynomials. It iteratively computes an updated quotient and remainder based on the leading terms, terminating when the remainder's degree is smaller than the divisor's degree or a recursion limit is met, and returns a tuple of a counter, the quotient, and the remainder.*)\nFixpoint redivp_rec_loop (q : {poly F}) sq cq\n (k : nat) (qq r : {poly F}) (n : nat) {struct n} :=\n if size r < sq then (k, qq, r) else\n let m := (lead_coef r) *: 'X^(size r - sq) in\n let qq1 := qq * cq%:P + m in\n let r1 := r * cq%:P - m * q in\n if n is n1.+1 then redivp_rec_loop q sq cq k.+1 qq1 r1 n1 else\n (k.+1, qq1, r1).\n\n(*This lemma states that, under a specific condition for the continuation, evaluating the result of the term-level polynomial division loop is equivalent to applying the continuation to the lifted results of the standard polynomial division loop performed on the evaluated inputs.*)\nLemma redivp_rec_loopTP (k : nat * polyF * polyF -> fF) :\n (forall c qq r e, qf_eval e (k (c,qq,r))\n = qf_eval e (k (c, lift (eval_poly e qq), lift (eval_poly e r))))\n -> forall q sq cq c qq r n e\n (d := redivp_rec_loop (eval_poly e q) sq (eval e cq)\n c (eval_poly e qq) (eval_poly e r) n),\n qf_eval e (redivp_rec_loopT q sq cq c qq r n k)\n = qf_eval e (k (d.1.1, lift d.1.2, lift d.2)).\n\n(*This lemma states that if the formal divisor, its leading coefficient term, the initial formal quotient, and the initial formal remainder are all regular, then the term-level polynomial division loop produces a result where the final formal quotient and formal remainder are also regular polynomials.*)\nLemma redivp_rec_loopT_qf (q : polyF) (sq : nat) (cq : tF)\n (c : nat) (qq r : polyF) (n : nat) :\n rpoly q -> rterm cq -> rpoly qq -> rpoly r ->\n qf_cps (fun x => [&& rpoly x.1.2 & rpoly x.2])\n (redivp_rec_loopT q sq cq c qq r n).\n\n(*This definition computes the pseudo-division of two formal polynomials in continuation-passing style. It returns a tuple containing a scaling factor, the formal quotient, and the formal remainder. If the divisor is zero, it returns the dividend as the remainder.*)\nDefinition redivpT (p : polyF) (q : polyF) : cps (nat * polyF * polyF) :=\n 'let b <- isnull q;\n if b then ret (0, [::0%T], p) else\n 'let sq <- sizeT q; 'let sp <- sizeT p;\n 'let lq <- lead_coefT q;\n redivp_rec_loopT q sq lq 0 [::0%T] p sp.\n\n(*This lemma states that the result of a recursive polynomial division helper function is identical to the result of the bounded recursive division loop when initialized with the divisor's size and leading coefficient.*)\nLemma redivp_rec_loopP (q : {poly F}) (c : nat) (qq r : {poly F}) (n : nat) :\n redivp_rec q c qq r n = redivp_rec_loop q (size q) (lead_coef q) c qq r n.\n\n(*This lemma states that, under a standard condition on the continuation, evaluating the result of the term-level polynomial pseudo-division is equivalent to applying the continuation to the lifted results of the standard pseudo-division performed on the evaluated dividend and divisor.*)\nLemma redivpTP (k : nat * polyF * polyF -> fF) :\n (forall c qq r e,\n qf_eval e (k (c,qq,r)) =\n qf_eval e (k (c, lift (eval_poly e qq), lift (eval_poly e r)))) ->\n forall p q e (d := redivp (eval_poly e p) (eval_poly e q)),\n qf_eval e (redivpT p q k) = qf_eval e (k (d.1.1, lift d.1.2, lift d.2)).\n\n(*This lemma states that if the formal dividend and formal divisor are regular polynomials, then the term-level pseudo-division computation produces a result where the final formal quotient and formal remainder are also regular polynomials.*)\nLemma redivpT_qf (p : polyF) (q : polyF) : rpoly p -> rpoly q ->\n qf_cps (fun x => [&& rpoly x.1.2 & rpoly x.2]) (redivpT p q).\n\n(*This definition computes the formal remainder of a polynomial pseudo-division by performing the division and extracting the remainder component from the resulting tuple.*)\nDefinition rmodpT (p : polyF) (q : polyF) : cps polyF :=\n 'let d <- redivpT p q; ret d.2.\n(*This definition computes the formal quotient of a polynomial pseudo-division by performing the division and extracting the quotient component from the resulting tuple.*)\nDefinition rdivpT (p : polyF) (q : polyF) : cps polyF :=\n 'let d <- redivpT p q; ret d.1.2.\n(*This definition computes the scaling factor from a polynomial pseudo-division by performing the division and extracting the natural number scale component from the resulting tuple.*)\nDefinition rscalpT (p : polyF) (q : polyF) : cps nat :=\n 'let d <- redivpT p q; ret d.1.1.\n(*This definition computes a boolean term indicating whether a first formal polynomial is divisible by a second formal polynomial by checking if the formal remainder of their division is zero.*)\nDefinition rdvdpT (p : polyF) (q : polyF) : cps bool :=\n 'let d <- rmodpT p q; isnull d.\n\n(*This fixpoint definition implements a bounded recursive loop for computing the greatest common divisor of two standard polynomials using the Euclidean algorithm, terminating either when a zero remainder is found or the recursion limit is reached.*)\nFixpoint rgcdp_loop n (pp qq : {poly F}) {struct n} :=\n let rr := rmodp pp qq in if rr == 0 then qq\n else if n is n1.+1 then rgcdp_loop n1 qq rr else rr.\n\n(*This fixpoint definition implements a bounded recursive loop in continuation-passing style for computing the greatest common divisor of two formal polynomials using the Euclidean algorithm.*)\nFixpoint rgcdp_loopT n (pp : polyF) (qq : polyF) : cps polyF :=\n 'let rr <- rmodpT pp qq; 'let nrr <- isnull rr; if nrr then ret qq\n else if n is n1.+1 then rgcdp_loopT n1 qq rr else ret rr.\n\n(*This lemma states that under a condition ensuring evaluation commutes with a given continuation function, the evaluation of a polynomial resulting from the continuation-passing-style Euclidean algorithm loop is equal to the evaluation of the result from the standard Euclidean algorithm loop applied to the evaluated input polynomials.*)\nLemma rgcdp_loopP (k : polyF -> fF) :\n (forall p e, qf_eval e (k p) = qf_eval e (k (lift (eval_poly e p)))) ->\n forall n p q e,\n qf_eval e (rgcdp_loopT n p q k) =\n qf_eval e (k (lift (rgcdp_loop n (eval_poly e p) (eval_poly e q)))).\n\n(*This lemma states that if two input polynomials satisfy a specific well-formedness property, then the continuation-passing-style computation representing the Euclidean algorithm loop produces a result that also preserves this well-formedness property.*)\nLemma rgcdp_loopT_qf (n : nat) (p : polyF) (q : polyF) :\n rpoly p -> rpoly q -> qf_cps rpoly (rgcdp_loopT n p q).\n\n(*This definition computes the greatest common divisor of two polynomials using a continuation-passing-style implementation of the Euclidean algorithm, which first orders the polynomials by size.*)\nDefinition rgcdpT (p : polyF) (q : polyF) : cps polyF :=\n let aux p1 q1 : cps polyF :=\n 'let b <- isnull p1; if b then ret q1\n else 'let n <- sizeT p1; rgcdp_loopT n p1 q1 in\n 'let b <- lt_sizeT p q; if b then aux q p else aux p q.\n\n(*This lemma states that under a condition ensuring evaluation commutes with a given continuation function, the evaluation of the greatest common divisor polynomial computed in continuation-passing style is equal to the evaluation of the greatest common divisor computed using a standard algorithm on the evaluated input polynomials.*)\nLemma rgcdpTP (k : polyF -> fF) :\n (forall p e, qf_eval e (k p) = qf_eval e (k (lift (eval_poly e p)))) ->\n forall p q e, qf_eval e (rgcdpT p q k) =\n qf_eval e (k (lift (rgcdp (eval_poly e p) (eval_poly e q)))).\n\n(*This lemma states that if two input polynomials satisfy a specific well-formedness property, then their greatest common divisor computed in continuation-passing style is a computation that preserves this well-formedness property.*)\nLemma rgcdpT_qf (p : polyF) (q : polyF) :\n rpoly p -> rpoly q -> qf_cps rpoly (rgcdpT p q).\n\n(*This fixpoint definition recursively computes the greatest common divisor of a sequence of polynomials in continuation-passing style by repeatedly applying the two-polynomial greatest common divisor operation. The greatest common divisor of an empty sequence is defined as the zero polynomial.*)\nFixpoint rgcdpTs (ps : seq polyF) : cps polyF :=\n if ps is p :: pr then 'let pr <- rgcdpTs pr; rgcdpT p pr else ret [::0%T].\n\n(*This lemma states that under a condition ensuring evaluation commutes with a given continuation function, the evaluation of the greatest common divisor of a sequence of polynomials, computed in continuation-passing style, is equal to the evaluation of the iterated greatest common divisor of the evaluated polynomials in the sequence.*)\nLemma rgcdpTsP (k : polyF -> fF) :\n (forall p e, qf_eval e (k p) = qf_eval e (k (lift (eval_poly e p)))) ->\n forall ps e,\n qf_eval e (rgcdpTs ps k) =\n qf_eval e (k (lift (\\big[@rgcdp _/0%:P]_(i <- ps)(eval_poly e i)))).\n\n(*This lemma states that if all polynomials in an input sequence satisfy a specific well-formedness property, then their greatest common divisor computed in continuation-passing style is a computation that preserves this well-formedness property.*)\nLemma rgcdpTs_qf (ps : seq polyF) :\n all rpoly ps -> qf_cps rpoly (rgcdpTs ps).\n\n(*This fixpoint definition specifies a recursive computation in continuation-passing style that, for a given number of iterations, repeatedly divides an input polynomial by its greatest common divisor with a second polynomial. If at any step the greatest common divisor becomes a constant, the current polynomial is returned.*)\nFixpoint rgdcop_recT n (q : polyF) (p : polyF) :=\n if n is m.+1 then\n 'let g <- rgcdpT p q; 'let sg <- sizeT g;\n if sg == 1 then ret p\n else 'let r <- rdivpT p g;\n rgdcop_recT m q r\n else 'let b <- isnull q; ret [::b%:R%T].\n\n(*This lemma states that under a condition ensuring evaluation commutes with a given continuation function, the evaluation of a polynomial resulting from a recursive 'make coprime' step, computed in continuation-passing style, is equal to the evaluation of the result from the corresponding standard recursive computation applied to the evaluated input polynomials.*)\nLemma rgdcop_recTP (k : polyF -> fF) :\n (forall p e, qf_eval e (k p) = qf_eval e (k (lift (eval_poly e p))))\n -> forall p q n e, qf_eval e (rgdcop_recT n p q k)\n = qf_eval e (k (lift (rgdcop_rec (eval_poly e p) (eval_poly e q) n))).\n\n(*This lemma states that if two input polynomials satisfy a specific well-formedness property, then the polynomial resulting from the recursive 'make coprime' computation in continuation-passing style is a computation that preserves this well-formedness property.*)\nLemma rgdcop_recT_qf (n : nat) (p : polyF) (q : polyF) :\n rpoly p -> rpoly q -> qf_cps rpoly (rgdcop_recT n p q).\n\n(*This definition computes the 'coprime part' of a polynomial with respect to another by calling a recursive helper function, where the number of recursion steps is determined by the size of the first polynomial.*)\nDefinition rgdcopT q p := 'let sp <- sizeT p; rgdcop_recT sp q p.\n\n(*This lemma states that under a condition ensuring evaluation commutes with a given continuation function, the evaluation of the 'coprime part' of a polynomial computed in continuation-passing style is equal to the evaluation of the result from the corresponding standard computation applied to the evaluated input polynomials.*)\nLemma rgdcopTP (k : polyF -> fF) :\n (forall p e, qf_eval e (k p) = qf_eval e (k (lift (eval_poly e p)))) ->\n forall p q e, qf_eval e (rgdcopT p q k) =\n qf_eval e (k (lift (rgdcop (eval_poly e p) (eval_poly e q)))).\n\n(*This lemma states that if two input polynomials satisfy a specific well-formedness property, then the 'coprime part' computation in continuation-passing style is a computation that preserves this well-formedness property.*)\nLemma rgdcopT_qf (p : polyF) (q : polyF) :\n rpoly p -> rpoly q -> qf_cps rpoly (rgdcopT p q).\n\n(*This definition performs an existential quantifier elimination step. It takes a sequence of polynomials and another polynomial, and returns a boolean value indicating whether the second polynomial is not trivial on the zero set of the first sequence of polynomials.*)\nDefinition ex_elim_seq (ps : seq polyF) (q : polyF) : fF :=\n ('let g <- rgcdpTs ps; 'let d <- rgdcopT q g;\n 'let n <- sizeT d; ret (n != 1)) GRing.Bool.\n\n(*This lemma provides the correctness property for the existential elimination procedure on sequences of polynomials. It asserts that evaluating the result of the procedure at a point is equivalent to checking if the size of the 'coprime part' of the evaluated polynomials is not equal to one.*)\nLemma ex_elim_seqP (ps : seq polyF) (q : polyF) (e : seq F) :\n let gp := (\\big[@rgcdp _/0%:P]_(p <- ps)(eval_poly e p)) in\n qf_eval e (ex_elim_seq ps q) = (size (rgdcop (eval_poly e q) gp) != 1).\n\n(*This lemma states that the existential elimination procedure for sequences of polynomials yields a quantifier-free boolean formula, provided that all input polynomials satisfy a specific well-formedness property.*)\nLemma ex_elim_seq_qf (ps : seq polyF) (q : polyF) :\n all rpoly ps -> rpoly q -> qf (ex_elim_seq ps q).\n\n(*This fixpoint definition converts a formal term into a univariate polynomial by treating a specified variable as the polynomial indeterminate and all other parts of the term as coefficients. Operations within the term are translated into corresponding polynomial operations.*)\nFixpoint abstrX (i : nat) (t : tF) :=\n match t with\n | 'X_n => if n == i then [::0; 1] else [::t]\n | - x => opppT (abstrX i x)\n | x + y => sumpT (abstrX i x) (abstrX i y)\n | x * y => mulpT (abstrX i x) (abstrX i y)\n | x *+ n => natmulpT n (abstrX i x)\n | x ^+ n => let ax := (abstrX i x) in iter n (mulpT ax) [::1]\n | _ => [::t]\n end%T.\n\n(*This lemma states that for any well-formed term, evaluating the univariate polynomial obtained by abstracting a specific variable is equivalent to evaluating the original term in an environment where that variable is assigned the corresponding value.*)\nLemma abstrXP (i : nat) (t : tF) (e : seq F) (x : F) :\n rterm t -> (eval_poly e (abstrX i t)).[x] = eval (set_nth 0 e i x) t.\n\n(*This lemma states that if a formal term is well-formed, then the univariate polynomial resulting from abstracting one of its variables satisfies a specific well-formedness property.*)\nLemma rabstrX (i : nat) (t : tF) : rterm t -> rpoly (abstrX i t).\n\nImplicit Types tx ty : tF.\n\n(*This lemma states that the function which abstracts a term into a polynomial is a morphism with respect to multiplication, meaning it maps the product of two terms to the polynomial product of their respective abstractions.*)\nLemma abstrX_mulM (i : nat) : {morph abstrX i : x y / x * y >-> mulpT x y}%T.\n\n(*This lemma states that abstracting the multiplicative identity term results in the constant polynomial one.*)\nLemma abstrX1 (i : nat) : abstrX i 1%T = [::1%T].\n\n(*This lemma states that polynomial evaluation is a morphism with respect to multiplication, meaning that the evaluation of a product of two polynomials is equal to the product of their individual evaluations.*)\nLemma eval_poly_mulM e : {morph eval_poly e : x y / mulpT x y >-> x * y}.\n\n(*This lemma states that evaluating the constant polynomial one yields the multiplicative identity element of the target ring.*)\nLemma eval_poly1 e : eval_poly e [::1%T] = 1.\n\n(*This notation provides a shorthand for the property that the term abstraction function preserves iterated products, building upon its preservation of binary products and the multiplicative identity.*)\nNotation abstrX_bigmul := (big_morph _ (abstrX_mulM _) (abstrX1 _)).\n(*This notation provides a shorthand for the property that polynomial evaluation preserves iterated products, building upon its preservation of binary products and the multiplicative identity.*)\nNotation eval_bigmul := (big_morph _ (eval_poly_mulM _) (eval_poly1 _)).\n(*This notation defines a simplified big operator expression which applies a given operation over a sequence of elements without any transformation or filtering.*)\nNotation bigmap_id := (big_map _ (fun _ => true) id).\n\n(*This lemma states that applying the term-to-polynomial abstraction function to every element of a sequence of well-formed terms results in a sequence of polynomials where each polynomial satisfies a specific well-formedness property.*)\nLemma rseq_poly_map (x : nat) (ts : seq tF) :\n all (@rterm _) ts -> all rpoly (map (abstrX x) ts).\n\n(*This definition describes an existential quantifier elimination procedure over a system of term equations and inequations. It transforms the terms into univariate polynomials with respect to a specified variable and then applies a polynomial-based elimination algorithm.*)\nDefinition ex_elim (x : nat) (pqs : seq tF * seq tF) :=\n ex_elim_seq (map (abstrX x) pqs.1)\n (abstrX x (\\big[GRing.Mul/1%T]_(q <- pqs.2) q)).\n\n(*This lemma states that the existential quantifier elimination procedure for terms produces a quantifier-free formula, provided the input terms are well-formed.*)\nLemma ex_elim_qf (x : nat) (pqs : seq tF * seq tF) :\n GRing.dnf_rterm pqs -> qf (ex_elim x pqs).\n\n(*This lemma states that a logical formula, representing a conjunction of polynomial equations, is satisfied under a variable assignment where one variable is set to a specific value, if and only if that value is a common root of all the given polynomials.*)\nLemma holds_conj : forall e i x ps, all (@rterm _) ps ->\n (GRing.holds (set_nth 0 e i x)\n (foldr (fun t : tF => GRing.And (t == 0)) GRing.True%T ps)\n <-> all ((@root _)^~ x) (map (eval_poly e \\o abstrX i) ps)).\n\n(*This lemma states that a logical formula, representing a conjunction of polynomial inequations, is satisfied under a variable assignment where one variable is set to a specific value, if and only if that value is not a root of any of the given polynomials.*)\nLemma holds_conjn (e : seq F) (i : nat) (x : F) (ps : seq tF) :\n all (@rterm _) ps ->\n (GRing.holds (set_nth 0 e i x)\n (foldr (fun t : tF => GRing.And (t != 0)) GRing.True ps) <->\n all (fun p => ~~root p x) (map (eval_poly e \\o abstrX i) ps)).\n\n(*This lemma states that the 'ex_elim' function provides a valid method for quantifier elimination. Specifically, it asserts that applying this function to a formula containing an existential quantifier produces a new formula that is logically equivalent but free of that quantifier.*)\nLemma holds_ex_elim: GRing.valid_QE_proj ex_elim.\n\n(*This lemma states that the 'ex_elim' quantifier elimination function is well-founded, which ensures that its computation always terminates.*)\nLemma wf_ex_elim : GRing.wf_QE_proj ex_elim.\n\nEnd ClosedFieldQE.\nEnd ClosedFieldQE.\n\n(*This is a structure factory that creates a record certifying a given field is algebraically closed. It bundles the field with a proof that every non-constant monic polynomial over the field has at least one root within that same field.*)\nHB.factory Record Field_isAlgClosed F of GRing.Field F := {\n solve_monicpoly : GRing.closed_field_axiom F;\n}.\n\nHB.builders Context F of Field_isAlgClosed F.\n HB.instance Definition _ := GRing.Field_QE_isDecField.Build F\n (@ClosedFieldQE.wf_ex_elim F)\n (ClosedFieldQE.holds_ex_elim solve_monicpoly).\n(*This lemma states that for any non-constant polynomial with coefficients in a countable field, there exists a larger countable field, an extension, that contains a root for that polynomial. The original field is embedded within this new extension via an injective ring homomorphism.*)\nLemma countable_field_extension (F : countFieldType) (p : {poly F}) :\n size p > 1 ->\n {E : countFieldType & {FtoE : {rmorphism F -> E} &\n {w : E | root (map_poly FtoE p) w\n & forall u : E, exists q, u = (map_poly FtoE q).[w]}}}.\n\n(*This definition provides the construction of an algebraic closure for any given countable field. The result is a new field that is itself countable, algebraically closed, and contains the original field as a subfield.*)\nLemma countable_algebraic_closure (F : countFieldType) :\n {K : countClosedFieldType & {FtoK : {rmorphism F -> K} | integralRange FtoK}}.", - "field.separable": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype tuple finfun bigop finset prime.\nFrom mathcomp Require Import binomial ssralg poly polydiv fingroup perm.\nFrom mathcomp Require Import morphism quotient gproduct finalg zmodp cyclic.\nFrom mathcomp Require Import matrix mxalgebra mxpoly polyXY vector falgebra.\nFrom mathcomp Require Import fieldext.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope ring_scope.\nImport GRing.Theory.\n\nHB.lock\n(*This definition states that a polynomial over an integral domain is separable if it is coprime with its formal derivative.*)\nDefinition separable_poly {R : idomainType} (p : {poly R}) := coprimep p p^`().\nCanonical separable_poly_unlockable := Unlockable separable_poly.unlock.\n\nSection SeparablePoly.\n\nVariable R : idomainType.\nImplicit Types p q d u v : {poly R}.\n\n(*This notation provides a local shorthand for the `separable_poly` predicate, which checks if a polynomial is separable.*)\nLocal Notation separable := (@separable_poly R).\n(*This notation provides a local shorthand for a property ensuring that the leading coefficient of a polynomial resulting from certain scaling operations over an integral domain is not zero.*)\nLocal Notation lcn_neq0 := (Pdiv.Idomain.lc_expn_scalp_neq0 _).\n\n(*This lemma states that if a polynomial is separable, then it cannot be the zero polynomial.*)\nLemma separable_poly_neq0 p : separable p -> p != 0.\n\n(*This lemma states that a polynomial has the property that any two of its factors are coprime if and only if the polynomial is not divisible by the square of any non-constant polynomial.*)\nLemma poly_square_freeP p :\n (forall u v, u * v %| p -> coprimep u v)\n <-> (forall u, size u != 1 -> ~~ (u ^+ 2 %| p)).\n\n(*This lemma provides an equivalent characterization of a separable polynomial, stating that a polynomial is separable if and only if two conditions are met: first, any two factors of the polynomial are coprime, and second, the derivative of any non-constant factor of the polynomial is not the zero polynomial.*)\nLemma separable_polyP {p} :\n reflect [/\\ forall u v, u * v %| p -> coprimep u v\n & forall u, u %| p -> 1 < size u -> u^`() != 0]\n (separable p).\n\n(*This lemma states that if a separable polynomial is divisible by the product of two other polynomials, then those two polynomials must be coprime.*)\nLemma separable_coprime p u v : separable p -> u * v %| p -> coprimep u v.\n\n(*This lemma states that a separable polynomial cannot be divisible by a power greater than one of any non-constant polynomial.*)\nLemma separable_nosquare p u k :\n separable p -> 1 < k -> size u != 1 -> (u ^+ k %| p) = false.\n\n(*This lemma states that for a separable polynomial, the formal derivative of any of its non-constant factors cannot be the zero polynomial.*)\nLemma separable_deriv_eq0 p u :\n separable p -> u %| p -> 1 < size u -> (u^`() == 0) = false.\n\n(*This lemma states that any factor of a separable polynomial is also separable.*)\nLemma dvdp_separable p q : q %| p -> separable p -> separable q.\n\n(*This lemma states that the product of two polynomials is separable if and only if both polynomials are individually separable and they are coprime to each other.*)\nLemma separable_mul p q :\n separable (p * q) = [&& separable p, separable q & coprimep p q].\n\n(*This lemma states that if two polynomials are associated, meaning they differ only by a multiplication by a unit, then one is separable if and only if the other is.*)\nLemma eqp_separable p q : p %= q -> separable p = separable q.\n\n(*This lemma states that the product of a polynomial and a linear factor corresponding to a value is separable if and only if the original polynomial is separable and the value is not a root of the original polynomial.*)\nLemma separable_root p x :\n separable (p * ('X - x%:P)) = separable p && ~~ root p x.\n\n(*This lemma states that a polynomial constructed as the product of linear factors derived from a sequence of elements is separable if and only if all elements in the sequence are distinct.*)\nLemma separable_prod_XsubC (r : seq R) :\n separable (\\prod_(x <- r) ('X - x%:P)) = uniq r.\n\n(*This lemma states that for any non-zero polynomial, a separable polynomial can be constructed by dividing the original polynomial by the greatest common divisor of itself and its formal derivative.*)\nLemma make_separable p : p != 0 -> separable (p %/ gcdp p p^`()).\n\nEnd SeparablePoly.\n\nArguments separable_polyP {R p}.\n\n(*This lemma states that the property of a polynomial being separable is preserved when its coefficients are mapped by a ring morphism from a field to an integral domain.*)\nLemma separable_map (F : fieldType) (R : idomainType)\n (f : {rmorphism F -> R}) (p : {poly F}) :\n separable_poly (map_poly f p) = separable_poly p.\n\nSection InfinitePrimitiveElementTheorem.\n\n(*A local notation for applying a morphism to the coefficients of a polynomial.*)\nLocal Notation \"p ^ f\" := (map_poly f p) : ring_scope.\n\nVariables (F L : fieldType) (iota : {rmorphism F -> L}).\nVariables (x y : L) (p : {poly F}).\nHypotheses (nz_p : p != 0) (px_0 : root (p ^ iota) x).\n\n(*This definition captures the property that an element in a field extension can be expressed as the evaluation of a polynomial at another element, where the polynomial's coefficients originate from a base field.*)\nLet inFz z w := exists q, (q ^ iota).[z] = w.\n\n(*This lemma, related to the Primitive Element Theorem for large fields, asserts that given a separable polynomial with a root in an extension field, it is possible to construct a single element from which two given elements of the extension can be generated polynomially, for most choices of a coefficient from the base field.*)\nLemma large_field_PET q :\n root (q ^ iota) y -> separable_poly q ->\n exists2 r, r != 0\n & forall t (z := iota t * y - x), ~~ root r (iota t) -> inFz z x /\\ inFz z y.\n\n(*This lemma, a version of the Primitive Element Theorem for fields of characteristic zero, states that given two elements in a field extension, where one is algebraic over the base field, there exists a natural number such that a specific linear combination of the two elements can be used to polynomially generate both original elements.*)\nLemma pchar0_PET (q : {poly F}) :\n q != 0 -> root (q ^ iota) y -> [pchar F] =i pred0 ->\n exists n, let z := y *+ n - x in inFz z x /\\ inFz z y.\n\nEnd InfinitePrimitiveElementTheorem.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pchar0_PET instead.\")]\n(*This is a deprecated notation that serves as an alias for the `pchar0_PET` lemma, related to the Primitive Element Theorem in characteristic zero.*)\nNotation char0_PET := (pchar0_PET) (only parsing).\n\nSection Separable.\n\nVariables (F : fieldType) (L : fieldExtType F).\nImplicit Types (U V W : {vspace L}) (E K M : {subfield L}) (D : 'End(L)).\n\nSection Derivation.\n\nVariables (K : {vspace L}) (D : 'End(L)).\n\n(*This definition specifies that a given endomorphism on a vector space qualifies as a derivation if it satisfies the Leibniz product rule for all pairs of basis vectors.*)\nDefinition Derivation : bool :=\n all2rel (fun u v => D (u * v) == D u * v + u * D v) (vbasis K).\n\nHypothesis derD : Derivation.\n\n(*This lemma states that if a linear map is a derivation on a vector space, then it satisfies the Leibniz product rule for all pairs of elements in that space, not just for basis vectors.*)\nLemma Derivation_mul : {in K &, forall u v, D (u * v) = D u * v + u * D v}.\n\n(*This lemma states that a derivation on an algebra can be extended to the ring of polynomials over that algebra, such that the extended map also satisfies the Leibniz product rule for polynomial multiplication.*)\nLemma Derivation_mul_poly (Dp := map_poly D) :\n {in polyOver K &, forall p q, Dp (p * q) = Dp p * q + p * Dp q}.\n\nEnd Derivation.\n\n(*This lemma states that if a linear map is a derivation on a given vector space, it is also a derivation on any of its subspaces.*)\nLemma DerivationS E K D : (K <= E)%VS -> Derivation E D -> Derivation K D.\n\nSection DerivationAlgebra.\n\nVariables (E : {subfield L}) (D : 'End(L)).\nHypothesis derD : Derivation E D.\n\n(*This lemma states that any derivation on a subalgebra maps the multiplicative identity element to zero.*)\nLemma Derivation1 : D 1 = 0.\n\n(*This lemma states that a derivation on a field extension maps any element from the base field to zero.*)\nLemma Derivation_scalar x : x \\in 1%VS -> D x = 0.\n\n(*This lemma provides the power rule for derivations, stating that the derivation of an element raised to a natural number power is equal to the exponent times the element raised to the power of the exponent minus one, all multiplied by the derivation of the element.*)\nLemma Derivation_exp x m : x \\in E -> D (x ^+ m) = x ^+ m.-1 *+ m * D x.\n\n(*This lemma provides a formula for applying a derivation to the evaluation of a polynomial at a point, expressing the result as the sum of the evaluation of the mapped polynomial and the product of the formal derivative's evaluation with the derivation of the point.*)\nLemma Derivation_horner p x :\n p \\is a polyOver E -> x \\in E ->\n D p.[x] = (map_poly D p).[x] + p^`().[x] * D x.\n\nEnd DerivationAlgebra.\n\n(*This definition states that an element is considered separable over a given subfield if its minimal polynomial with respect to that subfield is a separable polynomial.*)\nDefinition separable_element U x := separable_poly (minPoly U x).\n\nSection SeparableElement.\n\nVariables (K : {subfield L}) (x : L).\n\n(*This definition establishes that a subfield is a sub-vector space of the vector space obtained by adjoining a new element to it.*)\nLet sKxK : (K <= <>)%VS := subv_adjoin K x.\n(*This definition establishes that an adjoined element belongs to the vector space generated by a subfield and that element.*)\nLet Kx_x : x \\in <>%VS := memv_adjoin K x.\n\n(*This lemma states that an element is separable over a subfield if and only if there exists a polynomial over that subfield which has the element as a root and is itself a separable polynomial.*)\nLemma separable_elementP : \n reflect (exists f, [/\\ f \\is a polyOver K, root f x & separable_poly f])\n (separable_element K x).\n\n(*This lemma states that any element belonging to a base subfield is separable over that subfield.*)\nLemma base_separable : x \\in K -> separable_element K x.\n\n(*This lemma states that an element is separable over a subfield if and only if the formal derivative of its minimal polynomial over that subfield is not the zero polynomial.*)\nLemma separable_nz_der : separable_element K x = ((minPoly K x)^`() != 0).\n\n(*This lemma states that an element is not separable over a subfield if and only if there exists a prime number, which is the characteristic of the ambient field, such that the minimal polynomial of the element is a polynomial in the variable raised to the power of that prime.*)\nLemma separablePn_pchar :\n reflect (exists2 p, p \\in [pchar L] &\n exists2 g, g \\is a polyOver K & minPoly K x = g \\Po 'X^p)\n (~~ separable_element K x).\n\n(*This lemma states that for any given element, either the element is separable over a subfield, or it is a root of the formal derivative of its own minimal polynomial over that subfield.*)\nLemma separable_root_der : separable_element K x (+) root (minPoly K x)^`() x.\n\n(*This lemma provides a formula for the action of a derivation on a separable element, expressing it as the negative of the polynomial obtained by applying the derivation to the coefficients of the minimal polynomial evaluated at the element, divided by the derivative of the minimal polynomial evaluated at the element.*)\nLemma Derivation_separable D :\n Derivation <> D -> separable_element K x ->\n D x = - (map_poly D (minPoly K x)).[x] / (minPoly K x)^`().[x].\n\nSection ExtendDerivation.\n\nVariable D : 'End(L).\n\n(*This definition provides a shorthand for the formula that computes the action of a derivation on a separable element, parameterized by the subfield over which the minimal polynomial is taken.*)\nLet Dx E := - (map_poly D (minPoly E x)).[x] / ((minPoly E x)^`()).[x].\n\n(*This fact proves that a specific function, intended to extend a derivation, preserves addition and is therefore a morphism of additive groups.*)\nFact extendDerivation_zmod_morphism_subproof E (adjEx := Fadjoin_poly E x) :\n let body y (p := adjEx y) := (map_poly D p).[x] + p^`().[x] * Dx E in\n zmod_morphism body.\n\n(*This fact proves that a specific function, intended to extend a derivation, is compatible with scalar multiplication.*)\nFact extendDerivation_scalable_subproof E (adjEx := Fadjoin_poly E x) :\n let body y (p := adjEx y) := (map_poly D p).[x] + p^`().[x] * Dx E in\n scalable body.\n\nSection DerivationLinear.\nVariable (E : {subfield L}).\n(*This definition specifies a function that computes the value of an extended derivation on an element of a field extension, using the polynomial representation of that element.*)\nLet body (y : L) (p := Fadjoin_poly E x y) : L :=\n (map_poly D p).[x] + p^`().[x] * Dx E.\nHB.instance Definition _ := @GRing.isZmodMorphism.Build _ _ body\n (extendDerivation_zmod_morphism_subproof E).\n(*This definition bundles a function with its linearity proofs to create a formal linear map representing an extended derivation.*)\nLet extendDerivationLinear := Eval hnf in (body : {linear _ -> _}).\n(*This definition constructs a field endomorphism representing the extension of a given derivation from a subfield to a larger field generated by adjoining a separable element.*)\nDefinition extendDerivation : 'End(L) := linfun extendDerivationLinear.\nEnd DerivationLinear.\n\nHypothesis derD : Derivation K D.\n\n(*This lemma states that the extended derivation, when applied to an element of the original base subfield, yields the same result as the original derivation.*)\nLemma extendDerivation_id y : y \\in K -> extendDerivation K y = D y.\n\n(*This lemma states that for a separable element, the extended derivation applied to a polynomial evaluated at that element equals the sum of two terms: the polynomial formed by applying the original derivation to the coefficients evaluated at the element, and the product of the formal derivative of the polynomial evaluated at the element and the action of the extended derivation on the element itself.*)\nLemma extendDerivation_horner p :\n p \\is a polyOver K -> separable_element K x ->\n extendDerivation K p.[x] = (map_poly D p).[x] + p^`().[x] * Dx K.\n\n(*This lemma states that if an adjoined element is separable, the constructed extended endomorphism is a valid derivation on the field extension.*)\nLemma extendDerivationP :\n separable_element K x -> Derivation <> (extendDerivation K).\n\nEnd ExtendDerivation.\n\n(*This lemma provides an equivalence, stating that an element is separable over a subfield if and only if every derivation on the extended field that is zero on the base subfield must also be zero on the entire extended field.*)\nLemma Derivation_separableP :\n reflect\n (forall D, Derivation <> D -> K <= lker D -> <> <= lker D)%VS\n (separable_element K x).\n\nEnd SeparableElement.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use separablePn_pchar instead.\")]\n(*This notation serves as a deprecated alias for `separablePn_pchar`, used only for parsing older code.*)\nNotation separablePn := (separablePn_pchar) (only parsing).\n\nArguments separable_elementP {K x}.\n\n(*This lemma states that if an element is separable over a given subfield, it is also separable over any larger intermediate subfield.*)\nLemma separable_elementS K E x :\n (K <= E)%VS -> separable_element K x -> separable_element E x.\n\n(*This lemma provides an equivalence, stating that an element is separable over a subfield if and only if every element in the field extension generated by that element is also separable over the same subfield.*)\nLemma adjoin_separableP {K x} :\n reflect (forall y, y \\in <>%VS -> separable_element K y)\n (separable_element K x).\n\n(*This lemma states that for any element in a field, there exists an exponent, which is a power of the field's characteristic, such that raising the element to this exponent results in an element that is separable over the given subfield.*)\nLemma separable_exponent_pchar K x :\n exists n, [pchar L].-nat n && separable_element K (x ^+ n).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use separable_exponent_pchar instead.\")]\n(*This notation serves as a deprecated alias for `separable_exponent_pchar`, used only for parsing older code.*)\nNotation separable_exponent := (separable_exponent_pchar) (only parsing).\n\n(*This lemma states that in a field of characteristic zero, every element is separable over any given subfield.*)\nLemma pcharf0_separable K : [pchar L] =i pred0 -> forall x, separable_element K x.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf0_separable instead.\")]\n(*This notation serves as a deprecated alias for `pcharf0_separable`, used only for parsing older code.*)\nNotation charf0_separable := (pcharf0_separable) (only parsing).\n\n(*This lemma states that in a field of prime characteristic, an element is separable over a subfield if and only if it is contained in the field extension generated by that subfield and the element raised to any positive integer power of the characteristic.*)\nLemma pcharf_p_separable K x e p :\n p \\in [pchar L] -> separable_element K x = (x \\in <>%VS).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf_p_separable instead.\")]\n(*This notation serves as a deprecated alias for `pcharf_p_separable`, used only for parsing older code.*)\nNotation charf_p_separable := (pcharf_p_separable) (only parsing).\n\n(*This lemma states that in a field of positive characteristic, an element is separable over a subfield if and only if it belongs to the extension field generated by that subfield and the element raised to any power of the characteristic greater than one.*)\nLemma pcharf_n_separable K x n :\n [pchar L].-nat n -> 1 < n -> separable_element K x = (x \\in <>%VS).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcharf_n_separable instead.\")]\n(*This notation serves as a deprecated alias for `pcharf_n_separable`, used only for parsing older code.*)\nNotation charf_n_separable := (pcharf_n_separable) (only parsing).\n\n(*This definition specifies the property of an element being purely inseparable over a given subfield, which means its minimal polynomial over that subfield has only one distinct root.*)\nDefinition purely_inseparable_element U x :=\n x ^+ ex_minn (separable_exponent_pchar <> x) \\in U.\n\n(*This lemma provides a reflection property, stating that an element is purely inseparable over a given field if and only if there exists a natural number 'n' such that the element raised to the power of the field's characteristic raised to 'n' is a member of the base field.*)\nLemma purely_inseparable_elementP_pchar {K x} :\n reflect (exists2 n, [pchar L].-nat n & x ^+ n \\in K)\n (purely_inseparable_element K x).\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use purely_inseparable_elementP_pchar instead.\")]\n(*This notation provides a deprecated alias for the reflection lemma `purely_inseparable_elementP_pchar`, which characterizes purely inseparable elements.*)\nNotation purely_inseparable_elementP := (purely_inseparable_elementP_pchar) (only parsing).\n\n(*This lemma states that an element is both separable and purely inseparable over a given field if and only if that element is a member of the base field.*)\nLemma separable_inseparable_element K x :\n separable_element K x && purely_inseparable_element K x = (x \\in K).\n\n(*This lemma states that any element that belongs to a base field is considered purely inseparable over that same field.*)\nLemma base_inseparable K x : x \\in K -> purely_inseparable_element K x.\n\n(*This lemma states that if an element is purely inseparable over a base field, it remains purely inseparable over any larger intermediate field.*)\nLemma sub_inseparable K E x :\n (K <= E)%VS -> purely_inseparable_element K x ->\n purely_inseparable_element E x.\n\nSection PrimitiveElementTheorem.\n\nVariables (K : {subfield L}) (x y : L).\n\nSection FiniteCase.\n\nVariable N : nat.\n\n(*This definition introduces a boolean condition which is true if a given field contains more elements than a specified natural number.*)\nLet K_is_large := exists s, [/\\ uniq s, {subset s <= K} & N < size s].\n\n(*This lemma asserts that for any non-zero element in a field extension, either the base field has a size larger than some given natural number, or the element is a root of unity.*)\nLet cyclic_or_large (z : L) : z != 0 -> K_is_large \\/ exists a, z ^+ a.+1 = 1.\n\n(*This lemma, a version of the Primitive Element Theorem for finite fields, states that for a field extension generated by two elements, either the base field is sufficiently large, or the extension can be generated by a single element.*)\nLemma finite_PET : K_is_large \\/ exists z, (<< <>; x>> = <>)%VS.\n\nEnd FiniteCase.\n\nHypothesis sepKy : separable_element K y.\n\n(*This lemma, known as the Primitive Element Theorem, asserts that a field extension generated by an element and another, separable element can itself be generated by a single element.*)\nLemma Primitive_Element_Theorem : exists z, (<< <>; x>> = <>)%VS.\n\n(*This lemma states that if an element is separable over a field that has been extended by a single separable element, then it is also separable over the original base field.*)\nLemma adjoin_separable : separable_element <> x -> separable_element K x.\n\nEnd PrimitiveElementTheorem.\n\n(*This lemma provides a strong version of the Primitive Element Theorem, stating that if one element is separable over a field extended by another element, then the extension generated by both can be generated by a single element. It also asserts that if the second element is separable over the base field, then the first one must be as well.*)\nLemma strong_Primitive_Element_Theorem K x y :\n separable_element <> y ->\n exists2 z : L, (<< <>; x>> = <>)%VS\n & separable_element K x -> separable_element K y.\n\n(*This definition specifies that a field extension is separable if every element in a vector space basis for the extension field over the base field is a separable element.*)\nDefinition separable U W : bool :=\n all (separable_element U) (vbasis W).\n\n(*This definition specifies that a field extension is purely inseparable if every element in a vector space basis for the extension field over the base field is a purely inseparable element.*)\nDefinition purely_inseparable U W : bool :=\n all (purely_inseparable_element U) (vbasis W).\n\n(*This lemma states that the sum of two elements that are separable over a field is also separable over that same field.*)\nLemma separable_add K x y :\n separable_element K x -> separable_element K y -> separable_element K (x + y).\n\n(*This lemma states that the finite sum of a family of elements, all of which are separable over a given field, results in an element that is also separable over that field.*)\nLemma separable_sum I r (P : pred I) (v_ : I -> L) K :\n (forall i, P i -> separable_element K (v_ i)) ->\n separable_element K (\\sum_(i <- r | P i) v_ i).\n\n(*This lemma states that the sum of two elements that are purely inseparable over a field is also purely inseparable over that same field.*)\nLemma inseparable_add K x y :\n purely_inseparable_element K x -> purely_inseparable_element K y ->\n purely_inseparable_element K (x + y).\n\n(*This lemma states that the finite sum of a family of elements, all of which are purely inseparable over a given field, results in an element that is also purely inseparable over that field.*)\nLemma inseparable_sum I r (P : pred I) (v_ : I -> L) K :\n (forall i, P i -> purely_inseparable_element K (v_ i)) ->\n purely_inseparable_element K (\\sum_(i <- r | P i) v_ i).\n\n(*This lemma provides an alternative characterization of a separable extension, stating that an extension is separable if and only if every element in the extension field is separable over the base field.*)\nLemma separableP {K E} :\n reflect (forall y, y \\in E -> separable_element K y) (separable K E).\n\n(*This lemma provides an alternative characterization of a purely inseparable extension, stating that an extension is purely inseparable if and only if every element in the extension field is purely inseparable over the base field.*)\nLemma purely_inseparableP {K E} :\n reflect (forall y, y \\in E -> purely_inseparable_element K y)\n (purely_inseparable K E).\n\n(*This lemma states that an element is separable over a field if and only if the simple extension generated by that element is a separable extension over the field.*)\nLemma adjoin_separable_eq K x : separable_element K x = separable K <>%VS.\n\n(*This lemma asserts the existence of an element within a field extension that is both separable over the base field and generates an intermediate field over which the original extension is purely inseparable.*)\nLemma separable_inseparable_decomposition E K :\n {x | x \\in E /\\ separable_element K x & purely_inseparable <> E}.\n\n(*This definition constructs the separable generator of a field extension, which is an element that generates the largest separable sub-extension within the given extension.*)\nDefinition separable_generator K E : L :=\n s2val (locked (separable_inseparable_decomposition E K)).\n\n(*This lemma asserts that the separable generator of a field extension is an element of that extension.*)\nLemma separable_generator_mem E K : separable_generator K E \\in E.\n\n(*This lemma asserts that the separable generator of a field extension is a separable element over the base field.*)\nLemma separable_generatorP E K : separable_element K (separable_generator K E).\n\n(*This lemma asserts that a field extension is purely inseparable over the intermediate field formed by adjoining its separable generator to the base field.*)\nLemma separable_generator_maximal E K :\n purely_inseparable <> E.\n\n(*This lemma states that a separable field extension is contained as a subfield within the extension generated by its separable generator.*)\nLemma sub_adjoin_separable_generator E K :\n separable K E -> (E <= <>)%VS.\n\n(*This lemma states that a separable field extension is equal to the simple extension generated by its separable generator.*)\nLemma eq_adjoin_separable_generator E K :\n separable K E -> (K <= E)%VS ->\n E = <>%VS :> {vspace _}.\n\n(*This lemma states that any field is a separable extension of itself.*)\nLemma separable_refl K : separable K K.\n\n(*This lemma states that the property of being a separable field extension is transitive, meaning if a field M is a separable extension of K, and E is a separable extension of M, then E is also a separable extension of K.*)\nLemma separable_trans M K E : separable K M -> separable M E -> separable K E.\n\n(*This lemma asserts that the separability property of field extensions is preserved under taking subfields. Specifically, if a field is a separable extension of another, any subfield of the extension is a separable extension of any subfield of the base.*)\nLemma separableS K1 K2 E2 E1 : \n (K1 <= K2)%VS -> (E2 <= E1)%VS -> separable K1 E1 -> separable K2 E2.\n\n(*This lemma states that given a tower of fields where a third field is an extension of a second, which is in turn an extension of a first, if the extension of the third field over the first is separable, then the extension of the third field over the second is also separable.*)\nLemma separableSl K M E : (K <= M)%VS -> separable K E -> separable M E.\n\n(*This lemma states that given a tower of fields where a third field is an extension of a second, which is in turn an extension of a first, if the extension of the third field over the first is separable, then the extension of the second field over the first is also separable.*)\nLemma separableSr K M E : (M <= E)%VS -> separable K E -> separable K M.\n\n(*This lemma states that if all elements in a given finite sequence are separable over a base field, then the field extension obtained by adjoining all elements of that sequence to the base field is also a separable extension.*)\nLemma separable_Fadjoin_seq K rs :\n all (separable_element K) rs -> separable K <>.\n\n(*This lemma states that any field is a purely inseparable extension of itself.*)\nLemma purely_inseparable_refl K : purely_inseparable K K.\n\n(*This lemma states that the property of being a purely inseparable field extension is transitive. Specifically, for a tower of fields, if an intermediate field is a purely inseparable extension of a base field, and a larger field is a purely inseparable extension of the intermediate field, then the larger field is also a purely inseparable extension of the base field.*)\nLemma purely_inseparable_trans M K E :\n purely_inseparable K M -> purely_inseparable M E -> purely_inseparable K E.\n\nEnd Separable.\n\nArguments separable_elementP {F L K x}.\nArguments separablePn_pchar {F L K x}.\nArguments Derivation_separableP {F L K x}.\nArguments adjoin_separableP {F L K x}.\nArguments purely_inseparable_elementP_pchar {F L K x}.\nArguments separableP {F L K E}.", - "field.algebraics_fundamentals": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun ssrnat eqtype seq choice.\nFrom mathcomp Require Import div fintype path tuple bigop finset prime order.\nFrom mathcomp Require Import ssralg poly polydiv mxpoly countalg closed_field.\nFrom mathcomp Require Import ssrnum ssrint archimedean rat intdiv fingroup.\nFrom mathcomp Require Import finalg zmodp cyclic pgroup sylow vector falgebra.\nFrom mathcomp Require Import fieldext separable galois.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport Order.TTheory GroupScope GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\n(*This notation denotes the application of a given function to every coefficient of a given polynomial, resulting in a new polynomial.*)\nLocal Notation \"p ^ f\" := (map_poly f p) : ring_scope.\n(*This notation denotes the canonical lifting of a polynomial by applying the canonical algebraic embedding to each of its coefficients, transforming it into a polynomial over an extension structure.*)\nLocal Notation \"p ^@\" := (p ^ in_alg _) (at level 2, format \"p ^@\"): ring_scope.\n(*This notation denotes the vector subspace spanned by a given family of vectors within a larger vector space.*)\nLocal Notation \"<< E ; u >>\" := <>%VS.\nLocal Notation Qmorphism C := {rmorphism rat -> C}.\n\n(*This lemma states that any number field that contains an image of the rational numbers, under a morphism that maps integers to integral elements, satisfies the Archimedean axiom.*)\nLemma rat_algebraic_archimedean (C : numFieldType) (QtoC : Qmorphism C) :\n integralRange QtoC -> Num.archimedean_axiom C.\n\n(*This definition specifies a property of a function, stating that for any given element in the codomain, it is decidable whether that element belongs to the image of the function.*)\nDefinition decidable_embedding sT T (f : sT -> T) :=\n forall y, decidable (exists x, y = f x).\n\n(*This lemma states that for any ring morphism from the rational numbers to a field, if the morphism maps integers to integral elements, then it is decidable whether an element of the field is in the image of the rational numbers under this morphism.*)\nLemma rat_algebraic_decidable (C : fieldType) (QtoC : Qmorphism C) :\n integralRange QtoC -> decidable_embedding QtoC.\n\n(*This lemma states that given an element in an algebraically closed field that is integral over a subfield, one can construct its minimal polynomial over that subfield, provided that the embedding of the subfield is decidable. The constructed polynomial is monic, irreducible, and has the given element as a root.*)\nLemma minPoly_decidable_closure\n (F : fieldType) (L : closedFieldType) (FtoL : {rmorphism F -> L}) x :\n decidable_embedding FtoL -> integralOver FtoL x ->\n {p | [/\\ p \\is monic, root (p ^ FtoL) x & irreducible_poly p]}.\n\n(*This lemma states that for any field extension, the canonical embedding of the base field into the extension field maps every element of the base field to an element that is integral over the base field.*)\nLemma alg_integral (F : fieldType) (L : fieldExtType F) :\n integralRange (in_alg L).\n\nPrenex Implicits alg_integral.\n\nArguments map_poly_inj {F R} f [p1 p2].\n\n(*This theorem states the existence of an algebraically closed field that is equipped with a ring automorphism. This automorphism has two properties: it is involutive, meaning that applying it twice to any element returns the original element, and it is not the identity automorphism.*)\nTheorem Fundamental_Theorem_of_Algebraics :\n {L : closedFieldType &\n {conj : {rmorphism L -> L} | involutive conj & ~ conj =1 id}}.", - "field.algnum": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype tuple finfun bigop prime.\nFrom mathcomp Require Import ssralg poly polydiv ssrnum ssrint archimedean rat.\nFrom mathcomp Require Import finalg zmodp matrix mxalgebra mxpoly vector intdiv.\nFrom mathcomp Require Import falgebra fieldext separable galois algC cyclotomic.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope algC_scope.\nDeclare Scope algC_expanded_scope.\n\nImport GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\n(*This notation represents the canonical injection of an integer into the rational numbers.*)\nLocal Notation ZtoQ := (intr : int -> rat).\n(*This notation represents the canonical injection of an integer into the algebraic complex numbers.*)\nLocal Notation ZtoC := (intr : int -> algC).\n(*This notation represents the canonical injection of a rational number into the algebraic complex numbers.*)\nLocal Notation QtoC := (ratr : rat -> algC).\n\n(*This notation represents the function that transforms a polynomial by applying the canonical integer injection to each of its coefficients.*)\nLocal Notation intrp := (map_poly intr).\n(*This notation represents the function that converts a polynomial with integer coefficients into a polynomial with rational coefficients.*)\nLocal Notation pZtoQ := (map_poly ZtoQ).\n(*This notation represents the function that converts a polynomial with integer coefficients into a polynomial with algebraic complex coefficients.*)\nLocal Notation pZtoC := (map_poly ZtoC).\n(*This notation represents the function that converts a polynomial with rational coefficients into a polynomial with algebraic complex coefficients.*)\nLocal Notation pQtoC := (map_poly ratr).\n\n(*This definition provides the proof that the canonical map from integers to algebraic complex numbers is an injective function.*)\nLocal Definition intr_inj_ZtoC := (intr_inj : injective ZtoC).\n#[local] Hint Resolve intr_inj_ZtoC : core.\n\nSection MoreAlgCaut.\n\nImplicit Type rR : unitRingType.\n\n(*This lemma states that for any field extension of the rational numbers, scaling an element by a rational number is equivalent to multiplying by the image of that rational number within the field extension.*)\nLemma alg_num_field (Qz : fieldExtType rat) a : a%:A = ratr a :> Qz.\n\n(*This lemma states that a ring morphism from a field extension of the rationals to another ring preserves scalar multiplication by rational numbers.*)\nLemma rmorphZ_num (Qz : fieldExtType rat) rR (f : {rmorphism Qz -> rR}) a x :\n f (a *: x) = ratr a * f x.\n\n(*This lemma states that any ring morphism between two field extensions of the rational numbers is also a linear map over the rational numbers.*)\nLemma fmorph_numZ (Qz1 Qz2 : fieldExtType rat) (f : {rmorphism Qz1 -> Qz2}) :\n scalable f.\n\nEnd MoreAlgCaut.\n\n(*This lemma establishes a property related to the primitive element theorem for algebraic complex numbers, asserting that for any sequence of algebraic numbers that are polynomial evaluations, there exists an algebraic number that can be expressed as a linear combination of the sequence elements with natural number coefficients.*)\nLemma algC_PET (s : seq algC) :\n {z | exists a : nat ^ size s, z = \\sum_(i < size s) s`_i *+ a i\n & exists ps, s = [seq (pQtoC p).[z] | p <- ps]}.\n\n(*This lemma asserts that for any finite sequence of algebraic complex numbers, there exists a field extension of the rational numbers and an embedding into the algebraic complex numbers, such that the sequence is the image of a basis for the extension.*)\nLemma num_field_exists (s : seq algC) :\n {Qs : fieldExtType rat & {QsC : {rmorphism Qs -> algC}\n & {s1 : seq Qs | map QsC s1 = s & <<1 & s1>>%VS = fullv}}}.\n\n(*This definition describes the property of an algebraic complex number being a member of the vector space spanned by a given sequence of algebraic complex numbers over the field of rational numbers.*)\nDefinition in_Crat_span s x :=\n exists a : rat ^ size s, x = \\sum_i QtoC (a i) * s`_i.\n\n(*This fact asserts that it is decidable whether a given algebraic complex number belongs to the vector space spanned by a given sequence of algebraic complex numbers over the rational numbers.*)\nFact Crat_span_subproof s x : decidable (in_Crat_span s x).\n\n(*This definition creates a predicate representing the set of all algebraic complex numbers that can be expressed as a linear combination of a given sequence of algebraic complex numbers with rational coefficients.*)\nDefinition Crat_span s : pred algC := Crat_span_subproof s.\n(*This lemma provides a reflection principle, formally connecting the boolean predicate for membership in a rational span with the propositional existence of rational coefficients for the linear combination.*)\nLemma Crat_spanP s x : reflect (in_Crat_span s x) (x \\in Crat_span s).\n\n(*This lemma states that every element in a given sequence of algebraic complex numbers is contained within the rational linear span of that same sequence.*)\nLemma mem_Crat_span s : {subset s <= Crat_span s}.\n\n(*This fact asserts that the rational linear span of a sequence of algebraic complex numbers forms an additive subgroup.*)\nFact Crat_span_zmod_closed s : zmod_closed (Crat_span s).\n\nHB.instance Definition _ s := GRing.isZmodClosed.Build _ (Crat_span s)\n (Crat_span_zmod_closed s).\n\nSection NumFieldProj.\n\nVariables (Qn : fieldExtType rat) (QnC : {rmorphism Qn -> algC}).\n\n(*This lemma states that the rational linear span of a sequence of algebraic complex numbers is closed under multiplication by any rational number.*)\nLemma Crat_spanZ b a : {in Crat_span b, forall x, ratr a * x \\in Crat_span b}.\n\n(*This lemma states that the rational linear span of a sequence of algebraic complex numbers is closed under multiplication, meaning the product of any two elements within the span is also in the span.*)\nLemma Crat_spanM b : {in Crat & Crat_span b, forall a x, a * x \\in Crat_span b}.\n\n(*This lemma asserts the existence of a projection map from the algebraic complex numbers to a given field extension of the rationals, which acts as a left inverse to the canonical embedding of the field extension into the algebraic complex numbers.*)\nLemma num_field_proj : {CtoQn | CtoQn 0 = 0 & cancel QnC CtoQn}.\n\n(*This lemma states that if an automorphism of the algebraic complex numbers stabilizes the image of a given number field, then this automorphism can be restricted to an automorphism on the number field itself.*)\nLemma restrict_aut_to_num_field (nu : {rmorphism algC -> algC}) :\n (forall x, exists y, nu (QnC x) = QnC y) ->\n {nu0 : {lrmorphism Qn -> Qn} | {morph QnC : x / nu0 x >-> nu x}}.\n\n(*This lemma states that for a polynomial with rational coefficients, applying a composition of an algebraic complex number automorphism and the canonical embedding from a number field to its coefficients yields the same polynomial as applying only the canonical embedding.*)\nLemma map_Qnum_poly (nu : {rmorphism algC -> algC}) p :\n p \\in polyOver 1%VS -> map_poly (nu \\o QnC) p = (map_poly QnC p).\n\nEnd NumFieldProj.\n\n(*This lemma states that any automorphism of the algebraic complex numbers can be restricted to an automorphism on any given normal field extension of the rational numbers.*)\nLemma restrict_aut_to_normal_num_field (Qn : splittingFieldType rat)\n (QnC : {rmorphism Qn -> algC})(nu : {rmorphism algC -> algC}) :\n {nu0 : {lrmorphism Qn -> Qn} | {morph QnC : x / nu0 x >-> nu x}}.\n\n(*This lemma states that it is decidable whether a given vector of algebraic complex numbers can be expressed as a linear combination with integer coefficients of a given tuple of vectors.*)\nLemma dec_Cint_span (V : vectType algC) m (s : m.-tuple V) v :\n decidable (inIntSpan s v).\n\n(*This definition provides a predicate that determines whether an algebraic complex number belongs to the Z-module generated by a given sequence of algebraic complex numbers, essentially checking for membership in the integer span.*)\nDefinition Cint_span (s : seq algC) : pred algC :=\n fun x => dec_Cint_span (in_tuple [seq \\row_(i < 1) y | y <- s]) (\\row_i x).\n\n(*This lemma provides a reflection principle, formally connecting the boolean predicate for membership in an integer span with the propositional existence of integer coefficients for the linear combination.*)\nLemma Cint_spanP n (s : n.-tuple algC) x :\n reflect (inIntSpan s x) (x \\in Cint_span s).\n\n(*This lemma states that every element in a given sequence of algebraic complex numbers is contained within the integer linear span of that same sequence.*)\nLemma mem_Cint_span s : {subset s <= Cint_span s}.\n\n(*This lemma states that the set of all integer linear combinations of a given sequence of algebraic complex numbers forms an additive subgroup.*)\nLemma Cint_span_zmod_closed s : zmod_closed (Cint_span s).\n\nHB.instance Definition _ s := GRing.isZmodClosed.Build _ (Cint_span s)\n (Cint_span_zmod_closed s).\n\n(*This lemma asserts that any ring automorphism on a subfield of the algebraic numbers can be extended to a ring automorphism on the entire field of algebraic numbers. Given a field extension of the rationals and a ring automorphism on it, there exists a ring automorphism on the algebraic numbers that is compatible with the given automorphism on the subfield.*)\nLemma extend_algC_subfield_aut (Qs : fieldExtType rat)\n (QsC : {rmorphism Qs -> algC}) (phi : {rmorphism Qs -> Qs}) :\n {nu : {rmorphism algC -> algC} | {morph QsC : x / phi x >-> nu x}}.\n\n(*This lemma states that for any pair of coprime natural numbers, `k` and `n`, there exists a ring automorphism on the algebraic numbers that maps every n-th root of unity to its k-th power.*)\nLemma Qn_aut_exists k n :\n coprime k n ->\n {u : {rmorphism algC -> algC} | forall z, z ^+ n = 1 -> u z = z ^+ k}.\n\n(*This definition specifies the set of algebraic integers as the collection of all algebraic numbers whose minimal polynomial has only integer coefficients.*)\nDefinition Aint : {pred algC} := fun x => minCpoly x \\is a polyOver Num.int.\n\n(*This lemma states that if an algebraic number is a root of a monic polynomial with integer coefficients, then that number is an algebraic integer.*)\nLemma root_monic_Aint p x :\n root p x -> p \\is monic -> p \\is a polyOver Num.int -> x \\in Aint.\n\n(*This lemma states that any number that is both a rational number and an algebraic integer must be an integer.*)\nLemma Cint_rat_Aint z : z \\in Crat -> z \\in Aint -> z \\in Num.int.\n\n(*This lemma states that the set of integers is a subset of the set of algebraic integers, meaning every integer is an algebraic integer.*)\nLemma Aint_Cint : {subset Num.int <= Aint}.\n\n(*This lemma states that any integer, when viewed as an algebraic number, is an algebraic integer.*)\nLemma Aint_int x : x%:~R \\in Aint. \n\n(*This lemma states that the number zero is an algebraic integer.*)\nLemma Aint0 : 0 \\in Aint. \n(*This lemma states that the number one is an algebraic integer.*)\nLemma Aint1 : 1 \\in Aint. \n#[global] Hint Resolve Aint0 Aint1 : core.\n\n(*This lemma states that for any positive natural number, any root of unity of that order is an algebraic integer.*)\nLemma Aint_unity_root n x : (n > 0)%N -> n.-unity_root x -> x \\in Aint.\n\n(*This lemma states that for any natural number, any primitive root of unity of that order is an algebraic integer.*)\nLemma Aint_prim_root n z : n.-primitive_root z -> z \\in Aint.\n\n(*This lemma states that the set of natural numbers is a subset of the set of algebraic integers, meaning every natural number is an algebraic integer.*)\nLemma Aint_Cnat : {subset Num.nat <= Aint}.\n\n(*This lemma asserts that for any finite sequence of algebraic integers, there exists a set of algebraic numbers that is a subring, contains the given sequence, and is a finitely generated module over the integers. This means the subring can be represented as the set of all integer linear combinations of a finite basis.*)\nLemma Aint_subring_exists (X : seq algC) :\n {subset X <= Aint} ->\n {S : pred algC &\n subring_closed S\n /\\ {subset X <= S}\n & {Y : {n : nat & n.-tuple algC} &\n {subset tagged Y <= S}\n & forall x, reflect (inIntSpan (tagged Y) x) (x \\in S)}}.\n\nSection AlgIntSubring.\n\n(*This theorem states that if a set of algebraic numbers is closed under multiplication and is finitely generated as a module over the integers, then every element of that set is an algebraic integer.*)\nTheorem fin_Csubring_Aint S n (Y : n.-tuple algC) :\n mulr_closed S -> (forall x, reflect (inIntSpan Y x) (x \\in S)) ->\n {subset S <= Aint}.\n\n(*This corollary states that the set of algebraic integers is closed under addition, multiplication, and negation, thus forming a subring of the algebraic numbers.*)\nCorollary Aint_subring : subring_closed Aint.\n\n(*This lemma states that a ring automorphism on the algebraic numbers preserves the property of being an algebraic integer. An algebraic number is an algebraic integer if and only if its image under the automorphism is also an algebraic integer.*)\nLemma Aint_aut (nu : {rmorphism algC -> algC}) x :\n (nu x \\in Aint) = (x \\in Aint).\n\n(*This definition introduces a divisibility relation for algebraic numbers. It specifies that an algebraic number `e` divides an algebraic number `z` if the result of dividing `z` by `e` is an algebraic integer. If `e` is zero, it only divides zero.*)\nDefinition dvdA (e : Algebraics.divisor) : {pred algC} :=\n fun z => if e == 0 then z == 0 else z / e \\in Aint.\nDelimit Scope algC_scope with A.\nDelimit Scope algC_expanded_scope with Ax.\n(*This notation provides syntax for expressing divisibility in the ring of algebraic integers. The expression `e %| x` denotes that the algebraic number `e` divides the algebraic number `x`, which is true if their quotient is an algebraic integer.*)\nNotation \"e %| x\" := (x \\in dvdA e) : algC_expanded_scope.\n(*This notation expresses that a first algebraic divisor divides a second algebraic divisor.*)\nNotation \"e %| x\" := (@in_mem Algebraics.divisor x (mem (dvdA e))) : algC_scope.\n\n(*This fact asserts that for any given algebraic divisor, the set of all algebraic integers divisible by that divisor is closed under addition, negation, and multiplication by integers.*)\nFact dvdA_zmod_closed e : zmod_closed (dvdA e).\n\n(*This definition establishes that two algebraic divisors are congruent modulo a third algebraic divisor if the third divisor divides the difference of the first two.*)\nDefinition eqAmod (e x y : Algebraics.divisor) := (e %| x - y)%A.\n(*This notation represents the congruence relation between two algebraic divisors modulo a third algebraic divisor.*)\nNotation \"x == y %[mod e ]\" := (eqAmod e x y) : algC_scope.\n(*This notation represents the non-congruence relation between two algebraic divisors modulo a third algebraic divisor, meaning their congruence is false.*)\nNotation \"x != y %[mod e ]\" := (~~ (eqAmod e x y)) : algC_scope.\n\n(*This lemma states that any algebraic divisor is congruent to itself modulo any other algebraic divisor.*)\nLemma eqAmod_refl e x : (x == x %[mod e])%A.\n\n#[global] Hint Resolve eqAmod_refl : core.\n\n(*This lemma states that the congruence of a first algebraic divisor to a second one modulo a third is equivalent to the congruence of the second to the first modulo the same third divisor.*)\nLemma eqAmod_sym e x y : ((x == y %[mod e]) = (y == x %[mod e]))%A.\n\n(*This lemma states that if a first algebraic divisor is congruent to a second, and the second is congruent to a third, all modulo the same divisor, then the first is congruent to the third.*)\nLemma eqAmod_trans e y x z :\n (x == y %[mod e] -> y == z %[mod e] -> x == z %[mod e])%A.\n\n(*This lemma states that if two algebraic divisors are congruent modulo a third, then the congruence of the first to an arbitrary divisor is equivalent to the congruence of the second to that same arbitrary divisor.*)\nLemma eqAmod_transl e x y z :\n (x == y %[mod e])%A -> (x == z %[mod e])%A = (y == z %[mod e])%A.\n\n(*This lemma states that if two algebraic divisors are congruent modulo a third, then the congruence of an arbitrary divisor to the first is equivalent to the congruence of that arbitrary divisor to the second.*)\nLemma eqAmod_transr e x y z :\n (x == y %[mod e])%A -> (z == x %[mod e])%A = (z == y %[mod e])%A.\n\n(*This lemma states that an algebraic divisor is congruent to zero modulo a second algebraic divisor if and only if the second divisor divides the first one.*)\nLemma eqAmod0 e x : (x == 0 %[mod e])%A = (e %| x)%A.\n\n(*This lemma states that the congruence of the additive inverse of a first algebraic divisor to a second, modulo a third, is equivalent to the congruence of the first divisor to the additive inverse of the second, modulo the same third divisor.*)\nLemma eqAmodN e x y : (- x == y %[mod e])%A = (x == - y %[mod e])%A.\n\n(*This lemma establishes the equivalence between a modular congruence and the one obtained by adding the same algebraic divisor to the right of both terms.*)\nLemma eqAmodDr e x y z : (y + x == z + x %[mod e])%A = (y == z %[mod e])%A.\n\n(*This lemma establishes the equivalence between a modular congruence and the one obtained by adding the same algebraic divisor to the left of both terms.*)\nLemma eqAmodDl e x y z : (x + y == x + z %[mod e])%A = (y == z %[mod e])%A.\n\n(*This lemma states that if a first pair of algebraic divisors are congruent and a second pair are also congruent, all modulo the same divisor, then the sum of the first elements of each pair is congruent to the sum of the second elements of each pair.*)\nLemma eqAmodD e x1 x2 y1 y2 :\n (x1 == x2 %[mod e] -> y1 == y2 %[mod e] -> x1 + y1 == x2 + y2 %[mod e])%A.\n\n(*This lemma states that any algebraic divisor is congruent to zero modulo itself.*)\nLemma eqAmodm0 e : (e == 0 %[mod e])%A.\n\n#[global] Hint Resolve eqAmodm0 : core.\n\n(*This lemma states that for algebraic integers, if two of them are congruent modulo an algebraic divisor, then multiplying both by the same algebraic integer on the right preserves the congruence.*)\nLemma eqAmodMr e :\n {in Aint, forall z x y, x == y %[mod e] -> x * z == y * z %[mod e]}%A.\n\n(*This lemma states that for algebraic integers, if two of them are congruent modulo an algebraic divisor, multiplying both by another algebraic integer on the left maintains the congruence.*)\nLemma eqAmodMl e :\n {in Aint, forall z x y, x == y %[mod e] -> z * x == z * y %[mod e]}%A.\n\n(*This lemma states that for any algebraic integer, its product with an algebraic divisor is congruent to zero modulo that same divisor.*)\nLemma eqAmodMl0 e : {in Aint, forall x, x * e == 0 %[mod e]}%A.\n\n(*This lemma states that for any algebraic integer, the product of an algebraic divisor with that integer is congruent to zero modulo that same divisor.*)\nLemma eqAmodMr0 e : {in Aint, forall x, e * x == 0 %[mod e]}%A.\n\n(*This lemma states that for any two algebraic integers, the sum of a multiple of an algebraic divisor and a second algebraic integer is congruent to the second integer modulo that divisor.*)\nLemma eqAmod_addl_mul e : {in Aint, forall x y, x * e + y == y %[mod e]}%A.\n\n(*This lemma states that for algebraic integers, if a first pair is congruent and a second pair is congruent, all modulo the same algebraic divisor, then the product of the first elements of each pair is congruent to the product of the second elements of each pair.*)\nLemma eqAmodM e : {in Aint &, forall x1 y2 x2 y1,\n x1 == x2 %[mod e] -> y1 == y2 %[mod e] -> x1 * y1 == x2 * y2 %[mod e]}%A.\n\n(*This lemma states that for rational numbers, the concept of modular congruence with respect to an algebraic divisor is equivalent to the standard modular congruence defined for rational numbers.*)\nLemma eqAmod_rat :\n {in Crat & &, forall e m n, (m == n %[mod e])%A = (m == n %[mod e])%C}.\n\n(*This lemma states that for a rational number, being congruent to zero modulo an algebraic divisor is equivalent to being divisible by that divisor in the context of rational numbers.*)\nLemma eqAmod0_rat : {in Crat &, forall e n, (n == 0 %[mod e])%A = (e %| n)%C}.\n\n(*This lemma states that for natural numbers, modular congruence with respect to an algebraic divisor given as a natural number is equivalent to the standard modular congruence defined for natural numbers.*)\nLemma eqAmod_nat (e m n : nat) : (m == n %[mod e])%A = (m == n %[mod e])%N.\n\n(*This lemma states that for a natural number, being congruent to zero modulo an algebraic divisor given as a natural number is equivalent to being divisible by that number in the standard sense for natural numbers.*)\nLemma eqAmod0_nat (e m : nat) : (m == 0 %[mod e])%A = (e %| m)%N.\n\n(*This definition computes the multiplicative order of an algebraic number that is a root of unity. It identifies this order as the index of the cyclotomic polynomial that is the minimal polynomial of the given number.*)\nDefinition orderC x :=\n let p := minCpoly x in\n oapp val 0 [pick n : 'I_(2 * size p ^ 2) | p == intrp 'Phi_n].\n\n(*This notation represents the multiplicative order of an algebraic number that is a root of unity.*)\nNotation \"#[ x ]\" := (orderC x) : C_scope.\n\n(*This lemma states that any algebraic number that is a root of unity, when raised to the power of its multiplicative order, equals one.*)\nLemma exp_orderC x : x ^+ #[x]%C = 1.\n\n(*This lemma states that if an algebraic number raised to a given integer power equals one, then the multiplicative order of the number must divide that integer.*)\nLemma dvdn_orderC x n : (#[x]%C %| n)%N = (x ^+ n == 1).", - "field.cyclotomic": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype tuple finfun bigop prime.\nFrom mathcomp Require Import ssralg poly finset fingroup finalg zmodp cyclic.\nFrom mathcomp Require Import ssrnum ssrint archimedean polydiv intdiv mxpoly.\nFrom mathcomp Require Import rat vector falgebra fieldext separable galois algC.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\nSection CyclotomicPoly.\n\nSection NzRing.\n\nVariable R : nzRingType.\n\n(*This definition defines the nth cyclotomic polynomial for a given ring element and a natural number n. The polynomial is constructed as the product of linear factors of the form (the variable minus the ring element raised to the power of k), for all natural numbers k that are less than n and coprime to n.*)\nDefinition cyclotomic (z : R) n :=\n \\prod_(k < n | coprime k n) ('X - (z ^+ k)%:P).\n\n(*This lemma states that the cyclotomic polynomial, defined for a ring element and a natural number, is always monic, meaning its leading coefficient is one.*)\nLemma cyclotomic_monic z n : cyclotomic z n \\is monic.\n\n(*This lemma states that the size of the nth cyclotomic polynomial, which is its degree plus one, is equal to the value of Euler's totient function for n, plus one.*)\nLemma size_cyclotomic z n : size (cyclotomic z n) = (totient n).+1.\n\nEnd NzRing.\n\n(*This lemma states that for any integral domain and any natural number n, if the representation of n within the domain is not the zero element, then the polynomial 'variable to the power of n, minus one' is separable, meaning it has distinct roots in a splitting field.*)\nLemma separable_Xn_sub_1 (R : idomainType) n :\n n%:R != 0 :> R -> @separable_poly R ('X^n - 1).\n\nSection Field.\n\nVariables (F : fieldType) (n : nat) (z : F).\nHypothesis prim_z : n.-primitive_root z.\n(*This definition establishes a proof that the order of a primitive root of unity is a natural number greater than zero.*)\nLet n_gt0 := prim_order_gt0 prim_z.\n\n(*This lemma states that a field element is a root of the nth cyclotomic polynomial if and only if it is an nth primitive root of unity.*)\nLemma root_cyclotomic x : root (cyclotomic z n) x = n.-primitive_root x.\n\n(*This lemma states that the polynomial 'variable to the power of n, minus one' is equal to the product of d-th cyclotomic polynomials, where d ranges over all divisors of the natural number n.*)\nLemma prod_cyclotomic :\n 'X^n - 1 = \\prod_(d <- divisors n) cyclotomic (z ^+ (n %/ d)) d.\n\nEnd Field.\n\nEnd CyclotomicPoly.\n\n(*This notation represents the canonical injection function from the integers to the rational numbers.*)\nLocal Notation ZtoQ := (intr : int -> rat).\n(*This notation represents the canonical injection function from the integers to the algebraic numbers.*)\nLocal Notation ZtoC := (intr : int -> algC).\n(*This notation represents the canonical injection function from the rational numbers to the algebraic numbers.*)\nLocal Notation QtoC := (ratr : rat -> algC).\n\n(*This notation represents a function that transforms a polynomial by applying the canonical integer injection to each of its coefficients.*)\nLocal Notation intrp := (map_poly intr).\n(*This notation represents a function that converts a polynomial with integer coefficients into a polynomial with rational coefficients by applying the integer-to-rational number injection to each coefficient.*)\nLocal Notation pZtoQ := (map_poly ZtoQ).\n(*This notation represents a function that converts a polynomial with integer coefficients into a polynomial with algebraic number coefficients by applying the integer-to-algebraic number injection to each coefficient.*)\nLocal Notation pZtoC := (map_poly ZtoC).\n(*This notation represents a function that converts a polynomial with rational coefficients into a polynomial with algebraic number coefficients by applying the rational-to-algebraic number injection to each coefficient.*)\nLocal Notation pQtoC := (map_poly ratr).\n\n(*This definition captures the property that the canonical map from integers to algebraic numbers is injective, meaning distinct integers are mapped to distinct algebraic numbers.*)\nLocal Definition algC_intr_inj := @intr_inj algC.\n#[local] Hint Resolve algC_intr_inj : core.\n(*This notation refers to the cancellation property stating that applying the floor function to an integer that has been embedded into the field of algebraic numbers results in the original integer.*)\nLocal Notation intCK := (@intrKfloor algC).\n\n(*This lemma states that for any positive natural number n, there exists an algebraic number that is an nth primitive root of unity.*)\nLemma C_prim_root_exists n : (n > 0)%N -> {z : algC | n.-primitive_root z}.\n\n(*This definition specifies the nth cyclotomic polynomial with integer coefficients. It is constructed by first defining the polynomial over the algebraic numbers using a primitive root of unity, and then taking the integer floor of each coefficient.*)\nDefinition Cyclotomic n : {poly int} :=\n let: exist z _ := C_prim_root_exists (ltn0Sn n.-1) in\n map_poly Num.floor (cyclotomic z n).\n\n(*This notation denotes the nth cyclotomic polynomial with integer coefficients, which takes a natural number n as input.*)\nNotation \"''Phi_' n\" := (Cyclotomic n)\n (at level 8, n at level 2, format \"''Phi_' n\").\n\n(*This lemma states that the nth cyclotomic polynomial with integer coefficients is monic, meaning its leading coefficient is one.*)\nLemma Cyclotomic_monic n : 'Phi_n \\is monic.\n\n(*This lemma states that if an algebraic number is an n-th primitive root of unity, then embedding the nth integer cyclotomic polynomial into the ring of polynomials over algebraic numbers results in the same polynomial as that defined directly using the given primitive root.*)\nLemma Cintr_Cyclotomic n z :\n n.-primitive_root z -> pZtoC 'Phi_n = cyclotomic z n.\n\n(*This lemma states that for any positive natural number n, the polynomial 'variable to the power of n, minus one' is equal to the product of all d-th integer cyclotomic polynomials, where d ranges over the divisors of n.*)\nLemma prod_Cyclotomic n :\n (n > 0)%N -> \\prod_(d <- divisors n) 'Phi_d = 'X^n - 1.\n\n(*This lemma states that the 0th integer cyclotomic polynomial is the constant polynomial equal to one.*)\nLemma Cyclotomic0 : 'Phi_0 = 1.\n\n(*This lemma states that the size of the nth integer cyclotomic polynomial, which is its degree plus one, is equal to the value of Euler's totient function for n, plus one.*)\nLemma size_Cyclotomic n : size 'Phi_n = (totient n).+1.\n\n(*This lemma states that the nth integer cyclotomic polynomial, when its coefficients are mapped to the field of rational numbers, is the minimal polynomial of any nth primitive root of unity over the rational numbers.*)\nLemma minCpoly_cyclotomic n z :\n n.-primitive_root z -> minCpoly z = cyclotomic z n.", - "field.algC": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun ssrnat eqtype seq choice.\nFrom mathcomp Require Import div fintype path bigop finset prime order ssralg.\nFrom mathcomp Require Import poly polydiv mxpoly generic_quotient countalg.\nFrom mathcomp Require Import ssrnum closed_field ssrint archimedean rat intdiv.\nFrom mathcomp Require Import algebraics_fundamentals.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope C_scope.\nDeclare Scope C_core_scope.\nDeclare Scope C_expanded_scope.\n\nImport Order.TTheory GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\n(*This record defines the structure of a complex-like field, which is an algebraically closed field equipped with an involutive conjugation ring morphism that is not the identity function.*)\nHB.factory Record isComplex L of GRing.ClosedField L := {\n conj : {rmorphism L -> L};\n conjK : involutive conj;\n conj_nt : ~ conj =1 id\n}.\n\nHB.builders Context L of isComplex L.\n\n(*This lemma states that the element two is not equal to the zero element of the underlying field.*)\nLemma nz2: 2 != 0 :> L.\n\n(*This lemma states that the function which multiplies an element of the field by two is injective, meaning that if two elements produce the same result when multiplied by two, they must be equal.*)\nLemma mul2I: injective (fun z : L => z *+ 2).\n\n(*This definition provides a specific value for the square root of a given element, obtained by solving the polynomial equation where the square of the variable equals the given element.*)\nDefinition sqrt x : L :=\n sval (sig_eqW (@solve_monicpoly _ 2%N (nth 0 [:: x]) isT)).\n\n(*This lemma states that squaring the square root of a given element yields the original element.*)\nLemma sqrtK x: sqrt x ^+ 2 = x.\n\n(*This lemma states that if the square of a first element is equal to a second element, then the first element must be either the positive or the negative square root of the second element.*)\nLemma sqrtE x y: y ^+ 2 = x -> {b : bool | y = (-1) ^+ b * sqrt x}.\n\n(*This definition introduces the imaginary unit as the square root of negative one.*)\nDefinition i := sqrt (- 1).\n\n(*This lemma states that the square of the product of the imaginary unit and another element is equal to the negative of the square of that other element.*)\nLemma sqrMi x: (i * x) ^+ 2 = - x ^+ 2.\n\n(*This lemma states that the conjugate of the imaginary unit is equal to its additive inverse.*)\nLemma iJ : conj i = - i.\n\n(*This definition introduces the norm of an element, which corresponds to its modulus or absolute value.*)\nDefinition norm x := sqrt x * conj (sqrt x).\n\n(*This lemma states that the square of the norm of an element is equal to the product of that element and its conjugate.*)\nLemma normK x : norm x ^+ 2 = x * conj x.\n\n(*This lemma states that if a first element squared is equal to a second element, then the norm of the second element is equal to the product of the first element and its conjugate.*)\nLemma normE x y : y ^+ 2 = x -> norm x = y * conj y.\n\n(*This lemma states that if the norm of an element is zero, then the element itself must be zero.*)\nLemma norm_eq0 x : norm x = 0 -> x = 0.\n\n(*This lemma states that the norm is multiplicative, meaning the norm of the product of two elements is equal to the product of their individual norms.*)\nLemma normM x y : norm (x * y) = norm x * norm y.\n\n(*This lemma states that the norm of the additive inverse of an element is the same as the norm of the element itself.*)\nLemma normN x : norm (- x) = norm x.\n\n(*This definition introduces a 'less than or equal to' relation between two elements, which holds if the norm of their difference is equal to the difference itself.*)\nDefinition le x y := norm (y - x) == y - x.\n(*This definition introduces a 'strictly less than' relation between two elements, which holds if they are not equal and the first is less than or equal to the second.*)\nDefinition lt x y := (y != x) && le x y.\n\n(*This lemma states that an element is greater than or equal to zero if and only if its norm is equal to the element itself.*)\nLemma posE x: le 0 x = (norm x == x).\n\n(*This lemma states that the 'less than or equal to' relation between two elements is equivalent to their difference being greater than or equal to zero.*)\nLemma leB x y: le x y = le 0 (y - x).\n\n(*This lemma establishes that an element is greater than or equal to zero if and only if it can be expressed as the product of some element and its conjugate.*)\nLemma posP x : reflect (exists y, x = y * conj y) (le 0 x).\n\n(*This lemma states that any element that is greater than or equal to zero must be its own conjugate.*)\nLemma posJ x : le 0 x -> conj x = x.\n\n(*This lemma states that the 'less than or equal to' relation defines a total order on the subset of elements that are greater than or equal to zero.*)\nLemma pos_linear x y : le 0 x -> le 0 y -> le x y || le y x.\n\n(*This lemma states that adding a strictly positive element to a non-negative element results in a strictly positive sum.*)\nLemma sposDl x y : lt 0 x -> le 0 y -> lt 0 (x + y).\n\n(*This lemma states that the sum of two strictly positive elements is also strictly positive.*)\nLemma sposD x y : lt 0 x -> lt 0 y -> lt 0 (x + y).\n\n(*This lemma states the triangle inequality for the norm, asserting that the norm of a sum of two elements is less than or equal to the sum of their individual norms.*)\nLemma normD x y : le (norm (x + y)) (norm x + norm y).\n\nHB.instance Definition _ :=\n Num.IntegralDomain_isNumRing.Build L normD sposD norm_eq0\n pos_linear normM (fun x y => erefl (le x y))\n (fun x y => erefl (lt x y)).\n\nHB.instance Definition _ :=\n Num.NumField_isImaginary.Build L (sqrtK _) normK.\n\nHB.end.\n\nModule Algebraics.\n\nModule Type Specification.\n\nParameter type : Type.\n\nParameter conjMixin : Num.ClosedField type.\n\nParameter isCountable : Countable type.\n\nAxiom archimedean : Num.archimedean_axiom (Num.ClosedField.Pack conjMixin).\n\nAxiom algebraic : integralRange (@ratr (Num.ClosedField.Pack conjMixin)).\n\nEnd Specification.\n\nModule Implementation : Specification.\n\n(*This definition establishes a type for the field of algebraic numbers, based on a construction that realizes the fundamental theorem of algebra for this field.*)\nDefinition L := tag Fundamental_Theorem_of_Algebraics.\n\n(*This definition provides the conjugation operation for the field of algebraic numbers as a ring morphism.*)\nDefinition conjL : {rmorphism L -> L} :=\n s2val (tagged Fundamental_Theorem_of_Algebraics).\n\n(*This fact asserts that the conjugation operation on the field of algebraic numbers is involutive, meaning applying it twice is equivalent to the identity function.*)\nFact conjL_K : involutive conjL.\n\n(*This fact asserts that the conjugation operation on the field of algebraic numbers is not the identity function.*)\nFact conjL_nt : ~ conjL =1 id.\n\n(*This definition introduces a type that is definitionally equivalent to the type of algebraic numbers, often used for technical reasons related to type class inference.*)\nDefinition L' : Type := eta L.\nHB.instance Definition _ := GRing.ClosedField.on L'.\nHB.instance Definition _ := isComplex.Build L' conjL_K conjL_nt.\n\n(*A notation for the type of the ambient algebraically closed field in which algebraic numbers are defined.*)\nNotation cfType := (L' : closedFieldType).\n\n(*Defines the canonical ring morphism that embeds the rational numbers into the ambient algebraically closed field.*)\nDefinition QtoL : {rmorphism _ -> _} := @ratr cfType.\n\n(*A notation for the function that transforms a polynomial with rational coefficients into a polynomial with coefficients in the ambient algebraically closed field by applying the canonical embedding to each coefficient.*)\nNotation pQtoL := (map_poly QtoL).\n\n(*Defines a function that computes the value of an algebraic number within the ambient algebraically closed field. It takes a pair representing an algebraic number, consisting of a polynomial with rational coefficients and a root index, and returns the corresponding root of the polynomial.*)\nDefinition rootQtoL p_j :=\n if p_j.1 == 0 then 0 else\n (sval (closed_field_poly_normal (pQtoL p_j.1)))`_p_j.2.\n\n(*Defines the equivalence relation on representations of algebraic numbers. Two representations are considered equivalent if they evaluate to the same value in the ambient algebraically closed field.*)\nDefinition eq_root p_j q_k := rootQtoL p_j == rootQtoL q_k.\n\n(*This fact establishes that the relation comparing representations of algebraic numbers for equality of their values is a proper equivalence relation.*)\nFact eq_root_is_equiv : equiv_class_of eq_root.\n\nCanonical eq_root_equiv := EquivRelPack eq_root_is_equiv.\n\n(*Defines the type of algebraic numbers as the set of equivalence classes of their representations, where two representations are equivalent if they correspond to the same value.*)\nDefinition type : Type := {eq_quot eq_root}%qT.\n\nHB.instance Definition _ : EqQuotient _ eq_root type := EqQuotient.on type.\nHB.instance Definition _ := Choice.on type.\nHB.instance Definition _ := isCountable.Build type\n (pcan_pickleK (can_pcan reprK)).\n\n(*Defines the function that maps an abstract algebraic number to its concrete value in the ambient algebraically closed field. This serves as the canonical embedding of the type of algebraic numbers into the closed field.*)\nDefinition CtoL (u : type) := rootQtoL (repr u).\n\n(*This fact establishes that the function mapping abstract algebraic numbers to their values in the ambient field is injective, meaning distinct algebraic numbers have distinct values.*)\nFact CtoL_inj : injective CtoL.\n\n(*This fact asserts that the value of any abstract algebraic number within the ambient field is integral over the rational numbers.*)\nFact CtoL_P u : integralOver QtoL (CtoL u).\n\n(*This fact provides a constructive proof that for any element in the ambient field that is integral over the rational numbers, there exists a corresponding abstract algebraic number whose value is that element.*)\nFact LtoC_subproof z : integralOver QtoL z -> {u | CtoL u = z}.\n\n(*Defines a function that maps an element of the ambient field back to an abstract algebraic number, provided a proof that the element is integral over the rationals.*)\nDefinition LtoC z Az := sval (@LtoC_subproof z Az).\n(*This fact states that converting an integral element of the ambient field to an abstract algebraic number and then mapping it back to the field yields the original element.*)\nFact LtoC_K z Az : CtoL (@LtoC z Az) = z.\n\n(*This fact states that mapping an abstract algebraic number to its value in the ambient field and then converting that value back to an abstract algebraic number yields the original abstract number.*)\nFact CtoL_K u : LtoC (CtoL_P u) = u.\n\n(*Defines the additive identity, zero, for the type of algebraic numbers, as the element corresponding to the zero of the ambient field.*)\nDefinition zero := LtoC (integral0 _).\n(*Defines addition for algebraic numbers. The operation is performed by mapping the two algebraic numbers to their values in the ambient field, adding these values, and then mapping the result back to the type of algebraic numbers.*)\nDefinition add u v := LtoC (integral_add (CtoL_P u) (CtoL_P v)).\n(*Defines the additive inverse of an algebraic number. The operation is performed by mapping the algebraic number to its value in the ambient field, taking its additive inverse there, and mapping the result back.*)\nDefinition opp u := LtoC (integral_opp (CtoL_P u)).\n\n(*This fact establishes that the addition operation on algebraic numbers is associative.*)\nFact addA : associative add.\n\n(*This fact establishes that the addition operation on algebraic numbers is commutative.*)\nFact addC : commutative add.\n\n(*This fact establishes that the defined zero is the left identity for addition of algebraic numbers.*)\nFact add0 : left_id zero add.\n\n(*This fact establishes that for any algebraic number, its additive inverse is a true left inverse with respect to addition.*)\nFact addN : left_inverse zero opp add.\n\nHB.instance Definition _ := GRing.isZmodule.Build type addA addC add0 addN.\n\n(*This fact establishes that the canonical embedding of algebraic numbers into the ambient field is a Z-module morphism, meaning it preserves the additive group structure.*)\nFact CtoL_is_zmod_morphism : zmod_morphism CtoL.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `CtoL_inj_is_zmod_morphism` instead\")]\n(*This definition provides an alias for the proof that the mapping from algebraic numbers to their values in the ambient field is a Z-module morphism.*)\nDefinition CtoL_is_additive := CtoL_is_zmod_morphism.\nHB.instance Definition _ := GRing.isZmodMorphism.Build type L' CtoL\n CtoL_is_zmod_morphism.\n\n(*Defines the multiplicative identity, one, for the type of algebraic numbers, as the element corresponding to the one of the ambient field.*)\nDefinition one := LtoC (integral1 _).\n(*Defines multiplication for algebraic numbers. The operation is performed by mapping the two algebraic numbers to their values in the ambient field, multiplying these values, and then mapping the result back to the type of algebraic numbers.*)\nDefinition mul u v := LtoC (integral_mul (CtoL_P u) (CtoL_P v)).\n(*Defines the multiplicative inverse of an algebraic number. The operation works by mapping the algebraic number to its value in the ambient field, computing the inverse of that value, and then mapping the result back into the type of algebraic numbers.*)\nDefinition inv u := LtoC (integral_inv (CtoL_P u)).\n\n(*This fact establishes that the multiplication operation on algebraic numbers is associative.*)\nFact mulA : associative mul.\n\n(*This fact establishes that the multiplication operation on algebraic numbers is commutative.*)\nFact mulC : commutative mul.\n\n(*This fact establishes that the defined one is the left identity for multiplication of algebraic numbers.*)\nFact mul1 : left_id one mul.\n\n(*This fact establishes that multiplication of algebraic numbers is left-distributive over addition.*)\nFact mulD : left_distributive mul +%R.\n\n(*This fact asserts that the multiplicative identity element is distinct from the additive identity element.*)\nFact one_nz : one != 0 :> type.\n\nHB.instance Definition _ :=\n GRing.Zmodule_isComNzRing.Build type mulA mulC mul1 mulD one_nz.\n\n(*This fact asserts that the `CtoL` function preserves the structure of a multiplicative monoid, meaning it maps the product of two elements to the product of their images and maps the multiplicative identity to the multiplicative identity.*)\nFact CtoL_is_monoid_morphism : monoid_morphism CtoL.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `CtoL_is_monoid_morphism` instead\")]\n(*This deprecated definition states that the `CtoL` function is multiplicative, meaning it preserves products and the multiplicative identity. It serves as an alias for the more modern `CtoL_is_monoid_morphism` property.*)\nDefinition CtoL_is_multiplicative :=\n (fun g => (g.2,g.1)) CtoL_is_monoid_morphism.\nHB.instance Definition _ := GRing.isMonoidMorphism.Build type L' CtoL\n CtoL_is_monoid_morphism.\n\n(*This fact states that for any non-zero element, multiplying it by its multiplicative inverse results in the multiplicative identity.*)\nFact mulVf u : u != 0 -> inv u * u = 1.\n\n(*This fact defines the multiplicative inverse of the additive identity element to be the additive identity itself.*)\nFact inv0 : inv 0 = 0. \n\nHB.instance Definition _ := GRing.ComNzRing_isField.Build type mulVf inv0.\n\n(*This fact asserts that the underlying type forms an algebraically closed field, meaning every non-constant univariate polynomial with coefficients from this type has at least one root within the type.*)\nFact closedFieldAxiom : GRing.closed_field_axiom type.\n\nHB.instance Definition _ := Field_isAlgClosed.Build type closedFieldAxiom.\n\n(*This fact establishes that for any element, its conjugate, when mapped to the appropriate structure, is integral over the rational numbers.*)\nFact conj_subproof u : integralOver QtoL (conjL (CtoL u)).\n\n(*This fact asserts that the conjugation function preserves the structure of addition and scaling by natural numbers.*)\nFact conj_is_nmod_morphism : nmod_morphism (fun u => LtoC (conj_subproof u)).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `conj_is_nmod_morphism` instead\")]\n(*This deprecated definition states that the conjugation function is semi-additive, meaning it preserves addition and scaling by natural numbers. It is an alias for `conj_is_nmod_morphism`.*)\nDefinition conj_is_semi_additive := conj_is_nmod_morphism.\n\n(*This fact asserts that the conjugation function preserves the structure of addition and additive inverse, making it a module morphism over the integers.*)\nFact conj_is_zmod_morphism : {morph (fun u => LtoC (conj_subproof u)) : x / - x}.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `CtoL_inj_is_zmod_morphism` instead\")]\n(*This deprecated definition states that the conjugation function is additive, meaning it preserves addition and additive inverse. It is an alias for `conj_is_zmod_morphism`.*)\nDefinition conj_is_additive := conj_is_zmod_morphism.\n\n(*This fact asserts that the conjugation function preserves the structure of a multiplicative monoid, meaning it distributes over multiplication and maps the multiplicative identity to itself.*)\nFact conj_is_monoid_morphism : monoid_morphism (fun u => LtoC (conj_subproof u)).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `conj_is_monoid_morphism` instead\")]\n(*This deprecated definition states that the conjugation function is multiplicative. It is an alias for `conj_is_monoid_morphism`.*)\nDefinition conj_is_multiplicative :=\n (fun g => (g.2,g.1)) conj_is_monoid_morphism.\n(*This definition establishes the conjugation function as a ring morphism, which is a function that preserves both the additive and multiplicative structures of the ring.*)\nDefinition conj : {rmorphism type -> type} :=\n GRing.RMorphism.Pack\n (GRing.RMorphism.Class\n (GRing.isNmodMorphism.Build _ _ _ conj_is_nmod_morphism)\n (GRing.isMonoidMorphism.Build _ _ _ conj_is_monoid_morphism)).\n\n(*This lemma states that the conjugation function is an involution, meaning that applying it twice to any element returns the original element.*)\nLemma conjK : involutive conj.\n\n(*This fact asserts that the conjugation function is not the identity function, meaning there exists at least one element that is not equal to its own conjugate.*)\nFact conj_nt : ~ conj =1 id.\n\n(*This definition packages the properties of the underlying type to form a mixin for a structure of a field with a conjugation, based on it being an algebraically closed field.*)\nDefinition conjMixin := Num.ClosedField.on type.\n\n(*This lemma states that every element of the underlying type is algebraic, meaning it is a root of a non-zero polynomial with rational coefficients.*)\nLemma algebraic : integralRange (@ratr type).\n\n(*This fact asserts that the underlying type satisfies the Archimedean axiom, which implies that for any element, there exists a natural number whose magnitude is greater than the magnitude of that element.*)\nFact archimedean : Num.archimedean_axiom type.\n\n(*This definition establishes that the underlying type is countable, meaning its elements can be put into a one-to-one correspondence with the natural numbers.*)\nDefinition isCountable := Countable.on type.\n\nEnd Implementation.\n\n(*This definition provides an alias named `divisor` for the main underlying type of algebraic numbers defined within the implementation module.*)\nDefinition divisor := Implementation.type.\n\n#[export] HB.instance Definition _ := Implementation.conjMixin.\n#[export] HB.instance Definition _ :=\n Num.NumDomain_bounded_isArchimedean.Build Implementation.type\n Implementation.archimedean.\n(*A local notation for the underlying type representing algebraic numbers.*)\nLocal Notation algC := type.\n\n(*This notation defines QtoC as an alias for the canonical embedding function that maps a rational number to its corresponding representation in the field of algebraic numbers.*)\nLocal Notation QtoC := (ratr : rat -> algC).\n(*A local notation for the function that converts a polynomial with rational coefficients into a polynomial with algebraic number coefficients by applying the rational-to-algebraic embedding to each coefficient.*)\nLocal Notation pQtoC := (map_poly QtoC : {poly rat} -> {poly algC}).\n\n(*This fact asserts the existence of an algebraic number whose square is equal to the additive inverse of the multiplicative identity, corresponding to the imaginary unit.*)\nFact algCi_subproof : {i : algC | i ^+ 2 = -1}.\n\n(**)\nVariant getCrat_spec : Type := GetCrat_spec CtoQ of cancel QtoC CtoQ.\n\n(*This fact provides a proof that there exists a function that can map an algebraic number which is rational back to its original rational number representation, acting as a partial inverse to the embedding of rationals.*)\nFact getCrat_subproof : getCrat_spec.\n\n(*This fact asserts that for any given algebraic number, there exists a unique monic polynomial with rational coefficients, known as its minimal polynomial, which has the given number as a root and divides any other rational-coefficient polynomial that also has that number as a root.*)\nFact minCpoly_subproof (x : algC) :\n {p : {poly rat} | p \\is monic & forall q, root (pQtoC q) x = (p %| q)%R}.\n\n(*This definition explicitly converts an algebraic number to the `divisor` type, which serves as an alias for the type of algebraic numbers.*)\nDefinition algC_divisor (x : algC) := x : divisor.\n(*This definition provides a function to convert an integer into its corresponding representation as a `divisor` by using the canonical ring embedding.*)\nDefinition int_divisor m := m%:~R : divisor.\n(*This definition provides a function to convert a natural number into its corresponding representation as a `divisor` by using the canonical ring embedding.*)\nDefinition nat_divisor n := n%:R : divisor.\n\nEnd Internals.\n\nModule Import Exports.\n\nImport Implementation Internals.\n\n(*A notation for the type of algebraic numbers, which are the complex numbers that are roots of non-zero polynomials with rational coefficients.*)\nNotation algC := type.\nDelimit Scope C_scope with C.\nDelimit Scope C_core_scope with Cc.\nDelimit Scope C_expanded_scope with Cx.\nOpen Scope C_core_scope.\n(*A notation for the type of algebraic numbers, viewed as a type equipped with a decidable equality relation.*)\nNotation algCeq := (type : eqType).\n(*A notation for the type of algebraic numbers, viewed as a structure that supports addition, additive inverses, and a zero element.*)\nNotation algCzmod := (type : zmodType).\n(*A notation for the type of algebraic numbers, viewed as a commutative ring structure in which the multiplicative identity is distinct from the additive identity.*)\nNotation algCnzRing := (type : nzRingType).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use algCnzRing instead.\")]\n(*A deprecated notation for the type of algebraic numbers, viewed as a commutative ring structure in which the multiplicative identity is distinct from the additive identity.*)\nNotation algCring := (type : nzRingType).\n(*A notation for the type of algebraic numbers, viewed as a commutative ring where every non-zero element has a multiplicative inverse.*)\nNotation algCuring := (type : unitRingType).\n(*A notation for the type of algebraic numbers, viewed as a numeric domain with characteristic zero that supports an embedding of the rational numbers.*)\nNotation algCnum := (type : numDomainType).\n(*A notation for the type of algebraic numbers, viewed as a field, which is a structure supporting addition, subtraction, multiplication, and division by non-zero elements.*)\nNotation algCfield := (type : fieldType).\n(*A notation for the type of algebraic numbers, viewed as a field with characteristic zero.*)\nNotation algCnumField := (type : numFieldType).\n(*A notation for the type of algebraic numbers, viewed as an algebraically closed field with characteristic zero, where every non-constant polynomial has a root.*)\nNotation algCnumClosedField := (type : numClosedFieldType).\n\n(*A notation representing the set of real algebraic numbers, defined as the subset of algebraic numbers that are real.*)\nNotation Creal := (@Num.Def.Rreal algCnum).\n\n(*This definition provides a function that converts an algebraic number, which is provably rational, into its corresponding rational number representation.*)\nDefinition getCrat := let: GetCrat_spec CtoQ _ := getCrat_subproof in CtoQ.\n(*This definition specifies a predicate that evaluates to true if a given algebraic number is rational, by checking if converting it to a rational number and back to an algebraic number recovers the original value.*)\nDefinition Crat : {pred algC} := fun x => ratr (getCrat x) == x.\n\n(*This definition computes the minimal polynomial of a given algebraic number. The result is the unique monic polynomial with rational coefficients of least degree for which the given algebraic number is a root.*)\nDefinition minCpoly x : {poly algC} :=\n let: exist2 p _ _ := minCpoly_subproof x in map_poly ratr p.\n\nCoercion nat_divisor : nat >-> divisor.\nCoercion int_divisor : int >-> divisor.\nCoercion algC_divisor : algC >-> divisor.\n\n(*This lemma states that a natural number is equal to its canonical representation as a divisor within the algebraic number field.*)\nLemma nCdivE (p : nat) : p = p%:R :> divisor. \n(*This lemma states that an integer is equal to its canonical representation as a divisor within the algebraic number field.*)\nLemma zCdivE (p : int) : p = p%:~R :> divisor. \n(*This definition bundles two lemmas, one for natural numbers and one for integers, which state that these numbers are equal to their canonical representations as divisors.*)\nDefinition CdivE := (nCdivE, zCdivE).\n\n(*This definition specifies a predicate for divisibility among algebraic numbers. An algebraic number is considered divisible by a given divisor if the quotient of the number by the divisor results in an integer. If the divisor is zero, the number must also be zero.*)\nDefinition dvdC (x : divisor) : {pred algC} :=\n fun y => if x == 0 then y == 0 else y / x \\in Num.int.\n(*A notation for the predicate that checks if a given divisor divides an algebraic number. This is true if the quotient of the algebraic number by the divisor is an integer.*)\nNotation \"x %| y\" := (y \\in dvdC x) : C_expanded_scope.\n(*A notation for the divisibility relation between two algebraic numbers, asserting that the first number divides the second.*)\nNotation \"x %| y\" := (@in_mem divisor y (mem (dvdC x))) : C_scope.\n\n(*This definition establishes that two algebraic numbers are congruent modulo a third algebraic number if their difference is divisible by that third number.*)\nDefinition eqCmod (e x y : divisor) := (e %| x - y)%C.\n\n(*A notation for checking if two algebraic numbers are congruent modulo a third algebraic number.*)\nNotation \"x == y %[mod e ]\" := (eqCmod e x y) : C_scope.\n(*A notation for checking if two algebraic numbers are not congruent modulo a third algebraic number.*)\nNotation \"x != y %[mod e ]\" := (~~ (x == y %[mod e])%C) : C_scope.\n\nEnd Exports.\n\nModule HBExports. HB.reexport. End HBExports.\n\nEnd Algebraics.\n\nExport Algebraics.Exports.\n\nExport Algebraics.HBExports.\n\nSection AlgebraicsTheory.\n\nImplicit Types (x y z : algC) (n : nat) (m : int) (b : bool).\nImport Algebraics.Internals.\n\n(*This notation represents the canonical function that converts an integer into its corresponding rational number representation.*)\nLocal Notation ZtoQ := (intr : int -> rat).\n(*This notation represents the canonical function that converts an integer into its corresponding algebraic number representation.*)\nLocal Notation ZtoC := (intr : int -> algC).\n(*A local notation for the canonical function that embeds the rational numbers into the type of algebraic numbers.*)\nLocal Notation QtoC := (ratr : rat -> algC).\n(*This notation represents a function that attempts to convert an algebraic number into its corresponding rational number representation, if such a representation exists.*)\nLocal Notation CtoQ := getCrat.\n(*This notation represents a function that transforms a polynomial by applying the canonical injection from the coefficient ring to a target ring on each of its coefficients.*)\nLocal Notation intrp := (map_poly intr).\n(*This notation represents a function that converts a polynomial with integer coefficients into a polynomial with rational coefficients by applying the integer-to-rational conversion to each coefficient.*)\nLocal Notation pZtoQ := (map_poly ZtoQ).\n(*This notation represents a function that converts a polynomial with integer coefficients into a polynomial with algebraic coefficients by applying the integer-to-algebraic-number conversion to each coefficient.*)\nLocal Notation pZtoC := (map_poly ZtoC).\n(*This notation represents a function that converts a polynomial with rational coefficients into a polynomial with algebraic coefficients by applying the rational-to-algebraic-number conversion to each coefficient.*)\nLocal Notation pQtoC := (map_poly ratr).\n\n(*This statement asserts that the canonical function mapping integers to algebraic numbers is injective, meaning distinct integers map to distinct algebraic numbers.*)\nLet intr_inj_ZtoC := (intr_inj : injective ZtoC).\n#[local] Hint Resolve intr_inj_ZtoC : core.\n\n(*This definition asserts that the equality comparison of two natural numbers holds if and only if their corresponding representations as algebraic numbers are equal.*)\nDefinition eqC_nat n p : (n%:R == p%:R :> algC) = (n == p) := eqr_nat _ n p.\n(*This definition asserts that the less-than-or-equal comparison of two natural numbers holds if and only if their corresponding representations as algebraic numbers satisfy the less-than-or-equal relation.*)\nDefinition leC_nat n p : (n%:R <= p%:R :> algC) = (n <= p)%N := ler_nat _ n p.\n(*This definition asserts that the less-than comparison of two natural numbers holds if and only if their corresponding representations as algebraic numbers satisfy the less-than relation.*)\nDefinition ltC_nat n p : (n%:R < p%:R :> algC) = (n < p)%N := ltr_nat _ n p.\n(*This definition establishes that the characteristic of the field of algebraic numbers is zero.*)\nDefinition Cpchar : [pchar algC] =i pred0 := @pchar_num _.\n\n(*This definition bundles a collection of proofs demonstrating that the canonical injection from rational numbers to algebraic numbers preserves algebraic structures such as zero, one, addition, multiplication, and order relations.*)\nDefinition CratrE :=\n let CnF : numClosedFieldType := algC in\n let QtoCm : {rmorphism _ -> _} := @ratr CnF in\n ((rmorph0 QtoCm, rmorph1 QtoCm, rmorphMn QtoCm, rmorphN QtoCm, rmorphD QtoCm),\n (rmorphM QtoCm, rmorphXn QtoCm, fmorphV QtoCm),\n (rmorphMz QtoCm, rmorphXz QtoCm, @ratr_norm CnF, @ratr_sg CnF),\n =^~ (@ler_rat CnF, @ltr_rat CnF, (inj_eq (fmorph_inj QtoCm)))).\n\n(*This definition bundles a collection of proofs demonstrating that the canonical injection from integers to algebraic numbers preserves algebraic structures such as zero, one, addition, multiplication, and order relations.*)\nDefinition CintrE :=\n let CnF : numClosedFieldType := algC in\n let ZtoCm : {rmorphism _ -> _} := *~%R (1 : CnF) in\n ((rmorph0 ZtoCm, rmorph1 ZtoCm, rmorphMn ZtoCm, rmorphN ZtoCm, rmorphD ZtoCm),\n (rmorphM ZtoCm, rmorphXn ZtoCm),\n (rmorphMz ZtoCm, @intr_norm CnF, @intr_sg CnF),\n =^~ (@ler_int CnF, @ltr_int CnF, (inj_eq (@intr_inj CnF)))).\n\n(*This statement asserts that the algebraic number representation of two is not equal to the algebraic number representation of zero.*)\nLet nz2 : 2 != 0 :> algC.\n\n(*This definition states that any element of the type of algebraic numbers is algebraic, meaning it is a root of a non-zero polynomial with rational coefficients.*)\nDefinition algC_algebraic x := Algebraics.Implementation.algebraic x.\n\n(*This lemma states that any algebraic number can be expressed as the sum of its real part and its imaginary part multiplied by the imaginary unit.*)\nLemma algCrect x : x = 'Re x + 'i * 'Im x.\n\n(*This lemma states that the real part of any algebraic number is itself a real algebraic number.*)\nLemma algCreal_Re x : 'Re x \\is Creal.\n\n(*This lemma states that the imaginary part of any algebraic number is itself a real algebraic number.*)\nLemma algCreal_Im x : 'Im x \\is Creal.\n\nHint Resolve algCreal_Re algCreal_Im : core.\n\n(*This lemma establishes the equivalence between the divisibility of two algebraic numbers and the existence of an integer multiplier that relates them. Specifically, one algebraic number divides another if and only if the second is an integer multiple of the first.*)\nLemma dvdCP x y : reflect (exists2 z, z \\in Num.int & y = z * x) (x %| y)%C.\n\n(*This lemma states that if a non-negative algebraic number divides another non-negative algebraic number, then there exists a natural number such that the second number is the product of the first number and the natural number's canonical representation as an algebraic number.*)\nLemma dvdCP_nat x y : 0 <= x -> 0 <= y -> (x %| y)%C -> {n | y = n%:R * x}.\n\n(*This lemma states that any algebraic number divides the algebraic number zero.*)\nLemma dvdC0 x : (x %| 0)%C.\n\n(*This lemma states that the algebraic number zero divides another algebraic number if and only if that other algebraic number is itself zero.*)\nLemma dvd0C x : (0 %| x)%C = (x == 0).\n\n(*This lemma states that if an algebraic number divides another algebraic number, it also divides the product of the second algebraic number and any integer.*)\nLemma dvdC_mull x y z : y \\in Num.int -> (x %| z)%C -> (x %| y * z)%C.\n\n(*This lemma states that if an algebraic number divides another algebraic number, it also divides the product of any integer and the second algebraic number.*)\nLemma dvdC_mulr x y z : y \\in Num.int -> (x %| z)%C -> (x %| z * y)%C.\n\n(*This lemma states that for three complex numbers, if the second number is non-zero, then the product of the first and second numbers divides the product of the third and second numbers if and only if the first number divides the third number.*)\nLemma dvdC_mul2r x y z : y != 0 -> (x * y %| z * y)%C = (x %| z)%C.\n\n(*This lemma states that for three complex numbers, if the second number is non-zero, then the product of the second and first numbers divides the product of the second and third numbers if and only if the first number divides the third number.*)\nLemma dvdC_mul2l x y z : y != 0 -> (y * x %| y * z)%C = (x %| z)%C.\n\n(*This lemma states that divisibility for complex numbers is transitive; if a first complex number divides a second one, and the second one divides a third one, then the first complex number divides the third one.*)\nLemma dvdC_trans x y z : (x %| y)%C -> (y %| z)%C -> (x %| z)%C.\n\n(*This lemma states that divisibility for complex numbers is reflexive, meaning any complex number divides itself.*)\nLemma dvdC_refl x : (x %| x)%C.\n\nHint Resolve dvdC_refl : core.\n\n(*This lemma states that for any given complex number, the set of all complex numbers divisible by it forms a Z-module.*)\nLemma dvdC_zmod x : zmod_closed (dvdC x).\n\nHB.instance Definition _ x := GRing.isZmodClosed.Build _ (dvdC x) (dvdC_zmod x).\n\n(*This lemma states that for any two natural numbers, one divides the other in the complex number system if and only if it divides the other in the natural number system.*)\nLemma dvdC_nat (p n : nat) : (p %| n)%C = (p %| n)%N.\n\n(*This lemma states that for a natural number and an integer, the natural number divides the integer within the complex number system if and only if the natural number divides the absolute value of the integer within the natural number system.*)\nLemma dvdC_int (p : nat) x :\n x \\in Num.int -> (p %| x)%C = (p %| `|Num.floor x|)%N.\n\n(*This lemma states that modular equality for complex numbers is reflexive; any complex number is congruent to itself modulo any other complex number.*)\nLemma eqCmod_refl e x : (x == x %[mod e])%C.\n\n(*This lemma states that any complex number is congruent to zero modulo itself.*)\nLemma eqCmodm0 e : (e == 0 %[mod e])%C. \nHint Resolve eqCmod_refl eqCmodm0 : core.\n\n(*This lemma states that a complex number is congruent to zero modulo a second complex number if and only if the second complex number divides the first one.*)\nLemma eqCmod0 e x : (x == 0 %[mod e])%C = (e %| x)%C.\n\n(*This lemma states that modular equality for complex numbers is symmetric; if a first complex number is congruent to a second one modulo a third, then the second is also congruent to the first modulo the third.*)\nLemma eqCmod_sym e x y : ((x == y %[mod e]) = (y == x %[mod e]))%C.\n\n(*This lemma states that modular equality for complex numbers is transitive; if a first complex number is congruent to a second, and the second is congruent to a third, all modulo the same number, then the first is congruent to the third.*)\nLemma eqCmod_trans e y x z :\n (x == y %[mod e] -> y == z %[mod e] -> x == z %[mod e])%C.\n\n(*This lemma states that if two complex numbers are congruent modulo a third, then a fourth complex number is congruent to the first if and only if it is congruent to the second, all modulo the same number.*)\nLemma eqCmod_transl e x y z :\n (x == y %[mod e])%C -> (x == z %[mod e])%C = (y == z %[mod e])%C.\n\n(*This lemma states that if two complex numbers are congruent modulo a third, then the first is congruent to a fourth complex number if and only if the second is congruent to the fourth, all modulo the same number.*)\nLemma eqCmod_transr e x y z :\n (x == y %[mod e])%C -> (z == x %[mod e])%C = (z == y %[mod e])%C.\n\n(*This lemma states that for complex numbers, the additive inverse of a first number is congruent to a second number modulo a third if and only if the first number is congruent to the additive inverse of the second number modulo the third.*)\nLemma eqCmodN e x y : (- x == y %[mod e])%C = (x == - y %[mod e])%C.\n\n(*This lemma states that adding the same complex number to both sides of a modular equality does not change the truth of the equality; it is a right-cancellation law for addition.*)\nLemma eqCmodDr e x y z : (y + x == z + x %[mod e])%C = (y == z %[mod e])%C.\n\n(*This lemma states that adding the same complex number to the left of both sides of a modular equality does not change the truth of the equality; it is a left-cancellation law for addition.*)\nLemma eqCmodDl e x y z : (x + y == x + z %[mod e])%C = (y == z %[mod e])%C.\n\n(*This lemma states that modular equality for complex numbers is compatible with addition; if two pairs of complex numbers are congruent modulo a given number, then their sums are also congruent modulo that same number.*)\nLemma eqCmodD e x1 x2 y1 y2 :\n (x1 == x2 %[mod e] -> y1 == y2 %[mod e] -> x1 + y1 == x2 + y2 %[mod e])%C.\n\n(*This lemma states that for any three natural numbers, two of them are congruent modulo the third in the complex number system if and only if they are congruent modulo the third in the natural number system.*)\nLemma eqCmod_nat (e m n : nat) : (m == n %[mod e])%C = (m == n %[mod e]).\n\n(*This lemma states that for two natural numbers, the first is congruent to zero modulo the second in the complex number system if and only if the second divides the first in the natural number system.*)\nLemma eqCmod0_nat (e m : nat) : (m == 0 %[mod e])%C = (e %| m)%N.\n\n(*This lemma states that for integers, modular equality with respect to a complex modulus is preserved under right multiplication by any integer.*)\nLemma eqCmodMr e :\n {in Num.int, forall z x y, x == y %[mod e] -> x * z == y * z %[mod e]}%C.\n\n(*This lemma states that for integers, modular equality with respect to a complex modulus is preserved under left multiplication by any integer.*)\nLemma eqCmodMl e :\n {in Num.int, forall z x y, x == y %[mod e] -> z * x == z * y %[mod e]}%C.\n\n(*This lemma states that for any integer and any complex number, their product is congruent to zero modulo that complex number.*)\nLemma eqCmodMl0 e : {in Num.int, forall x, x * e == 0 %[mod e]}%C.\n\n(*This lemma states that for any complex number and any integer, their product is congruent to zero modulo that complex number.*)\nLemma eqCmodMr0 e : {in Num.int, forall x, e * x == 0 %[mod e]}%C.\n\n(*This lemma states that for any two integers and a complex modulus, adding a multiple of the modulus to the second integer results in a number that is congruent to the second integer.*)\nLemma eqCmod_addl_mul e : {in Num.int, forall x y, x * e + y == y %[mod e]}%C.\n\n(*This lemma states that modular equality for integers with respect to a complex modulus is compatible with multiplication; if two pairs of integers are congruent modulo a given complex number, then their products are also congruent modulo that same number.*)\nLemma eqCmodM e : {in Num.int & Num.int, forall x1 y2 x2 y1,\n x1 == x2 %[mod e] -> y1 == y2 %[mod e] -> x1 * y1 == x2 * y2 %[mod e]}%C.\n\n(*This lemma states that the function converting a complex number to a rational number is a left inverse of the function converting a rational number to a complex number.*)\nLemma ratCK : cancel QtoC CtoQ.\n\n(*This lemma states that for complex numbers that are representable as rationals, the function converting a rational to a complex number is a left inverse of the function converting such a complex number back to a rational.*)\nLemma getCratK : {in Crat, cancel CtoQ QtoC}.\n\n(*This lemma states that applying the conversion from a rational number to a complex number always results in a complex number that belongs to the set of rationals embedded within the complex numbers.*)\nLemma Crat_rat (a : rat) : QtoC a \\in Crat.\n\n(*This lemma provides a characterization of the set of complex numbers that represent rationals, stating that a complex number belongs to this set if and only if there exists a rational number that maps to it under the standard embedding.*)\nLemma CratP x : reflect (exists a, x = QtoC a) (x \\in Crat).\n\n(*This lemma states that the complex number zero is an element of the set of complex numbers with rational coefficients.*)\nLemma Crat0 : 0 \\in Crat. \n(*This lemma states that the complex number one is an element of the set of complex numbers with rational coefficients.*)\nLemma Crat1 : 1 \\in Crat. \n#[local] Hint Resolve Crat0 Crat1 : core.\n\n(*This fact asserts that the set of complex numbers with rational coefficients is closed under addition, negation, multiplication, and multiplicative inversion of non-zero elements.*)\nFact Crat_divring_closed : divring_closed Crat.\n\n(*This lemma states that any subset of the complex numbers that is closed under division ring operations contains the set of all complex numbers with rational coefficients.*)\nLemma rpred_Crat (S : divringClosed algC) : {subset Crat <= S}.\n\n(*This lemma states that for any complex number with rational coefficients, its complex conjugate is equal to itself, which implies it is a real number.*)\nLemma conj_Crat z : z \\in Crat -> z^* = z.\n\n(*This lemma states that the set of complex numbers with rational coefficients is a subset of the set of real algebraic numbers.*)\nLemma Creal_Crat : {subset Crat <= Creal}.\n\n(*This lemma states that a rational number is an integer if and only if its embedding as a complex number belongs to the set of integers.*)\nLemma Cint_rat a : (QtoC a \\in Num.int) = (a \\in Num.int).\n\n(*This lemma characterizes the minimal polynomial of a complex algebraic number. It asserts the existence of a unique monic polynomial with rational coefficients such that its complex embedding is the minimal polynomial, and any other rational polynomial that has the algebraic number as a root is a multiple of this minimal polynomial.*)\nLemma minCpolyP x :\n {p : {poly rat} | minCpoly x = pQtoC p /\\ p \\is monic\n & forall q, root (pQtoC q) x = (p %| q)%R}.\n\n(*This lemma states that the minimal polynomial of a complex algebraic number is a monic polynomial.*)\nLemma minCpoly_monic x : minCpoly x \\is monic.\n\n(*This lemma states that the minimal polynomial of a complex algebraic number is never the zero polynomial.*)\nLemma minCpoly_eq0 x : (minCpoly x == 0) = false.\n\n(*This lemma states that any complex algebraic number is a root of its own minimal polynomial.*)\nLemma root_minCpoly x : root (minCpoly x) x.\n\n(*This lemma states that the degree of the minimal polynomial of a complex algebraic number is strictly greater than zero.*)\nLemma size_minCpoly x : (1 < size (minCpoly x))%N.\n\nSection AutC.\n\nImplicit Type nu : {rmorphism algC -> algC}.\n\n(*This lemma states that any ring automorphism of the field of complex algebraic numbers acts as the identity function when restricted to the subset of complex numbers with rational coefficients.*)\nLemma aut_Crat nu : {in Crat, nu =1 id}.\n\n(*This lemma states that a complex algebraic number has rational coefficients if and only if its image under any ring automorphism of the complex algebraic numbers also has rational coefficients.*)\nLemma Crat_aut nu x : (nu x \\in Crat) = (x \\in Crat).\n\n(*This lemma provides the constructive proof that for any ring automorphism of the complex algebraic numbers and any element in its codomain, there exists a corresponding element in the domain that maps to it, establishing surjectivity.*)\nLemma algC_invaut_subproof nu x : {y | nu y = x}.\n\n(*This definition specifies the inverse of a given ring automorphism of the complex algebraic numbers, which maps an element to its preimage under the automorphism.*)\nDefinition algC_invaut nu x := sval (algC_invaut_subproof nu x).\n\n(*This lemma states that composing the inverse of a ring automorphism of algebraic numbers with the automorphism itself results in the identity function, confirming it is a left inverse.*)\nLemma algC_invautK nu : cancel (algC_invaut nu) nu.\n\n(*This lemma states that composing a ring automorphism of algebraic numbers with its inverse results in the identity function, confirming it is a right inverse.*)\nLemma algC_autK nu : cancel nu (algC_invaut nu).\n\n(*This fact asserts that the inverse of a ring automorphism of the complex algebraic numbers is a morphism of modules over the integers, meaning it preserves addition and negation.*)\nFact algC_invaut_is_zmod_morphism nu : zmod_morphism (algC_invaut nu).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `algC_invaut_is_zmod_morphism` instead\")]\n(*This is a deprecated definition aliasing `algC_invaut_is_zmod_morphism`, which states that the inverse of a ring automorphism of algebraic numbers preserves addition. Use `algC_invaut_is_zmod_morphism` instead.*)\nDefinition algC_invaut_is_additive := algC_invaut_is_zmod_morphism.\n\n(*This fact asserts that the inverse of a ring automorphism of the complex algebraic numbers is a monoid morphism, meaning it preserves multiplication and the multiplicative identity.*)\nFact algC_invaut_is_monoid_morphism nu : monoid_morphism (algC_invaut nu).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `algC_invaut_is_monoid_morphism` instead\")]\n(*This is a deprecated definition asserting that the inverse of a ring automorphism of algebraic numbers preserves multiplication. Use `algC_invaut_is_monoid_morphism` instead.*)\nDefinition algC_invaut_is_multiplicative nu :=\n (fun g => (g.2,g.1)) (algC_invaut_is_monoid_morphism nu).\nHB.instance Definition _ (nu : {rmorphism algC -> algC}) :=\n GRing.isZmodMorphism.Build algC algC (algC_invaut nu)\n (algC_invaut_is_zmod_morphism nu).\n\n(*This lemma states that the minimal polynomial of a complex algebraic number is invariant under any ring automorphism of the complex algebraic numbers.*)\nLemma minCpoly_aut nu x : minCpoly (nu x) = minCpoly x.\n\nEnd AutC.\n\nEnd AlgebraicsTheory.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use Cpchar instead.\")]\n(*A deprecated notation for the characteristic polynomial of a complex algebraic number, which is now aliased to `Cpchar` for parsing purposes. Use `Cpchar` instead.*)\nNotation Cchar := (Cpchar) (only parsing).\n\n#[global] Hint Resolve Crat0 Crat1 dvdC0 dvdC_refl eqCmod_refl eqCmodm0 : core.\n\n(*This notation represents the application of a function to each coefficient of a given polynomial.*)\nLocal Notation \"p ^^ f\" := (map_poly f p)\n (at level 30, f at level 30, format \"p ^^ f\").\n\n(*This record defines the type of real algebraic numbers as a subset of complex algebraic numbers, bundling a complex algebraic number with a proof that it is a real number.*)\nRecord algR := in_algR {algRval :> algC; algRvalP : algRval \\is Creal}.\n\nHB.instance Definition _ := [isSub for algRval].\nHB.instance Definition _ := [Countable of algR by <:].\nHB.instance Definition _ := [SubChoice_isSubIntegralDomain of algR by <:].\nHB.instance Definition _ := [SubIntegralDomain_isSubField of algR by <:].\nHB.instance Definition _ : Order.isPOrder ring_display algR :=\n Order.CancelPartial.Pcan _ valK.\n(*This lemma states that the standard less-than-or-equal-to relation on the set of real algebraic numbers is total, meaning that for any two real algebraic numbers, one is less than or equal to the other.*)\nLemma total_algR : total (<=%O : rel (algR : porderType _)).\n\nHB.instance Definition _ := Order.POrder_isTotal.Build _ algR total_algR.\n\n(*This lemma states that the embedding function from the type of real algebraic numbers to the type of complex algebraic numbers preserves addition and negation.*)\nLemma algRval_is_zmod_morphism : zmod_morphism algRval. \n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `algRval_is_zmod_morphism` instead\")]\n(*This is a deprecated definition aliasing `algRval_is_zmod_morphism`, which states that the embedding of real algebraic numbers into complex algebraic numbers preserves addition. Use `algRval_is_zmod_morphism` instead.*)\nDefinition algRval_is_additive := algRval_is_zmod_morphism.\n(*This lemma states that the embedding function from the type of real algebraic numbers to the type of complex algebraic numbers preserves multiplication and the multiplicative identity.*)\nLemma algRval_is_monoid_morphism : monoid_morphism algRval. \n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `algRval_is_monoid_morphism` instead\")]\n(*This definition asserts that the function which embeds algebraic real numbers into algebraic complex numbers preserves the multiplication operation.*)\nDefinition algRval_is_multiplicative :=\n (fun g => (g.2,g.1)) algRval_is_monoid_morphism.\nHB.instance Definition _ := GRing.isZmodMorphism.Build algR algC algRval\n algRval_is_zmod_morphism.\nHB.instance Definition _ := GRing.isMonoidMorphism.Build algR algC algRval\n algRval_is_monoid_morphism.\n\n(*This definition provides a norm for an algebraic real number, which is a non-negative algebraic real number representing its magnitude.*)\nDefinition algR_norm (x : algR) : algR := in_algR (normr_real (val x)).\n(*This lemma states that the norm of the sum of two algebraic real numbers is less than or equal to the sum of their individual norms.*)\nLemma algR_ler_normD x y : algR_norm (x + y) <= (algR_norm x + algR_norm y).\n\n(*This lemma states that an algebraic real number is equal to zero if and only if its norm is equal to zero.*)\nLemma algR_normr0_eq0 x : algR_norm x = 0 -> x = 0.\n\n(*This lemma states that the norm of an algebraic real number scaled by a natural number is equal to the norm of the number scaled by the same natural number.*)\nLemma algR_normrMn x n : algR_norm (x *+ n) = algR_norm x *+ n.\n\n(*This lemma states that the norm of the additive inverse of an algebraic real number is equal to the norm of the original number.*)\nLemma algR_normrN x : algR_norm (- x) = algR_norm x.\n\nSection Num.\n\nSection withz.\n(*This definition introduces a local name for the algebraic real number zero, intended for use as a reference in subsequent lemmas concerning positivity and order relations.*)\nLet z : algR := 0.\n(*This lemma states that the sum of two positive algebraic real numbers is also a positive algebraic real number.*)\nLemma algR_addr_gt0 (x y : algR) : z < x -> z < y -> z < x + y.\n\n(*This lemma states that any two non-negative algebraic real numbers are comparable, meaning one is less than or equal to the other.*)\nLemma algR_ger_leVge (x y : algR) : z <= x -> z <= y -> (x <= y) || (y <= x).\n\n(*This lemma asserts that the norm function for algebraic real numbers is multiplicative, meaning the norm of a product of two numbers is the product of their norms.*)\nLemma algR_normrM : {morph algR_norm : x y / x * y}.\n\n(*This lemma provides a definition for the less-than-or-equal relation on algebraic real numbers, stating that one number is less than or equal to another if and only if their difference is equal to its own norm, which implies that the difference is non-negative.*)\nLemma algR_ler_def (x y : algR) : (x <= y) = (algR_norm (y - x) == y - x).\n\nEnd withz.\n\nHB.instance Definition _ := Num.Zmodule_isNormed.Build _ algR\n algR_ler_normD algR_normr0_eq0 algR_normrMn algR_normrN.\n(*This definition provides a mixin that establishes that the type of algebraic real numbers satisfies the Archimedean axiom, which states that for any number, there exists a natural number greater than it.*)\nDefinition algR_archiFieldMixin : Num.archimedean_axiom algR.\n\nHB.instance Definition _ := Num.NumDomain_bounded_isArchimedean.Build algR\n algR_archiFieldMixin.\n\n(*This definition constructs a polynomial with algebraic real coefficients associated with an algebraic complex number. If the number is real, the polynomial is linear of the form 'X minus the number'. If the number is not real, the polynomial is quadratic of the form 'X squared minus twice the real part of the number times X plus the squared norm of the number'.*)\nDefinition algR_pfactor (x : algC) : {poly algR} :=\n if x \\is Creal =P true is ReflectT xR then 'X - (in_algR xR)%:P else\n 'X^2 - (in_algR (Creal_Re x) *+ 2) *: 'X + ((in_algR (normr_real x))^+2)%:P.\nNotation algC_pfactor x := (algR_pfactor x ^^ algRval).\n\n(*This lemma states that for an algebraic complex number that is real, its associated polynomial with real coefficients is 'X minus the number'.*)\nLemma algR_pfactorRE (x : algC) (xR : x \\is Creal) :\n algR_pfactor x = 'X - (in_algR xR)%:P.\n\n(*This lemma states that for an algebraic complex number that is real, its associated polynomial with complex coefficients is 'X minus the number'.*)\nLemma algC_pfactorRE (x : algC) : x \\is Creal ->\n algC_pfactor x = 'X - x%:P.\n\n(*This lemma states that for a non-real algebraic complex number, its associated polynomial with real coefficients is a quadratic polynomial given by 'X squared minus two times the real part of the number times X, plus the squared norm of the number'.*)\nLemma algR_pfactorCE (x : algC) : x \\isn't Creal ->\n algR_pfactor x =\n 'X^2 - (in_algR (Creal_Re x) *+ 2) *: 'X + ((in_algR (normr_real x))^+2)%:P.\n\n(*This lemma states that for a non-real algebraic complex number, its associated polynomial with complex coefficients is the product of 'X minus the number' and 'X minus the complex conjugate of the number'.*)\nLemma algC_pfactorCE (x : algC) : x \\isn't Creal ->\n algC_pfactor x = ('X - x%:P) * ('X - x^*%:P).\n\n(*This lemma provides a unified expression for the complex polynomial factor of an algebraic complex number, which simplifies to 'X minus the number' if the number is real, and to the product of 'X minus the number' and 'X minus its conjugate' if the number is not real.*)\nLemma algC_pfactorE x :\n algC_pfactor x = ('X - x%:P) * ('X - x^*%:P) ^+ (x \\isn't Creal).\n\n(*This lemma states that the size of the complex polynomial factor of an algebraic complex number is two if the number is real, and three if it is not real.*)\nLemma size_algC_pfactor x : size (algC_pfactor x) = (x \\isn't Creal).+2.\n\n(*This lemma states that the size of the real polynomial factor of an algebraic complex number is two if the number is real, and three if it is not real.*)\nLemma size_algR_pfactor x : size (algR_pfactor x) = (x \\isn't Creal).+2.\n\n(*This lemma states that the complex polynomial factor associated with any algebraic complex number is never the zero polynomial.*)\nLemma algC_pfactor_eq0 x : (algC_pfactor x == 0) = false.\n\n(*This lemma states that the real polynomial factor associated with any algebraic complex number is never the zero polynomial.*)\nLemma algR_pfactor_eq0 x : (algR_pfactor x == 0) = false.\n\n(*This lemma states that when the complex polynomial factor of a non-real algebraic complex number is evaluated at any real value, the result is a strictly positive real number.*)\nLemma algC_pfactorCgt0 x y : x \\isn't Creal -> y \\is Creal ->\n (algC_pfactor x).[y] > 0.\n\n(*This lemma relates the sign of a linear polynomial at two points to the position of its root. It states that for three real algebraic complex numbers, where the first defines a linear polynomial and the other two are evaluation points with the first point less than or equal to the second, the product of the polynomial evaluations at these two points is less than or equal to zero if and only if the root of the polynomial lies between the two evaluation points.*)\nLemma algR_pfactorR_mul_gt0 (x a b : algC) :\n x \\is Creal -> a \\is Creal -> b \\is Creal ->\n a <= b ->\n ((algC_pfactor x).[a] * (algC_pfactor x).[b] <= 0) =\n (a <= x <= b).\n\n(*This lemma states that the complex polynomial factor associated with any algebraic complex number is a monic polynomial, meaning its leading coefficient is one.*)\nLemma monic_algC_pfactor x : algC_pfactor x \\is monic.\n\n(*This lemma states that the real polynomial factor associated with any algebraic complex number is a monic polynomial, meaning its leading coefficient is one.*)\nLemma monic_algR_pfactor x : algR_pfactor x \\is monic.\n\n(*This lemma states that any non-zero polynomial with algebraic real coefficients can be completely factored over the algebraic complex numbers. The factorization consists of the polynomial's leading coefficient multiplied by a product of the canonical polynomial factors associated with its complex roots.*)\nLemma poly_algR_pfactor (p : {poly algR}) :\n { r : seq algC |\n p ^^ algRval = val (lead_coef p) *: \\prod_(z <- r) algC_pfactor z }.\n\n(*This definition provides a mixin that establishes that the type of algebraic real numbers satisfies the axioms for a real closed field, which implies properties such as every positive number having a square root and every odd-degree polynomial having a root within the field.*)\nDefinition algR_rcfMixin : Num.real_closed_axiom algR.", - "field.qfpoly": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype tuple div bigop binomial finset finfun.\nFrom mathcomp Require Import ssralg countalg finalg poly polydiv qpoly perm.\nFrom mathcomp Require Import fingroup falgebra fieldext finfield galois.\nFrom mathcomp Require Import finalg zmodp matrix vector.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GRing.Theory.\nImport Pdiv.CommonRing.\nImport Pdiv.RingMonic.\nImport Pdiv.Field.\nImport FinRing.Theory.\nLocal Open Scope ring_scope.\n\nReserved Notation \"{ 'poly' '%/' p 'with' mi }\"\n (p at level 2, mi at level 10, format \"{ 'poly' '%/' p 'with' mi }\").\n\nSection DomainDef.\n\nVariable R : idomainType.\nVariable h : {poly R}.\n\n(*This definition specifies a predicate for a polynomial over an integral domain, which is satisfied if the polynomial is both irreducible and has a leading coefficient of one.*)\nDefinition monic_irreducible_poly (p : {poly R}) :=\n ((irreducible_poly p) * (p \\is monic))%type.\nHypothesis hI : monic_irreducible_poly h.\n\n(*This definition constructs the type for the quotient ring of polynomials modulo a given monic and irreducible polynomial. The resulting type represents elements as polynomials where two polynomials are considered equivalent if their difference is a multiple of the given irreducible polynomial.*)\nDefinition qfpoly : monic_irreducible_poly h -> predArgType :=\n fun=> {poly %/ h}.\n\nEnd DomainDef.\n\n(*This notation provides a syntax for defining the quotient ring of polynomials modulo a given monic and irreducible polynomial. The first argument is the polynomial used for the modulus, and the second argument is the proof that this polynomial is both monic and irreducible.*)\nNotation \"{ 'poly' '%/' p 'with' hi }\" := (@qfpoly _ p hi).\n\nSection iDomain.\n\nVariable R : idomainType.\nVariable h : {poly R}.\nHypothesis hI : monic_irreducible_poly h.\n\n(*A notation that provides a shorthand for the proof that the polynomial `h` is monic, meaning that its leading coefficient is one.*)\nLocal Notation hQ := (mk_monic h).\n\nHypothesis hI : monic_irreducible_poly h.\n\nHB.instance Definition _ := GRing.ComUnitRing.on {poly %/ h with hI}.\n\n(*This lemma states that applying the function to make a polynomial monic to an already monic polynomial returns the original polynomial unchanged.*)\nLemma mk_monicE : mk_monic h = h.\n\n(*This lemma states that any non-zero element of the quotient ring of polynomials, when viewed as a polynomial representative, is coprime to the irreducible polynomial that defines the quotient.*)\nLemma coprimep_unit (p : {poly %/ h}) : p != 0%R -> coprimep hQ p.\n\n(*This lemma states that for any non-zero element in the quotient polynomial ring, multiplying it by its computed inverse results in the multiplicative identity element, establishing the existence of a right inverse.*)\nLemma qpoly_mulVp (p : {poly %/ h}) : p != 0%R -> (qpoly_inv p * p = 1)%R.\n\n(*This lemma states that the multiplicative inverse of the zero element in the quotient polynomial ring is defined to be the zero element itself.*)\nLemma qpoly_inv0 : qpoly_inv 0%R = 0%R :> {poly %/ h}.\n\nHB.instance Definition _ := GRing.ComUnitRing_isField.Build {poly %/ h with hI}\n coprimep_unit.\n\nHB.instance Definition _ := GRing.UnitAlgebra.on {poly %/ h with hI}.\n(*This is a local notation that serves as an alias for the monic polynomial used to construct the quotient field. It refers to the result of making the defining polynomial monic, which is the defining polynomial itself when it is already monic.*)\nLocal Notation hQ := (mk_monic h).\n\nHB.instance Definition _ := Finite.on {poly %/ h}.\n\nHypothesis hI : monic_irreducible_poly h.\n\n(*This lemma states that the cardinality of the quotient ring of polynomials, formed by a monic irreducible polynomial, is equal to the cardinality of the coefficient ring raised to the power of the degree of the polynomial.*)\nLemma card_qfpoly : #|{poly %/ h with hI}| = #|R| ^ (size h).-1.\n\n(*This lemma states that the cardinality of the quotient ring of polynomials, formed by a monic irreducible polynomial, is strictly greater than one.*)\nLemma card_qfpoly_gt1 : 1 < #|{poly %/ h with hI}|.\n\nEnd FinField.\n\nSection inPoly.\n\nVariable R : comNzRingType.\nVariable h : {poly R}.\n\n(*This lemma states that the image of the composition of two polynomials in a quotient ring is equivalent to the evaluation of the image of the first polynomial at the image of the second polynomial using Horner's method.*)\nLemma in_qpoly_comp_horner (p q : {poly R}) :\n in_qpoly h (p \\Po q) =\n (map_poly (qpolyC h) p).[in_qpoly h q].\n\n(*This lemma states that the function which remaps a polynomial's coefficients into a quotient ring is injective.*)\nLemma map_poly_div_inj : injective (map_poly (qpolyC h)).\n\nEnd inPoly.\n\nSection finPoly.\n\n(*This definition provides a function that converts an element from an integral domain into its corresponding constant polynomial within the quotient ring formed by a monic irreducible polynomial.*)\nDefinition qfpoly_const (R : idomainType) (h : {poly R})\n (hMI : monic_irreducible_poly h) : R -> {poly %/ h with hMI} :=\n qpolyC h.\n\n(*This lemma states that the function which maps a polynomial's coefficients into the quotient field formed by a monic irreducible polynomial is injective.*)\nLemma map_fpoly_div_inj (R : idomainType) (h : {poly R})\n (hMI : monic_irreducible_poly h) :\n injective (map_poly (qfpoly_const hMI)).\n\nEnd finPoly.\n\nSection Splitting.\n\nVariable F : finFieldType.\nVariable h : {poly F}.\nHypothesis hI : monic_irreducible_poly h.\n\n(*This definition constructs the type for the splitting field of a polynomial over a finite field, using a quotient ring of polynomials as the field extension.*)\nDefinition qfpoly_splitting_field_type :=\n FinSplittingFieldType F {poly %/ h with hI}.\n\nEnd Splitting.\n\nSection PrimitivePoly.\n\nVariable F : finFieldType.\nVariable h : {poly F}.\nHypothesis sh_gt2 : 2 < size h.\n(*This local definition establishes that the size of a given polynomial is strictly greater than one.*)\nLet sh_gt1 : 1 < size h.\n\n(*This definition specifies the boolean properties for a polynomial over a finite field to be primitive. A polynomial is primitive if it is monic, irreducible, and its image in the corresponding quotient ring generates the multiplicative group of that ring.*)\nDefinition primitive_poly (p: {poly F}) :=\n let v := #|{poly %/ p}|.-1 in\n [&& p \\is monic,\n irreducibleb p,\n p %| 'X^v - 1 &\n [forall n : 'I_v, (p %| 'X^n - 1) ==> (n == 0%N :> nat)]].\n\n(*This lemma provides an equivalent logical characterization of a primitive polynomial, stating it is a monic irreducible polynomial that divides 'X^v - 1', where 'v' is the order of the multiplicative group of the quotient ring, but does not divide 'X^n - 1' for any smaller positive 'n'.*)\nLemma primitive_polyP (p : {poly F}) :\n reflect\n (let v := #|{poly %/ p}|.-1 in\n [/\\ monic_irreducible_poly p,\n p %| 'X^v - 1 &\n forall n, 0 < n < v -> ~~ (p %| 'X^n - 1)])\n (primitive_poly p).\n\nHypothesis Hh : primitive_poly h.\n\n(*This lemma states that a polynomial assumed to be primitive is also a monic and irreducible polynomial.*)\nLemma primitive_mi : monic_irreducible_poly h.\n\n(*This lemma states that the image of a polynomial in the quotient ring formed by a primitive polynomial is zero if and only if the primitive polynomial divides it.*)\nLemma primitive_poly_in_qpoly_eq0 p : (in_qpoly h p == 0) = (h %| p).\n\n(*A local notation providing an alias for the quotient ring type formed by polynomials modulo a given primitive polynomial.*)\nLocal Notation qT := {poly %/ h with primitive_mi}.\n\n(*This lemma states that the number of elements in the quotient ring formed by a primitive polynomial is equal to the number of elements in the base field raised to the power of the polynomial's degree.*)\nLemma card_primitive_qpoly : #|{poly %/ h}|= #|F| ^ (size h).-1.\n\n(*This lemma states that the image of the indeterminate 'X' in the quotient ring is not the zero element.*)\nLemma qX_neq0 : 'qX != 0 :> qT.\n\n(*This lemma states that the image of the indeterminate 'X' in the quotient ring is a unit, meaning it has a multiplicative inverse.*)\nLemma qX_in_unit : ('qX : qT) \\in GRing.unit.\n\n(*This definition introduces a canonical unit in the quotient ring, corresponding to the image of the polynomial indeterminate under the quotient map.*)\nDefinition gX : {unit qT} := FinRing.unit _ qX_in_unit.\n\n(*This lemma asserts that a primitive polynomial divides the polynomial 'X^n - 1' if and only if its canonical unit image raised to the power 'n' is the multiplicative identity.*)\nLemma dvdp_order n : (h %| 'X^n - 1) = (gX ^+ n == 1)%g.\n\n(*This lemma states that the multiplicative order of the canonical unit derived from the indeterminate 'X' is equal to the size of the multiplicative group of the quotient ring.*)\nLemma gX_order : #[gX]%g = (#|qT|).-1.\n\n(*This lemma states that the cyclic subgroup generated by the canonical unit derived from the indeterminate 'X' is the entire multiplicative group of units of the quotient ring.*)\nLemma gX_all : <[gX]>%g = [set: {unit qT}]%G.\n\n(*This local definition asserts that the order of the multiplicative group of the quotient ring is strictly greater than zero.*)\nLet pred_card_qT_gt0 : 0 < #|qT|.-1.\n\n(*This definition specifies the discrete logarithm function within a finite field constructed as a quotient ring. It maps an element of the field to the smallest non-negative exponent that produces it when applied to the field's generator, or returns zero for the zero element.*)\nDefinition qlogp (p : qT) : nat :=\n odflt (Ordinal pred_card_qT_gt0) (pick [pred i in 'I_ _ | ('qX ^+ i == p)]).\n\n(*This lemma states that the discrete logarithm of any element in the quotient ring is strictly less than the order of the ring's multiplicative group.*)\nLemma qlogp_lt p : qlogp p < #|qT|.-1.\n\n(*This lemma states that for any non-zero element in the quotient ring, raising the ring's generator to the power of the element's discrete logarithm yields the original element.*)\nLemma qlogp_qX (p : qT) : p != 0 -> 'qX ^+ (qlogp p) = p.\n\n(*This lemma states that raising the canonical generator of the quotient ring to the power of the size of the multiplicative group results in the multiplicative identity element.*)\nLemma qX_order_card : 'qX ^+ (#|qT|).-1 = 1 :> qT.\n\n(*This lemma states that if raising the canonical generator of the quotient ring to a certain power yields the multiplicative identity, then that power must be a multiple of the order of the multiplicative group.*)\nLemma qX_order_dvd (i : nat) : 'qX ^+ i = 1 :> qT -> (#|qT|.-1 %| i)%N.\n\n(*This lemma states that the discrete logarithm of the zero element in the quotient ring is zero.*)\nLemma qlogp0 : qlogp 0 = 0%N.\n\n(*This lemma states that the discrete logarithm of the multiplicative identity element in the quotient ring is zero.*)\nLemma qlogp1 : qlogp 1 = 0%N.\n\n(*This lemma states that the discrete logarithm of an element in the quotient ring is zero if and only if the element is either the additive identity or the multiplicative identity.*)\nLemma qlogp_eq0 (q : qT) : (qlogp q == 0%N) = (q == 0) || (q == 1).\n\n(*This lemma states that any natural number power of the generator of the quotient field is not equal to the zero element of that field.*)\nLemma qX_exp_neq0 i : 'qX ^+ i != 0 :> qT.\n\n(*This lemma states that if two natural number exponents are less than the size of the multiplicative group of the quotient field, and the powers of the generator raised to these exponents are equal, then the exponents themselves must be equal.*)\nLemma qX_exp_inj i j :\n i < #|qT|.-1 -> j < #|qT|.-1 -> 'qX ^+ i = 'qX ^+ j :> qT -> i = j.\n\n(*This lemma states that if two natural number exponents are congruent modulo the size of the multiplicative group of the quotient field, then the powers of the generator of that field raised to these exponents are equal.*)\nLemma powX_eq_mod i j : i = j %[mod #|qT|.-1] -> 'qX ^+ i = 'qX ^+ j :> qT.\n\n(*This lemma states that for a natural number exponent less than the size of the multiplicative group of the quotient field, the discrete logarithm of the generator raised to that exponent is equal to the exponent itself.*)\nLemma qX_expK i : i < #|qT|.-1 -> qlogp ('qX ^+ i) = i.\n\n(*This lemma states that for any two non-zero elements of the quotient field, the discrete logarithm of their product is equal to the sum of their individual discrete logarithms, computed modulo the size of the multiplicative group of the field.*)\nLemma qlogpD (q1 q2 : qT) :\n q1 != 0 -> q2 != 0 ->qlogp (q1 * q2) = ((qlogp q1 + qlogp q2) %% #|qT|.-1)%N.\n\nEnd PrimitivePoly.\n\nSection Plogp.\n\nVariable F : finFieldType.\n\n(*This definition introduces a function that computes the discrete logarithm of a given polynomial within the context of a quotient field formed by another polynomial, which serves as the modulus. If the modulus polynomial is primitive, the function returns the discrete logarithm of the given polynomial's image in the quotient field; otherwise, it returns zero.*)\nDefinition plogp (p q : {poly F}) :=\n if boolP (primitive_poly p) is AltTrue Hh then\n qlogp ((in_qpoly p q) : {poly %/ p with primitive_mi Hh})\n else 0%N.\n\n(*This lemma states that for two polynomials over a finite field, where the size of the first polynomial is greater than two, the discrete logarithm of the second polynomial with respect to the first is a natural number strictly less than the size of the multiplicative group of the corresponding quotient field.*)\nLemma plogp_lt (p q : {poly F}) : 2 < size p -> plogp p q < #|{poly %/ p}|.-1.\n\n(*This lemma states that if a primitive polynomial of size greater than two does not divide a second polynomial, then the second polynomial is congruent to the variable 'X' raised to the power of its own discrete logarithm, all modulo the primitive polynomial.*)\nLemma plogp_X (p q : {poly F}) :\n 2 < size p -> primitive_poly p -> ~~ (p %| q) -> p %| q - 'X ^+ plogp p q.\n\n(*This lemma states that for any polynomial with size greater than two, the discrete logarithm of the zero polynomial with respect to it is equal to zero.*)\nLemma plogp0 (p : {poly F}) : 2 < size p -> plogp p 0 = 0%N.\n\n(*This lemma states that for any polynomial with size greater than two, the discrete logarithm of the constant polynomial one with respect to it is equal to zero.*)\nLemma plogp1 (p : {poly F}) : 2 < size p -> plogp p 1 = 0%N.\n\n(*This lemma states that if a polynomial of size greater than two divides a second polynomial, then the discrete logarithm of the second polynomial with respect to the first is equal to zero.*)\nLemma plogp_div_eq0 (p q : {poly F}) :\n 2 < size p -> (p %| q) -> plogp p q = 0%N.\n\n(*This lemma describes the logarithmic property of the polynomial discrete logarithm function. It states that for a primitive modulus polynomial and two other polynomials that are not divisible by it, the discrete logarithm of their product is equal to the sum of their individual discrete logarithms, computed modulo the size of the multiplicative group of the quotient field.*)\nLemma plogpD (p q1 q2 : {poly F}) :\n 2 < size p -> primitive_poly p -> ~~ (p %| q1) -> ~~ (p %| q2) ->\n plogp p (q1 * q2) = ((plogp p q1 + plogp p q2) %% #|{poly %/ p}|.-1)%N.", - "field.galois": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype tuple finfun bigop ssralg poly.\nFrom mathcomp Require Import polydiv finset fingroup morphism quotient perm.\nFrom mathcomp Require Import action zmodp cyclic matrix mxalgebra vector.\nFrom mathcomp Require Import falgebra fieldext separable.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nReserved Notation \"''Gal' ( A / B )\"\n (A at level 35, format \"''Gal' ( A / B )\").\n\nImport GroupScope GRing.Theory.\nLocal Open Scope ring_scope.\n\nSection SplittingFieldFor.\n\nVariables (F : fieldType) (L : fieldExtType F).\n\n(*This definition asserts that a vector space is a splitting field for a given polynomial over a base vector space if there exists a sequence of elements such that the polynomial splits completely into linear factors with these elements as roots, and the target vector space is generated by the base space and these roots.*)\nDefinition splittingFieldFor (U : {vspace L}) (p : {poly L}) (V : {vspace L}) :=\n exists2 rs, p %= \\prod_(z <- rs) ('X - z%:P) & <>%VS = V.\n\n(*This lemma states that if a field extension is a splitting field for a polynomial over a given base field, it is also a splitting field for the same polynomial over any intermediate field.*)\nLemma splittingFieldForS (K M E : {subfield L}) p :\n (K <= M)%VS -> (M <= E)%VS ->\n splittingFieldFor K p E -> splittingFieldFor M p E.\n\nEnd SplittingFieldFor.\n\nSection kHom.\n\nVariables (F : fieldType) (L : fieldExtType F).\nImplicit Types (U V : {vspace L}) (K E : {subfield L}) (f g : 'End(L)).\n\n(*This definition describes a property of a function, stating that it is a 'k-homomorphism' from a source vector space to a target vector space if the function is an additive homomorphism into the target space and fixes every element of the source space.*)\nDefinition kHom U V f := ahom_in V f && (U <= fixedSpace f)%VS.\n\n(*This lemma provides an equivalent characterization of a k-homomorphism, stating that it is a function that fixes every element of its source space and preserves multiplication for any two elements within its target space.*)\nLemma kHomP_tmp {K V f} :\n reflect [/\\ {in K, forall x, f x = x} &\n {in V &, forall x y, f (x * y) = f x * f y}]\n (kHom K V f).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `kHomP_tmp` instead\")]\n(*This lemma provides an equivalent characterization of a k-homomorphism, stating that it is a function that preserves multiplication for any two elements within its target space and fixes every element of its source space. This lemma is deprecated; use `kHomP_tmp` instead.*)\nLemma kHomP {K V f} :\n reflect [/\\ {in V &, forall x y, f (x * y) = f x * f y} &\n {in K, forall x, f x = x}]\n (kHom K V f).\n\n(*This lemma states that for an additive endomorphism, being a k-homomorphism from a source space to a target space is equivalent to the endomorphism fixing every element of the source space.*)\nLemma kAHomP {U V} {f : 'AEnd(L)} :\n reflect {in U, forall x, f x = x} (kHom U V f).\n\n(*This lemma states that the identity endomorphism is a k-homomorphism from any source vector space to a target vector space.*)\nLemma kHom1 U V : kHom U V \\1.\n\n(*This lemma states that a function is a k-homomorphism from the trivial vector space to a given target vector space if and only if it is an additive homomorphism into that target space.*)\nLemma k1HomE V f : kHom 1 V f = ahom_in V f.\n\n(*This lemma states that for an endomorphism on a field extension, being a k-homomorphism from the trivial vector space to the entire field extension is equivalent to being a monoid morphism.*)\nLemma kHom_monoid_morphism (f : 'End(L)) :\n reflect (monoid_morphism f) (kHom 1 {:L} f).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `kHom_monoid_morphism` instead\")]\n(*This lemma states that for an endomorphism on a field extension, being a k-homomorphism from the trivial vector space to the entire field extension is equivalent to being a multiplicative function. This lemma is deprecated; use `kHom_monoid_morphism` instead.*)\nLemma kHom_lrmorphism (f : 'End(L)) : reflect (multiplicative f) (kHom 1 {:L} f).\n\n(*This lemma states that any additive endomorphism on a field extension is a k-homomorphism from the trivial vector space to any given target vector space.*)\nLemma k1AHom V (f : 'AEnd(L)) : kHom 1 V f.\n\n(*This lemma states that if a function is a k-homomorphism that fixes a given subfield, then applying this function to the coefficients of any polynomial defined over that subfield results in the same polynomial.*)\nLemma kHom_poly_id K E f p :\n kHom K E f -> p \\is a polyOver K -> map_poly f p = p.\n\n(*This lemma states that if a function is a k-homomorphism that fixes a certain vector space, it is also a k-homomorphism that fixes any of its subspaces.*)\nLemma kHomSl U1 U2 V f : (U1 <= U2)%VS -> kHom U2 V f -> kHom U1 V f.\n\n(*This lemma states that if a function is a k-homomorphism with respect to a target vector space, it is also a k-homomorphism with respect to any subspace of that target.*)\nLemma kHomSr K V1 V2 f : (V1 <= V2)%VS -> kHom K V2 f -> kHom K V1 f.\n\n(*This lemma states that if a function is a k-homomorphism, it remains a k-homomorphism when both its source (fixed) space and its target space are restricted to any of their respective subspaces.*)\nLemma kHomS K1 K2 V1 V2 f :\n (K1 <= K2)%VS -> (V1 <= V2)%VS -> kHom K2 V2 f -> kHom K1 V1 f.\n\n(*This lemma states that for two functions that are equal on a given vector space, one function is a k-homomorphism with that space as the target if and only if the other function is also a k-homomorphism with the same target space.*)\nLemma kHom_eq K E f g :\n (K <= E)%VS -> {in E, f =1 g} -> kHom K E f = kHom K E g.\n\n(*This lemma states that a k-homomorphism on a subfield preserves multiplicative inverses for all non-zero elements within that subfield.*)\nLemma kHom_inv K E f : kHom K E f -> {in E, {morph f : x / x^-1}}.\n\n(*This lemma states that a k-homomorphism from a subfield to itself preserves the dimension of the subfield, meaning the dimension of the image of the subfield under the homomorphism is equal to the dimension of the original subfield.*)\nLemma kHom_dim K E f : kHom K E f -> \\dim (f @: E) = \\dim E.\n\nSection kHomMorphism.\nVariables (K E : {subfield L}) (f : 'End(L)).\n(*This definition provides a version of a given endomorphism whose domain is explicitly restricted to the elements of a specific subfield.*)\nLet kHomf : subvs_of E -> L := f \\o vsval.\n\n(*This lemma states that if a function is a k-homomorphism on a subfield, then the function restricted to that subfield is an additive group morphism.*)\nLemma kHom_is_zmod_morphism : kHom K E f -> zmod_morphism kHomf.\n\n#[deprecated(since=\"mathcomp 2.5.0\", note=\"use `kHom_is_zmod_morphism` instead\")]\n(*This lemma states that if a function is a k-homomorphism on a subfield, then the function restricted to that subfield is an additive function. This lemma is deprecated; use `kHom_is_zmod_morphism` instead.*)\nDefinition kHom_is_additive := kHom_is_zmod_morphism.\n\n(*This lemma states that if a function is a k-homomorphism on a subfield, then the function restricted to that subfield is a multiplicative monoid morphism.*)\nLemma kHom_is_monoid_morphism : kHom K E f -> monoid_morphism kHomf.\n\n#[deprecated(since=\"mathcomp 2.5.0\", note=\"use `kHom_is_monoid_morphism` instead\")]\n(*This definition states that if a function is a k-homomorphism on a subfield, then the function restricted to that subfield is multiplicative. This definition is deprecated; use `kHom_is_monoid_morphism` instead.*)\nDefinition kHom_is_multiplicative :=\n (fun p => (p.1, p.2)) \\o kHom_is_monoid_morphism.\n\nVariable (homKEf : kHom K E f).\nHB.instance Definition _ :=\n @GRing.isZmodMorphism.Build _ _ kHomf (kHom_is_zmod_morphism homKEf).\n(*This definition constructs a formal ring morphism from a function, given a proof that the function is a k-homomorphism over a specific subfield.*)\nDefinition kHom_rmorphism := Eval hnf in (kHomf : {rmorphism _ -> _}).\n\nEnd kHomMorphism.\n\n(*This lemma states that for a k-homomorphism, applying the homomorphism to the result of a polynomial evaluation is equivalent to first mapping the polynomial's coefficients with the homomorphism and then evaluating the new polynomial at the mapped value.*)\nLemma kHom_horner K E f p x :\n kHom K E f -> p \\is a polyOver E -> x \\in E -> f p.[x] = (map_poly f p).[f x].\n\n(*This lemma states that a k-homomorphism maps roots of a polynomial to roots of the transformed polynomial, where the transformation applies the homomorphism to the polynomial's coefficients.*)\nLemma kHom_root K E f p x :\n kHom K E f -> p \\is a polyOver E -> x \\in E -> root p x ->\n root (map_poly f p) (f x).\n\n(*This lemma states that if a function is a k-homomorphism fixing a base subfield, it maps any root of a polynomial with coefficients in that base subfield to another root of the same polynomial.*)\nLemma kHom_root_id K E f p x :\n (K <= E)%VS -> kHom K E f -> p \\is a polyOver K -> x \\in E -> root p x ->\n root p (f x).\n\nSection kHomExtend.\n\nVariables (K E : {subfield L}) (f : 'End(L)) (x y : L).\n\n(*This definition specifies a function that extends a given ring homomorphism to an algebraic field extension. The function takes an element from the extension field, represents it as a polynomial in the algebraic element, applies the homomorphism to the coefficients of this polynomial, and then evaluates the resulting polynomial at a designated target element.*)\nLet kHomf z := (map_poly f (Fadjoin_poly E x z)).[y].\n\n(*This fact states that the function for extending a homomorphism preserves addition and maps zero to zero.*)\nFact kHomExtend_zmod_morphism_subproof : zmod_morphism kHomf.\n\n(*This fact states that the function for extending a homomorphism is compatible with scalar multiplication.*)\nFact kHomExtend_scalable_subproof : scalable kHomf.\n\nHB.instance Definition _ := @GRing.isZmodMorphism.Build _ _ kHomf\n kHomExtend_zmod_morphism_subproof.\n(*This definition constructs a formal linear map from the function that extends a homomorphism, based on proofs that it preserves addition and scalar multiplication.*)\nLet kHomExtendLinear := Eval hnf in (kHomf : {linear _ -> _}).\n(*This definition provides the function that extends a given field homomorphism to a larger field containing an algebraic element. This function maps the algebraic element to a specified root in the target field.*)\nDefinition kHomExtend := linfun kHomExtendLinear.\n\n(*This lemma states that the extended homomorphism, when applied to an element of the extension field, is equivalent to first representing that element as a polynomial, then applying the original homomorphism to the polynomial's coefficients, and finally evaluating the resulting polynomial at the target element.*)\nLemma kHomExtendE z : kHomExtend z = (map_poly f (Fadjoin_poly E x z)).[y].\n\nHypotheses (sKE : (K <= E)%VS) (homKf : kHom K E f).\n(*This notation defines a shorthand for the minimal polynomial of an algebraic element over a given field.*)\nLocal Notation Px := (minPoly E x).\nHypothesis fPx_y_0 : root (map_poly f Px) y.\n\n(*This lemma states that the extended homomorphism behaves identically to the original homomorphism when applied to elements from the original base field.*)\nLemma kHomExtend_id z : z \\in E -> kHomExtend z = f z.\n\n(*This lemma states that the extended homomorphism maps the specific algebraic element of the extension field to its designated target element in the codomain.*)\nLemma kHomExtend_val : kHomExtend x = y.\n\n(*This lemma states that applying the extended homomorphism to the value of a polynomial evaluated at a specific algebraic element is equivalent to first transforming the polynomial's coefficients with the original homomorphism and then evaluating the new polynomial at a designated target element.*)\nLemma kHomExtend_poly p :\n p \\in polyOver E -> kHomExtend p.[x] = (map_poly f p).[y].\n\n(*This lemma asserts that the extended homomorphism is a valid field homomorphism over a base field for the given algebraic field extension.*)\nLemma kHomExtendP : kHom K <> kHomExtend.\n\nEnd kHomExtend.\n\n(*This definition specifies a k-automorphism as a k-homomorphism from a vector space to itself that is also surjective.*)\nDefinition kAut U V f := kHom U V f && (f @: V == V)%VS.\n\n(*This lemma clarifies that for a finite-dimensional vector space, a k-automorphism is a k-homomorphism that maps the space into itself, as this containment implies surjectivity.*)\nLemma kAutE K E f : kAut K E f = kHom K E f && (f @: E <= E)%VS.\n\n(*This lemma states that if a function is a k-automorphism with respect to a field, it is also a k-automorphism with respect to any of its subfields.*)\nLemma kAutS U1 U2 V f : (U1 <= U2)%VS -> kAut U2 V f -> kAut U1 V f.\n\n(*This lemma states that any k-automorphism is, by definition, also a k-homomorphism.*)\nLemma kHom_kAut_sub K E f : kAut K E f -> kHom K E f. \n\n(*This lemma states that if two endomorphisms are equal on a given subspace, then the property of being a k-automorphism on that subspace is equivalent for both functions.*)\nLemma kAut_eq K E (f g : 'End(L)) :\n (K <= E)%VS -> {in E, f =1 g} -> kAut K E f = kAut K E g.\n\n(*This lemma states that for the entire ambient field, the notion of a k-automorphism is equivalent to that of a k-homomorphism.*)\nLemma kAutfE K f : kAut K {:L} f = kHom K {:L} f.\n\n(*This lemma states that an algebra endomorphism is a 1-automorphism on a subspace if and only if it maps that subspace into itself, because the condition of being a homomorphism over the prime field is always satisfied.*)\nLemma kAut1E E (f : 'AEnd(L)) : kAut 1 E f = (f @: E <= E)%VS.\n\n(*This lemma states that any k-homomorphism defined over the entire ambient field is injective, meaning its kernel contains only the zero vector.*)\nLemma kAutf_lker0 K f : kHom K {:L} f -> lker f == 0%VS.\n\n(*This lemma states that the inverse of an invertible k-homomorphism defined on the entire ambient field is also a k-homomorphism.*)\nLemma inv_kHomf K f : kHom K {:L} f -> kHom K {:L} f^-1.\n\n(*This lemma states that the inverse of an invertible algebra endomorphism on the entire ambient field is also an algebra homomorphism.*)\nLemma inv_is_ahom (f : 'AEnd(L)) : ahom_in {:L} f^-1.\n\nCanonical inv_ahom (f : 'AEnd(L)) : 'AEnd(L) := AHom (inv_is_ahom f).\n(**)\nNotation \"f ^-1\" := (inv_ahom f) : lrfun_scope.\n\n(*This lemma states that if one k-homomorphism acts on a subspace and a second k-homomorphism acts on the image of that subspace under the first map, their composition results in a valid k-homomorphism on the original subspace.*)\nLemma comp_kHom_img K E f g :\n kHom K (g @: E) f -> kHom K E g -> kHom K E (f \\o g).\n\n(*This lemma states that the composition of a k-homomorphism on the entire ambient field with a k-homomorphism on a subspace is also a k-homomorphism on that subspace.*)\nLemma comp_kHom K E f g : kHom K {:L} f -> kHom K E g -> kHom K E (f \\o g).\n\n(*This lemma, known as the homomorphism extension theorem, states that any k-homomorphism from a field to an extension field can be extended to a larger field, specifically a splitting field of a polynomial, while preserving the homomorphism's behavior on the original domain.*)\nLemma kHom_extends K E f p U :\n (K <= E)%VS -> kHom K E f ->\n p \\is a polyOver K -> splittingFieldFor E p U ->\n {g | kHom K U g & {in E, f =1 g}}.\n\nEnd kHom.\n\n(*This notation represents the inverse of an automorphism with respect to function composition within the group of automorphisms of a splitting field.*)\nNotation \"f ^-1\" := (inv_ahom f) : lrfun_scope.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\"]\nArguments kHomP {F L K V f}.\nArguments kHomP_tmp {F L K V f}.\nArguments kAHomP {F L U V f}.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\"]\nArguments kHom_lrmorphism {F L f}.\nArguments kHom_monoid_morphism {F L f}.\n\n(*This definition specifies the axiom for a splitting field, which asserts that for a given field extension, there exists a polynomial with coefficients in the base field such that the extension field is the smallest field where this polynomial splits into linear factors.*)\nDefinition splitting_field_axiom (F : fieldType) (L : fieldExtType F) :=\n exists2 p : {poly L}, p \\is a polyOver 1%VS & splittingFieldFor 1 p {:L}.\n\n(*This record defines a mixin that endows a field extension with the property of being a splitting field by requiring a proof that the splitting field axiom holds.*)\nHB.mixin Record FieldExt_isSplittingField (F : fieldType) L of FieldExt F L := {\n splittingFieldP_subproof : splitting_field_axiom L\n}.\n\n#[mathcomp(axiom=\"splitting_field_axiom\"), short(type=\"splittingFieldType\")]\n(*This definition creates a structure for a splitting field over a base field, bundling the properties of a field extension with the axiom that it is a splitting field for some polynomial over the base field.*)\nHB.structure Definition SplittingField F :=\n { T of FieldExt_isSplittingField F T & FieldExt F T }.\n\nModule SplittingFieldExports.\nBind Scope ring_scope with SplittingField.sort.\nEnd SplittingFieldExports.\nHB.export SplittingFieldExports.\n\n(*This lemma states that if for every subfield of a given field extension and for every element in that extension, the minimal polynomial of the element over the subfield splits completely into linear factors within the extension, then the field extension satisfies the splitting field axiom.*)\nLemma normal_field_splitting (F : fieldType) (L : fieldExtType F) :\n (forall (K : {subfield L}) x,\n exists r, minPoly K x == \\prod_(y <- r) ('X - y%:P)) ->\n SplittingField.axiom L.\n\n(*This record defines a factory for creating a splitting field structure from a field extension that is normal, meaning for any of its subfields, the minimal polynomial of any element in the extension splits completely.*)\nHB.factory Record FieldExt_isNormalSplittingField\n (F : fieldType) L of FieldExt F L := {\n normal_field_splitting_axiom : forall (K : {subfield L}) x,\n exists r, minPoly K x == \\prod_(y <- r) ('X - y%:P)\n}.\n\nHB.builders Context F L of FieldExt_isNormalSplittingField F L.\nHB.instance Definition _ := FieldExt_isSplittingField.Build F L\n (normal_field_splitting normal_field_splitting_axiom).\nHB.end.\n\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (F : fieldType) := GRing.Field.on (F^o).\n\n(*This fact asserts that any field, when considered as an extension of itself, trivially satisfies the splitting field axiom.*)\nFact regular_splittingAxiom (F : fieldType) : SplittingField.axiom F^o.\n\n(*This lemma states that any type with the structure of a splitting field satisfies the splitting field axiom.*)\nLemma splittingFieldP : SplittingField.axiom L.\n\n(*This lemma provides the existential polynomial for a splitting field, asserting the existence of a polynomial with coefficients in the base field for which the given field is a splitting field.*)\nLemma splittingPoly :\n {p : {poly L} | p \\is a polyOver 1%VS & splittingFieldFor 1 p {:L}}.\n\n(*This fact asserts that if a field is a splitting field over a base field, it also satisfies the splitting field axiom when considered as an extension of any of its intermediate subfields.*)\nFact fieldOver_splitting E : SplittingField.axiom (fieldOver E).\n\n(*This lemma provides a finite sequence that enumerates all automorphisms of a splitting field, asserting that every automorphism is an element of this sequence.*)\nLemma enum_AEnd : {kAutL : seq 'AEnd(L) | forall f, f \\in kAutL}.\n\n(*This lemma states that in a splitting field, for any intermediate subfield and any element of the splitting field, the minimal polynomial of that element over the subfield splits completely into linear factors.*)\nLemma splitting_field_normal K x :\n exists r, minPoly K x == \\prod_(y <- r) ('X - y%:P).\n\n(*This lemma states that any field homomorphism between two subfields of a splitting field can be extended to a full automorphism of the entire splitting field.*)\nLemma kHom_to_AEnd K E f : kHom K E f -> {g : 'AEnd(L) | {in E, f =1 val g}}.\n\nEnd SplittingFieldTheory.\n\nModule Import AEnd_FinGroup.\nSection AEnd_FinGroup.\n\nVariables (F : fieldType) (L : splittingFieldType F).\nImplicit Types (U V W : {vspace L}) (K M E : {subfield L}).\n\n(*This definition provides a canonical representation for an automorphism of a splitting field by mapping it to its position within a canonical enumeration of all such automorphisms.*)\nDefinition inAEnd f := SeqSub (svalP (enum_AEnd L) f).\n(*This fact asserts that the mapping from an automorphism to its canonical representation is invertible, meaning the original automorphism can be recovered from its representation.*)\nFact inAEndK : cancel inAEnd val. \n\nHB.instance Definition _ := Countable.copy 'AEnd(L) (can_type inAEndK).\n(*This definition specifies the binary operation for the group of automorphisms on a splitting field, which is the composition of two given automorphisms.*)\nDefinition comp_AEnd (f g : 'AEnd(L)) : 'AEnd(L) := (g \\o f)%AF.\n\n(*This fact asserts that the composition of automorphisms on a splitting field is an associative operation.*)\nFact comp_AEndA : associative comp_AEnd.\n\n(*This fact asserts that the identity automorphism acts as a left identity element for the composition of automorphisms.*)\nFact comp_AEnd1l : left_id \\1%AF comp_AEnd.\n\n(*This fact asserts that every automorphism on a splitting field has a left inverse with respect to composition, which yields the identity automorphism.*)\nFact comp_AEndK : left_inverse \\1%AF (@inv_ahom _ L) comp_AEnd.\n\n(*This instance declaration establishes that the set of all automorphisms on a splitting field forms a multiplicative group, where the group operation is function composition.*)\nHB.instance Definition _:= isMulGroup.Build 'AEnd(L)\n comp_AEndA comp_AEnd1l comp_AEndK.\n\n(*This definition specifies a set of automorphisms of the ambient splitting field, containing all those that map a given source vector subspace to a given target vector subspace.*)\nDefinition kAEnd U V := [set f : 'AEnd(L) | kAut U V f].\n(*This definition specifies the subgroup of automorphisms of the ambient splitting field that fix every element of a given subfield.*)\nDefinition kAEndf U := kAEnd U {:L}.\n\n(*This lemma asserts that the set of all automorphisms of the ambient splitting field which map a given subfield to another given subfield forms a group under composition.*)\nLemma kAEnd_group_set K E : group_set (kAEnd K E).\n\nCanonical kAEnd_group K E := group (kAEnd_group_set K E).\nCanonical kAEndf_group K := [group of kAEndf K].\n\n(*This lemma states that the set of automorphisms mapping a subfield K to a subfield E is a subset of the normalizer of the subgroup of automorphisms that fix E pointwise.*)\nLemma kAEnd_norm K E : kAEnd K E \\subset 'N(kAEndf E)%g.\n\n(*This lemma states that any automorphism that maps a subfield K to a subfield E is an element of the right coset generated by that same automorphism with respect to the subgroup of automorphisms that fix E.*)\nLemma mem_kAut_coset K E (g : 'AEnd(L)) :\n kAut K E g -> g \\in coset (kAEndf E) g.\n\n(*This lemma establishes an equivalence for automorphisms and cosets: two automorphisms belong to the same coset of the subgroup fixing a subfield E if and only if they have the same action on every element of E.*)\nLemma aut_mem_eqP E (x y : coset_of (kAEndf E)) f g : \n f \\in x -> g \\in y -> reflect {in E, f =1 g} (x == y).\n\nEnd AEnd_FinGroup.\nEnd AEnd_FinGroup.\n\nSection GaloisTheory.\n\nVariables (F : fieldType) (L : splittingFieldType F).\n\nImplicit Types (U V W : {vspace L}).\nImplicit Types (K M E : {subfield L}).\n\nSection gal_of_Definition.\n\nVariable V : {vspace L}.\n\n(*This inductive type defines the elements of a Galois group, constructed as elements of the quotient group formed by the automorphisms stabilizing a vector space divided by the subgroup of automorphisms fixing the field generated by that space.*)\nInductive gal_of := Gal of [subg kAEnd_group 1 <> / kAEndf (agenv V)].\n(*This definition maps an automorphism of the ambient splitting field to its corresponding element in the Galois group, which is represented as a coset.*)\nDefinition gal (f : 'AEnd(L)) := Gal (subg _ (coset _ f)).\n(*This definition extracts the underlying quotient group element from an element of the Galois group type.*)\nDefinition gal_sgval x := let: Gal u := x in u.\n\n(*This fact asserts that the constructor for a Galois group element and the function that extracts its underlying value form a pair of inverse operations.*)\nFact gal_sgvalK : cancel gal_sgval Gal. \n(*This lemma states that the function which extracts the underlying group element from a Galois group structure element is injective. Therefore, if two elements from the Galois group structure map to the same underlying group element, they must be identical.*)\nLet gal_sgval_inj := can_inj gal_sgvalK.\n\nHB.instance Definition _ := Countable.copy gal_of (can_type gal_sgvalK).\nHB.instance Definition _ := isFinite.Build gal_of\n (pcan_enumP (can_pcan gal_sgvalK)).\n\n(*This definition specifies the identity element of the Galois group, which is constructed from the identity automorphism of the underlying group of automorphisms.*)\nDefinition gal_one := Gal 1%g.\n(*This definition provides the inverse of an element in the Galois group. It is computed by taking the inverse of the underlying automorphism corresponding to the given Galois group element and re-packaging it as a Galois group element.*)\nDefinition gal_inv x := Gal (gal_sgval x)^-1.\n(*This definition specifies the multiplication operation for two elements of a Galois group. The result is obtained by multiplying their underlying automorphisms and constructing a new Galois group element from this product.*)\nDefinition gal_mul x y := Gal (gal_sgval x * gal_sgval y).\n(*This fact proves that the defined identity element of the Galois group acts as a left identity with respect to the group's multiplication operation, meaning that multiplying any element by the identity on the left yields the original element.*)\nFact gal_oneP : left_id gal_one gal_mul.\n\n(*This fact proves that the defined inverse operation for the Galois group yields a left inverse for any given element. Multiplying the inverse of an element by the element itself results in the group's identity element.*)\nFact gal_invP : left_inverse gal_one gal_inv gal_mul.\n\n(*This fact proves that the defined multiplication operation for the Galois group is associative.*)\nFact gal_mulP : associative gal_mul.\n\n(*This fact establishes that the function for constructing a Galois group element from an automorphism is a group morphism. This means that applying this construction to the product of two automorphisms yields the same result as multiplying the Galois group elements constructed from each automorphism individually.*)\nFact gal_is_morphism : {in kAEnd 1 (agenv V) &, {morph gal : x y / x * y}%g}.\n\nCanonical gal_morphism := Morphism gal_is_morphism.\n\n(*This lemma states a cancellation property, asserting that applying the function to represent a Galois group element as an automorphism immediately after constructing that element from an automorphism returns the original automorphism.*)\nLemma gal_reprK : cancel gal_repr gal.\n\n(*This lemma asserts that the function which represents a Galois group element as an automorphism is injective. This implies that distinct Galois group elements necessarily correspond to distinct automorphisms.*)\nLemma gal_repr_inj : injective gal_repr.\n\n(*This lemma states that the automorphism obtained by representing any given element of the Galois group is a member of the set of K-algebra automorphisms.*)\nLemma gal_AEnd x : gal_repr x \\in kAEnd 1 (agenv V).\n\nEnd gal_of_Definition.\n\nPrenex Implicits gal_repr.\n\n(*This lemma establishes the equivalence between the boolean equality of two Galois group elements and the equality of their actions on all elements of the stabilized subspace. It asserts that two Galois group elements are considered equal if and only if their corresponding automorphisms behave identically on the subspace.*)\nLemma gal_eqP E {x y : gal_of E} : reflect {in E, x =1 y} (x == y).\n\n(*This lemma states that for any automorphism on a larger space that stabilizes a particular subspace, the action of its corresponding Galois group element on that subspace is identical to the action of the original automorphism on that same subspace.*)\nLemma galK E (f : 'AEnd(L)) : (f @: E <= E)%VS -> {in E, gal E f =1 f}.\n\n(*This lemma provides a condition for the equality of two Galois group elements constructed from automorphisms. It states that for any two automorphisms that both stabilize a given subspace, their corresponding Galois group elements are equal if and only if the two original automorphisms act identically on every element of that subspace.*)\nLemma eq_galP E (f g : 'AEnd(L)) :\n (f @: E <= E)%VS -> (g @: E <= E)%VS ->\n reflect {in E, f =1 g} (gal E f == gal E g).\n\n(*This lemma asserts that the image of the stabilized subspace under the action of any Galois group element is the subspace itself. This implies that the automorphism corresponding to a Galois element acts as a permutation on the stabilized subspace.*)\nLemma limg_gal E (x : gal_of E) : (x @: E)%VS = E.\n\n(*This lemma states that any automorphism corresponding to an element of a Galois group preserves its stabilized subspace. Applying the automorphism to any element within the subspace yields a result that is also within that subspace.*)\nLemma memv_gal E (x : gal_of E) a : a \\in E -> x a \\in E.\n\n(*This lemma states that the identity element of the Galois group acts as the identity function, meaning it leaves any element to which it is applied unchanged.*)\nLemma gal_id E a : (1 : gal_of E)%g a = a.\n\n(*This lemma describes how group multiplication translates to function application. It specifies that applying the product of two Galois group elements to an element of the stabilized subspace is equivalent to the composition of their corresponding automorphisms, applied in the reverse order of multiplication.*)\nLemma galM E (x y : gal_of E) a : a \\in E -> (x * y)%g a = y (x a).\n\n(*This lemma connects the group inverse with the functional inverse. It asserts that the action of the group-theoretic inverse of a Galois element on its stabilized subspace is identical to the action of the functional inverse of its corresponding automorphism on that same subspace.*)\nLemma galV E (x : gal_of E) : {in E, (x^-1)%g =1 x^-1%VF}.\n\n(*This definition constructs the Galois group of a field extension. It is defined as the set of automorphisms on the extension field that fix every element of the base field, with each such automorphism then being formally structured as an element of the Galois group type.*)\nDefinition galoisG V U := gal V @* <>.\n(*This notation provides a standard syntax for referring to the Galois group of a field extension. It represents the group of automorphisms of a larger field that leave every element of a smaller subfield fixed.*)\nLocal Notation \"''Gal' ( V / U )\" := (galoisG V U) : group_scope.\nCanonical galoisG_group E U := Eval hnf in [group of (galoisG E U)].\n(*This notation represents the Galois group of a field extension, which is the set of all field automorphisms of the larger field that leave every element of the smaller subfield unchanged.*)\nLocal Notation \"''Gal' ( V / U )\" := (galoisG_group V U) : Group_scope.\n\nSection Automorphism.\n\n(*This lemma states that the Galois group of a vector space over a second vector space is identical to the Galois group of the first space over the intersection of both spaces.*)\nLemma gal_cap U V : 'Gal(V / U) = 'Gal(V / U :&: V).\n\n(*This lemma states that for a field extension where one field is a subfield of another, an element belongs to the Galois group of the extension if and only if it is a field automorphism of the larger field that fixes the smaller subfield.*)\nLemma gal_kAut K E x : (K <= E)%VS -> (x \\in 'Gal(E / K)) = kAut K E x.\n\n(*This lemma states that for a field extension where one field is a subfield of another, an element belongs to the Galois group of the extension if and only if it is a field homomorphism of the larger field that fixes the smaller subfield.*)\nLemma gal_kHom K E x : (K <= E)%VS -> (x \\in 'Gal(E / K)) = kHom K E x.\n\n(*This lemma states that any function which is a field automorphism of a larger field that fixes a smaller subfield can be represented as an element of the Galois group of the corresponding field extension.*)\nLemma kAut_to_gal K E f :\n kAut K E f -> {x : gal_of E | x \\in 'Gal(E / K) & {in E, f =1 x}}.\n\n(*This lemma states that for a field extension, applying any automorphism from the Galois group to an element of the base field results in the same element.*)\nLemma fixed_gal K E x a :\n (K <= E)%VS -> x \\in 'Gal(E / K) -> a \\in K -> x a = a.\n\n(*This lemma states that for a field extension, applying any automorphism from the Galois group to a polynomial whose coefficients are all in the base field results in the same polynomial.*)\nLemma fixedPoly_gal K E x p :\n (K <= E)%VS -> x \\in 'Gal(E / K) -> p \\is a polyOver K -> map_poly x p = p.\n\n(*This lemma states that for a field extension, if an element of the extension field is a root of its minimal polynomial over the base field, then the image of that element under any automorphism from the Galois group is also a root of the same minimal polynomial.*)\nLemma root_minPoly_gal K E x a :\n (K <= E)%VS -> x \\in 'Gal(E / K) -> a \\in E -> root (minPoly K a) (x a).\n\nEnd Automorphism.\n\n(*This lemma states that two automorphisms in the Galois group of a simple field extension are identical if and only if they map the adjoined element to the same value.*)\nLemma gal_adjoin_eq K a x y :\n x \\in 'Gal(<> / K) -> y \\in 'Gal(<> / K) ->\n (x == y) = (x a == y a).\n\n(*This lemma states that for a tower of field extensions, the Galois group of the largest field over the intermediate field is a subset of the Galois group of the largest field over the smallest field.*)\nLemma galS K M E : (K <= M)%VS -> 'Gal(E / M) \\subset 'Gal(E / K).\n\n(*This lemma states that conjugating the Galois group of a field extension by a field automorphism yields the Galois group of the same extension field over the image of the original base field under that automorphism.*)\nLemma gal_conjg K E x : 'Gal(E / K) :^ x = 'Gal(E / x @: K).\n\n(*This definition specifies the fixed field of a given set of field automorphisms as the subfield containing all elements that are left unchanged by every automorphism in the set.*)\nDefinition fixedField V (A : {set gal_of V}) :=\n (V :&: \\bigcap_(x in A) fixedSpace x)%VS.\n\n(*This lemma provides a boolean criterion for an element to belong to the fixed field of a set of automorphisms, stating this is equivalent to the condition that the element is unchanged by every automorphism in the set.*)\nLemma fixedFieldP E {A : {set gal_of E}} a :\n a \\in E -> reflect (forall x, x \\in A -> x a = a) (a \\in fixedField A).\n\n(*This lemma states that if an element belongs to the fixed field of a set of automorphisms, then it is an element of the larger field and is left unchanged by every automorphism in the set.*)\nLemma mem_fixedFieldP E (A : {set gal_of E}) a :\n a \\in fixedField A -> a \\in E /\\ (forall x, x \\in A -> x a = a).\n\n(*This fact asserts that the fixed field corresponding to a set of automorphisms is an algebraic subspace, thus forming a valid subfield structure.*)\nFact fixedField_is_aspace E (A : {set gal_of E}) : is_aspace (fixedField A).\n\nCanonical fixedField_aspace E A : {subfield L} :=\n ASpace (@fixedField_is_aspace E A).\n\n(*This lemma states that the fixed field associated with a set of automorphisms on a given field is a subfield of that given field.*)\nLemma fixedField_bound E (A : {set gal_of E}) : (fixedField A <= E)%VS.\n\n(*This lemma states that if one set of field automorphisms is a subset of another, then the fixed field of the larger set is a subfield of the fixed field of the smaller set.*)\nLemma fixedFieldS E (A B : {set gal_of E}) :\n A \\subset B -> (fixedField B <= fixedField A)%VS.\n\n(*This lemma states that for a field extension, the base field is a subfield of the fixed field of the corresponding Galois group.*)\nLemma galois_connection_subv K E :\n (K <= E)%VS -> (K <= fixedField ('Gal(E / K)))%VS.\n\n(*This lemma states that any set of field automorphisms is a subset of the Galois group of the field extension over the fixed field of that set of automorphisms.*)\nLemma galois_connection_subset E (A : {set gal_of E}):\n A \\subset 'Gal(E / fixedField A).\n\n(*This lemma states that a given set of field automorphisms is a subset of the Galois group of a field extension if and only if the base field of the extension is a subfield of the fixed field of that set of automorphisms.*)\nLemma galois_connection K E (A : {set gal_of E}):\n (K <= E)%VS -> (A \\subset 'Gal(E / K)) = (K <= fixedField A)%VS.\n\n(*This definition specifies the Galois trace of an element in a field extension as the sum of the images of that element under all automorphisms in the corresponding Galois group.*)\nDefinition galTrace U V a := \\sum_(x in 'Gal(V / U)) (x a).\n\n(*This definition specifies the Galois norm of an element in a field extension as the product of the images of that element under all automorphisms in the corresponding Galois group.*)\nDefinition galNorm U V a := \\prod_(x in 'Gal(V / U)) (x a).\n\nSection TraceAndNormMorphism.\n\nVariables U V : {vspace L}.\n\n(*This fact asserts that the Galois trace function is a module homomorphism, which implies it distributes over addition.*)\nFact galTrace_is_zmod_morphism : zmod_morphism (galTrace U V).\n\n#[deprecated(since=\"mathcomp 2.5.0\", note=\"use `galTrace_is_zmod_morphism` instead\")]\n(*This definition is a deprecated alias for the fact that the Galois trace function is a module homomorphism, indicating it preserves addition.*)\nDefinition galTrace_is_additive := galTrace_is_zmod_morphism.\n(*This lemma states that the Galois norm of the multiplicative identity element is the identity element itself.*)\nLemma galNorm1 : galNorm U V 1 = 1.\n\n(*This lemma states that the Galois norm function is a multiplicative morphism, meaning the norm of a product of two elements is the product of their individual norms.*)\nLemma galNormM : {morph galNorm U V : a b / a * b}.\n\n(*This lemma states that the Galois norm of the multiplicative inverse of an element is equal to the multiplicative inverse of the Galois norm of that element.*)\nLemma galNormV : {morph galNorm U V : a / a^-1}.\n\n(*This lemma states that the Galois norm of an element raised to an integer power is equal to the Galois norm of the element raised to the same power.*)\nLemma galNormX n : {morph galNorm U V : a / a ^+ n}.\n\n(*This lemma states that the Galois norm of a finite product of elements is equal to the finite product of the Galois norms of those elements.*)\nLemma galNorm_prod (I : Type) (r : seq I) (P : pred I) (B : I -> L) :\n galNorm U V (\\prod_(i <- r | P i) B i)\n = \\prod_(i <- r | P i) galNorm U V (B i).\n\n(*This lemma states that the Galois norm of the additive identity element is the additive identity element itself.*)\nLemma galNorm0 : galNorm U V 0 = 0.\n\n(*This lemma states that the Galois norm of an element is zero if and only if the element itself is zero.*)\nLemma galNorm_eq0 a : (galNorm U V a == 0) = (a == 0).\n\nEnd TraceAndNormMorphism.\n\nSection TraceAndNormField.\n\nVariables K E : {subfield L}.\n\n(*This lemma states that for any element of a field extension, its Galois trace belongs to the fixed field of the corresponding Galois group.*)\nLemma galTrace_fixedField a :\n a \\in E -> galTrace K E a \\in fixedField 'Gal(E / K).\n\n(*This lemma states that the Galois trace of an element is invariant under the action of any automorphism from the corresponding Galois group.*)\nLemma galTrace_gal a x :\n a \\in E -> x \\in 'Gal(E / K) -> galTrace K E (x a) = galTrace K E a.\n\n(*This lemma states that for any element of a field extension, its Galois norm belongs to the fixed field of the corresponding Galois group.*)\nLemma galNorm_fixedField a :\n a \\in E -> galNorm K E a \\in fixedField 'Gal(E / K).\n\n(*This lemma states that the Galois norm of an element is invariant under the action of any automorphism from the corresponding Galois group.*)\nLemma galNorm_gal a x :\n a \\in E -> x \\in 'Gal(E / K) -> galNorm K E (x a) = galNorm K E a.\n\nEnd TraceAndNormField.\n\n(*This definition specifies that a field extension is a normal extension if every algebra endomorphism of the ambient field that fixes the base field also restricts to an automorphism of the extension field.*)\nDefinition normalField U V := [forall x in kAEndf U, x @: V == V]%VS.\n\n(*This lemma states that if a field is a normal extension of a base field, any automorphism of a larger field that fixes the base field will also restrict to an automorphism of the normal extension.*)\nLemma normalField_kAut K M E f :\n (K <= M <= E)%VS -> normalField K M -> kAut K E f -> kAut K M f.\n\n(*This lemma provides an equivalence for a normal field extension, stating that an extension is normal if and only if for every element in it, its minimal polynomial over the base field splits completely into linear factors within the extension.*)\nLemma normalFieldP K E :\n reflect {in E, forall a, exists2 r,\n all [in E] r & minPoly K a = \\prod_(b <- r) ('X - b%:P)}\n (normalField K E).\n\n(*This lemma states that the ambient field is always a normal extension of any of its subfields.*)\nLemma normalFieldf K : normalField K {:L}.\n\n(*This lemma states that if a field is a normal extension of a base field, it is also a normal extension of any intermediate field.*)\nLemma normalFieldS K M E : (K <= M)%VS -> normalField K E -> normalField M E.\n\n(*This lemma asserts that a finite field extension is normal if and only if it acts as the splitting field for some polynomial defined over the base field.*)\nLemma splitting_normalField E K :\n (K <= E)%VS ->\n reflect (exists2 p, p \\is a polyOver K & splittingFieldFor K p E)\n (normalField K E).\n\n(*This lemma states that within a normal field extension of a base field, any field homomorphism from an intermediate field into the extension that fixes the base field can be extended to a full automorphism of the extension field.*)\nLemma kHom_to_gal K M E f :\n (K <= M <= E)%VS -> normalField K E -> kHom K M f ->\n {x | x \\in 'Gal(E / K) & {in M, f =1 x}}.\n\n(*This lemma states that in a normal field extension, for any given element, any other root of its minimal polynomial can be obtained by applying some automorphism from the Galois group to the original element.*)\nLemma normalField_root_minPoly K E a b :\n (K <= E)%VS -> normalField K E -> a \\in E -> root (minPoly K a) b ->\n exists2 x, x \\in 'Gal(E / K) & x a = b.\n\nArguments normalFieldP {K E}.\n\n(*This lemma states that a field extension is normal if and only if the minimal polynomial of any of its elements factors completely into linear terms, where the roots are the images of the element under a subset of the Galois group.*)\nLemma normalField_factors K E :\n (K <= E)%VS ->\n reflect {in E, forall a, exists2 r : seq (gal_of E),\n r \\subset 'Gal(E / K)\n & minPoly K a = \\prod_(x <- r) ('X - (x a)%:P)}\n (normalField K E).\n\n(*This definition specifies that a field extension is a Galois extension if it is both a normal extension and a separable extension.*)\nDefinition galois U V := [&& (U <= V)%VS, separable U V & normalField U V].\n\n(*This lemma states that if a field is a Galois extension of a base field, it is also a Galois extension of any intermediate field.*)\nLemma galoisS K M E : (K <= M <= E)%VS -> galois K E -> galois M E.\n\n(*This lemma states that for a finite Galois extension, the dimension of the extension field as a vector space over the base field is equal to the number of automorphisms in the Galois group.*)\nLemma galois_dim K E : galois K E -> \\dim_K E = #|'Gal(E / K)|.\n\n(*This lemma states that a field extension is Galois if and only if for any element, its minimal polynomial factors into distinct roots that are precisely the images of that element under a subset of the Galois group.*)\nLemma galois_factors K E :\n (K <= E)%VS ->\n reflect {in E, forall a, exists r, let r_a := [seq x a | x : gal_of E <- r] in\n [/\\ r \\subset 'Gal(E / K), uniq r_a\n & minPoly K a = \\prod_(b <- r_a) ('X - b%:P)]}\n (galois K E).\n\n(*This lemma states that a finite field extension is a Galois extension if and only if it is the splitting field of a separable polynomial over the base field.*)\nLemma splitting_galoisField K E :\n reflect (exists p, [/\\ p \\is a polyOver K, separable_poly p\n & splittingFieldFor K p E]) \n (galois K E).\n\n(*This lemma states that a finite field extension is Galois if and only if the subfield of elements fixed by every automorphism in the Galois group is precisely the base field.*)\nLemma galois_fixedField K E :\n reflect (fixedField 'Gal(E / K) = K) (galois K E).\n\n(*This lemma states that for any element in a Galois extension, its Galois trace is an element of the base field.*)\nLemma mem_galTrace K E a : galois K E -> a \\in E -> galTrace K E a \\in K.\n\n(*This lemma states that for any element in a Galois extension, its Galois norm is an element of the base field.*)\nLemma mem_galNorm K E a : galois K E -> a \\in E -> galNorm K E a \\in K.\n\n(*This lemma, a contrapositive form of Dedekind's lemma on linear independence of characters, states that for any non-trivial linear combination of distinct field automorphisms, there exists a field element for which the combination does not evaluate to zero.*)\nLemma gal_independent_contra E (P : pred (gal_of E)) (c_ : gal_of E -> L) x :\n P x -> c_ x != 0 ->\n exists2 a, a \\in E & \\sum_(y | P y) c_ y * y a != 0.\n\n(*This lemma, known as Dedekind's theorem on the linear independence of characters, states that if a linear combination of distinct field automorphisms evaluates to zero for all elements of the field, then all coefficients of the combination must be zero.*)\nLemma gal_independent E (P : pred (gal_of E)) (c_ : gal_of E -> L) :\n (forall a, a \\in E -> \\sum_(x | P x) c_ x * x a = 0) ->\n (forall x, P x -> c_ x = 0).\n\n(*This lemma, the multiplicative version of Hilbert's Theorem 90, states that for a cyclic Galois extension, an element has a Galois norm of one if and only if it can be written as a quotient of some non-zero element and its image under a generator of the Galois group.*)\nLemma Hilbert's_theorem_90 K E x a :\n generator 'Gal(E / K) x -> a \\in E ->\n reflect (exists2 b, b \\in E /\\ b != 0 & a = b / x b) (galNorm K E a == 1).\n\nSection Matrix.\n\nVariable (E : {subfield L}) (A : {set gal_of E}).\n\n(*A local definition for the field `K` as the set of elements in a larger field that are left unchanged by every automorphism in a given set.*)\nLet K := fixedField A.\n\n(*This lemma guarantees the existence of a tuple of elements from a field that has special properties with respect to a given set of field automorphisms. It states that these elements are non-zero, and the matrix formed by applying each automorphism to each element in the tuple is invertible. Furthermore, these elements are linearly independent over the fixed field, and if the set of automorphisms forms a group, they constitute a basis for the field over this fixed field.*)\nLemma gal_matrix :\n {w : #|A|.-tuple L | {subset w <= E} /\\ 0 \\notin w &\n [/\\ \\matrix_(i, j < #|A|) enum_val i (tnth w j) \\in unitmx,\n directv (\\sum_i K * <[tnth w i]>) &\n group_set A -> (\\sum_i K * <[tnth w i]>)%VS = E] }.\n\nEnd Matrix.\n\n(*This lemma by Artin states that for any finite group of automorphisms of a field, the size of the group is equal to the dimension of the field as a vector space over the subfield of elements fixed by the group.*)\nLemma dim_fixedField E (G : {group gal_of E}) : #|G| = \\dim_(fixedField G) E.\n\n(*This lemma states that for a Galois extension and a subgroup of its Galois group, the dimension of the subgroup's fixed field over the base field is equal to the index of the subgroup within the full Galois group.*)\nLemma dim_fixed_galois K E (G : {group gal_of E}) :\n galois K E -> G \\subset 'Gal(E / K) ->\n \\dim_K (fixedField G) = #|'Gal(E / K) : G|.\n\n(*This lemma states that for any finite group of automorphisms of a field, the Galois group of the field over its fixed subfield is precisely that original group of automorphisms.*)\nLemma gal_fixedField E (G : {group gal_of E}): 'Gal(E / fixedField G) = G.\n\n(*This lemma states that for a given field and a set of its automorphisms, the Galois group of the field over the subfield fixed by these automorphisms is equal to the group generated by that set of automorphisms.*)\nLemma gal_generated E (A : {set gal_of E}) : 'Gal(E / fixedField A) = <>.\n\n(*This lemma states that for any given field and any set of its automorphisms, the field extension over the subfield fixed by these automorphisms is a Galois extension.*)\nLemma fixedField_galois E (A : {set gal_of E}): galois (fixedField A) E.\n\nSection FundamentalTheoremOfGaloisTheory.\n\nVariables E K : {subfield L}.\nHypothesis galKE : galois K E.\n\nSection IntermediateField.\n\nVariable M : {subfield L}.\nHypothesis (sKME : (K <= M <= E)%VS) (nKM : normalField K M).\n\n(*This lemma states that if a field extension is Galois and contains an intermediate field that is a normal extension of the base field, then the extension from the base field to the intermediate field is also Galois.*)\nLemma normalField_galois : galois K M.\n\n(*This definition constructs a function that takes a field automorphism from a larger field extension and restricts its domain to an intermediate subfield, yielding an automorphism on that subfield.*)\nDefinition normalField_cast (x : gal_of E) : gal_of M := gal M x.\n\n(*This lemma asserts that when an automorphism from the Galois group of a larger extension is restricted to an intermediate field, its action on any element of that intermediate field is identical to its original action.*)\nLemma normalField_cast_eq x :\n x \\in 'Gal(E / K) -> {in M, normalField_cast x =1 x}.\n\n(*This lemma establishes that the function which restricts field automorphisms to an intermediate subfield is a group homomorphism, meaning it preserves the group's composition operation.*)\nLemma normalField_castM :\n {in 'Gal(E / K) &, {morph normalField_cast : x y / (x * y)%g}}.\n\nCanonical normalField_cast_morphism := Morphism normalField_castM.\n\n(*This lemma states that the kernel of the automorphism restriction homomorphism from a larger field extension to an intermediate field is precisely the Galois group of the larger field over the intermediate field.*)\nLemma normalField_ker : 'ker normalField_cast = 'Gal(E / M).\n\n(*This lemma asserts that for a Galois extension containing a normal intermediate extension, the Galois group of the full extension over the intermediate field is a normal subgroup of the Galois group over the base field.*)\nLemma normalField_normal : 'Gal(E / M) <| 'Gal(E / K).\n\n(*This lemma states that the image of the Galois group of a larger extension under the automorphism restriction map to a normal intermediate field is exactly the Galois group of that intermediate field over the base field.*)\nLemma normalField_img : normalField_cast @* 'Gal(E / K) = 'Gal(M / K).\n\n(*This lemma establishes a group isomorphism showing that the quotient of the Galois group of a field extension by the Galois group of an intermediate normal extension is isomorphic to the Galois group of that intermediate extension. It further provides properties that link this isomorphism to the original automorphism restriction map.*)\nLemma normalField_isom :\n {f : {morphism ('Gal(E / K) / 'Gal(E / M)) >-> gal_of M} |\n isom ('Gal(E / K) / 'Gal (E / M)) 'Gal(M / K) f\n & (forall A, f @* (A / 'Gal(E / M)) = normalField_cast @* A)\n /\\ {in 'Gal(E / K) & M, forall x, f (coset 'Gal (E / M) x) =1 x} }%g.\n\n(*This lemma provides a concise statement that the quotient group formed by the Galois group of a large extension over a base field, divided by the Galois group of the large extension over an intermediate field, is isomorphic to the Galois group of the intermediate field over the base field.*)\nLemma normalField_isog : 'Gal(E / K) / 'Gal(E / M) \\isog 'Gal(M / K).\n\nEnd IntermediateField.\n\nSection IntermediateGroup.\n\nVariable G : {group gal_of E}.\nHypothesis nsGgalE : G <| 'Gal(E / K).\n\n(*This lemma states that for a Galois extension, the fixed field of any normal subgroup of its Galois group forms a Galois extension over the base field.*)\nLemma normal_fixedField_galois : galois K (fixedField G).\n\nEnd IntermediateGroup.\n\nEnd FundamentalTheoremOfGaloisTheory.\n\nEnd GaloisTheory.\n\nPrenex Implicits gal_repr gal gal_reprK.\nArguments gal_repr_inj {F L V} [x1 x2].\n\n(*This notation represents the Galois group of a field extension, consisting of all automorphisms of the larger field, denoted by V, that leave every element of the subfield, denoted by U, unchanged.*)\nNotation \"''Gal' ( V / U )\" := (galoisG V U) : group_scope.\n(*A notation for the Galois group of the field extension V over U, which consists of the group of all field automorphisms of V that fix every element of U.*)\nNotation \"''Gal' ( V / U )\" := (galoisG_group V U) : Group_scope.\n\nArguments fixedFieldP {F L E A a}.\nArguments normalFieldP {F L K E}.\nArguments splitting_galoisField {F L K E}.", - "field.finfield": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype div tuple bigop prime finset fingroup.\nFrom mathcomp Require Import ssralg poly polydiv morphism action countalg.\nFrom mathcomp Require Import finalg zmodp cyclic center pgroup abelian matrix.\nFrom mathcomp Require Import mxpoly vector falgebra fieldext separable galois.\nFrom mathcomp Require ssrnum ssrint archimedean algC cyclotomic.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport GroupScope GRing.Theory FinRing.Theory.\nLocal Open Scope ring_scope.\n\nSection FinNzRing.\n\nVariable R : finNzRingType.\n\n(*This lemma states that the set of all elements in any finite non-zero ring is not the singleton set containing only the zero element.*)\nLemma finNzRing_nontrivial : [set: R] != 1%g.\n\n(*This lemma states that the number of elements in any finite non-zero ring is strictly greater than one.*)\nLemma finNzRing_gt1 : 1 < #|R|.\n\nEnd FinNzRing.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use finNzRing_nontrivial instead.\")]\n(*A deprecated notation that serves as an alias for the lemma asserting that a finite non-zero ring is non-trivial, meaning its underlying set is not the singleton set containing only the zero element.*)\nNotation finRing_nontrivial := (finNzRing_nontrivial) (only parsing).\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use finNzRing_gt1 instead.\")]\n(*A deprecated notation that serves as an alias for the lemma asserting that the cardinality of any finite non-zero ring is strictly greater than one.*)\nNotation finRing_gt1 := (finNzRing_gt1) (only parsing).\n\nSection FinField.\n\nVariable F : finFieldType.\n\n(*This lemma states that the number of units in a finite field is equal to the total number of elements in the field minus one.*)\nLemma card_finField_unit : #|[set: {unit F}]| = #|F|.-1.\n\n(*This definition constructs the unit element corresponding to a given non-zero element of a finite field.*)\nDefinition finField_unit x (nz_x : x != 0) :=\n FinRing.unit F (etrans (unitfE x) nz_x).\n\n(*This lemma states that for any element in a finite field, raising it to the power of the field's cardinality results in the element itself.*)\nLemma expf_card x : x ^+ #|F| = x :> F.\n\n(*This lemma states that the polynomial formed by taking the indeterminate raised to the power of the field's cardinality and subtracting the indeterminate is equal to the product of all linear factors corresponding to the elements of the finite field.*)\nLemma finField_genPoly : 'X^#|F| - 'X = \\prod_x ('X - x%:P) :> {poly F}.\n\n(*This lemma asserts the existence of a prime number that is the characteristic of the given finite field.*)\nLemma finPcharP : {p | prime p & p \\in [pchar F]}.\n\n(*This lemma states that the set of all elements in a finite field forms an abelian group under the field's addition operation.*)\nLemma finField_is_abelem : is_abelem [set: F].\n\n(*This lemma states that if the cardinality of a finite field is a power of a prime number, then that prime number is the characteristic of the field.*)\nLemma card_finPcharP p n : #|F| = (p ^ n)%N -> prime p -> p \\in [pchar F].\n\nEnd FinField.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use finPcharP instead.\")]\n(*A deprecated notation that serves as an alias for the lemma asserting the existence of a prime number which is the characteristic of the given finite field.*)\nNotation finCharP := (finPcharP) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use card_finPcharP instead.\")]\n(*A deprecated notation that serves as an alias for the lemma stating that if a finite field's cardinality is a power of a prime number, then that prime number is the characteristic of the field.*)\nNotation card_finCharP := (card_finPcharP) (only parsing).\n\nSection CardVspace.\n\nVariables (F : finFieldType) (T : finType).\n\nSection Vector.\n\nVariable cvT : Vector F T.\n(*A local definition representing the packed vector space structure derived from a given carrier type and a finite field.*)\nLet vT := Vector.Pack cvT.\n\n(*This lemma states that the cardinality of any vector subspace over a finite field is equal to the cardinality of the field raised to the power of the dimension of the subspace.*)\nLemma card_vspace (V : {vspace vT}) : #|V| = (#|F| ^ \\dim V)%N.\n\n(*This lemma states that the cardinality of the entire vector space is equal to the cardinality of its underlying finite carrier type.*)\nLemma card_vspacef : #|{: vT}%VS| = #|T|.\n\nEnd Vector.\n\nVariable caT : Falgebra F T.\n(*A local definition representing the packed finite algebra structure derived from a given carrier type and a finite field.*)\nLet aT := Falgebra.Pack caT.\n\n(*This lemma states that the cardinality of the one-dimensional subspace spanned by the multiplicative identity of a finite algebra over a finite field is equal to the cardinality of the field.*)\nLemma card_vspace1 : #|(1%VS : {vspace aT})| = #|F|.\n\nEnd CardVspace.\n\n(*This definition provides a type alias for a given type, intended to be used for equipping a type that already has a vector space structure with a canonical finite type structure.*)\nDefinition finvect_type (vT : Type) : predArgType := vT.\n\nSection FinVector.\nVariables (R : finNzRingType) (vT : vectType R).\n(*A local notation for the aliased type of a vector space, used to attach a canonical finite type structure to it.*)\nLocal Notation fvT := (finvect_type vT).\n\nHB.instance Definition _ := Vector.on fvT.\nHB.instance Definition _ := isCountable.Build fvT\n (pcan_pickleK (can_pcan VectorInternalTheory.v2rK)).\n(*A local notation for the aliased type of a field extension, used to attach canonical structures such as a finite type instance or a splitting field instance.*)\nLocal Notation ffT := (finvect_type fT).\n\nHB.instance Definition _ := FieldExt.on ffT.\n\n(*This lemma provides the proof that a finite field extension satisfies the axiom of a splitting field, which asserts that for any element in the extension, the roots of its minimal polynomial over the base field are also contained within the extension.*)\nLemma ffT_splitting_subproof : SplittingField.axiom ffT.\n\n(*This definition defines a structure that packages a given finite field extension into a canonical splitting field type over its base finite field.*)\nDefinition FinSplittingFieldType (F : finFieldType) (fT : fieldExtType F) :=\n HB.pack_for (splittingFieldType F) fT (SplittingField.on (finvect_type fT)).\n(*This definition defines a structure that packages a given finite field extension, already recognized as a splitting field, into a canonical finite field type.*)\nDefinition FinFieldExtType (F : finFieldType) (fT : fieldExtType F) :=\n HB.pack_for finFieldType (FinSplittingFieldType fT)\n (FinRing.Field.on (finvect_type fT)).\nArguments FinSplittingFieldType : clear implicits.\n\nSection PrimeChar.\n\nVariable p : nat.\n\nSection PrimeCharRing.\n\nVariable R0 : nzRingType.\n\n(*This definition creates a type alias for a non-zero ring, parameterized by a proof that a given natural number is its characteristic, making this characteristic available for dependent-type programming.*)\nDefinition pPrimeCharType of p \\in [pchar R0] : predArgType := R0.\n\nHypothesis pcharRp : p \\in [pchar R0].\n(*A local notation for the aliased type of a ring which has a specific natural number as its characteristic, making this fact readily available in the local context.*)\nLocal Notation R := (pPrimeCharType pcharRp).\nImplicit Types (a b : 'F_p) (x y : R).\n\nHB.instance Definition _ := GRing.NzRing.on R.\n\n(*This definition specifies a scalar multiplication operation, where a scalar from the prime field of characteristic p acts on an element of a ring with the same characteristic p by canonical injection followed by ring multiplication.*)\nDefinition pprimeChar_scale a x := a%:R * x.\nLocal Infix \"*p':\" := pprimeChar_scale (at level 40).\n\n(*This local lemma asserts that for a ring with prime characteristic, converting a natural number to an element of the corresponding prime field and then mapping it into the ring yields the same result as directly mapping the natural number into the ring.*)\nLet natrFp n : (inZp n : 'F_p)%:R = n%:R :> R.\n\n(*This lemma states that the scalar multiplication of a ring element by elements of the corresponding prime field is associative, meaning that scaling by one scalar and then another is equivalent to scaling by the product of the two scalars.*)\nLemma pprimeChar_scaleA a b x : a *p': (b *p': x) = (a * b) *p': x.\n\n(*This lemma states that the multiplicative identity of the prime field acts as a left identity for the defined scalar multiplication on the ring, meaning scaling any ring element by one leaves it unchanged.*)\nLemma pprimeChar_scale1 : left_id 1 pprimeChar_scale.\n\n(*This lemma states that the prime characteristic scalar multiplication is right-distributive over ring addition.*)\nLemma pprimeChar_scaleDr : right_distributive pprimeChar_scale +%R.\n\n(*This lemma states that for any fixed ring element, the prime characteristic scalar multiplication is a morphism with respect to addition in its first argument, which means it is left-distributive.*)\nLemma pprimeChar_scaleDl x : {morph pprimeChar_scale^~ x: a b / a + b}.\n\nHB.instance Definition _ := GRing.Zmodule_isLmodule.Build 'F_p R\n pprimeChar_scaleA pprimeChar_scale1 pprimeChar_scaleDr pprimeChar_scaleDl.\n\n(*This lemma states that prime characteristic scalar multiplication is compatible with ring multiplication on the left, showing that scaling a product of two ring elements is the same as scaling the first element and then multiplying by the second.*)\nLemma pprimeChar_scaleAl (a : 'F_p) (u v : R) : a *: (u * v) = (a *: u) * v.\n\nHB.instance Definition _ := GRing.Lmodule_isLalgebra.Build 'F_p R\n pprimeChar_scaleAl.\n\n(*This lemma states that prime characteristic scalar multiplication is compatible with ring multiplication on the right, showing that scaling a product of two ring elements is the same as multiplying the first element by the scaled second element.*)\nLemma pprimeChar_scaleAr (a : 'F_p) (x y : R) : a *: (x * y) = x * (a *: y).\n\n(*This notation provides a local alias for the `pPrimeCharType` constructor, which builds a ring type with a specified prime characteristic.*)\nLocal Notation type := @pPrimeCharType.\n\nHB.instance Definition _ (R : unitRingType) pcharRp :=\n GRing.UnitRing.on (type R pcharRp).\nHB.instance Definition _ (R : comNzRingType) pcharRp :=\n GRing.ComNzRing.on (type R pcharRp).\nHB.instance Definition _ (R : comUnitRingType) pcharRp :=\n GRing.ComUnitRing.on (type R pcharRp).\nHB.instance Definition _ (R : idomainType) pcharRp :=\n GRing.IntegralDomain.on (type R pcharRp).\nHB.instance Definition _ (R : fieldType) pcharRp :=\n GRing.Field.on (type R pcharRp).\n\nSection FinNzRing.\n\nVariables (R0 : finNzRingType) (pcharRp : p \\in [pchar R0]).\n(*This notation provides a local alias for the ring type equipped with a specific prime characteristic.*)\nLocal Notation R := (type _ pcharRp).\n\nHB.instance Definition _ := FinGroup.on R.\n\n(*This definition establishes a proof that the characteristic `p` of the ring is a prime number.*)\nLet pr_p : prime p. \n\n(*This lemma states that the additive group of a ring with prime characteristic `p` is a `p`-elementary abelian group, meaning every non-identity element has order `p`.*)\nLemma pprimeChar_abelem : p.-abelem [set: R].\n\n(*This lemma states that the additive group of a ring with prime characteristic `p` is a `p`-group, meaning the order of every element is a power of `p`.*)\nLemma pprimeChar_pgroup : p.-group [set: R].\n\n(*This lemma states that the order of any non-zero element in the additive group of a ring with prime characteristic `p` is equal to `p`.*)\nLemma order_pprimeChar x : x != 0 :> R -> #[x]%g = p.\n\n(*This definition introduces `n` as the exponent such that the cardinality of the ring is equal to the prime characteristic `p` raised to the power of `n`.*)\nLet n := logn p #|R|.\n\n(*This lemma states that the cardinality of a finite ring with prime characteristic `p` is equal to `p` raised to the power of `n`, where `n` is the base-`p` logarithm of the ring's cardinality.*)\nLemma card_pprimeChar : #|R| = (p ^ n)%N.\n\n(*This lemma states that a finite ring with prime characteristic `p` satisfies the axioms of a vector space of dimension `n` over the prime field with `p` elements.*)\nLemma pprimeChar_vectAxiom : Vector.axiom n R.\n\n(*This lemma states that the dimension of a finite ring with prime characteristic `p` when viewed as a vector space over the prime field with `p` elements is equal to `n`, the base-`p` logarithm of the ring's cardinality.*)\nLemma pprimeChar_dimf : \\dim {: R : vectType 'F_p } = n.\n\nEnd FinNzRing.\n\nHB.instance Definition _ (R : finUnitRingType) pcharRp :=\n FinRing.UnitRing.on (type R pcharRp).\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (R : finUnitRingType) pcharRp :=\n FinRing.UnitAlgebra.on (type R pcharRp).\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (R : finUnitRingType) pcharRp :=\n Falgebra.on (type R pcharRp).\nHB.instance Definition _ (R : finComNzRingType) pcharRp :=\n FinRing.ComNzRing.on (type R pcharRp).\nHB.instance Definition _ (R : finComUnitRingType) pcharRp :=\n FinRing.ComUnitRing.on (type R pcharRp).\n(*This notation provides a local alias for the finite field type equipped with a specific prime characteristic.*)\nLocal Notation F := (type _ pcharFp).\n\nHB.instance Definition _ := Finite.on F.\n(*This notation is a deprecated alias for `pPrimeCharType`, used for parsing only. It constructs a ring type with a specified prime characteristic.*)\nNotation PrimeCharType := (pPrimeCharType) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_scale instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_scale`, used for parsing only. It refers to the scalar multiplication of a ring element by an element from its prime field.*)\nNotation primeChar_scale := (pprimeChar_scale) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_scaleA instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_scaleA`, used for parsing only. It refers to a lemma asserting the associativity of prime characteristic scalar multiplication.*)\nNotation primeChar_scaleA := (pprimeChar_scaleA) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_scale1 instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_scale1`, used for parsing only. It refers to a lemma asserting that scalar multiplication by one from the prime field is the identity.*)\nNotation primeChar_scale1 := (pprimeChar_scale1) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_scaleDr instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_scaleDr`, used for parsing only. It refers to a lemma asserting the right-distributivity of prime characteristic scalar multiplication over ring addition.*)\nNotation primeChar_scaleDr := (pprimeChar_scaleDr) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_scaleDl instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_scaleDl`, used for parsing only. It refers to a lemma asserting the left-distributivity of prime characteristic scalar multiplication over scalar addition.*)\nNotation primeChar_scaleDl := (pprimeChar_scaleDl) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_scaleAl instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_scaleAl`, used for parsing only. It refers to a lemma asserting the left-compatibility of prime characteristic scalar multiplication with ring multiplication.*)\nNotation primeChar_scaleAl := (pprimeChar_scaleAl) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_scaleAr instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_scaleAr`, used for parsing only. It refers to a lemma asserting the right-compatibility of prime characteristic scalar multiplication with ring multiplication.*)\nNotation primeChar_scaleAr := (pprimeChar_scaleAr) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_abelem instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_abelem`, used for parsing only. It refers to a lemma stating that the additive group of a ring with prime characteristic is a `p`-elementary abelian group.*)\nNotation primeChar_abelem := (pprimeChar_abelem) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_pgroup instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_pgroup`, used for parsing only. It refers to a lemma stating that the additive group of a ring with prime characteristic is a `p`-group.*)\nNotation primeChar_pgroup := (pprimeChar_pgroup) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use order_pprimeChar instead.\")]\n(*This notation is a deprecated alias for `order_pprimeChar`, used for parsing only. It refers to a lemma stating that the order of any non-zero element in a ring with prime characteristic `p` is equal to `p`.*)\nNotation order_primeChar := (order_pprimeChar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use card_pprimeChar instead.\")]\n(*This notation is a deprecated alias for `card_pprimeChar`, used for parsing only. It refers to a lemma stating that the cardinality of a finite ring with prime characteristic `p` is a power of `p`.*)\nNotation card_primeChar := (card_pprimeChar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_vectAxiom instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_vectAxiom`, used for parsing only. It refers to a lemma stating that a finite ring with prime characteristic satisfies the axioms of a vector space over its prime field.*)\nNotation primeChar_vectAxiom := (pprimeChar_vectAxiom) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pprimeChar_dimf instead.\")]\n(*This notation is a deprecated alias for `pprimeChar_dimf`, used for parsing only. It refers to a lemma stating the dimension of a finite ring with prime characteristic as a vector space over its prime field.*)\nNotation primeChar_dimf := (pprimeChar_dimf) (only parsing).\n\nSection FinSplittingField.\n\nVariable F : finFieldType.\n\n(*This definition specifies the order, or cardinality, of a vector space over a finite field as the cardinality of the field raised to the power of the dimension of the space.*)\nLet order (L : vectType F) (K : {vspace L}) := (#|F| ^ \\dim K)%N.\n\nSection FinGalois.\n\nVariable L : splittingFieldType F.\nImplicit Types (a b : F) (x y : L) (K E : {subfield L}).\n\n(*This definition constructs the Galois group of a splitting field over one of its subfields.*)\nLet galL K : galois K {:L}.\n\n(*This fact asserts the existence of a generator for the Galois group of a splitting field over a subfield. This generator, known as the Frobenius automorphism, acts on any element of the field by raising it to the power of the size of the subfield.*)\nFact galLgen K :\n {alpha | generator 'Gal({:L} / K) alpha & forall x, alpha x = x ^+ order K}.\n\n(*This lemma states that if one finite field is a subfield of another, then the larger field is a Galois extension of the smaller one.*)\nLemma finField_galois K E : (K <= E)%VS -> galois K E.\n\n(*This lemma states that for any extension of finite fields, the Galois group is cyclic and has a specific generator. This generator is the Frobenius automorphism, which maps every element of the larger field to itself raised to the power of the size of the smaller field.*)\nLemma finField_galois_generator K E :\n (K <= E)%VS ->\n {alpha | generator 'Gal(E / K) alpha\n & {in E, forall x, alpha x = x ^+ order K}}.\n\nEnd FinGalois.\n\n(*This lemma states that an element of a larger field belongs to a given finite subfield if and only if that element is a fixed point of the Frobenius automorphism for that subfield, which means the element is equal to itself raised to the power of the size of the subfield.*)\nLemma Fermat's_little_theorem (L : fieldExtType F) (K : {subfield L}) a :\n (a \\in K) = (a ^+ order K == a).\n\nEnd FinSplittingField.\n\nSection FinFieldExists.\n\n(*This definition provides a function to convert a polynomial over a base field into a polynomial over an extension field by applying the canonical field inclusion to each of the polynomial's coefficients.*)\nLet map_poly_extField (F : fieldType) (L : fieldExtType F) :=\n map_poly (in_alg L) : {poly F} -> {poly L}.\n\n(*This notation represents the operation of embedding a polynomial over a base field into the corresponding polynomial ring over an extension field by applying the canonical field inclusion to its coefficients.*)\nLocal Notation \"p ^%:A\" := (map_poly_extField _ p)\n (at level 2, format \"p ^%:A\") : ring_scope.\n\n(*This lemma asserts the existence of a splitting field for any non-zero polynomial defined over a finite field, which is a field extension where the polynomial completely factors into linear terms.*)\nLemma FinSplittingFieldFor (F : finFieldType) (p : {poly F}) :\n p != 0 -> {L : splittingFieldType F | splittingFieldFor 1 p^%:A {:L}}.\n\n(*This lemma states that for any prime number and any positive exponent, there exists a finite field whose characteristic is that prime and whose size is the prime raised to that exponent.*)\nLemma pPrimePowerField p k (m := (p ^ k)%N) :\n prime p -> 0 < k -> {Fm : finFieldType | p \\in [pchar Fm] & #|Fm| = m}.\n\nEnd FinFieldExists.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pPrimePowerField instead.\")]\n(*This notation is a deprecated, parsing-only alias for the lemma asserting the existence of a finite field for any given prime power. It is recommended to use `pPrimePowerField` instead.*)\nNotation PrimePowerField := (pPrimePowerField) (only parsing).\n\nSection FinDomain.\n\nImport order ssrnum ssrint archimedean algC cyclotomic Order.TTheory Num.Theory.\nLocal Infix \"%|\" := dvdn. \n\nVariable R : finUnitRingType.\n\nHypothesis domR : GRing.integral_domain_axiom R.\nImplicit Types x y : R.\n\n(*This definition provides a proof that any non-zero element in a finite integral domain is left-regular, meaning that left multiplication by this element is an injective map.*)\nLet lregR x : x != 0 -> GRing.lreg x.\n\n(*This lemma states that any finite integral domain is a field, asserting that it satisfies the axiom guaranteeing that every non-zero element has a multiplicative inverse.*)\nLemma finDomain_field : GRing.field_axiom R.\n\n(*This theorem states that multiplication in any finite integral domain is commutative.*)\nTheorem finDomain_mulrC : @commutative R R *%R.\n\n(*This definition constructs a canonical finite field structure from any finite integral domain. It bundles the domain with proofs of its commutativity and the existence of multiplicative inverses for non-zero elements.*)\nDefinition FinDomainFieldType : finFieldType :=\n let cC := GRing.PzRing_hasCommutativeMul.Build R finDomain_mulrC in\n let cR : comUnitRingType := HB.pack R cC in\n let iC := GRing.ComUnitRing_isIntegral.Build cR domR in\n let iR : finIdomainType := HB.pack cR iC in\n let fC := GRing.UnitRing_isField.Build iR finDomain_field in\n HB.pack iR fC.\n\n(*This definition constructs a splitting field structure for a finite integral domain of a given prime characteristic. It endows the domain with the structure of a field that is a splitting extension over its own prime subfield.*)\nDefinition FinDomainSplittingFieldType_pchar p (pcharRp : p \\in [pchar R]) :=\n SplittingField.clone 'F_p R (@pPrimeCharType p FinDomainFieldType pcharRp).\n\nEnd FinDomain.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use FinDomainSplittingFieldType_pchar instead.\")]\n(*This definition constructs a finite field type for the prime field of a given prime characteristic. It uses a provided finite integral domain that is known to have this prime as its characteristic as a model, creating an isomorphic type that formally represents this prime field.*)", - "field.all_field": "From mathcomp Require Export algC.\nFrom mathcomp Require Export algebraics_fundamentals.\nFrom mathcomp Require Export algnum.\nFrom mathcomp Require Export closed_field.\nFrom mathcomp Require Export cyclotomic.\nFrom mathcomp Require Export falgebra.\nFrom mathcomp Require Export fieldext.\nFrom mathcomp Require Export finfield.\nFrom mathcomp Require Export galois.\nFrom mathcomp Require Export separable.", - "field.fieldext": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq div.\nFrom mathcomp Require Import choice fintype tuple finfun bigop ssralg countalg.\nFrom mathcomp Require Import finalg zmodp matrix vector falgebra poly polydiv.\nFrom mathcomp Require Import mxpoly generic_quotient.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nLocal Open Scope ring_scope.\nImport GRing.Theory.\n\n#[short(type=\"fieldExtType\")]\n(*This structure defines a field extension as a type that is simultaneously a field and an algebra over a base non-zero ring.*)\nHB.structure Definition FieldExt (R : nzRingType) := {T of Falgebra R T &\n GRing.PzRing_hasCommutativeMul T & GRing.Field T}.\n\nModule FieldExtExports.\nBind Scope ring_scope with FieldExt.sort.\n(*This notation denotes the type of all subfields within a given field extension.*)\nNotation \"{ 'subfield' L }\" := (aspace L)\n \n (format \"{ 'subfield' L }\") : type_scope.\nEnd FieldExtExports.\nHB.export FieldExtExports.\n\n(*This lemma states that for any vector subspace and any non-zero element of the field extension, the dimension of the subspace formed by multiplying the original subspace by the subspace spanned by the element is equal to the dimension of the original subspace.*)\nLemma dim_cosetv U x : x != 0 -> \\dim (U * <[x]>) = \\dim U.\n\n(*This lemma states that the product of vector subspaces within a field extension is a commutative operation.*)\nLemma prodvC : commutative (@prodv F0 L).\n\nHB.instance Definition _ :=\n SemiGroup.isCommutativeLaw.Build {vspace L} (@prodv _ L) prodvC.\n\n(*This lemma states that the product of vector subspaces within a field extension is left-commutative, meaning that multiplying a product of two subspaces on the left by a third subspace yields the same result as if the first two were swapped.*)\nLemma prodvCA : left_commutative (@prodv F0 L).\n\n(*This lemma states that the product of vector subspaces within a field extension is right-commutative, meaning that multiplying a subspace by a product of two other subspaces yields the same result as if the first subspace and the first factor of the product were swapped.*)\nLemma prodvAC : right_commutative (@prodv F0 L).\n\n(*This lemma states that the identity element of any subfield, when considered as an algebra, is the multiplicative identity element 1 of the larger field.*)\nLemma algid1 K : algid K = 1. \n\n(*This lemma states that the multiplicative identity element 1 is always a member of any subfield.*)\nLemma mem1v K : 1 \\in K. \n(*This lemma states that the subspace generated by the multiplicative identity element 1 is a sub-structure of any subfield.*)\nLemma sub1v K : (1 <= K)%VS. \n\n(*This lemma states that any subfield is algebraically closed, meaning that the algebra generated by the elements of the subfield is the subfield itself.*)\nLemma subfield_closed K : agenv K = K.\n\n(*This lemma states that any algebra homomorphism from a field extension to another algebra over the same base field is injective, which means its linear kernel is the zero subspace.*)\nLemma AHom_lker0 (rT : falgType F0) (f : 'AHom(L, rT)) : lker f == 0%VS.\n\n(*This lemma states that any algebra endomorphism on a field extension is injective, meaning its linear kernel is the zero subspace.*)\nLemma AEnd_lker0 (f : 'AEnd(L)) : lker f == 0%VS. \n\n(*This fact asserts that the image of a subfield under an algebra homomorphism is itself an algebra subspace.*)\nFact aimg_is_aspace (rT : falgType F0) (f : 'AHom(L, rT)) (E : {subfield L}) :\n is_aspace (f @: E).\n\nCanonical aimg_aspace rT f E := ASpace (@aimg_is_aspace rT f E).\n\n(*This lemma provides a reflection property, stating that the vector space obtained by adjoining an element to a subfield is identical to the original subfield if and only if the element is already a member of that subfield.*)\nLemma Fadjoin_idP {K x} : reflect (<>%VS = K) (x \\in K).\n\n(*This lemma states that adjoining the zero element to any subfield results in the original subfield itself.*)\nLemma Fadjoin0 K : <>%VS = K.\n\n(*This lemma states that adjoining an empty sequence of elements to a subfield results in the original subfield.*)\nLemma Fadjoin_nil K : <>%VS = K.\n\n(*This lemma provides a reflection property, stating that the subalgebra generated by a subfield and an additional element is a substructure of another subfield if and only if the original subfield is a substructure of the other subfield and the additional element is also a member of it.*)\nLemma FadjoinP {K x E} :\n reflect (K <= E /\\ x \\in E)%VS (<>%AS <= E)%VS.\n\n(*This lemma provides a reflection property, stating that the subalgebra generated by a subfield and a sequence of elements is a substructure of another subfield if and only if the original subfield is a substructure of the other subfield and all elements from the sequence are members of it.*)\nLemma Fadjoin_seqP {K} {rs : seq L} {E} :\n reflect (K <= E /\\ {subset rs <= E})%VS (<> <= E)%VS.\n\n(*This lemma states that for any subfield, a polynomial with coefficients from the base field, when its coefficients are mapped into the larger field extension, is considered a polynomial over that subfield.*)\nLemma alg_polyOver E p : map_poly (in_alg L) p \\is a polyOver E.\n\n(*This lemma states that the vector space generated by the multiplicative identity and another element is a sub-structure of a given subfield if and only if that element is a member of the subfield.*)\nLemma sub_adjoin1v x E : (<<1; x>> <= E)%VS = (x \\in E)%VS.\n\n(*This fact asserts that the value inclusion map, which embeds an element from a subfield into the larger ambient field, is a monoid morphism with respect to multiplication.*)\nFact vsval_monoid_morphism K : monoid_morphism (vsval : subvs_of K -> L).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `subfx_eval_is_monoid_morphism` instead\")]\n(*This definition, now deprecated since mathcomp 2.5.0, provides proof that the value inclusion map from a subfield into the larger ambient field is multiplicative. Use `subfx_eval_is_monoid_morphism` instead.*)\nDefinition vsval_is_multiplicative K :=\n (fun g => (g.2,g.1)) (vsval_monoid_morphism K).\nHB.instance Definition _ (K : {subfield L}) :=\n GRing.isMonoidMorphism.Build (subvs_of K) L vsval (vsval_monoid_morphism K).\n\n(*This lemma states that for any element of a subfield, the image of its multiplicative inverse under the value inclusion map is equal to the multiplicative inverse of its image in the larger field.*)\nLemma vsval_invf K (w : subvs_of K) : val w^-1 = (vsval w)^-1.\n\n(*This fact asserts that any subfield is closed under right division, meaning that dividing any element of the subfield by any non-zero element of the same subfield results in an element that is also within that subfield.*)\nFact aspace_divr_closed K : divr_closed K.\n\nHB.instance Definition _ K :=\n GRing.isDivClosed.Build L (pred_of_vspace K) (aspace_divr_closed K).\n\nHB.instance Definition _ (K : {subfield L}) :=\n GRing.isSubPzSemiRing.Build L (pred_of_vspace K) (subvs_of K)\n (rmorph1 _, rmorphM _).\n\nHB.instance Definition _ (K : {subfield L}) :=\n [SubNzRing_isSubComNzRing of subvs_of K by <:].\nHB.instance Definition _ (K : {subfield L}) :=\n [SubComUnitRing_isSubIntegralDomain of subvs_of K by <:].\n\n(*This lemma provides the field axiom for the type of elements of a subfield, which is the property that every non-zero element has a multiplicative inverse within the subfield.*)\nLemma subvs_fieldMixin K : GRing.field_axiom (subvs_of K).\n\n(*This lemma establishes an equivalence, stating that a polynomial with coefficients in the larger field is a polynomial over a given subfield if and only if there exists a corresponding polynomial with coefficients explicitly typed as elements of that subfield, which maps to the original polynomial.*)\nLemma polyOver_subvs {K} {p : {poly L}} :\n reflect (exists q : {poly subvs_of K}, p = map_poly vsval q)\n (p \\is a polyOver K).\n\n(*This lemma states that the set of polynomials over a given subfield is closed under polynomial division, meaning the quotient of two such polynomials is also a polynomial over that subfield.*)\nLemma divp_polyOver K : {in polyOver K &, forall p q, p %/ q \\is a polyOver K}.\n\n(*This lemma states that the set of polynomials over a given subfield is closed under the polynomial modulus operation, meaning the remainder of the division of two such polynomials is also a polynomial over that subfield.*)\nLemma modp_polyOver K : {in polyOver K &, forall p q, p %% q \\is a polyOver K}.\n\n(*This lemma states that the set of polynomials over a given subfield is closed under the polynomial greatest common divisor operation, meaning the greatest common divisor of two such polynomials is also a polynomial over that subfield.*)\nLemma gcdp_polyOver K :\n {in polyOver K &, forall p q, gcdp p q \\is a polyOver K}.\n\n(*This fact asserts that the product of two subfields, considered as vector subspaces, forms an algebraic subspace.*)\nFact prodv_is_aspace E F : is_aspace (E * F).\n\nCanonical prodv_aspace E F : {subfield L} := ASpace (prodv_is_aspace E F).\n\n(*This fact asserts that the algebraic identity of a given subfield is an element of another subfield.*)\nFact field_mem_algid E F : algid E \\in F. \nCanonical capv_aspace E F : {subfield L} := aspace_cap (field_mem_algid E F).\n\n(*This lemma states that if a vector space is a subspace of another, then the polynomials with coefficients from the first space form a subset of the polynomials with coefficients from the second.*)\nLemma polyOverSv U V : (U <= V)%VS -> {subset polyOver U <= polyOver V}.\n\n(*This lemma states that a vector space is a subspace of the vector space formed by scaling it on the left by the elements of a field.*)\nLemma field_subvMl F U : (U <= F * U)%VS.\n\n(*This lemma states that a vector space is a subspace of the vector space formed by scaling it on the right by the elements of a field.*)\nLemma field_subvMr U F : (U <= U * F)%VS.\n\n(*This lemma states that if a vector space is closed under scalar multiplication by a field, then the vector space resulting from this scalar multiplication is identical to the original vector space.*)\nLemma field_module_eq F M : (F * M <= M)%VS -> (F * M)%VS = M.\n\n(*This lemma states that for a field and a subfield, the condition that the larger field is a module over the subfield is equivalent to the condition that the subfield is a subspace of the larger field.*)\nLemma sup_field_module F E : (F * E <= E)%VS = (F <= E)%VS.\n\n(*This lemma states that if a vector space is a module over a field, then the dimension of the field divides the dimension of the vector space.*)\nLemma field_module_dimS F M : (F * M <= M)%VS -> (\\dim F %| \\dim M)%N.\n\n(*This lemma states that if one field is a subfield of another, then the dimension of the first field divides the dimension of the second.*)\nLemma field_dimS F E : (F <= E)%VS -> (\\dim F %| \\dim E)%N.\n\n(*This lemma states that if a vector space is a module over a field, its total dimension is the product of its dimension over that field and the dimension of the field itself.*)\nLemma dim_field_module F M : (F * M <= M)%VS -> \\dim M = (\\dim_F M * \\dim F)%N.\n\n(*This lemma states that if one field is a subfield of another, the dimension of the larger field is the product of its dimension over the subfield and the dimension of the subfield.*)\nLemma dim_sup_field F E : (F <= E)%VS -> \\dim E = (\\dim_F E * \\dim F)%N.\n\n(*This lemma states that for any vector space that is a module over a field, there exists a basis. Specifically, it asserts the existence of a finite sequence of non-zero vectors such that the vector space is the direct sum of the subspaces spanned by these basis vectors over the field.*)\nLemma field_module_semisimple F M (m := \\dim_F M) :\n (F * M <= M)%VS ->\n {X : m.-tuple L | {subset X <= M} /\\ 0 \\notin X\n & let FX := (\\sum_(i < m) F * <[X`_i]>)%VS in FX = M /\\ directv FX}.\n\nSection FadjoinPolyDefinitions.\n\nVariables (U : {vspace L}) (x : L).\n\n(*This definition specifies the degree of an extension, calculated as the dimension of the vector space generated by a given vector space and an adjoined element, relative to the original vector space.*)\nDefinition adjoin_degree := (\\dim_U <>).-1.+1.\n(*This notation introduces a shorthand for the 'adjoin_degree', which represents the degree of a field extension obtained by adjoining an element.*)\nLocal Notation n := adjoin_degree.\n\n(*This definition specifies a vector space constructed as the sum of subspaces, where each subspace is generated by multiplying a base vector space by successive powers of a given adjoined element, up to one less than the extension degree.*)\nDefinition Fadjoin_sum := (\\sum_(i < n) U * <[x ^+ i]>)%VS.\n\n(*This definition specifies a function that maps a vector from a field extension space to a polynomial, where the coefficients of the polynomial are the coordinates of the vector with respect to the basis formed by the powers of the adjoined element.*)\nDefinition Fadjoin_poly v : {poly L} :=\n \\poly_(i < n) (sumv_pi Fadjoin_sum (inord i) v / x ^+ i).\n\n(*This definition specifies the minimal polynomial of an adjoined element as a monic polynomial whose degree equals the extension degree and whose constant term and lower-order coefficients are determined by the representation of the next power of the adjoined element.*)\nDefinition minPoly : {poly L} := 'X^n - Fadjoin_poly (x ^+ n).\n\n(*This lemma states that the size of a polynomial created by the 'Fadjoin_poly' function is at most the degree of the corresponding field extension.*)\nLemma size_Fadjoin_poly v : size (Fadjoin_poly v) <= n.\n\n(*This lemma states that any polynomial generated by the 'Fadjoin_poly' function has all its coefficients within the original base vector space.*)\nLemma Fadjoin_polyOver v : Fadjoin_poly v \\is a polyOver U.\n\n(*This fact asserts that the 'Fadjoin_poly' function, which converts a vector to a polynomial, is a linear map.*)\nFact Fadjoin_poly_is_linear : linear_for (in_alg L \\; *:%R) Fadjoin_poly.\n\n(*This lemma states that the size of the minimal polynomial is exactly one greater than the degree of the corresponding field extension.*)\nLemma size_minPoly : size minPoly = n.+1.\n\n(*This lemma states that the defined minimal polynomial is monic, meaning its leading coefficient is one.*)\nLemma monic_minPoly : minPoly \\is monic.\n\nEnd FadjoinPolyDefinitions.\n\nSection FadjoinPoly.\n\nVariables (K : {subfield L}) (x : L).\n(*A variable representing the degree of a simple algebraic field extension, which is equal to the dimension of the extension field as a vector space over the base field.*)\nLocal Notation n := (adjoin_degree (asval K) x).\n(*A notation for the vector space constructed as the direct sum of subspaces spanned by the powers of an algebraic element over a base field, representing a simple field extension.*)\nLocal Notation sumKx := (Fadjoin_sum (asval K) x).\n\n(*This lemma states that the degree of a simple algebraic extension is equal to the dimension of the extended field when viewed as a vector space over the base field.*)\nLemma adjoin_degreeE : n = \\dim_K <>.\n\n(*This lemma relates the dimension of a simple algebraic extension vector space to the dimension of its base field, stating that the former is the product of the extension degree and the latter.*)\nLemma dim_Fadjoin : \\dim <> = (n * \\dim K)%N.\n\n(*This lemma states that adjoining the zero element to a field results in a field extension of degree one.*)\nLemma adjoin0_deg : adjoin_degree K 0 = 1.\n\n(*This lemma states that a simple algebraic extension has a degree of one if and only if the adjoined element is already a member of the base field.*)\nLemma adjoin_deg_eq1 : (n == 1) = (x \\in K).\n\n(*This lemma asserts that the vector spaces whose sum forms a simple algebraic extension are in a direct sum, implying their basis vectors are linearly independent.*)\nLemma Fadjoin_sum_direct : directv sumKx.\n\n(*This lemma states that for any natural number index which is less than the degree of the field extension, the corresponding power of the adjoined element is not equal to zero.*)\nLet nz_x_i (i : 'I_n) : x ^+ i != 0.\n\n(*This lemma establishes that the vector space generated by adjoining an algebraic element to a field is identical to the canonical construction of this space as a direct sum.*)\nLemma Fadjoin_eq_sum : <>%VS = sumKx.\n\n(*This lemma states that for any element in a simple field extension, evaluating its canonical polynomial representation at the adjoined algebraic element reconstructs the original element.*)\nLemma Fadjoin_poly_eq v : v \\in <>%VS -> (Fadjoin_poly K x v).[x] = v.\n\n(*This lemma asserts that the result of evaluating a polynomial with coefficients from a base field at an algebraic element is always an element of the corresponding field extension.*)\nLemma mempx_Fadjoin p : p \\is a polyOver K -> p.[x] \\in <>%VS.\n\n(*This lemma states that an element belongs to the vector space generated by an element over a field if and only if it can be expressed as the evaluation of some polynomial with coefficients in that field at the given element.*)\nLemma Fadjoin_polyP {v} :\n reflect (exists2 p, p \\in polyOver K & v = p.[x]) (v \\in <>%VS).\n\n(*This lemma guarantees the uniqueness of the polynomial representation of an element in a simple extension, stating that if a polynomial of sufficiently small degree evaluates to that element, it must be the canonical polynomial representation.*)\nLemma Fadjoin_poly_unique p v :\n p \\is a polyOver K -> size p <= n -> p.[x] = v -> Fadjoin_poly K x v = p.\n\n(*This lemma states that the canonical polynomial representation of an element that is already in the base field is the corresponding constant polynomial.*)\nLemma Fadjoin_polyC v : v \\in K -> Fadjoin_poly K x v = v%:P.\n\n(*This lemma states that if an adjoined algebraic element is not originally in the base field, its canonical polynomial representation is the monomial of degree one.*)\nLemma Fadjoin_polyX : x \\notin K -> Fadjoin_poly K x x = 'X.\n\n(*This lemma asserts that the minimal polynomial of an algebraic element over a field is a polynomial whose coefficients belong to that field.*)\nLemma minPolyOver : minPoly K x \\is a polyOver K.\n\n(*This lemma states that an algebraic element is a root of its own minimal polynomial, meaning evaluation results in zero.*)\nLemma minPolyxx : (minPoly K x).[x] = 0.\n\n(*This lemma asserts that an algebraic element is a root of its minimal polynomial over a given field.*)\nLemma root_minPoly : root (minPoly K x) x. \n\n(*This lemma states that the canonical polynomial representation of a polynomial evaluated at an algebraic element is equivalent to the original polynomial reduced modulo the minimal polynomial.*)\nLemma Fadjoin_poly_mod p :\n p \\is a polyOver K -> Fadjoin_poly K x p.[x] = p %% minPoly K x.\n\n(*This lemma states that the minimal polynomial of an element is a linear polynomial if and only if that element is a member of the base field.*)\nLemma minPoly_XsubC : reflect (minPoly K x = 'X - x%:P) (x \\in K).\n\n(*This lemma states that if a polynomial over a base field has a degree no greater than the extension degree, it has the adjoined algebraic element as a root if and only if it is the zero polynomial.*)\nLemma root_small_adjoin_poly p :\n p \\is a polyOver K -> size p <= n -> root p x = (p == 0).\n\n(*This lemma establishes the irreducibility of the minimal polynomial by stating that any polynomial that divides it must be associated with either a unit or the minimal polynomial itself.*)\nLemma minPoly_irr p :\n p \\is a polyOver K -> p %| minPoly K x -> (p %= minPoly K x) || (p %= 1).\n\n(*This lemma states that the minimal polynomial of an algebraic element over a field divides every other polynomial over that field which has the element as a root.*)\nLemma minPoly_dvdp p : p \\is a polyOver K -> root p x -> (minPoly K x) %| p.\n\nEnd FadjoinPoly.\n\n(*This lemma relates minimal polynomials across a tower of fields, stating that if one field is a subfield of another, the minimal polynomial of an element with respect to the larger field divides its minimal polynomial with respect to the smaller field.*)\nLemma minPolyS K E a : (K <= E)%VS -> minPoly E a %| minPoly K a.\n\nArguments Fadjoin_polyP {K x v}.\n(*This lemma establishes that an element belongs to a simple extension over a prime field if and only if it can be expressed as a polynomial in the adjoined element, where the polynomial's coefficients are mapped from the prime field.*)\nLemma Fadjoin1_polyP x v :\n reflect (exists p, v = (map_poly (in_alg L) p).[x]) (v \\in <<1; x>>%VS).\n\nSection Horner.\n\nVariables z : L.\n\n(*This definition introduces a ring homomorphism that evaluates a polynomial at a specified algebraic element using Horner's method.*)\nDefinition fieldExt_horner := horner_morph (fun x => mulrC z (in_alg L x)).\nHB.instance Definition _ := GRing.RMorphism.on fieldExt_horner.\n(*This lemma states that applying the Horner-based evaluation homomorphism to a constant polynomial yields the corresponding constant element in the extension field.*)\nLemma fieldExt_hornerC b : fieldExt_horner b%:P = b%:A.\n\n(*This lemma states that the Horner-based evaluation homomorphism maps the polynomial indeterminate to the specific algebraic element used for the evaluation.*)\nLemma fieldExt_hornerX : fieldExt_horner 'X = z.\n\n(*This fact declares that the Horner-based polynomial evaluation homomorphism is a scalable morphism, meaning it preserves scalar multiplication.*)\nFact fieldExt_hornerZ : scalable fieldExt_horner.\n\n(*A notation representing the intersection of two vector subspaces, which itself forms a vector subspace.*)\nNotation \"E :&: F\" := (capv_aspace E F) : aspace_scope.\n(*This notation represents the centralizer of an element within a given algebra, which is the set of all elements in the algebra that commute with the given element.*)\nNotation \"'C_ E [ x ]\" := (capv_aspace E 'C[x]) : aspace_scope.\n(*This notation is a parsing variant for the centralizer of an element within a given algebra, representing the set of all elements in the algebra that commute with the given element.*)\nNotation \"'C_ ( E ) [ x ]\" := (capv_aspace E 'C[x])\n (only parsing) : aspace_scope.\n(*This notation represents the centralizer of a subspace within a given algebra, which is the set of all elements in the algebra that commute with every element of the subspace.*)\nNotation \"'C_ E ( V )\" := (capv_aspace E 'C(V)) : aspace_scope.\n(*This notation is a parsing variant for the centralizer of a subspace within a given algebra, representing the set of all elements in the algebra that commute with every element of the subspace.*)\nNotation \"'C_ ( E ) ( V )\" := (capv_aspace E 'C(V))\n (only parsing) : aspace_scope.\n(*This notation represents the direct product of two algebraic subspaces, forming a new algebraic subspace whose elements are pairs of elements from the original subspaces.*)\nNotation \"E * F\" := (prodv_aspace E F) : aspace_scope.\n(*This notation represents the image of an algebraic subspace under an algebra homomorphism, which forms a new algebraic subspace.*)\nNotation \"f @: E\" := (aimg_aspace f E) : aspace_scope.\n\nArguments Fadjoin_idP {F0 L K x}.\nArguments FadjoinP {F0 L K x E}.\nArguments Fadjoin_seqP {F0 L K rs E}.\nArguments polyOver_subvs {F0 L K p}.\nArguments Fadjoin_polyP {F0 L K x v}.\nArguments Fadjoin1_polyP {F0 L x v}.\nArguments minPoly_XsubC {F0 L K x}.\n\nSection MapMinPoly.\n\nVariables (F0 : fieldType) (L rL : fieldExtType F0) (f : 'AHom(L, rL)).\nVariables (K : {subfield L}) (x : L).\n\n(*This lemma states that the degree of a field extension generated by adjoining an element to a base field is invariant under a field homomorphism. Specifically, the degree of the extension of a subfield by an element is equal to the degree of the extension of the homomorphic image of the subfield by the image of the element.*)\nLemma adjoin_degree_aimg : adjoin_degree (f @: K) (f x) = adjoin_degree K x.\n\n(*This lemma states that applying a field homomorphism to the coefficients of the minimal polynomial of an element over a subfield yields the minimal polynomial of the image of that element over the image of the subfield.*)\nLemma map_minPoly : map_poly f (minPoly K x) = minPoly (f @: K) (f x).\n\nEnd MapMinPoly.\n\nSection FieldOver.\n\nVariables (F0 : fieldType) (L : fieldExtType F0) (F : {subfield L}).\n\n(*This definition introduces a type that represents a field extension, but is viewed specifically as a vector space over one of its subfields. This allows for reasoning about the field's structure relative to a smaller base field.*)\nDefinition fieldOver of {vspace L} : Type := L.\n(*This local notation refers to the vector space structure implicitly defined by a subfield, allowing the subfield itself to be treated as a subspace of the larger field extension.*)\nLocal Notation K_F := (subvs_of F).\n(*This local notation refers to a field extension viewed as a vector space over one of its specified subfields.*)\nLocal Notation L_F := (fieldOver F).\n\nHB.instance Definition _ := GRing.Field.on L_F.\n\n(*This definition specifies the scalar multiplication operation for a field extension viewed as a vector space over one of its subfields. The operation multiplies an element of the extension field by a scalar from the subfield using the multiplication of the extension field.*)\nDefinition fieldOver_scale (a : K_F) (u : L_F) : L_F := vsval a * u.\nLocal Infix \"*F:\" := fieldOver_scale (at level 40).\n\n(*This fact establishes the associativity of scalar multiplication in a field extension viewed as a vector space. It states that scaling a vector by one scalar, and then scaling the result by another, is equivalent to scaling the original vector by the product of the two scalars.*)\nFact fieldOver_scaleA a b u : a *F: (b *F: u) = (a * b) *F: u.\n\n(*This fact establishes that scaling an element of a field extension by the multiplicative identity of the base subfield leaves the element unchanged.*)\nFact fieldOver_scale1 u : 1 *F: u = u.\n\n(*This fact establishes the distributivity of scalar multiplication over vector addition in a field extension viewed as a vector space. It states that scaling the sum of two vectors is equivalent to the sum of scaling each vector individually.*)\nFact fieldOver_scaleDr a u v : a *F: (u + v) = a *F: u + a *F: v.\n\n(*This fact establishes the distributivity of scalar multiplication over scalar addition in a field extension viewed as a vector space. It states that scaling a vector by the sum of two scalars is equivalent to the sum of scaling the vector by each scalar individually.*)\nFact fieldOver_scaleDl v a b : (a + b) *F: v = a *F: v + b *F: v.\n\nHB.instance Definition _ := GRing.Zmodule_isLmodule.Build _ L_F\n fieldOver_scaleA fieldOver_scale1 fieldOver_scaleDr fieldOver_scaleDl.\n\n(*This lemma confirms that the generic scalar multiplication on a field extension, when viewed as a module over a subfield, is equivalent to the multiplication within the larger field between the scalar from the subfield and the vector element.*)\nLemma fieldOver_scaleE a (u : L) : a *: (u : L_F) = vsval a * u.\n\n(*This fact establishes a compatibility property between scalar multiplication and the internal multiplication of the field extension. It states that scaling a product of two field elements is equivalent to first scaling one of the elements and then performing the product.*)\nFact fieldOver_scaleAl a u v : a *F: (u * v) = (a *F: u) * v.\n\nHB.instance Definition _ := GRing.Lmodule_isLalgebra.Build _ L_F\n fieldOver_scaleAl.\n\n(*This fact establishes a compatibility property between scalar multiplication and the internal multiplication of the field extension. It states that scaling a product of two field elements is equivalent to performing the product after scaling the second element.*)\nFact fieldOver_scaleAr a u v : a *F: (u * v) = u * (a *F: v).\n\nHB.instance Definition _ := GRing.Lalgebra_isAlgebra.Build _ L_F\n fieldOver_scaleAr.\n\n(*This fact provides the property that a field extension, when viewed as a module over a subfield, has a finite dimension.*)\nFact fieldOver_vectMixin : Lmodule_hasFinDim K_F L_F.\n\n(*This lemma states that the one-dimensional subspace spanned by the multiplicative identity of a field extension is isomorphic, as a vector space, to the base subfield over which it is defined.*)\nLemma trivial_fieldOver : (1%VS : {vspace L_F}) =i F.\n\n(*This definition creates a new vector space over a subfield from an existing vector space over a larger field extension. The new space is spanned by the same basis elements as the original space, but they are now considered vectors over the subfield.*)\nDefinition vspaceOver V := <>%VS.\n\n(*This lemma states that the vector space created by restricting the scalars of a given vector subspace to a subfield is isomorphic to the subspace spanned by the products of elements from the subfield and the original vector subspace.*)\nLemma mem_vspaceOver V : vspaceOver V =i (F * V)%VS.\n\n(*This lemma states that if a field is a sub-algebra of another field, then viewing the larger field as a vector space over the smaller field results in a vector space that is isomorphic to the larger field itself.*)\nLemma mem_aspaceOver E : (F <= E)%VS -> vspaceOver E =i E.\n\n(*This fact asserts that viewing a subfield as a vector space over a smaller base field results in a structure that is a valid algebraic subspace.*)\nFact aspaceOver_suproof E : is_aspace (vspaceOver E).\n\nCanonical aspaceOver E := ASpace (aspaceOver_suproof E).\n\n(*This lemma states that for a vector subspace that is also a module over a given subfield, the dimension of this subspace when viewed as a vector space over the subfield is equal to its dimension as a module over that same subfield.*)\nLemma dim_vspaceOver M : (F * M <= M)%VS -> \\dim (vspaceOver M) = \\dim_F M.\n\n(*This lemma states that for a field extension over a subfield, the dimension of the extension when viewed as a vector space over the subfield is equal to the degree of the field extension.*)\nLemma dim_aspaceOver E : (F <= E)%VS -> \\dim (vspaceOver E) = \\dim_F E.\n\n(*This lemma provides an existence principle, stating that for any given vector space over a subfield, there exists a corresponding vector space over the larger ambient field such that the original space can be recovered by restricting its scalars, and the two spaces are isomorphic.*)\nLemma vspaceOverP V_F :\n {V | [/\\ V_F = vspaceOver V, (F * V <= V)%VS & V_F =i V]}.\n\n(*This lemma provides an existence principle for algebraic subspaces, stating that for any given algebraic subspace over a subfield, there exists a corresponding algebraic subspace over the larger ambient field such that the original space can be recovered by restricting scalars, and the two spaces are isomorphic.*)\nLemma aspaceOverP (E_F : {subfield L_F}) :\n {E | [/\\ E_F = aspaceOver E, (F <= E)%VS & E_F =i E]}.\n\nEnd FieldOver.\n\nSection BaseField.\n\nVariables (F0 : fieldType) (F : fieldExtType F0) (L : fieldExtType F).\n\n(*This definition introduces a type alias for a field, typically used to designate it as the base field in the context of subsequent field extensions.*)\nDefinition baseFieldType : Type := L.\n(*This notation provides a short name for the type `L` when it is considered as a vector space over the base field `F0`.*)\nNotation L0 := baseFieldType.\n\nHB.instance Definition _ := GRing.Field.on L0.\n\n(*This definition specifies the external multiplication of an element of the vector space `L0` by a scalar from the base field `F0`.*)\nDefinition baseField_scale (a : F0) (u : L0) : L0 := in_alg F a *: u.\nLocal Infix \"*F0:\" := baseField_scale (at level 40).\n\n(*This fact states that scaling a vector by one scalar and then by another scalar is equivalent to scaling the vector by the product of the two scalars.*)\nFact baseField_scaleA a b u : a *F0: (b *F0: u) = (a * b) *F0: u.\n\n(*This fact asserts that scaling any vector by the multiplicative identity of the base field yields the vector itself.*)\nFact baseField_scale1 u : 1 *F0: u = u.\n\n(*This fact asserts that scalar multiplication distributes over vector addition; scaling the sum of two vectors is equivalent to the sum of the results of scaling each vector individually.*)\nFact baseField_scaleDr a u v : a *F0: (u + v) = a *F0: u + a *F0: v.\n\n(*This fact asserts that scalar multiplication distributes over scalar addition; scaling a vector by the sum of two scalars is equivalent to the sum of the results of scaling the vector by each scalar individually.*)\nFact baseField_scaleDl v a b : (a + b) *F0: v = a *F0: v + b *F0: v.\n\nHB.instance Definition _ := GRing.Zmodule_isLmodule.Build _ L0\n baseField_scaleA baseField_scale1 baseField_scaleDr baseField_scaleDl.\n\n(*This lemma states that scaling a vector from the field extension `L` by a scalar from the base field `F0` is equivalent to first coercing the scalar into the intermediate field `F` and then applying the native scaling operation of the algebra `L` over `F`.*)\nLemma baseField_scaleE a (u : L) : a *: (u : L0) = a%:A *: u.\n\n(*This fact demonstrates a compatibility property between scalar multiplication and the internal multiplication of the vector space. It states that scaling a product of two vectors is equivalent to scaling the first vector and then multiplying the result by the second vector.*)\nFact baseField_scaleAl a (u v : L0) : a *F0: (u * v) = (a *F0: u) * v.\n\nHB.instance Definition _ := GRing.Lmodule_isLalgebra.Build _ L0\n baseField_scaleAl.\n\n(*This fact demonstrates a compatibility property between scalar multiplication and the internal multiplication of the vector space. It states that scaling a product of two vectors is equivalent to multiplying the first vector by the result of scaling the second vector.*)\nFact baseField_scaleAr a u v : a *F0: (u * v) = u * (a *F0: v).\n\nHB.instance Definition _ := GRing.Lalgebra_isAlgebra.Build _ L0\n baseField_scaleAr.\n\n(*This definition sets `n` as the dimension of the field extension, which is a natural number representing the size of a basis for the extension when viewed as a vector space over its base field.*)\nLet n := \\dim {:F}.\n(*This definition provides a canonical basis for the field extension, represented as a finite sequence of elements from the extension field. The length of this sequence is equal to the dimension of the extension.*)\nLet bF : n.-tuple F := vbasis {:F}.\n(*This function takes an element from the field extension and returns its coordinates with respect to the canonical basis. The result is a finite sequence of scalars from the base field, corresponding to the coefficients of the basis elements in the unique linear combination that expresses the input element.*)\nLet coordF (x : F) := (coord_vbasis (memvf x)).\n\n(*This fact establishes that the field extension `L`, when viewed as a module over the base field `F0`, has a finite dimension.*)\nFact baseField_vectMixin : Lmodule_hasFinDim F0 L0.\n\n(*This lemma expresses an associativity property for nested scalar multiplications in a tower of fields. It shows that scaling a vector from `L` by a scalar from `F`, and then scaling the result by a scalar from `F0`, is equivalent to scaling the original vector by the product of the two scalars.*)\nLet F0ZEZ a x v : a *: ((x *: v : L) : L0) = (a *: x) *: v.\n\n(*This definition constructs a basis for a vector space `V` over field `F` when it is reinterpreted as a vector space over the base field `F0`. The new basis is formed by the set of all scalar products of basis elements from `V` over `F` with basis elements from `F` over `F0`.*)\nLet baseVspace_basis V : seq L0 :=\n [seq tnth bF ij.2 *: tnth (vbasis V) ij.1 | ij : 'I_(\\dim V) * 'I_n].\n(*This definition constructs a new vector space over the base field `F0` from a given vector space `V` over the field `F`. This new space is defined as the vector subspace spanned by a basis derived from the bases of `V` and `F`.*)\nDefinition baseVspace V := <>%VS.\n\n(*This lemma states that the vector space created by `baseVspace` over the base field has the same set of elements as the original vector space `V`.*)\nLemma mem_baseVspace V : baseVspace V =i V.\n\n(*This lemma, known as the tower law, states that the dimension of the vector space `baseVspace V` over the base field is equal to the product of the dimension of the original space `V` over `F` and the dimension of `F` over the base field.*)\nLemma dim_baseVspace V : \\dim (baseVspace V) = (\\dim V * n)%N.\n\n(*This fact asserts that for any subfield `E` of `L`, the vector space constructed as `baseVspace E` also has the structure of an affine space.*)\nFact baseAspace_suproof (E : {subfield L}) : is_aspace (baseVspace E).\n\nCanonical baseAspace E := ASpace (baseAspace_suproof E).\n\nEnd BaseField.\n\nArguments baseFieldType [F0 F]%_type L%_type.\n\n(*This definition creates a canonical affine space over the base field `F0` derived from a tower of field extensions `L` over `F` over `F0`. It is constructed by taking the unit affine space of `L` and transforming it into an affine space over `F0`.*)\nHB.lock Definition refBaseField (F0 : fieldType) (F : fieldExtType F0)\n (L : fieldExtType F) := baseAspace (1%AS : {aspace L}).\nCanonical refBaseField_unlockable := Unlockable refBaseField.unlock.\n\nSection RefBaseField.\n\nVariables (F0 : fieldType) (F : fieldExtType F0) (L : fieldExtType F).\n\n(*This notation provides a short alias `F1` for the canonical affine space `refBaseField L` derived from the field extension `L`.*)\nNotation F1 := (refBaseField L).\n(*This notation defines an alias for a constant used to unfold the definition of `refBaseField` within proofs.*)\nNotation F1unlock := refBaseField.unlock.\n(*A parameter representing a field that serves as an ambient structure for constructing subfields and modules within the current section.*)\nNotation L0 := (baseFieldType L).\n\n(*This definition specifies a natural number that represents the dimension of a field, considered as a vector space over its reference base field.*)\nLet n := \\dim {:F}.\n(*This definition provides a canonical basis for a field, viewed as a vector space, represented as a finite sequence of field elements.*)\nLet bF : n.-tuple F := vbasis {:F}.\n(*This function calculates the coordinates of a given field element with respect to the canonical basis of the field, returning a finite sequence of scalars.*)\nLet coordF (x : F) := (coord_vbasis (memvf x)).\n\n(*This lemma asserts that the dimension of a subfield, viewed as a vector space over its reference base field, is equal to a predefined natural number.*)\nLemma dim_refBaseField : \\dim F1 = n.\n\n(*This lemma states that the underlying vector space of any vector space over a field extension is closed under scalar multiplication by a specific subfield.*)\nLemma baseVspace_module V (V0 := baseVspace V) : (F1 * V0 <= V0)%VS.\n\n(*This lemma asserts that a given subfield is a vector subspace of the vector space structure underlying another subfield.*)\nLemma sub_baseField (E : {subfield L}) : (F1 <= baseVspace E)%VS.\n\n(*This lemma states that restricting the scalars of a vector space to a subfield results in a new vector space that is canonically isomorphic to the original one.*)\nLemma vspaceOver_refBase V : vspaceOver F1 (baseVspace V) =i V.\n\n(*This lemma establishes that a module closed under scalar multiplication by a subfield can be canonically endowed with a full vector space structure over that subfield.*)\nLemma module_baseVspace M0 :\n (F1 * M0 <= M0)%VS -> {V | M0 = baseVspace V & M0 =i V}.\n\n(*This lemma states that a subfield which is also a vector space over another subfield can be canonically endowed with a field extension structure.*)\nLemma module_baseAspace (E0 : {subfield L0}) :\n (F1 <= E0)%VS -> {E | E0 = baseAspace E & E0 =i E}.\n\nEnd RefBaseField.\n\nSection MoreFieldOver.\n\nVariables (F0 : fieldType) (L : fieldExtType F0) (F : {subfield L}).\n\n(*This lemma states that the underlying vector space obtained by restricting the scalars of a given vector space to a subfield is canonically isomorphic to the subspace spanned by multiplying the original vector space by elements of that subfield.*)\nLemma base_vspaceOver V : baseVspace (vspaceOver F V) =i (F * V)%VS.\n\n(*This lemma states that if a vector space is already closed under scalar multiplication by a subfield, then restricting its scalars to that subfield yields a new vector space whose underlying vector space is canonically isomorphic to the original one.*)\nLemma base_moduleOver V : (F * V <= V)%VS -> baseVspace (vspaceOver F V) =i V.\n\n(*This lemma states that if a subfield contains another subfield as a vector subspace, then restricting its scalars to the smaller subfield yields a vector space structure whose underlying vector space is canonically isomorphic to the original subfield itself.*)\nLemma base_aspaceOver (E : {subfield L}) :\n (F <= E)%VS -> baseVspace (vspaceOver F E) =i E.\n\nEnd MoreFieldOver.\n\nSection SubFieldExtension.\n\nLocal Open Scope quotient_scope.\n\nVariables (F L : fieldType) (iota : {rmorphism F -> L}).\nVariables (z : L) (p : {poly F}).\n\n(*This notation represents the polynomial that results from applying a given ring morphism to each coefficient of an input polynomial.*)\nLocal Notation \"p ^iota\" := (map_poly (GRing.RMorphism.sort iota) p)\n (at level 2, format \"p ^iota\") : ring_scope.\n\n(*This definition assigns a boolean value indicating whether a given polynomial is non-zero and whether a given field element is a root of this polynomial after its coefficients have been transformed by a ring morphism.*)\nLet wf_p := (p != 0) && root p^iota z.\n(*This definition creates a polynomial that is either the monic polynomial corresponding to a given polynomial, if that polynomial is non-zero and has a specific root after transformation, or the indeterminate polynomial 'X' otherwise.*)\nLet p0 : {poly F} := if wf_p then (lead_coef p)^-1 *: p else 'X.\n(*This definition yields a field element that is either a specific root element of a transformed polynomial or the zero element of the field, depending on whether the polynomial is non-zero and has that root.*)\nLet z0 := if wf_p then z else 0.\n(*This symbol represents a natural number, typically used as a dimension for vectors or an upper bound for polynomial degrees.*)\nLet n := (size p0).-1.\n\n(*This lemma asserts that a specific polynomial, used for modular arithmetic, is monic, meaning its leading coefficient is one.*)\nLet p0_mon : p0 \\is monic.\n\n(*This lemma asserts that a specific polynomial, which is used for modular arithmetic, is not the zero polynomial.*)\nLet nz_p0 : p0 != 0. \n\n(*This lemma asserts that a specific element is a root of a given polynomial when evaluated via a specific ring morphism.*)\nLet p0z0 : root p0^iota z0.\n\n(*This lemma asserts that a natural number, used as a dimension or bound, is strictly greater than zero.*)\nLet n_gt0: 0 < n.\n\n(*This definition constructs a commutative ring morphism that evaluates a polynomial by substituting a specific element for its variable.*)\nLet z0Ciota : commr_rmorph iota z0. \n(*This notation refers to a morphism derived from Horner's method, which efficiently evaluates a polynomial at a specific value.*)\nLocal Notation iotaPz := (horner_morph z0Ciota).\n(*This definition specifies a function that converts a row vector into a polynomial and then evaluates that polynomial at a pre-determined value.*)\nLet iotaFz (x : 'rV[F]_n) := iotaPz (rVpoly x).\n\n(*This definition introduces an equivalence relation on row vectors, where two vectors are considered equivalent if they produce the same result when converted to polynomials and evaluated at a specific value.*)\nDefinition equiv_subfext x y := (iotaFz x == iotaFz y).\n\n(*This fact asserts that the relation comparing the evaluation of polynomial representations of vectors is an equivalence relation, meaning it is reflexive, symmetric, and transitive.*)\nFact equiv_subfext_is_equiv : equiv_class_of equiv_subfext.\n\nCanonical equiv_subfext_equiv := EquivRelPack equiv_subfext_is_equiv.\nCanonical equiv_subfext_encModRel := defaultEncModRel equiv_subfext.\n\n(*This definition introduces a new type constructed as the set of equivalence classes of row vectors under a specific evaluation-based equivalence relation.*)\nDefinition subFExtend := {eq_quot equiv_subfext}.\n\nHB.instance Definition _ := Choice.on subFExtend.\nHB.instance Definition _ := Quotient.on subFExtend.\nHB.instance Definition _ : EqQuotient 'M[F]_(1, n) equiv_subfext subFExtend :=\n EqQuotient.on subFExtend.\n\n(*This definition specifies a function that maps an element from a quotient type to its corresponding value in the target ring, effectively representing the result of the evaluation that defines the equivalence classes.*)\nDefinition subfx_inj := lift_fun1 subFExtend iotaFz.\n\n(*This fact asserts that the canonical projection from the type of row vectors to the quotient type behaves as a monomorphism, meaning that applying the lifted injection to the equivalence class of a vector yields the same result as evaluating the vector's polynomial representation directly.*)\nFact pi_subfx_inj : {mono \\pi : x / iotaFz x >-> subfx_inj x}.\n\nCanonical pi_subfx_inj_morph := PiMono1 pi_subfx_inj.\n\n(*This lemma states that applying the polynomial evaluation morphism to the polynomial derived from a canonical representative vector of a quotient element is equivalent to applying the lifted injective function to the quotient element itself.*)\nLet iotaPz_repr x : iotaPz (rVpoly (repr (\\pi_(subFExtend) x))) = iotaFz x.\n\n(*This definition specifies the zero element in the quotient type, defined as the equivalence class containing the zero row vector.*)\nDefinition subfext0 := lift_cst subFExtend 0.\nCanonical subfext0_morph := PiConst subfext0.\n\n(*This definition specifies the addition operation on the quotient type, which is lifted from the component-wise addition of the underlying row vectors.*)\nDefinition subfext_add := lift_op2 subFExtend +%R.\n(*This fact asserts that the canonical projection to the quotient type is a morphism with respect to addition, meaning the sum of the projections of two vectors is the projection of their sum.*)\nFact pi_subfext_add : {morph \\pi : x y / x + y >-> subfext_add x y}.\n\nCanonical pi_subfx_add_morph := PiMorph2 pi_subfext_add.\n\n(*This definition specifies the additive inverse operation on the quotient type, which is lifted from the component-wise negation of the underlying row vectors.*)\nDefinition subfext_opp := lift_op1 subFExtend -%R.\n(*This fact asserts that the canonical projection to the quotient type is a morphism with respect to the additive inverse, meaning the inverse of a projected vector is the projection of its inverse.*)\nFact pi_subfext_opp : {morph \\pi : x / - x >-> subfext_opp x}.\n\nCanonical pi_subfext_opp_morph := PiMorph1 pi_subfext_opp.\n\n(*This fact asserts that the addition operation defined on the quotient type is associative.*)\nFact addfxA : associative subfext_add.\n\n(*This fact asserts that the addition operation defined on the quotient type is commutative.*)\nFact addfxC : commutative subfext_add.\n\n(*This fact asserts that the defined zero element is the left identity for the addition operation on the quotient type.*)\nFact add0fx : left_id subfext0 subfext_add.\n\n(*This fact asserts that the defined additive inverse operation provides a left inverse for every element with respect to the addition on the quotient type.*)\nFact addfxN : left_inverse subfext0 subfext_opp subfext_add.\n\nHB.instance Definition _ := GRing.isZmodule.Build subFExtend\n addfxA addfxC add0fx addfxN.\n\n(*This lemma states that converting a polynomial modulo another polynomial into a row vector and then back to a polynomial yields the original polynomial modulo the second polynomial.*)\nLet poly_rV_modp_K q : rVpoly (poly_rV (q %% p0) : 'rV[F]_n) = q %% p0.\n\n(*This lemma states that evaluating a polynomial at a specific value yields the same result as evaluating its remainder after division by another polynomial that has that specific value as a root.*)\nLet iotaPz_modp q : iotaPz (q %% p0) = iotaPz q.\n\n(*This definition specifies the multiplication of two row vectors by first converting them to polynomials, multiplying these polynomials, reducing the product modulo a fixed polynomial, and finally converting the result back to a row vector.*)\nDefinition subfx_mul_rep (x y : 'rV[F]_n) : 'rV[F]_n :=\n poly_rV ((rVpoly x) * (rVpoly y) %% p0).\n\n(*This definition specifies the multiplication operation on the quotient type, which is lifted from the representative multiplication operation defined on the underlying row vectors.*)\nDefinition subfext_mul := lift_op2 subFExtend subfx_mul_rep.\n(*This fact asserts that the canonical projection to the quotient type is a morphism with respect to multiplication, meaning the product of the projections of two vectors is the projection of their representative product.*)\nFact pi_subfext_mul :\n {morph \\pi : x y / subfx_mul_rep x y >-> subfext_mul x y}.\n\nCanonical pi_subfext_mul_morph := PiMorph2 pi_subfext_mul.\n\n(*This definition specifies the multiplicative identity element in the quotient type, defined as the equivalence class of the row vector corresponding to the constant polynomial one.*)\nDefinition subfext1 := lift_cst subFExtend (poly_rV 1).\nCanonical subfext1_morph := PiConst subfext1.\n\n(*This fact asserts that the multiplication operation defined on the quotient type is associative.*)\nFact mulfxA : associative (subfext_mul).\n\n(*This fact states that multiplication in a finite field extension is commutative.*)\nFact mulfxC : commutative subfext_mul.\n\n(*This fact asserts that the multiplicative identity element acts as a left identity for multiplication in a finite field extension.*)\nFact mul1fx : left_id subfext1 subfext_mul.\n\n(*This fact states that multiplication left-distributes over addition in a finite field extension.*)\nFact mulfx_addl : left_distributive subfext_mul subfext_add.\n\n(*This fact asserts that the multiplicative identity and the additive identity in a finite field extension are distinct elements.*)\nFact nonzero1fx : subfext1 != subfext0.\n\nHB.instance Definition _ := GRing.Zmodule_isComNzRing.Build subFExtend\n mulfxA mulfxC mul1fx mulfx_addl nonzero1fx.\n\n(*This definition describes a function to compute the multiplicative inverse of a polynomial with respect to a modulus, typically used for arithmetic in a quotient ring of polynomials.*)\nDefinition subfx_poly_inv (q : {poly F}) : {poly F} :=\n if iotaPz q == 0 then 0 else\n let r := gdcop q p0 in let: (u, v) := egcdp q r in\n ((u * q + v * r)`_0)^-1 *: u.\n\n(*This lemma states that the constant term of the polynomial inverse is equal to the inverse of the constant term of the original polynomial.*)\nLet subfx_poly_invE q : iotaPz (subfx_poly_inv q) = (iotaPz q)^-1.\n\n(*This definition provides a representative of the multiplicative inverse for an element of a finite field extension, which is represented as a vector. The computation involves converting the vector to a polynomial, finding its inverse, reducing it by a modulus, and converting it back to a vector.*)\nDefinition subfx_inv_rep (x : 'rV[F]_n) : 'rV[F]_n :=\n poly_rV (subfx_poly_inv (rVpoly x) %% p0).\n\n(*This definition introduces the multiplicative inverse operation for elements of a finite field extension, which is lifted from an operation on their underlying vector representatives.*)\nDefinition subfext_inv := lift_op1 subFExtend subfx_inv_rep.\n(*This canonical fact establishes that the projection from a vector representation to an element of a finite field extension is a morphism with respect to the multiplicative inverse operation.*)\nFact pi_subfext_inv : {morph \\pi : x / subfx_inv_rep x >-> subfext_inv x}.\n\nCanonical pi_subfext_inv_morph := PiMorph1 pi_subfext_inv.\n\n(*This fact establishes the field axiom for a finite field extension, stating that any non-zero element multiplied by its inverse yields the multiplicative identity.*)\nFact subfx_fieldAxiom : forall x, x != 0 -> subfext_inv x * x = 1.\n\n(*This fact states that the multiplicative inverse of the zero element in a finite field extension is the zero element itself.*)\nFact subfx_inv0 : subfext_inv (0 : subFExtend) = (0 : subFExtend).\n\nHB.instance Definition _ := GRing.ComNzRing_isField.Build subFExtend\n subfx_fieldAxiom subfx_inv0.\n\n(*This fact asserts that the canonical injection from a base field into its finite field extension is a module morphism, meaning it preserves addition and the zero element.*)\nFact subfx_inj_is_zmod_morphism : zmod_morphism subfx_inj.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `subfx_inj_is_zmod_morphism` instead\")]\n(*This definition is a deprecated alias for the property that the canonical injection into a finite field extension is a module morphism; use `subfx_inj_is_zmod_morphism` instead.*)\nDefinition subfx_inj_is_additive := subfx_inj_is_zmod_morphism.\n\n(*This fact asserts that the canonical injection from a base field into its finite field extension is a monoid morphism, meaning it preserves multiplication and the multiplicative identity.*)\nFact subfx_inj_is_monoid_morphism : monoid_morphism subfx_inj.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `subfx_inj_is_monoid_morphism` instead\")]\n(*This definition is a deprecated alias for the property that the canonical injection into a finite field extension is a monoid morphism; use `subfx_inj_is_monoid_morphism` instead.*)\nDefinition subfx_inj_is_multiplicative :=\n (fun g => (g.2,g.1)) subfx_inj_is_monoid_morphism.\nHB.instance Definition _ := GRing.isZmodMorphism.Build subFExtend L subfx_inj\n subfx_inj_is_zmod_morphism.\nHB.instance Definition _ := GRing.isMonoidMorphism.Build subFExtend L subfx_inj\n subfx_inj_is_monoid_morphism.\n\n(*This definition introduces the evaluation map from a polynomial ring to a finite field extension, which is defined by reducing a polynomial modulo a fixed irreducible polynomial.*)\nDefinition subfx_eval := lift_embed subFExtend (fun q => poly_rV (q %% p0)).\nCanonical subfx_eval_morph := PiEmbed subfx_eval.\n\n(*This definition identifies a root of the defining irreducible polynomial within the finite field extension, obtained by applying the evaluation map to the indeterminate polynomial.*)\nDefinition subfx_root := subfx_eval 'X.\n\n(*This lemma states that the evaluation map from a polynomial ring to a finite field extension is a module morphism, preserving addition and the zero element.*)\nLemma subfx_eval_is_zmod_morphism : zmod_morphism subfx_eval.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `subfx_eval_is_zmod_morphism` instead\")]\n(*This definition is a deprecated alias for the property that the polynomial evaluation map is a module morphism; use `subfx_eval_is_zmod_morphism` instead.*)\nDefinition subfx_eval_is_additive := subfx_eval_is_zmod_morphism.\n\n(*This lemma states that the evaluation map from a polynomial ring to a finite field extension is a monoid morphism, preserving multiplication and the multiplicative identity.*)\nLemma subfx_eval_is_monoid_morphism : monoid_morphism subfx_eval.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `subfx_eval_is_monoid_morphism` instead\")]\n(*This definition is a deprecated alias for the property that the polynomial evaluation map is a monoid morphism; use `subfx_eval_is_monoid_morphism` instead.*)\nDefinition subfx_eval_is_multiplicative :=\n (fun g => (g.2,g.1)) subfx_eval_is_monoid_morphism.\nHB.instance Definition _ :=\n GRing.isZmodMorphism.Build {poly F} subFExtend subfx_eval subfx_eval_is_zmod_morphism.\nHB.instance Definition _ :=\n GRing.isMonoidMorphism.Build {poly F} subFExtend subfx_eval\n subfx_eval_is_monoid_morphism.\n\n(*This definition provides the canonical injection map from a base field into its finite field extension, constructed by composing the map that creates constant polynomials with the polynomial evaluation map.*)\nDefinition inj_subfx := (subfx_eval \\o polyC).\nHB.instance Definition _ := GRing.RMorphism.on inj_subfx.\n\n(*This lemma asserts that the polynomial evaluation map is surjective, meaning every element in a finite field extension is the image of some polynomial.*)\nLemma subfxE x: exists p, x = subfx_eval p.\n\n(*This definition specifies scalar multiplication of an element in a finite field extension by a scalar from the base field, which is achieved by injecting the scalar into the extension and then performing multiplication.*)\nDefinition subfx_scale a x := inj_subfx a * x.\n(*This fact asserts the associativity of scalar multiplication, stating that scaling an element consecutively by two scalars is equivalent to scaling it once by their product.*)\nFact subfx_scalerA a b x :\n subfx_scale a (subfx_scale b x) = subfx_scale (a * b) x.\n\n(*This fact states that scaling an element of a finite field extension by the multiplicative identity of the base field results in the original element.*)\nFact subfx_scaler1r : left_id 1 subfx_scale.\n\n(*This fact establishes the right distributivity of scalar multiplication over addition in a finite field extension, meaning scaling a sum of two elements is the same as summing the scaled elements.*)\nFact subfx_scalerDr : right_distributive subfx_scale +%R.\n\n(*This fact establishes the left distributivity of scalar multiplication over addition of scalars, meaning scaling an element by a sum of two scalars is the same as summing the results of scaling by each scalar individually.*)\nFact subfx_scalerDl x : {morph subfx_scale^~ x : a b / a + b}.\n\nHB.instance Definition _ := GRing.Zmodule_isLmodule.Build _ subFExtend\n subfx_scalerA subfx_scaler1r subfx_scalerDr subfx_scalerDl.\n\n(*This fact asserts an algebra compatibility property, stating that scaling a product of two extension field elements is equivalent to scaling the first element and then multiplying by the second.*)\nFact subfx_scaleAl a u v : subfx_scale a (u * v) = (subfx_scale a u) * v.\n\nHB.instance Definition _ := GRing.Lmodule_isLalgebra.Build _ subFExtend\n subfx_scaleAl.\n\n(*This fact asserts an algebra compatibility property, stating that scaling a product of two extension field elements is equivalent to multiplying the first element by the scaled version of the second.*)\nFact subfx_scaleAr a u v : subfx_scale a (u * v) = u * (subfx_scale a v).\n\nHB.instance Definition _ := GRing.Lalgebra_isAlgebra.Build _ subFExtend\n subfx_scaleAr.\n\n(*This fact asserts that the polynomial evaluation function for the subfield extension is scalable over the integers, meaning that scaling a polynomial by an integer before evaluation yields the same result as scaling the evaluated element by that same integer.*)\nFact subfx_evalZ : scalable subfx_eval.\n\n(*This lemma states that for any given polynomial, injecting its evaluated value from the subfield extension into the containing field is equivalent to evaluating a corresponding polynomial at the adjoined root, where the coefficients of the corresponding polynomial are the canonical images of the original polynomial's coefficients.*)\nLemma subfx_inj_eval q : subfx_inj (subfx_eval q) = q^iota.[z].\n\n(*This lemma states that the canonical injection of the abstract root element from the subfield extension algebra maps to the concrete adjoined root element in the containing field.*)\nLemma subfx_inj_root : subfx_inj subfx_root = z.\n\n(*This lemma states that the canonical injection from the subfield extension preserves scalar multiplication; injecting an element that has been scaled by a scalar is equivalent to scaling the injected element by the canonical image of that scalar.*)\nLemma subfx_injZ b x : subfx_inj (b *: x) = iota b * subfx_inj x.\n\n(*This lemma states that injecting a base field element that has been embedded into the subfield extension algebra is equivalent to applying the canonical field morphism to that original base field element.*)\nLemma subfx_inj_base b : subfx_inj b%:A = iota b.\n\n(*This lemma asserts that every element of the subfield extension can be represented as the evaluation of some polynomial from the base field at the canonical adjoined root.*)\nLemma subfxEroot x : {q | x = (map_poly (in_alg subFExtend) q).[subfx_root]}.\n\n(*This lemma provides a criterion for irreducibility, stating that a polynomial is irreducible if and only if its degree is minimal among all non-zero polynomials that also have the adjoined element as a root, after a canonical mapping of coefficients.*)\nLemma subfx_irreducibleP :\n (forall q, root q^iota z -> q != 0 -> size p <= size q) <-> irreducible_poly p.\n\nEnd NonZero.\n\nSection Irreducible.\n\nHypothesis irr_p : irreducible_poly p.\n(*This hypothesis assumes that the defining polynomial for the field extension is not the zero polynomial.*)\nLet nz_p : p != 0. \n\n(*This lemma states that the sequence of powers of the canonical adjoined root, from degree zero up to one less than the degree of the defining polynomial, constitutes a basis for the field extension viewed as a vector space over the base field.*)\nLemma min_subfx_vect : Vector.axiom (size p).-1 subFExtend.\n\n(*This definition constructs the structure that formalizes the subfield extension as a finite-dimensional vector space over the base field, by combining its module properties with a proof of finite dimension.*)\nDefinition SubfxVect := Lmodule_hasFinDim.Build _ subFExtend min_subfx_vect.\n(*This definition combines the algebraic structure of the subfield extension with its finite-dimensional vector space properties to create the canonical type for a field extension.*)\nDefinition SubFieldExtType : fieldExtType F := HB.pack subFExtend SubfxVect.\n\nEnd Irreducible.\n\nEnd SubFieldExtension.\n\nPrenex Implicits subfx_inj.\n\n(*This definition provides the canonical field structure for the algebraic extension constructed by adjoining a root of a given irreducible polynomial to the base field.*)\nLemma irredp_FAdjoin (F : fieldType) (p : {poly F}) :\n irreducible_poly p ->\n {L : fieldExtType F & \\dim {:L} = (size p).-1 &\n {z | root (map_poly (in_alg L) p) z & <<1; z>>%VS = fullv}}.", - "field.falgebra": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path.\nFrom mathcomp Require Import choice fintype div tuple finfun bigop ssralg.\nFrom mathcomp Require Import finalg zmodp matrix vector poly.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope aspace_scope.\nDeclare Scope lrfun_scope.\n\nLocal Open Scope ring_scope.\n\nReserved Notation \"{ 'aspace' T }\" (format \"{ 'aspace' T }\").\nReserved Notation \"<< U & vs >>\" (format \"<< U & vs >>\").\nReserved Notation \"<< U ; x >>\" (format \"<< U ; x >>\").\nReserved Notation \"''AHom' ( T , rT )\" (format \"''AHom' ( T , rT )\").\nReserved Notation \"''AEnd' ( T )\" (format \"''AEnd' ( T )\").\n\n(*This notation defines the relative dimension of a vector space V over a vector space E as the quotient of the dimension of V divided by the dimension of E.*)\nNotation \"\\dim_ E V\" := (divn (\\dim V) (\\dim E))\n (at level 10, E at level 2, V at level 8, format \"\\dim_ E V\") : nat_scope.\n\nImport GRing.Theory.\n\n#[short(type=\"falgType\")]\n(*This definition introduces a structure for a finite-dimensional algebra, which is a type that is both a finite-dimensional vector space and a unital algebra over a given non-zero ring.*)\nHB.structure Definition Falgebra (R : nzRingType) :=\n { A of Vector R A & GRing.UnitAlgebra R A }.\n#[deprecated(since=\"mathcomp 2.0.0\", note=\"Use falgType instead.\")]\n(*This is a type for finite-dimensional algebras over a non-zero ring.*)\nNotation FalgType := falgType.\n\n(*This factory constructs an instance of a finite-dimensional algebra from a type that is already equipped with both a finite-dimensional vector space structure and a unital algebra structure over the same field.*)\nHB.factory Record Algebra_isFalgebra (K : fieldType) A\n of Vector K A & GRing.Algebra K A := {}.\n\nHB.builders Context K A of Algebra_isFalgebra K A.\n(*This definition provides an internal alias for the underlying type of the algebra, viewed as a vector space over a field.*)\n Let vA : Vector.type K := A.\n(*This definition creates a linear map corresponding to the operation of right multiplication by a given element of the algebra.*)\n Let am u := linfun (u \\o* idfun : vA -> vA).\n(*This predicate identifies the elements of the algebra for which the linear map corresponding to right multiplication by that element has a trivial kernel, meaning the map is injective.*)\n Let uam := [pred u | lker (am u) == 0%VS].\n(*This function computes the right multiplicative inverse of a given element if the linear map for right multiplication by that element is injective; otherwise, it returns the element itself.*)\n Let vam := [fun u => if u \\in uam then (am u)^-1%VF 1 else u].\n\n(*This lemma states that applying the linear map created from an element of the algebra to another element is equivalent to performing a right multiplication of the second element by the first.*)\n Lemma amE u v : am u v = v * u. \n\n(*This lemma states that for any element for which right multiplication is injective, multiplying the result of the `vam` function on the right by the original element yields the multiplicative identity.*)\n Lemma mulVr : {in uam, left_inverse 1 vam *%R}.\n \n\n(*This lemma states that for any element for which right multiplication is injective, multiplying the original element on the right by the result of the `vam` function yields the multiplicative identity.*)\n Lemma divrr : {in uam, right_inverse 1 vam *%R}.\n \n\n(*This lemma states that if an element has a two-sided multiplicative inverse, then the linear map corresponding to right multiplication by that element is injective.*)\n Lemma unitrP : forall x y, y * x = 1 /\\ x * y = 1 -> uam x.\n \n\n(*This lemma states that for any element for which the right multiplication map is not injective, the `vam` function acts as the identity, returning the element itself.*)\n Lemma invr_out : {in [predC uam], vam =1 id}.\n \n\n HB.instance Definition _ := GRing.NzRing_hasMulInverse.Build A\n mulVr divrr unitrP invr_out.\nHB.end.\n\nModule FalgebraExports.\nBind Scope ring_scope with sort.\nEnd FalgebraExports.\nHB.export FalgebraExports.\n\n(*This notation defines the symbol `1` within the vector space scope to represent the constant vector corresponding to the multiplicative identity of the underlying ring.*)\nNotation \"1\" := (vline 1) : vspace_scope.\n\nHB.instance Definition _ (K : fieldType) n :=\n Algebra_isFalgebra.Build K 'M[K]_n.+1.\n\n(*This lemma states that the entire vector space corresponding to the dual of a field is equivalent to the subspace spanned by the multiplicative identity element.*)\nLemma regular_fullv (K : fieldType) : (fullv = 1 :> {vspace K^o})%VS.\n\nSection Proper.\n\nVariables (R : nzRingType) (aT : falgType R).\n\nImport VectorInternalTheory.\n\n(*This lemma states that the dimension of any finite-dimensional algebra is greater than zero.*)\nLemma FalgType_proper : dim aT > 0.\n\nEnd Proper.\n\nModule FalgLfun.\n\nSection FalgLfun.\n\nVariable (R : comNzRingType) (aT : falgType R).\nImplicit Types f g : 'End(aT).\n\n(*This lemma states that applying the product of two endomorphisms to an element is equivalent to applying the first endomorphism and then applying the second endomorphism to the result.*)\nLemma lfun_mulE f g u : (f * g) u = g (f u). \n(*This lemma states that the composition of a second endomorphism with a first endomorphism is equal to the multiplicative product of the first endomorphism and the second endomorphism.*)\nLemma lfun_compE f g : (g \\o f)%VF = f * g. \n\nEnd FalgLfun.\n\nSection InvLfun.\n\nVariable (K : fieldType) (aT : falgType K).\nImplicit Types f g : 'End(aT).\n\n(*This definition provides an inverse for an endomorphism if it is injective, meaning it has a trivial kernel; otherwise, it returns the original endomorphism.*)\nDefinition lfun_invr f := if lker f == 0%VS then f^-1%VF else f.\n\n(*This lemma states that for any injective endomorphism, the product of its linear inverse and the endomorphism itself equals the identity endomorphism.*)\nLemma lfun_mulVr f : lker f == 0%VS -> f^-1%VF * f = 1.\n\n(*This lemma states that for any injective endomorphism, the product of the endomorphism and its linear inverse equals the identity endomorphism.*)\nLemma lfun_mulrV f : lker f == 0%VS -> f * f^-1%VF = 1.\n\n(*This fact asserts that for any injective endomorphism, the product of the result of the `lfun_invr` function and the endomorphism itself is the identity endomorphism.*)\nFact lfun_mulRVr f : lker f == 0%VS -> lfun_invr f * f = 1.\n\n(*This fact asserts that for any injective endomorphism, the product of the endomorphism and the result of the `lfun_invr` function is the identity endomorphism.*)\nFact lfun_mulrRV f : lker f == 0%VS -> f * lfun_invr f = 1.\n\n(*This fact asserts that if an endomorphism has a two-sided multiplicative inverse, then its kernel must be trivial.*)\nFact lfun_unitrP f g : g * f = 1 /\\ f * g = 1 -> lker f == 0%VS.\n\n(*This lemma states that if an endomorphism has a non-trivial kernel, the `lfun_invr` function returns the endomorphism unchanged.*)\nLemma lfun_invr_out f : lker f != 0%VS -> lfun_invr f = f.\n\n(*This lemma states that for an injective endomorphism, its inverse as a linear map is equal to its multiplicative inverse within the ring of endomorphisms.*)\nLemma lfun_invE f : lker f == 0%VS -> f^-1%VF = f^-1.\n\nEnd InvLfun.\n\nEnd FalgLfun.\n\nSection FalgebraTheory.\n\nVariables (K : fieldType) (aT : falgType K).\nImplicit Types (u v : aT) (U V W : {vspace aT}).\n\nImport FalgLfun.\n\n(*This definition creates an endomorphism corresponding to the operation of left multiplication by a given element of the algebra.*)\nDefinition amull u : 'End(aT) := linfun (u \\*o @idfun aT).\n(*This definition creates an endomorphism corresponding to the operation of right multiplication by a given element of the algebra.*)\nDefinition amulr u : 'End(aT) := linfun (u \\o* @idfun aT).\n\n(*This lemma states that the function mapping an algebra element to its corresponding left multiplication endomorphism is injective.*)\nLemma amull_inj : injective amull.\n\n(*This lemma states that the function mapping an algebra element to its corresponding right multiplication endomorphism is injective.*)\nLemma amulr_inj : injective amulr.\n\n(*This fact states that the function for left multiplication by an algebra element is a linear map.*)\nFact amull_is_linear : linear amull.\n\n#[hnf]\nHB.instance Definition _ := GRing.isSemilinear.Build K aT (hom aT aT) _ amull\n (GRing.semilinear_linear amull_is_linear).\n\n(*This lemma states that left multiplication by the multiplicative identity element of the algebra results in the identity function on the vector space.*)\nLemma amull1 : amull 1 = \\1%VF.\n\n(*This lemma states that the left multiplication function applied to a product of two algebra elements is equal to the composition of the left multiplication functions of the individual elements, but in the reverse order.*)\nLemma amullM u v : (amull (u * v) = amull v * amull u)%VF.\n\n(*This lemma states that the function for right multiplication by an algebra element is a linear map.*)\nLemma amulr_is_linear : linear amulr.\n\n(*This lemma states that the function for right multiplication by an algebra element is a monoid morphism, meaning it preserves the multiplicative identity and the multiplication operation.*)\nLemma amulr_is_monoid_morphism : monoid_morphism amulr.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `amulr_is_monoid_morphism` instead\")]\n(*This definition provides a proof that the function for right multiplication by an algebra element is multiplicative, meaning it preserves the multiplication operation. This is a deprecated definition, and `amulr_is_monoid_morphism` should be used instead.*)\nDefinition amulr_is_multiplicative :=\n (fun p => (p.2, p.1)) amulr_is_monoid_morphism.\n\n#[hnf]\nHB.instance Definition _ := GRing.isSemilinear.Build K aT (hom aT aT) _ amulr\n (GRing.semilinear_linear amulr_is_linear).\n#[hnf]\nHB.instance Definition _ := GRing.isMonoidMorphism.Build aT (hom aT aT) amulr\n amulr_is_monoid_morphism.\n\n(*This lemma states that if an algebra element is a unit, then the kernel of the left multiplication function associated with that element is the zero subspace.*)\nLemma lker0_amull u : u \\is a GRing.unit -> lker (amull u) == 0%VS.\n\n(*This lemma states that if an algebra element is a unit, then the kernel of the right multiplication function associated with that element is the zero subspace.*)\nLemma lker0_amulr u : u \\is a GRing.unit -> lker (amulr u) == 0%VS.\n\n(*This lemma states that applying the identity linear function to the coefficients of a polynomial results in the original polynomial.*)\nLemma lfun1_poly (p : {poly aT}) : map_poly \\1%VF p = p.\n\n(*This fact defines an opaque key used to lock the definition of the product of vector subspaces.*)\nFact prodv_key : unit. \n(*This definition specifies the product of two vector subspaces as the subspace spanned by all pairwise products of elements from the bases of the two input subspaces. The implementation is locked and should be accessed through its declared properties.*)\nDefinition prodv :=\n locked_with prodv_key (fun U V => <>%VS).\nCanonical prodv_unlockable := [unlockable fun prodv].\n(*This notation defines the infix asterisk operator as a shorthand for the product of two vector subspaces, applicable within the vector space scope.*)\nLocal Notation \"A * B\" := (prodv A B) : vspace_scope.\n\n(*This lemma states that for any two vector subspaces, the product of an element from the first subspace and an element from the second subspace is contained within the product of the two subspaces.*)\nLemma memv_mul U V : {in U & V, forall u v, u * v \\in (U * V)%VS}.\n\n(*This lemma establishes the equivalence between two statements: first, that for any two vector subspaces, their product subspace is a subspace of a third vector subspace, and second, that the product of any element from the first subspace and any element from the second subspace is contained within the third subspace.*)\nLemma prodvP {U V W} :\n reflect {in U & V, forall u v, u * v \\in W} (U * V <= W)%VS.\n\n(*This lemma states that the product of the one-dimensional subspace spanned by a first vector and the one-dimensional subspace spanned by a second vector is equal to the one-dimensional subspace spanned by the product of the two vectors.*)\nLemma prodv_line u v : (<[u]> * <[v]> = <[u * v]>)%VS.\n\n(*This lemma states that the dimension of the unit vector subspace, which is the subspace spanned by the multiplicative identity of the algebra, is equal to one.*)\nLemma dimv1: \\dim (1%VS : {vspace aT}) = 1.\n\n(*This lemma states that the dimension of the product of two vector subspaces is less than or equal to the product of their individual dimensions.*)\nLemma dim_prodv U V : \\dim (U * V) <= \\dim U * \\dim V.\n\n(*This lemma states that the unit vector subspace is not equal to the zero vector subspace.*)\nLemma vspace1_neq0 : (1 != 0 :> {vspace aT})%VS.\n\n(*This lemma states that there exists a non-zero element of the algebra such that the basis of the unit vector subspace is a sequence containing only that single element.*)\nLemma vbasis1 : exists2 k, k != 0 & vbasis 1 = [:: k%:A] :> seq aT.\n\n(*This lemma states that the zero vector subspace is a left zero for the vector subspace product operation, meaning the product of the zero subspace with any other subspace is the zero subspace.*)\nLemma prod0v : left_zero 0%VS prodv.\n\n(*This lemma states that the zero vector subspace is a right zero for the vector subspace product operation, meaning the product of any subspace with the zero subspace is the zero subspace.*)\nLemma prodv0 : right_zero 0%VS prodv.\n\nHB.instance Definition _ := Monoid.isMulLaw.Build {vspace aT} 0%VS prodv\n prod0v prodv0.\n\n(*This lemma states that the unit vector subspace is a left identity for the vector subspace product operation.*)\nLemma prod1v : left_id 1%VS prodv.\n\n(*This lemma states that the unit vector subspace is a right identity for the vector subspace product operation.*)\nLemma prodv1 : right_id 1%VS prodv.\n\n(*This lemma states that the vector subspace product is monotonic with respect to the subspace inclusion relation. Specifically, if a first subspace is a subspace of a second, and a third subspace is a subspace of a fourth, then the product of the first and third subspaces is a subspace of the product of the second and fourth subspaces.*)\nLemma prodvS U1 U2 V1 V2 : (U1 <= U2 -> V1 <= V2 -> U1 * V1 <= U2 * V2)%VS.\n\n(*This lemma states that the vector subspace product is monotonic in its left argument. If a first subspace is a subspace of a second, then the product of the first subspace with any third subspace is a subspace of the product of the second subspace with that same third subspace.*)\nLemma prodvSl U1 U2 V : (U1 <= U2 -> U1 * V <= U2 * V)%VS.\n\n(*This lemma states that the vector subspace product is monotonic in its right argument. If a first subspace is a subspace of a second, then the product of any third subspace with the first subspace is a subspace of the product of that same third subspace with the second subspace.*)\nLemma prodvSr U V1 V2 : (V1 <= V2 -> U * V1 <= U * V2)%VS.\n\n(*This lemma states that the vector subspace product operation is left-distributive over the vector subspace sum operation.*)\nLemma prodvDl : left_distributive prodv addv.\n\n(*This lemma states that the vector subspace product operation is right-distributive over the vector subspace sum operation.*)\nLemma prodvDr : right_distributive prodv addv.\n\nHB.instance Definition _ := Monoid.isAddLaw.Build {vspace aT} prodv addv\n prodvDl prodvDr.\n\n(*This lemma states that the vector subspace product operation is associative.*)\nLemma prodvA : associative prodv.\n\nHB.instance Definition _ := Monoid.isLaw.Build {vspace aT} 1%VS prodv\n prodvA prod1v prodv1.\n\n(*This definition specifies the exponentiation of a vector subspace to a natural number power. It is defined as the repeated product of the subspace with itself, iterated a number of times equal to the given natural number. The base case, exponentiation to the power of zero, yields the unit vector subspace.*)\nDefinition expv U n := iterop n.+1.-1 prodv U 1%VS.\n(*This notation represents the exponentiation of an element of a vector space to the power of a natural number.*)\nLocal Notation \"A ^+ n\" := (expv A n) : vspace_scope.\n\n(*This lemma states that any element of a vector space raised to the power of zero is equal to the multiplicative identity of that vector space.*)\nLemma expv0 U : (U ^+ 0 = 1)%VS. \n(*This lemma states that any element of a vector space raised to the power of one is equal to the element itself.*)\nLemma expv1 U : (U ^+ 1 = U)%VS. \n(*This lemma states that an element of a vector space raised to the power of two is equal to the product of the element with itself.*)\nLemma expv2 U : (U ^+ 2 = U * U)%VS. \n\n(*This lemma provides a recursive formula for exponentiation, stating that an element raised to the power of a successor of a natural number is equal to the product of the element and the element raised to the power of the original natural number.*)\nLemma expvSl U n : (U ^+ n.+1 = U * U ^+ n)%VS.\n\n(*This lemma states that the zero element of a vector space raised to a positive natural number power is zero, and when raised to the power of zero, it is the multiplicative identity.*)\nLemma expv0n n : (0 ^+ n = if n is _.+1 then 0 else 1)%VS.\n\n(*This lemma states that the multiplicative identity of a vector space raised to any natural number power remains the multiplicative identity.*)\nLemma expv1n n : (1 ^+ n = 1)%VS.\n\n(*This lemma states that raising an element of a vector space to the power of a sum of two natural numbers is equivalent to the product of the element raised to each of these numbers separately.*)\nLemma expvD U m n : (U ^+ (m + n) = U ^+ m * U ^+ n)%VS.\n\n(*This lemma provides an alternative recursive formula for exponentiation, stating that an element raised to the power of a successor of a natural number is equal to the product of the element raised to the original natural number and the element itself.*)\nLemma expvSr U n : (U ^+ n.+1 = U ^+ n * U)%VS.\n\n(*This lemma states that an element of a vector space raised to the power of a product of two natural numbers is equal to the element raised to the first number, with the result then raised to the power of the second number.*)\nLemma expvM U m n : (U ^+ (m * n) = U ^+ m ^+ n)%VS.\n\n(*This lemma states that the exponentiation operation is non-decreasing, meaning if a first vector space element is less than or equal to a second one, then the first element raised to any natural number power is also less than or equal to the second element raised to the same power.*)\nLemma expvS U V n : (U <= V -> U ^+ n <= V ^+ n)%VS.\n\n(*This lemma states that the n-th power of the linear subspace spanned by a single vector is equal to the linear subspace spanned by the n-th power of that vector.*)\nLemma expv_line u n : (<[u]> ^+ n = <[u ^+ n]>)%VS.\n\n(*This definition describes the centralizer of a single element in a vector space as the set of all elements that commute with the given element under multiplication.*)\nDefinition centraliser1_vspace u := lker (amulr u - amull u).\n(*This notation represents the centralizer of a single element within a vector space, which is the subspace of all elements that commute with the given element.*)\nLocal Notation \"'C [ u ]\" := (centraliser1_vspace u) : vspace_scope.\n(*This definition describes the centralizer of a vector subspace as the intersection of the centralizers of all its basis vectors, effectively representing the set of all elements that commute with every element in the subspace.*)\nDefinition centraliser_vspace V := (\\bigcap_i 'C[tnth (vbasis V) i])%VS.\n(*This notation represents the centralizer of a given vector subspace, which is the set of all elements that commute with every element of that subspace.*)\nLocal Notation \"'C ( V )\" := (centraliser_vspace V) : vspace_scope.\n(*This definition describes the center of a vector subspace as the intersection of the subspace with its own centralizer, which consists of all elements within the subspace that commute with every other element of the subspace.*)\nDefinition center_vspace V := (V :&: 'C(V))%VS.\n(*This notation represents the center of a vector subspace, which is the set of elements within the subspace that commute with all other elements of the subspace.*)\nLocal Notation \"'Z ( V )\" := (center_vspace V) : vspace_scope.\n\n(*This lemma establishes an equivalence in a vector space: two elements commute with each other under multiplication if and only if the first element is a member of the centralizer of the second element.*)\nLemma cent1vP u v : reflect (u * v = v * u) (u \\in 'C[v]%VS).\n\n(*This lemma states that the multiplicative identity element of a vector space is always a member of the centralizer of any given element.*)\nLemma cent1v1 u : 1 \\in 'C[u]%VS. \n(*This lemma states that any element in a vector space is always a member of its own centralizer.*)\nLemma cent1v_id u : u \\in 'C[u]%VS. \n(*This lemma states that any natural number power of an element in a vector space is a member of the centralizer of that same element.*)\nLemma cent1vX u n : u ^+ n \\in 'C[u]%VS. \n(*This lemma states that the property of an element being in the centralizer of another is symmetric: a first element is in the centralizer of a second element if and only if the second element is in the centralizer of the first.*)\nLemma cent1vC u v : (u \\in 'C[v])%VS = (v \\in 'C[u])%VS.\n\n(*This lemma establishes an equivalence: an element is a member of the centralizer of a vector subspace if and only if it commutes with every element within that subspace.*)\nLemma centvP u V : reflect {in V, forall v, u * v = v * u} (u \\in 'C(V))%VS.\n\n(*This lemma establishes that a vector subspace is included in the centralizer of another subspace if and only if the multiplication operation is commutative between any element from the first subspace and any element from the second.*)\nLemma centvsP U V : reflect {in U & V, commutative *%R} (U <= 'C(V))%VS.\n\n(*This lemma states that a vector subspace is contained within the centralizer of a given element if and only if that element is a member of the centralizer of the subspace.*)\nLemma subv_cent1 U v : (U <= 'C[v])%VS = (v \\in 'C(U)%VS).\n\n(*This lemma states that the multiplicative identity element is always a member of the centralizer of any given vector subspace.*)\nLemma centv1 V : 1 \\in 'C(V)%VS.\n\n(*This lemma states that if an element is a member of the centralizer of a vector subspace, then any natural number power of that element is also a member of that centralizer.*)\nLemma centvX V u n : u \\in 'C(V)%VS -> u ^+ n \\in 'C(V)%VS.\n\n(*This lemma states that the inclusion of one vector subspace in the centralizer of another is a symmetric relationship: the first subspace is included in the centralizer of the second if and only if the second subspace is included in the centralizer of the first.*)\nLemma centvC U V : (U <= 'C(V))%VS = (V <= 'C(U))%VS.\n\n(*This lemma states that the center of any vector subspace is itself a subspace of that same vector subspace.*)\nLemma centerv_sub V : ('Z(V) <= V)%VS. \n(*This lemma states that any algebra subspace is contained within the centralizer of its center.*)\nLemma cent_centerv V : (V <= 'C('Z(V)))%VS.\n\n(*This definition describes the property of an element being the algebraic identity for a vector subspace. An element satisfies this property if it is a non-zero member of the subspace and acts as both a left and right multiplicative identity for every element within that subspace.*)\nDefinition is_algid e U :=\n [/\\ e \\in U, e != 0 & {in U, forall u, e * u = u /\\ u * e = u}].\n\n(*This fact asserts that it is computationally decidable whether a given vector subspace contains an algebraic identity element.*)\nFact algid_decidable U : decidable (exists e, is_algid e U).\n\n(*This definition establishes a boolean predicate indicating whether a vector subspace contains an algebraic identity.*)\nDefinition has_algid : pred {vspace aT} := algid_decidable.\n\n(*This lemma states that the boolean predicate for the existence of an algebraic identity within a vector subspace is true if and only if such an identity element actually exists.*)\nLemma has_algidP {U} : reflect (exists e, is_algid e U) (has_algid U).\n\n(*This lemma states that if the multiplicative identity element of the ambient algebra is a member of a given subspace, then that subspace possesses an algebraic identity.*)\nLemma has_algid1 U : 1 \\in U -> has_algid U.\n\n(*This definition specifies the properties required for a vector subspace to be considered an algebra subspace, namely that it must possess an algebraic identity and be closed under multiplication.*)\nDefinition is_aspace U := has_algid U && (U * U <= U)%VS.\n(*This structure defines an algebra subspace as a record that bundles a vector subspace with a proof that it contains an algebraic identity and is closed under multiplication.*)\nStructure aspace := ASpace {asval :> {vspace aT}; _ : is_aspace asval}.\n\nHB.instance Definition _ := [isSub for asval].\n(*This definition provides a way to construct an algebra subspace from a vector subspace that is already known to satisfy the algebra subspace properties, optionally using an existing algebra subspace as a hint for type-checking.*)\nDefinition clone_aspace U (A : aspace) :=\n fun algU & phant_id algU (valP A) => @ASpace U algU : aspace.\n\n(*This fact provides a proof that the trivial vector subspace containing only the multiplicative identity element is an algebra subspace.*)\nFact aspace1_subproof : is_aspace 1.\n\nCanonical aspace1 : aspace := ASpace aspace1_subproof.\n\n(*This lemma provides a proof that the entire ambient algebra, considered as a vector subspace, is an algebra subspace.*)\nLemma aspacef_subproof : is_aspace fullv.\n\nCanonical aspacef : aspace := ASpace aspacef_subproof.\n\n(*This lemma states that a polynomial's coefficients belong to the trivial subspace of scalars if and only if the polynomial is equivalent to one formed by mapping the coefficients of a base field polynomial into the algebra.*)\nLemma polyOver1P p :\n reflect (exists q, p = map_poly (in_alg aT) q) (p \\is a polyOver 1%VS).\n\nEnd FalgebraTheory.\n\nDelimit Scope aspace_scope with AS.\nBind Scope aspace_scope with aspace.\nArguments asval {K aT} a%_AS.\nArguments aspace [K]%_type aT%_type.\nArguments clone_aspace [K aT U%_VS A%_AS algU] _.\n\n(*This notation is used to represent the type of all algebra subspaces of a given ambient algebra type.*)\nNotation \"{ 'aspace' T }\" := (aspace T) : type_scope.\n(*This notation denotes the product of two vector subspaces, which is the subspace generated by all pairwise products of elements from the given subspaces.*)\nNotation \"A * B\" := (prodv A B) : vspace_scope.\n(*This notation denotes the exponentiation of a vector subspace to a natural number power, defined as the iterated product of the subspace with itself.*)\nNotation \"A ^+ n\" := (expv A n) : vspace_scope.\n(*This notation represents the centralizer of a single element, defined as the vector subspace of all elements that commute with it.*)\nNotation \"'C [ u ]\" := (centraliser1_vspace u) : vspace_scope.\n(*This notation represents the centralizer of an element within a specific vector subspace, defined as the intersection of the given subspace with the element's centralizer.*)\nNotation \"'C_ U [ v ]\" := (capv U 'C[v]) : vspace_scope.\n(*This notation provides a parsing variant for the centralizer of an element within a vector subspace, allowing the subspace to be enclosed in parentheses.*)\nNotation \"'C_ ( U ) [ v ]\" := (capv U 'C[v]) (only parsing) : vspace_scope.\n(*This notation represents the centralizer of a vector subspace, which is the subspace containing all elements that commute with every element of the given subspace.*)\nNotation \"'C ( V )\" := (centraliser_vspace V) : vspace_scope.\n(*This notation represents the centralizer of one vector subspace relative to another, defined as the intersection of the second subspace with the centralizer of the first.*)\nNotation \"'C_ U ( V )\" := (capv U 'C(V)) : vspace_scope.\n(*This notation provides a parsing variant for the centralizer of one vector subspace within another, allowing the containing subspace to be enclosed in parentheses.*)\nNotation \"'C_ ( U ) ( V )\" := (capv U 'C(V)) (only parsing) : vspace_scope.\n(*This notation represents the center of a vector subspace, consisting of all elements within that subspace that commute with every other element of the same subspace.*)\nNotation \"'Z ( V )\" := (center_vspace V) : vspace_scope.\n\n(*This notation represents the trivial algebra subspace that contains only the multiplicative identity element.*)\nNotation \"1\" := (aspace1 _) : aspace_scope.\n(*This notation represents the full algebra viewed as an algebra subspace of itself for a given algebra type.*)\nNotation \"{ : aT }\" := (aspacef aT) : aspace_scope.\n(*This notation is used to view a vector subspace as an algebra subspace, assuming the necessary properties are provable from the context.*)\nNotation \"[ 'aspace' 'of' U ]\" := (@clone_aspace _ _ U _ _ id)\n (format \"[ 'aspace' 'of' U ]\") : form_scope.\n(*This notation is used to view a vector subspace as an algebra subspace, using an existing algebra subspace as a hint for type inference.*)\nNotation \"[ 'aspace' 'of' U 'for' A ]\" := (@clone_aspace _ _ U A _ idfun)\n (format \"[ 'aspace' 'of' U 'for' A ]\") : form_scope.\n\nArguments prodvP {K aT U V W}.\nArguments cent1vP {K aT u v}.\nArguments centvP {K aT u V}.\nArguments centvsP {K aT U V}.\nArguments has_algidP {K aT U}.\nArguments polyOver1P {K aT p}.\n\nSection AspaceTheory.\n\nVariables (K : fieldType) (aT : falgType K).\nImplicit Types (u v e : aT) (U V : {vspace aT}) (A B : {aspace aT}).\nImport FalgLfun.\n\n(*This lemma provides a constructive proof that for any vector subspace, there exists an element within it that serves as the two-sided multiplicative identity for all elements in the subspace, provided the subspace is an algebra subspace.*)\nLemma algid_subproof U :\n {e | e \\in U\n & has_algid U ==> (U <= lker (amull e - 1) :&: lker (amulr e - 1))%VS}.\n\n(*This definition designates the canonical algebraic identity element of a given algebra subspace. If the subspace does not have a unique identity, it provides a default element.*)\nDefinition algid U := s2val (algid_subproof U).\n\n(*This lemma states that the canonical algebraic identity of a vector subspace is an element of that subspace.*)\nLemma memv_algid U : algid U \\in U.\n\n(*This lemma states that the canonical algebraic identity of an algebra subspace acts as a left identity for multiplication with all elements within that subspace.*)\nLemma algidl A : {in A, left_id (algid A) *%R}.\n\n(*This lemma states that for any algebra subspace, its algebraic identity element acts as a right identity for multiplication with any element within that subspace.*)\nLemma algidr A : {in A, right_id (algid A) *%R}.\n\n(*This lemma states that if an algebra subspace contains an invertible ring element, then the algebraic identity of that subspace is equal to the multiplicative identity of the ring.*)\nLemma unitr_algid1 A u : u \\in A -> u \\is a GRing.unit -> algid A = 1.\n\n(*This lemma states that the algebraic identity of an algebra subspace is equal to the ring's multiplicative identity if and only if the multiplicative identity is an element of the subspace.*)\nLemma algid_eq1 A : (algid A == 1) = (1 \\in A).\n\n(*This lemma states that the algebraic identity of any algebra subspace is not equal to the zero element of the ring.*)\nLemma algid_neq0 A : algid A != 0.\n\n(*This lemma states that the vector subspace spanned by the algebraic identity of an algebra subspace has a dimension of one.*)\nLemma dim_algid A : \\dim <[algid A]> = 1%N.\n\n(*This lemma states that the dimension of any algebra subspace is strictly greater than zero.*)\nLemma adim_gt0 A : (0 < \\dim A)%N.\n\n(*This lemma states that an algebra subspace cannot be a sub-vector space of the zero vector space.*)\nLemma not_asubv0 A : ~~ (A <= 0)%VS.\n\n(*This lemma states that an algebra subspace has a dimension of one if and only if it is equal to the vector space spanned by its algebraic identity.*)\nLemma adim1P {A} : reflect (A = <[algid A]>%VS :> {vspace aT}) (\\dim A == 1%N).\n\n(*This lemma states that the product of an algebra subspace with itself is contained within that same algebra subspace.*)\nLemma asubv A : (A * A <= A)%VS.\n\n(*This lemma states that an algebra subspace is closed under multiplication, meaning the product of any two elements from the subspace is also an element of the subspace.*)\nLemma memvM A : {in A &, forall u v, u * v \\in A}.\n\n(*This lemma states that the product of an algebra subspace with itself is equal to the original algebra subspace.*)\nLemma prodv_id A : (A * A)%VS = A.\n\n(*This lemma states that if two vector subspaces are contained within an algebra subspace, then their product is also contained within that same algebra subspace.*)\nLemma prodv_sub U V A : (U <= A -> V <= A -> U * V <= A)%VS.\n\n(*This lemma states that for any positive natural number exponent, raising an algebra subspace to that power results in the original algebra subspace.*)\nLemma expv_id A n : (A ^+ n.+1)%VS = A.\n\n(*This lemma states that the linear image of a vector subspace under the operation of right multiplication by a given element is equal to the product of that vector subspace and the subspace spanned by the given element.*)\nLemma limg_amulr U v : (amulr v @: U = U * <[v]>)%VS.\n\n(*This lemma states that an element is a member of the vector space product of a subspace and the space spanned by another element if and only if it can be expressed as the product of an element from the first subspace and the spanning element.*)\nLemma memv_cosetP {U v w} :\n reflect (exists2 u, u\\in U & w = u * v) (w \\in U * <[v]>)%VS.\n\n(*This lemma states that if an element is invertible, then the dimension of the vector space resulting from the product of a given subspace and the subspace spanned by that element is equal to the dimension of the original subspace.*)\nLemma dim_cosetv_unit V u : u \\is a GRing.unit -> \\dim (V * <[u]>) = \\dim V.\n\n(*This lemma states that for any given algebra subspace, an element is a member of that subspace if and only if its multiplicative inverse is also a member.*)\nLemma memvV A u : (u^-1 \\in A) = (u \\in A).\n\n(*This fact asserts that the intersection of an algebra subspace and another vector subspace is itself an algebra subspace, provided that the second vector subspace contains the algebraic identity of the first.*)\nFact aspace_cap_subproof A B : algid A \\in B -> is_aspace (A :&: B).\n\n(*This definition constructs an algebra subspace structure on the intersection of two vector subspaces, provided a proof that the second subspace contains the algebraic identity of the first.*)\nDefinition aspace_cap A B BeA := ASpace (@aspace_cap_subproof A B BeA).\n\n(*This fact asserts that the centralizer of any single element is an algebra subspace.*)\nFact centraliser1_is_aspace u : is_aspace 'C[u].\n\nCanonical centraliser1_aspace u := ASpace (centraliser1_is_aspace u).\n\n(*This fact asserts that the centralizer of any vector subspace is an algebra subspace.*)\nFact centraliser_is_aspace V : is_aspace 'C(V).\n\nCanonical centraliser_aspace V := ASpace (centraliser_is_aspace V).\n\n(*This lemma states that the algebraic identity of an algebra subspace is an element of the centralizer of that same subspace.*)\nLemma centv_algid A : algid A \\in 'C(A)%VS.\n\nCanonical center_aspace A := [aspace of 'Z(A) for aspace_cap (centv_algid A)].\n\n(*This lemma states that the algebraic identity of the center of an algebra subspace is equal to the algebraic identity of the algebra subspace itself.*)\nLemma algid_center A : algid 'Z(A) = algid A.\n\n(*This lemma states that within the context of finite-dimensional algebras, if the underlying ring structure is an integral domain, then it is also a field.*)\nLemma Falgebra_FieldMixin :\n GRing.integral_domain_axiom aT -> GRing.field_axiom aT.\n\nSection SkewField.\n\nHypothesis fieldT : GRing.field_axiom aT.\n\n(*This lemma states that when the ambient ring is a skew field, the algebraic identity of any algebra subspace is equal to the multiplicative identity of the ring.*)\nLemma skew_field_algid1 A : algid A = 1.\n\n(*This lemma states that if a module over a skew field is closed under multiplication by an algebra subspace, then the module is semisimple and can be decomposed into a direct sum of submodules generated by individual non-zero elements.*)\nLemma skew_field_module_semisimple A M :\n let sumA X := (\\sum_(x <- X) A * <[x]>)%VS in\n (A * M <= M)%VS -> {X | [/\\ sumA X = M, directv (sumA X) & 0 \\notin X]}.\n\n(*This lemma states that if a module is closed under multiplication by an algebra subspace over a skew field, then the dimension of the algebra subspace must divide the dimension of the module.*)\nLemma skew_field_module_dimS A M : (A * M <= M)%VS -> \\dim A %| \\dim M.\n\n(*This lemma states that if one algebra subspace is contained within another over a skew field, then the dimension of the smaller subspace must divide the dimension of the larger one.*)\nLemma skew_field_dimS A B : (A <= B)%VS -> \\dim A %| \\dim B.\n\nEnd SkewField.\n\nEnd AspaceTheory.\n\n(*This notation denotes the centralizer of a single element, which is the algebra subspace containing all elements that commute with the given element.*)\nNotation \"'C [ u ]\" := (centraliser1_aspace u) : aspace_scope.\n(*This notation denotes the centralizer of a vector space, which is the algebra subspace containing all elements that commute with every element of the given vector space.*)\nNotation \"'C ( V )\" := (centraliser_aspace V) : aspace_scope.\n(*This notation denotes the center of a given algebra, which consists of all elements that commute with every other element in the algebra.*)\nNotation \"'Z ( A )\" := (center_aspace A) : aspace_scope.\n\nArguments adim1P {K aT A}.\nArguments memv_cosetP {K aT U v w}.\n\nSection Closure.\n\nVariables (K : fieldType) (aT : falgType K).\nImplicit Types (u v : aT) (U V W : {vspace aT}).\n\n(*This definition constructs the algebra generated by a given vector subspace, which is the smallest subalgebra containing that subspace. It is computed as the sum of all powers of the subspace up to the dimension of the ambient algebra.*)\nDefinition agenv U := (\\sum_(i < \\dim {:aT}) U ^+ i)%VS.\n(*This notation represents the algebra generated by adjoining a finite sequence of vectors to an existing vector subspace.*)\nLocal Notation \"<< U & vs >>\" := (agenv (U + <>)) : vspace_scope.\n(*This notation represents the algebra generated by adjoining a single vector to an existing vector subspace.*)\nLocal Notation \"<< U ; x >>\" := (agenv (U + <[x]>)) : vspace_scope.\n\n(*This lemma states that the algebra generated by a vector subspace can be characterized as the vector space sum of the subspace containing the multiplicative identity and the left product of the original subspace with the generated algebra itself.*)\nLemma agenvEl U : agenv U = (1 + U * agenv U)%VS.\n\n(*This lemma states that the algebra generated by a vector subspace can be characterized as the vector space sum of the subspace containing the multiplicative identity and the right product of the generated algebra with the original subspace.*)\nLemma agenvEr U : agenv U = (1 + agenv U * U)%VS.\n\n(*This lemma asserts that if a vector subspace is a left module for another subspace, then it is also a left module for the algebra generated by that other subspace.*)\nLemma agenv_modl U V : (U * V <= V -> agenv U * V <= V)%VS.\n\n(*This lemma asserts that if a vector subspace is a right module for another subspace, then it is also a right module for the algebra generated by that other subspace.*)\nLemma agenv_modr U V : (V * U <= V -> V * agenv U <= V)%VS.\n\n(*This fact states that the vector space generated by a given subspace is itself a subalgebra.*)\nFact agenv_is_aspace U : is_aspace (agenv U).\n\nCanonical agenv_aspace U : {aspace aT} := ASpace (agenv_is_aspace U).\n\n(*This lemma establishes that the algebra generated by a vector subspace is definitionally equal to its canonical representation as a subalgebra.*)\nLemma agenvE U : agenv U = agenv_aspace U. \n\n(*This lemma states that the algebra generated by a vector subspace is closed under multiplication, meaning the product of the generated algebra with itself is equal to the generated algebra.*)\nLemma agenvM U : (agenv U * agenv U)%VS = agenv U. \n(*This lemma asserts that any positive power of the algebra generated by a vector subspace is equal to the generated algebra itself.*)\nLemma agenvX n U : (agenv U ^+ n.+1)%VS = agenv U. \n\n(*This lemma states that the multiplicative identity element is always contained within the algebra generated by any vector subspace.*)\nLemma sub1_agenv U : (1 <= agenv U)%VS. \n\n(*This lemma states that any vector subspace is a subset of the algebra it generates.*)\nLemma sub_agenv U : (U <= agenv U)%VS.\n\n(*This lemma states that any power of a vector subspace is contained within the algebra generated by that subspace.*)\nLemma subX_agenv U n : (U ^+ n <= agenv U)%VS.\n\n(*This lemma establishes that if a vector subspace contains the multiplicative identity and is a left module for another subspace, then it must contain the entire algebra generated by that other subspace.*)\nLemma agenv_sub_modl U V : (1 <= V -> U * V <= V -> agenv U <= V)%VS.\n\n(*This lemma establishes that if a vector subspace contains the multiplicative identity and is a right module for another subspace, then it must contain the entire algebra generated by that other subspace.*)\nLemma agenv_sub_modr U V : (1 <= V -> V * U <= V -> agenv U <= V)%VS.\n\n(*This lemma states that the operation of generating an algebra is idempotent, meaning that generating an algebra from a space that is already a generated algebra yields the original generated algebra.*)\nLemma agenv_id U : agenv (agenv U) = agenv U.\n\n(*This lemma states that the algebra generation operation is monotonic with respect to subspace inclusion; if a first vector subspace is contained in a second one, then the algebra generated by the first is contained in the algebra generated by the second.*)\nLemma agenvS U V : (U <= V -> agenv U <= agenv V)%VS.\n\n(*This lemma provides a simplification rule, stating that the algebra generated by the sum of a generated algebra and a vector subspace is the same as the algebra generated by the sum of the original subspace and the other vector subspace.*)\nLemma agenv_add_id U V : agenv (agenv U + V) = agenv (U + V).\n\n(*This lemma states that a vector subspace is contained within the algebra generated by adjoining a single vector to it.*)\nLemma subv_adjoin U x : (U <= <>)%VS.\n\n(*This lemma states that a vector subspace is contained within the algebra generated by adjoining a sequence of vectors to it.*)\nLemma subv_adjoin_seq U xs : (U <= <>)%VS.\n\n(*This lemma states that a vector is an element of the algebra generated by adjoining that same vector to a vector subspace.*)\nLemma memv_adjoin U x : x \\in <>%VS.\n\n(*This lemma states that all vectors from a given sequence are contained within the algebra generated by adjoining that sequence to a vector subspace.*)\nLemma seqv_sub_adjoin U xs : {subset xs <= <>%VS}.\n\n(*This lemma states that any vector belonging to a given vector subspace also belongs to the algebra generated by adjoining another vector to that subspace.*)\nLemma subvP_adjoin U x y : y \\in U -> y \\in <>%VS.\n\n(*This lemma states that adjoining an empty sequence of vectors to a vector subspace is equivalent to simply generating an algebra from that subspace.*)\nLemma adjoin_nil V : <>%VS = agenv V.\n\n(*This lemma provides a recursive definition for adjoining a sequence of vectors, stating that adjoining a non-empty sequence is equivalent to first adjoining the head of the sequence and then adjoining the tail to the resulting algebra.*)\nLemma adjoin_cons V x rs : <>%VS = << <> & rs>>%VS.\n\n(*This lemma provides a recursive definition for adjoining a sequence of vectors from the right, stating that adjoining a sequence with an element appended is equivalent to first adjoining the initial sequence and then adjoining the final element to the resulting algebra.*)\nLemma adjoin_rcons V rs x : <>%VS = << <>%VS; x>>%VS.\n\n(*This lemma states that adjoining a singleton sequence containing a vector is equivalent to adjoining just that vector.*)\nLemma adjoin_seq1 V x : <>%VS = <>%VS.\n\n(*This lemma states that the operation of adjoining two individual vectors to a vector subspace is commutative, meaning the final generated algebra does not depend on the order in which the vectors are adjoined.*)\nLemma adjoinC V x y : << <>; y>>%VS = << <>; x>>%VS.\n\n(*This lemma states that if a first subspace is contained within a second subspace, then the subspace generated by adjoining a vector to the first is also contained within the subspace generated by adjoining the same vector to the second.*)\nLemma adjoinSl U V x : (U <= V -> <> <= <>)%VS.\n\n(*This lemma states that if a first subspace is contained within a second subspace, then the subspace generated by adjoining a sequence of vectors to the first subspace is also contained within the subspace generated by adjoining that same sequence of vectors to the second subspace.*)\nLemma adjoin_seqSl U V rs : (U <= V -> <> <= <>)%VS.\n\n(*This lemma states that if the set of vectors in a first sequence is a subset of the set of vectors in a second sequence, then the subspace generated by adjoining the first sequence to a given subspace is contained within the subspace generated by adjoining the second sequence to that same subspace.*)\nLemma adjoin_seqSr U rs1 rs2 :\n {subset rs1 <= rs2} -> (<> <= <>)%VS.\n\nEnd Closure.\n\n(*This notation represents the subspace spanned by a given collection of vectors, viewed as a subspace of the ambient space.*)\nNotation \"<< U >>\" := (agenv_aspace U) : aspace_scope.\n(*This notation represents the subspace generated by adjoining a sequence of vectors to a given subspace.*)\nNotation \"<< U & vs >>\" := (agenv (U + <>)) : vspace_scope.\n(*This notation represents the subspace generated by adjoining a single vector to a given subspace.*)\nNotation \"<< U ; x >>\" := (agenv (U + <[x]>)) : vspace_scope.\n(*A notation for adjoining a finite sequence of vectors to a vector subspace, yielding a new vector subspace.*)\nNotation \"<< U & vs >>\" := << U + <> >>%AS : aspace_scope.\n(*A notation for adjoining a single vector to a vector subspace, yielding a new vector subspace.*)\nNotation \"<< U ; x >>\" := << U + <[x]> >>%AS : aspace_scope. \n\nSection SubFalgType.\n\nVariable (K : fieldType) (aT : falgType K) (A : {aspace aT}).\n\n(*This definition specifies the multiplicative identity for subspace multiplication, defined as the one-dimensional subspace spanned by the multiplicative identity of the algebra.*)\nDefinition subvs_one := Subvs (memv_algid A).\n(*This definition specifies the multiplication of two subspaces of an algebra, resulting in a new subspace that is generated by all possible products of elements from the two input subspaces.*)\nDefinition subvs_mul (u v : subvs_of A) :=\n Subvs (subv_trans (memv_mul (subvsP u) (subvsP v)) (asubv _)).\n\n(*This fact states that the multiplication operation defined for subspaces of an algebra is associative.*)\nFact subvs_mulA : associative subvs_mul.\n\n(*This fact states that the subspace containing the algebra's multiplicative identity acts as a left identity for subspace multiplication.*)\nFact subvs_mu1l : left_id subvs_one subvs_mul.\n\n(*This fact states that the subspace containing the algebra's multiplicative identity acts as a right identity for subspace multiplication.*)\nFact subvs_mul1 : right_id subvs_one subvs_mul.\n\n(*This fact states that subspace multiplication is left-distributive over subspace addition.*)\nFact subvs_mulDl : left_distributive subvs_mul +%R.\n\n(*This fact states that subspace multiplication is right-distributive over subspace addition.*)\nFact subvs_mulDr : right_distributive subvs_mul +%R.\n\nHB.instance Definition _ := GRing.Zmodule_isNzRing.Build (subvs_of A)\n subvs_mulA subvs_mu1l subvs_mul1 subvs_mulDl subvs_mulDr (algid_neq0 _).\n\n(*This lemma states that scaling the product of two subspaces by a scalar value is equivalent to scaling the first subspace by that scalar and then multiplying it by the second subspace.*)\nLemma subvs_scaleAl k (x y : subvs_of A) : k *: (x * y) = (k *: x) * y.\n\nHB.instance Definition _ := GRing.Lmodule_isLalgebra.Build K (subvs_of A)\n subvs_scaleAl.\n\n(*This lemma states that scaling the product of two subspaces by a scalar value is equivalent to multiplying the first subspace by the second subspace that has been scaled by that scalar.*)\nLemma subvs_scaleAr k (x y : subvs_of A) : k *: (x * y) = x * (k *: y).\n\nHB.instance Definition _ := GRing.Lalgebra_isAlgebra.Build K (subvs_of A)\n subvs_scaleAr.\n\n(*This lemma states that if the canonical representative vector of a subspace is invertible in the base algebra, then the subspace itself is an invertible element in the algebra of subspaces.*)\nLemma vsval_unitr w : vsval w \\is a GRing.unit -> w \\is a GRing.unit.\n\n(*This lemma states that if a subspace has an invertible representative vector, then the representative vector of its multiplicative inverse subspace is equal to the multiplicative inverse of the original representative vector.*)\nLemma vsval_invr w : vsval w \\is a GRing.unit -> val w^-1 = (val w)^-1.\n\nEnd SubFalgType.\n\nSection AHom.\n\nVariable K : fieldType.\n\nSection Class_Def.\n\nVariables aT rT : falgType K.\n\n(*This definition specifies a property for a linear map between two algebras. The property holds if the map preserves multiplication when applied to the basis vectors of a given subspace, and it maps the multiplicative identity of the source algebra to that of the target algebra.*)\nDefinition ahom_in (U : {vspace aT}) (f : 'Hom(aT, rT)) :=\n all2rel (fun x y : aT => f (x * y) == f x * f y) (vbasis U) && (f 1 == 1).\n\n(*This lemma provides a reflection, stating that a linear map has the algebra homomorphism property on a given subspace if and only if it preserves multiplication for all elements within that subspace and also preserves the multiplicative identity.*)\nLemma ahom_inP {f : 'Hom(aT, rT)} {U : {vspace aT}} :\n reflect ({in U &, {morph f : x y / x * y >-> x * y}} * (f 1 = 1))\n (ahom_in U f).\n\n(*This lemma provides a reflection, stating that a linear map satisfies the algebra homomorphism property over its entire domain if and only if it is a monoid morphism, meaning it preserves both multiplication and the multiplicative identity element.*)\nLemma ahomP_tmp {f : 'Hom(aT, rT)} : reflect (monoid_morphism f) (ahom_in {:aT} f).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `ahomP_tmp` instead\")]\n(*This deprecated lemma provides a reflection stating that a linear map is multiplicative over its entire domain algebra if and only if it satisfies the algebra homomorphism property on that domain. Use of `ahomP_tmp` is recommended instead.*)\nLemma ahomP {f : 'Hom(aT, rT)} : reflect (multiplicative f) (ahom_in {:aT} f).\n\n(*This structure defines an algebra homomorphism as a linear map between two algebras that is proven to preserve the algebraic structure, specifically multiplication and the multiplicative identity.*)\nStructure ahom := AHom {ahval :> 'Hom(aT, rT); _ : ahom_in {:aT} ahval}.\n\nHB.instance Definition _ := [isSub for ahval].\nHB.instance Definition _ := [Equality of ahom by <:].\n(*This fact states that a function which is both a ring morphism and a linear map automatically satisfies the conditions to be an algebra homomorphism over its entire domain.*)\nFact linfun_is_ahom (f : {lrmorphism aT -> rT}) : ahom_in {:aT} (linfun f).\n\nCanonical linfun_ahom f := AHom (linfun_is_ahom f).\n\nEnd Class_Def.\n\nArguments ahom_in [aT rT].\nArguments ahom_inP {aT rT f U}.\n#[warning=\"-deprecated-since-mathcomp-2.5.0\"]\nArguments ahomP {aT rT f}.\nArguments ahomP_tmp {aT rT f}.\n\nSection LRMorphism.\n\nVariables aT rT sT : falgType K.\n\n(*This fact states that any function with the structure of an algebra homomorphism is also a monoid morphism, meaning it preserves the multiplicative operation and the identity element.*)\nFact ahom_is_monoid_morphism (f : ahom aT rT) : monoid_morphism f.\n\n#[hnf]\n(*This deprecated definition asserts that an algebra homomorphism is a multiplicative function. Use of `ahom_is_monoid_morphism` is recommended instead.*)\nDefinition ahom_is_multiplicative (f : ahom aT rT) : multiplicative f :=\n (fun p => (p.2, p.1)) (ahom_is_monoid_morphism f).\n\n(*This lemma states that if a linear map is an algebra homomorphism defined on an entire algebra, it also satisfies the algebra homomorphism property with respect to any subspace of that algebra.*)\nLemma ahomWin (f : ahom aT rT) U : ahom_in U f.\n\n(*This lemma states that the identity map on an algebra satisfies the conditions of an algebra homomorphism with respect to any of its subspaces.*)\nLemma id_is_ahom (V : {vspace aT}) : ahom_in V \\1.\n\nCanonical id_ahom := AHom (id_is_ahom (aspacef aT)).\n\n(*This lemma states that the composition of two linear maps preserves the algebra homomorphism property. If a linear map is an algebra homomorphism on a subspace and another linear map is an algebra homomorphism on its full domain, then their composition is also an algebra homomorphism on that same subspace.*)\nLemma comp_is_ahom (V : {vspace aT}) (f : 'Hom(rT, sT)) (g : 'Hom(aT, rT)) :\n ahom_in {:rT} f -> ahom_in V g -> ahom_in V (f \\o g).\n\nCanonical comp_ahom (f : ahom rT sT) (g : ahom aT rT) :=\n AHom (comp_is_ahom (valP f) (valP g)).\n\n(*This lemma states that the image under an algebra homomorphism of the product of two subspaces is equal to the product of the images of those two subspaces.*)\nLemma aimgM (f : ahom aT rT) U V : (f @: (U * V) = f @: U * f @: V)%VS.\n\n(*This lemma states that the image of the one-dimensional subspace containing the multiplicative identity under an algebra homomorphism is the one-dimensional subspace containing the multiplicative identity of the target algebra.*)\nLemma aimg1 (f : ahom aT rT) : (f @: 1 = 1)%VS.\n\n(*This lemma states that an algebra homomorphism commutes with taking subspace powers, meaning the image of the n-th power of a subspace is the n-th power of its image.*)\nLemma aimgX (f : ahom aT rT) U n : (f @: (U ^+ n) = f @: U ^+ n)%VS.\n\n(*This lemma states that the image of the subalgebra generated by a subspace under an algebra homomorphism is identical to the subalgebra generated by the image of that subspace.*)\nLemma aimg_agen (f : ahom aT rT) U : (f @: agenv U)%VS = agenv (f @: U).\n\n(*This lemma states that the image of a subspace adjoined with a vector, under an algebra homomorphism, is equal to the image of the subspace adjoined with the image of the vector.*)\nLemma aimg_adjoin (f : ahom aT rT) U x : (f @: <> = <>)%VS.\n\n(*This lemma states that the image of a subspace adjoined with a sequence of vectors, under an algebra homomorphism, is equal to the image of the subspace adjoined with the sequence of the images of those vectors.*)\nLemma aimg_adjoin_seq (f : ahom aT rT) U xs :\n (f @: <> = <>)%VS.\n\n(*This lemma states that for any two affine homomorphisms between the same pair of affine spaces, the linear kernel of the difference between their associated linear maps constitutes an affine space.*)\nFact ker_sub_ahom_is_aspace (f g : ahom aT rT) :\n is_aspace (lker (ahval f - ahval g)).\n\nCanonical ker_sub_ahom_aspace f g := ASpace (ker_sub_ahom_is_aspace f g).\n\nEnd LRMorphism.\n\nCanonical fixedSpace_aspace aT (f : ahom aT aT) := [aspace of fixedSpace f].\n\nEnd AHom.\n\nArguments ahom_in [K aT rT].\n\n(*This notation represents the type of affine homomorphisms from a source affine space to a target affine space.*)\nNotation \"''AHom' ( aT , rT )\" := (ahom aT rT) : type_scope.\n(*This notation represents the type of affine endomorphisms of an affine space, which are affine homomorphisms from the space to itself.*)\nNotation \"''AEnd' ( aT )\" := (ahom aT aT) : type_scope.\n\nDelimit Scope lrfun_scope with AF.\nBind Scope lrfun_scope with ahom.\n\n(*This notation represents the identity affine homomorphism, which is the function that maps every point of an affine space to itself.*)\nNotation \"\\1\" := (@id_ahom _ _) : lrfun_scope.\n(*This notation denotes the composition of two affine homomorphisms. The resulting affine homomorphism is equivalent to applying the second homomorphism first and then applying the first homomorphism to the result.*)", - "character.inertia": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path.\nFrom mathcomp Require Import choice fintype div tuple finfun bigop prime order.\nFrom mathcomp Require Import ssralg ssrnum finset fingroup morphism perm.\nFrom mathcomp Require Import automorphism quotient action zmodp cyclic center.\nFrom mathcomp Require Import gproduct commutator gseries nilpotent pgroup.\nFrom mathcomp Require Import sylow maximal frobenius matrix mxalgebra.\nFrom mathcomp Require Import mxrepresentation vector algC classfun character.\nFrom mathcomp Require Import archimedean.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport Order.TTheory GroupScope GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\nReserved Notation \"''I[' phi ]\" (format \"''I[' phi ]\").\nReserved Notation \"''I_' G [ phi ]\" (G at level 2, format \"''I_' G [ phi ]\").\n\nSection ConjDef.\n\nVariables (gT : finGroupType) (B : {set gT}) (y : gT) (phi : 'CF(B)).\n(*This notation provides an abbreviation for the subgroup generated by a given set of group elements.*)\nLocal Notation G := <>.\n\n(*This fact establishes that a function defined by conjugating the argument of a class function by a given group element is itself a class function. The conjugation is performed by the inverse of the element if that element is in the normalizer of the subgroup; otherwise, the original class function is used unchanged.*)\nFact cfConjg_subproof :\n is_class_fun G [ffun x => phi (if y \\in 'N(G) then x ^ y^-1 else x)].\n\n(*This definition constructs the conjugated class function, which is formed by applying a given class function to an input that has been conjugated by a specified group element.*)\nDefinition cfConjg := Cfun 1 cfConjg_subproof.\n\nEnd ConjDef.\n\nPrenex Implicits cfConjg.\n(*This notation represents the conjugation of a class function by a group element.*)\nNotation \"f ^ y\" := (cfConjg y f) : cfun_scope.\n\nSection Conj.\n\nVariables (gT : finGroupType) (G : {group gT}).\nImplicit Type phi : 'CF(G).\n\n(*This lemma states that when an element belongs to the normalizer of a group, applying a class function conjugated by this element to a second element is equivalent to applying the original class function to the second element conjugated by the inverse of the first.*)\nLemma cfConjgE phi y x : y \\in 'N(G) -> (phi ^ y)%CF x = phi (x ^ y^-1)%g.\n\n(*This lemma states that for an element in the normalizer of a group, applying a class function conjugated by this element to a second element that has also been conjugated by the first element is equivalent to applying the original class function to the second element.*)\nLemma cfConjgEJ phi y x : y \\in 'N(G) -> (phi ^ y)%CF (x ^ y) = phi x.\n\n(*This lemma states that if a group element is not in the normalizer of a group, then the class function conjugated by that element is equal to the original class function.*)\nLemma cfConjgEout phi y : y \\notin 'N(G) -> (phi ^ y = phi)%CF.\n\n(*This lemma asserts that for an element in the normalizer of a group, conjugating a class function by this element is equivalent to applying the class function isomorphism induced by the conjugation automorphism on the group.*)\nLemma cfConjgEin phi y (nGy : y \\in 'N(G)) :\n (phi ^ y)%CF = cfIsom (norm_conj_isom nGy) phi.\n\n(*This lemma states that for any two elements in the normalizer of a group, conjugating a class function by their product is equivalent to successively conjugating the class function by each element.*)\nLemma cfConjgMnorm phi :\n {in 'N(G) &, forall y z, phi ^ (y * z) = (phi ^ y) ^ z}%CF.\n\n(*This lemma states that conjugating a class function by an element that belongs to the group itself results in the original class function.*)\nLemma cfConjg_id phi y : y \\in G -> (phi ^ y)%CF = phi.\n\n(*This lemma states that if a group is a normal subgroup of a larger group, then for any two elements in the larger group, conjugating a class function on the subgroup by their product is equivalent to successively conjugating the class function by each element.*)\nLemma cfConjgM L phi :\n G <| L -> {in L &, forall y z, phi ^ (y * z) = (phi ^ y) ^ z}%CF.\n\n(*This lemma states that conjugating a class function by the identity element of the group results in the original class function.*)\nLemma cfConjgJ1 phi : (phi ^ 1)%CF = phi.\n\n(*This lemma states that the operation of conjugating a class function by a group element is cancelled by the operation of conjugating by the inverse of that element.*)\nLemma cfConjgK y : cancel (cfConjg y) (cfConjg y^-1 : 'CF(G) -> 'CF(G)).\n\n(*This lemma states that the operation of conjugating a class function by the inverse of a group element is cancelled by the operation of conjugating by the original element.*)\nLemma cfConjgKV y : cancel (cfConjg y^-1) (cfConjg y : 'CF(G) -> 'CF(G)).\n\n(*This lemma states that the value of a conjugated class function at the group's identity element is equal to the value of the original class function at the identity element.*)\nLemma cfConjg1 phi y : (phi ^ y)%CF 1%g = phi 1%g.\n\n(*This fact establishes that for any given group element, the operation of conjugating class functions by that element is a linear transformation.*)\nFact cfConjg_is_linear y : linear (cfConjg y : 'CF(G) -> 'CF(G)).\n\nHB.instance Definition _ y := GRing.isSemilinear.Build _ _ _ _ (cfConjg y)\n (GRing.semilinear_linear (cfConjg_is_linear y)).\n\n(*This lemma states that if a group element belongs to the normalizer of a group, then conjugating the indicator class function of a subset by this element is equivalent to the indicator class function of the set obtained by conjugating the subset by the same element.*)\nLemma cfConjg_cfuniJ A y : y \\in 'N(G) -> ('1_A ^ y)%CF = '1_(A :^ y) :> 'CF(G).\n\n(*This lemma states that if a group element belongs to the normalizer of a subgroup, then conjugating the indicator class function of that subgroup by this element yields the same indicator class function.*)\nLemma cfConjg_cfuni A y : y \\in 'N(A) -> ('1_A ^ y)%CF = '1_A :> 'CF(G).\n\n(*This lemma states that conjugating the principal character of a group by any group element results in the principal character itself.*)\nLemma cfConjg_cfun1 y : (1 ^ y)%CF = 1 :> 'CF(G).\n\n(*This fact establishes that for any given group element, the operation of conjugating class functions preserves the monoid structure, meaning it maps the product of two class functions to the product of their conjugated versions and preserves the identity class function.*)\nFact cfConjg_is_monoid_morphism y : monoid_morphism (cfConjg y : _ -> 'CF(G)).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `cfConjg_is_monoid_morphism` instead\")]\n(*This definition states that the operation of conjugating a class function is a multiplicative morphism. It is deprecated and `cfConjg_is_monoid_morphism` should be used instead.*)\nDefinition cfConjg_is_multiplicative y :=\n (fun g => (g.2,g.1)) (cfConjg_is_monoid_morphism y).\n(*This lemma states that a conjugated class function is equal to the principal character if and only if the original class function is equal to the principal character.*)\nLemma cfConjg_eq1 phi y : ((phi ^ y)%CF == 1) = (phi == 1).\n\n(*This lemma states that applying a group automorphism to a conjugated class function yields the same result as first applying the automorphism to the original class function and then conjugating the result.*)\nLemma cfAutConjg phi u y : cfAut u (phi ^ y) = (cfAut u phi ^ y)%CF.\n\n(*This lemma states that the complex conjugate of a conjugated class function is equal to the conjugation of the complex conjugate of the original class function.*)\nLemma conj_cfConjg phi y : (phi ^ y)^*%CF = (phi^* ^ y)%CF.\n\n(*This lemma states that for an element in the normalizer of a group, the kernel of a class function conjugated by this element is equal to the set obtained by conjugating the kernel of the original class function by the same element.*)\nLemma cfker_conjg phi y : y \\in 'N(G) -> cfker (phi ^ y) = cfker phi :^ y.\n\n(*This lemma states that the determinant of a class function conjugated by a group element is equal to the result of conjugating the determinant of the original class function by the same element.*)\nLemma cfDetConjg phi y : cfDet (phi ^ y) = (cfDet phi ^ y)%CF.\n\nEnd Conj.\n\nSection Inertia.\n\nVariable gT : finGroupType.\n\n(*This definition introduces the inertia group of a class function with respect to a generating set. It is defined as the set of all elements in the normalizer of the generated subgroup that leave the class function unchanged when conjugating it.*)\nDefinition inertia (B : {set gT}) (phi : 'CF(B)) :=\n [set y in 'N(B) | (phi ^ y)%CF == phi].\n\n(*This notation provides a shorthand for the inertia group of a given class function.*)\nLocal Notation \"''I[' phi ]\" := (inertia phi) : group_scope.\n(*This notation denotes the inertia subgroup of a class function within a specific group, defined as the intersection of that group with the inertia group of the class function.*)\nLocal Notation \"''I_' G [ phi ]\" := (G%g :&: 'I[phi]) : group_scope.\n\n(*This fact establishes that the inertia set of a class function on a group is itself a subgroup.*)\nFact group_set_inertia (H : {group gT}) phi : group_set 'I[phi : 'CF(H)].\n\nCanonical inertia_group H phi := Group (@group_set_inertia H phi).\n\n(*This notation denotes the inertia group of a given class function. The inertia group consists of all elements in the normalizer of the class function's domain that leave the class function unchanged when acting by conjugation.*)\nLocal Notation \"''I[' phi ]\" := (inertia_group phi) : Group_scope.\n(*This notation represents the intersection of a given group with the inertia group of a class function. This is often called the inertia group of the class function within the larger group.*)\nLocal Notation \"''I_' G [ phi ]\" := (G :&: 'I[phi])%G : Group_scope.\n\nVariables G H : {group gT}.\nImplicit Type phi : 'CF(H).\n\n(*This lemma states that if an element belongs to the inertia group of a class function, then conjugating the class function by that element yields the original class function.*)\nLemma inertiaJ phi y : y \\in 'I[phi] -> (phi ^ y)%CF = phi.\n\n(*This lemma states that for any element in the inertia group of a class function, the value of the class function at a group element is equal to its value at the conjugate of that element by the inertia group member.*)\nLemma inertia_valJ phi x y : y \\in 'I[phi] -> phi (x ^ y)%g = phi x.\n\n(*This lemma states that the inertia group of a class function within a larger group is a subgroup of that larger group.*)\nLemma Inertia_sub phi : 'I_G[phi] \\subset G.\n\n(*This lemma states that the inertia group of a class function defined on a group is a subgroup of the normalizer of that group.*)\nLemma norm_inertia phi : 'I[phi] \\subset 'N(H).\n\n(*This lemma states that a group is a subgroup of the inertia group of any class function defined on it.*)\nLemma sub_inertia phi : H \\subset 'I[phi].\n\n(*This lemma states that a group is a normal subgroup of the inertia group of any class function defined on it.*)\nLemma normal_inertia phi : H <| 'I[phi].\n\n(*This lemma states that if a first group is a subgroup of a second group, then the first group is also a subgroup of the inertia group, within the second group, of any class function defined on the first group.*)\nLemma sub_Inertia phi : H \\subset G -> H \\subset 'I_G[phi].\n\n(*This lemma states that the inertia group of a class function on a subgroup, when considered within a larger group, is a subgroup of the normalizer of the original subgroup.*)\nLemma norm_Inertia phi : 'I_G[phi] \\subset 'N(H).\n\n(*This lemma states that if a first group is a subgroup of a second group, then the first group is a normal subgroup of the inertia group, within the second group, of any class function defined on the first group.*)\nLemma normal_Inertia phi : H \\subset G -> H <| 'I_G[phi].\n\n(*This lemma states that for a class function on a normal subgroup of a larger group, the equality between two of its conjugates by elements from the larger group is equivalent to the second conjugating element belonging to the right coset of the inertia group in the larger group determined by the first.*)\nLemma cfConjg_eqE phi :\n H <| G ->\n {in G &, forall y z, (phi ^ y == phi ^ z)%CF = (z \\in 'I_G[phi] :* y)}.\n\n(*This lemma states that the centralizer of a group is a subgroup of the inertia group of any class function defined on that group.*)\nLemma cent_sub_inertia phi : 'C(H) \\subset 'I[phi].\n\n(*This lemma states that the centralizer of a subgroup within a larger group is itself a subgroup of the inertia group of any class function, considered within that larger group.*)\nLemma cent_sub_Inertia phi : 'C_G(H) \\subset 'I_G[phi].\n\n(*This lemma states that for a class function defined on a subgroup, the center of the ambient group is a subgroup of the inertia group considered within that ambient group.*)\nLemma center_sub_Inertia phi : H \\subset G -> 'Z(G) \\subset 'I_G[phi].\n\n(*This lemma states that for an element in the normalizer of a group, the conjugate of the inertia group of a class function by that element is equal to the inertia group of the conjugated class function.*)\nLemma conjg_inertia phi y : y \\in 'N(H) -> 'I[phi] :^ y = 'I[phi ^ y].\n\n(*This lemma states that the inertia group of the zero class function on a group is equal to the normalizer of that group.*)\nLemma inertia0 : 'I[0 : 'CF(H)] = 'N(H).\n\n(*This lemma states that the intersection of the inertia groups of two class functions is a subgroup of the inertia group of their sum.*)\nLemma inertia_add phi psi : 'I[phi] :&: 'I[psi] \\subset 'I[phi + psi].\n\n(*This lemma states that for a family of class functions, the intersection of all their inertia groups with the normalizer of their domain group is a subgroup of the inertia group of their sum.*)\nLemma inertia_sum I r (P : pred I) (Phi : I -> 'CF(H)) :\n 'N(H) :&: \\bigcap_(i <- r | P i) 'I[Phi i]\n \\subset 'I[\\sum_(i <- r | P i) Phi i].\n\n(*This lemma states that the inertia group of a class function is a subgroup of the inertia group of any scalar multiple of that class function.*)\nLemma inertia_scale a phi : 'I[phi] \\subset 'I[a *: phi].\n\n(*This lemma states that if a class function is multiplied by a non-zero scalar, its inertia group is equal to the inertia group of the original class function.*)\nLemma inertia_scale_nz a phi : a != 0 -> 'I[a *: phi] = 'I[phi].\n\n(*This lemma states that the inertia group of the additive inverse of a class function is equal to the inertia group of the original class function.*)\nLemma inertia_opp phi : 'I[- phi] = 'I[phi].\n\n(*This lemma states that the inertia group of the principal character of a group is equal to the normalizer of that group.*)\nLemma inertia1 : 'I[1 : 'CF(H)] = 'N(H).\n\n(*This lemma states that for a normal subgroup, the inertia group of its principal character, when considered within the larger group, is equal to the larger group itself.*)\nLemma Inertia1 : H <| G -> 'I_G[1 : 'CF(H)] = G.\n\n(*This lemma states that the intersection of the inertia groups of two class functions is a subgroup of the inertia group of their product.*)\nLemma inertia_mul phi psi : 'I[phi] :&: 'I[psi] \\subset 'I[phi * psi].\n\n(*This lemma states that for a family of class functions, the intersection of all their inertia groups with the normalizer of their domain group is a subgroup of the inertia group of their product.*)\nLemma inertia_prod I r (P : pred I) (Phi : I -> 'CF(H)) :\n 'N(H) :&: \\bigcap_(i <- r | P i) 'I[Phi i]\n \\subset 'I[\\prod_(i <- r | P i) Phi i].\n\n(*This lemma states that if a character is injective when restricted to its domain group, then its inertia group is equal to the centralizer of that group.*)\nLemma inertia_injective (chi : 'CF(H)) :\n {in H &, injective chi} -> 'I[chi] = 'C(H).\n\n(*This lemma states that for a group of prime order, the inertia group of any of its non-principal irreducible characters is equal to the centralizer of that group.*)\nLemma inertia_irr_prime p i :\n #|H| = p -> prime p -> i != 0 -> 'I['chi[H]_i] = 'C(H).\n\n(*This lemma states that the inertia group of the principal irreducible character of a group is equal to the normalizer of that group.*)\nLemma inertia_irr0 : 'I['chi[H]_0] = 'N(H).\n\n(*This lemma states that the operation of conjugating a class function by a group element is an isometry, meaning it preserves the inner product between class functions.*)\nLemma cfConjg_iso y : isometry (cfConjg y : 'CF(H) -> 'CF(H)).\n\n(*This lemma states that the dot product of a class function psi restricted from a group G to a subgroup H, with a class function phi on H conjugated by an element y from G, is equal to the dot product of the restricted psi with the original phi.*)\nLemma cfdot_Res_conjg psi phi y :\n y \\in G -> '['Res[H, G] psi, phi ^ y] = '['Res[H] psi, phi].\n\n(*This lemma states that if a given class function is a character, then the class function resulting from conjugating it by a group element is also a character.*)\nLemma cfConjg_char (chi : 'CF(H)) y :\n chi \\is a character -> (chi ^ y)%CF \\is a character.\n\n(*This lemma states that if a given class function is a linear character, then the class function obtained by conjugating it with a group element is also a linear character.*)\nLemma cfConjg_lin_char (chi : 'CF(H)) y :\n chi \\is a linear_char -> (chi ^ y)%CF \\is a linear_char.\n\n(*This lemma states that if a given character is an irreducible character of a group, then its conjugate by any group element is also an irreducible character of that group.*)\nLemma cfConjg_irr y chi : chi \\in irr H -> (chi ^ y)%CF \\in irr H.\n\n(*This definition specifies a function that, given an index of an irreducible character and a group element, returns the index corresponding to the irreducible character obtained by conjugating the original character by the given element.*)\nDefinition conjg_Iirr i y := cfIirr ('chi[H]_i ^ y)%CF.\n\n(*This lemma states that the irreducible character corresponding to the index computed by applying the `conjg_Iirr` function to an initial index and a group element is equal to the class function obtained by conjugating the original irreducible character by that group element.*)\nLemma conjg_IirrE i y : 'chi_(conjg_Iirr i y) = ('chi_i ^ y)%CF.\n\n(*This lemma states that the function which maps a character index to the index of its conjugate by a group element, when composed with the function that maps an index to its conjugate by the inverse of that element, results in the identity function on indices.*)\nLemma conjg_IirrK y : cancel (conjg_Iirr^~ y) (conjg_Iirr^~ y^-1%g).\n\n(*This lemma states that the function which maps a character index to the index of its conjugate by the inverse of a group element, when composed with the function that maps an index to its conjugate by that element, results in the identity function on indices.*)\nLemma conjg_IirrKV y : cancel (conjg_Iirr^~ y^-1%g) (conjg_Iirr^~ y).\n\n(*This lemma states that for any given group element, the function that maps the index of an irreducible character to the index of its conjugate character is injective.*)\nLemma conjg_Iirr_inj y : injective (conjg_Iirr^~ y).\n\n(*This lemma states that the index of a conjugated irreducible character is equal to zero if and only if the index of the original irreducible character is zero.*)\nLemma conjg_Iirr_eq0 i y : (conjg_Iirr i y == 0) = (i == 0).\n\n(*This lemma states that applying the character index conjugation function to the index zero and any group element results in the index zero.*)\nLemma conjg_Iirr0 x : conjg_Iirr 0 x = 0.\n\n(*This lemma states that for a normal subgroup, the dot product of an irreducible character of that subgroup with its conjugate by an element from the larger group evaluates to one if the element belongs to the inertia subgroup of the character, and zero otherwise.*)\nLemma cfdot_irr_conjg i y :\n H <| G -> y \\in G -> '['chi_i, 'chi_i ^ y]_H = (y \\in 'I_G['chi_i])%:R.\n\n(*This definition constructs a finite sequence of class functions, representing the conjugacy class of a given class function within a group. This sequence is formed by conjugating the input class function by a set of representatives, one from each right coset of its inertia subgroup.*)\nDefinition cfclass (A : {set gT}) (phi : 'CF(A)) (B : {set gT}) :=\n [seq (phi ^ repr Tx)%CF | Tx in rcosets 'I_B[phi] B].\n\n(*This notation represents the conjugacy class of a class function within a group, which is a sequence of all distinct class functions obtained by conjugating the original one by elements of the group.*)\nLocal Notation \"phi ^: G\" := (cfclass phi G) : cfun_scope.\n\n(*This lemma states that the number of distinct class functions in the conjugacy class of an irreducible character is equal to the index of the character's inertia subgroup within the larger group.*)\nLemma size_cfclass i : size ('chi[H]_i ^: G)%CF = #|G : 'I_G['chi_i]|.\n\n(*This lemma states that a given class function is a member of the conjugacy class of another class function if and only if the first can be obtained by conjugating the second by some element of the group.*)\nLemma cfclassP (A : {group gT}) phi psi :\n reflect (exists2 y, y \\in A & psi = phi ^ y)%CF (psi \\in phi ^: A)%CF.\n\n(*This lemma asserts that the conjugacy class of a class function of a subgroup, when computed with respect to a group, is the same, up to reordering, as the conjugacy class computed with respect to the normalizer of the subgroup in the group.*)\nLemma cfclassInorm phi : (phi ^: 'N_G(H) =i phi ^: G)%CF.\n\n(*This lemma states that any class function is a member of its own conjugacy class within a group.*)\nLemma cfclass_refl phi : phi \\in (phi ^: G)%CF.\n\n(*This lemma states that if a class function is in the conjugacy class of another class function, then the conjugacy classes of both functions are equal up to reordering.*)\nLemma cfclass_transr phi psi :\n (psi \\in phi ^: G)%CF -> (phi ^: G =i psi ^: G)%CF.\n\n(*This lemma establishes the symmetric property of conjugacy for class functions, stating that a class function `psi` is in the conjugacy class of `phi` if and only if `phi` is in the conjugacy class of `psi`.*)\nLemma cfclass_sym phi psi : (psi \\in phi ^: G)%CF = (phi \\in psi ^: G)%CF.\n\n(*This lemma states that for a class function defined on a normal subgroup, the finite sequence representing its conjugacy class in the larger group contains no duplicate elements.*)\nLemma cfclass_uniq phi : H <| G -> uniq (phi ^: G)%CF.\n\n(*This lemma states that if a group is entirely contained within the inertia subgroup of a class function, then the conjugacy class of that function consists of a singleton sequence containing only the function itself.*)\nLemma cfclass_invariant phi : G \\subset 'I[phi] -> (phi ^: G)%CF = phi.\n\n(*This lemma states that for a normal subgroup, the conjugacy class of the trivial character is a singleton sequence containing only the trivial character itself.*)\nLemma cfclass1 : H <| G -> (1 ^: G)%CF = [:: 1 : 'CF(H)].\n\n(*This definition computes a finite sequence of indices of irreducible characters. It is formed by taking an initial character index and applying the conjugation map for each element in a given finite sequence of group elements.*)\nDefinition cfclass_Iirr (A : {set gT}) i := conjg_Iirr i @: A.\n\n(*This lemma establishes an equivalence: an index is a member of the sequence of indices representing a character conjugacy class if and only if the irreducible character corresponding to that index is a member of the sequence of class functions representing that same conjugacy class.*)\nLemma cfclass_IirrE i j :\n (j \\in cfclass_Iirr G i) = ('chi_j \\in 'chi_i ^: G)%CF.\n\n(*This lemma states that the sequence of indices representing the conjugacy class of an irreducible character is equal to that of another character if and only if the second character's index is a member of the first character's index conjugacy class.*)\nLemma eq_cfclass_IirrE i j :\n (cfclass_Iirr G j == cfclass_Iirr G i) = (j \\in cfclass_Iirr G i).\n\n(*This lemma states that for a normal subgroup, the finite sequence of irreducible characters obtained by mapping indices from a character's index-conjugacy class is a permutation of the sequence of class functions forming the character's conjugacy class.*)\nLemma im_cfclass_Iirr i :\n H <| G -> perm_eq [seq 'chi_j | j in cfclass_Iirr G i] ('chi_i ^: G)%CF.\n\n(*This lemma states that for a normal subgroup, the number of indices in the sequence representing the conjugacy class of an irreducible character's index is equal to the index of that character's inertia subgroup.*)\nLemma card_cfclass_Iirr i : H <| G -> #|cfclass_Iirr G i| = #|G : 'I_G['chi_i]|.\n\n(*This lemma provides a re-indexing rule for summations over a conjugacy class of characters. It states that applying a commutative operation to the values of a function over all characters in a given conjugacy class is equivalent to applying the same operation to the values of the function over all irreducible characters whose indices are in the corresponding index-conjugacy class.*)\nLemma reindex_cfclass R idx (op : Monoid.com_law idx) (F : 'CF(H) -> R) i :\n H <| G ->\n \\big[op/idx]_(chi <- ('chi_i ^: G)%CF) F chi\n = \\big[op/idx]_(j | 'chi_j \\in ('chi_i ^: G)%CF) F 'chi_j.\n\n(*This lemma relates the restriction and induction of class functions, likely establishing a property such as Frobenius reciprocity for characters.*)\nLemma cfResInd j:\n H <| G ->\n 'Res[H] ('Ind[G] 'chi_j) = #|H|%:R^-1 *: (\\sum_(y in G) 'chi_j ^ y)%CF.\n\n(*This lemma states that when a group character is restricted to a normal subgroup, the resulting character is equal to the sum over the orbit of one of its irreducible constituents, where this sum is scaled by the multiplicity of that constituent in the restricted character.*)\nLemma Clifford_Res_sum_cfclass i j :\n H <| G -> j \\in irr_constt ('Res[H, G] 'chi_i) ->\n 'Res[H] 'chi_i =\n '['Res[H] 'chi_i, 'chi_j] *: (\\sum_(chi <- ('chi_j ^: G)%CF) chi).\n\n(*This lemma states that if a character of a normal subgroup is invariant under the action of the larger group, then inducing this character to the larger group and subsequently restricting it back to the subgroup yields the original character scaled by the index of the subgroup in the group.*)\nLemma cfRes_Ind_invariant psi :\n H <| G -> G \\subset 'I[psi] -> 'Res ('Ind[G, H] psi) = #|G : H|%:R *: psi.\n\n(*This lemma states that if the restriction of an irreducible group character to a normal subgroup contains the trivial character as a constituent, then the normal subgroup must be a subset of the character kernel of the original irreducible character.*)\nCorollary constt0_Res_cfker i :\n H <| G -> 0 \\in irr_constt ('Res[H] 'chi[G]_i) -> H \\subset cfker 'chi[G]_i.\n\n(*This lemma states that if an irreducible character of a normal subgroup is a constituent of the restriction of an irreducible character of a larger group, then the degree of the subgroup's character must divide the degree of the larger group's character.*)\nLemma dvdn_constt_Res1_irr1 i j :\n H <| G -> j \\in irr_constt ('Res[H, G] 'chi_i) ->\n exists n, 'chi_i 1%g = n%:R * 'chi_j 1%g.\n\n(*This lemma states that for a normal subgroup, any two of its characters that are conjugate under the action of the larger group will produce the same induced character in the larger group.*)\nLemma cfclass_Ind phi psi :\n H <| G -> psi \\in (phi ^: G)%CF -> 'Ind[G] phi = 'Ind[G] psi.\n\nEnd Inertia.\n\nArguments inertia {gT B%_g} phi%_CF.\nArguments cfclass {gT A%_g} phi%_CF B%_g.\nArguments conjg_Iirr_inj {gT H} y [i1 i2] : rename.\n\n(*This notation represents the inertia group of a given group character, which is the subgroup consisting of all elements that fix the character under the conjugation action.*)\nNotation \"''I[' phi ] \" := (inertia phi) : group_scope.\n(*This notation designates the set of constituents of a given class function. A character is considered a constituent if its inner product with the class function is a non-zero value.*)\nNotation \"''I[' phi ] \" := (inertia_group phi) : Group_scope.\n(*This notation designates the set of irreducible characters of a given group that are also constituents of a given class function. A character is considered a constituent if its inner product with the class function is a non-zero value.*)\nNotation \"''I_' G [ phi ] \" := (G%g :&: 'I[phi]) : group_scope.\n(*This notation denotes the inertia group of a given class function within a specified group. The inertia group is the subgroup composed of all elements from the specified group such that conjugating the class function by any of these elements results in the original class function.*)\nNotation \"''I_' G [ phi ] \" := (G :&: 'I[phi])%G : Group_scope.\n(*A notation representing the set of all class functions obtained by conjugating a given class function by each element of a specified group.*)\nNotation \"phi ^: G\" := (cfclass phi G) : cfun_scope.\n\nSection ConjRestrict.\n\nVariables (gT : finGroupType) (G H K : {group gT}).\n\n(*This lemma states that for a class function, conjugating its restriction to a subgroup is equivalent to restricting its conjugate, provided the conjugating element normalizes both the domain group and the subgroup.*)\nLemma cfConjgRes_norm phi y :\n y \\in 'N(K) -> y \\in 'N(H) -> ('Res[K, H] phi ^ y)%CF = 'Res (phi ^ y)%CF.\n\n(*This lemma states that for a class function, conjugating its restriction to a subgroup is equivalent to restricting its conjugate, provided both the domain group and the subgroup are normal in a larger ambient group, and the conjugating element belongs to that ambient group.*)\nLemma cfConjgRes phi y :\n H <| G -> K <| G -> y \\in G -> ('Res[K, H] phi ^ y)%CF = 'Res (phi ^ y)%CF.\n\n(*This lemma states that the inertia subgroup of a class function is contained within the inertia subgroup of its restriction to a smaller domain, provided the group defining the inertia subgroup normalizes the original domain of the class function.*)\nLemma sub_inertia_Res phi :\n G \\subset 'N(K) -> 'I_G[phi] \\subset 'I_G['Res[K, H] phi].\n\n(*This lemma states that for a class function, conjugating its induction from a subgroup to a larger group is equivalent to inducing its conjugate, provided the conjugating element normalizes both the subgroup and the larger group.*)\nLemma cfConjgInd_norm phi y :\n y \\in 'N(K) -> y \\in 'N(H) -> ('Ind[H, K] phi ^ y)%CF = 'Ind (phi ^ y)%CF.\n\n(*This lemma states that for a class function, conjugating its induction from a subgroup to a larger group is equivalent to inducing its conjugate, provided both the subgroup and the larger group are normal in an ambient group, and the conjugating element belongs to that ambient group.*)\nLemma cfConjgInd phi y :\n H <| G -> K <| G -> y \\in G -> ('Ind[H, K] phi ^ y)%CF = 'Ind (phi ^ y)%CF.\n\n(*This lemma states that the inertia subgroup of a class function is contained within the inertia subgroup of its induction to a larger group, provided the group defining the inertia subgroup normalizes the original domain of the class function.*)\nLemma sub_inertia_Ind phi :\n G \\subset 'N(H) -> 'I_G[phi] \\subset 'I_G['Ind[H, K] phi].\n\nEnd ConjRestrict.\n\nSection MoreInertia.\n\nVariables (gT : finGroupType) (G H : {group gT}) (i : Iirr H).\n(*This definition establishes an alias for the inertia subgroup of a given irreducible character within a larger ambient group.*)\nLet T := 'I_G['chi_i].\n\n(*This lemma states that the inertia subgroup of an irreducible character, when computed within its own inertia subgroup, is the inertia subgroup itself.*)\nLemma inertia_id : 'I_T['chi_i] = T. \n\n(*This lemma states that the set of all conjugates of an irreducible character under the action of its own inertia subgroup contains only the original character itself.*)\nLemma cfclass_inertia : ('chi[H]_i ^: T)%CF = [:: 'chi_i].\n\nEnd MoreInertia.\n\nSection ConjMorph.\n\nVariables (aT rT : finGroupType) (D G H : {group aT}) (f : {morphism D >-> rT}).\n\n(*This lemma states that conjugating a class function that has been pulled back along a group morphism is equivalent to pulling back the class function that has been conjugated by the image of the conjugating element under the morphism, provided the element normalizes the domain of the pullback.*)\nLemma cfConjgMorph (phi : 'CF(f @* H)) y :\n y \\in D -> y \\in 'N(H) -> (cfMorph phi ^ y)%CF = cfMorph (phi ^ f y).\n\n(*This lemma states that the inertia subgroup of a class function pulled back along a group morphism is equal to the intersection of the domain group and the preimage of the inertia subgroup of the original class function in the image group.*)\nLemma inertia_morph_pre (phi : 'CF(f @* H)) :\n H <| G -> G \\subset D -> 'I_G[cfMorph phi] = G :&: f @*^-1 'I_(f @* G)[phi].\n\n(*This lemma states that the image of the inertia subgroup of a pulled-back class function under the group morphism is equal to the inertia subgroup of the original class function in the image group.*)\nLemma inertia_morph_im (phi : 'CF(f @* H)) :\n H <| G -> G \\subset D -> f @* 'I_G[cfMorph phi] = 'I_(f @* G)[phi].\n\nVariables (R S : {group rT}).\nVariables (g : {morphism G >-> rT}) (h : {morphism H >-> rT}).\nHypotheses (isoG : isom G R g) (isoH : isom H S h).\nHypotheses (eq_hg : {in H, h =1 g}) (sHG : H \\subset G).\n\n(*This lemma states that pushing forward a class function along a group isomorphism and then conjugating it by the image of an element is equivalent to first conjugating the class function by the element and then pushing it forward along the isomorphism.*)\nLemma cfConjgIsom phi y :\n y \\in G -> y \\in 'N(H) -> (cfIsom isoH phi ^ g y)%CF = cfIsom isoH (phi ^ y).\n\n(*This lemma states that the inertia subgroup of a class function that has been pushed forward along an isomorphism is the image of the original class function's inertia subgroup under that isomorphism.*)\nLemma inertia_isom phi : 'I_R[cfIsom isoH phi] = g @* 'I_G[phi].\n\nEnd ConjMorph.\n\nSection ConjQuotient.\n\nVariables gT : finGroupType.\nImplicit Types G H K : {group gT}.\n\n(*This lemma states that conjugating a class function that has been lifted from a quotient group is equivalent to lifting the class function that has been conjugated by the corresponding coset, provided the conjugating element normalizes both the group and the normal subgroup used for the quotient.*)\nLemma cfConjgMod_norm H K (phi : 'CF(H / K)) y :\n y \\in 'N(K) -> y \\in 'N(H) -> ((phi %% K) ^ y)%CF = (phi ^ coset K y %% K)%CF.\n\n(*This lemma states that conjugating a class function lifted from a quotient group by an element of an ambient group is equivalent to lifting the class function that has been conjugated by the corresponding coset, provided both the group and the normal subgroup are themselves normal in the ambient group.*)\nLemma cfConjgMod G H K (phi : 'CF(H / K)) y :\n H <| G -> K <| G -> y \\in G ->\n ((phi %% K) ^ y)%CF = (phi ^ coset K y %% K)%CF.\n\n(*This lemma states that conjugating a class function on a quotient group by a coset is equivalent to first conjugating the original class function by a representative of that coset and then projecting the result to the quotient group, provided the representative normalizes both the original group and the subgroup.*)\nLemma cfConjgQuo_norm H K (phi : 'CF(H)) y :\n y \\in 'N(K) -> y \\in 'N(H) -> ((phi / K) ^ coset K y)%CF = (phi ^ y / K)%CF.\n\n(*This lemma states that conjugating a class function on a quotient group by a coset is equivalent to first conjugating the original class function by an element of an ambient group representing that coset and then projecting to the quotient group, provided all relevant groups are normal in the ambient group.*)\nLemma cfConjgQuo G H K (phi : 'CF(H)) y :\n H <| G -> K <| G -> y \\in G ->\n ((phi / K) ^ coset K y)%CF = (phi ^ y / K)%CF.\n\n(*This lemma states that the inertia subgroup of a class function lifted from a quotient group is the intersection of the ambient group and the preimage, under the canonical projection, of the inertia subgroup of the original class function in the corresponding quotient of the ambient group.*)\nLemma inertia_mod_pre G H K (phi : 'CF(H / K)) :\n H <| G -> K <| G -> 'I_G[phi %% K] = G :&: coset K @*^-1 'I_(G / K)[phi].\n\n(*This lemma states that the quotient of the inertia subgroup of a lifted class function is equal to the inertia subgroup of the original class function in the corresponding quotient group.*)\nLemma inertia_mod_quo G H K (phi : 'CF(H / K)) :\n H <| G -> K <| G -> ('I_G[phi %% K] / K)%g = 'I_(G / K)[phi].\n\n(*This lemma states that the inertia subgroup of a class function projected to a quotient group is equal to the projection of the inertia subgroup of the original class function, provided the subgroup used for the quotient is contained in the kernel of the class function.*)\nLemma inertia_quo G H K (phi : 'CF(H)) :\n H <| G -> K <| G -> K \\subset cfker phi ->\n 'I_(G / K)[phi / K] = ('I_G[phi] / K)%g.\n\nEnd ConjQuotient.\n\nSection InertiaSdprod.\n\nVariables (gT : finGroupType) (K H G : {group gT}).\n\nHypothesis defG : K ><| H = G.\n\n(*This lemma states that conjugating a class function that has been lifted from a factor group to a semidirect product is equivalent to lifting the conjugated class function, provided the conjugating element normalizes both factor groups.*)\nLemma cfConjgSdprod phi y :\n y \\in 'N(K) -> y \\in 'N(H) ->\n (cfSdprod defG phi ^ y = cfSdprod defG (phi ^ y))%CF.\n\n(*This lemma states that the inertia subgroup of a class function lifted from a factor group to a semidirect product is the same as the inertia subgroup of the original class function, when both are computed within a group that normalizes both factors of the semidirect product.*)\nLemma inertia_sdprod (L : {group gT}) phi :\n L \\subset 'N(K) -> L \\subset 'N(H) -> 'I_L[cfSdprod defG phi] = 'I_L[phi].\n\nEnd InertiaSdprod.\n\nSection InertiaDprod.\n\nVariables (gT : finGroupType) (G K H : {group gT}).\nImplicit Type L : {group gT}.\nHypothesis KxH : K \\x H = G.\n\n(*This lemma states that conjugating a class function that has been lifted from the left factor of a direct product is equivalent to lifting the conjugated class function, provided the conjugating element normalizes both factor groups.*)\nLemma cfConjgDprodl phi y :\n y \\in 'N(K) -> y \\in 'N(H) ->\n (cfDprodl KxH phi ^ y = cfDprodl KxH (phi ^ y))%CF.\n\n(*This lemma states that conjugating a class function that has been lifted from the right factor of a direct product is equivalent to lifting the conjugated class function, provided the conjugating element normalizes both factor groups.*)\nLemma cfConjgDprodr psi y :\n y \\in 'N(K) -> y \\in 'N(H) ->\n (cfDprodr KxH psi ^ y = cfDprodr KxH (psi ^ y))%CF.\n\n(*This lemma states that conjugating the tensor product of two class functions defined on the factors of a direct product is equivalent to taking the tensor product of the individually conjugated class functions, provided the conjugating element normalizes both factor groups.*)\nLemma cfConjgDprod phi psi y :\n y \\in 'N(K) -> y \\in 'N(H) ->\n (cfDprod KxH phi psi ^ y = cfDprod KxH (phi ^ y) (psi ^ y))%CF.\n\n(*This lemma states that the inertia subgroup of a class function lifted from the left factor of a direct product is the same as the inertia subgroup of the original class function, when both are computed within a group that normalizes both factors.*)\nLemma inertia_dprodl L phi :\n L \\subset 'N(K) -> L \\subset 'N(H) -> 'I_L[cfDprodl KxH phi] = 'I_L[phi].\n\n(*This lemma states that the inertia subgroup of a class function lifted from the right factor of a direct product is the same as the inertia subgroup of the original class function, when both are computed within a group that normalizes both factors.*)\nLemma inertia_dprodr L psi :\n L \\subset 'N(K) -> L \\subset 'N(H) -> 'I_L[cfDprodr KxH psi] = 'I_L[psi].\n\n(*This lemma states that for two class functions from groups K and H respectively, the inertia group within a subgroup L of their Deligne product character is the intersection of the inertia groups of the individual class functions. This holds under the conditions that L is contained in the normalizer of both K and H, and that the class functions do not evaluate to zero at the identity element.*)\nLemma inertia_dprod L (phi : 'CF(K)) (psi : 'CF(H)) :\n L \\subset 'N(K) -> L \\subset 'N(H) -> phi 1%g != 0 -> psi 1%g != 0 ->\n 'I_L[cfDprod KxH phi psi] = 'I_L[phi] :&: 'I_L[psi].\n\n(*This lemma states that for two irreducible characters, one from a group K and one from a group H, the inertia group of their Deligne product character within a subgroup L is the intersection of their individual inertia groups within L, assuming L is contained in the normalizers of both K and H.*)\nLemma inertia_dprod_irr L i j :\n L \\subset 'N(K) -> L \\subset 'N(H) ->\n 'I_L[cfDprod KxH 'chi_i 'chi_j] = 'I_L['chi_i] :&: 'I_L['chi_j].\n\nEnd InertiaDprod.\n\nSection InertiaBigdprod.\n\nVariables (gT : finGroupType) (I : finType) (P : pred I).\nVariables (A : I -> {group gT}) (G : {group gT}).\nImplicit Type L : {group gT}.\nHypothesis defG : \\big[dprod/1%g]_(i | P i) A i = G.\n\nSection ConjBig.\n\nVariable y : gT.\nHypothesis nAy: forall i, P i -> y \\in 'N(A i).\n\n(*This lemma states that the conjugation of an embedded class function from a component group by a group element is equivalent to embedding the class function after it has been conjugated by that same element. This equivalence holds if the conjugating element is in the normalizer of the component group.*)\nLemma cfConjgBigdprodi i (phi : 'CF(A i)) :\n (cfBigdprodi defG phi ^ y = cfBigdprodi defG (phi ^ y))%CF.\n\n(*This lemma states that conjugating a class function, which is defined as a product over a family of class functions, by a group element yields the same result as forming the product from the family of individually conjugated class functions. This holds when the conjugating element normalizes every group in the family.*)\nLemma cfConjgBigdprod phi :\n (cfBigdprod defG phi ^ y = cfBigdprod defG (fun i => phi i ^ y))%CF.\n\nEnd ConjBig.\n\nSection InertiaBig.\n\nVariable L : {group gT}.\nHypothesis nAL : forall i, P i -> L \\subset 'N(A i).\n\n(*This lemma states that the inertia group within a subgroup L of a class function lifted from a component group to a direct product group is identical to the inertia group of the original class function within L, provided that L is contained in the normalizer of the component group.*)\nLemma inertia_bigdprodi i (phi : 'CF(A i)) :\n P i -> 'I_L[cfBigdprodi defG phi] = 'I_L[phi].\n\n(*This lemma states that the inertia group within a subgroup L of a class function formed as a product over a family of class functions is the intersection of L with the intersection of all individual inertia groups from the family. This requires that the product class function is non-zero at the identity element and that L is contained in the normalizer of each component group.*)\nLemma inertia_bigdprod phi (Phi := cfBigdprod defG phi) :\n Phi 1%g != 0 -> 'I_L[Phi] = L :&: \\bigcap_(i | P i) 'I_L[phi i].\n\n(*This lemma states that for a family of irreducible characters, the inertia group within a subgroup L of the class function formed by their product is the intersection of L with the intersection of the individual inertia groups of each character in the family. This holds when L is contained in the normalizer of each component group.*)\nLemma inertia_bigdprod_irr Iphi (phi := fun i => 'chi_(Iphi i)) :\n 'I_L[cfBigdprod defG phi] = L :&: \\bigcap_(i | P i) 'I_L[phi i].\n\nEnd InertiaBig.\n\nEnd InertiaBigdprod.\n\nSection ConsttInertiaBijection.\n\nVariables (gT : finGroupType) (H G : {group gT}) (t : Iirr H).\nHypothesis nsHG : H <| G.\n\n(*This notation defines theta as an alias for the irreducible character associated with a given irreducible representation of a group.*)\nLocal Notation theta := 'chi_t.\n(*This notation defines T as a shorthand for the inertia subgroup within a group G, corresponding to a character of a normal subgroup H. This subgroup consists of all elements of G that fix the character under conjugation.*)\nLocal Notation T := 'I_G[theta]%G.\n(*This notation defines 'T' as a formatted representation of the inertia subgroup T, specifically referring to the underlying set of group elements rather than the group structure itself.*)\nLocal Notation \"` 'T'\" := 'I_(gval G)[theta] (format \"` 'T'\") : group_scope.\n\n(*This definition assigns `calA` to the set of irreducible characters of the inertia subgroup `T` that correspond, via Clifford theory, to the character `theta` from the normal subgroup `H`.*)\nLet calA := irr_constt ('Ind[T] theta).\n(*This definition assigns `calB` to be the set of irreducible constituents of the character that results from inducing the character `theta` on the normal subgroup `H` up to the larger group `G`.*)\nLet calB := irr_constt ('Ind[G] theta).\n(*This notation defines `AtoB` as a shorthand for the function that performs character induction of an irreducible character from a subgroup to a larger ambient group.*)\nLocal Notation AtoB := (Ind_Iirr G).\n\n(*This theorem, known as the Clifford correspondence, establishes a bijection between two sets of irreducible characters. It states that inducing characters from the inertia subgroup to the main group maps a set of characters `calA` bijectively onto another set `calB`. The theorem also asserts that inducing a character from `calA` yields an irreducible character, that restricting this induced character back to the inertia subgroup recovers the original character as a unique constituent, and that a form of Frobenius reciprocity holds for the involved characters.*)\nTheorem constt_Inertia_bijection :\n [/\\ {in calA, forall s, 'Ind[G] 'chi_s \\in irr G},\n {in calA &, injective (Ind_Iirr G)},\n Ind_Iirr G @: calA =i calB,\n {in calA, forall s (psi := 'chi_s) (chi := 'Ind[G] psi),\n [predI irr_constt ('Res chi) & calA] =i pred1 s}\n & {in calA, forall s (psi := 'chi_s) (chi := 'Ind[G] psi),\n '['Res psi, theta] = '['Res chi, theta]}].\n\nEnd ConsttInertiaBijection.\n\nSection ExtendInvariantIrr.\n\nVariable gT : finGroupType.\nImplicit Types G H K L M N : {group gT}.\n\nSection ConsttIndExtendible.\n\nVariables (G N : {group gT}) (t : Iirr N) (c : Iirr G).\n(*A local alias for a specified irreducible character, typically associated with a subgroup for use in constructions like character induction and restriction.*)\nLet theta := 'chi_t.\n(*A local alias for a specified irreducible character of a group, serving as a base character for constructing new characters.*)\nLet chi := 'chi_c.\n\n(*This definition specifies a function that constructs a new irreducible character of a group by taking an irreducible character of a quotient group, lifting it to the full group, and multiplying it with a pre-existing base character.*)\nDefinition mul_Iirr b := cfIirr ('chi_b * chi).\n(*This definition specifies a function that constructs a new irreducible character of a group from an irreducible character of a quotient group by first applying a canonical transformation and then multiplying the result with a fixed base character.*)\nDefinition mul_mod_Iirr (b : Iirr (G / N)) := mul_Iirr (mod_Iirr b).\n\nHypotheses (nsNG : N <| G) (cNt : 'Res[N] chi = theta).\n(*A local definition establishing that one group is a subgroup of another, which is a direct consequence of it being a normal subgroup.*)\nLet sNG : N \\subset G. \n(*A local definition establishing that a group is contained within the normalizer of one of its normal subgroups, a property that holds by definition of a normal subgroup.*)\nLet nNG : G \\subset 'N(N). \n\n(*This lemma states that an irreducible character of a normal subgroup is invariant under the action of the entire group if it is the restriction of a character from that group.*)\nLemma extendible_irr_invariant : G \\subset 'I[theta].\n\n(*A local alias for the proof asserting that an extendible irreducible character of a normal subgroup is invariant under the action of the full group.*)\nLet IGtheta := extendible_irr_invariant.\n\n(*This theorem describes the decomposition of an induced character that arises from the product of two characters of a normal subgroup. It asserts that if one character is invariant under the action of the larger group and the other is the restriction of an irreducible character of that larger group, then there is a bijective correspondence between the irreducible constituents of the induced product character and those of the induced invariant character. The theorem also provides an explicit formula for this decomposition.*)\nTheorem constt_Ind_mul_ext f (phi := 'chi_f) (psi := phi * theta) :\n G \\subset 'I[phi] -> psi \\in irr N ->\n let calS := irr_constt ('Ind phi) in\n [/\\ {in calS, forall b, 'chi_b * chi \\in irr G},\n {in calS &, injective mul_Iirr},\n irr_constt ('Ind psi) =i [seq mul_Iirr b | b in calS]\n & 'Ind psi = \\sum_(b in calS) '['Ind phi, 'chi_b] *: 'chi_(mul_Iirr b)].\n\n(*This corollary specifies the structure of irreducible characters of a group that contain a given group-invariant irreducible character of a normal subgroup upon restriction. It asserts that these characters are precisely the products of a fixed extension of the subgroup character with the irreducible characters of the corresponding quotient group. The result establishes a bijective correspondence and provides the decomposition formula for the induced character.*)\nCorollary constt_Ind_ext :\n [/\\ forall b : Iirr (G / N), 'chi_(mod_Iirr b) * chi \\in irr G,\n injective mul_mod_Iirr,\n irr_constt ('Ind theta) =i codom mul_mod_Iirr\n & 'Ind theta = \\sum_b 'chi_b 1%g *: 'chi_(mul_mod_Iirr b)].\n\nEnd ConsttIndExtendible.\n\n(*This theorem presents a case analysis for the behavior of a group-invariant irreducible character when restricted to a normal subgroup, under the condition that the quotient group is an abelian chief factor. The theorem asserts that the restricted character must satisfy one of three properties: it remains irreducible, it becomes a specific multiple of a single irreducible character, or it decomposes into a sum of distinct irreducible characters.*)\nTheorem invariant_chief_irr_cases G K L s (theta := 'chi[K]_s) :\n chief_factor G L K -> abelian (K / L) -> G \\subset 'I[theta] ->\n let t := #|K : L| in\n [\\/ 'Res[L] theta \\in irr L,\n exists2 e, exists p, 'Res[L] theta = e%:R *: 'chi_p & (e ^ 2)%N = t\n | exists2 p, injective p & 'Res[L] theta = \\sum_(i < t) 'chi_(p i)].\n\n(*This corollary describes the behavior of an irreducible character of a group when restricted to a normal subgroup of prime index. It asserts that the resulting character on the subgroup is either itself irreducible or decomposes into a sum of distinct irreducible characters.*)\nCorollary cfRes_prime_irr_cases G N s p (chi := 'chi[G]_s) :\n N <| G -> #|G : N| = p -> prime p ->\n [\\/ 'Res[N] chi \\in irr N\n | exists2 c, injective c & 'Res[N] chi = \\sum_(i < p) 'chi_(c i)].\n\n(*This corollary asserts that a group-invariant irreducible character of a normal subgroup is guaranteed to be extendible to the full group if the subgroup has a prime index.*)\nCorollary prime_invariant_irr_extendible G N s p :\n N <| G -> #|G : N| = p -> prime p -> G \\subset 'I['chi_s] ->\n {t | 'Res[N, G] 'chi_t = 'chi_s}.\n\n(*This lemma establishes the existence and uniqueness of an extension of an irreducible character from a normal subgroup to the full group with a prescribed character determinant. This holds under the condition that the index of the subgroup is coprime to the degree of the character and that the prescribed determinant is itself an extension of the original character's determinant.*)\nLemma extend_to_cfdet G N s c0 u :\n let theta := 'chi_s in let lambda := cfDet theta in let mu := 'chi_u in\n N <| G -> coprime #|G : N| (Num.truncn (theta 1%g)) ->\n 'Res[N, G] 'chi_c0 = theta -> 'Res[N, G] mu = lambda ->\n exists2 c, 'Res 'chi_c = theta /\\ cfDet 'chi_c = mu\n & forall c1, 'Res 'chi_c1 = theta -> cfDet 'chi_c1 = mu -> c1 = c.\n\n(*This theorem provides a criterion for extending a group-invariant irreducible character from a normal subgroup to the full group. It asserts that, when the quotient group is solvable and a certain coprime condition on the character degree holds, the character is extendible if and only if its determinant character is extendible.*)\nTheorem solvable_irr_extendible_from_det G N s (theta := 'chi[N]_s) :\n N <| G -> solvable (G / N) ->\n G \\subset 'I[theta] -> coprime #|G : N| (Num.truncn (theta 1%g)) ->\n [exists c, 'Res 'chi[G]_c == theta]\n = [exists u, 'Res 'chi[G]_u == cfDet theta].\n\n(*This theorem establishes a local-to-global principle for extending a group-invariant linear character from a normal subgroup. It asserts that the character can be extended to the whole group if, for each prime dividing the character's order, it can be extended to certain intermediate subgroups related to the Sylow structure of the quotient group.*)\nTheorem extend_linear_char_from_Sylow G N (lambda : 'CF(N)) :\n N <| G -> lambda \\is a linear_char -> G \\subset 'I[lambda] ->\n (forall p, p \\in \\pi('o(lambda)%CF) ->\n exists2 Hp : {group gT},\n [/\\ N \\subset Hp, Hp \\subset G & p.-Sylow(G / N) (Hp / N)%g]\n & exists u, 'Res 'chi[Hp]_u = lambda) ->\n exists u, 'Res[N, G] 'chi_u = lambda.\n\n(*This corollary guarantees the existence and uniqueness of an extension for a group-invariant linear character from a normal subgroup to the full group. It asserts that if the order of the character is coprime to the index of the subgroup, then a unique extension exists which also has the same order as the original character.*)\nCorollary extend_coprime_linear_char G N (lambda : 'CF(N)) :\n N <| G -> lambda \\is a linear_char -> G \\subset 'I[lambda] ->\n coprime #|G : N| 'o(lambda)%CF ->\n exists u, [/\\ 'Res 'chi[G]_u = lambda, 'o('chi_u)%CF = 'o(lambda)%CF\n & forall v,\n 'Res 'chi_v = lambda -> coprime #|G : N| 'o('chi_v)%CF ->\n v = u].\n\n(*This corollary asserts the existence and uniqueness of an extension for an irreducible character of a normal subgroup. Specifically, if a finite group has a normal subgroup with a solvable quotient group, and an irreducible character of that subgroup is invariant under the larger group's conjugation, a unique extension of this character to an irreducible character of the larger group exists. This is guaranteed if the subgroup's index is coprime to the product of the character's order and degree. The extended character preserves the original order and is unique among all extensions whose order is also coprime to the subgroup's index.*)\nCorollary extend_solvable_coprime_irr G N t (theta := 'chi[N]_t) :\n N <| G -> solvable (G / N) -> G \\subset 'I[theta] ->\n coprime #|G : N| ('o(theta)%CF * Num.truncn (theta 1%g)) ->\n exists c, [/\\ 'Res 'chi[G]_c = theta, 'o('chi_c)%CF = 'o(theta)%CF\n & forall d,\n 'Res 'chi_d = theta -> coprime #|G : N| 'o('chi_d)%CF ->\n d = c].\n\nEnd ExtendInvariantIrr.\n\nSection Frobenius.\n\nVariables (gT : finGroupType) (G K : {group gT}).\n\nHypothesis frobGK : [Frobenius G with kernel K].\n\n(*This theorem states that for a Frobenius group with a given kernel, the inertia subgroup in the main group of any non-trivial irreducible character of that kernel is equal to the kernel itself.*)\nTheorem inertia_Frobenius_ker i : i != 0 -> 'I_G['chi[K]_i] = K.\n\n(*This theorem states that for a Frobenius group with a given kernel, the character induced on the main group from any non-trivial irreducible character of the kernel is itself an irreducible character.*)\nTheorem irr_induced_Frobenius_ker i : i != 0 -> 'Ind[G, K] 'chi_i \\in irr G.\n\n(*This lemma states that for a Frobenius group and its kernel, a character that is induced from an irreducible character of the kernel to the whole group is itself irreducible if and only if the original character of the kernel is not the trivial character.*)\nTheorem Frobenius_Ind_irrP j :\n reflect (exists2 i, i != 0 & 'chi_j = 'Ind[G, K] 'chi_i)\n (~~ (K \\subset cfker 'chi_j)).", - "character.mxabelem": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype tuple finfun bigop prime.\nFrom mathcomp Require Import ssralg poly finset fingroup morphism perm.\nFrom mathcomp Require Import automorphism quotient gproduct action finalg.\nFrom mathcomp Require Import zmodp commutator cyclic center pgroup gseries.\nFrom mathcomp Require Import nilpotent sylow maximal abelian matrix.\nFrom mathcomp Require Import mxalgebra mxrepresentation.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope abelem_scope.\n\nImport GroupScope GRing.Theory FinRing.Theory.\nLocal Open Scope ring_scope.\n\nSection FinNzRingRepr.\n\nVariable (R : finComUnitRingType) (gT : finGroupType).\nVariables (G : {group gT}) (n : nat) (rG : mx_representation R G n).\n\n(*This definition specifies the action of a group element on a row vector. The action is defined as the product of the row vector and the matrix corresponding to the group element in a given matrix representation.*)\nDefinition mx_repr_act (u : 'rV_n) x := u *m rG (val (subg G x)).\n\n(*This lemma states that for any group element, the action on a row vector is equivalent to the product of the row vector and the matrix associated with that group element by the representation.*)\nLemma mx_repr_actE u x : x \\in G -> mx_repr_act u x = u *m rG x.\n\n(*This fact establishes that the defined multiplication of a row vector by a matrix from a group representation constitutes a valid group action.*)\nFact mx_repr_is_action : is_action G mx_repr_act.\n\n(*This canonical structure packages the vector-matrix multiplication defined by a group representation into a formal group action structure, making it available for inference.*)\nCanonical Structure mx_repr_action := Action mx_repr_is_action.\n\n(*This fact establishes that the action derived from a matrix representation preserves the additive group structure of the vector space, meaning the action of any group element is a group homomorphism on the vectors.*)\nFact mx_repr_is_groupAction : is_groupAction [set: 'rV[R]_n] mx_repr_action.\n\n(*This canonical structure packages the action derived from a matrix representation and its associated proof of homomorphism into a formal group action structure that respects the additive vector space properties.*)\nCanonical Structure mx_repr_groupAction := GroupAction mx_repr_is_groupAction.\n\nEnd FinNzRingRepr.\n\n(*This notation provides a shorthand for the group action derived from a matrix representation. It is used to refer to either the basic action structure or the more specific group action structure that respects vector addition, depending on the active scope.*)\nNotation \"''MR' rG\" := (mx_repr_action rG)\n (at level 10, rG at level 8) : action_scope.\n(*A notation for constructing a matrix from a given sequence of row vectors, where each vector in the sequence becomes a row in the resulting matrix.*)\nNotation \"''MR' rG\" := (mx_repr_groupAction rG) : groupAction_scope.\n\nSection FinFieldRepr.\n\nVariable F : finFieldType.\n\nSection ScaleAction.\n\nVariables m n : nat.\n\n(*This definition describes the action of scaling a matrix over a finite field by a unit element from that field. It takes a matrix and a unit, and returns a new matrix where each entry has been multiplied by the value of the unit.*)\nDefinition scale_act (A : 'M[F]_(m, n)) (a : {unit F}) := val a *: A.\n(*This lemma states that the scale action on a matrix with a unit element is equivalent to performing scalar multiplication of the matrix by the value of that unit element.*)\nLemma scale_actE A a : scale_act A a = val a *: A. \n(*This fact asserts that the operation of scaling a matrix by a unit from its underlying field constitutes a valid mathematical action on the set of all matrices. This implies that scaling by the multiplicative identity leaves the matrix unchanged and that scaling by a product of units is equivalent to sequential scaling.*)\nFact scale_is_action : is_action setT scale_act.\n\nCanonical scale_action := Action scale_is_action.\n(*This fact asserts that the scaling of matrices by units of the underlying field constitutes a valid group action on the set of all matrices.*)\nFact scale_is_groupAction : is_groupAction setT scale_action.\n\nCanonical scale_groupAction := GroupAction scale_is_groupAction.\n\n(*This lemma states that for any non-zero matrix, the stabilizer subgroup under the scaling action is the trivial group, which implies that the only unit element that leaves a non-zero matrix unchanged when scaled is the multiplicative identity.*)\nLemma astab1_scale_act A : A != 0 -> 'C[A | scale_action] = 1%g.\n\nEnd ScaleAction.\n\n(*A local notation that provides a shorthand for the scalar multiplication action on matrices over a finite field.*)\nLocal Notation \"'Zm\" := (scale_action _ _) (at level 8) : action_scope.\n\nSection RowGroup.\n\nVariable n : nat.\n(*A local notation for the type of row vectors of a given dimension over a finite field.*)\nLocal Notation rVn := 'rV[F]_n.\n\n(*This definition assigns to a given matrix the set of all row vectors that belong to its row space.*)\nDefinition rowg m (A : 'M[F]_(m, n)) : {set rVn} := [set u | u <= A]%MS.\n\n(*This lemma states that a row vector is an element of the row space of a given matrix if and only if that vector can be expressed as a linear combination of the matrix's rows.*)\nLemma mem_rowg m A v : (v \\in @rowg m A) = (v <= A)%MS.\n\n(*This fact asserts that the set of vectors constituting the row space of a matrix forms a group under vector addition.*)\nFact rowg_group_set m A : group_set (@rowg m A).\n\nCanonical rowg_group m A := Group (@rowg_group_set m A).\n\n(*This lemma states that the row space of a matrix is stable under the scaling action by units of the underlying field, meaning any vector in the row space remains within that space after being scaled.*)\nLemma rowg_stable m (A : 'M_(m, n)) : [acts setT, on rowg A | 'Zm].\n\n(*This lemma states that the row space of one matrix is a subset of the row space of another matrix if and only if the row space of the first is a subspace of the row space of the second.*)\nLemma rowgS m1 m2 (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (rowg A \\subset rowg B) = (A <= B)%MS.\n\n(*This lemma states that if two matrices generate the same row space, then the sets representing their row spaces are equal.*)\nLemma eq_rowg m1 m2 (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (A :=: B)%MS -> rowg A = rowg B.\n\n(*This lemma states that the row space of a zero matrix is the trivial group, which consists solely of the zero vector.*)\nLemma rowg0 m : rowg (0 : 'M_(m, n)) = 1%g.\n\n(*This lemma states that the row space of the identity matrix is the set of all possible row vectors of the given dimension.*)\nLemma rowg1 : rowg 1%:M = setT.\n\n(*This lemma states that the row space of a matrix is the trivial group if and only if the matrix is equivalent to the zero matrix.*)\nLemma trivg_rowg m (A : 'M_(m, n)) : (rowg A == 1%g) = (A == 0).\n\n(*This definition constructs a matrix from a given set of row vectors by arranging the vectors as rows of the matrix in a canonical order.*)\nDefinition rowg_mx (L : {set rVn}) := <<\\matrix_(i < #|L|) enum_val i>>%MS.\n\n(*This lemma states that constructing a matrix from the row space of an initial matrix results in a new matrix that generates the same row space as the original one.*)\nLemma rowgK m (A : 'M_(m, n)) : (rowg_mx (rowg A) :=: A)%MS.\n\n(*This lemma states that constructing a matrix from a set of vectors is a monotone operation. Specifically, if one set of vectors is a subset of another, then the row space of the matrix constructed from the first set is a subspace of the row space of the matrix constructed from the second.*)\nLemma rowg_mxS (L M : {set 'rV[F]_n}) :\n L \\subset M -> (rowg_mx L <= rowg_mx M)%MS.\n\n(*This lemma states that any given set of row vectors is a subset of the row space generated by the matrix that is constructed from that same set of vectors.*)\nLemma sub_rowg_mx (L : {set rVn}) : L \\subset rowg (rowg_mx L).\n\n(*This lemma states that for any set of row vectors that forms a vector subspace, constructing a matrix from this set and then computing the row space of that matrix yields the original vector subspace.*)\nLemma stable_rowg_mxK (L : {group rVn}) :\n [acts setT, on L | 'Zm] -> rowg (rowg_mx L) = L.\n\n(*This lemma states that constructing a matrix from the trivial vector group, which contains only the zero vector, results in a matrix that is equivalent to the zero matrix.*)\nLemma rowg_mx1 : rowg_mx 1%g = 0.\n\n(*This lemma states that the matrix constructed from a group of row vectors is equivalent to the zero matrix if and only if that group of vectors is the trivial group.*)\nLemma rowg_mx_eq0 (L : {group rVn}) : (rowg_mx L == 0) = (L :==: 1%g).\n\n(*This lemma states that the row space operation distributes over the intersection of matrix row spaces. The row space corresponding to the intersection of two matrix row spaces is equal to the set-theoretic intersection of their individual row spaces.*)\nLemma rowgI m1 m2 (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n rowg (A :&: B)%MS = rowg A :&: rowg B.\n\n(*This lemma states that the number of vectors in the row space of a matrix over a finite field is equal to the size of the field raised to the power of the matrix's rank.*)\nLemma card_rowg m (A : 'M_(m, n)) : #|rowg A| = (#|F| ^ \\rank A)%N.\n\n(*This lemma states that the row space operation distributes over the sum of matrix row spaces. The row space corresponding to the sum of the row spaces of two matrices is equal to the group-theoretic sum of their individual row space groups.*)\nLemma rowgD m1 m2 (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n rowg (A + B)%MS = (rowg A * rowg B)%g.\n\n(*This lemma states that the group-theoretic product of the row spaces of two matrices is equal to the row space corresponding to the sum of the two original matrix row spaces.*)\nLemma cprod_rowg m1 m2 (A : 'M_(m1, n)) (B : 'M_(m2, n)) :\n (rowg A \\* rowg B)%g = rowg (A + B)%MS.\n\n(*This lemma states that if the sum of the row spaces of two matrices is a direct sum, then the direct product of their row space groups is equal to the row space corresponding to that sum.*)\nLemma dprod_rowg m1 m2 (A : 'M[F]_(m1, n)) (B : 'M[F]_(m2, n)) :\n mxdirect (A + B) -> rowg A \\x rowg B = rowg (A + B)%MS.\n\n(*This lemma generalizes the relationship between the product of groups and the sum of subspaces to an indexed collection of matrices, stating that the iterated group product of their row spaces corresponds to the row space of their summed subspaces.*)\nLemma bigcprod_rowg m I r (P : pred I) (A : I -> 'M[F]_n) (B : 'M[F]_(m, n)) :\n (\\sum_(i <- r | P i) A i :=: B)%MS ->\n \\big[cprod/1%g]_(i <- r | P i) rowg (A i) = rowg B.\n\n(*This lemma states that if a matrix is equal to a direct sum of a family of matrices, then the row group derived from that matrix is equal to the direct product of the row groups derived from each matrix in the family.*)\nLemma bigdprod_rowg m (I : finType) (P : pred I) A (B : 'M[F]_(m, n)) :\n let S := (\\sum_(i | P i) A i)%MS in (S :=: B)%MS -> mxdirect S ->\n \\big[dprod/1%g]_(i | P i) rowg (A i) = rowg B.\n\nEnd RowGroup.\n\nVariables (gT : finGroupType) (G : {group gT}) (n' : nat).\n(*This notation assigns the local name `n` to the successor of a natural number that is present in the context. It serves as a convenience for managing related dimensions or indices that differ by one.*)\nLocal Notation n := n'.+1.\nVariable (rG : mx_representation F G n).\n\n(*This fact asserts that the function which maps an element of the general linear group to its underlying matrix is a valid matrix representation.*)\nFact GL_mx_repr : mx_repr 'GL_n[F] GLval. \nCanonical GLrepr := MxRepresentation GL_mx_repr.\n\n(*This lemma states that the canonical matrix representation of the general linear group is faithful, meaning distinct group elements are mapped to distinct matrices.*)\nLemma GLmx_faithful : mx_faithful GLrepr.\n\n(*This definition describes a function that maps an element from a source group to an element in the general linear group by applying a given matrix representation.*)\nDefinition reprGLm x : {'GL_n[F]} := insubd (1%g : {'GL_n[F]}) (rG x).\n\n(*This lemma states that for any element in the domain group, the underlying matrix of the element's image in the general linear group via the `reprGLm` map is equal to the matrix produced by the original matrix representation.*)\nLemma val_reprGLm x : x \\in G -> val (reprGLm x) = rG x.\n\n(*This lemma states that a given matrix representation function is equal to the composition of the `reprGLm` mapping into the general linear group, followed by the function that extracts the underlying matrix.*)\nLemma comp_reprGLm : {in G, GLval \\o reprGLm =1 rG}.\n\n(*This lemma states that the function `reprGLm` is a group homomorphism, meaning it preserves the group multiplication operation.*)\nLemma reprGLmM : {in G &, {morph reprGLm : x y / x * y}}%g.\n\nCanonical reprGL_morphism := Morphism reprGLmM.\n\n(*This lemma states that the kernel of the group homomorphism `reprGLm` is equal to the kernel of the underlying matrix representation.*)\nLemma ker_reprGLm : 'ker reprGLm = rker rG.\n\n(*This lemma states that the stabilizer of the row group of a matrix under the action induced by a matrix representation is equal to the right stabilizer of the matrix itself under the same representation.*)\nLemma astab_rowg_repr m (A : 'M_(m, n)) : 'C(rowg A | 'MR rG) = rstab rG A.\n\n(*This lemma states that the normalizer of the row group of a matrix under the action induced by a matrix representation is equal to the right set-stabilizer of the matrix itself under the same representation.*)\nLemma astabs_rowg_repr m (A : 'M_(m, n)) : 'N(rowg A | 'MR rG) = rstabs rG A.\n\n(*This lemma states that the proposition that a group acts on the row group of a square matrix via a given matrix representation is equivalent to the proposition that the matrix forms a module for that representation.*)\nLemma acts_rowg (A : 'M_n) : [acts G, on rowg A | 'MR rG] = mxmodule rG A.\n\n(*This lemma states that the stabilizer of the entire space of row vectors under the action induced by a matrix representation is equal to the kernel of that representation.*)\nLemma astab_setT_repr : 'C(setT | 'MR rG) = rker rG.\n\n(*This lemma states that the proposition that a group acts faithfully on the space of row vectors via a matrix representation is equivalent to the proposition that the representation itself is faithful.*)\nLemma mx_repr_action_faithful :\n [faithful G, on setT | 'MR rG] = mx_faithful rG.\n\n(*This lemma states that for any subset of a group, the set of fixed points in the row vector space under the action induced by a matrix representation is equal to the row group of the matrix whose rows form a basis for these fixed points.*)\nLemma afix_repr (H : {set gT}) :\n H \\subset G -> 'Fix_('MR rG)(H) = rowg (rfix_mx rG H).\n\n(*This lemma states that for any subset of a group, the centralizer of this subset within the action on row vectors, which is the set of points fixed by the subset, is equal to the row group of the matrix whose rows form a basis for these fixed points.*)\nLemma gacent_repr (H : {set gT}) :\n H \\subset G -> 'C_(| 'MR rG)(H) = rowg (rfix_mx rG H).\n\nEnd FinFieldRepr.\n\nArguments rowg_mx {F n%_N} L%_g.\n(*This notation represents the canonical scalar multiplication action, where elements of a ring or field act on elements of a module by scaling.*)\nNotation \"''Zm'\" := (scale_action _ _ _) : action_scope.\n(*A notation representing the ring of integers, used to specify the scalars acting on a group, thereby defining a module structure over the integers.*)\nNotation \"''Zm'\" := (scale_groupAction _ _ _) : groupAction_scope.\n\nSection MatrixGroups.\n\nImplicit Types m n p q : nat.\n\n(*This lemma states that for positive dimensions 'm' and 'n' and a modulus 'q' greater than one, the exponent of the additive group of 'm' by 'n' matrices over the integers modulo 'q' is equal to 'q'.*)\nLemma exponent_mx_group m n q :\n m > 0 -> n > 0 -> q > 1 -> exponent [set: 'M['Z_q]_(m, n)] = q.\n\n(*This lemma states that the rank of the additive group of 'm' by 'n' matrices over the integers modulo 'q' is equal to the product of the natural numbers 'm' and 'n'.*)\nLemma rank_mx_group m n q : 'r([set: 'M['Z_q]_(m, n)]) = (m * n)%N.\n\n(*This lemma states that the additive group of 'm' by 'n' matrices with entries from the integers modulo 'q' is a homocyclic group.*)\nLemma mx_group_homocyclic m n q : homocyclic [set: 'M['Z_q]_(m, n)].\n\n(*This lemma states that for a modulus 'q' greater than one, the abelian type of the additive group of 'm' by 'n' matrices over the integers modulo 'q' is a finite sequence whose length is the product of 'm' and 'n' and whose elements are all equal to 'q'.*)\nLemma abelian_type_mx_group m n q :\n q > 1 -> abelian_type [set: 'M['Z_q]_(m, n)] = nseq (m * n) q.\n\nEnd MatrixGroups.\n\nDelimit Scope abelem_scope with Mg.\nOpen Scope abelem_scope.\n\n(*This definition provides a dimension-like value for a finite set within a group, calculated as one less than the base-'p' logarithm of the size of the set, where 'p' is the largest prime divisor of the set's size.*)\nDefinition abelem_dim' (gT : finGroupType) (E : {set gT}) :=\n (logn (pdiv #|E|) #|E|).-1.\nArguments abelem_dim' {gT} E%_g.\n(*A notation representing the dimension of a p-elementary abelian group, which is calculated as the base-'p' logarithm of the group's order, where 'p' is the characteristic prime associated with the group.*)\nNotation \"''dim' E\" := (abelem_dim' E).+1\n (at level 10, E at level 8, format \"''dim' E\") : abelem_scope.\n\n(*A notation for the type of row vectors whose length corresponds to the dimension of a given p-elementary abelian group.*)\nNotation \"''rV' ( E )\" := 'rV_('dim E) (format \"''rV' ( E )\") : abelem_scope.\n(*A notation for the type of square matrices whose size corresponds to the dimension of a given p-elementary abelian group.*)\nNotation \"''M' ( E )\" := 'M_('dim E) (format \"''M' ( E )\") : abelem_scope.\n(*A notation for specifying the type of row vectors over a given field, where the length of the vectors is the dimension of a p-elementary abelian group.*)\nNotation \"''rV[' F ] ( E )\" := 'rV[F]_('dim E) (only parsing) : abelem_scope.\n(*A notation for specifying the type of square matrices over a given field, where the size of the matrices is the dimension of a p-elementary abelian group.*)\nNotation \"''M[' F ] ( E )\" := 'M[F]_('dim E) (only parsing) : abelem_scope.\n\nSection AbelemRepr.\n\nSection FpMatrix.\n\nVariables p m n : nat.\n(*A local notation serving as an abbreviation for the type of 'm' by 'n' matrices with entries from the prime field of characteristic 'p'.*)\nLocal Notation Mmn := 'M['F_p]_(m, n).\n\n(*This lemma states that if 'p' is a prime number, then the additive group formed by 'm' by 'n' matrices over the prime field of characteristic 'p' qualifies as a p-elementary abelian group.*)\nLemma mx_Fp_abelem : prime p -> p.-abelem [set: Mmn].\n\n(*This lemma states that any subgroup of the additive group of matrices over a prime field is stable under scalar multiplication by integers, which implies it has the structure of a module over the ring of integers.*)\nLemma mx_Fp_stable (L : {group Mmn}) : [acts setT, on L | 'Zm].\n\nEnd FpMatrix.\n\nSection FpRow.\n\nVariables p n : nat.\n(*A local notation serving as an abbreviation for the type of row vectors of a given length 'n' with entries from the prime field of characteristic 'p'.*)\nLocal Notation rVn := 'rV['F_p]_n.\n\n(*This lemma states that for any group composed of row vectors, the process of forming a matrix from these vectors and then extracting the row space of that matrix recovers the original group.*)\nLemma rowg_mxK (L : {group rVn}) : rowg (rowg_mx L) = L.\n\n(*This lemma establishes that the row space generated by a matrix formed from a given set of row vectors is a subspace of the row space from a matrix formed from a given group of row vectors if and only if the set is a subset of the group.*)\nLemma rowg_mxSK (L : {set rVn}) (M : {group rVn}) :\n (rowg_mx L <= rowg_mx M)%MS = (L \\subset M).\n\n(*This lemma states that for a prime number 'p', the rank of a matrix formed by using the elements of a group of row vectors over the prime field of characteristic 'p' as its rows is equal to the base-'p' logarithm of the group's size.*)\nLemma mxrank_rowg (L : {group rVn}) :\n prime p -> \\rank (rowg_mx L) = logn p #|L|.\n\nEnd FpRow.\n\nVariables (p : nat) (gT : finGroupType) (E : {group gT}).\nHypotheses (abelE : p.-abelem E) (ntE : E :!=: 1%g).\n\n(*A local definition that establishes the p-group structure for a given group, based on the prior assumption that the group is p-elementary abelian.*)\nLet pE : p.-group E := abelem_pgroup abelE.\n(*A local definition holding the proof that a natural number 'p' is prime, which is a necessary condition derived from a group being p-elementary abelian for that prime 'p'.*)\nLet p_pr : prime p. \n\n(*A local notation representing a value equal to one less than the dimension of a given p-elementary abelian group.*)\nLocal Notation n' := (abelem_dim' (gval E)).\n(*This notation defines `n` as an alias for the successor of a given natural number `n'`.*)\nLocal Notation n := n'.+1.\n(*This type represents the canonical vector space of a given dimension over a prime field, to which an elementary abelian group is isomorphic.*)\nLocal Notation rVn := 'rV['F_p](gval E).\n\n(*This lemma states that the dimension of the canonical vector space associated with an elementary abelian p-group is equal to the base-p logarithm of the cardinality of the group.*)\nLemma dim_abelemE : n = logn p #|E|.\n\n(*This lemma states that the cardinality of the canonical vector space is equal to the cardinality of the elementary abelian group.*)\nLemma card_abelem_rV : #|rVn| = #|E|.\n\n(*This lemma states that the elementary abelian group is isomorphic to the additive group structure of its corresponding canonical vector space.*)\nLemma isog_abelem_rV : E \\isog [set: rVn].\n\n(*A local notation for the proposition asserting the existence of a group isomorphism between an elementary abelian group and its corresponding canonical vector space.*)\nLocal Notation ab_rV_P := (existsP isog_abelem_rV).\n(*This definition establishes a specific function from a group to a canonical vector space, chosen from the set of existing isomorphisms between the elementary abelian group and the vector space.*)\nDefinition abelem_rV : gT -> rVn := xchoose ab_rV_P.\n\n(*A local notation for the function that maps elements from an elementary abelian group to the corresponding canonical vector space.*)\nLocal Notation ErV := abelem_rV.\n\n(*This lemma states that the function mapping from an elementary abelian group to its canonical vector space is a group morphism, meaning it maps the group product of two elements to the sum of their images.*)\nLemma abelem_rV_M : {in E &, {morph ErV : x y / (x * y)%g >-> x + y}}.\n\nCanonical abelem_rV_morphism := Morphism abelem_rV_M.\n\n(*This lemma states that the function mapping an elementary abelian group to its canonical vector space is a group isomorphism.*)\nLemma abelem_rV_isom : isom E setT ErV.\n\n(*This lemma states that the group morphism from an elementary abelian group to its canonical vector space is injective.*)\nLemma abelem_rV_injm : 'injm ErV. \n\n(*This lemma states that the function mapping from an elementary abelian group to its canonical vector space is injective when restricted to the group.*)\nLemma abelem_rV_inj : {in E &, injective ErV}.\n\n(*This lemma states that the image of an elementary abelian group under the isomorphism to its canonical vector space is the entire set of elements of the vector space.*)\nLemma im_abelem_rV : ErV @* E = setT. \n\n(*This lemma states that any element of the canonical vector space belongs to the image of the elementary abelian group under the corresponding isomorphism.*)\nLemma mem_im_abelem_rV u : u \\in ErV @* E.\n\n(*This lemma states that any subset of the canonical vector space is also a subset of the image of the corresponding elementary abelian group under their isomorphism.*)\nLemma sub_im_abelem_rV mA : subset mA (mem (ErV @* E)).\n\nHint Resolve mem_im_abelem_rV sub_im_abelem_rV : core.\n\n(*This lemma states that the isomorphism from an elementary abelian group to its canonical vector space maps the identity element of the group to the zero vector.*)\nLemma abelem_rV_1 : ErV 1 = 0%R. \n\n(*This lemma states that for any element in an elementary abelian group, applying the isomorphism to the group exponentiation of the element by a scalar is equivalent to performing scalar multiplication on the element's image in the canonical vector space.*)\nLemma abelem_rV_X x i : x \\in E -> ErV (x ^+ i) = i%:R *: ErV x.\n\n(*This lemma states that for any element in an elementary abelian group, the isomorphism maps the inverse of that element to the additive inverse of its image in the canonical vector space.*)\nLemma abelem_rV_V x : x \\in E -> ErV x^-1 = - ErV x.\n\n(*This definition establishes the inverse function of the isomorphism between an elementary abelian group and its canonical vector space, mapping elements from the vector space back to the group.*)\nDefinition rVabelem : rVn -> gT := invm abelem_rV_injm.\nCanonical rVabelem_morphism := [morphism of rVabelem].\n(*A local notation for the function that maps elements from the canonical vector space back to the corresponding elementary abelian group.*)\nLocal Notation rV_E := rVabelem.\n\n(*This lemma states that the isomorphism from the canonical vector space to an elementary abelian group maps the zero vector to the identity element of the group.*)\nLemma rVabelem0 : rV_E 0 = 1%g. \n\n(*This lemma states that the isomorphism from the canonical vector space to an elementary abelian group is a group morphism, mapping the sum of two vectors to the group product of their images.*)\nLemma rVabelemD : {morph rV_E : u v / u + v >-> (u * v)%g}.\n\n(*This lemma states that the isomorphism from the canonical vector space to an elementary abelian group maps the additive inverse of a vector to the group inverse of its image.*)\nLemma rVabelemN : {morph rV_E: u / - u >-> (u^-1)%g}.\n\n(*This lemma states that the isomorphism from the canonical vector space to an elementary abelian group maps the scalar product of a vector to the group exponentiation of its image by that scalar.*)\nLemma rVabelemZ (m : 'F_p) : {morph rV_E : u / m *: u >-> (u ^+ m)%g}.\n\n(*This lemma states that applying the inverse isomorphism from the vector space to the group, followed by the main isomorphism from the group back to the vector space, acts as the identity function on the vector space.*)\nLemma abelem_rV_K : {in E, cancel ErV rV_E}. \n\n(*This lemma states that applying the main isomorphism from the group to the vector space, followed by its inverse from the vector space back to the group, acts as the identity function on the group.*)\nLemma rVabelemK : cancel rV_E ErV. \n\n(*This lemma states that the function mapping from the canonical vector space to the corresponding elementary abelian group is injective.*)\nLemma rVabelem_inj : injective rV_E. \n\n(*This lemma states that the isomorphism from the canonical vector space to its corresponding elementary abelian group is an injective group morphism.*)\nLemma rVabelem_injm : 'injm rV_E. \n\n(*This lemma states that the image of the canonical vector space under its isomorphism to an elementary abelian group is precisely the entire group.*)\nLemma im_rVabelem : rV_E @* setT = E.\n\n(*This lemma states that for any vector in the canonical vector space, its image under the isomorphism to the corresponding elementary abelian group is an element of that group.*)\nLemma mem_rVabelem u : rV_E u \\in E.\n\n(*This lemma states that the image of any subset of the canonical vector space under the isomorphism to the corresponding elementary abelian group is a subset of that group.*)\nLemma sub_rVabelem L : rV_E @* L \\subset E.\n\nHint Resolve mem_rVabelem sub_rVabelem : core.\n\n(*This lemma states that the cardinality of the set obtained by applying the abelian element embedding to a set of vectors is equal to the cardinality of the original set of vectors.*)\nLemma card_rVabelem L : #|rV_E @* L| = #|L|.\n\n(*This lemma states that applying the vector space embedding and then the group element embedding to a set of group elements that is a subset of the base set results in the original set.*)\nLemma abelem_rV_mK (H : {set gT}) : H \\subset E -> rV_E @* (ErV @* H) = H.\n\n(*This lemma states that applying the group element embedding and then the vector space embedding to a set of vectors results in the original set.*)\nLemma rVabelem_mK L : ErV @* (rV_E @* L) = L.\n\n(*This lemma states that the abelian element embedding function from the vector space to the group is injective.*)\nLemma rVabelem_minj : injective (morphim (MorPhantom rV_E)).\n\n(*This lemma states that the subset relation holds between the images of two vector sets under the abelian element embedding if and only if it holds between the original vector sets.*)\nLemma rVabelemS L M : (rV_E @* L \\subset rV_E @* M) = (L \\subset M).\n\n(*This lemma states that for two sets of group elements contained in the base set, the subset relation holds between their images under the vector space embedding if and only if it holds between the original sets.*)\nLemma abelem_rV_S (H K : {set gT}) :\n H \\subset E -> (ErV @* H \\subset ErV @* K) = (H \\subset K).\n\n(*This lemma states that the image of a set of vectors under the abelian element embedding is a subset of a given set of group elements if and only if the original set of vectors is a subset of the image of the group element set under the vector space embedding.*)\nLemma sub_rVabelem_im L (H : {set gT}) :\n (rV_E @* L \\subset H) = (L \\subset ErV @* H).\n\n(*This lemma states that for a set of group elements contained in the base set, its image under the vector space embedding is a subset of a given set of vectors if and only if the original set of group elements is a subset of the image of the vector set under the group element embedding.*)\nLemma sub_abelem_rV_im (H : {set gT}) (L : {set 'rV['F_p]_n}) :\n H \\subset E -> (ErV @* H \\subset L) = (H \\subset rV_E @* L).\n\nSection OneGroup.\n\nVariable G : {group gT}.\n(*This definition specifies a function that, for a given group element, maps a vector to another vector by embedding it into the group, conjugating by the group element, and then mapping the result back to the vector space.*)\nDefinition abelem_mx_fun (g : subg_of G) v := ErV ((rV_E v) ^ val g).\n(*This definition constructs a matrix representation for a group, where each group element is mapped to the matrix of the linear transformation corresponding to conjugation by that element, acting on an abelian normal subgroup.*)\nDefinition abelem_mx of G \\subset 'N(E) :=\n fun x => lin1_mx (abelem_mx_fun (subg G x)).\n\nHypothesis nEG : G \\subset 'N(E).\n(*A local notation for the matrix representation derived from the abelian element conjugation action, assuming the group normalizes the base set.*)\nLocal Notation r := (abelem_mx nEG).\n\n(*This fact asserts that the function defined by embedding a vector into a group, conjugating by a fixed group element, and mapping back to the vector space is a linear transformation.*)\nFact abelem_mx_linear_proof g : linear (abelem_mx_fun g).\n\n(*This an intermediate lemma that asserts that for any vector and any group element, applying the abelian element embedding to the product of the vector and the matrix for the group element is equivalent to conjugating the embedded vector by the group element.*)\nLet rVabelemJmx v x : x \\in G -> rV_E (v *m r x) = (rV_E v) ^ x.\n\n(*This fact asserts that the mapping from group elements to matrices corresponding to the abelian conjugation action constitutes a valid matrix representation of the group.*)\nFact abelem_mx_repr : mx_repr G r.\n\nCanonical abelem_repr := MxRepresentation abelem_mx_repr.\n(*A local notation for the canonical matrix representation derived from the abelian element conjugation action.*)\nLet rG := abelem_repr.\n\n(*This lemma states that for a given vector and group element, applying the abelian element embedding to the result of multiplying the vector by the group element's matrix representation is equivalent to conjugating the embedded vector by the group element.*)\nLemma rVabelemJ v x : x \\in G -> rV_E (v *m rG x) = (rV_E v) ^ x.\n\n(*This lemma states that for any two group elements, where the first is in the base set, the vector space embedding of their conjugation is equal to the product of the vector embedding of the first element and the matrix representation of the second.*)\nLemma abelem_rV_J : {in E & G, forall x y, ErV (x ^ y) = ErV x *m rG y}.\n\n(*This lemma states that for a given matrix and group element, the image of the row space of the matrix multiplied by the group element's representation is equal to the set-wise conjugation of the image of the original matrix's row space by that group element.*)\nLemma abelem_rowgJ m (A : 'M_(m, n)) x :\n x \\in G -> rV_E @* rowg (A *m rG x) = (rV_E @* rowg A) :^ x.\n\n(*This lemma states that for a subgroup contained in the base set and an element from the ambient group, the vector space embedding of the subgroup conjugated by the element is equal to the row space of the matrix product of the subgroup's vector space representation and the element's matrix representation.*)\nLemma rV_abelem_sJ (L : {group gT}) x :\n x \\in G -> L \\subset E -> ErV @* (L :^ x) = rowg (rowg_mx (ErV @* L) *m rG x).\n\n(*This lemma states that the stabilizer of a matrix under the abelian element matrix representation is equal to the centralizer within the group of the set of elements corresponding to the matrix's row space.*)\nLemma rstab_abelem m (A : 'M_(m, n)) : rstab rG A = 'C_G(rV_E @* rowg A).\n\n(*This lemma states that the setwise stabilizer of a matrix under the abelian element matrix representation is equal to the normalizer within the group of the set of elements corresponding to the matrix's row space.*)\nLemma rstabs_abelem m (A : 'M_(m, n)) : rstabs rG A = 'N_G(rV_E @* rowg A).\n\n(*This lemma states that for a subgroup contained in the base set, the setwise stabilizer of its corresponding matrix under the abelian element representation is equal to the normalizer of that subgroup within the ambient group.*)\nLemma rstabs_abelemG (L : {group gT}) :\n L \\subset E -> rstabs rG (rowg_mx (ErV @* L)) = 'N_G(L).\n\n(*This lemma states that a given subspace is a module under the abelian element matrix representation if and only if the group normalizes the set of group elements corresponding to the basis of that subspace.*)\nLemma mxmodule_abelem m (U : 'M['F_p]_(m, n)) :\n mxmodule rG U = (G \\subset 'N(rV_E @* rowg U)).\n\n(*This lemma states that for a subgroup contained in the base set, the vector space it spans is a module under the abelian element matrix representation if and only if the ambient group normalizes that subgroup.*)\nLemma mxmodule_abelemG (L : {group gT}) :\n L \\subset E -> mxmodule rG (rowg_mx (ErV @* L)) = (G \\subset 'N(L)).\n\n(*This lemma provides an equivalence, stating that a subspace is a simple module under the abelian element matrix representation if and only if the corresponding set of group elements is a minimal normal subgroup.*)\nLemma mxsimple_abelemP (U : 'M['F_p]_n) :\n reflect (mxsimple rG U) (minnormal (rV_E @* rowg U) G).\n\n(*This lemma provides an equivalence for a subgroup contained within the base set, stating that the vector space it spans is a simple module under the abelian element matrix representation if and only if the subgroup itself is a minimal normal subgroup of the ambient group.*)\nLemma mxsimple_abelemGP (L : {group gT}) :\n L \\subset E -> reflect (mxsimple rG (rowg_mx (ErV @* L))) (minnormal L G).\n\n(*This lemma provides an equivalence, stating that the abelian element matrix representation is irreducible if and only if the base set, which is an abelian normal subgroup, is a minimal normal subgroup of the ambient group.*)\nLemma abelem_mx_irrP : reflect (mx_irreducible rG) (minnormal E G).\n\n(*This lemma states that for a given subset of the group, the fixed-point subspace under the abelian element matrix representation is the subspace spanned by the vector embeddings of the elements in the base set that commute with every element of the given subset.*)\nLemma rfix_abelem (H : {set gT}) :\n H \\subset G -> (rfix_mx rG H :=: rowg_mx (ErV @* 'C_E(H)%g))%MS.\n\n(*This lemma states that the kernel of the abelian element matrix representation is the centralizer of the base set within the group.*)\nLemma rker_abelem : rker rG = 'C_G(E).\n\n(*This lemma states that the abelian element matrix representation is faithful if the centralizer of the base set within the group is trivial.*)\nLemma abelem_mx_faithful : 'C_G(E) = 1%g -> mx_faithful rG.\n\nEnd OneGroup.\n\nSection SubGroup.\n\nVariables G H : {group gT}.\nHypotheses (nEG : G \\subset 'N(E)) (sHG : H \\subset G).\n(*This definition establishes that a subgroup H is a subset of the normalizer of E, derived from the facts that H is a subgroup of G and G is a subset of the normalizer of E.*)\nLet nEH := subset_trans sHG nEG.\n(*This notation defines the abelian element representation of a group G, which provides a canonical representation for its elements.*)\nLocal Notation rG := (abelem_repr nEG).\n(*This notation defines the representation of a subgroup H, which is inherited from the abelian element representation of its containing group G.*)\nLocal Notation rHG := (subg_repr rG sHG).\n(*This notation defines the abelian element representation of a group H, derived from its status as a subgroup of a normalizer.*)\nLocal Notation rH := (abelem_repr nEH).\n\n(*This lemma states that for any element in a subgroup H, its representation inherited from the containing group G is identical to its direct abelian element representation.*)\nLemma eq_abelem_subg_repr : {in H, rHG =1 rH}.\n\n(*This lemma states that the abelian element representation of a subgroup H inherited from a larger group G is similar to the direct abelian element representation of H.*)\nLemma rsim_abelem_subg : mx_rsim rHG rH.\n\n(*This lemma states that for a given matrix, the matrix module generated under the inherited representation of a subgroup is equal to the module generated under its direct representation.*)\nLemma mxmodule_abelem_subg m (U : 'M_(m, n)) : mxmodule rHG U = mxmodule rH U.\n\n(*This lemma states that a matrix module is simple under the inherited representation of a subgroup if and only if it is simple under the direct representation of that subgroup.*)\nLemma mxsimple_abelem_subg U : mxsimple rHG U <-> mxsimple rH U.\n\nEnd SubGroup.\n\nEnd AbelemRepr.\n\nArguments rVabelem_inj {p%_N gT E%_G} abelE ntE [v1%_R v2%_R] : rename.\n\nSection ModularRepresentation.\n\nVariables (F : fieldType) (p : nat) (gT : finGroupType).\nHypothesis pcharFp : p \\in [pchar F].\nImplicit Types G H : {group gT}.\n\n(*This lemma states that for any non-trivial matrix representation of a finite group over a field with characteristic p, the subspace of vectors fixed by every element of a p-subgroup of the group is not the zero subspace.*)\nLemma rfix_pgroup_pchar G H n (rG : mx_representation F G n) :\n n > 0 -> p.-group H -> H \\subset G -> rfix_mx rG H != 0.\n\nVariables (G : {group gT}) (n : nat) (rG : mx_representation F G n).\n\n(*This lemma states that for a matrix representation of a group G over a field of characteristic p, if a module is simple, then the p-core of G is a subgroup of the stabilizer of that module.*)\nLemma pcore_sub_rstab_mxsimple_pchar M :\n mxsimple rG M -> 'O_p(G) \\subset rstab rG M.\n\n(*This lemma states that for any irreducible matrix representation of a group G over a field of characteristic p, the p-core of G is a subgroup of the kernel of the representation.*)\nLemma pcore_sub_rker_mx_irr_pchar :\n mx_irreducible rG -> 'O_p(G) \\subset rker rG.\n\n(*This lemma states that if a matrix representation of a group G over a field with characteristic p is both irreducible and faithful, then the p-core of G must be the trivial group.*)\nLemma pcore_faithful_mx_irr_pchar :\n mx_irreducible rG -> mx_faithful rG -> 'O_p(G) = 1%g.\n\nEnd ModularRepresentation.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use rfix_pgroup_pchar instead.\")]\n(*This is a deprecated notation which is an alias for a lemma stating that for any non-trivial matrix representation of a finite group over a field with characteristic p, the subspace of vectors fixed by a p-subgroup is non-trivial.*)\nNotation rfix_pgroup_char := (rfix_pgroup_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcore_sub_rstab_mxsimple_pchar instead.\")]\n(*This is a deprecated notation which is an alias for a lemma stating that for a simple module of a matrix representation over a field of characteristic p, the p-core of the group is a subgroup of the module's stabilizer.*)\nNotation pcore_sub_rstab_mxsimple := (pcore_sub_rstab_mxsimple_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcore_sub_rker_mx_irr_pchar instead.\")]\n(*This is a deprecated notation which is an alias for a lemma stating that for an irreducible matrix representation over a field of characteristic p, the p-core of the group is a subgroup of the representation's kernel.*)\nNotation pcore_sub_rker_mx_irr := (pcore_sub_rker_mx_irr_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use pcore_faithful_mx_irr_pchar instead.\")]\n(*This is a deprecated notation which is an alias for a lemma stating that for a faithful and irreducible matrix representation over a field of characteristic p, the p-core of the group is the trivial group.*)\nNotation pcore_faithful_mx_irr := (pcore_faithful_mx_irr_pchar) (only parsing).\n\nSection Extraspecial.\n\nVariables (F : fieldType) (gT : finGroupType) (S : {group gT}) (p n : nat).\nHypotheses (pS : p.-group S) (esS : extraspecial S).\nHypothesis oSpn : #|S| = (p ^ n.*2.+1)%N.\nHypotheses (splitF : group_splitting_field F S) (F'S : [pchar F]^'.-group S).\n\n(*This definition specifies the prime number associated with an extraspecial p-group.*)\nLet p_pr := extraspecial_prime pS esS.\n(*This definition provides a proof that the prime number associated with the extraspecial group is greater than zero.*)\nLet p_gt0 := prime_gt0 p_pr.\n(*This definition provides a proof that the prime number associated with the extraspecial group is greater than one.*)\nLet p_gt1 := prime_gt1 p_pr.\n(*This definition gives the cardinality of the center of the extraspecial group, which is equal to the associated prime number.*)\nLet oZp := card_center_extraspecial pS esS.\n\n(*This lemma states that for any natural number i less than a prime number p minus one, the value of i plus one, modulo p, is equal to i plus one.*)\nLet modIp' (i : 'I_p.-1) : (i.+1 %% p = i.+1)%N.\n\n(*This theorem describes the structure of the irreducible representations of an extraspecial p-group over a splitting field whose characteristic does not divide p. It asserts that there are a specific number of linear representations, and p-1 non-linear, faithful, irreducible representations of a certain degree. Furthermore, it details how central elements are represented by scalar matrices involving primitive roots of unity.*)\nTheorem extraspecial_repr_structure_pchar (sS : irrType F S) :\n [/\\ #|linear_irr sS| = (p ^ n.*2)%N,\n exists iphi : 'I_p.-1 -> sS, let phi i := irr_repr (iphi i) in\n [/\\ injective iphi,\n codom iphi =i ~: linear_irr sS,\n forall i, mx_faithful (phi i),\n forall z, z \\in 'Z(S)^# ->\n exists2 w, primitive_root_of_unity p w\n & forall i, phi i z = (w ^+ i.+1)%:M\n & forall i, irr_degree (iphi i) = (p ^ n)%N]\n & #|sS| = (p ^ n.*2 + p.-1)%N].\n\nVariables (m : nat) (rS : mx_representation F S m) (U : 'M[F]_m).\nHypotheses (simU : mxsimple rS U) (ffulU : rstab rS U == 1%g).\n(*This definition establishes the center of the extraspecial group S as a subgroup.*)\nLet sZS := center_sub S.\n(*This definition provides the matrix representation of the center of the extraspecial group, obtained by restricting a representation of the whole group.*)\nLet rZ := subg_repr rS sZS.\n\n(*This lemma asserts two properties of a simple and faithful module for an extraspecial group representation: first, its dimension is a specific power of the associated prime, and second, if another simple module is isomorphic to it as a module over the center, then it is also isomorphic as a module over the entire group.*)\nLemma faithful_repr_extraspecial_pchar :\n \\rank U = (p ^ n)%N /\\\n (forall V, mxsimple rS V -> mx_iso rZ U V -> mx_iso rS U V).\n\nEnd Extraspecial.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use extraspecial_repr_structure_pchar instead.\")]\n(*This is a deprecated notation which is an alias for the theorem that describes the number, degrees, and properties of the irreducible representations of an extraspecial p-group.*)\nNotation extraspecial_repr_structure := (extraspecial_repr_structure_pchar)\n (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use faithful_repr_extraspecial_pchar instead.\")]\n(*This is a deprecated notation which is aliased to a lemma concerning simple, faithful modules of an extraspecial group representation, establishing their dimension and an isomorphism condition.*)\nNotation faithful_repr_extraspecial := (faithful_repr_extraspecial_pchar)", - "character.vcharacter": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype tuple finfun bigop prime order.\nFrom mathcomp Require Import ssralg poly finset fingroup morphism perm.\nFrom mathcomp Require Import automorphism quotient finalg action gproduct.\nFrom mathcomp Require Import zmodp commutator cyclic center pgroup sylow.\nFrom mathcomp Require Import frobenius vector ssrnum ssrint archimedean intdiv.\nFrom mathcomp Require Import algC algnum classfun character integral_char.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport Order.TTheory GroupScope GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\nSection Basics.\n\nVariables (gT : finGroupType) (B : {set gT}) (S : seq 'CF(B)) (A : {set gT}).\n\n(*This definition specifies the set of class functions that can be expressed as an integer linear combination of a given sequence of class functions and whose support is contained within a given set of group elements.*)\nDefinition Zchar : {pred 'CF(B)} :=\n [pred phi in 'CF(B, A) | dec_Cint_span (in_tuple S) phi].\n\n(*This lemma states that the zero class function is always an element of the set of integer linear combinations of any given sequence of class functions.*)\nLemma cfun0_zchar : 0 \\in Zchar.\n\n(*This fact asserts that any set of class functions formed by integer linear combinations of a given sequence is closed under addition and subtraction, forming a Z-module.*)\nFact Zchar_zmod : zmod_closed Zchar.\n\n(*This lemma states that if a class function is an integer linear combination of a given sequence of class functions, then scaling that function by any integer results in a function that is also an integer linear combination of the same sequence.*)\nLemma scale_zchar a phi : a \\in Num.int -> phi \\in Zchar -> a *: phi \\in Zchar.\n\nEnd Basics.\n\n(*A notation for the set of class functions that can be expressed as an integer linear combination of the functions in a given sequence and whose support is contained within a given set of group elements.*)\nNotation \"''Z[' S , A ]\" := (Zchar S A) (format \"''Z[' S , A ]\") : group_scope.\n(*A notation for the set of class functions that can be expressed as an integer linear combination of the functions in a given sequence, with no restriction on their support.*)\nNotation \"''Z[' S ]\" := 'Z[S, setT] (format \"''Z[' S ]\") : group_scope.\n\nSection Zchar.\n\nVariables (gT : finGroupType) (G : {group gT}).\nImplicit Types (A B : {set gT}) (S : seq 'CF(G)).\n\n(*This lemma states that a class function belongs to the set of integer combinations of a sequence of class functions with support in a given set if and only if it is an integer combination of that sequence and, separately, its support is contained within that set.*)\nLemma zchar_split S A phi :\n phi \\in 'Z[S, A] = (phi \\in 'Z[S]) && (phi \\in 'CF(G, A)).\n\n(*This lemma establishes that a class function is an integer linear combination of a given sequence of functions with support that excludes the group identity element if and only if it is an integer linear combination of that sequence and evaluates to zero at the identity element.*)\nLemma zcharD1E phi S : (phi \\in 'Z[S, G^#]) = (phi \\in 'Z[S]) && (phi 1%g == 0).\n\n(*This lemma shows that a class function belongs to the integer span of a sequence of functions with support in a set excluding the identity element, if and only if it belongs to the integer span with support in the original set and also evaluates to zero at the identity element.*)\nLemma zcharD1 phi S A :\n (phi \\in 'Z[S, A^#]) = (phi \\in 'Z[S, A]) && (phi 1%g == 0).\n\n(*This lemma states that the set of integer linear combinations of a sequence of class functions with support in a specific set is a subset of the integer linear combinations of the same sequence without any support restriction.*)\nLemma zcharW S A : {subset 'Z[S, A] <= 'Z[S]}.\n\n(*This lemma states that any class function expressible as an integer linear combination of a sequence of functions with support in a given set is itself a class function with support contained in that same set.*)\nLemma zchar_on S A : {subset 'Z[S, A] <= 'CF(G, A)}.\n\n(*This lemma asserts that if a set of group elements is a subset of another, then the set of integer character combinations with support in the smaller set is a subset of the integer character combinations with support in the larger set.*)\nLemma zchar_onS A B S : A \\subset B -> {subset 'Z[S, A] <= 'Z[S, B]}.\n\n(*This lemma states that the set of integer linear combinations of a sequence of class functions with support specified as the entire group is identical to the set of integer linear combinations of that sequence with no support restriction.*)\nLemma zchar_onG S : 'Z[S, G] =i 'Z[S].\n\n(*This lemma states that any virtual character with support restricted to a given set is a class function whose support is contained within that same set.*)\nLemma irr_vchar_on A : {subset 'Z[irr G, A] <= 'CF(G, A)}.\n\n(*This lemma states that if a class function belongs to the set of integer combinations of a given sequence of functions with restricted support, then the support of that class function is a subset of the specified restricting set.*)\nLemma support_zchar S A phi : phi \\in 'Z[S, A] -> support phi \\subset A.\n\n(*This lemma states that a class function from a given sequence is an element of the integer span of that sequence, provided the function's support is contained within a specified set.*)\nLemma mem_zchar_on S A phi :\n phi \\in 'CF(G, A) -> phi \\in S -> phi \\in 'Z[S, A].\n\n(*This lemma states that any class function belonging to a given sequence of class functions is also an element of the set of integer linear combinations of that sequence.*)\nLemma mem_zchar S phi : phi \\in S -> phi \\in 'Z[S].\n\n(*This lemma states that any class function in the integer span of a sequence of functions can be written as a finite sum where each term is an element of the sequence scaled by an integer coefficient.*)\nLemma zchar_nth_expansion S A phi :\n phi \\in 'Z[S, A] ->\n {z | forall i, z i \\in Num.int & phi = \\sum_(i < size S) z i *: S`_i}.\n\n(*This lemma states that any class function in the integer span of a tuple of functions can be written as a finite sum where each term is an element of the tuple scaled by an integer coefficient.*)\nLemma zchar_tuple_expansion n (S : n.-tuple 'CF(G)) A phi :\n phi \\in 'Z[S, A] ->\n {z | forall i, z i \\in Num.int & phi = \\sum_(i < n) z i *: S`_i}.\n\n(*This lemma states that if a class function is in the integer span of a sequence of unique class functions, then it can be expressed as a sum over the elements of the sequence, where each element is scaled by an integer coefficient.*)\nLemma zchar_expansion S A phi : uniq S ->\n phi \\in 'Z[S, A] ->\n {z | forall xi, z xi \\in Num.int & phi = \\sum_(xi <- S) z xi *: xi}.\n\n(*This lemma states that the set of integer linear combinations of a sequence of class functions is a subset of the vector space spanned by the same sequence over the complex numbers.*)\nLemma zchar_span S A : {subset 'Z[S, A] <= <>%VS}.\n\n(*This lemma provides a transitivity property, stating that if a first sequence of class functions is contained within the integer span of a second sequence, then the integer span of the first sequence with a given support restriction is a subset of the integer span of the second sequence with the same support restriction.*)\nLemma zchar_trans S1 S2 A B :\n {subset S1 <= 'Z[S2, B]} -> {subset 'Z[S1, A] <= 'Z[S2, A]}.\n\n(*This lemma states that if a first sequence of class functions is contained within the integer span of a second sequence with a given support restriction, then the entire integer span of the first sequence is also a subset of the integer span of the second sequence with the same support restriction.*)\nLemma zchar_trans_on S1 S2 A :\n {subset S1 <= 'Z[S2, A]} -> {subset 'Z[S1] <= 'Z[S2, A]}.\n\n(*This lemma specifies that if every function in a given sequence is a virtual character, then the integer span of that sequence with a given support restriction is a subset of the set of all virtual characters with that same support restriction.*)\nLemma zchar_sub_irr S A :\n {subset S <= 'Z[irr G]} -> {subset 'Z[S, A] <= 'Z[irr G, A]}.\n\n(*This lemma states that if a first collection of class functions is a sub-collection of a second, then the integer span of the first is a subset of the integer span of the second, under the same support restriction.*)\nLemma zchar_subset S1 S2 A :\n {subset S1 <= S2} -> {subset 'Z[S1, A] <= 'Z[S2, A]}.\n\n(*This lemma states that if a first sequence of class functions is a subsequence of a second, then the integer span of the first sequence is a subset of the integer span of the second, given the same support restriction for both.*)\nLemma zchar_subseq S1 S2 A :\n subseq S1 S2 -> {subset 'Z[S1, A] <= 'Z[S2, A]}.\n\n(*This lemma states that the integer span of a sequence of class functions filtered by some predicate is a subset of the integer span of the original, unfiltered sequence, under the same support restriction.*)\nLemma zchar_filter S A (p : pred 'CF(G)) :\n {subset 'Z[filter p S, A] <= 'Z[S, A]}.\n\nEnd Zchar.\n\nSection VChar.\n\nVariables (gT : finGroupType) (G : {group gT}).\nImplicit Types (A B : {set gT}) (phi chi : 'CF(G)) (S : seq 'CF(G)).\n\n(*This lemma states that any character of a group is also a virtual character, meaning it can be expressed as an integer linear combination of the group's irreducible characters.*)\nLemma char_vchar chi : chi \\is a character -> chi \\in 'Z[irr G].\n\n(*This lemma states that every irreducible character of a group is, by definition, an element of the set of virtual characters of that group.*)\nLemma irr_vchar i : 'chi[G]_i \\in 'Z[irr G].\n\n(*This lemma states that the principal character, which is the class function that constantly evaluates to one, is a virtual character.*)\nLemma cfun1_vchar : 1 \\in 'Z[irr G]. \n\n(*This lemma states that a class function is a virtual character if and only if it can be written as the difference of two characters.*)\nLemma vcharP phi :\n reflect (exists2 chi1, chi1 \\is a character\n & exists2 chi2, chi2 \\is a character & phi = chi1 - chi2)\n (phi \\in 'Z[irr G]).\n\n(*This lemma states that the value of a virtual character at any group element is an algebraic integer.*)\nLemma Aint_vchar phi x : phi \\in 'Z[irr G] -> phi x \\in Aint.\n\n(*This lemma states that evaluating a virtual character at the identity element of the group yields an integer.*)\nLemma Cint_vchar1 phi : phi \\in 'Z[irr G] -> phi 1%g \\in Num.int.\n\n(*This lemma states that the class function inner product of a virtual character with any irreducible character results in an integer.*)\nLemma Cint_cfdot_vchar_irr i phi :\n phi \\in 'Z[irr G] -> '[phi, 'chi_i] \\in Num.int.\n\n(*This lemma states that when the second argument is a virtual character, the inner product of two class functions can be computed as a sum over all irreducible characters, where each term is the product of their respective inner products with that irreducible character.*)\nLemma cfdot_vchar_r phi psi :\n psi \\in 'Z[irr G] -> '[phi, psi] = \\sum_i '[phi, 'chi_i] * '[psi, 'chi_i].\n\n(*This lemma states that the class function inner product of any two virtual characters is an integer.*)\nLemma Cint_cfdot_vchar :\n {in 'Z[irr G] &, forall phi psi, '[phi, psi] \\in Num.int}.\n\n(*This lemma states that the norm of a virtual character, computed using the class function inner product, is a non-negative integer.*)\nLemma Cnat_cfnorm_vchar : {in 'Z[irr G], forall phi, '[phi] \\in Num.nat}.\n\n(*This fact asserts that the set of virtual characters is closed under pointwise multiplication.*)\nFact vchar_mulr_closed : mulr_closed 'Z[irr G].\n\n(*This lemma states that for any given subring of algebraic numbers, the set of virtual characters whose values lie within that subring is closed under pointwise multiplication.*)\nLemma mul_vchar A :\n {in 'Z[irr G, A] &, forall phi psi, phi * psi \\in 'Z[irr G, A]}.\n\nSection CfdotPairwiseOrthogonal.\n\nVariables (M : {group gT}) (S : seq 'CF(G)) (nu : 'CF(G) -> 'CF(M)).\nHypotheses (Inu : {in 'Z[S] &, isometry nu}) (oSS : pairwise_orthogonal S).\n\n(*This definition establishes a free basis for a space of class functions, derived from an underlying orthonormal subset of functions.*)\nLet freeS := orthogonal_free oSS.\n(*This definition provides a proof that a linearly independent sequence of class functions contains no duplicate elements.*)\nLet uniqS : uniq S := free_uniq freeS.\n(*This definition establishes that the set of elements in a given sequence of class functions is a subset of the integer-linear span of that same sequence.*)\nLet Z_S : {subset S <= 'Z[S]}. \n(*This definition provides a proof that the zero class function is not present in a given pairwise orthogonal sequence of class functions.*)\nLet notS0 : 0 \\notin S. \n(*This definition extracts the proof that the norm of any class function within a pairwise orthogonal sequence is non-zero.*)\nLet dotSS := proj2 (pairwise_orthogonalP oSS).\n\n(*This lemma states that applying an isometry to each element of a pairwise orthogonal sequence of class functions produces a new sequence that is also pairwise orthogonal.*)\nLemma map_pairwise_orthogonal : pairwise_orthogonal (map nu S).\n\n(*This lemma provides a formula for the inner product between a linear combination of mapped orthogonal class functions and one of the functions from that mapped sequence. The result is the corresponding scalar coefficient multiplied by the original function's norm if the function was included in the combination, and zero otherwise.*)\nLemma cfproj_sum_orthogonal P z phi :\n phi \\in S ->\n '[\\sum_(xi <- S | P xi) z xi *: nu xi, nu phi]\n = if P phi then z phi * '[phi] else 0.\n\n(*This lemma provides a formula for the inner product of two linear combinations of mapped orthogonal class functions. It states the result is the sum, over all functions in the original sequence, of the product of the first scalar coefficient, the complex conjugate of the second scalar coefficient, and the norm of the function.*)\nLemma cfdot_sum_orthogonal z1 z2 :\n '[\\sum_(xi <- S) z1 xi *: nu xi, \\sum_(xi <- S) z2 xi *: nu xi]\n = \\sum_(xi <- S) z1 xi * (z2 xi)^* * '[xi].\n\n(*This lemma provides a formula for the norm of a linear combination of mapped orthogonal class functions. It states the result is the sum, over all functions in the sequence, of the squared magnitude of each scalar coefficient multiplied by the norm of the corresponding function.*)\nLemma cfnorm_sum_orthogonal z :\n '[\\sum_(xi <- S) z xi *: nu xi] = \\sum_(xi <- S) `|z xi| ^+ 2 * '[xi].\n\n(*This lemma states that the norm of the sum of a sequence of mapped orthogonal class functions equals the sum of the individual norms of the functions in the original sequence.*)\nLemma cfnorm_orthogonal : '[\\sum_(xi <- S) nu xi] = \\sum_(xi <- S) '[xi].\n\nEnd CfdotPairwiseOrthogonal.\n\n(*This lemma asserts that any class function lying in the vector span of a pairwise orthogonal sequence can be written as a specific linear combination of the sequence's elements. It provides a formula for the coefficients of this combination, where each coefficient is the inner product of the class function with the corresponding element from the sequence, divided by that element's norm.*)\nLemma orthogonal_span S phi :\n pairwise_orthogonal S -> phi \\in <>%VS ->\n {z | z = fun xi => '[phi, xi] / '[xi] & phi = \\sum_(xi <- S) z xi *: xi}.\n\nSection CfDotOrthonormal.\n\nVariables (M : {group gT}) (S : seq 'CF(G)) (nu : 'CF(G) -> 'CF(M)).\nHypotheses (Inu : {in 'Z[S] &, isometry nu}) (onS : orthonormal S).\n(*This definition establishes that an orthonormal sequence of class functions is, by implication, also a pairwise orthogonal sequence.*)\nLet oSS := orthonormal_orthogonal onS.\n(*This definition provides a proof that a sequence of pairwise orthogonal class functions is linearly independent.*)\nLet freeS := orthogonal_free oSS.\n(*This definition establishes the condition that every class function within a given set has a squared norm equal to one.*)\nLet nS1 : {in S, forall phi, '[phi] = 1}.\n\n(*This lemma states that applying a norm-preserving additive function to each element of an orthonormal sequence of class functions results in a new sequence that is also orthonormal.*)\nLemma map_orthonormal : orthonormal (map nu S).\n\n(*This lemma states that for a sequence of class functions derived from an orthonormal set by a structure-preserving map, the inner product of a linear combination of these functions with one of the functions from the sequence yields its corresponding coefficient in the combination.*)\nLemma cfproj_sum_orthonormal z phi :\n phi \\in S -> '[\\sum_(xi <- S) z xi *: nu xi, nu phi] = z phi.\n\n(*This lemma states that the inner product of two linear combinations of class functions from an orthonormal set is equal to the sum of the products of their corresponding coefficients, with the coefficient from the second linear combination being complex-conjugated.*)\nLemma cfdot_sum_orthonormal z1 z2 :\n '[\\sum_(xi <- S) z1 xi *: xi, \\sum_(xi <- S) z2 xi *: xi]\n = \\sum_(xi <- S) z1 xi * (z2 xi)^*.\n\n(*This lemma states that the squared norm of a linear combination of class functions from a transformed orthonormal set is equal to the sum of the squared magnitudes of the coefficients.*)\nLemma cfnorm_sum_orthonormal z :\n '[\\sum_(xi <- S) z xi *: nu xi] = \\sum_(xi <- S) `|z xi| ^+ 2.\n\n(*This lemma states that the squared norm of the sum of all class functions in a transformed orthonormal sequence is equal to the size of the sequence, interpreted as a real number.*)\nLemma cfnorm_map_orthonormal : '[\\sum_(xi <- S) nu xi] = (size S)%:R.\n\n(*This lemma states that if a class function lies in the vector space spanned by an orthonormal set of class functions, then it can be expressed as a linear combination of the functions in the set, where each coefficient is the inner product of the class function with the corresponding function from the set.*)\nLemma orthonormal_span phi :\n phi \\in <>%VS ->\n {z | z = fun xi => '[phi, xi] & phi = \\sum_(xi <- S) z xi *: xi}.\n\nEnd CfDotOrthonormal.\n\n(*This lemma states that for any orthonormal set of class functions, the squared norm of their sum is equal to the number of functions in the set.*)\nLemma cfnorm_orthonormal S :\n orthonormal S -> '[\\sum_(xi <- S) xi] = (size S)%:R.\n\n(*This lemma provides a reflection property, stating that a set of virtual characters is orthonormal if and only if it is a permutation of a set of irreducible characters, where each irreducible character may optionally be multiplied by negative one.*)\nLemma vchar_orthonormalP S :\n {subset S <= 'Z[irr G]} ->\n reflect (exists I : {set Iirr G}, exists b : Iirr G -> bool,\n perm_eq S [seq (-1) ^+ b i *: 'chi_i | i in I])\n (orthonormal S).\n\n(*This lemma states that if a virtual character has a squared norm equal to one, then it must be either an irreducible character or its additive inverse.*)\nLemma vchar_norm1P phi :\n phi \\in 'Z[irr G] -> '[phi] = 1 ->\n exists b : bool, exists i : Iirr G, phi = (-1) ^+ b *: 'chi_i.\n\n(*This lemma states that if a virtual character has an integer squared norm strictly less than four, then it can be decomposed into a sum of a number of orthonormal virtual characters equal to its squared norm.*)\nLemma zchar_small_norm phi n :\n phi \\in 'Z[irr G] -> '[phi] = n%:R -> (n < 4)%N ->\n {S : n.-tuple 'CF(G) |\n [/\\ orthonormal S, {subset S <= 'Z[irr G]} & phi = \\sum_(xi <- S) xi]}.\n\n(*This lemma states that if a virtual character over the non-identity elements of a group has a squared norm of two, it must be the difference of two distinct irreducible characters.*)\nLemma vchar_norm2 phi :\n phi \\in 'Z[irr G, G^#] -> '[phi] = 2 ->\n exists i, exists2 j, j != i & phi = 'chi_i - 'chi_j.\n\nEnd VChar.\n\nSection Isometries.\n\nVariables (gT : finGroupType) (L G : {group gT}) (S : seq 'CF(L)).\nImplicit Type nu : {additive 'CF(L) -> 'CF(G)}.\n\n(*This lemma states that if two pairwise orthogonal sequences of class functions have the same sequence of squared norms, and the target sequence consists of virtual characters, then there exists a linear map which maps the first sequence to the second and is an isometry on the module of integer-linear combinations of the first sequence.*)\nLemma Zisometry_of_cfnorm (tauS : seq 'CF(G)) :\n pairwise_orthogonal S -> pairwise_orthogonal tauS ->\n map cfnorm tauS = map cfnorm S -> {subset tauS <= 'Z[irr G]} ->\n {tau : {linear 'CF(L) -> 'CF(G)} | map tau S = tauS\n & {in 'Z[S], isometry tau, to 'Z[irr G]}}.\n\n(*This lemma states that a function that acts as an isometry on each element of a linearly independent sequence of class functions can be extended to a linear map that is an isometry on the entire integer-linear span of that sequence.*)\nLemma Zisometry_of_iso f :\n free S -> {in S, isometry f, to 'Z[irr G]} ->\n {tau : {linear 'CF(L) -> 'CF(G)} | {in S, tau =1 f}\n & {in 'Z[S], isometry tau, to 'Z[irr G]}}.\n\n(*This lemma states that any map that is an isometry on a module of linear combinations of class functions is also injective on that module.*)\nLemma Zisometry_inj A nu :\n {in 'Z[S, A] &, isometry nu} -> {in 'Z[S, A] &, injective nu}.\n\n(*This lemma states that if a linear map acts as an isometry on each class function in a given sequence, then it also acts as an isometry on the integer-linear span of that sequence.*)\nLemma isometry_in_zchar nu : {in S &, isometry nu} -> {in 'Z[S] &, isometry nu}.\n\nEnd Isometries.\n\nSection AutVchar.\n\nVariables (u : {rmorphism algC -> algC}) (gT : finGroupType) (G : {group gT}).\n(*This notation defines the application of a class function automorphism, induced by a field automorphism, to a class function.*)\nLocal Notation \"alpha ^u\" := (cfAut u alpha).\nImplicit Type (S : seq 'CF(G)) (phi chi : 'CF(G)).\n\n(*This lemma states that if a set of class functions is closed under a given class function automorphism, then any linear combination of these functions with coefficients from a given ring is also mapped to a linear combination of the same form by that automorphism.*)\nLemma cfAut_zchar S A psi :\n cfAut_closed u S -> psi \\in 'Z[S, A] -> psi^u \\in 'Z[S, A].\n\n(*This lemma states that applying a class function automorphism to a generalized character results in another generalized character of the same type.*)\nLemma cfAut_vchar A psi : psi \\in 'Z[irr G, A] -> psi^u \\in 'Z[irr G, A].\n\n(*This lemma states that if a linear combination of virtual characters and its image under a class function automorphism both belong to a specific module of generalized characters, then their difference belongs to a related module where the coefficients are of a specific algebraic form derived from the automorphism.*)\nLemma sub_aut_zchar S A psi :\n {subset S <= 'Z[irr G]} -> psi \\in 'Z[S, A] -> psi^u \\in 'Z[S, A] ->\n psi - psi^u \\in 'Z[S, A^#].\n\n(*This lemma asserts that for any virtual character, applying a field automorphism that commutes with complex conjugation and then taking the complex conjugate of the result is equivalent to first taking the complex conjugate and then applying the automorphism.*)\nLemma conjC_vcharAut chi x : chi \\in 'Z[irr G] -> (u (chi x))^* = u (chi x)^*.\n\n(*This lemma states that for any two class functions, one of which is a virtual character, the inner product of their images under a class function automorphism is equal to the field automorphism applied to their original inner product.*)\nLemma cfdot_aut_vchar phi chi :\n chi \\in 'Z[irr G] -> '[phi^u , chi^u] = u '[phi, chi].\n\n(*This lemma states that a class function is a generalized character with coefficients in a specific ring if and only if its image under a class function automorphism is also a generalized character with coefficients in the same ring.*)\nLemma vchar_aut A chi : (chi^u \\in 'Z[irr G, A]) = (chi \\in 'Z[irr G, A]).\n\nEnd AutVchar.\n\n(*This definition specifies a version of the class function automorphism for virtual characters where the underlying field automorphism is complex conjugation.*)\nDefinition cfConjC_vchar := cfAut_vchar conjC.\n\nSection MoreVchar.\n\nVariables (gT : finGroupType) (G H : {group gT}).\n\n(*This lemma states that restricting a virtual character of a group to one of its subgroups results in a virtual character of the subgroup.*)\nLemma cfRes_vchar phi : phi \\in 'Z[irr G] -> 'Res[H] phi \\in 'Z[irr H].\n\n(*This lemma states that if a class function is a generalized character of a group with coefficients from a given ring, its restriction to a subgroup is also a generalized character of the subgroup with coefficients from the same ring.*)\nLemma cfRes_vchar_on A phi :\n H \\subset G -> phi \\in 'Z[irr G, A] -> 'Res[H] phi \\in 'Z[irr H, A].\n\n(*This lemma states that inducing a virtual character from a subgroup to the parent group results in a virtual character of the parent group.*)\nLemma cfInd_vchar phi : phi \\in 'Z[irr H] -> 'Ind[G] phi \\in 'Z[irr G].\n\n(*This lemma states that for any generalized character with coefficients in a given ring, the difference between the character and its complex conjugate is a generalized character whose coefficients belong to a related algebraic ring.*)\nLemma sub_conjC_vchar A phi :\n phi \\in 'Z[irr G, A] -> phi - (phi^%CF \\in 'Z[irr G, A^#].\n\n(*This lemma asserts the existence of the Frobenius kernel of a character, which is the normal subgroup consisting of all group elements on which the character takes the same value as it does on the identity element.*)\nLemma Frobenius_kernel_exists :\n [Frobenius G with complement H] -> {K : {group gT} | [Frobenius G = K ><| H]}.\n\nEnd MoreVchar.\n\n(*This definition introduces a predicate on class functions over a given set of group elements. The predicate is true for any class function that is either an irreducible character or the additive inverse of an irreducible character.*)\nDefinition dirr (gT : finGroupType) (B : {set gT}) : {pred 'CF(B)} :=\n [pred f | (f \\in irr B) || (- f \\in irr B)].\nArguments dirr {gT}.\n\nSection Norm1vchar.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This fact states that the set of class functions, where each is either an irreducible character or its opposite, is closed under the additive inverse operation.*)\nFact dirr_oppr_closed : oppr_closed (dirr G).\n\n(*This lemma states that a class function belongs to the set containing irreducible characters and their opposites if and only if its additive inverse also belongs to that set.*)\nLemma dirr_opp v : (- v \\in dirr G) = (v \\in dirr G). \n(*This lemma states that for any natural number, scaling a class function by negative one raised to that number results in a function that belongs to the set of irreducible characters and their opposites if and only if the original class function also belongs to that set.*)\nLemma dirr_sign n v : ((-1)^+ n *: v \\in dirr G) = (v \\in dirr G).\n\n(*This lemma states that any irreducible character of a group is an element of the set containing irreducible characters and their opposites.*)\nLemma irr_dirr i : 'chi_i \\in dirr G.\n\n(*This lemma provides a reflection property, stating that a class function belongs to the set of irreducible characters and their opposites if and only if it can be expressed as some irreducible character scaled by either positive one or negative one.*)\nLemma dirrP f :\n reflect (exists b : bool, exists i, f = (-1) ^+ b *: 'chi_i) (f \\in dirr G).\n\n(*This lemma provides an equivalence, stating that a class function belongs to the set of irreducible characters and their opposites if and only if it is a virtual character and its character norm is equal to one.*)\nLemma dirrE phi : phi \\in dirr G = (phi \\in 'Z[irr G]) && ('[phi] == 1).\n\n(*This lemma states that for any two class functions belonging to the set of irreducible characters and their opposites, their inner product is negative one if one function is the additive inverse of the other, one if they are equal, and zero otherwise.*)\nLemma cfdot_dirr f g : f \\in dirr G -> g \\in dirr G ->\n '[f, g] = (if f == - g then -1 else (f == g)%:R).\n\n(*This lemma states that any virtual character whose character norm is equal to one must belong to the set of irreducible characters and their opposites.*)\nLemma dirr_norm1 phi : phi \\in 'Z[irr G] -> '[phi] = 1 -> phi \\in dirr G.\n\n(*This lemma states that applying a character automorphism to a class function results in a function that belongs to the set of irreducible characters and their opposites if and only if the original class function also belongs to that set.*)\nLemma dirr_aut u phi : (cfAut u phi \\in dirr G) = (phi \\in dirr G).\n\n(*This definition introduces a type that is a pair consisting of a boolean value and an index of an irreducible character. This type is used to represent signed indices for characters.*)\nDefinition dIirr (B : {set gT}) := (bool * (Iirr B))%type.\n\n(*This definition specifies a default signed character index, corresponding to the principal character with a positive sign, represented as a pair of the boolean value false and the natural number zero.*)\nDefinition dirr1 (B : {set gT}) : dIirr B := (false, 0).\n\n(*This definition introduces a function that takes a signed character index and returns a new index where the sign is flipped by negating the boolean component, while leaving the character index unchanged.*)\nDefinition ndirr (B : {set gT}) (i : dIirr B) : dIirr B :=\n (~~ i.1, i.2).\n\n(*This lemma states that applying the sign-flipping operation to any signed character index always results in a different index.*)\nLemma ndirr_diff (i : dIirr G) : ndirr i != i.\n\n(*This lemma states that the sign-flipping operation for signed character indices is an involution, meaning applying it twice returns the original index.*)\nLemma ndirrK : involutive (@ndirr G).\n\n(*This lemma states that the sign-flipping operation for signed character indices is injective.*)\nLemma ndirr_inj : injective (@ndirr G).\n\n(*This definition introduces a function that constructs a class function from a signed character index. The resulting class function is the irreducible character corresponding to the index part, scaled by either positive one or negative one according to the boolean sign part.*)\nDefinition dchi (B : {set gT}) (i : dIirr B) : 'CF(B) := (-1)^+ i.1 *: 'chi_i.2.\n\n(*This lemma states that the class function constructed from the default signed character index, which represents the principal character with a positive sign, is the constant one function.*)\nLemma dchi1 : dchi (dirr1 G) = 1.\n\n(*This lemma states that any class function constructed from a signed character index belongs to the set of irreducible characters and their opposites.*)\nLemma dirr_dchi i : dchi i \\in dirr G.\n\n(*This lemma provides a reflection property, stating that a class function belongs to the set of irreducible characters and their opposites if and only if it can be constructed from a signed character index.*)\nLemma dIrrP phi : reflect (exists i, phi = dchi i) (phi \\in dirr G).\n\n(*This lemma states that the class function constructed from a sign-flipped index is the additive inverse of the class function constructed from the original index.*)\nLemma dchi_ndirrE (i : dIirr G) : dchi (ndirr i) = - dchi i.\n\n(*This lemma provides a formula for the inner product of two class functions constructed from signed character indices. The result is one if the indices are identical, negative one if one index is the sign-flipped version of the other, and zero otherwise.*)\nLemma cfdot_dchi (i j : dIirr G) : \n '[dchi i, dchi j] = (i == j)%:R - (i == ndirr j)%:R.\n\n(*This lemma states that any class function constructed from a signed character index is a virtual character.*)\nLemma dchi_vchar i : dchi i \\in 'Z[irr G].\n\n(*This lemma states that the character norm of any class function constructed from a signed character index is equal to one.*)\nLemma cfnorm_dchi (i : dIirr G) : '[dchi i] = 1.\n\n(*This lemma states that the function which constructs a class function from a signed character index is injective, meaning distinct signed indices map to distinct class functions.*)\nLemma dirr_inj : injective (@dchi G).\n\n(*This definition introduces a function that computes the signed character index corresponding to a given class function from a family of class functions. If a matching signed index exists, it is returned; otherwise, a default index is returned.*)\nDefinition dirr_dIirr (B : {set gT}) J (f : J -> 'CF(B)) j : dIirr B :=\n odflt (dirr1 B) [pick i | dchi i == f j].\n\n(*This lemma states that for a family of class functions, if all functions corresponding to indices that satisfy a given predicate belong to the set of irreducible characters and their opposites, then for any such index, converting the function to its signed character index and back will recover the original function.*)\nLemma dirr_dIirrPE J (f : J -> 'CF(G)) (P : pred J) :\n (forall j, P j -> f j \\in dirr G) ->\n forall j, P j -> dchi (dirr_dIirr f j) = f j.\n\n(*This lemma states that if every function in a given family of class functions belongs to the set of irreducible characters and their opposites, then for any index, converting the function to its signed character index and back will recover the original function.*)\nLemma dirr_dIirrE J (f : J -> 'CF(G)) :\n (forall j, f j \\in dirr G) -> forall j, dchi (dirr_dIirr f j) = f j.\n\n(*This definition specifies a set of signed character indices associated with a given class function. The set includes all signed indices for which the inner product of the given class function with the character corresponding to the index is positive.*)\nDefinition dirr_constt (B : {set gT}) (phi: 'CF(B)) : {set (dIirr B)} :=\n [set i | 0 < '[phi, dchi i]].\n\n(*This lemma provides an equivalence for membership in the set of signed constituent characters. It states that a signed character index belongs to this set for a given class function if and only if the inner product of the class function and the character corresponding to the index is positive.*)\nLemma dirr_consttE (phi : 'CF(G)) (i : dIirr G) :\n (i \\in dirr_constt phi) = (0 < '[phi, dchi i]).\n\n(*This lemma states that if a class function is an integer linear combination of irreducible characters, then its scalar product with any of its associated directed irreducible character constituents results in a natural number.*)\nLemma Cnat_dirr (phi : 'CF(G)) i :\n phi \\in 'Z[irr G] -> i \\in dirr_constt phi -> '[phi, dchi i] \\in Num.nat.\n\n(*This lemma states that a directed irreducible character is a constituent of the additive inverse of a class function if and only if the opposite directed character is a constituent of the original class function.*)\nLemma dirr_constt_oppr (i : dIirr G) (phi : 'CF(G)) :\n (i \\in dirr_constt (-phi)) = (ndirr i \\in dirr_constt phi).\n\n(*This lemma states that for any class function, the set of its directed irreducible constituents is disjoint from the set of directed irreducible constituents of its additive inverse.*)\nLemma dirr_constt_oppI (phi: 'CF(G)) :\n dirr_constt phi :&: dirr_constt (-phi) = set0.\n\n(*This lemma states that if a directed irreducible character is a constituent of a given class function, then the opposite of that directed character is not a constituent of the same class function.*)\nLemma dirr_constt_oppl (phi: 'CF(G)) i :\n i \\in dirr_constt phi -> (ndirr i) \\notin dirr_constt phi.\n\n(*This definition specifies a function that converts an irreducible character into a directed irreducible character, relative to a given class function. The direction is a boolean value indicating whether the scalar product of the class function and the original character is negative, and the second component is the original irreducible character itself.*)\nDefinition to_dirr (B : {set gT}) (phi : 'CF(B)) (i : Iirr B) : dIirr B :=\n ('[phi, 'chi_i] < 0, i).\n\n(*This definition describes a function that recovers the original irreducible character from a directed irreducible character by projecting onto the second component of the pair.*)\nDefinition of_irr (B : {set gT}) (i : dIirr B) : Iirr B := i.2.\n\n(*This lemma states that for a class function that is an integer combination of irreducible characters, an irreducible character is a constituent of the function if and only if its corresponding directed version is a directed constituent of the same function.*)\nLemma irr_constt_to_dirr (phi: 'CF(G)) i : phi \\in 'Z[irr G] ->\n (i \\in irr_constt phi) = (to_dirr phi i \\in dirr_constt phi).\n\n(*This lemma states that for any given class function, converting an irreducible character to its directed version and then extracting the underlying irreducible character from the result yields the original irreducible character.*)\nLemma to_dirrK (phi: 'CF(G)) : cancel (to_dirr phi) (@of_irr G).\n\n(*This lemma states that for any class function, if you take a directed irreducible character that is a constituent of that function, extract its underlying irreducible character, and then convert it back to a directed character using the same class function, you obtain the original directed irreducible character.*)\nLemma of_irrK (phi: 'CF(G)) :\n {in dirr_constt phi, cancel (@of_irr G) (to_dirr phi)}.\n\n(*This lemma states that for any class function and any irreducible character, the class function resulting from scaling the associated directed character by its scalar product with the original class function is identical to the class function resulting from scaling the original non-directed character by its scalar product with the original class function.*)\nLemma cfdot_todirrE (phi: 'CF(G)) i (phi_i := dchi (to_dirr phi i)) :\n '[phi, phi_i] *: phi_i = '[phi, 'chi_i] *: 'chi_i.\n\n(*This lemma states that any class function that is an integer linear combination of irreducible characters is equal to the sum, over all its directed irreducible constituents, of terms where each term is the directed character scaled by its scalar product with the original class function.*)\nLemma cfun_sum_dconstt (phi : 'CF(G)) :\n phi \\in 'Z[irr G] ->\n phi = \\sum_(i in dirr_constt phi) '[phi, dchi i] *: dchi i.\n\n(*This lemma states that for any class function that is an integer linear combination of irreducible characters, its squared norm is the sum of the squares of its scalar products with each of its directed irreducible character constituents.*)\nLemma cnorm_dconstt (phi : 'CF(G)) :\n phi \\in 'Z[irr G] ->\n '[phi] = \\sum_(i in dirr_constt phi) '[phi, dchi i] ^+ 2.\n\n(*This lemma states that if a class function is an integer linear combination of irreducible characters and its squared norm is a natural number less than four, then three properties hold: the number of its directed irreducible constituents equals its squared norm; the set of its directed constituents is disjoint from the set of constituents of its additive inverse; and the class function itself is equal to the sum of its directed character constituents.*)\nLemma dirr_small_norm (phi : 'CF(G)) n :\n phi \\in 'Z[irr G] -> '[phi] = n%:R -> (n < 4)%N ->\n [/\\ #|dirr_constt phi| = n, dirr_constt phi :&: dirr_constt (- phi) = set0 &\n phi = \\sum_(i in dirr_constt phi) dchi i].\n\n(*This lemma gives an explicit formula for the scalar product of two class functions, each being the sum of their respective directed character constituents. The result is given by the number of directed constituents common to both functions, minus the number of constituents in the first function whose opposites are constituents in the second function.*)\nLemma cfdot_sum_dchi (phi1 phi2 : 'CF(G)) :\n '[\\sum_(i in dirr_constt phi1) dchi i,\n \\sum_(i in dirr_constt phi2) dchi i] =\n #|dirr_constt phi1 :&: dirr_constt phi2|%:R -\n #|dirr_constt phi1 :&: dirr_constt (- phi2)|%:R.\n\n(*This lemma states that for any two directed irreducible characters, their scalar product equals one if and only if the two characters are identical.*)\nLemma cfdot_dirr_eq1 :\n {in dirr G &, forall phi psi, ('[phi, psi] == 1) = (phi == psi)}.\n\n(*This lemma states that for any three normal virtual characters of a finite group, if the inner product of the sum of the first two characters with the third is equal to one, then the third character must be identical to either the first or the second character.*)\nLemma cfdot_add_dirr_eq1 :\n {in dirr G & &, forall phi1 phi2 psi,\n '[phi1 + phi2, psi] = 1 -> psi = phi1 \\/ psi = phi2}.\n\nEnd Norm1vchar.\n\nPrenex Implicits ndirr ndirrK to_dirr to_dirrK of_irr.", - "character.integral_char": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype tuple finfun bigop prime order.\nFrom mathcomp Require Import ssralg poly finset fingroup morphism perm.\nFrom mathcomp Require Import automorphism quotient action countalg finalg zmodp.\nFrom mathcomp Require Import commutator cyclic center pgroup sylow gseries.\nFrom mathcomp Require Import nilpotent abelian ssrnum ssrint archimedean.\nFrom mathcomp Require Import polydiv rat matrix mxalgebra intdiv mxpoly vector.\nFrom mathcomp Require Import falgebra fieldext separable galois algC cyclotomic.\nFrom mathcomp Require Import algnum mxrepresentation classfun character.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport Order.TTheory GroupScope GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\n(*This lemma states that for any given finite group, there exists a number field that is a Galois splitting field over the rational numbers. This field can be embedded into the field of algebraic numbers, and it contains a primitive root of unity whose order is the size of the given group. Furthermore, this number field is guaranteed to contain the values of all characters for any group element whose order divides the size of the original group.*)\nLemma group_num_field_exists (gT : finGroupType) (G : {group gT}) :\n {Qn : splittingFieldType rat & galois 1 {:Qn} &\n {QnC : {rmorphism Qn -> algC}\n & forall nuQn : argumentType [in 'Gal({:Qn} / 1)],\n {nu : {rmorphism algC -> algC} |\n {morph QnC: a / nuQn a >-> nu a}}\n & {w : Qn & #|G|.-primitive_root w /\\ <<1; w>>%VS = fullv\n & forall (hT : finGroupType) (H : {group hT}) (phi : 'CF(H)),\n phi \\is a character ->\n forall x, (#[x] %| #|G|)%N -> {a | QnC a = phi x}}}}.\n\nSection GenericClassSums.\n\nVariable (gT : finGroupType) (G : {group gT}) (F : fieldType).\n\n(*This definition computes a set of pairs of group elements. Given two input sets of group elements and a target group element, it returns the set containing all pairs where the first element of the pair is from the first input set, the second element is from the second input set, and their group product equals the target element.*)\nDefinition gring_classM_coef_set (Ki Kj : {set gT}) g :=\n [set xy in [predX Ki & Kj] | let: (x, y) := xy in x * y == g]%g.\n\n(*This definition computes a structure coefficient for the center of a group algebra. Given three indices corresponding to conjugacy classes of a group, it returns a natural number representing the count of pairs of group elements whose product equals a representative of the third class, where the first element of the pair is drawn from the first class and the second element is from the second class.*)\nDefinition gring_classM_coef (i j k : 'I_#|classes G|) :=\n #|gring_classM_coef_set (enum_val i) (enum_val j) (repr (enum_val k))|.\n\n(*This definition constructs an element within the center of a group algebra over a given field. Given an index that identifies a conjugacy class of a group, it returns the element of the group algebra corresponding to the formal sum of all elements in that class, with each element having a coefficient of one.*)\nDefinition gring_class_sum (i : 'I_#|classes G|) := gset_mx F G (enum_val i).\n\n(*This notation defines a shorthand for the formal sum of elements belonging to a specific conjugacy class of a group. It takes an index of a conjugacy class and represents the corresponding element in the center of the group algebra, which is the sum of all elements in that class.*)\nLocal Notation \"''K_' i\" := (gring_class_sum i)\n (at level 8, i at level 2, format \"''K_' i\") : ring_scope.\n(*This notation provides a shorthand for the structure constants of the center of a group ring. For three given indices of conjugacy classes, it represents the coefficient of the class sum corresponding to the third index in the basis expansion of the product of the class sums corresponding to the first two indices.*)\nLocal Notation a := gring_classM_coef.\n\n(*This lemma states that for any given index of a conjugacy class, the corresponding formal sum of the elements in that class belongs to the center of the group algebra. This implies that the class sum commutes with all elements of the group algebra under multiplication.*)\nLemma gring_class_sum_central i : ('K_i \\in 'Z(group_ring F G))%MS.\n\n(*This lemma states that the structure coefficient for the center of the group algebra is well-defined and independent of the choice of representative from the target conjugacy class. Given three indices for conjugacy classes and an element from the third class, the lemma asserts that the structure coefficient is equal to the number of pairs, with elements from the first and second classes respectively, whose group product is that chosen element.*)\nLemma set_gring_classM_coef (i j k : 'I_#|classes G|) g :\n g \\in enum_val k ->\n a i j k = #|gring_classM_coef_set (enum_val i) (enum_val j) g|.\n\n(*This theorem describes the multiplication rule for the basis of class sums within the center of a group algebra. It states that the product of two class sums is equal to a linear combination of all class sums, where the scalar coefficient for each class sum in the expansion is the corresponding structure coefficient computed from the indices of the three relevant conjugacy classes.*)\nTheorem gring_classM_expansion i j : 'K_i *m 'K_j = \\sum_k (a i j k)%:R *: 'K_k.\n\nEnd GenericClassSums.\n\n(*This definition computes a specific class function, known as a central character or a primitive central idempotent of the group algebra. For a given index of an irreducible character of a group, it returns a new class function created by scaling the irreducible character by the multiplicative inverse of its value at the identity element, which corresponds to the degree of the character.*)\nHB.lock Definition gring_irr_mode (gT : finGroupType) (G : {group gT})\n (i : Iirr G) := ('chi_i 1%g)^-1 *: 'chi_i.\nCanonical gring_irr_mode_unlockable := Unlockable gring_irr_mode.unlock.\nArguments gring_irr_mode {gT G%_G} i%_R _%_g : extra scopes.\n\n(*A notation that represents the sum of all elements in the i-th conjugacy class of a group, viewed as a single element in the corresponding group ring.*)\nNotation \"''K_' i\" := (gring_class_sum _ i)\n (at level 8, i at level 2, format \"''K_' i\") : ring_scope.\n\n(*A notation that takes an index for an irreducible representation and a central element of a group ring, and returns the scalar value by which that central element acts on the vector space of the corresponding irreducible representation.*)\nNotation \"''omega_' i [ A ]\" := (xcfun (gring_irr_mode i) A)\n (at level 8, i at level 2, format \"''omega_' i [ A ]\") : ring_scope.\n\nSection IntegralChar.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that for any character of a finite group, its value at any group element is an algebraic integer.*)\nLemma Aint_char (chi : 'CF(G)) x : chi \\is a character -> chi x \\in Aint.\n\n(*This lemma states that the value of any irreducible character of a finite group at any group element is an algebraic integer.*)\nLemma Aint_irr i x : 'chi[G]_i x \\in Aint.\n\n(*This local notation defines an alias for the group ring of a given finite group over the field of algebraic numbers.*)\nLocal Notation R_G := (group_ring algCfield G).\n(*This notation provides a compact alias for the function that computes the structure coefficients of the center of a group algebra, which count how pairs of elements from two conjugacy classes multiply to yield an element of a third class.*)\nLocal Notation a := gring_classM_coef.\n\n(*This lemma states that for any irreducible matrix representation of a finite group, a central element of the group ring acts as a scalar matrix.*)\nLemma mx_irr_gring_op_center_scalar n (rG : mx_representation algCfield G n) A :\n mx_irreducible rG -> (A \\in 'Z(R_G))%MS -> is_scalar_mx (gring_op rG A).\n\nSection GringIrrMode.\n\nVariable i : Iirr G.\n\n(*This definition assigns the degree of the irreducible representation corresponding to a given index to a local variable.*)\nLet n := irr_degree (socle_of_Iirr i).\n(*This definition establishes that the function mapping a scalar to a scalar matrix of a given dimension over the algebraic numbers is injective.*)\nLet mxZn_inj: injective (@scalar_mx algCfield n).\n\n(*This lemma states that if a matrix representation has the i-th irreducible character as its character, then any central element of the group ring acts on this representation as the scalar matrix corresponding to the i-th group ring mode of that central element.*)\nLemma cfRepr_gring_center n1 (rG : mx_representation algCfield G n1) A :\n cfRepr rG = 'chi_i -> (A \\in 'Z(R_G))%MS -> gring_op rG A = 'omega_i[A]%:M.\n\n(*This lemma states that a central element of the group ring acts on the i-th canonical irreducible representation as the scalar matrix corresponding to the i-th group ring mode of that central element.*)\nLemma irr_gring_center A :\n (A \\in 'Z(R_G))%MS -> gring_op 'Chi_i A = 'omega_i[A]%:M.\n\n(*This lemma states that the group ring mode function for the i-th irreducible character is a ring homomorphism, meaning it preserves multiplication for central elements of the group ring.*)\nLemma gring_irr_modeM A B :\n (A \\in 'Z(R_G))%MS -> (B \\in 'Z(R_G))%MS ->\n 'omega_i[A *m B] = 'omega_i[A] * 'omega_i[B].\n\n(*This lemma provides a formula for the i-th group ring mode of a class sum. It states that this value is equal to the size of the conjugacy class of an element in that class, times the value of the i-th irreducible character on that element, divided by the degree of the character.*)\nLemma gring_mode_class_sum_eq (k : 'I_#|classes G|) g :\n g \\in enum_val k -> 'omega_i['K_k] = #|g ^: G|%:R * 'chi_i g / 'chi_i 1%g.\n\n(*This lemma states that the group ring mode of a class sum, for any irreducible character, is an algebraic integer.*)\nLemma Aint_gring_mode_class_sum k : 'omega_i['K_k] \\in Aint.\n\n(*This corollary states that for any element of a finite group and any irreducible character, the product of the size of the element's conjugacy class and the character's value at that element, divided by the character's degree, results in an algebraic integer.*)\nCorollary Aint_class_div_irr1 x :\n x \\in G -> #|x ^: G|%:R * 'chi_i x / 'chi_i 1%g \\in Aint.\n\n(*This theorem states that if the degree of an irreducible character is coprime to the size of the conjugacy class of a group element, and that element is not in the center of the character, then the character must evaluate to zero on that element.*)\nTheorem coprime_degree_support_cfcenter g :\n coprime (Num.truncn ('chi_i 1%g)) #|g ^: G| -> g \\notin ('Z('chi_i))%CF ->\n 'chi_i g = 0.\n\nEnd GringIrrMode.\n\n(*This theorem states that for any non-abelian simple finite group, the size of any conjugacy class, other than the trivial class of the identity element, must be divisible by at least two distinct prime numbers.*)\nTheorem primes_class_simple_gt1 C :\n simple G -> ~~ abelian G -> C \\in (classes G)^# -> (size (primes #|C|) > 1)%N.\n\nEnd IntegralChar.\n\nSection MoreIntegralChar.\n\nImplicit Type gT : finGroupType.\n\n(*This theorem, known as Burnside's p-a q-b theorem, states that any finite group whose order is divisible by at most two distinct prime numbers is a solvable group.*)\nTheorem Burnside_p_a_q_b gT (G : {group gT}) :\n (size (primes #|G|) <= 2)%N -> solvable G.\n\n(*This theorem states that the degree of any irreducible character of a finite group must divide the order of the group.*)\nTheorem dvd_irr1_cardG gT (G : {group gT}) i : ('chi[G]_i 1%g %| #|G|)%C.\n\n(*This theorem states that the degree of an irreducible character of a finite group must divide the index of the center of that character in the group.*)\nTheorem dvd_irr1_index_center gT (G : {group gT}) i :\n ('chi[G]_i 1%g %| #|G : 'Z('chi_i)%CF|)%C.\n\n(*This lemma provides a formula for the structure coefficients of the center of the group algebra. It expresses the coefficient for a product of two class sums in terms of a weighted sum over the irreducible characters of the group, involving character values on representatives of the respective conjugacy classes.*)\nLemma gring_classM_coef_sum_eq gT (G : {group gT}) j1 j2 k g1 g2 g :\n let a := @gring_classM_coef gT G j1 j2 in let a_k := a k in\n g1 \\in enum_val j1 -> g2 \\in enum_val j2 -> g \\in enum_val k ->\n let sum12g := \\sum_i 'chi[G]_i g1 * 'chi_i g2 * ('chi_i g)^* / 'chi_i 1%g in\n a_k%:R = (#|enum_val j1| * #|enum_val j2|)%:R / #|G|%:R * sum12g.\n\n(*This lemma states that for a character of a group, if the support of the character is a subgroup and either this subgroup is trivial or the parent group is abelian, then the index of the subgroup in the parent group must divide the degree of the character.*)\nLemma index_support_dvd_degree gT (G H : {group gT}) chi :\n H \\subset G -> chi \\is a character -> chi \\in 'CF(G, H) ->\n (H :==: 1%g) || abelian G ->\n (#|G : H| %| chi 1%g)%C.\n\n(*This theorem states that if a faithful irreducible character of a group has a degree which is a power of a prime number, and the Sylow subgroup for that prime is abelian, then the degree of the character is equal to the p-part of the index of the center of the group.*)\nTheorem faithful_degree_p_part gT (p : nat) (G P : {group gT}) i :\n cfaithful 'chi[G]_i -> p.-nat (Num.truncn ('chi_i 1%g)) ->\n p.-Sylow(G) P -> abelian P ->\n 'chi_i 1%g = (#|G : 'Z(G)|`_p)%:R.\n\n(*This lemma concerns a property of the sum of the squared norm of the values of a character of a finite group, evaluated on the elements of a generating set for that group.*)\nLemma sum_norm2_char_generators gT (G : {group gT}) (chi : 'CF(G)) :\n let S := [pred s | generator G s] in\n chi \\is a character -> {in S, forall s, chi s != 0} ->\n \\sum_(s in S) `|chi s| ^+ 2 >= #|S|%:R.\n\n(*This theorem asserts that for any non-abelian finite group, there exists at least one non-linear irreducible character and at least one group element on which this character evaluates to zero.*)\nTheorem nonlinear_irr_vanish gT (G : {group gT}) i :\n 'chi[G]_i 1%g > 1 -> exists2 x, x \\in G & 'chi_i x = 0.", - "character.all_character": "From mathcomp Require Export character.\nFrom mathcomp Require Export classfun.\nFrom mathcomp Require Export inertia.\nFrom mathcomp Require Export integral_char.\nFrom mathcomp Require Export mxabelem.\nFrom mathcomp Require Export mxrepresentation.", - "character.classfun": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype tuple finfun bigop prime order.\nFrom mathcomp Require Import ssralg poly finset fingroup morphism perm.\nFrom mathcomp Require Import automorphism quotient finalg action gproduct zmodp.\nFrom mathcomp Require Import commutator cyclic center pgroup sylow matrix.\nFrom mathcomp Require Import vector falgebra ssrnum algC algnum archimedean.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope cfun_scope.\n\nImport Order.TTheory GroupScope GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\nDelimit Scope cfun_scope with CF.\n\nReserved Notation \"''CF' ( G , A )\" (format \"''CF' ( G , A )\").\nReserved Notation \"''CF' ( G )\" (format \"''CF' ( G )\").\nReserved Notation \"''1_' G\" (at level 8, G at level 2, format \"''1_' G\").\nReserved Notation \"''Res[' H , G ]\". \nReserved Notation \"''Res[' H ]\" (format \"''Res[' H ]\").\nReserved Notation \"''Res'\". \nReserved Notation \"''Ind[' G , H ]\". \nReserved Notation \"''Ind[' G ]\". \nReserved Notation \"''Ind'\". \nReserved Notation \"'[ phi , psi ]_ G\" (at level 0). \nReserved Notation \"'[ phi ]_ G\" (at level 0). \nReserved Notation \"phi ^u\" (format \"phi ^u\").\n\nSection AlgC.\n\nVariable (gT : finGroupType).\nImplicit Types (G : {group gT}) (B : {set gT}).\n\n(*This lemma states that for any finite group, its order, when interpreted as an algebraic number, is not equal to zero.*)\nLemma neq0CG G : (#|G|)%:R != 0 :> algC. \n(*This lemma states that for any finite group and a subset of that group, the index of the subset within the group, when interpreted as an algebraic number, is not equal to zero.*)\nLemma neq0CiG G B : (#|G : B|)%:R != 0 :> algC.\n\n(*This lemma states that for any finite group, its order, when interpreted as an algebraic number, is strictly greater than zero.*)\nLemma gt0CG G : 0 < #|G|%:R :> algC. \n(*This lemma states that for any finite group and a subset of that group, the index of the subset within the group, when interpreted as an algebraic number, is strictly greater than zero.*)\nLemma gt0CiG G B : 0 < #|G : B|%:R :> algC. \n\n(*This lemma states that for any finite group, the space of partial characters with values in the algebraic numbers forms a prime characteristic group structure.*)\nLemma algC'G_pchar G : [pchar algC]^'.-group G.\n\nEnd AlgC.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use algC'G_pchar instead.\")]\n(*A deprecated notation for the prime characteristic group structure formed by partial characters with values in the algebraic numbers over a finite group.*)\nNotation algC'G := (algC'G_pchar) (only parsing).\n\nSection Defs.\n\nVariable gT : finGroupType.\n\n(*This definition specifies the properties of a class function on a subset of a finite group. A function satisfies these properties if it is constant on the conjugacy classes within the given subset and its support is contained within that same subset.*)\nDefinition is_class_fun (B : {set gT}) (f : {ffun gT -> algC}) :=\n [forall x, forall y in B, f (x ^ y) == f x] && (support f \\subset B).\n\n(*This lemma provides a construction rule for a class function. It states that a function on a finite group type is a class function of a given group if it is constant on the conjugacy classes of the group and is zero for all elements outside the group.*)\nLemma intro_class_fun (G : {group gT}) f :\n {in G &, forall x y, f (x ^ y) = f x} ->\n (forall x, x \\notin G -> f x = 0) ->\n is_class_fun G (finfun f).\n\nVariable B : {set gT}.\n(*A local notation for the carrier type of a group structure, typically representing the main group being considered in the current context.*)\nLocal Notation G := <>.\n\n(*A record that defines the type for class functions. A class function is represented as a finite-domain function from a group type to the algebraic numbers, bundled with a proof that it is constant on conjugacy classes and supported on a specific group.*)\nRecord classfun : predArgType :=\n Classfun {cfun_val; _ : is_class_fun G cfun_val}.\nImplicit Types phi psi xi : classfun.\n\n(*A fact defining a key of unit type, used internally to lock the constructor for class functions, following a design pattern for building canonical structures.*)\nFact classfun_key : unit. \n(*This definition provides a locked constructor for creating instances of the class function type. It wraps the raw constructor and controls its usage through a key, a common pattern for managing structured types.*)\nDefinition Cfun := locked_with classfun_key (fun flag : nat => Classfun).\n\nHB.instance Definition _ := [isSub for cfun_val].\nHB.instance Definition _ := [Choice of classfun by <:].\n\n(*This definition establishes that the type of class functions is equipped with a decidable equality relation.*)\nDefinition cfun_eqType : eqType := classfun.\n\n(*This definition defines a coercion that allows a class function to be automatically treated as its underlying function from the group type to the algebraic numbers.*)\nDefinition fun_of_cfun phi := cfun_val phi : gT -> algC.\nCoercion fun_of_cfun : classfun >-> Funclass.\n\n(*This lemma states that creating a class function from a given function using the locked constructor, and then coercing it back to a function, results in a function that is pointwise equal to the original function.*)\nLemma cfunElock k f fP : @Cfun k (finfun f) fP =1 f.\n\n(*This lemma states that creating a class function from a given function using the standard constructor, and then coercing it back to a function, results in a function that is pointwise equal to the original function.*)\nLemma cfunE f fP : @Cfun 0 (finfun f) fP =1 f.\n\n(*This lemma establishes the principle of extensionality for class functions, stating that two class functions are equal if and only if their underlying functions are pointwise equal.*)\nLemma cfunP phi psi : phi =1 psi <-> phi = psi.\n\n(*This lemma states that a class function defined over a group evaluates to zero for any element that is not in that group.*)\nLemma cfun0gen phi x : x \\notin G -> phi x = 0.\n\n(*This lemma states that two class functions are equal if they are pointwise equal on all elements belonging to their underlying group.*)\nLemma cfun_in_genP phi psi : {in G, phi =1 psi} -> phi = psi.\n\n(*This lemma states that a class function's value at a given element is unchanged when that element is conjugated by any element from the underlying group.*)\nLemma cfunJgen phi x y : y \\in G -> phi (x ^ y) = phi x.\n\n(*A fact that provides the proof that the constant zero function satisfies the properties of a class function over any given group.*)\nFact cfun_zero_subproof : is_class_fun G (0 : {ffun _}).\n\n(*This definition introduces the zero class function, which is the class function corresponding to the function that maps every element to zero.*)\nDefinition cfun_zero := Cfun 0 cfun_zero_subproof.\n\n(*A fact that provides the proof that composing a class function with another function that maps zero to zero results in a new function that also satisfies the properties of a class function.*)\nFact cfun_comp_subproof f phi :\n f 0 = 0 -> is_class_fun G [ffun x => f (phi x)].\n\n(*This definition creates a new class function by composing a given class function with an external function that maps zero to zero.*)\nDefinition cfun_comp f f0 phi := Cfun 0 (@cfun_comp_subproof f phi f0).\n(*This definition provides the additive inverse of a class function, obtained by applying the ring's opposition operation to the value of the function at each point.*)\nDefinition cfun_opp := cfun_comp (oppr0 _).\n\n(*A fact proving that the pointwise sum of two class functions results in a function that also satisfies the properties of a class function.*)\nFact cfun_add_subproof phi psi : is_class_fun G [ffun x => phi x + psi x].\n\n(*This definition specifies the addition of two class functions as the new class function obtained by taking their pointwise sum.*)\nDefinition cfun_add phi psi := Cfun 0 (cfun_add_subproof phi psi).\n\n(*A fact proving that an indicator function for a union of conjugacy classes is a class function. The function is one for elements whose conjugacy class is contained in a given set, and zero otherwise.*)\nFact cfun_indicator_subproof (A : {set gT}) :\n is_class_fun G [ffun x => ((x \\in G) && (x ^: G \\subset A))%:R].\n\n(*This definition creates the indicator class function for a given set. The resulting function evaluates to one for any element whose entire conjugacy class is contained within the set, and to zero otherwise.*)\nDefinition cfun_indicator A := Cfun 1 (cfun_indicator_subproof A).\n(*A notation for the indicator class function of a given set. This function evaluates to one for elements whose conjugacy class is contained entirely within the set, and zero otherwise.*)\nLocal Notation \"''1_' A\" := (cfun_indicator A) : ring_scope.\n\n(*This lemma states that evaluating the multiplicative identity class function at any element of the group yields the multiplicative identity of the codomain ring.*)\nLemma cfun1Egen x : '1_G x = (x \\in G)%:R.\n\n(*This fact establishes that the pointwise product of two class functions on a group is itself a class function on that group.*)\nFact cfun_mul_subproof phi psi : is_class_fun G [ffun x => phi x * psi x].\n\n(*This definition specifies the multiplication of two class functions as their pointwise product, resulting in a new class function.*)\nDefinition cfun_mul phi psi := Cfun 0 (cfun_mul_subproof phi psi).\n\n(*This definition specifies the set of unit class functions as those that never evaluate to the zero element of the codomain ring for any element of the group.*)\nDefinition cfun_unit := [pred phi : classfun | [forall x in G, phi x != 0]].\n(*This definition provides the pointwise multiplicative inverse of a class function. If the given class function is a unit, meaning it never evaluates to zero, the result is a new class function where each value is the multiplicative inverse of the original value; otherwise, the original function is returned.*)\nDefinition cfun_inv phi :=\n if phi \\in cfun_unit then cfun_comp (invr0 _) phi else phi.\n\n(*This definition defines the scaling of a class function by a scalar from the coefficient ring. The resulting class function is obtained by pointwise multiplication of the original function's values by the scalar.*)\nDefinition cfun_scale a := cfun_comp (mulr0 a).\n\n(*This fact asserts that the addition of class functions is an associative operation.*)\nFact cfun_addA : associative cfun_add.\n\n(*This fact asserts that the addition of class functions is a commutative operation.*)\nFact cfun_addC : commutative cfun_add.\n\n(*This fact asserts that the zero class function serves as the left identity element for class function addition.*)\nFact cfun_add0 : left_id cfun_zero cfun_add.\n\n(*This fact asserts that for any class function, its opposite, obtained by pointwise negation, acts as its left additive inverse.*)\nFact cfun_addN : left_inverse cfun_zero cfun_opp cfun_add.\n\nHB.instance Definition _ := GRing.isZmodule.Build classfun\n cfun_addA cfun_addC cfun_add0 cfun_addN.\n\n(*This lemma states that multiplying a class function by a natural number and then evaluating it at a group element is equivalent to first evaluating the class function at that element and then multiplying the resulting ring value by the natural number.*)\nLemma muln_cfunE phi n x : (phi *+ n) x = phi x *+ n.\n\n(*This lemma states that evaluating a filtered finite sum of class functions at a group element yields the same result as performing the same filtered sum on the values obtained by evaluating each individual class function at that same element.*)\nLemma sum_cfunE I r (P : pred I) (phi : I -> classfun) x :\n (\\sum_(i <- r | P i) phi i) x = \\sum_(i <- r | P i) (phi i) x.\n\n(*This fact asserts that the multiplication of class functions is an associative operation.*)\nFact cfun_mulA : associative cfun_mul.\n\n(*This fact asserts that the multiplication of class functions is a commutative operation.*)\nFact cfun_mulC : commutative cfun_mul.\n\n(*This fact asserts that the identity class function corresponding to the whole group serves as the left identity element for class function multiplication.*)\nFact cfun_mul1 : left_id '1_G cfun_mul.\n\n(*This fact asserts that class function multiplication is left-distributive over class function addition.*)\nFact cfun_mulD : left_distributive cfun_mul cfun_add.\n\n(*This fact asserts that the multiplicative identity class function is distinct from the zero class function.*)\nFact cfun_nz1 : '1_G != 0.\n\nHB.instance Definition _ := GRing.Zmodule_isComNzRing.Build classfun\n cfun_mulA cfun_mulC cfun_mul1 cfun_mulD cfun_nz1.\n\n(*This definition establishes the type of class functions as a non-zero commutative ring.*)\nDefinition cfun_nzRingType : nzRingType := classfun.\n\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use cfun_nzRingType instead.\")]\n(*A deprecated parsing-only notation that represents the non-zero commutative ring structure on the type of class functions. Modern code should use the `cfun_nzRingType` identifier instead.*)\nNotation cfun_ringType := (cfun_nzRingType) (only parsing).\n\n(*This lemma states that raising a class function to a positive successor power and then evaluating it at a group element is equivalent to first evaluating the class function at that element and then raising the result to the same power.*)\nLemma expS_cfunE phi n x : (phi ^+ n.+1) x = phi x ^+ n.+1.\n\n(*This fact asserts that for any unit class function, its corresponding inverse acts as a left inverse under class function multiplication, resulting in the multiplicative identity class function.*)\nFact cfun_mulV : {in cfun_unit, left_inverse 1 cfun_inv *%R}.\n\n(*This fact establishes that a class function is a unit function, which never evaluates to zero, provided it has a left inverse under class function multiplication.*)\nFact cfun_unitP phi psi : psi * phi = 1 -> phi \\in cfun_unit.\n\n(*This fact asserts that the multiplicative inversion operation, when applied to a non-unit class function, one that evaluates to zero for at least one element, returns the function unchanged.*)\nFact cfun_inv0id : {in [predC cfun_unit], cfun_inv =1 id}.\n\nHB.instance Definition _ :=\n GRing.ComNzRing_hasMulInverse.Build classfun cfun_mulV cfun_unitP cfun_inv0id.\n\n(*This fact asserts that scaling a class function first by one scalar and then by another is equivalent to scaling the function by the product of the two scalars.*)\nFact cfun_scaleA a b phi :\n cfun_scale a (cfun_scale b phi) = cfun_scale (a * b) phi.\n\n(*This fact asserts that scaling a class function by the multiplicative identity of the scalar ring leaves the function unchanged.*)\nFact cfun_scale1 : left_id 1 cfun_scale.\n\n(*This fact asserts that scaling is right-distributive over the addition of class functions, meaning scaling a sum of class functions is equivalent to summing the scaled class functions.*)\nFact cfun_scaleDr : right_distributive cfun_scale +%R.\n\n(*This fact asserts that scaling a class function by a sum of two scalars is equivalent to summing the results of scaling the class function by each scalar individually.*)\nFact cfun_scaleDl phi : {morph cfun_scale^~ phi : a b / a + b}.\n\nHB.instance Definition _ := GRing.Zmodule_isLmodule.Build algC classfun\n cfun_scaleA cfun_scale1 cfun_scaleDr cfun_scaleDl.\n\n(*This fact asserts the compatibility of scalar multiplication with class function multiplication, stating that scaling a product of two class functions is equivalent to scaling the first function and then multiplying by the second.*)\nFact cfun_scaleAl a phi psi : a *: (phi * psi) = (a *: phi) * psi.\n\n(*This fact asserts a compatibility property between scalar multiplication and class function multiplication, stating that scaling a product of two class functions is equivalent to multiplying the first function by the scaled second function.*)\nFact cfun_scaleAr a phi psi : a *: (phi * psi) = phi * (a *: psi).\n\nHB.instance Definition _ := GRing.Lmodule_isLalgebra.Build algC classfun\n cfun_scaleAl.\n\nHB.instance Definition _ := GRing.Lalgebra_isAlgebra.Build algC classfun\n cfun_scaleAr.\n\nSection Automorphism.\n\nVariable u : {rmorphism algC -> algC}.\n\n(*This definition specifies an operator on class functions that is induced by a given ring morphism on the codomain ring. The operator acts pointwise, applying the ring morphism to the value of the class function at each element.*)\nDefinition cfAut := cfun_comp (rmorph0 u).\n\n(*This lemma states that a specific class function automorphism preserves the indicator function of any given conjugacy class.*)\nLemma cfAut_cfun1i A : cfAut '1_A = '1_A.\n\n(*This lemma states that the class function automorphism of a class function scaled by a scalar element is equal to the class function automorphism of the original function, scaled by the image of the scalar under a ring automorphism.*)\nLemma cfAutZ a phi : cfAut (a *: phi) = u a *: cfAut phi.\n\n(*This lemma states that the class function automorphism operation is a Z-module morphism, meaning it preserves addition of class functions and scaling by integers.*)\nLemma cfAut_is_zmod_morphism : zmod_morphism cfAut.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `cfAut_is_zmod_morphism` instead\")]\n(*This definition provides a legacy name for the property that the class function automorphism is a Z-module morphism, meaning it preserves addition of class functions and scaling by integers.*)\nDefinition cfAut_is_additive := cfAut_is_zmod_morphism.\n\n(*This lemma states that the class function automorphism operation is a monoid morphism, meaning it preserves the pointwise multiplication of class functions and the multiplicative identity class function.*)\nLemma cfAut_is_monoid_morphism : monoid_morphism cfAut.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `cfAut_is_monoid_morphism` instead\")]\n(*This definition provides a legacy name for the property that the class function automorphism preserves pointwise multiplication of class functions and the multiplicative identity.*)\nDefinition cfAut_is_multiplicative :=\n (fun g => (g.2,g.1)) cfAut_is_monoid_morphism.\n\nHB.instance Definition _ := GRing.isZmodMorphism.Build classfun classfun cfAut\n cfAut_is_zmod_morphism.\nHB.instance Definition _ := GRing.isMonoidMorphism.Build classfun classfun cfAut\n cfAut_is_monoid_morphism.\n\n(*This lemma states that the class function automorphism maps the multiplicative identity class function, which is the function that is constant one, to itself.*)\nLemma cfAut_cfun1 : cfAut 1 = 1. \n\n(*This lemma states that the class function automorphism is scalable, meaning that applying the automorphism to a class function scaled by a scalar is equivalent to scaling the automorphed class function by the image of that scalar under a corresponding ring automorphism.*)\nLemma cfAut_scalable : scalable_for (u \\; *:%R) cfAut.\n\n(*This definition defines the property that a given sequence of class functions is closed under the class function automorphism, meaning that for any class function in the sequence, its image under the automorphism is also in the sequence.*)\nDefinition cfAut_closed (S : seq classfun) :=\n {in S, forall phi, cfAut phi \\in S}.\n\nEnd Automorphism.\n\n(*A notation for the complex conjugation operation on algebraic complex numbers.*)\nNotation conjC := Num.conj_op.\n\n(*This definition specifies that a class function is real if it is equal to its pointwise complex conjugate, which means that all values in its range are real numbers.*)\nDefinition cfReal phi := cfAut conjC phi == phi.\n\n(*This definition specifies a relationship between two finite sequences of class functions, requiring that the first sequence contains no duplicate elements, is a subset of the second sequence, and is closed under the action of pointwise complex conjugation.*)\nDefinition cfConjC_subset (S1 S2 : seq classfun) :=\n [/\\ uniq S1, {subset S1 <= S2} & cfAut_closed conjC S1].\n\n(*This fact establishes that the type of class functions over a group forms a finite-dimensional vector space, where the dimension is equal to the number of conjugacy classes of the group.*)\nFact cfun_vect_iso : Vector.axiom #|classes G| classfun.\n\n(*This definition establishes the canonical vector space structure on the type of class functions.*)\nDefinition cfun_vectType : vectType _ := classfun.\n\n(*This definition constructs a tuple of indicator functions for a specified subset of the conjugacy classes of a group, which can serve as a basis.*)\nDefinition cfun_base A : #|classes B ::&: A|.-tuple classfun :=\n [tuple of [seq '1_xB | xB in classes B ::&: A]].\n(*This definition declares a vector space of class functions spanned by the indicator functions of a specified subset of conjugacy classes.*)\nDefinition classfun_on A := <>%VS.\n\n(*This definition specifies the inner product of two class functions, calculated as the normalized sum over the group of the pointwise product of the first function and the complex conjugate of the second function.*)\nDefinition cfdot phi psi := #|B|%:R^-1 * \\sum_(x in B) phi x * (psi x)^*.\n(*This definition provides a version of the class function inner product with the arguments swapped.*)\nDefinition cfdotr psi phi := cfdot phi psi.\n(*This definition computes the squared norm of a class function as its inner product with itself.*)\nDefinition cfnorm phi := cfdot phi phi.\n\nCoercion seq_of_cfun phi := [:: phi].\n\n(*This definition computes the order of a class function as the least common multiple of the multiplicative orders of all values in its range.*)\nDefinition cforder phi := \\big[lcmn/1]_(x in <>) #[phi x]%C.\n\nEnd Defs.\n\nBind Scope cfun_scope with classfun.\n\nArguments classfun {gT} B%_g.\nArguments classfun_on {gT} B%_g A%_g.\nArguments cfun_indicator {gT} B%_g.\nArguments cfAut {gT B%_g} u phi%_CF.\nArguments cfReal {gT B%_g} phi%_CF.\nArguments cfdot {gT B%_g} phi%_CF psi%_CF.\nArguments cfdotr {gT B%_g} psi%_CF phi%_CF /.\nArguments cfnorm {gT B%_g} phi%_CF /.\n\n(*A notation for the type of class functions defined on a group, which can also denote the full vector space of these functions depending on the context.*)\nNotation \"''CF' ( G )\" := (classfun G) : type_scope.\n\n(*This notation represents the type of class functions defined on a given group. A class function is a function from the group to a ring that has the same value for all elements within the same conjugacy class.*)\nNotation \"''CF' ( G )\" := (@fullv _ (cfun_vectType G)) : vspace_scope.\n(*This notation represents the indicator function for a given subset. This function evaluates to one for elements inside the subset and to zero for elements outside the subset.*)\nNotation \"''1_' A\" := (cfun_indicator _ A) : ring_scope.\nNotation \"''CF' ( G , A )\" := (classfun_on G A) : ring_scope.\n(*This notation represents the constant class function that maps every element of a group to the multiplicative identity, which is one, of the target ring.*)\nNotation \"1\" := (@GRing.one (cfun_nzRingType _)) (only parsing) : cfun_scope.\n\n(*This notation provides a shorthand for the complex conjugation operation on numbers.*)\nNotation conjC := Num.conj_op.\n\n(*This notation represents the class function obtained by applying complex conjugation to the output of a given class function.*)\nNotation \"phi ^*\" := (cfAut conjC phi) : cfun_scope.\n(*This notation represents the property that a set of class functions is closed under the operation of applying complex conjugation to the output of each function.*)\nNotation cfConjC_closed := (cfAut_closed conjC).\nPrenex Implicits cfReal.\n\n(*This notation provides a reflection lemma that equates the propositional equality of two class functions with the boolean property that they are equal.*)\nNotation eqcfP := (@eqP (cfun_eqType _) _ _) (only parsing).\n\n(*This notation represents the number of distinct values taken by a given class function.*)\nNotation \"#[ phi ]\" := (cforder phi) : cfun_scope.\n(*This notation represents the inner product of two class functions defined on a specified group.*)\nNotation \"''[' u , v ]_ G\":= (@cfdot _ G u v) (only parsing) : ring_scope.\n(*This notation represents the inner product of two class functions, where the underlying group is inferred from the context.*)\nNotation \"''[' u , v ]\" := (cfdot u v) : ring_scope.\n(*This notation represents the squared norm of a class function, calculated as the inner product of the function with itself over a specified group.*)\nNotation \"''[' u ]_ G\" := '[u, u]_G (only parsing) : ring_scope.\n(*This notation represents the squared norm of a class function, calculated as the inner product of the function with itself, where the underlying group is inferred from the context.*)\nNotation \"''[' u ]\" := '[u, u] : ring_scope.\n\nSection Predicates.\n\nVariables (gT rT : finGroupType) (D : {set gT}) (R : {set rT}).\nImplicit Types (phi psi : 'CF(D)) (S : seq 'CF(D)) (tau : 'CF(D) -> 'CF(R)).\n\n(*This definition computes the kernel of a class function. The kernel is the set of group elements that, when multiplied on the left with any other group element, do not change the value of the class function.*)\nDefinition cfker phi := [set x in D | [forall y, phi (x * y)%g == phi y]].\n\n(*This definition states that a class function is faithful if its kernel contains only the identity element of the group.*)\nDefinition cfaithful phi := cfker phi \\subset [1].\n\n(*This definition is a recursive helper that checks if two sequences of class functions are orthogonal. It holds if the inner product of every function from the first sequence with every function from the second sequence is zero.*)\nDefinition ortho_rec S1 S2 :=\n all [pred phi | all [pred psi | '[phi, psi] == 0] S2] S1.\n(*This definition states that two sequences of class functions are orthogonal if the inner product of every function from the first sequence with every function from the second sequence is zero.*)\nDefinition orthogonal := ortho_rec.\nArguments orthogonal : simpl never.\n\n(*This definition is a recursive helper function that checks if a sequence of class functions is pairwise orthogonal. It iteratively verifies that each function in the sequence is orthogonal to all subsequent functions.*)\nFixpoint pair_ortho_rec S :=\n if S is psi :: S' then ortho_rec psi S' && pair_ortho_rec S' else true.\n\n(*This definition states that a sequence of class functions is pairwise orthogonal if it does not contain the zero function and if the inner product of any two distinct functions from the sequence is zero.*)\nDefinition pairwise_orthogonal S := (0 \\notin S) && pair_ortho_rec S.\n\n(*This definition states that a sequence of class functions is orthonormal if the squared norm of each function in the sequence is one, and the inner product of any two distinct functions from the sequence is zero.*)\nDefinition orthonormal S := all [pred psi | '[psi] == 1] S && pair_ortho_rec S.\n\n(*This definition states that a function between spaces of class functions is an isometry if it preserves the inner product. That is, the inner product of the images of any two class functions is equal to the inner product of the original two class functions.*)\nDefinition isometry tau := forall phi psi, '[tau phi, tau psi] = '[phi, psi].\n\n(*This definition specifies that a given function between two sets of class functions is an isometry from a source set to a target set. This holds if the function preserves the inner product for all pairs of functions from the source set and maps every function from the source set to a function within the target set.*)\nDefinition isometry_from_to mCFD tau mCFR :=\n prop_in2 mCFD (inPhantom (isometry tau))\n /\\ prop_in1 mCFD (inPhantom (forall phi, in_mem (tau phi) mCFR)).\n\nEnd Predicates.\nArguments orthogonal : simpl never.\n\nArguments cfker {gT D%_g} phi%_CF.\nArguments cfaithful {gT D%_g} phi%_CF.\nArguments orthogonal {gT D%_g} S1%_CF S2%_CF.\nArguments pairwise_orthogonal {gT D%_g} S%_CF.\nArguments orthonormal {gT D%_g} S%_CF.\nArguments isometry {gT rT D%_g R%_g} tau%_CF.\n\n(*This notation expresses that a given function is an isometry from a source set of class functions to a target set of class functions. This property requires the function to preserve the inner product and to map elements from the source set to the target set.*)\nNotation \"{ 'in' CFD , 'isometry' tau , 'to' CFR }\" :=\n (isometry_from_to (mem CFD) tau (mem CFR))\n (format \"{ 'in' CFD , 'isometry' tau , 'to' CFR }\")\n : type_scope.\n\nSection ClassFun.\n\nVariables (gT : finGroupType) (G : {group gT}).\nImplicit Types (A B : {set gT}) (H K : {group gT}) (phi psi xi : 'CF(G)).\n\n(*A notation for the class function constructed from a given set, defined as the sum of indicator functions for all conjugacy classes fully contained within that set.*)\nLocal Notation \"''1_' A\" := (cfun_indicator G A).\n\n(*This lemma states that for any class function, its value is zero for any element that does not belong to the underlying group.*)\nLemma cfun0 phi x : x \\notin G -> phi x = 0.\n\n(*This lemma states that the support of any class function, which is the set of elements where the function is non-zero, is a subset of the underlying group.*)\nLemma support_cfun phi : support phi \\subset G.\n\n(*This lemma states that a class function has the same value on all elements within a conjugacy class; specifically, for any element in the group, its value is equal to the value of any of its conjugates.*)\nLemma cfunJ phi x y : y \\in G -> phi (x ^ y) = phi x.\n\n(*This lemma states that the value of a class function at an element is equal to its value at the canonical representative of that element's conjugacy class.*)\nLemma cfun_repr phi x : phi (repr (x ^: G)) = phi x.\n\n(*This lemma provides an extensionality principle for class functions, stating that two class functions are equal if they produce the same value for every element in the underlying group.*)\nLemma cfun_inP phi psi : {in G, phi =1 psi} -> phi = psi.\n\n(*This lemma states that for a set which is a union of conjugacy classes, its associated indicator class function evaluates to one for elements within the set and to zero for elements outside the set.*)\nLemma cfuniE A x : A <| G -> '1_A x = (x \\in A)%:R.\n\n(*This lemma states that for a set which is a union of conjugacy classes, the support of its associated indicator class function is equal to the set itself.*)\nLemma support_cfuni A : A <| G -> support '1_A =i A.\n\n(*This lemma states that when a class function is multiplied by the indicator class function of a set that is a union of conjugacy classes, the resulting function is equal to the original class function for all elements within that set.*)\nLemma eq_mul_cfuni A phi : A <| G -> {in A, phi * '1_A =1 phi}.\n\n(*This lemma states that for any element within a set that is a union of conjugacy classes, the indicator class function of that set evaluates to one, which is the same value as the multiplicative identity class function.*)\nLemma eq_cfuni A : A <| G -> {in A, '1_A =1 (1 : 'CF(G))}.\n\n(*This lemma states that the indicator class function of the entire group is equal to the multiplicative identity class function, which is the function that constantly evaluates to one.*)\nLemma cfuniG : '1_G = 1.\n\n(*This lemma specifies that the multiplicative identity class function evaluates to one for any element belonging to the group, and to zero otherwise.*)\nLemma cfun1E g : (1 : 'CF(G)) g = (g \\in G)%:R.\n\n(*This lemma states that the multiplicative identity class function evaluates to one when applied to the identity element of the group.*)\nLemma cfun11 : (1 : 'CF(G)) 1%g = 1.\n\n(*This lemma states that evaluating the product of a family of class functions at a given group element yields the same result as taking the product of the individual evaluations of each class function at that same element.*)\nLemma prod_cfunE I r (P : pred I) (phi : I -> 'CF(G)) x :\n x \\in G -> (\\prod_(i <- r | P i) phi i) x = \\prod_(i <- r | P i) (phi i) x.\n\n(*This lemma states that raising a class function to a natural number power and then evaluating it at a group element is equivalent to first evaluating the function at that element and then raising the result to the same power.*)\nLemma exp_cfunE phi n x : x \\in G -> (phi ^+ n) x = phi x ^+ n.\n\n(*This lemma states that the product of the class functions constructed from two sets is equal to the class function constructed from the intersection of those two sets.*)\nLemma mul_cfuni A B : '1_A * '1_B = '1_(A :&: B) :> 'CF(G).\n\n(*This lemma specifies that the indicator class function for a given conjugacy class evaluates to one if and only if the input element belongs to that conjugacy class.*)\nLemma cfun_classE x y : '1_(x ^: G) y = ((x \\in G) && (y \\in x ^: G))%:R.\n\n(*This lemma states that the vector space of class functions whose support is contained within a given set is equal to the vector space spanned by the indicator functions of all conjugacy classes that are subsets of that set.*)\nLemma cfun_on_sum A :\n 'CF(G, A) = (\\sum_(xG in classes G | xG \\subset A) <['1_xG]>)%VS.\n\n(*This lemma establishes that a class function belongs to the subspace of functions with support in a given set if and only if that function evaluates to zero for all elements outside of that set.*)\nLemma cfun_onP A phi :\n reflect (forall x, x \\notin A -> phi x = 0) (phi \\in 'CF(G, A)).\n\nArguments cfun_onP {A phi}.\n\n(*This lemma states that if a class function has its support contained within a given set, then its value must be zero for any element not in that set.*)\nLemma cfun_on0 A phi x : phi \\in 'CF(G, A) -> x \\notin A -> phi x = 0.\n\n(*This lemma provides a formula for computing the sum of a class function over the entire group, stating that this sum is equal to the sum, over all conjugacy classes, of the product of each class's size and the function's value at that class's representative.*)\nLemma sum_by_classes (R : nzRingType) (F : gT -> R) :\n {in G &, forall g h, F (g ^ h) = F g} ->\n \\sum_(g in G) F g = \\sum_(xG in classes G) #|xG|%:R * F (repr xG).\n\n(*This lemma states that the standard basis for the space of class functions with support in a given set, which consists of indicator functions of conjugacy classes, is linearly independent.*)\nLemma cfun_base_free A : free (cfun_base G A).\n\n(*This lemma states that the dimension of the vector space of all class functions is equal to the number of conjugacy classes in the group.*)\nLemma dim_cfun : \\dim 'CF(G) = #|classes G|.\n\n(*This lemma states that the dimension of the vector space of class functions with support in a given set is equal to the number of conjugacy classes that are entirely contained within that set.*)\nLemma dim_cfun_on A : \\dim 'CF(G, A) = #|classes G ::&: A|.\n\n(*This lemma states that for an abelian group, the dimension of the vector space of class functions with support in a given subset of the group is equal to the number of elements in that subset.*)\nLemma dim_cfun_on_abelian A : abelian G -> A \\subset G -> \\dim 'CF(G, A) = #|A|.\n\n(*This lemma states that the class function constructed from a given set belongs to the space of class functions whose support is contained within that set.*)\nLemma cfuni_on A : '1_A \\in 'CF(G, A).\n\n(*This lemma states that multiplying any class function by the class function constructed from a given set results in a new class function whose support is contained within that set.*)\nLemma mul_cfuni_on A phi : phi * '1_A \\in 'CF(G, A).\n\n(*This lemma establishes an equivalence stating that a class function belongs to the subspace associated with a given set if and only if the support of the function is a subset of that set.*)\nLemma cfun_onE phi A : (phi \\in 'CF(G, A)) = (support phi \\subset A).\n\n(*This lemma states that any class function is an element of the space of class functions whose support is contained within the entire underlying carrier type of the group.*)\nLemma cfun_onT phi : phi \\in 'CF(G, [set: gT]).\n\n(*This lemma states that if a class function belongs to the subspaces associated with two different sets, it also belongs to the subspace associated with their intersection.*)\nLemma cfun_onD1 phi A :\n (phi \\in 'CF(G, A^#)) = (phi \\in 'CF(G, A)) && (phi 1%g == 0).\n\n(*This lemma states that any class function on a group is considered to be supported on the entire group, which is a trivial property.*)\nLemma cfun_onG phi : phi \\in 'CF(G, G).\n\n(*This lemma provides an equivalence for a class function being a member of a special set of functions, stating that such membership is equivalent to the function evaluating to zero at the group's identity element.*)\nLemma cfunD1E phi : (phi \\in 'CF(G, G^#)) = (phi 1%g == 0).\n\n(*This lemma states that the set of all class functions on a group, when viewed as functions supported on the entire group, is identical to the canonical vector space structure defined on the set of class functions.*)\nLemma cfunGid : 'CF(G, G) = 'CF(G)%VS.\n\n(*This lemma states that if a class function is supported on a given subset of a group, it is also considered to be supported on any superset of that subset. A function is supported on a subset if it evaluates to zero for all group elements outside that subset.*)\nLemma cfun_onS A B phi : B \\subset A -> phi \\in 'CF(G, B) -> phi \\in 'CF(G, A).\n\n(*This lemma states that if a subset of a group is a normal subgroup, then the entire vector space of class functions on the group can be expressed as the direct sum of the subspace of functions supported on the normal subgroup and the subspace of functions supported on its set-theoretic complement.*)\nLemma cfun_complement A :\n A <| G -> ('CF(G, A) + 'CF(G, G :\\: A)%SET = 'CF(G))%VS.\n\n(*This lemma states that the evaluation of a conjugate class function at a group element is equal to the conjugate of the value of the original class function at that same element.*)\nLemma cfConjCE phi x : ( phi^* )%CF x = (phi x)^*.\n\n(*This lemma states that the operation of taking the conjugate of a class function is an involution, meaning that applying the conjugation twice returns the original class function.*)\nLemma cfConjCK : involutive (fun phi => phi^* )%CF.\n\n(*This lemma states that the conjugate of the principal class function, which maps all elements to one, is the principal class function itself.*)\nLemma cfConjC_cfun1 : ( 1^* )%CF = 1 :> 'CF(G).\n\n(*This fact states that the kernel of a class function, defined as the set of group elements mapped to the same value as the group's identity element, is a group.*)\nFact cfker_is_group phi : group_set (cfker phi).\n\nCanonical cfker_group phi := Group (cfker_is_group phi).\n\n(*This lemma states that the kernel of a class function is a subgroup of the domain group.*)\nLemma cfker_sub phi : cfker phi \\subset G.\n\n(*This lemma states that the entire domain group is contained within the normalizer of the kernel of any class function, which implies the kernel is a normal subgroup.*)\nLemma cfker_norm phi : G \\subset 'N(cfker phi).\n\n(*This lemma states that the kernel of a class function is a normal subgroup of the domain group.*)\nLemma cfker_normal phi : cfker phi <| G.\n\n(*This lemma states that for any element in the kernel of a class function, the function's value at the product of that kernel element and any other group element is equal to the function's value at the second group element.*)\nLemma cfkerMl phi x y : x \\in cfker phi -> phi (x * y)%g = phi y.\n\n(*This lemma states that for any element in the kernel of a class function, the function's value at the product of any group element with that kernel element is equal to the function's value at the first group element.*)\nLemma cfkerMr phi x y : x \\in cfker phi -> phi (y * x)%g = phi y.\n\n(*This lemma states that for any element in the kernel of a class function, the value of the function at that element is equal to its value at the group's identity element.*)\nLemma cfker1 phi x : x \\in cfker phi -> phi x = phi 1%g.\n\n(*This lemma states that the kernel of the zero class function, which maps all group elements to zero, is the entire group.*)\nLemma cfker_cfun0 : @cfker _ G 0 = G.\n\n(*This lemma states that the intersection of the kernels of two class functions is a subset of the kernel of their sum.*)\nLemma cfker_add phi psi : cfker phi :&: cfker psi \\subset cfker (phi + psi).\n\n(*This lemma states that the intersection of the kernels of a family of class functions is a subset of the kernel of the sum of that family of functions.*)\nLemma cfker_sum I r (P : pred I) (Phi : I -> 'CF(G)) :\n G :&: \\bigcap_(i <- r | P i) cfker (Phi i)\n \\subset cfker (\\sum_(i <- r | P i) Phi i).\n\n(*This lemma states that the kernel of a class function is a subset of the kernel of the same function scaled by any scalar.*)\nLemma cfker_scale a phi : cfker phi \\subset cfker (a *: phi).\n\n(*This lemma states that for any non-zero scalar, the kernel of a class function scaled by that scalar is equal to the kernel of the original class function.*)\nLemma cfker_scale_nz a phi : a != 0 -> cfker (a *: phi) = cfker phi.\n\n(*This lemma states that the kernel of the additive inverse of a class function is equal to the kernel of the original function.*)\nLemma cfker_opp phi : cfker (- phi) = cfker phi.\n\n(*This lemma states that the kernel of the principal class function, which maps all group elements to one, is the entire group.*)\nLemma cfker_cfun1 : @cfker _ G 1 = G.\n\n(*This lemma states that the intersection of the kernels of two class functions is a subset of the kernel of their pointwise product.*)\nLemma cfker_mul phi psi : cfker phi :&: cfker psi \\subset cfker (phi * psi).\n\n(*This lemma states that the intersection of the kernels of a family of class functions is a subset of the kernel of the pointwise product of that family of functions.*)\nLemma cfker_prod I r (P : pred I) (Phi : I -> 'CF(G)) :\n G :&: \\bigcap_(i <- r | P i) cfker (Phi i)\n \\subset cfker (\\prod_(i <- r | P i) Phi i).\n\n(*This lemma states that a class function is faithful if and only if its kernel is the trivial subgroup containing only the identity element.*)\nLemma cfaithfulE phi : cfaithful phi = (cfker phi \\subset [1]).\n\nEnd ClassFun.\n\nArguments classfun_on {gT} B%_g A%_g.\n(*This notation provides a shorthand for the set of class functions on a group that are supported on a specific subset of that group. A function is considered supported on a subset if it evaluates to zero for all group elements that are not in the subset.*)\nNotation \"''CF' ( G , A )\" := (classfun_on G A) : ring_scope.\n\nArguments cfun_onP {gT G A phi}.\nArguments cfConjCK {gT G} phi : rename.\n#[global] Hint Resolve cfun_onT : core.\n\nSection DotProduct.\n\nVariable (gT : finGroupType) (G : {group gT}).\nImplicit Types (M : {group gT}) (phi psi xi : 'CF(G)) (R S : seq 'CF(G)).\n\n(*This lemma provides the definition for the dot product of two class functions. The dot product is computed as the sum of the product of the first function's value and the conjugate of the second function's value over all elements of the group, scaled by the inverse of the group's order.*)\nLemma cfdotE phi psi :\n '[phi, psi] = #|G|%:R^-1 * \\sum_(x in G) phi x * (psi x)^*.\n\n(*This lemma states that if two class functions are respectively supported on two subsets of a group, their dot product can be computed by summing only over the elements in the intersection of those two subsets. A function is supported on a subset if it evaluates to zero for all group elements outside that subset.*)\nLemma cfdotElr A B phi psi :\n phi \\in 'CF(G, A) -> psi \\in 'CF(G, B) ->\n '[phi, psi] = #|G|%:R^-1 * \\sum_(x in A :&: B) phi x * (psi x)^*.\n\n(*This lemma states that if the first of two class functions in a dot product is supported on a given subset of the group, their dot product can be computed by summing only over the elements of that subset. A function is supported on a subset if it evaluates to zero for all group elements outside that subset.*)\nLemma cfdotEl A phi psi :\n phi \\in 'CF(G, A) ->\n '[phi, psi] = #|G|%:R^-1 * \\sum_(x in A) phi x * (psi x)^*.\n\n(*This lemma states that if the second of two class functions in a dot product is supported on a given subset of the group, their dot product can be computed by summing only over the elements of that subset. A function is supported on a subset if it evaluates to zero for all group elements outside that subset.*)\nLemma cfdotEr A phi psi :\n psi \\in 'CF(G, A) ->\n '[phi, psi] = #|G|%:R^-1 * \\sum_(x in A) phi x * (psi x)^*.\n\n(*This lemma states that the inner product of two complex-valued functions on a group is zero if the support of the first function is contained in a given subset and the support of the second function is contained in the complement of that subset.*)\nLemma cfdot_complement A phi psi :\n phi \\in 'CF(G, A) -> psi \\in 'CF(G, G :\\: A) -> '[phi, psi] = 0.\n\n(*This lemma provides the formula for the squared norm of a complex-valued function with support restricted to a subset of a group, which is calculated as the sum of the squared magnitudes of the function's values over the subset, all divided by the size of the group.*)\nLemma cfnormE A phi :\n phi \\in 'CF(G, A) -> '[phi] = #|G|%:R^-1 * (\\sum_(x in A) `|phi x| ^+ 2).\n\n(*This lemma states that the inner product of two complex-valued functions remains the same if the first function is replaced by another that agrees with it on the support of the second function.*)\nLemma eq_cfdotl A phi1 phi2 psi :\n psi \\in 'CF(G, A) -> {in A, phi1 =1 phi2} -> '[phi1, psi] = '[phi2, psi].\n\n(*This lemma states that the inner product of the characteristic functions of two subsets of a group is equal to the size of the intersection of the subsets divided by the size of the group.*)\nLemma cfdot_cfuni A B :\n A <| G -> B <| G -> '['1_A, '1_B]_G = #|A :&: B|%:R / #|G|%:R.\n\n(*This lemma states that the squared norm of the constant function which is equal to one everywhere on a group is one.*)\nLemma cfnorm1 : '[1]_G = 1.\n\n(*This lemma asserts that applying the right-inner-product function to two complex-valued functions is equivalent to taking the inner product with the arguments swapped.*)\nLemma cfdotrE psi phi : cfdotr psi phi = '[phi, psi]. \n\n(*This lemma establishes that for any fixed second argument, the inner product operation is a linear map when viewed as a function of its first argument.*)\nLemma cfdotr_is_linear xi : linear (cfdotr xi : 'CF(G) -> algC^o).\n\nHB.instance Definition _ xi := GRing.isSemilinear.Build algC _ _ _ (cfdotr xi)\n (GRing.semilinear_linear (cfdotr_is_linear xi)).\n\n(*This lemma states that the inner product of the zero function with any complex-valued function is zero.*)\nLemma cfdot0l xi : '[0, xi] = 0.\n\n(*This lemma states that the inner product of the pointwise additive inverse of a complex-valued function with another function is the additive inverse of their original inner product.*)\nLemma cfdotNl xi phi : '[- phi, xi] = - '[phi, xi].\n\n(*This lemma shows that the inner product is left-distributive over the pointwise addition of complex-valued functions.*)\nLemma cfdotDl xi phi psi : '[phi + psi, xi] = '[phi, xi] + '[psi, xi].\n\n(*This lemma shows that the inner product is left-distributive over the pointwise subtraction of complex-valued functions.*)\nLemma cfdotBl xi phi psi : '[phi - psi, xi] = '[phi, xi] - '[psi, xi].\n\n(*This lemma states that multiplying a complex-valued function by an integer scalar in the first argument of the inner product results in the inner product being multiplied by that same integer scalar.*)\nLemma cfdotMnl xi phi n : '[phi *+ n, xi] = '[phi, xi] *+ n.\n\n(*This lemma shows that the inner product of a finite sum of complex-valued functions with another function is equal to the sum of the individual inner products.*)\nLemma cfdot_suml xi I r (P : pred I) (phi : I -> 'CF(G)) :\n '[\\sum_(i <- r | P i) phi i, xi] = \\sum_(i <- r | P i) '[phi i, xi].\n\n(*This lemma states that multiplying a complex-valued function by a complex scalar in the first argument of the inner product results in the inner product being multiplied by that same complex scalar.*)\nLemma cfdotZl xi a phi : '[a *: phi, xi] = a * '[phi, xi].\n\n(*This lemma states that swapping the two arguments of the inner product of complex-valued functions results in the complex conjugate of the original value.*)\nLemma cfdotC phi psi : '[phi, psi] = ('[psi, phi])^*.\n\n(*This lemma states that the inner product of two complex-valued functions remains the same if the second function is replaced by another that agrees with it on the support of the first function.*)\nLemma eq_cfdotr A phi psi1 psi2 :\n phi \\in 'CF(G, A) -> {in A, psi1 =1 psi2} -> '[phi, psi1] = '[phi, psi2].\n\n(*This lemma shows that the inner product is right-distributive over the pointwise subtraction of complex-valued functions.*)\nLemma cfdotBr xi phi psi : '[xi, phi - psi] = '[xi, phi] - '[xi, psi].\n\n(*This lemma states that the inner product of any complex-valued function with the zero function is zero.*)\nLemma cfdot0r xi : '[xi, 0] = 0. \n(*This lemma states that the inner product of a complex-valued function with the pointwise additive inverse of another function is the additive inverse of their original inner product.*)\nLemma cfdotNr xi phi : '[xi, - phi] = - '[xi, phi].\n\n(*This lemma shows that the inner product is right-distributive over the pointwise addition of complex-valued functions.*)\nLemma cfdotDr xi phi psi : '[xi, phi + psi] = '[xi, phi] + '[xi, psi].\n\n(*This lemma states that multiplying a complex-valued function by an integer scalar in the second argument of the inner product results in the inner product being multiplied by that same integer scalar.*)\nLemma cfdotMnr xi phi n : '[xi, phi *+ n] = '[xi, phi] *+ n.\n\n(*This lemma shows that the inner product of a function with a finite sum of other complex-valued functions is equal to the sum of the individual inner products.*)\nLemma cfdot_sumr xi I r (P : pred I) (phi : I -> 'CF(G)) :\n '[xi, \\sum_(i <- r | P i) phi i] = \\sum_(i <- r | P i) '[xi, phi i].\n\n(*This lemma states that multiplying a complex-valued function by a complex scalar in the second argument of the inner product results in the inner product being multiplied by the complex conjugate of that scalar.*)\nLemma cfdotZr a xi phi : '[xi, a *: phi] = a^* * '[xi, phi].\n\n(*This lemma describes how the inner product interacts with a pointwise application of a ring morphism on the function values, stating that if the morphism acts as complex conjugation on the values of the second function, then the inner product of the transformed functions is equal to the morphism applied to their original inner product.*)\nLemma cfdot_cfAut (u : {rmorphism algC -> algC}) phi psi :\n {in image psi G, {morph u : x / x^*}} ->\n '[cfAut u phi, cfAut u psi] = u '[phi, psi].\n\n(*This lemma states that the inner product of the pointwise complex conjugates of two functions is equal to the complex conjugate of the inner product of the original functions.*)\nLemma cfdot_conjC phi psi : '[phi^*, psi^*] = '[phi, psi]^*.\n\n(*This lemma states that the inner product of the pointwise conjugate of the first function with the second function is equal to the complex conjugate of the inner product of the first function with the pointwise conjugate of the second.*)\nLemma cfdot_conjCl phi psi : '[phi^*, psi] = '[phi, psi^*]^*.\n\n(*This lemma states that the inner product of the first function with the pointwise conjugate of the second is equal to the complex conjugate of the inner product of the pointwise conjugate of the first function with the second.*)\nLemma cfdot_conjCr phi psi : '[phi, psi^*] = '[phi^*, psi]^*.\n\n(*This lemma asserts that the squared norm of any complex-valued function is always greater than or equal to zero.*)\nLemma cfnorm_ge0 phi : 0 <= '[phi].\n\n(*This lemma states that the squared norm of a complex-valued function is zero if and only if the function is the zero function.*)\nLemma cfnorm_eq0 phi : ('[phi] == 0) = (phi == 0).\n\n(*This lemma states that the squared norm of a complex-valued function is strictly greater than zero if and only if the function is not the zero function.*)\nLemma cfnorm_gt0 phi : ('[phi] > 0) = (phi != 0).\n\n(*This lemma states that the square root of the squared canonical norm of a vector is greater than or equal to zero.*)\nLemma sqrt_cfnorm_ge0 phi : 0 <= sqrtC '[phi].\n\n(*This lemma states that the square root of the squared canonical norm of a vector is equal to zero if and only if the vector is the zero vector.*)\nLemma sqrt_cfnorm_eq0 phi : (sqrtC '[phi] == 0) = (phi == 0).\n\n(*This lemma states that the square root of the squared canonical norm of a vector is greater than zero if and only if the vector is not the zero vector.*)\nLemma sqrt_cfnorm_gt0 phi : (sqrtC '[phi] > 0) = (phi != 0).\n\n(*This lemma states that the squared canonical norm of a vector scaled by an integer is equal to the product of the square of the absolute value of the integer and the squared canonical norm of the original vector.*)\nLemma cfnormZ a phi : '[a *: phi]= `|a| ^+ 2 * '[phi]_G.\n\n(*This lemma states that the squared canonical norm of the additive inverse of a vector is equal to the squared canonical norm of the vector itself.*)\nLemma cfnormN phi : '[- phi] = '[phi].\n\n(*This lemma states that scaling a vector by negative one raised to a natural number power does not change its squared canonical norm.*)\nLemma cfnorm_sign n phi : '[(-1) ^+ n *: phi] = '[phi].\n\n(*This lemma states that the squared canonical norm of the sum of two vectors is equal to the sum of their individual squared canonical norms plus twice the real part of their inner product.*)\nLemma cfnormD phi psi :\n let d := '[phi, psi] in '[phi + psi] = '[phi] + '[psi] + ( d + d^* ).\n\n(*This lemma states that the squared canonical norm of the difference of two vectors is equal to the sum of their individual squared canonical norms minus twice the real part of their inner product.*)\nLemma cfnormB phi psi :\n let d := '[phi, psi] in '[phi - psi] = '[phi] + '[psi] - ( d + d^* ).\n\n(*This lemma, a form of the Pythagorean theorem, states that if two vectors are orthogonal, the squared canonical norm of their sum is equal to the sum of their individual squared canonical norms.*)\nLemma cfnormDd phi psi : '[phi, psi] = 0 -> '[phi + psi] = '[phi] + '[psi].\n\n(*This lemma states that if two vectors are orthogonal, the squared canonical norm of their difference is equal to the sum of their individual squared canonical norms.*)\nLemma cfnormBd phi psi : '[phi, psi] = 0 -> '[phi - psi] = '[phi] + '[psi].\n\n(*This lemma states that the squared canonical norm of the conjugate of a vector is equal to the squared canonical norm of the vector itself.*)\nLemma cfnorm_conjC phi : '[phi^*] = '[phi].\n\n(*This lemma states the Cauchy-Schwarz inequality, asserting that the squared magnitude of the inner product of two vectors is less than or equal to the product of their squared canonical norms. Equality holds if and only if the two vectors are linearly dependent.*)\nLemma cfCauchySchwarz phi psi :\n `|'[phi, psi]| ^+ 2 <= '[phi] * '[psi] ?= iff ~~ free (phi :: psi).\n\n(*This lemma states a variant of the Cauchy-Schwarz inequality, asserting that the magnitude of the inner product of two vectors is less than or equal to the product of their canonical norms. Equality holds if and only if the two vectors are linearly dependent.*)\nLemma cfCauchySchwarz_sqrt phi psi :\n `|'[phi, psi]| <= sqrtC '[phi] * sqrtC '[psi] ?= iff ~~ free (phi :: psi).\n\n(*This lemma states the triangle inequality, asserting that the norm of the sum of two vectors is less than or equal to the sum of their norms. Equality holds if and only if the vectors are linearly dependent and point in the same direction.*)\nLemma cf_triangle_leif phi psi :\n sqrtC '[phi + psi] <= sqrtC '[phi] + sqrtC '[psi]\n ?= iff ~~ free (phi :: psi) && (0 <= coord [tuple psi] 0 phi).\n\n(*This lemma states that a sequence of vectors constructed by prepending a vector to another sequence is orthogonal to a second sequence of vectors if and only if the prepended vector is orthogonal to the second sequence and the original first sequence is also orthogonal to the second sequence.*)\nLemma orthogonal_cons phi R S :\n orthogonal (phi :: R) S = orthogonal phi S && orthogonal R S.\n\n(*This lemma provides the reflection of the orthogonality property, stating that two vectors are orthogonal if and only if their inner product is zero.*)\nLemma orthoP phi psi : reflect ('[phi, psi] = 0) (orthogonal phi psi).\n\n(*This lemma provides the reflection of the orthogonality property for sequences of vectors, stating that two sequences of vectors are orthogonal if and only if every vector from the first sequence has an inner product of zero with every vector from the second sequence.*)\nLemma orthogonalP S R :\n reflect {in S & R, forall phi psi, '[phi, psi] = 0} (orthogonal S R).\n\n(*This lemma provides the reflection of the orthogonality property for a single vector and a sequence of vectors, stating that a vector is orthogonal to a sequence if and only if its inner product with every vector in the sequence is zero.*)\nLemma orthoPl phi S :\n reflect {in S, forall psi, '[phi, psi] = 0} (orthogonal phi S).\n\nArguments orthoPl {phi S}.\n\n(*This lemma states that the orthogonality relation between two sequences of vectors is symmetric.*)\nLemma orthogonal_sym : symmetric (@orthogonal _ G).\n\n(*This lemma provides the reflection of the orthogonality property for a sequence of vectors and a single vector, stating that a sequence is orthogonal to a vector if and only if the inner product of every vector in the sequence with the given vector is zero.*)\nLemma orthoPr S psi :\n reflect {in S, forall phi, '[phi, psi] = 0} (orthogonal S psi).\n\n(*This lemma states that the orthogonality property between two sequences of vectors is invariant under reordering or duplication of elements within each sequence.*)\nLemma eq_orthogonal R1 R2 S1 S2 :\n R1 =i R2 -> S1 =i S2 -> orthogonal R1 S1 = orthogonal R2 S2.\n\n(*This lemma states that the concatenation of two sequences of vectors is orthogonal to a third sequence if and only if each of the first two sequences is individually orthogonal to the third sequence.*)\nLemma orthogonal_catl R1 R2 S :\n orthogonal (R1 ++ R2) S = orthogonal R1 S && orthogonal R2 S.\n\n(*This lemma states that a sequence of vectors is orthogonal to the concatenation of two other sequences if and only if the first sequence is individually orthogonal to each of the other two sequences.*)\nLemma orthogonal_catr R S1 S2 :\n orthogonal R (S1 ++ S2) = orthogonal R S1 && orthogonal R S2.\n\n(*This lemma states that if two sets of vectors are orthogonal, then any vector in the span of the first set is orthogonal to any vector in the span of the second set.*)\nLemma span_orthogonal S1 S2 phi1 phi2 :\n orthogonal S1 S2 -> phi1 \\in <>%VS -> phi2 \\in <>%VS ->\n '[phi1, phi2] = 0.\n\n(*This lemma asserts the orthogonal decomposition of a vector with respect to a subspace. It states that any vector can be expressed as the sum of a component within the vector space spanned by a given set of vectors and a component that is orthogonal to that entire vector space.*)\nLemma orthogonal_split S beta :\n {X : 'CF(G) & X \\in <>%VS &\n {Y | [/\\ beta = X + Y, '[X, Y] = 0 & orthogonal Y S]}}.\n\n(*This lemma states that an isometry, a function that preserves inner products, also preserves the orthogonality relationship between two sets of vectors when applied to them.*)\nLemma map_orthogonal M (nu : 'CF(G) -> 'CF(M)) S R (A : {pred 'CF(G)}) :\n {in A &, isometry nu} -> {subset S <= A} -> {subset R <= A} ->\n orthogonal (map nu S) (map nu R) = orthogonal S R.\n\n(*This lemma states that a sequence of vectors is orthogonal to another sequence if and only if it is also orthogonal to the sequence of their additive inverses.*)\nLemma orthogonal_oppr S R : orthogonal S (map -%R R) = orthogonal S R.\n\n(*This lemma states that a sequence of vectors is orthogonal to another sequence if and only if the sequence of their additive inverses is also orthogonal to the second sequence.*)\nLemma orthogonal_oppl S R : orthogonal (map -%R S) R = orthogonal S R.\n\n(*This lemma provides a reflection for pairwise orthogonality, stating that a sequence of vectors is pairwise orthogonal if and only if it consists of unique, non-zero vectors, and any two distinct vectors from the sequence have an inner product of zero.*)\nLemma pairwise_orthogonalP S :\n reflect (uniq (0 :: S)\n /\\ {in S &, forall phi psi, phi != psi -> '[phi, psi] = 0})\n (pairwise_orthogonal S).\n\n(*This lemma states a condition for the concatenation of two sequences of vectors to be pairwise orthogonal. It asserts that if two sequences are each pairwise orthogonal and are also mutually orthogonal to each other, then their concatenation is also a pairwise orthogonal sequence.*)\nLemma pairwise_orthogonal_cat R S :\n pairwise_orthogonal (R ++ S) =\n [&& pairwise_orthogonal R, pairwise_orthogonal S & orthogonal R S].\n\n(*This lemma states that if a first finite sequence of character functions is a permutation of a second finite sequence of character functions, then the boolean indicating whether the first sequence is pairwise orthogonal is equal to the boolean indicating whether the second is pairwise orthogonal.*)\nLemma eq_pairwise_orthogonal R S :\n perm_eq R S -> pairwise_orthogonal R = pairwise_orthogonal S.\n\n(*This lemma states that if a first finite sequence of character functions is a sub-multiset of a second, the first sequence contains no duplicate elements, and the second sequence is pairwise orthogonal, then the first sequence is also pairwise orthogonal.*)\nLemma sub_pairwise_orthogonal S1 S2 :\n {subset S1 <= S2} -> uniq S1 ->\n pairwise_orthogonal S2 -> pairwise_orthogonal S1.\n\n(*This lemma states that if a finite sequence of character functions is pairwise orthogonal, then it is also linearly independent.*)\nLemma orthogonal_free S : pairwise_orthogonal S -> free S.\n\n(*This lemma states that if a finite sequence of character functions is pairwise orthogonal, then filtering this sequence with any predicate results in a new sequence that is also pairwise orthogonal.*)\nLemma filter_pairwise_orthogonal S p :\n pairwise_orthogonal S -> pairwise_orthogonal (filter p S).\n\n(*This lemma states that if a finite sequence of character functions is orthonormal, then the zero character function is not an element of that sequence.*)\nLemma orthonormal_not0 S : orthonormal S -> 0 \\notin S.\n\n(*This lemma states that a finite sequence of character functions is orthonormal if and only if every character function in the sequence has a norm of one and the sequence is pairwise orthogonal.*)\nLemma orthonormalE S :\n orthonormal S = all [pred phi | '[phi] == 1] S && pairwise_orthogonal S.\n\n(*This lemma states that if a finite sequence of character functions is orthonormal, then it is also pairwise orthogonal.*)\nLemma orthonormal_orthogonal S : orthonormal S -> pairwise_orthogonal S.\n\n(*This lemma states that the concatenation of two finite sequences of character functions is orthonormal if and only if both original sequences are orthonormal and they are mutually orthogonal.*)\nLemma orthonormal_cat R S :\n orthonormal (R ++ S) = [&& orthonormal R, orthonormal S & orthogonal R S].\n\n(*This lemma states that if a first finite sequence of character functions is a permutation of a second finite sequence of character functions, then the boolean indicating whether the first sequence is orthonormal is equal to the boolean indicating whether the second is orthonormal.*)\nLemma eq_orthonormal R S : perm_eq R S -> orthonormal R = orthonormal S.\n\n(*This lemma states that if a finite sequence of character functions is orthonormal, then it is also linearly independent.*)\nLemma orthonormal_free S : orthonormal S -> free S.\n\n(*This lemma provides a reflection property, stating that a finite sequence of character functions is orthonormal if and only if the sequence contains no duplicate elements and for any two character functions from the sequence, their inner product is one if they are the same function and zero otherwise.*)\nLemma orthonormalP S :\n reflect (uniq S /\\ {in S &, forall phi psi, '[phi, psi]_G = (phi == psi)%:R})\n (orthonormal S).\n\n(*This lemma states that if a first finite sequence of character functions is a sub-multiset of a second, the first sequence contains no duplicate elements, and the second sequence is orthonormal, then the first sequence is also orthonormal.*)\nLemma sub_orthonormal S1 S2 :\n {subset S1 <= S2} -> uniq S1 -> orthonormal S2 -> orthonormal S1.\n\n(*This lemma provides a reflection property, stating that a two-element sequence of character functions is orthonormal if and only if the inner product of the two functions is zero, and the norm of each function is one.*)\nLemma orthonormal2P phi psi :\n reflect [/\\ '[phi, psi] = 0, '[phi] = 1 & '[psi] = 1]\n (orthonormal [:: phi; psi]).\n\n(*This lemma states that if a sequence of character functions is closed under complex conjugation, contains no real-valued character functions, is pairwise orthogonal, and contains a given character function, then the two-element sequence consisting of that character function and its complex conjugate is pairwise orthogonal.*)\nLemma conjC_pair_orthogonal S chi :\n cfConjC_closed S -> ~~ has cfReal S -> pairwise_orthogonal S -> chi \\in S ->\n pairwise_orthogonal (chi :: chi^*%CF).\n\n(*This lemma states that if a character function is real-valued, then its inner product with the complex conjugate of a second character function is equal to the complex conjugate of its inner product with the second character function.*)\nLemma cfdot_real_conjC phi psi : cfReal phi -> '[phi, psi^*]_G = '[phi, psi]^*.\n\n(*This lemma states that if a first set of character functions is closed under complex conjugation and contains no real-valued character functions, a second set is a conjugation-closed subset of the first, and a given character function is in the first set but not the second, then the set formed by adding the character function and its complex conjugate to the second set is also a conjugation-closed subset of the first.*)\nLemma extend_cfConjC_subset S X phi :\n cfConjC_closed S -> ~~ has cfReal S -> phi \\in S -> phi \\notin X ->\n cfConjC_subset X S -> cfConjC_subset [:: phi, phi^* & X]%CF S.\n\nEnd DotProduct.\n\nArguments orthoP {gT G phi psi}.\nArguments orthoPl {gT G phi S}.\nArguments orthoPr {gT G S psi}.\nArguments orthogonalP {gT G S R}.\nArguments pairwise_orthogonalP {gT G S}.\nArguments orthonormalP {gT G S}.\n\nSection CfunOrder.\n\nVariables (gT : finGroupType) (G : {group gT}) (phi : 'CF(G)).\n\n(*This lemma provides a reflection property, stating that the order of a character function divides a given natural number if and only if raising the value of the character function at any group element to the power of that natural number results in one.*)\nLemma dvdn_cforderP n :\n reflect {in G, forall x, phi x ^+ n = 1} (#[phi]%CF %| n)%N.\n\n(*This lemma states that the divisibility of the order of a character function by a natural number is equivalent to the equality of the character function raised to the power of that number and the trivial character function.*)\nLemma dvdn_cforder n : (#[phi]%CF %| n) = (phi ^+ n == 1).\n\n(*This lemma states that a character function raised to the power of its own order results in the trivial character function.*)\nLemma exp_cforder : phi ^+ #[phi]%CF = 1.\n\nEnd CfunOrder.\n\nArguments dvdn_cforderP {gT G phi n}.\n\nSection MorphOrder.\n\nVariables (aT rT : finGroupType) (G : {group aT}) (R : {group rT}).\nVariable f : {rmorphism 'CF(G) -> 'CF(R)}.\n\n(*This lemma states that for any ring morphism between spaces of character functions, the order of the image of a character function under the morphism divides the order of the original character function.*)\nLemma cforder_rmorph phi : #[f phi]%CF %| #[phi]%CF.\n\n(*This lemma states that for any injective ring morphism between spaces of character functions, the order of the image of a character function under the morphism is equal to the order of the original character function.*)\nLemma cforder_inj_rmorph phi : injective f -> #[f phi]%CF = #[phi]%CF.\n\nEnd MorphOrder.\n\nSection BuildIsometries.\n\nVariable (gT : finGroupType) (L G : {group gT}).\nImplicit Types (phi psi xi : 'CF(L)) (R S : seq 'CF(L)).\nImplicit Types (U : {pred 'CF(L)}) (W : {pred 'CF(G)}).\n\n(*This lemma states that if a function is an isometry from a first set of character functions to a second set, then it is also an isometry from any subset of the first set to any superset of the second set.*)\nLemma sub_iso_to U1 U2 W1 W2 tau :\n {subset U2 <= U1} -> {subset W1 <= W2} ->\n {in U1, isometry tau, to W1} -> {in U2, isometry tau, to W2}.\n\n(*This lemma states that if a function acts as an isometry on each element of a linearly independent finite sequence of character functions, then there exists a linear map which agrees with the given function on the sequence and is an isometry on the entire vector space spanned by that sequence.*)\nLemma isometry_of_free S f :\n free S -> {in S &, isometry f} ->\n {tau : {linear 'CF(L) -> 'CF(G)} |\n {in S, tau =1 f} & {in <>%VS &, isometry tau}}.\n\n(*This lemma states that given a first and a second pairwise orthogonal finite sequence of character functions, if the norms of the elements in the second sequence are the same as the norms of the corresponding elements in the first sequence, then there exists a linear map that maps the first sequence to the second and is an isometry on the vector space spanned by the first sequence.*)\nLemma isometry_of_cfnorm S tauS :\n pairwise_orthogonal S -> pairwise_orthogonal tauS ->\n map cfnorm tauS = map cfnorm S ->\n {tau : {linear 'CF(L) -> 'CF(G)} | map tau S = tauS\n & {in <>%VS &, isometry tau}}.\n\n(*This lemma states that if an additive function between spaces of character functions is an isometry on a set and that set is closed under subtraction, then the function is injective on that set.*)\nLemma isometry_raddf_inj U (tau : {additive 'CF(L) -> 'CF(G)}) :\n {in U &, isometry tau} -> {in U &, forall u v, u - v \\in U} ->\n {in U &, injective tau}.\n\n(*This lemma states that the additive inverse function on a space of character functions is an isometry.*)\nLemma opp_isometry : @isometry _ _ G G -%R.\n\nEnd BuildIsometries.\n\nSection Restrict.\n\nVariables (gT : finGroupType) (A B : {set gT}).\n(*A local notation for the carrier type of a group structure, typically representing a subgroup or a factor group in the current context.*)\nLocal Notation H := <>.\n(*A local notation for the carrier type of a group structure, typically representing the main group being considered in the current context.*)\nLocal Notation G := <>.\n\n(*This fact provides a proof that a function constructed from a class function on a source group is itself a class function on a target subgroup. The constructed function evaluates the original class function on elements of the target subgroup.*)\nFact cfRes_subproof (phi : 'CF(B)) :\n is_class_fun H [ffun x => phi (if H \\subset G then x else 1%g) *+ (x \\in H)].\n\n(*This definition constructs the restriction of a class function on a source group to a target subgroup. It packages a proof term, which verifies that the resulting function is a valid class function on the target subgroup.*)\nDefinition cfRes phi := Cfun 1 (cfRes_subproof phi).\n\n(*This lemma states that when a class function defined on a group is restricted to a subgroup, the resulting function agrees with the original class function for all elements within that subgroup.*)\nLemma cfResE phi : A \\subset B -> {in A, cfRes phi =1 phi}.\n\n(*This lemma states that the restriction of a class function to a subgroup preserves the value of the function at the identity element of the group.*)\nLemma cfRes1 phi : cfRes phi 1%g = phi 1%g.\n\n(*This lemma states that the operation of restricting a class function to a subgroup is a linear map.*)\nLemma cfRes_is_linear : linear cfRes.\n\nHB.instance Definition _ := GRing.isSemilinear.Build algC _ _ _ cfRes\n (GRing.semilinear_linear cfRes_is_linear).\n\n(*This lemma states that restricting the constant class function with value one on a group results in the constant class function with value one on the subgroup.*)\nLemma cfRes_cfun1 : cfRes 1 = 1.\n\n(*This lemma states that the operation of restricting class functions to a subgroup is a monoid morphism, meaning it preserves pointwise multiplication and the multiplicative identity class function.*)\nLemma cfRes_is_monoid_morphism : monoid_morphism cfRes.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `cfRes_is_monoid_morphism` instead\")]\n(*This definition, now deprecated, asserts that the class function restriction operator is a multiplicative morphism. It is preserved for backward compatibility and users should prefer using the 'cfRes_is_monoid_morphism' lemma instead.*)\nDefinition cfRes_is_multiplicative :=\n (fun g => (g.2,g.1)) cfRes_is_monoid_morphism.\n(*This notation stands for the restriction of a class function. It is used to apply the restriction operator to a class function defined on a group, limiting its domain to a subgroup.*)\nNotation \"''Res[' H , G ]\" := (@cfRes _ H G) (only parsing) : ring_scope.\n(*This notation provides a shorthand for restricting a class function to a subgroup, where the original ambient group is inferred from the context.*)\nNotation \"''Res[' H ]\" := 'Res[H, _] : ring_scope.\n(*This notation provides a shorthand for the class function restriction operator where both the subgroup and the ambient group are inferred from the context.*)\nNotation \"''Res'\" := 'Res[_] (only parsing) : ring_scope.\n\nSection MoreRestrict.\n\nVariables (gT : finGroupType) (G H : {group gT}).\nImplicit Types (A : {set gT}) (phi : 'CF(G)).\n\n(*This lemma states that if a given set is not a subgroup of a class function's domain, then restricting the class function to that set results in a constant function whose value is the original function's value at the identity.*)\nLemma cfResEout phi : ~~ (H \\subset G) -> 'Res[H] phi = (phi 1%g)%:A.\n\n(*This lemma states that class function restriction is transitive. For a chain of nested subgroups, restricting a class function from the largest group to the middle one and then to the smallest one is equivalent to restricting it directly from the largest to the smallest group.*)\nLemma cfResRes A phi :\n A \\subset H -> H \\subset G -> 'Res[A] ('Res[H] phi) = 'Res[A] phi.\n\n(*This lemma states that restricting a class function already defined on a group to that same group results in the original class function.*)\nLemma cfRes_id A psi : 'Res[A] psi = psi.\n\n(*This lemma states that if a set is a subset of both a group and the kernel of a class function, then that set is also a subset of the kernel of the class function after it has been restricted to that group.*)\nLemma sub_cfker_Res A phi :\n A \\subset H -> A \\subset cfker phi -> A \\subset cfker ('Res[H, G] phi).\n\n(*This lemma states that if a subgroup is contained within the kernel of a class function, then the kernel of the class function restricted to that subgroup is precisely the subgroup itself.*)\nLemma eq_cfker_Res phi : H \\subset cfker phi -> cfker ('Res[H, G] phi) = H.\n\n(*This lemma states that if a subgroup is contained within the kernel of a class function, then restricting that class function to the subgroup yields a constant function, with the value being the value of the original function at the identity element.*)\nLemma cfRes_sub_ker phi : H \\subset cfker phi -> 'Res[H, G] phi = (phi 1%g)%:A.\n\n(*This lemma states that the order of a restricted class function divides the order of the original class function.*)\nLemma cforder_Res phi : #['Res[H] phi]%CF %| #[phi]%CF.\n\nEnd MoreRestrict.\n\nSection Morphim.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\n\nSection Main.\n\nVariable G : {group aT}.\nImplicit Type phi : 'CF(f @* G).\n\n(*This fact establishes a necessary property for defining the inflation of a class function: it proves that a specific function, constructed by composing a given class function with a group morphism, is indeed a class function on the domain group.*)\nFact cfMorph_subproof phi :\n is_class_fun <>\n [ffun x => phi (if G \\subset D then f x else 1%g) *+ (x \\in G)].\n\n(*This definition introduces the inflation of a class function along a group morphism. It lifts a class function from the codomain of the morphism back to a class function on the domain group.*)\nDefinition cfMorph phi := Cfun 1 (cfMorph_subproof phi).\n\n(*This lemma specifies the value of an inflated class function. For an element within the domain group, the inflated function evaluates to the original class function applied to the image of the element under the group morphism.*)\nLemma cfMorphE phi x : G \\subset D -> x \\in G -> cfMorph phi x = phi (f x).\n\n(*This lemma states that the inflation of a class function preserves the value at the identity element.*)\nLemma cfMorph1 phi : cfMorph phi 1%g = phi 1%g.\n\n(*This lemma describes the behavior of class function inflation when the intended domain group is not a subgroup of the morphism's domain. In this case, the inflated function is a constant function whose value is the original function's value at the identity.*)\nLemma cfMorphEout phi : ~~ (G \\subset D) -> cfMorph phi = (phi 1%g)%:A.\n\n(*This lemma states that inflating the constant class function with value one results in the constant class function with value one.*)\nLemma cfMorph_cfun1 : cfMorph 1 = 1.\n\n(*This fact asserts that the class function inflation operator is linear.*)\nFact cfMorph_is_linear : linear cfMorph.\n\nHB.instance Definition _ := GRing.isSemilinear.Build algC _ _ _ cfMorph\n (GRing.semilinear_linear cfMorph_is_linear).\n\n(*This fact asserts that the class function inflation operator is a monoid morphism, meaning it preserves pointwise multiplication and the identity class function.*)\nFact cfMorph_is_monoid_morphism : monoid_morphism cfMorph.\n\n(*This lemma states that, provided the domain group is a subgroup of the group morphism's domain, the class function inflation operator is injective.*)\nLemma cfMorph_inj : injective cfMorph.\n\n(*This lemma shows that an inflated class function is equal to the constant one function if and only if the original class function is also equal to the constant one function.*)\nLemma cfMorph_eq1 phi : (cfMorph phi == 1) = (phi == 1).\n\n(*This lemma provides an explicit formula for the kernel of an inflated class function. The kernel is the intersection of the domain group with the preimage of the original function's kernel under the group morphism.*)\nLemma cfker_morph phi : cfker (cfMorph phi) = G :&: f @*^-1 (cfker phi).\n\n(*This lemma states that the image of the kernel of an inflated class function under the defining group morphism is equal to the kernel of the original class function.*)\nLemma cfker_morph_im phi : f @* cfker (cfMorph phi) = cfker phi.\n\n(*This lemma provides an equivalence for when a set is a subset of the kernel of an inflated class function. This holds if and only if the set is a subset of the domain group and its image under the group morphism is contained in the kernel of the original class function.*)\nLemma sub_cfker_morph phi (A : {set aT}) :\n (A \\subset cfker (cfMorph phi)) = (A \\subset G) && (f @* A \\subset cfker phi).\n\n(*This lemma provides an equivalence for when the image of a set under a group morphism is a subset of a class function's kernel. This condition is equivalent to the conjunction of two properties: first, if the set is a subset of the domain group, then it must also be a subset of the inflated function's kernel; second, if the set is a subset of the morphism's kernel, then the group identity must belong to the original function's kernel.*)\nLemma sub_morphim_cfker phi (A : {set aT}) :\n A \\subset G -> (f @* A \\subset cfker phi) = (A \\subset cfker (cfMorph phi)).\n\n(*This lemma states that the order of a class function is preserved when it is lifted from a quotient group to the parent group via the class function morphism.*)\nLemma cforder_morph phi : #[cfMorph phi]%CF = #[phi]%CF.\n\nEnd Main.\n\n(*This lemma states that for a class function defined on a group, restricting the class function morphism to a subgroup is equivalent to applying the class function morphism to the restriction of the original class function to that subgroup.*)\nLemma cfResMorph (G H : {group aT}) (phi : 'CF(f @* G)) :\n H \\subset G -> G \\subset D -> 'Res (cfMorph phi) = cfMorph ('Res[f @* H] phi).\n\nEnd Morphim.\n\nPrenex Implicits cfMorph.\n\nSection Isomorphism.\n\nVariables (aT rT : finGroupType) (G : {group aT}) (f : {morphism G >-> rT}).\nVariable R : {group rT}.\n\nHypothesis isoGR : isom G R f.\n\n(*This definition establishes an alias for the codomain group of a given group isomorphism, obtained from the image of the isomorphism.*)\nLet defR := isom_im isoGR.\n(*This notation defines a local alias for the domain group of a group isomorphism, constructed as the image of the codomain group under the inverse isomorphism.*)\nLocal Notation G1 := (isom_inv isoGR @* R).\n(*This definition provides the proof that the domain group of a group isomorphism is equal to the group constructed as the image of the codomain group under the inverse isomorphism.*)\nLet defG : G1 = G := isom_im (isom_sym isoGR).\n\n(*This fact defines an opaque key used to lock the definition of the class function isomorphism, controlling its computational behavior.*)\nFact cfIsom_key : unit. \n(*This definition specifies a mapping that transforms a class function on the domain of a group isomorphism into a class function on the codomain, such that the value of the new function at the image of an element is the same as the original function's value at that element.*)\nDefinition cfIsom :=\n locked_with cfIsom_key (cfMorph \\o 'Res[G1] : 'CF(G) -> 'CF(R)).\nCanonical cfIsom_unlockable := [unlockable of cfIsom].\n\n(*This lemma states that for a given group isomorphism, the class function induced on the codomain, when evaluated at the image of an element from the domain group, yields the same value as the original class function evaluated at that element.*)\nLemma cfIsomE phi (x : aT : finType) : x \\in G -> cfIsom phi (f x) = phi x.\n\n(*This lemma states that the class function induced on the codomain by a group isomorphism evaluates to the same value at the identity element as the original class function does at its identity element.*)\nLemma cfIsom1 phi : cfIsom phi 1%g = phi 1%g.\n\n(*This lemma states that the mapping which transforms class functions along a group isomorphism is an additive group homomorphism, meaning it preserves addition and the zero element.*)\nLemma cfIsom_is_zmod_morphism : zmod_morphism cfIsom.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `cfIsom_is_zmod_morphism` instead\")]\n(*This definition is a deprecated alias for the lemma stating that the class function isomorphism mapping preserves addition.*)\nDefinition cfIsom_is_additive := cfIsom_is_zmod_morphism.\n\n(*This lemma states that the mapping which transforms class functions along a group isomorphism is a monoid homomorphism, meaning it preserves pointwise multiplication and the multiplicative identity class function.*)\nLemma cfIsom_is_monoid_morphism : monoid_morphism cfIsom.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `cfIsom_is_monoid_morphism` instead\")]\n(*This definition is a deprecated alias for the property that the class function isomorphism mapping preserves pointwise multiplication.*)\nDefinition cfIsom_is_multiplicative :=\n (fun g => (g.2,g.1)) cfIsom_is_monoid_morphism.\n\n(*This lemma states that the mapping which transforms class functions along a group isomorphism is scalable, meaning it commutes with scalar multiplication.*)\nLemma cfIsom_is_scalable : scalable cfIsom.\n\nHB.instance Definition _ := GRing.isZmodMorphism.Build _ _ cfIsom cfIsom_is_zmod_morphism.\nHB.instance Definition _ := GRing.isMonoidMorphism.Build _ _ cfIsom\n cfIsom_is_monoid_morphism.\n(*This lemma states that the mapping which transforms class functions along a group isomorphism maps the multiplicative identity class function, which is constant one, to itself.*)\nLemma cfIsom_cfun1 : cfIsom 1 = 1. \n\n(*This lemma states that the kernel of a class function transformed by a group isomorphism is equal to the image of the kernel of the original class function under that same isomorphism.*)\nLemma cfker_isom phi : cfker (cfIsom phi) = f @* cfker phi.\n\nEnd Isomorphism.\n\nPrenex Implicits cfIsom.\n\nSection InvMorphism.\n\nVariables (aT rT : finGroupType) (G : {group aT}) (f : {morphism G >-> rT}).\nVariable R : {group rT}.\n\nHypothesis isoGR : isom G R f.\n\n(*This lemma states that the class function isomorphism induced by a group isomorphism acts as a left inverse to the class function isomorphism induced by the inverse group isomorphism, meaning their composition is the identity function.*)\nLemma cfIsomK : cancel (cfIsom isoGR) (cfIsom (isom_sym isoGR)).\n\n(*This lemma states that the class function isomorphism induced by the inverse of a group isomorphism acts as a left inverse to the class function isomorphism induced by the original group isomorphism, meaning their composition is the identity function.*)\nLemma cfIsomKV : cancel (cfIsom (isom_sym isoGR)) (cfIsom isoGR).\n\n(*This lemma states that the mapping which transforms class functions along a group isomorphism is injective.*)\nLemma cfIsom_inj : injective (cfIsom isoGR). \n\n(*This lemma states that a class function transformed by a group isomorphism is the multiplicative identity class function if and only if the original class function is the multiplicative identity.*)\nLemma cfIsom_eq1 phi : (cfIsom isoGR phi == 1) = (phi == 1).\n\n(*This lemma states that the order of a class function is preserved when it is transformed by a group isomorphism.*)\nLemma cforder_isom phi : #[cfIsom isoGR phi]%CF = #[phi]%CF.\n\nEnd InvMorphism.\n\nArguments cfIsom_inj {aT rT G f R} isoGR [phi1 phi2] : rename.\n\nSection Coset.\n\nVariables (gT : finGroupType) (G : {group gT}) (B : {set gT}).\nImplicit Type rT : finGroupType.\n(*This notation defines a local alias for the subgroup generated by a given set of group elements.*)\nLocal Notation H := <>%g.\n\n(*This definition defines a function that lifts a class function defined on the cosets of a subgroup to a class function on the parent group.*)\nDefinition cfMod : 'CF(G / B) -> 'CF(G) := cfMorph.\n\n(*This definition specifies the construction of a function on the cosets of a subgroup, derived from a class function on the parent group. For each coset, its value is conditionally defined by evaluating the original class function at a coset representative if the subgroup is contained in the function's kernel, and at the identity otherwise.*)\nDefinition ffun_Quo (phi : 'CF(G)) :=\n [ffun Hx : coset_of B =>\n phi (if B \\subset cfker phi then repr Hx else 1%g) *+ (Hx \\in G / B)%g].\n(*This fact provides the proof that the function constructed by projecting a class function from a group to its cosets is a well-defined class function on the set of cosets.*)\nFact cfQuo_subproof phi : is_class_fun <> (ffun_Quo phi).\n\n(*This definition defines an operator that projects a class function from a group onto the set of cosets of a given subgroup, yielding a new class function on the cosets.*)\nDefinition cfQuo phi := Cfun 1 (cfQuo_subproof phi).\n\n(*This notation provides syntax for projecting a class function onto the cosets of a subgroup.*)\nLocal Notation \"phi / 'B'\" := (cfQuo phi)\n (at level 40, left associativity) : cfun_scope.\n(*This notation provides syntax for lifting a class function defined on the cosets of a subgroup to a class function on the parent group.*)\nLocal Notation \"phi %% 'B'\" := (cfMod phi) (at level 40) : cfun_scope.\n\n(*This lemma states that for a normal subgroup, the class function lifted from the quotient group, when evaluated at an element of the parent group, yields the same value as the original class function evaluated at the coset containing that element.*)\nLemma cfModE phi x : B <| G -> x \\in G -> (phi %% B)%CF x = phi (coset B x).\n\n(*This lemma states that a class function lifted from the cosets of a subgroup evaluates to the same value at the identity element of the parent group as the original function does at the identity coset.*)\nLemma cfMod1 phi : (phi %% B)%CF 1%g = phi 1%g. \n\n(*This lemma states that the class function obtained by modulating the multiplicative identity class function by a group is equal to the multiplicative identity class function itself.*)\nLemma cfMod_cfun1 : (1 %% B)%CF = 1. \n\n(*This lemma states that for a class function on a group, if a subgroup is normal, then this subgroup is contained within the character kernel of the class function modulated by that subgroup.*)\nLemma cfker_mod phi : B <| G -> B \\subset cfker (phi %% B).\n\n(*This lemma states that for a class function on a group, if a subgroup is contained in the character kernel of the class function and an element belongs to the normalizer of that subgroup, then the value of the quotient class function at the coset formed by the element is equal to the value of the original class function at that element.*)\nLemma cfQuoEnorm (phi : 'CF(G)) x :\n B \\subset cfker phi -> x \\in 'N_G(B) -> (phi / B)%CF (coset B x) = phi x.\n\n(*This lemma states that for a class function on a group, if a subgroup is normal and is contained in the character kernel of the class function, then for any element in the group, the value of the quotient class function at the coset formed by that element is equal to the value of the original class function at that element.*)\nLemma cfQuoE (phi : 'CF(G)) x :\n B <| G -> B \\subset cfker phi -> x \\in G -> (phi / B)%CF (coset B x) = phi x.\n\n(*This lemma states that the value of a quotient class function at the coset of the identity element is equal to the value of the original class function at the identity element.*)\nLemma cfQuo1 (phi : 'CF(G)) : (phi / B)%CF 1%g = phi 1%g.\n\n(*This lemma states that if a subgroup is not contained in the character kernel of a class function, then the quotient of that class function by the subgroup is a constant function whose value is the same as the original class function evaluated at the identity element.*)\nLemma cfQuoEout (phi : 'CF(G)) :\n ~~ (B \\subset cfker phi) -> (phi / B)%CF = (phi 1%g)%:A.\n\n(*This lemma states that the class function obtained by taking the quotient of the multiplicative identity class function by a group is equal to the multiplicative identity class function itself.*)\nLemma cfQuo_cfun1 : (1 / B)%CF = 1.\n\n(*This lemma states that for a normal subgroup, the modulation operation is a left inverse to the quotient operation on class functions.*)\nLemma cfModK : B <| G -> cancel cfMod cfQuo.\n\n(*This lemma states that for a class function on a group, if a subgroup is normal and is contained within the character kernel of the class function, then modulating the quotient of the class function by that subgroup results in the original class function.*)\nLemma cfQuoK :\n B <| G -> forall phi, B \\subset cfker phi -> (phi / B %% B)%CF = phi.\n\n(*This lemma states that for a class function on a quotient group, its modulation by the corresponding normal subgroup is equal to the identity class function if and only if the original class function is equal to the identity class function.*)\nLemma cfMod_eq1 psi : B <| G -> (psi %% B == 1)%CF = (psi == 1).\n\n(*This lemma states that for a class function on a group, if a normal subgroup is contained in its character kernel, then the quotient of the class function by that subgroup is equal to the identity class function if and only if the original class function is equal to the identity class function.*)\nLemma cfQuo_eq1 phi :\n B <| G -> B \\subset cfker phi -> (phi / B == 1)%CF = (phi == 1).\n\nEnd Coset.\n\nArguments cfQuo {gT G%_G} B%_g phi%_CF.\nArguments cfMod {gT G%_G B%_g} phi%_CF.\n(*This notation defines the quotient of a class function by a subgroup.*)\nNotation \"phi / H\" := (cfQuo H phi) : cfun_scope.\n(*This notation defines the modulation of a class function defined on a quotient group by the corresponding normal subgroup.*)\nNotation \"phi %% H\" := (@cfMod _ _ H phi) : cfun_scope.\n\nSection MoreCoset.\n\nVariables (gT : finGroupType) (G : {group gT}).\nImplicit Types (H K : {group gT}) (phi : 'CF(G)).\n\n(*This lemma states that for a class function on a quotient group, restricting its modulation to a subgroup is equivalent to first restricting the class function to the corresponding quotient of the subgroup and then applying the modulation.*)\nLemma cfResMod H K (psi : 'CF(G / K)) :\n H \\subset G -> K <| G -> ('Res (psi %% K) = 'Res[H / K] psi %% K)%CF.\n\n(*This lemma states that for a class function on a quotient group, the quotient of the character kernel of its modulation by the normal subgroup is equal to the character kernel of the original class function.*)\nLemma quotient_cfker_mod (A : {set gT}) K (psi : 'CF(G / K)) :\n K <| G -> (cfker (psi %% K) / K)%g = cfker psi.\n\n(*This lemma states that for a class function on a quotient group and a set of elements contained in the normalizer of the corresponding normal subgroup, the set is a subset of the character kernel of the modulated class function if and only if the quotient of the set is a subset of the character kernel of the original class function.*)\nLemma sub_cfker_mod (A : {set gT}) K (psi : 'CF(G / K)) :\n K <| G -> A \\subset 'N(K) ->\n (A \\subset cfker (psi %% K)) = (A / K \\subset cfker psi)%g.\n\n(*This lemma states that if a normal subgroup is contained in the character kernel of a class function, then the character kernel of the quotient class function is the quotient of the original character kernel by that subgroup.*)\nLemma cfker_quo H phi :\n H <| G -> H \\subset cfker (phi) -> cfker (phi / H) = (cfker phi / H)%g.\n\n(*This lemma states that for any class function, the value of its quotient by its own character kernel at a given coset is equal to the value of the original class function at the representative element of that coset.*)\nLemma cfQuoEker phi x :\n x \\in G -> (phi / cfker phi)%CF (coset (cfker phi) x) = phi x.\n\n(*This lemma states that the quotient of any class function by its own character kernel is a faithful class function, meaning its character kernel is trivial.*)\nLemma cfaithful_quo phi : cfaithful (phi / cfker phi).\n\n(*This lemma states that under certain subgroup inclusion conditions, restricting a quotient class function to a quotient subgroup is equivalent to taking the quotient of the restricted original class function.*)\nLemma cfResQuo H K phi :\n K \\subset cfker phi -> K \\subset H -> H \\subset G ->\n ('Res[H / K] (phi / K) = 'Res[H] phi / K)%CF.\n\n(*This lemma states that if a subgroup is contained in the character kernel of a class function, the resulting quotient class function is equivalent to the inflation of the quotient of the class function restricted to the normalizer of that subgroup.*)\nLemma cfQuoInorm K phi :\n K \\subset cfker phi -> (phi / K)%CF = 'Res ('Res['N_G(K)] phi / K)%CF.\n\n(*This lemma states that the order of a modulated class function is equal to the order of the original class function on the quotient group.*)\nLemma cforder_mod H (psi : 'CF(G / H)) : H <| G -> #[psi %% H]%CF = #[psi]%CF.\n\n(*This lemma states that if a normal subgroup is contained in the character kernel of a class function, the order of the quotient class function is equal to the order of the original class function.*)\nLemma cforder_quo H phi :\n H <| G -> H \\subset cfker phi -> #[phi / H]%CF = #[phi]%CF.\n\nEnd MoreCoset.\n\nSection Product.\n\nVariable (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that the product of two class functions, each having values in a specific set, is a class function whose values lie in the intersection of those two sets.*)\nLemma cfunM_onI A B phi psi :\n phi \\in 'CF(G, A) -> psi \\in 'CF(G, B) -> phi * psi \\in 'CF(G, A :&: B).\n\n(*This lemma states that the product of two class functions that both have values in a given set is also a class function with values in that same set.*)\nLemma cfunM_on A phi psi :\n phi \\in 'CF(G, A) -> psi \\in 'CF(G, A) -> phi * psi \\in 'CF(G, A).\n\nEnd Product.\n\nSection SDproduct.\n\nVariables (gT : finGroupType) (G K H : {group gT}).\nHypothesis defG : K ><| H = G.\n\n(*This fact serves as a private key to lock the definition of the semidirect product of class functions, ensuring its definitional properties are encapsulated.*)\nFact cfSdprodKey : unit. \n\n(*This definition specifies a function that maps a class function on a subgroup to a class function on the containing group, assuming the containing group is a semidirect product. This is achieved by composing a morphism with an isomorphism related to the semidirect product structure.*)\nDefinition cfSdprod :=\n locked_with cfSdprodKey\n (cfMorph \\o cfIsom (tagged (sdprod_isom defG)) : 'CF(H) -> 'CF(G)).\nCanonical cfSdprod_unlockable := [unlockable of cfSdprod].\n\n(*This lemma states that the function mapping class functions via the semidirect product structure is a morphism of modules over the integers, a property which implies it preserves addition and the zero element.*)\nLemma cfSdprod_is_zmod_morphism : zmod_morphism cfSdprod.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `cfSdprod_is_zmod_morphism` instead\")]\n(*This definition provides a deprecated alias stating that the function mapping class functions via the semidirect product structure is an additive function. It is now recommended to use the equivalent property that it is a module morphism over the integers.*)\nDefinition cfSdprod_is_additive := cfSdprod_is_zmod_morphism.\n\n(*This lemma states that the function mapping class functions via the semidirect product structure is a monoid morphism, meaning it preserves multiplication and the multiplicative identity element.*)\nLemma cfSdprod_is_monoid_morphism : monoid_morphism cfSdprod.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `cfSdprod_is_monoid_morphism` instead\")]\n(*This definition provides a deprecated proof that the `cfSdprod` operator for class functions respects multiplication, establishing it as a monoid morphism.*)\nDefinition cfSdprod_is_multiplicative :=\n (fun g => (g.2,g.1)) cfSdprod_is_monoid_morphism.\n\n(*This lemma states that the `cfSdprod` operator for class functions is scalable, which means that it commutes with scalar multiplication.*)\nLemma cfSdprod_is_scalable : scalable cfSdprod.\n\nHB.instance Definition _ := GRing.isZmodMorphism.Build _ _ cfSdprod cfSdprod_is_zmod_morphism.\nHB.instance Definition _ := GRing.isMonoidMorphism.Build _ _ cfSdprod\n cfSdprod_is_monoid_morphism.\n(*This lemma asserts that evaluating a `cfSdprod`-lifted class function at the group's identity element yields the same value as evaluating the original class function at the identity element of its domain.*)\nLemma cfSdprod1 phi : cfSdprod phi 1%g = phi 1%g.\n\n(*This lemma establishes that the group K is a normal subgroup of the group G, based on the properties derived from a semidirect product construction.*)\nLet nsKG : K <| G. \n(*This statement introduces the local assumption that a group `H` is a subgroup of a group `G`.*)\nLet sHG : H \\subset G. \n(*This statement introduces the local assumption that a group `K` is a subgroup of a group `G`.*)\nLet sKG : K \\subset G. \n\n(*This lemma states that for any given class function, the normal subgroup `K` of the semidirect product group is entirely contained within the kernel of the class function lifted by `cfSdprod`.*)\nLemma cfker_sdprod phi : K \\subset cfker (cfSdprod phi).\n\n(*This lemma asserts that a class function lifted by `cfSdprod` from a subgroup `H` has the same values as the original class function for all elements within that subgroup `H`.*)\nLemma cfSdprodEr phi : {in H, cfSdprod phi =1 phi}.\n\n(*This lemma specifies that a `cfSdprod`-lifted class function, when evaluated at a product of an element from subgroup `K` and an element from subgroup `H`, returns the value of the original class function at the element from `H`.*)\nLemma cfSdprodE phi : {in K & H, forall x y, cfSdprod phi (x * y)%g = phi y}.\n\n(*This lemma states that the `cfSdprod` operator is a left inverse to the operation of restricting a class function to the subgroup `H`.*)\nLemma cfSdprodK : cancel cfSdprod 'Res[H].\n\n(*This lemma asserts that the `cfSdprod` operator is injective, which means that distinct class functions are mapped to distinct lifted class functions.*)\nLemma cfSdprod_inj : injective cfSdprod. \n\n(*This lemma proves that a class function lifted by `cfSdprod` is the unit class function if and only if the original class function was also the unit class function.*)\nLemma cfSdprod_eq1 phi : (cfSdprod phi == 1) = (phi == 1).\n\n(*This lemma states that if the subgroup `K` is contained within the kernel of a class function, then lifting the restriction of that class function from subgroup `H` back to the full group using `cfSdprod` recovers the original class function.*)\nLemma cfRes_sdprodK phi : K \\subset cfker phi -> cfSdprod ('Res[H] phi) = phi.\n\n(*This lemma shows that the kernel of a class function lifted by `cfSdprod` is equal to the semidirect product of the subgroup `K` and the kernel of the original class function.*)\nLemma sdprod_cfker phi : K ><| cfker phi = cfker (cfSdprod phi).\n\n(*This lemma asserts that the `cfSdprod` operator preserves the order of a class function, meaning that the order of the lifted class function is identical to the order of the original one.*)\nLemma cforder_sdprod phi : #[cfSdprod phi]%CF = #[phi]%CF.\n\nEnd SDproduct.\n\nSection DProduct.\n\nVariables (gT : finGroupType) (G K H : {group gT}).\nHypothesis KxH : K \\x H = G.\n\n(*This lemma states that for a group which is a direct product of two subgroups, a large commutative operation over all elements of the group can be rewritten as a nested operation over the elements of the two subgroups.*)\nLemma reindex_dprod R idx (op : Monoid.com_law idx) (F : gT -> R) :\n \\big[op/idx]_(g in G) F g =\n \\big[op/idx]_(k in K) \\big[op/idx]_(h in H) F (k * h)%g.\n\n(*This definition introduces the `cfDprodr` operator, which lifts a class function defined on the right-hand factor of a direct product group to a class function on the entire product group.*)\nDefinition cfDprodr := cfSdprod (dprodWsd KxH).\n(*This definition introduces the `cfDprodl` operator, which lifts a class function defined on the left-hand factor of a direct product group to a class function on the entire product group.*)\nDefinition cfDprodl := cfSdprod (dprodWsdC KxH).\n(*This definition creates a class function on a direct product group by multiplying the results of lifting two class functions, one from the left factor via `cfDprodl` and one from the right factor via `cfDprodr`.*)\nDefinition cfDprod phi psi := cfDprodl phi * cfDprodr psi.\n\nHB.instance Definition _ := GRing.LRMorphism.on cfDprodl.\n(*This lemma states that a class function lifted from the left factor of a direct product, when evaluated at the identity element of the product group, yields the same value as the original class function evaluated at the identity of its domain.*)\nLemma cfDprodl1 phi : cfDprodl phi 1%g = phi 1%g. \n(*This lemma states that a class function lifted from the right factor of a direct product, when evaluated at the identity element of the product group, yields the same value as the original class function evaluated at the identity of its domain.*)\nLemma cfDprodr1 psi : cfDprodr psi 1%g = psi 1%g. \n(*This lemma asserts that the class function created by `cfDprod`, when evaluated at the identity of the product group, results in the product of the values of the two original class functions at their respective identity elements.*)\nLemma cfDprod1 phi psi : cfDprod phi psi 1%g = phi 1%g * psi 1%g.\n\n(*This lemma establishes that a class function lifted from the left factor group using `cfDprodl` is the unit class function if and only if the original class function is the unit class function.*)\nLemma cfDprodl_eq1 phi : (cfDprodl phi == 1) = (phi == 1).\n\n(*This lemma establishes that a class function lifted from the right factor group using `cfDprodr` is the unit class function if and only if the original class function is the unit class function.*)\nLemma cfDprodr_eq1 psi : (cfDprodr psi == 1) = (psi == 1).\n\n(*This lemma shows that creating a direct product class function using `cfDprod` where the right component is the unit class function is equivalent to simply lifting the left class function using `cfDprodl`.*)\nLemma cfDprod_cfun1r phi : cfDprod phi 1 = cfDprodl phi.\n\n(*This lemma shows that creating a direct product class function using `cfDprod` where the left component is the unit class function is equivalent to simply lifting the right class function using `cfDprodr`.*)\nLemma cfDprod_cfun1l psi : cfDprod 1 psi = cfDprodr psi.\n\n(*This lemma states that applying the `cfDprod` operator with the unit class function for both factors yields the unit class function on the direct product group.*)\nLemma cfDprod_cfun1 : cfDprod 1 1 = 1.\n\n(*This lemma shows that the direct product class function `cfDprod` of two class functions can be decomposed into the product of the `cfDprod` of the first class function with the unit function and the `cfDprod` of the unit function with the second class function.*)\nLemma cfDprod_split phi psi : cfDprod phi psi = cfDprod phi 1 * cfDprod 1 psi.\n\n(*This statement introduces the local assumption that a group `K` is a normal subgroup of a group `G`.*)\nLet nsKG : K <| G. \n(*This hypothesis asserts that a group H is a normal subgroup of a group G.*)\nLet nsHG : H <| G. \n(*This hypothesis asserts that a group H is a subset of the centralizer of a group K, meaning every element of H commutes with every element of K.*)\nLet cKH : H \\subset 'C(K). \n(*This definition establishes the canonical subgroup structure for a group K, based on the assumption that it is a normal subgroup of a group G.*)\nLet sKG := normal_sub nsKG.\n(*This definition establishes the canonical subgroup structure for a group H, based on the assumption that it is a normal subgroup of a group G.*)\nLet sHG := normal_sub nsHG.\n\n(*This lemma states that applying the operator to lift a class function from a group K to its direct product with another group, and then restricting the resulting function back to K, recovers the original class function.*)\nLemma cfDprodlK : cancel cfDprodl 'Res[K]. \n(*This lemma states that applying the operator to lift a class function from a group H to its direct product with another group, and then restricting the resulting function back to H, recovers the original class function.*)\nLemma cfDprodrK : cancel cfDprodr 'Res[H]. \n\n(*This lemma states that the kernel of a class function lifted from a group K to the direct product of K and H is the direct product of the kernel of the original class function on K and the entire group H.*)\nLemma cfker_dprodl phi : cfker phi \\x H = cfker (cfDprodl phi).\n\n(*This lemma states that the kernel of a class function lifted from a group H to the direct product of K and H is the direct product of the entire group K and the kernel of the original class function on H.*)\nLemma cfker_dprodr psi : K \\x cfker psi = cfker (cfDprodr psi).\n\n(*This lemma states that for any element k from a group K and any element h from a group H, applying a class function lifted from K to their product is equivalent to applying the original class function to k.*)\nLemma cfDprodEl phi : {in K & H, forall k h, cfDprodl phi (k * h)%g = phi k}.\n\n(*This lemma states that for any element k from a group K and any element h from a group H, applying a class function lifted from H to their product is equivalent to applying the original class function to h.*)\nLemma cfDprodEr psi : {in K & H, forall k h, cfDprodr psi (k * h)%g = psi h}.\n\n(*This lemma states that applying the direct product of two class functions to the product of two group elements, one from each component group, is equivalent to the product of the values obtained by applying each class function to its corresponding element.*)\nLemma cfDprodE phi psi :\n {in K & H, forall h k, cfDprod phi psi (h * k)%g = phi h * psi k}.\n\n(*This lemma states that restricting the direct product of two class functions, one on group K and another on group H, to the subgroup K yields the first class function scaled by the value of the second class function at the identity element.*)\nLemma cfDprod_Resl phi psi : 'Res[K] (cfDprod phi psi) = psi 1%g *: phi.\n\n(*This lemma states that restricting the direct product of two class functions, one on group K and another on group H, to the subgroup H yields the second class function scaled by the value of the first class function at the identity element.*)\nLemma cfDprod_Resr phi psi : 'Res[H] (cfDprod phi psi) = phi 1%g *: psi.\n\n(*This lemma states that if a class function on a group H evaluates to one at the identity element, then the operator that forms a direct product class function with this function as the second component is a right inverse to the restriction operator from the product group to the first component group K.*)\nLemma cfDprodKl (psi : 'CF(H)) : psi 1%g = 1 -> cancel (cfDprod^~ psi) 'Res.\n\n(*This lemma states that if a class function on a group K evaluates to one at the identity element, then the operator that forms a direct product class function with this function as the first component is a right inverse to the restriction operator from the product group to the second component group H.*)\nLemma cfDprodKr (phi : 'CF(K)) : phi 1%g = 1 -> cancel (cfDprod phi) 'Res.\n\n(*This lemma states that the subgroup generated by the kernels of two class functions, one on group K and one on group H, is a subgroup of the kernel of their direct product class function.*)\nLemma cfker_dprod phi psi :\n cfker phi <*> cfker psi \\subset cfker (cfDprod phi psi).\n\n(*This lemma states that the inner product of two direct product class functions is equal to the product of the inner products of their respective component class functions.*)\nLemma cfdot_dprod phi1 phi2 psi1 psi2 :\n '[cfDprod phi1 psi1, cfDprod phi2 psi2] = '[phi1, phi2] * '[psi1, psi2].\n\n(*This lemma states that the operation of lifting a class function from a group K to the direct product of K and H preserves the inner product, making it an isometry.*)\nLemma cfDprodl_iso : isometry cfDprodl.\n\n(*This lemma states that the operation of lifting a class function from a group H to the direct product of K and H preserves the inner product, making it an isometry.*)\nLemma cfDprodr_iso : isometry cfDprodr.\n\n(*This lemma states that the order of a class function lifted from a group K to the direct product of K and H is identical to the order of the original class function.*)\nLemma cforder_dprodl phi : #[cfDprodl phi]%CF = #[phi]%CF.\n\n(*This lemma states that the order of a class function lifted from a group H to the direct product of K and H is identical to the order of the original class function.*)\nLemma cforder_dprodr psi : #[cfDprodr psi]%CF = #[psi]%CF.\n\nEnd DProduct.\n\n(*This lemma states that, given two groups K and H whose direct products, K-times-H and H-times-K, are both equal to a group G, the direct product class function formed from a class function on K and a class function on H is equivalent to the one formed by swapping the order of the component groups and their corresponding class functions.*)\nLemma cfDprodC (gT : finGroupType) (G K H : {group gT})\n (KxH : K \\x H = G) (HxK : H \\x K = G) chi psi :\n cfDprod KxH chi psi = cfDprod HxK psi chi.\n\nSection Bigdproduct.\n\nVariables (gT : finGroupType) (I : finType) (P : pred I).\nVariables (A : I -> {group gT}) (G : {group gT}).\nHypothesis defG : \\big[dprod/1%g]_(i | P i) A i = G.\n\n(*This definition provides the subgroup inclusion of a component group into the larger direct product group for each index satisfying a given predicate.*)\nLet sAG i : P i -> A i \\subset G.\n\n(*This fact states that a large direct product group can be represented as the internal direct product of any single component group and the subgroup generated by all other component groups.*)\nFact cfBigdprodi_subproof i :\n gval (if P i then A i else 1%G) \\x <<\\bigcup_(j | P j && (j != i)) A j>> = G.\n\n(*This definition constructs an operator that lifts a class function from a component group to the larger direct product group, based on a decomposition of the large group into that component and the product of the others.*)\nDefinition cfBigdprodi i := cfDprodl (cfBigdprodi_subproof i) \\o 'Res[_, A i].\n\n(*This lemma states that applying a class function that has been lifted from a component group to the identity element of the large group yields the same value as applying the original class function to the identity element of its component group.*)\nLemma cfBigdprodi1 i (phi : 'CF(A i)) : cfBigdprodi phi 1%g = phi 1%g.\n\n(*This lemma states that for an active component group, its lifted class function is the trivial character, which always evaluates to one, if and only if the original class function on the component group is also the trivial character.*)\nLemma cfBigdprodi_eq1 i (phi : 'CF(A i)) :\n P i -> (cfBigdprodi phi == 1) = (phi == 1).\n\n(*This lemma states that for an active component group, applying the lifting operator to one of its class functions and then restricting the result back to that component group yields the original class function.*)\nLemma cfBigdprodiK i : P i -> cancel (@cfBigdprodi i) 'Res[A i].\n\n(*This lemma states that for an active component group, the lifting operator for class functions is injective, meaning distinct class functions on the component group are mapped to distinct class functions on the large direct product group.*)\nLemma cfBigdprodi_inj i : P i -> injective (@cfBigdprodi i).\n\n(*This lemma states that projecting a class function from a dependent product of groups to a single component group, and then evaluating it at an element of that product, is equivalent to evaluating the original component class function at the corresponding component of the element.*)\nLemma cfBigdprodEi i (phi : 'CF(A i)) x :\n P i -> (forall j, P j -> x j \\in A j) ->\n cfBigdprodi phi (\\prod_(j | P j) x j)%g = phi (x i).\n\n(*This lemma states that for a given index, the function that projects a class function from a dependent product of groups to its corresponding component class function is an isometry, meaning it preserves the inner product.*)\nLemma cfBigdprodi_iso i : P i -> isometry (@cfBigdprodi i).\n\n(*This definition constructs a class function on a dependent product of groups from a family of class functions, one for each component group.*)\nDefinition cfBigdprod (phi : forall i, 'CF(A i)) :=\n \\prod_(i | P i) cfBigdprodi (phi i).\n\n(*This lemma states that evaluating the class function of a dependent product at a product element is equivalent to forming a product of the values obtained by evaluating each component class function at the corresponding component of the element.*)\nLemma cfBigdprodE phi x :\n (forall i, P i -> x i \\in A i) ->\n cfBigdprod phi (\\prod_(i | P i) x i)%g = \\prod_(i | P i) phi i (x i).\n\n(*This lemma states that evaluating the class function of a dependent product at the identity element is equivalent to the product of the evaluations of each component class function at the identity element of its respective group.*)\nLemma cfBigdprod1 phi : cfBigdprod phi 1%g = \\prod_(i | P i) phi i 1%g.\n\n(*This lemma asserts a relationship between a component class function and the total class function on a dependent product, showing that, under certain non-zero conditions, the component class function can be recovered by scaling the restriction of the total class function.*)\nLemma cfBigdprodK phi (Phi := cfBigdprod phi) i (a := phi i 1%g / Phi 1%g) :\n Phi 1%g != 0 -> P i -> a != 0 /\\ a *: 'Res[A i] Phi = phi i.\n\n(*This lemma states that the inner product of two class functions on a dependent product of groups is equal to the product of the inner products of their corresponding component class functions.*)\nLemma cfdot_bigdprod phi psi :\n '[cfBigdprod phi, cfBigdprod psi] = \\prod_(i | P i) '[phi i, psi i].\n\nEnd Bigdproduct.\n\nSection MorphIsometry.\n\nVariable gT : finGroupType.\nImplicit Types (D G H K : {group gT}) (aT rT : finGroupType).\n\n(*This lemma states that the function which restricts class functions from a group to a subgroup, via a group morphism, is an isometry, provided the subgroup is contained in the domain of the morphism.*)\nLemma cfMorph_iso aT rT (G D : {group aT}) (f : {morphism D >-> rT}) :\n G \\subset D -> isometry (cfMorph : 'CF(f @* G) -> 'CF(G)).\n\n(*This lemma states that the function which transports class functions across a group isomorphism is an isometry.*)\nLemma cfIsom_iso rT G (R : {group rT}) (f : {morphism G >-> rT}) :\n forall isoG : isom G R f, isometry (cfIsom isoG).\n\n(*This lemma states that for a normal subgroup, the function that lifts class functions from the quotient group to the original group is an isometry.*)\nLemma cfMod_iso H G : H <| G -> isometry (@cfMod _ G H).\n\n(*This lemma states that for a normal subgroup, the function that quotients a class function of the group to a class function of the quotient group is an isometry when restricted to the set of class functions whose kernel contains the normal subgroup.*)\nLemma cfQuo_iso H G :\n H <| G -> {in [pred phi | H \\subset cfker phi] &, isometry (@cfQuo _ G H)}.\n\n(*This lemma states that for a normal subgroup and a class function whose kernel contains that subgroup, the squared norm of the resulting quotient class function is equal to the squared norm of the original class function.*)\nLemma cfnorm_quo H G phi :\n H <| G -> H \\subset cfker phi -> '[phi / H] = '[phi]_G.\n\n(*This lemma states that the function which constructs a class function on a semidirect product group from its constituent groups is an isometry.*)\nLemma cfSdprod_iso K H G (defG : K ><| H = G) : isometry (cfSdprod defG).\n\nEnd MorphIsometry.\n\nSection Induced.\n\nVariable gT : finGroupType.\n\nSection Def.\n\nVariables B A : {set gT}.\n(*A local notation for the subgroup generated by a given set of elements from a finite group type.*)\nLocal Notation G := <>.\n(*This notation defines a local alias for the group generated by a given set of elements.*)\nLocal Notation H := <>.\n\n(*This definition specifies the underlying function for an induced class function. If the source set generates a subgroup of the target group, it computes a normalized sum of the given class function applied to all conjugates of the input element; otherwise, it produces a scaled multiple of the trivial character.*)\nDefinition ffun_cfInd (phi : 'CF(A)) :=\n [ffun x => if H \\subset G then #|A|%:R^-1 * (\\sum_(y in G) phi (x ^ y))\n else #|G|%:R * '[phi, 1] *+ (x == 1%g)].\n\n(*This fact proves that the function underlying the induction map produces a valid class function on the larger group.*)\nFact cfInd_subproof phi : is_class_fun G (ffun_cfInd phi).\n\n(*This definition formally constructs an induced class function on a larger group from a class function on a smaller set, based on a proof that the underlying map is constant on conjugacy classes.*)\nDefinition cfInd phi := Cfun 1 (cfInd_subproof phi).\n\n(*This lemma states that the induction map, which transforms a class function from a subgroup to a class function on the larger group, is a linear transformation.*)\nLemma cfInd_is_linear : linear cfInd.\n\n(*A notation for the induction of a class function from the group generated by the second set argument to the group generated by the first set argument.*)\nLocal Notation \"''Ind[' B , A ]\" := (@cfInd B A) : ring_scope.\n(*A notation for the induction of a class function to the group generated by the given set, where the source subgroup is inferred from the context.*)\nLocal Notation \"''Ind[' B ]\" := 'Ind[B, _] : ring_scope.\n\n(*This lemma provides the explicit formula for an induced class function evaluated at an element, given that the source group is a subgroup of the target group. The value is a normalized sum of the original class function applied to all conjugates of the element.*)\nLemma cfIndE (G H : {group gT}) phi x :\n H \\subset G -> 'Ind[G, H] phi x = #|H|%:R^-1 * (\\sum_(y in G) phi (x ^ y)).\n\nVariables G K H : {group gT}.\nImplicit Types (phi : 'CF(H)) (psi : 'CF(G)).\n\n(*This lemma states that if the source group is not a subgroup of the target group, the induced class function is a scalar multiple of the trivial character on the target group.*)\nLemma cfIndEout phi :\n ~~ (H \\subset G) -> 'Ind[G] phi = (#|G|%:R * '[phi, 1]) *: '1_1%G.\n\n(*This lemma provides a simplified formula for computing an induced class function in the specific case of a semidirect product, expressing it as a sum over one of the component subgroups.*)\nLemma cfIndEsdprod (phi : 'CF(K)) x :\n K ><| H = G -> 'Ind[G] phi x = \\sum_(w in H) phi (x ^ w)%g.\n\n(*This lemma states that inducing a class function whose values are algebraic integers results in another class function whose values are also algebraic integers.*)\nLemma cfInd_on A phi :\n H \\subset G -> phi \\in 'CF(H, A) -> 'Ind[G] phi \\in 'CF(G, class_support A G).\n\n(*This lemma states that inducing a class function from a group to itself yields the original class function.*)\nLemma cfInd_id phi : 'Ind[H] phi = phi.\n\n(*This lemma states that if a class function is induced from a normal subgroup, the resulting class function on the larger group is zero for all elements outside of that normal subgroup.*)\nLemma cfInd_normal phi : H <| G -> 'Ind[G] phi \\in 'CF(G, H).\n\n(*This lemma states that when a class function is induced from a subgroup, its value at the identity element of the larger group is the index of the subgroup multiplied by the value of the original class function at the identity.*)\nLemma cfInd1 phi : H \\subset G -> 'Ind[G] phi 1%g = #|G : H|%:R * phi 1%g.\n\n(*This lemma states that inducing the trivial character from a normal subgroup results in a class function on the larger group which is a scalar multiple of the trivial character of the subgroup, extended to be zero outside the subgroup. The scalar is the index of the subgroup.*)\nLemma cfInd_cfun1 : H <| G -> 'Ind[G, H] 1 = #|G : H|%:R *: '1_H.\n\n(*This lemma states that the squared norm of the class function resulting from inducing the trivial character of a normal subgroup is equal to the index of that subgroup in the larger group.*)\nLemma cfnorm_Ind_cfun1 : H <| G -> '['Ind[G, H] 1] = #|G : H|%:R.\n\n(*This lemma states that the induction of a class function is transitive. Inducing a class function from a subgroup to an intermediate subgroup, and then from the intermediate subgroup to a larger group, yields the same result as inducing the class function directly from the initial subgroup to the final group, provided the necessary subgroup inclusions hold.*)\nLemma cfIndInd phi :\n K \\subset G -> H \\subset K -> 'Ind[G] ('Ind[K] phi) = 'Ind[G] phi.\n\n(*This lemma states the Frobenius reciprocity theorem, which asserts that the inner product of a class function of a subgroup with the restriction of a class function from the whole group is equal to the inner product of the induced class function with the original class function from the whole group.*)\nLemma Frobenius_reciprocity phi psi : '[phi, 'Res[H] psi] = '['Ind[G] phi, psi].\n\n(*This definition provides an alias for the Frobenius reciprocity theorem, referring to it in the context of an inner product involving a restriction on the right-hand side.*)\nDefinition cfdot_Res_r := Frobenius_reciprocity.\n\n(*This lemma states a variant of the Frobenius reciprocity theorem, asserting that the inner product of a restricted class function with another class function of the subgroup is equal to the inner product of the original class function with the induced class function.*)\nLemma cfdot_Res_l psi phi : '['Res[H] psi, phi] = '[psi, 'Ind[G] phi].\n\n(*This lemma, also known as the projection formula, states that inducing the pointwise product of a class function of a subgroup and the restriction of a class function from the whole group is equivalent to taking the pointwise product of the induced class function and the original class function from the whole group.*)\nLemma cfIndM phi psi: H \\subset G ->\n 'Ind[G] (phi * ('Res[H] psi)) = 'Ind[G] phi * psi.\n\nEnd Induced.\n\nArguments cfInd {gT} B%_g {A%_g} phi%_CF.\n(*This notation provides a syntax for the induction of a class function from a subgroup to a group, where both the source subgroup and the target group are explicitly specified.*)\nNotation \"''Ind[' G , H ]\" := (@cfInd _ G H) (only parsing) : ring_scope.\n(*This notation provides a syntax for the induction of a class function to a specified group, leaving the source subgroup to be inferred from the context.*)\nNotation \"''Ind[' G ]\" := 'Ind[G, _] : ring_scope.\n(*This notation provides a general syntax for the induction of a class function, where both the source subgroup and the target group are to be inferred from the context.*)\nNotation \"''Ind'\" := 'Ind[_] (only parsing) : ring_scope.\n\nSection MorphInduced.\n\nVariables (aT rT : finGroupType) (D G H : {group aT}) (R S : {group rT}).\n\n(*This lemma states how a group morphism interacts with class function induction, asserting that inducing a class function that has been lifted via a group morphism is equivalent to first inducing the original class function between the images of the groups under the morphism and then lifting the result, under specific subgroup inclusion conditions.*)\nLemma cfIndMorph (f : {morphism D >-> rT}) (phi : 'CF(f @* H)) :\n 'ker f \\subset H -> H \\subset G -> G \\subset D ->\n 'Ind[G] (cfMorph phi) = cfMorph ('Ind[f @* G] phi).\n\nVariables (g : {morphism G >-> rT}) (h : {morphism H >-> rT}).\nHypotheses (isoG : isom G R g) (isoH : isom H S h) (eq_hg : {in H, h =1 g}).\nHypothesis sHG : H \\subset G.\n\n(*This lemma states that character restriction commutes with transportation across group isomorphisms. Restricting a class function that has been transported from a group to an isomorphic group is equivalent to first restricting the class function to a subgroup and then transporting the result via the corresponding subgroup isomorphism.*)\nLemma cfResIsom phi : 'Res[S] (cfIsom isoG phi) = cfIsom isoH ('Res[H] phi).\n\n(*This lemma states that character induction commutes with transportation across group isomorphisms. Inducing a class function that has been transported from a subgroup to an isomorphic subgroup is equivalent to first inducing the class function to the larger group and then transporting the result via the corresponding group isomorphism.*)\nLemma cfIndIsom phi : 'Ind[R] (cfIsom isoH phi) = cfIsom isoG ('Ind[G] phi).\n\nEnd MorphInduced.\n\nSection FieldAutomorphism.\n\nVariables (u : {rmorphism algC -> algC}) (gT rT : finGroupType).\nVariables (G K H : {group gT}) (f : {morphism G >-> rT}) (R : {group rT}).\nImplicit Types (phi : 'CF(G)) (S : seq 'CF(G)).\n(*This notation represents the application of a field automorphism to a class function, resulting in a new class function where each value has been transformed by the automorphism.*)\nLocal Notation \"phi ^u\" := (cfAut u phi).\n\n(*This lemma states that applying a field automorphism to a class function scaled by a natural number is equivalent to scaling the transformed class function by the same natural number.*)\nLemma cfAutZ_nat n phi : (n%:R *: phi)^u = n%:R *: phi^u.\n\n(*This lemma states that if a complex number is a natural number, then applying a field automorphism to a class function scaled by this number is equivalent to scaling the transformed class function by the same number.*)\nLemma cfAutZ_Cnat z phi : z \\in Num.nat -> (z *: phi)^u = z *: phi^u.\n\n(*This lemma states that if a complex number is an integer, then applying a field automorphism to a class function scaled by this number is equivalent to scaling the transformed class function by the same number.*)\nLemma cfAutZ_Cint z phi : z \\in Num.int -> (z *: phi)^u = z *: phi^u.\n\n(*This lemma states that the operation of applying a field automorphism to a class function is cancelled by applying the inverse field automorphism; that is, their composition is the identity function.*)\nLemma cfAutK : cancel (@cfAut gT G u) (cfAut (algC_invaut u)).\n\n(*This lemma states that the operation of applying an inverse field automorphism to a class function is cancelled by applying the original field automorphism; that is, their composition is the identity function.*)\nLemma cfAutVK : cancel (cfAut (algC_invaut u)) (@cfAut gT G u).\n\n(*This lemma states that the operation of applying a field automorphism to class functions is injective, meaning distinct class functions map to distinct transformed class functions.*)\nLemma cfAut_inj : injective (@cfAut gT G u).\n\n(*This lemma states that a class function transformed by a field automorphism is the principal character if and only if the original class function was the principal character.*)\nLemma cfAut_eq1 phi : (cfAut u phi == 1) = (phi == 1).\n\n(*This lemma states that the support of a class function, which is the set of group elements where the function is nonzero, remains the same after applying a field automorphism to the class function.*)\nLemma support_cfAut phi : support phi^u =i support phi.\n\n(*This lemma states that if a sequence of class functions is linearly independent and the set of functions is closed under a given field automorphism, then the sequence obtained by applying the automorphism to each function in the original sequence is also linearly independent.*)\nLemma map_cfAut_free S : cfAut_closed u S -> free S -> free (map (cfAut u) S).\n\n(*This lemma states that a class function transformed by a field automorphism takes its values in a specific subfield if and only if the original class function also takes its values in that same subfield.*)\nLemma cfAut_on A phi : (phi^u \\in 'CF(G, A)) = (phi \\in 'CF(G, A)).\n\n(*This lemma states that the kernel of a class function, defined as the set of group elements mapped to the value at the identity element, remains unchanged when a field automorphism is applied to the class function.*)\nLemma cfker_aut phi : cfker phi^u = cfker phi.\n\n(*This lemma states that the uniform class function on a subgroup, which has a value of one on the subgroup and zero elsewhere, is a fixed point under any field automorphism.*)\nLemma cfAut_cfuni A : ('1_A)^u = '1_A :> 'CF(G).\n\n(*This lemma states that the order of a class function is invariant under the application of a field automorphism.*)\nLemma cforder_aut phi : #[phi^u]%CF = #[phi]%CF.\n\n(*This lemma states that a field automorphism commutes with the restriction of a class function to a subgroup. Applying an automorphism to a restricted class function is equivalent to restricting the class function that has been transformed by the automorphism.*)\nLemma cfAutRes phi : ('Res[H] phi)^u = 'Res phi^u.\n\n(*This lemma states that applying a field automorphism commutes with the operation of lifting a class function via a group morphism.*)\nLemma cfAutMorph (psi : 'CF(f @* H)) : (cfMorph psi)^u = cfMorph psi^u.\n\n(*This lemma states that applying a field automorphism commutes with the operation of transporting a class function across a group isomorphism.*)\nLemma cfAutIsom (isoGR : isom G R f) phi :\n (cfIsom isoGR phi)^u = cfIsom isoGR phi^u.\n\n(*This lemma states that a field automorphism commutes with the deflation of a class function. Applying the automorphism to a deflated class function is equivalent to deflating the class function that has been transformed by the automorphism.*)\nLemma cfAutQuo phi : (phi / H)^u = (phi^u / H)%CF.\n\n(*This lemma states that a field automorphism commutes with the inflation of a class function. Applying the automorphism to an inflated class function is equivalent to inflating the class function that has been transformed by the automorphism.*)\nLemma cfAutMod (psi : 'CF(G / H)) : (psi %% H)^u = (psi^u %% H)%CF.\n\n(*This lemma states that applying a field automorphism to an induced class function yields the same result as first applying the automorphism to the original class function and then performing the induction.*)\nLemma cfAutInd (psi : 'CF(H)) : ('Ind[G] psi)^u = 'Ind psi^u.\n\nHypothesis KxH : K \\x H = G.\n\n(*This lemma states that for a group that is a direct product of two subgroups, applying a field automorphism to a class function lifted from the left factor is equivalent to first applying the automorphism to the class function on the left factor and then lifting it to the product group.*)\nLemma cfAutDprodl (phi : 'CF(K)) : (cfDprodl KxH phi)^u = cfDprodl KxH phi^u.\n\n(*This lemma states that for a group that is a direct product of two subgroups, applying a field automorphism to a class function lifted from the right factor is equivalent to first applying the automorphism to the class function on the right factor and then lifting it to the product group.*)\nLemma cfAutDprodr (psi : 'CF(H)) : (cfDprodr KxH psi)^u = cfDprodr KxH psi^u.\n\n(*This lemma states that applying a field automorphism to the tensor product of two class functions over a direct product group is identical to taking the tensor product of the two class functions after each has been transformed by the field automorphism.*)\nLemma cfAutDprod (phi : 'CF(K)) (psi : 'CF(H)) :\n (cfDprod KxH phi psi)^u = cfDprod KxH phi^u psi^u.\n\nEnd FieldAutomorphism.\n\nArguments cfAutK u {gT G}.\nArguments cfAutVK u {gT G}.\nArguments cfAut_inj u {gT G} [phi1 phi2] : rename.\n\n(*This definition establishes a theorem asserting that taking the complex conjugate of a restricted class function is equivalent to first taking the complex conjugate of the original class function and then restricting it to the subgroup.*)\nDefinition conj_cfRes := cfAutRes conjC.\n(*This definition establishes a theorem stating that the kernel of a class function remains unchanged when the class function is transformed by complex conjugation.*)\nDefinition cfker_conjC := cfker_aut conjC.\n(*This definition establishes a theorem indicating that taking the complex conjugate of a class function that has been lifted from a quotient group is the same as first taking the complex conjugate of the class function on the quotient group and then lifting it.*)\nDefinition conj_cfQuo := cfAutQuo conjC.\n(*This definition establishes a theorem stating that taking the complex conjugate of a class function that is reduced modulo a prime number is equivalent to first conjugating the class function and then performing the modular reduction.*)\nDefinition conj_cfMod := cfAutMod conjC.\n(*This definition establishes a theorem stating that taking the complex conjugate of an induced class function gives the same result as inducing the complex conjugate of the original class function.*)\nDefinition conj_cfInd := cfAutInd conjC.\n(*This definition establishes a theorem asserting that a class function is the constant function one if and only if its complex conjugate is also the constant function one.*)", - "character.character": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype choice ssrnat seq.\nFrom mathcomp Require Import path div fintype tuple finfun bigop prime order.\nFrom mathcomp Require Import ssralg poly finset gproduct fingroup morphism.\nFrom mathcomp Require Import perm automorphism quotient finalg action zmodp.\nFrom mathcomp Require Import commutator cyclic center pgroup nilpotent sylow.\nFrom mathcomp Require Import abelian matrix mxalgebra mxpoly mxrepresentation.\nFrom mathcomp Require Import vector ssrnum algC classfun archimedean.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nImport Order.TTheory GroupScope GRing.Theory Num.Theory.\nLocal Open Scope ring_scope.\n\nSection AlgC.\n\nVariable (gT : finGroupType).\n\n(*This lemma states that the field of algebraic numbers is a group closure field for any given finite group, meaning it contains all the character values of that group.*)\nLemma groupC : group_closure_field algC gT.\n\nEnd AlgC.\n\nSection Tensor.\n\nVariable (F : fieldType).\n\n(*This fixpoint defines a function that computes the Kronecker product of a row vector and a matrix. It returns a larger matrix formed by placing blocks, where each block is the input matrix scaled by the corresponding entry of the input row vector.*)\nFixpoint trow (n1 : nat) :\n forall (A : 'rV[F]_n1) m2 n2 (B : 'M[F]_(m2,n2)), 'M[F]_(m2,n1 * n2) :=\n if n1 is n'1.+1\n then\n fun (A : 'M[F]_(1,(1 + n'1))) m2 n2 (B : 'M[F]_(m2,n2)) =>\n (row_mx (lsubmx A 0 0 *: B) (trow (rsubmx A) B))\n else (fun _ _ _ _ => 0).\n\n(*This lemma states that the Kronecker product of a zero row vector and any given matrix results in a zero matrix.*)\nLemma trow0 n1 m2 n2 B : @trow n1 0 m2 n2 B = 0.\n\n(*This definition provides a version of the `trow` function with its arguments reordered, taking a matrix as the first argument and a row vector as the second to compute their Kronecker product.*)\nDefinition trowb n1 m2 n2 B A := @trow n1 A m2 n2 B.\n\n(*This lemma states that applying the `trowb` function to a matrix and a row vector is equivalent to applying the original `trow` function to the row vector and the matrix.*)\nLemma trowbE n1 m2 n2 A B : trowb B A = @trow n1 A m2 n2 B.\n\n(*This lemma states that for any fixed matrix, the `trowb` function, which computes a Kronecker product, behaves as a linear map with respect to its row vector input.*)\nLemma trowb_is_linear n1 m2 n2 (B : 'M_(m2,n2)) : linear (@trowb n1 m2 n2 B).\n\nHB.instance Definition _ n1 m2 n2 B :=\n GRing.isSemilinear.Build _ _ _ _ (trowb B)\n (GRing.semilinear_linear (@trowb_is_linear n1 m2 n2 B)).\n\n(*This lemma states that for any fixed row vector, the `trow` function, which computes a Kronecker product, behaves as a linear map with respect to its matrix input.*)\nLemma trow_is_linear n1 m2 n2 (A : 'rV_n1) : linear (@trow n1 A m2 n2).\n\n(*This fixpoint defines the Kronecker product, also known as the tensor product, of two matrices. The resulting matrix is a block matrix where each block is the second input matrix scaled by the corresponding entry from the first input matrix.*)\nFixpoint tprod (m1 : nat) :\n forall n1 (A : 'M[F]_(m1,n1)) m2 n2 (B : 'M[F]_(m2,n2)),\n 'M[F]_(m1 * m2,n1 * n2) :=\n if m1 is m'1.+1\n return forall n1 (A : 'M[F]_(m1,n1)) m2 n2 (B : 'M[F]_(m2,n2)),\n 'M[F]_(m1 * m2,n1 * n2)\n then\n fun n1 (A : 'M[F]_(1 + m'1,n1)) m2 n2 B =>\n (col_mx (trow (usubmx A) B) (tprod (dsubmx A) B))\n else (fun _ _ _ _ _ => 0).\n\n(*This lemma states that extracting the submatrix consisting of all rows but the first from a product of two matrices is equivalent to first extracting the same submatrix from the first matrix factor and then performing the matrix multiplication.*)\nLemma dsumx_mul m1 m2 n p A B :\n dsubmx ((A *m B) : 'M[F]_(m1 + m2, n)) = dsubmx (A : 'M_(m1 + m2, p)) *m B.\n\n(*This lemma states that extracting the first row from a product of two matrices is equivalent to first extracting the first row from the first matrix factor and then performing the matrix multiplication.*)\nLemma usumx_mul m1 m2 n p A B :\n usubmx ((A *m B) : 'M[F]_(m1 + m2, n)) = usubmx (A : 'M_(m1 + m2, p)) *m B.\n\n(*This lemma establishes a distributivity-like property for the Kronecker product of a row vector and a matrix product. It states that the Kronecker product of a row vector with a product of two matrices is equal to the matrix product of the first matrix factor and the Kronecker product of the row vector with the second matrix factor.*)\nLet trow_mul (m1 m2 n2 p2 : nat)\n (A : 'rV_m1) (B1: 'M[F]_(m2,n2)) (B2 :'M[F]_(n2,p2)) :\n trow A (B1 *m B2) = B1 *m trow A B2.\n\n(*This lemma states the mixed-product property for the Kronecker product of matrices. It asserts that the Kronecker product of two matrix products is equivalent to the matrix product of the Kronecker products of the corresponding factors.*)\nLemma tprodE m1 n1 p1 (A1 :'M[F]_(m1,n1)) (A2 :'M[F]_(n1,p1))\n m2 n2 p2 (B1 :'M[F]_(m2,n2)) (B2 :'M[F]_(n2,p2)) :\n tprod (A1 *m A2) (B1 *m B2) = (tprod A1 B1) *m (tprod A2 B2).\n\n(*This lemma provides an alternative, column-wise recursive formula for the Kronecker product of two matrices, relating it to the `trow` operation, transposes, and column submatrices.*)\nLet tprod_tr m1 n1 (A :'M[F]_(m1, 1 + n1)) m2 n2 (B :'M[F]_(m2, n2)) :\n tprod A B = row_mx (trow (lsubmx A)^T B^T)^T (tprod (rsubmx A) B).\n\n(*This lemma states that the Kronecker product of two identity matrices is itself an identity matrix.*)\nLemma tprod1 m n : tprod (1%:M : 'M[F]_(m,m)) (1%:M : 'M[F]_(n,n)) = 1%:M.\n\n(*This lemma states that the trace of the Kronecker product of two square matrices is equal to the product of their individual traces.*)\nLemma mxtrace_prod m n (A :'M[F]_(m)) (B :'M[F]_(n)) :\n \\tr (tprod A B) = \\tr A * \\tr B.\n\nEnd Tensor.\n\nSection StandardRepresentation.\n\nVariables (R : fieldType) (gT : finGroupType) (G : {group gT}).\n(*This notation defines `reprG` as an abbreviation for the type of matrix representations of a given group over a specified field.*)\nLocal Notation reprG := (mx_representation R G).\n\n(*This record defines a structure for a group representation, which encapsulates the degree of the representation and the underlying group homomorphism mapping group elements to matrices.*)\nRecord representation :=\n Representation {rdegree; mx_repr_of_repr :> reprG rdegree}.\n\n(*This lemma establishes that the function mapping every element of a group to the zero-dimensional identity matrix is a valid group representation.*)\nLemma mx_repr0 : mx_repr G (fun _ : gT => 1%:M : 'M[R]_0).\n\n(*This definition provides the canonical zero-dimensional group representation, also known as the trivial representation of degree zero.*)\nDefinition grepr0 := Representation (MxRepresentation mx_repr0).\n\n(*This lemma states that the direct sum of two group representations is also a valid group representation. The direct sum is constructed by creating a block diagonal matrix from the matrices of the two original representations for each group element.*)\nLemma add_mx_repr (rG1 rG2 : representation) :\n mx_repr G (fun g => block_mx (rG1 g) 0 0 (rG2 g)).\n\n(*This definition constructs the direct sum of two group representations, yielding a new representation whose matrices are the block-diagonal combinations of the input representations' matrices.*)\nDefinition dadd_grepr rG1 rG2 :=\n Representation (MxRepresentation (add_mx_repr rG1 rG2)).\n\nSection DsumRepr.\n\nVariables (n : nat) (rG : reprG n).\n\n(*This lemma states that if two submodules of a representation space are isomorphic to two given representations, and their sum is direct, then the representation afforded by this direct sum of submodules is isomorphic to the direct sum of the two given representations.*)\nLemma mx_rsim_dadd (U V W : 'M_n) (rU rV : representation)\n (modU : mxmodule rG U) (modV : mxmodule rG V) (modW : mxmodule rG W) :\n (U + V :=: W)%MS -> mxdirect (U + V) ->\n mx_rsim (submod_repr modU) rU -> mx_rsim (submod_repr modV) rV ->\n mx_rsim (submod_repr modW) (dadd_grepr rU rV).\n\n(*This lemma generalizes the property of direct sums of representations to a finite family of submodules. It states that if a submodule is a direct sum of a collection of submodules, and each submodule in the collection is isomorphic to a corresponding representation, then the representation afforded by the total direct sum is isomorphic to the big direct sum of the corresponding representations.*)\nLemma mx_rsim_dsum (I : finType) (P : pred I) U rU (W : 'M_n)\n (modU : forall i, mxmodule rG (U i)) (modW : mxmodule rG W) :\n let S := (\\sum_(i | P i) U i)%MS in (S :=: W)%MS -> mxdirect S ->\n (forall i, mx_rsim (submod_repr (modU i)) (rU i : representation)) ->\n mx_rsim (submod_repr modW) (\\big[dadd_grepr/grepr0]_(i | P i) rU i).\n\n(*This definition specifies the `n`-th multiple of a group representation, which is constructed by taking the direct sum of the representation with itself `n` times.*)\nDefinition muln_grepr rW k := \\big[dadd_grepr/grepr0]_(i < k) rW.\n\n(*This lemma states a property about the representation afforded by an isotypic component of a module's socle. If the simple representation associated with this component is isomorphic to a given representation, then the representation afforded by the submodule corresponding to this entire isotypic component is isomorphic to the direct sum of the given representation with itself a number of times equal to the component's multiplicity.*)\nLemma mx_rsim_socle (sG : socleType rG) (W : sG) (rW : representation) :\n let modW : mxmodule rG W := component_mx_module rG (socle_base W) in\n mx_rsim (socle_repr W) rW ->\n mx_rsim (submod_repr modW) (muln_grepr rW (socle_mult W)).\n\nEnd DsumRepr.\n\nSection ProdRepr.\n\nVariables (n1 n2 : nat) (rG1 : reprG n1) (rG2 : reprG n2).\n\n(*This lemma establishes that the tensor product of two group representations, defined pointwise as the Kronecker product of their matrices, is itself a valid group representation.*)\nLemma prod_mx_repr : mx_repr G (fun g => tprod (rG1 g) (rG2 g)).\n\n(*This definition constructs the tensor product of two group representations, resulting in a new representation whose matrices are the Kronecker products of the matrices from the input representations.*)\nDefinition prod_repr := MxRepresentation prod_mx_repr.\n\nEnd ProdRepr.\n\n(*This lemma provides a simplified expression for the tensor product of a one-dimensional representation and another representation. It states that for any group element, the resulting matrix is equivalent to the matrix of the second representation scaled by the scalar value of the one-dimensional representation for that same element.*)\nLemma prod_repr_lin n2 (rG1 : reprG 1) (rG2 : reprG n2) :\n {in G, forall x, let cast_n2 := esym (mul1n n2) in\n prod_repr rG1 rG2 x = castmx (cast_n2, cast_n2) (rG1 x 0 0 *: rG2 x)}.\n\nEnd StandardRepresentation.\n\nArguments grepr0 {R gT G}.\nPrenex Implicits dadd_grepr.\n\nSection Char.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This fact establishes that the character of a finite group representation over the field of algebraic numbers is a class function. The character is defined as the function mapping each group element to the trace of its corresponding matrix in the representation.*)\nFact cfRepr_subproof n (rG : mx_representation algC G n) :\n is_class_fun <> [ffun x => \\tr (rG x) *+ (x \\in G)].\n\n(*This definition constructs the character of a given group representation as a formal class function. The character maps each group element to the trace of its corresponding matrix representation, and is zero for any element not in the group.*)\nDefinition cfRepr n rG := Cfun 0 (@cfRepr_subproof n rG).\n\n(*This lemma states that the class function associated with a given matrix representation, when evaluated at the identity element of the group, yields the dimension of the representation as a ring element.*)\nLemma cfRepr1 n rG : @cfRepr n rG 1%g = n%:R.\n\n(*This lemma states that if two matrix representations are similar, then their corresponding class functions are equal.*)\nLemma cfRepr_sim n1 n2 rG1 rG2 :\n mx_rsim rG1 rG2 -> @cfRepr n1 rG1 = @cfRepr n2 rG2.\n\n(*This lemma states that the class function corresponding to the zero representation is the zero class function.*)\nLemma cfRepr0 : cfRepr grepr0 = 0.\n\n(*This lemma states that the class function of the direct sum of two matrix representations is equal to the sum of the class functions of the individual representations.*)\nLemma cfRepr_dadd rG1 rG2 :\n cfRepr (dadd_grepr rG1 rG2) = cfRepr rG1 + cfRepr rG2.\n\n(*This lemma states that the class function of a direct sum of a family of matrix representations over a given range is equal to the sum of the class functions of the individual representations in that family.*)\nLemma cfRepr_dsum I r (P : pred I) rG :\n cfRepr (\\big[dadd_grepr/grepr0]_(i <- r | P i) rG i)\n = \\sum_(i <- r | P i) cfRepr (rG i).\n\n(*This lemma states that the class function of a representation formed by taking the direct sum of a given representation with itself a specified number of times is equal to the original class function multiplied by that number.*)\nLemma cfRepr_muln rG k : cfRepr (muln_grepr rG k) = cfRepr rG *+ k.\n\nSection StandardRepr.\n\nVariables (n : nat) (rG : mx_representation algC G n).\n(*This definition introduces a type representing the socle of a given matrix representation, which is the sum of its irreducible sub-representations.*)\nLet sG := DecSocleType rG.\n(*This definition establishes a type for the irreducible components of a representation, built from the socle type structure.*)\nLet iG : irrType algC G := DecSocleType _.\n\n(*This definition computes the standard irreducible component associated with a given element of the socle type by extracting its underlying representation.*)\nDefinition standard_irr (W : sG) := irr_comp iG (socle_repr W).\n\n(*This definition selects a representative element from the socle type that corresponds to a given standard irreducible component.*)\nDefinition standard_socle i := pick [pred W | standard_irr W == i].\n(*A local notation for the function that selects a representative element from the socle type corresponding to a given standard irreducible component.*)\nLocal Notation soc := standard_socle.\n\n(*This definition computes the multiplicity coefficient of a standard irreducible component by retrieving the multiplicity of its corresponding representative in the socle.*)\nDefinition standard_irr_coef i := oapp (fun W => socle_mult W) 0 (soc i).\n\n(*This definition constructs the standard group representation as a direct sum of its irreducible components, where each component is repeated according to its multiplicity.*)\nDefinition standard_grepr :=\n \\big[dadd_grepr/grepr0]_i\n muln_grepr (Representation (socle_repr i)) (standard_irr_coef i).\n\n(*This lemma states that any given matrix representation is similar to its reconstructed standard representation.*)\nLemma mx_rsim_standard : mx_rsim rG standard_grepr.\n\nEnd StandardRepr.\n\n(*This definition constructs the regular class function for a given set of group elements, defined as the characteristic function of the identity element scaled by the size of the set.*)\nDefinition cfReg (B : {set gT}) : 'CF(B) := #|B|%:R *: '1_[1].\n\n(*This lemma provides an explicit formula for the regular class function, stating that its value at a group element is the size of the group if the element is the identity, and zero otherwise.*)\nLemma cfRegE x : @cfReg G x = #|G|%:R *+ (x == 1%g).\n\n(*This lemma states that the class function associated with the regular representation of a group is equal to the group's regular class function.*)\nLemma cfReprReg : cfRepr (regular_repr algC G) = cfReg G.\n\n(*This definition specifies a function that evaluates a class function on an element of the group algebra by computing the dot product of the element's representation with the vector of class function values over the group.*)\nDefinition xcfun (chi : 'CF(G)) A :=\n (gring_row A *m (\\col_(i < #|G|) chi (enum_val i))) 0 0.\n\n(*This lemma states that for any given class function, the corresponding extended character function is a module morphism over the integers, meaning it preserves addition and zero.*)\nLemma xcfun_is_zmod_morphism phi : zmod_morphism (xcfun phi).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `xcfun_is_zmod_morphism` instead\")]\n(*This definition is a deprecated alias for the lemma stating that the extended character function is a module morphism over the integers.*)\nDefinition xcfun_is_additive := xcfun_is_zmod_morphism.\nHB.instance Definition _ phi :=\n GRing.isZmodMorphism.Build 'M_(gcard G) _ (xcfun phi) (xcfun_is_zmod_morphism phi).\n\n(*This lemma states that applying the extended character function to a group algebra element scaled by an integer is equivalent to scaling the result of the function by the same integer.*)\nLemma xcfunZr a phi A : xcfun phi (a *: A) = a * xcfun phi A.\n\n(*This definition provides a variant of the extended character function with its arguments swapped, which is useful for fixing the group algebra element and varying the class function.*)\nDefinition xcfun_r A phi := xcfun phi A.\nArguments xcfun_r A phi /.\n\n(*This lemma confirms that the reversed-argument extended character function is equivalent to the original extended character function with its arguments swapped.*)\nLemma xcfun_rE A chi : xcfun_r A chi = xcfun chi A. \n\n(*This fact asserts that for any given element of the group algebra, the reversed-argument extended character function is a module morphism over the integers, meaning it preserves addition and zero of class functions.*)\nFact xcfun_r_is_zmod_morphism A : zmod_morphism (xcfun_r A).\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `xcfun_r_is_zmod_morphism` instead\")]\n(*This definition is a deprecated alias for the fact stating that the reversed-argument extended character function is a module morphism over the integers.*)\nDefinition xcfun_r_is_additive := xcfun_r_is_zmod_morphism.\n(*This lemma states that applying the extended character function with a class function scaled by an integer is equivalent to scaling the result of the function by that same integer.*)\nLemma xcfunZl a phi A : xcfun (a *: phi) A = a * xcfun phi A.\n\n(*This lemma establishes a fundamental connection between the extended character function and matrix representations, stating that applying the function with a character of a representation to a group algebra element yields the trace of the matrix corresponding to that element in the given representation.*)\nLemma xcfun_repr n rG A : xcfun (@cfRepr n rG) A = \\tr (gring_op rG A).\n\nEnd Char.\nArguments xcfun_r {_ _} A phi /.\n(*A notation for applying an extended character function to an element of the group algebra.*)\nNotation \"phi .[ A ]\" := (xcfun phi A) : cfun_scope.\n\n(*This definition computes a value equal to the number of conjugacy classes of a given group minus one.*)\nDefinition pred_Nirr gT B := #|@classes gT B|.-1.\nArguments pred_Nirr {gT} B%_g.\nNotation Nirr G := (pred_Nirr G).+1.\nNotation Iirr G := 'I_(Nirr G).\n\nSection IrrClassDef.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This definition establishes a type representing the indices for the simple modules in the decomposition of the regular representation of a finite group. This index type corresponds to the set of irreducible characters of the group.*)\nLet sG := DecSocleType (regular_repr algC G).\n\n(*This lemma states that the number of irreducible characters of a finite group is equal to the number of its conjugacy classes.*)\nLemma NirrE : Nirr G = #|classes G|.\n\n(*This fact asserts that the number of irreducible characters of a group is equal to the cardinality of the socle type derived from the group's regular representation.*)\nFact Iirr_cast : Nirr G = #|sG|.\n\n(*This definition computes the index of the principal character within the canonical enumeration of irreducible characters, serving as an offset to align different enumerations.*)\nLet offset := cast_ord (esym Iirr_cast) (enum_rank [1 sG]%irr).\n\n(*This definition provides a mapping from the type of irreducible characters to the socle type of the group's regular representation. It translates an index of an irreducible character into the corresponding element in the enumerated socle.*)\nDefinition socle_of_Iirr (i : Iirr G) : sG :=\n enum_val (cast_ord Iirr_cast (i + offset)).\n(*This definition provides a mapping from the socle type of the group's regular representation to the type of irreducible characters. It converts an element of the socle into its corresponding index in the enumeration of irreducible characters.*)\nDefinition irr_of_socle (Wi : sG) : Iirr G :=\n cast_ord (esym Iirr_cast) (enum_rank Wi) - offset.\n(*This notation provides a local shorthand for the 'socle_of_Iirr' function, which maps an irreducible character index to its corresponding element in the socle type.*)\nLocal Notation W := socle_of_Iirr.\n\n(*This lemma states that the mapping from irreducible character indices to socle elements sends the index zero to the principal character.*)\nLemma socle_Iirr0 : W 0 = [1 sG]%irr.\n\n(*This lemma states that composing the function from a socle element to its irreducible character index with the function from that index back to the socle element results in the original socle element.*)\nLemma socle_of_IirrK : cancel W irr_of_socle.\n\n(*This lemma states that composing the function from an irreducible character index to its socle element with the function from that socle element back to the index results in the original index.*)\nLemma irr_of_socleK : cancel irr_of_socle W.\n\nHint Resolve socle_of_IirrK irr_of_socleK : core.\n\n(*This lemma states that the function 'irr_of_socle', which maps from the socle type to irreducible character indices, is a bijection when its codomain is restricted to any subset of irreducible character indices.*)\nLemma irr_of_socle_bij (A : {pred (Iirr G)}) : {on A, bijective irr_of_socle}.\n\n(*This lemma states that the function 'socle_of_Iirr', which maps from irreducible character indices to the socle type, is a bijection when its codomain is restricted to any subset of the socle type.*)\nLemma socle_of_Iirr_bij (A : {pred sG}) : {on A, bijective W}.\n\nEnd IrrClassDef.\n\nPrenex Implicits socle_of_IirrK irr_of_socleK.\nArguments socle_of_Iirr {gT G%_G} i%_R.\n\n(*A notation for the irreducible representation of a finite group corresponding to a given index. A representation is a function that maps each element of the group to an invertible matrix.*)\nNotation \"''Chi_' i\" := (irr_repr (socle_of_Iirr i))\n (at level 8, i at level 2, format \"''Chi_' i\").\n\n(*This definition constructs a tuple that contains all the irreducible characters of a given group, where each element of the tuple is the class function corresponding to an irreducible character.*)\nHB.lock Definition irr gT B : (Nirr B).-tuple 'CF(B) :=\n let irr_of i := 'Res[B, <>] (@cfRepr gT _ _ 'Chi_(inord i)) in\n [tuple of mkseq irr_of (Nirr B)].\nArguments irr {gT} B%_g.\n\n(*A notation for the irreducible character of a finite group corresponding to a given index. A character is a function that maps each element of the group to a complex number and is constant on conjugacy classes.*)\nNotation \"''chi_' i\" := (tnth (irr _) i%R)\n (at level 8, i at level 2, format \"''chi_' i\") : ring_scope.\n(*A notation for the irreducible character of an explicitly specified finite group, corresponding to a given index. This is a parsing-only notation, meaning it can be used for input but the system will display it using the format where the group is implicit.*)\nNotation \"''chi[' G ]_ i\" := (tnth (irr G) i%R)\n (at level 8, i at level 2, only parsing) : ring_scope.\n\nSection IrrClass.\n\nVariable (gT : finGroupType) (G : {group gT}).\nImplicit Types (i : Iirr G) (B : {set gT}).\nOpen Scope group_ring_scope.\n\n(*This lemma states that if two indices of irreducible characters are equal, then the corresponding character functions are also equal.*)\nLemma congr_irr i1 i2 : i1 = i2 -> 'chi_i1 = 'chi_i2. \n\n(*This lemma states that for any non-trivial group, the index of the second irreducible character in the standard enumeration is not zero.*)\nLemma Iirr1_neq0 : G :!=: 1%g -> inord 1 != 0 :> Iirr G.\n\n(*This lemma asserts that any non-trivial group possesses at least one non-principal irreducible character.*)\nLemma has_nonprincipal_irr : G :!=: 1%g -> {i : Iirr G | i != 0}.\n\n(*This lemma states that the canonical class function representation of the i-th irreducible character, denoted 'Chi_i', is equal to the i-th character, denoted 'chi_i', taken from the standard tuple of irreducible characters.*)\nLemma irrRepr i : cfRepr 'Chi_i = 'chi_i.\n\n(*This lemma states that the irreducible character at index zero is the principal character, which is the class function that evaluates to one for all group elements.*)\nLemma irr0 : 'chi[G]_0 = 1.\n\n(*This lemma asserts that the principal character is always an element of the set of irreducible characters for any group.*)\nLemma cfun1_irr : 1 \\in irr G.\n\n(*This lemma states that for any valid index, the corresponding irreducible character is a member of the collection of all irreducible characters of the group.*)\nLemma mem_irr i : 'chi_i \\in irr G.\n\n(*This lemma establishes that a class function is a member of the set of irreducible characters if and only if there exists an index for which that class function is the corresponding irreducible character.*)\nLemma irrP xi : reflect (exists i, xi = 'chi_i) (xi \\in irr G).\n\n(*This definition establishes a type representing the socle of the regular representation of a group over the complex numbers, which corresponds to the set of irreducible characters.*)\nLet sG := DecSocleType (regular_repr algC G).\n(*This definition establishes a type for the p-Brauer characters of a given group, with values in the field of algebraic numbers.*)\nLet C'G := algC'G_pchar G.\n(*This definition creates a canonical group structure for the underlying type of the group G.*)\nLet closG := @groupC _ G.\nLocal Notation W i := (@socle_of_Iirr _ G i).\n(*A local notation representing the degree of the i-th irreducible representation of the group.*)\nLocal Notation \"''n_' i\" := 'n_(W i).\n(*A local notation for the minimal two-sided ideal in the group algebra corresponding to the i-th irreducible representation of the group.*)\nLocal Notation \"''R_' i\" := 'R_(W i).\n(*A local notation for the primitive central idempotent of the group algebra associated with the i-th irreducible representation of the group.*)\nLocal Notation \"''e_' i\" := 'e_(W i).\n\n(*This lemma states that the value of the i-th irreducible character at the identity element of the group is equal to the degree of the corresponding representation, converted to a ring element.*)\nLemma irr1_degree i : 'chi_i 1%g = ('n_i)%:R.\n\n(*This lemma states that the value of the i-th irreducible character at the identity element of the group is a natural number.*)\nLemma Cnat_irr1 i : 'chi_i 1%g \\in Num.nat.\n\n(*This lemma states that the value of the i-th irreducible character at the identity element of the group is strictly greater than zero.*)\nLemma irr1_gt0 i : 0 < 'chi_i 1%g.\n\n(*This lemma states that the value of the i-th irreducible character at the identity element of the group is not equal to zero.*)\nLemma irr1_neq0 i : 'chi_i 1%g != 0.\n\n(*This lemma states that the i-th irreducible character is not the zero class function.*)\nLemma irr_neq0 i : 'chi_i != 0.\n\n(*This remark defines a key used to lock the definition of the function that maps a class function to its index among irreducible characters, preventing uncontrolled unfolding.*)\nLocal Remark cfIirr_key : unit. \n(*This definition provides a function that takes a class function belonging to the set of irreducible characters of a group and returns its corresponding index as an ordinal number.*)\nDefinition cfIirr : forall B, 'CF(B) -> Iirr B :=\n locked_with cfIirr_key (fun B chi => inord (index chi (irr B))).\n\n(*This lemma states that for any given irreducible character of a group, applying the function that finds its index and then retrieving the character at that index yields the original character.*)\nLemma cfIirrE chi : chi \\in irr G -> 'chi_(cfIirr chi) = chi.\n\n(*This lemma states that for a family of functions mapping from an index set to the space of class functions, if a function at a given index is an irreducible character, then applying the index-finding function and re-indexing the characters recovers the original function.*)\nLemma cfIirrPE J (f : J -> 'CF(G)) (P : pred J) :\n (forall j, P j -> f j \\in irr G) ->\n forall j, P j -> 'chi_(cfIirr (f j)) = f j.\n\n(*This corollary states that the sum of the squares of the degrees of all irreducible characters of a group is equal to the order of the group.*)\nCorollary irr_sum_square : \\sum_i ('chi[G]_i 1%g) ^+ 2 = #|G|%:R.\n\n(*This lemma states that the regular character of a group is equal to the sum, over all irreducible characters, of each irreducible character multiplied by its own degree.*)\nLemma cfReg_sum : cfReg G = \\sum_i 'chi_i 1%g *: 'chi_i.\n\n(*This definition assigns a name to the regular representation of the group G over the field of algebraic numbers.*)\nLet aG := regular_repr algC G.\n(*This definition assigns a name to the group ring of the group G over the field of algebraic numbers.*)\nLet R_G := group_ring algC G.\n\n(*This lemma states that if two indices i and j are different, then the action of any element from the j-th minimal two-sided ideal of the group algebra on the i-th irreducible character results in zero.*)\nLemma xcfun_annihilate i j A : i != j -> (A \\in 'R_j)%MS -> ('chi_i).[A]%CF = 0.\n\n(*This lemma states that for any class function, its extension to an action on the group algebra, when applied to a group element from the regular representation, is equivalent to evaluating the class function at that group element.*)\nLemma xcfunG phi x : x \\in G -> phi.[aG x]%CF = phi x.\n\n(*This lemma states that for any element in the group ring, the action of the i-th irreducible character on this element is the same as its action on the product of the i-th primitive central idempotent and this element.*)\nLemma xcfun_mul_id i A :\n (A \\in R_G)%MS -> ('chi_i).['e_i *m A]%CF = ('chi_i).[A]%CF.\n\n(*This lemma states that the action of the i-th irreducible character on the j-th primitive central idempotent is equal to the degree of the i-th character if the indices i and j are the same, and zero otherwise.*)\nLemma xcfun_id i j : ('chi_i).['e_j]%CF = 'chi_i 1%g *+ (i == j).\n\n(*This lemma states that the collection of irreducible characters of a group contains no duplicate elements.*)\nLemma irr_free : free (irr G).\n\n(*This lemma states that the function which maps an ordinal index to the corresponding irreducible character of a group is injective.*)\nLemma irr_inj : injective (tnth (irr G)).\n\n(*This lemma states that the function retrieving an irreducible character by its index is a left inverse to the function that computes the index of an irreducible character.*)\nLemma irrK : cancel (tnth (irr G)) (@cfIirr G).\n\n(*This lemma states that the i-th irreducible character is the trivial character, which maps all group elements to one, if and only if its index is zero.*)\nLemma irr_eq1 i : ('chi_i == 1) = (i == 0).\n\n(*This lemma states that the order of the i-th irreducible character as a class function is one if and only if its index is zero.*)\nLemma cforder_irr_eq1 i : (#['chi_i]%CF == 1) = (i == 0).\n\n(*This lemma states that the set of irreducible characters of a group forms a basis for the vector space of class functions over the algebraic numbers.*)\nLemma irr_basis : basis_of 'CF(G)%VS (irr G).\n\n(*This lemma states that summing a sequence of coefficients multiplied by the i-th irreducible characters gives the same result whether the i-th character is denoted by the specific character notation or by indexing into the formal set of irreducible characters.*)\nLemma eq_sum_nth_irr a : \\sum_i a i *: 'chi[G]_i = \\sum_i a i *: (irr G)`_i.\n\n(*This theorem asserts that any class function can be uniquely expressed as a linear combination of the irreducible characters of the group, where the coefficients are complex numbers.*)\nTheorem cfun_irr_sum phi : {a | phi = \\sum_i a i *: 'chi[G]_i}.\n\n(*This lemma states that the character of a standard group representation is equal to the linear combination of the irreducible characters, where each coefficient is the corresponding standard irreducible coefficient of the original matrix representation.*)\nLemma cfRepr_standard n (rG : mx_representation algC G n) :\n cfRepr (standard_grepr rG)\n = \\sum_i (standard_irr_coef rG (W i))%:R *: 'chi_i.\n\n(*This lemma states that if two matrix representations of a group have equal characters, then the representations are similar.*)\nLemma cfRepr_inj n1 n2 rG1 rG2 :\n @cfRepr _ G n1 rG1 = @cfRepr _ G n2 rG2 -> mx_rsim rG1 rG2.\n\n(*This lemma provides a boolean reflection of the property that two matrix representations of a group are similar if and only if their corresponding characters are equal.*)\nLemma cfRepr_rsimP n1 n2 rG1 rG2 :\n reflect (mx_rsim rG1 rG2) (@cfRepr _ G n1 rG1 == @cfRepr _ G n2 rG2).\n\n(*This lemma provides a boolean reflection of the property that a class function is an irreducible character if and only if there exists an irreducible matrix representation of the group whose character is that class function.*)\nLemma irr_reprP xi :\n reflect (exists2 rG : representation _ G, mx_irreducible rG & xi = cfRepr rG)\n (xi \\in irr G).\n\n(*This lemma provides an explicit formula for a primitive central idempotent of the group algebra, expressing it as a scaled sum over group elements, where the coefficients involve the values of the corresponding irreducible character.*)\nLemma Wedderburn_id_expansion i :\n 'e_i = #|G|%:R^-1 *: \\sum_(x in G) 'chi_i 1%g * 'chi_i x^-1%g *: aG x.\n\nEnd IrrClass.\n\nArguments cfReg {gT} B%_g.\nPrenex Implicits cfIirr irrK.\nArguments irrP {gT G xi}.\nArguments irr_reprP {gT G xi}.\nArguments irr_inj {gT G} [x1 x2].\n\nSection IsChar.\n\nVariable gT : finGroupType.\n\n(*This definition establishes a predicate that holds for a class function if and only if all of its coordinates in the basis of irreducible characters are natural numbers.*)\nDefinition character_pred {G : {set gT}} :=\n fun phi : 'CF(G) => [forall i, coord (irr G) i phi \\in Num.nat].\nArguments character_pred _ _ /.\n(*This definition introduces the type of characters of a group, defined as those class functions whose coordinates in the basis of irreducible characters are natural numbers.*)\nDefinition character {G : {set gT}} := [qualify a phi | @character_pred G phi].\n\nVariable G : {group gT}.\nImplicit Types (phi chi xi : 'CF(G)) (i : Iirr G).\n\n(*This lemma states that every irreducible character of a group is a character.*)\nLemma irr_char i : 'chi_i \\is a character.\n\n(*This lemma states that the constant class function equal to one, which corresponds to the character of the trivial representation, is a character.*)\nLemma cfun1_char : (1 : 'CF(G)) \\is a character.\n\n(*This lemma states that the zero class function is a character.*)\nLemma cfun0_char : (0 : 'CF(G)) \\is a character.\n\n(*This fact states that the set of characters is closed under addition; that is, the sum of two characters is also a character.*)\nFact add_char : addr_closed (@character G).\n\nHB.instance Definition _ := GRing.isAddClosed.Build (classfun G) character_pred\n add_char.\n\n(*This lemma provides a boolean reflection of the property that a class function is a character if and only if it can be expressed as a linear combination of irreducible characters with non-negative integer coefficients.*)\nLemma char_sum_irrP {phi} :\n reflect (exists n, phi = \\sum_i (n i)%:R *: 'chi_i) (phi \\is a character).\n\n(*This lemma states that any character can be written as a sum of irreducible characters, where each irreducible character may appear multiple times.*)\nLemma char_sum_irr chi :\n chi \\is a character -> {r | chi = \\sum_(i <- r) 'chi_i}.\n\n(*This lemma states that the value of any character at the identity element of the group is a natural number.*)\nLemma Cnat_char1 chi : chi \\is a character -> chi 1%g \\in Num.nat.\n\n(*This lemma states that the value of any character at the identity element of the group is greater than or equal to zero.*)\nLemma char1_ge0 chi : chi \\is a character -> 0 <= chi 1%g.\n\n(*This lemma states that for a given character, its value at the identity element of the group is zero if and only if the character is the zero class function.*)\nLemma char1_eq0 chi : chi \\is a character -> (chi 1%g == 0) = (chi == 0).\n\n(*This lemma states that for a given character, its value at the identity element of the group is strictly positive if and only if the character is not the zero class function.*)\nLemma char1_gt0 chi : chi \\is a character -> (0 < chi 1%g) = (chi != 0).\n\n(*This lemma provides a boolean reflection of the property that a class function is a character if and only if it is the character of some representation of the group.*)\nLemma char_reprP phi :\n reflect (exists rG : representation algC G, phi = cfRepr rG)\n (phi \\is a character).\n\n(*This notation defines a shorthand for the type of matrix representations of a given group over the field of complex numbers.*)\nLocal Notation reprG := (mx_representation algC G).\n\n(*This lemma states that the character associated with any matrix representation of a group is a character.*)\nLemma cfRepr_char n (rG : reprG n) : cfRepr rG \\is a character.\n\n(*This lemma states that the character of the regular representation of a group is a character.*)\nLemma cfReg_char : cfReg G \\is a character.\n\n(*This lemma states that the pointwise product of the characters of two matrix representations is equal to the character of the tensor product of those representations.*)\nLemma cfRepr_prod n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n cfRepr rG1 * cfRepr rG2 = cfRepr (prod_repr rG1 rG2).\n\n(*This lemma states that the set of characters is closed under pointwise multiplication; that is, the product of two characters is also a character.*)\nLemma mul_char : mulr_closed (@character G).\n\n(*This lemma states that the character of a matrix representation transformed by a field automorphism is equal to the result of applying that same automorphism to the original character.*)\nLemma cfRepr_map u n (rG : mx_representation algC G n) :\n cfRepr (map_repr u rG) = cfAut u (cfRepr rG).\n\n(*This lemma states that applying a field automorphism to the values of a class function preserves the property of being a character.*)\nLemma cfAut_char u chi : (cfAut u chi \\is a character) = (chi \\is a character).\n\n(*This lemma states that a class function is a character if and only if its complex conjugate class function is also a character.*)\nLemma cfConjC_char chi : (chi^*%CF \\is a character) = (chi \\is a character).\n\n(*This lemma states that for any character, its value at the group's identity element remains unchanged after applying a field automorphism to its values.*)\nLemma cfAut_char1 u (chi : 'CF(G)) :\n chi \\is a character -> cfAut u chi 1%g = chi 1%g.\n\n(*This lemma states that the value of any irreducible character at the group's identity element remains unchanged after applying a field automorphism to its values.*)\nLemma cfAut_irr1 u i : (cfAut u 'chi[G]_i) 1%g = 'chi_i 1%g.\n\n(*This lemma states that for any character, its value at the group's identity element is equal to its complex conjugate, which implies the value is a real number.*)\nLemma cfConjC_char1 (chi : 'CF(G)) :\n chi \\is a character -> chi^*%CF 1%g = chi 1%g.\n\n(*This lemma states that the value of the complex conjugate of an irreducible character at the identity element is equal to the value of the original irreducible character at the identity element.*)\nLemma cfConjC_irr1 u i : ('chi[G]_i)^*%CF 1%g = 'chi_i 1%g.\n\nEnd AutChar.\n\nSection Linear.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This definition specifies a predicate that is true for a given class function if and only if that function is a character and its value at the identity element is one.*)\nDefinition linear_char_pred {B : {set gT}} :=\n fun phi : 'CF(B) => (phi \\is a character) && (phi 1%g == 1).\nArguments linear_char_pred _ _ /.\n(*This definition introduces the type of linear characters, which are class functions that satisfy the linear character predicate, meaning they are characters whose value at the identity element is one.*)\nDefinition linear_char {B : {set gT}} :=\n [qualify a phi | @linear_char_pred B phi].\n\nSection OneChar.\n\nVariable xi : 'CF(G).\nHypothesis CFxi : xi \\is a linear_char.\n\n(*This lemma states that a linear character evaluated at the identity element of the group yields the value one.*)\nLemma lin_char1: xi 1%g = 1.\n\n(*This lemma states that any linear character is also a character.*)\nLemma lin_charW : xi \\is a character.\n\n(*This lemma states that the principal character, which is the class function that is constantly one, is a linear character.*)\nLemma cfun1_lin_char : (1 : 'CF(G)) \\is a linear_char.\n\n(*This lemma states that a linear character is a group homomorphism, meaning it maps the product of two group elements to the product of their images under the character.*)\nLemma lin_charM : {in G &, {morph xi : x y / (x * y)%g >-> x * y}}.\n\n(*This lemma states that a linear character of a product of group elements is equal to the product of the character values of each of those group elements.*)\nLemma lin_char_prod I r (P : pred I) (x : I -> gT) :\n (forall i, P i -> x i \\in G) ->\n xi (\\prod_(i <- r | P i) x i)%g = \\prod_(i <- r | P i) xi (x i).\n\n(*This lemma establishes that for any group element, the product of its image under a linear character and the image of its inverse is one.*)\nLet xiMV x : x \\in G -> xi x * xi (x^-1)%g = 1.\n\n(*This lemma states that the value of a linear character at any group element is never zero.*)\nLemma lin_char_neq0 x : x \\in G -> xi x != 0.\n\n(*This lemma states that the value of a linear character at the inverse of a group element is equal to the multiplicative inverse of the character's value at that element.*)\nLemma lin_charV x : x \\in G -> xi x^-1%g = (xi x)^-1.\n\n(*This lemma states that for any group element and any integer, the value of a linear character at the element raised to the integer power is equal to the character's value at that element, raised to the same integer power.*)\nLemma lin_charX x n : x \\in G -> xi (x ^+ n)%g = xi x ^+ n.\n\n(*This lemma states that for any group element, the value of a linear character at that element, when raised to the power of the order of that element, is equal to one.*)\nLemma lin_char_unity_root x : x \\in G -> xi x ^+ #[x] = 1.\n\n(*This lemma states that the complex norm of the value of a linear character at any group element is equal to one.*)\nLemma normC_lin_char x : x \\in G -> `|xi x| = 1.\n\n(*This lemma states that the value of a linear character at the inverse of a group element is equal to the complex conjugate of its value at that element.*)\nLemma lin_charV_conj x : x \\in G -> xi x^-1%g = (xi x)^*.\n\n(*This lemma states that any linear character is an irreducible character.*)\nLemma lin_char_irr : xi \\in irr G.\n\n(*This lemma states that the product of a linear character with its complex conjugate class function is the principal character, which is the class function that is constantly one.*)\nLemma mul_conjC_lin_char : xi * xi^*%CF = 1.\n\n(*This lemma states that any linear character is a unit in the ring of class functions.*)\nLemma lin_char_unitr : xi \\in GRing.unit.\n\n(*This lemma states that the multiplicative inverse of a linear character in the ring of class functions is its complex conjugate.*)\nLemma invr_lin_char : xi^-1 = xi^*%CF.\n\n(*This lemma states that if a linear character is faithful, meaning its kernel is trivial, then the character function is injective.*)\nLemma fful_lin_char_inj : cfaithful xi -> {in G &, injective xi}.\n\nEnd OneChar.\n\n(*This lemma states that composing a class function with a group automorphism preserves the property of being a linear character; that is, the composition is a linear character if and only if the original class function is a linear character.*)\nLemma cfAut_lin_char u (xi : 'CF(G)) :\n (cfAut u xi \\is a linear_char) = (xi \\is a linear_char).\n\n(*This lemma states that the complex conjugate of a class function is a linear character if and only if the original class function is a linear character.*)\nLemma cfConjC_lin_char (xi : 'CF(G)) :\n (xi^*%CF \\is a linear_char) = (xi \\is a linear_char).\n\n(*This lemma states that for any abelian group, the number of irreducible characters is equal to the order of the group.*)\nLemma card_Iirr_abelian : abelian G -> #|Iirr G| = #|G|.\n\n(*This lemma states that for any cyclic group, the number of irreducible characters is equal to the order of the group.*)\nLemma card_Iirr_cyclic : cyclic G -> #|Iirr G| = #|G|.\n\n(*This lemma states that a finite group is abelian if and only if all of its irreducible characters are linear characters.*)\nLemma char_abelianP :\n reflect (forall i : Iirr G, 'chi_i \\is a linear_char) (abelian G).\n\n(*This lemma states that if an irreducible character is linear, then the value of the corresponding irreducible matrix representation for any group element is the one-by-one scalar matrix containing the value of that character at that element.*)\nLemma irr_repr_lin_char (i : Iirr G) x :\n x \\in G -> 'chi_i \\is a linear_char ->\n irr_repr (socle_of_Iirr i) x = ('chi_i x)%:M.\n\n(*This fact asserts that the set of linear characters of a group is closed under division in the ring of class functions.*)\nFact linear_char_divr : divr_closed (@linear_char G).\n\n(*This lemma states that for a cyclic group, all of its irreducible characters are linear characters.*)\nLemma irr_cyclic_lin i : cyclic G -> 'chi[G]_i \\is a linear_char.\n\n(*This lemma states that if the order of a group is a prime number, then all of its irreducible characters are linear characters.*)\nLemma irr_prime_lin i : prime #|G| -> 'chi[G]_i \\is a linear_char.\n\nEnd Linear.\n\nPrenex Implicits linear_char.\nArguments linear_char_pred _ _ _ /.\n\nSection OrthogonalityRelations.\n\nVariables aT gT : finGroupType.\n\n(*This lemma asserts that any matrix representation of an abelian group is similar to a representation consisting entirely of diagonal matrices.*)\nLemma repr_rsim_diag (G : {group gT}) f (rG : mx_representation algC G f) x :\n x \\in G -> let chi := cfRepr rG in\n exists e,\n [/\\ exists2 B, B \\in unitmx & rG x = invmx B *m diag_mx e *m B,\n (forall i, e 0 i ^+ #[x] = 1) /\\ (forall i, `|e 0 i| = 1),\n chi x = \\sum_i e 0 i /\\ `|chi x| <= chi 1%g\n & chi x^-1%g = (chi x)^*].\n\nVariables (A : {group aT}) (G : {group gT}).\n\n(*This lemma states that for any character of a group, its value at the inverse of a group element is equal to the complex conjugate of its value at that element.*)\nLemma char_inv (chi : 'CF(G)) x : chi \\is a character -> chi x^-1%g = (chi x)^*.\n\n(*This lemma states that for any irreducible character of a group, its value at the inverse of a group element is equal to the complex conjugate of its value at that element.*)\nLemma irr_inv i x : 'chi[G]_i x^-1%g = ('chi_i x)^*.\n\n(*This theorem asserts that the scaled sum over a group of the product of a first irreducible character evaluated at a shifted group element and a second irreducible character evaluated at an inverted group element is equal to zero if the characters are different. If the characters are the same, the sum equals the character's value at the shift element divided by its degree.*)\nTheorem generalized_orthogonality_relation y (i j : Iirr G) :\n #|G|%:R^-1 * (\\sum_(x in G) 'chi_i (x * y)%g * 'chi_j x^-1%g)\n = (i == j)%:R * ('chi_i y / 'chi_i 1%g).\n\n(*This corollary, also known as the first orthogonality relation, states that the inner product of two distinct irreducible characters of a group is zero, and the inner product of an irreducible character with itself is one.*)\nCorollary first_orthogonality_relation (i j : Iirr G) :\n #|G|%:R^-1 * (\\sum_(x in G) 'chi_i x * 'chi_j x^-1%g) = (i == j)%:R.\n\n(*This definition describes a function that maps an index, which is a natural number, to the corresponding conjugacy class of a group.*)\nDefinition irr_class i := enum_val (cast_ord (NirrE G) i).\n(*This definition describes a function that maps a conjugacy class of a group to the corresponding index of an irreducible character.*)\nDefinition class_Iirr xG :=\n cast_ord (esym (NirrE G)) (enum_rank_in (classes1 G) xG).\n\n(*A local notation for the function that maps an index to its corresponding conjugacy class.*)\nLocal Notation c := irr_class.\nLocal Notation g i := (repr (c i)).\n(*A local notation for the function that maps a conjugacy class to the index of its corresponding irreducible character.*)\nLocal Notation iC := class_Iirr.\n\n(*This definition constructs the character table of a group as a matrix where the entry at a given row and column is the value of the irreducible character associated with the row index, evaluated at a representative element from the conjugacy class associated with the column index.*)\nDefinition character_table := \\matrix_(i, j) 'chi[G]_i (g j).\n(*A local notation for the character table of a group.*)\nLocal Notation X := character_table.\n\n(*This lemma asserts that the conjugacy class obtained from the index of an irreducible character is a valid conjugacy class within the group.*)\nLemma irr_classP i : c i \\in classes G.\n\n(*This lemma states that the conjugacy class generated by the designated representative element of the i-th class is indeed the i-th class itself.*)\nLemma repr_irr_classK i : g i ^: G = c i.\n\n(*This lemma asserts that composing the function that maps a conjugacy class to an index with the function that maps an index back to a class results in the identity function on conjugacy classes.*)\nLemma irr_classK : cancel c iC.\n\n(*This lemma asserts that composing the function that maps an index to a conjugacy class with the function that maps a class back to an index results in the identity function on the indices of irreducible characters.*)\nLemma class_IirrK : {in classes G, cancel iC c}.\n\n(*This lemma provides a rule for symbolic computation, stating that a cumulative commutative operation performed over all conjugacy classes of a group can be equivalently computed by performing the operation over all indices of irreducible characters, substituting each class with the one corresponding to its index.*)\nLemma reindex_irr_class R idx (op : @Monoid.com_law R idx) F :\n \\big[op/idx]_(xG in classes G) F xG = \\big[op/idx]_i F (c i).\n\n(*This definition constructs an auxiliary matrix where each entry is derived from the complex conjugate of an irreducible character's value on a class representative, scaled by the inverse of the size of that representative's centralizer.*)\nLet X' := \\matrix_(i, j) (#|'C_G[g i]|%:R^-1 * ('chi[G]_j (g i))^.\n(*This local proof term demonstrates that the matrix product of the character table and a specific auxiliary matrix results in the identity matrix.*)\nLet XX'_1: X *m X' = 1%:M.\n\n(*This lemma proves that the character table of a group is an invertible matrix.*)\nLemma character_table_unit : X \\in unitmx.\n\n(*A local definition holding the proof that the character table is an invertible matrix.*)\nLet uX := character_table_unit.\n\n(*This theorem, also known as the second orthogonality relation, asserts that the sum, taken over all irreducible characters, of the product of a character's value at a first group element and its conjugate value at a second group element is zero if the two elements are not conjugate. If the elements are conjugate, the sum equals the size of the centralizer of the first element.*)\nTheorem second_orthogonality_relation x y :\n y \\in G ->\n \\sum_i 'chi[G]_i x * ('chi_i y)^* = #|'C_G[x]|%:R *+ (x \\in y ^: G).\n\n(*This lemma establishes that two group elements belong to the same conjugacy class if and only if every irreducible character of the group evaluates to the same value for both elements.*)\nLemma eq_irr_mem_classP x y :\n y \\in G -> reflect (forall i, 'chi[G]_i x = 'chi_i y) (x \\in y ^: G).\n\n(*This lemma states that for a group acting compatibly on both the irreducible characters and the conjugacy classes of another group, the number of fixed points in the set of irreducible characters is equal to the number of fixed points in the set of conjugacy classes.*)\nLemma card_afix_irr_classes (ito : action A (Iirr G)) (cto : action A _) a :\n a \\in A -> [acts A, on classes G | cto] ->\n (forall i x y, x \\in G -> y \\in cto (x ^: G) a ->\n 'chi_i x = 'chi_(ito i a) y) ->\n #|'Fix_ito[a]| = #|'Fix_(classes G | cto)[a]|.\n\nEnd OrthogonalityRelations.\n\nPrenex Implicits irr_class class_Iirr irr_classK.\nArguments class_IirrK {gT G%_G} [xG%_g] GxG : rename.\nArguments character_table {gT} G%_g.\n\nSection InnerProduct.\n\nVariable (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that the inner product of two irreducible characters is one if they are the same character and zero if they are different.*)\nLemma cfdot_irr i j : '['chi_i, 'chi_j]_G = (i == j)%:R.\n\n(*This lemma states that the norm of any irreducible character, defined via the class function inner product, is equal to one.*)\nLemma cfnorm_irr i : '['chi[G]_i] = 1.\n\n(*This lemma asserts that the set of all irreducible characters of a group forms an orthonormal set with respect to the standard inner product on class functions.*)\nLemma irr_orthonormal : orthonormal (irr G).\n\n(*This lemma states that the coordinate of a class function with respect to the i-th irreducible character in the orthonormal basis of characters is given by the inner product of the class function with that irreducible character.*)\nLemma coord_cfdot phi i : coord (irr G) i phi = '[phi, 'chi_i].\n\n(*This lemma shows that any class function can be expressed as a linear combination of the irreducible characters, where each coefficient is the inner product of the function with the corresponding irreducible character.*)\nLemma cfun_sum_cfdot phi : phi = \\sum_i '[phi, 'chi_i]_G *: 'chi_i.\n\n(*This lemma, also known as Parseval's identity for class functions, states that the inner product of two class functions is equal to the sum of the products of their corresponding coordinates in the basis of irreducible characters, with one set of coordinates being complex conjugated.*)\nLemma cfdot_sum_irr phi psi :\n '[phi, psi]_G = \\sum_i '[phi, 'chi_i] * '[psi, 'chi_i]^*.\n\n(*This lemma asserts that if a class function is a character, then its inner product with any irreducible character results in a non-negative integer.*)\nLemma Cnat_cfdot_char_irr i phi :\n phi \\is a character -> '[phi, 'chi_i]_G \\in Num.nat.\n\n(*This lemma states that for any two characters of a group, their inner product is symmetric, meaning the order of the functions does not change the result.*)\nLemma cfdot_char_r phi chi :\n chi \\is a character -> '[phi, chi]_G = \\sum_i '[phi, 'chi_i] * '[chi, 'chi_i].\n\n(*This lemma states that the inner product of two characters is a natural number.*)\nLemma Cnat_cfdot_char chi xi :\n chi \\is a character -> xi \\is a character -> '[chi, xi]_G \\in Num.nat.\n\n(*This lemma states that the inner product operation on two characters is commutative.*)\nLemma cfdotC_char chi xi :\n chi \\is a character-> xi \\is a character -> '[chi, xi]_G = '[xi, chi].\n\n(*This lemma provides an equivalence for a class function being an irreducible character: it holds if and only if the function is a character and its norm-squared is equal to one.*)\nLemma irrEchar chi : (chi \\in irr G) = (chi \\is a character) && ('[chi] == 1).\n\n(*This lemma states that any irreducible character is also a character.*)\nLemma irrWchar chi : chi \\in irr G -> chi \\is a character.\n\n(*This lemma states that the norm of any irreducible character is equal to one.*)\nLemma irrWnorm chi : chi \\in irr G -> '[chi] = 1.\n\n(*This lemma states that the product of a linear character and an irreducible character results in another irreducible character.*)\nLemma mul_lin_irr xi chi :\n xi \\is a linear_char -> chi \\in irr G -> xi * chi \\in irr G.\n\n(*This lemma provides conditions for the equality of two scaled irreducible characters. The equality holds if and only if the scalars are equal, and either the scalar is zero or the characters are the same.*)\nLemma eq_scaled_irr a b i j :\n (a *: 'chi[G]_i == b *: 'chi_j) = (a == b) && ((a == 0) || (i == j)).\n\n(*This lemma states that two possibly negated irreducible characters are equal if and only if their signs are the same and they are the same irreducible character.*)\nLemma eq_signed_irr (s t : bool) i j :\n ((-1) ^+ s *: 'chi[G]_i == (-1) ^+ t *: 'chi_j) = (s == t) && (i == j).\n\n(*This lemma states that scaling two irreducible characters by the same scalar results in equal class functions if and only if the scalar is zero or the characters were identical.*)\nLemma eq_scale_irr a (i j : Iirr G) :\n (a *: 'chi_i == a *: 'chi_j) = (a == 0) || (i == j).\n\n(*This lemma provides the conditions under which a linear combination of two irreducible characters is equal to another such linear combination. This equality holds if either the characters and their corresponding coefficients match pairwise, or if the characters are swapped and their coefficients are equal, or in specific cases where both linear combinations collapse to the zero function.*)\nLemma eq_addZ_irr a b (i j r t : Iirr G) :\n (a *: 'chi_i + b *: 'chi_j == a *: 'chi_r + b *: 'chi_t)\n = [|| [&& (a == 0) || (i == r) & (b == 0) || (j == t)],\n [&& i == t, j == r & a == b] | [&& i == j, r == t & a == - b]].\n\n(*This lemma establishes the conditions for equality between two class functions, each formed by the difference of two irreducible characters scaled by natural numbers. Equality holds if the corresponding scaled characters are equal, or if both functions collapse to zero because the characters in each difference are the same and their coefficients are equal.*)\nLemma eq_subZnat_irr (a b : nat) (i j r t : Iirr G) :\n (a%:R *: 'chi_i - b%:R *: 'chi_j == a%:R *: 'chi_r - b%:R *: 'chi_t)\n = [|| a == 0 | i == r] && [|| b == 0 | j == t]\n || [&& i == j, r == t & a == b].\n\nEnd InnerProduct.\n\nSection IrrConstt.\n\nVariable (gT : finGroupType) (G H : {group gT}).\n\n(*This lemma states that for any character, the absolute value of its evaluation at any group element is less than or equal to its value at the identity element.*)\nLemma char1_ge_norm (chi : 'CF(G)) x :\n chi \\is a character -> `|chi x| <= chi 1%g.\n\n(*This lemma states that if the absolute value of the character of a matrix representation at a group element is equal to the degree of the representation, then the matrix for that element must be a scalar matrix, with the scalar having an absolute value of one.*)\nLemma max_cfRepr_norm_scalar n (rG : mx_representation algC G n) x :\n x \\in G -> `|cfRepr rG x| = cfRepr rG 1%g ->\n exists2 c, `|c| = 1 & rG x = c%:M.\n\n(*This lemma states that if the character of a matrix representation evaluated at a group element is equal to the degree of the representation, then the matrix for that element must be the identity matrix.*)\nLemma max_cfRepr_mx1 n (rG : mx_representation algC G n) x :\n x \\in G -> cfRepr rG x = cfRepr rG 1%g -> rG x = 1%:M.\n\n(*This definition specifies the set of irreducible constituents of a class function as the set of indices of irreducible characters that have a non-zero inner product with the given class function.*)\nDefinition irr_constt (B : {set gT}) phi := [pred i | '[phi, 'chi_i]_B != 0].\n\n(*This lemma provides an equivalent condition for an index belonging to the set of irreducible constituents of a class function: it holds if and only if the inner product of the class function with the corresponding irreducible character is non-zero.*)\nLemma irr_consttE i phi : (i \\in irr_constt phi) = ('[phi, 'chi_i]_G != 0).\n\n(*This lemma states that for a given character, an irreducible character is a constituent of it if and only if the given character can be expressed as the sum of that irreducible character and another character.*)\nLemma constt_charP (i : Iirr G) chi :\n chi \\is a character ->\n reflect (exists2 chi', chi' \\is a character & chi = 'chi_i + chi')\n (i \\in irr_constt chi).\n\n(*This lemma states that any class function can be reconstructed as the sum of its constituent irreducible characters, where each is scaled by its corresponding inner product with the class function.*)\nLemma cfun_sum_constt (phi : 'CF(G)) :\n phi = \\sum_(i in irr_constt phi) '[phi, 'chi_i] *: 'chi_i.\n\n(*This lemma states that any non-zero class function must have at least one irreducible constituent.*)\nLemma neq0_has_constt (phi : 'CF(G)) :\n phi != 0 -> exists i, i \\in irr_constt phi.\n\n(*This lemma states that the set of irreducible constituents of an irreducible character consists solely of that character itself.*)\nLemma constt_irr i : irr_constt 'chi[G]_i =i pred1 i.\n\n(*This lemma states that if an irreducible character is a constituent of another character, then the degree of the irreducible character is less than or equal to the degree of the other character.*)\nLemma char1_ge_constt (i : Iirr G) chi :\n chi \\is a character -> i \\in irr_constt chi -> 'chi_i 1%g <= chi 1%g.\n\n(*This lemma states that if two characters are orthogonal, then any irreducible constituent of the first character is orthogonal to any irreducible constituent of the second character.*)\nLemma constt_ortho_char (phi psi : 'CF(G)) i j :\n phi \\is a character -> psi \\is a character ->\n i \\in irr_constt phi -> j \\in irr_constt psi ->\n '[phi, psi] = 0 -> '['chi_i, 'chi_j] = 0.\n\nEnd IrrConstt.\n\nArguments irr_constt {gT B%_g} phi%_CF.\n\nSection Kernel.\n\nVariable (gT : finGroupType) (G : {group gT}).\nImplicit Types (phi chi xi : 'CF(G)) (H : {group gT}).\n\n(*This lemma states that the kernel of the character of a representation is equal to the kernel of the representation itself.*)\nLemma cfker_repr n (rG : mx_representation algC G n) :\n cfker (cfRepr rG) = rker rG.\n\n(*This lemma provides an equivalent definition for the kernel of a character as the set of group elements at which the character's value equals its degree.*)\nLemma cfkerEchar chi :\n chi \\is a character -> cfker chi = [set x in G | chi x == chi 1%g].\n\n(*This lemma states that for a non-zero character, its kernel is the set of group elements where the character's value is equal to its value at the identity.*)\nLemma cfker_nzcharE chi :\n chi \\is a character -> chi != 0 -> cfker chi = [set x | chi x == chi 1%g].\n\n(*This lemma characterizes the kernel of an irreducible character as the set of group elements where the character's value equals its degree.*)\nLemma cfkerEirr i : cfker 'chi[G]_i = [set x | 'chi_i x == 'chi_i 1%g].\n\n(*This lemma states that the kernel of the trivial irreducible character is the entire group.*)\nLemma cfker_irr0 : cfker 'chi[G]_0 = G.\n\n(*This lemma states that the character of the regular representation is faithful, meaning its kernel contains only the identity element.*)\nLemma cfaithful_reg : cfaithful (cfReg G).\n\n(*This lemma states that the kernel of a character is equal to the intersection of the kernels of all its irreducible constituent characters.*)\nLemma cfkerE chi :\n chi \\is a character ->\n cfker chi = G :&: \\bigcap_(i in irr_constt chi) cfker 'chi_i.\n\n(*This lemma states that the intersection of the kernels of all irreducible characters of a group is the trivial subgroup containing only the identity element.*)\nLemma TI_cfker_irr : \\bigcap_i cfker 'chi[G]_i = [1].\n\n(*This lemma states that if a given function is a character and a specific irreducible character is one of its constituents, then the character kernel of the given function is a subgroup of the character kernel of that irreducible character.*)\nLemma cfker_constt i chi :\n chi \\is a character -> i \\in irr_constt chi ->\n cfker chi \\subset cfker 'chi[G]_i.\n\nSection KerLin.\n\nVariable xi : 'CF(G).\nHypothesis lin_xi : xi \\is a linear_char.\n(*This hypothesis asserts that a given class function is a character.*)\nLet Nxi: xi \\is a character. \n\n(*This lemma states that for any linear character, the derived subgroup of the group is contained within the character kernel of that linear character.*)\nLemma lin_char_der1 : G^`(1)%g \\subset cfker xi.\n\n(*This lemma asserts that the order of a linear character is equal to the exponent of the quotient group of the underlying group by the character's kernel.*)\nLemma cforder_lin_char : #[xi]%CF = exponent (G / cfker xi)%g.\n\n(*This lemma states that the order of a linear character divides the order of the group.*)\nLemma cforder_lin_char_dvdG : #[xi]%CF %| #|G|.\n\n(*This lemma establishes that the order of a linear character is always a positive natural number.*)\nLemma cforder_lin_char_gt0 : (0 < #[xi]%CF)%N.\n\nEnd KerLin.\n\nEnd Kernel.\n\nSection Restrict.\n\nVariable (gT : finGroupType) (G H : {group gT}).\n\n(*This lemma states that the character of a representation restricted to a subgroup is the same as the restriction of the character of the original representation to that subgroup.*)\nLemma cfRepr_sub n (rG : mx_representation algC G n) (sHG : H \\subset G) :\n cfRepr (subg_repr rG sHG) = 'Res[H] (cfRepr rG).\n\n(*This lemma asserts that if a class function on a group is a character, then its restriction to a subgroup is also a character on that subgroup.*)\nLemma cfRes_char chi : chi \\is a character -> 'Res[H, G] chi \\is a character.\n\n(*This lemma states that for any character of a group, its restriction to a subgroup is the zero function if and only if the original character was the zero function.*)\nLemma cfRes_eq0 phi : phi \\is a character -> ('Res[H, G] phi == 0) = (phi == 0).\n\n(*This lemma states that if a class function on a group is a linear character, then its restriction to a subgroup is also a linear character.*)\nLemma cfRes_lin_char chi :\n chi \\is a linear_char -> 'Res[H, G] chi \\is a linear_char.\n\n(*This lemma states that the restriction of any irreducible character of a group to one of its subgroups is never the zero class function.*)\nLemma Res_irr_neq0 i : 'Res[H, G] 'chi_i != 0.\n\n(*This lemma states that if a class function is a character of a group, and its restriction to a subgroup is a linear character, then the original class function must also be a linear character.*)\nLemma cfRes_lin_lin (chi : 'CF(G)) :\n chi \\is a character -> 'Res[H] chi \\is a linear_char -> chi \\is a linear_char.\n\n(*This lemma establishes that if a given class function is a character of a group and its restriction to a subgroup is an irreducible character of that subgroup, then the original class function is also an irreducible character of the group.*)\nLemma cfRes_irr_irr chi :\n chi \\is a character -> 'Res[H] chi \\in irr H -> chi \\in irr G.\n\n(*This definition computes the index of an irreducible character on a subgroup, which is obtained by restricting an irreducible character from the larger group and then finding its corresponding index among the irreducible characters of the subgroup.*)\nDefinition Res_Iirr (A B : {set gT}) i := cfIirr ('Res[B, A] 'chi_i).\n\n(*This lemma shows that applying the irreducible character restriction process to the trivial character of a group, which has index zero, results in the trivial character of the subgroup, which also has index zero.*)\nLemma Res_Iirr0 : Res_Iirr H (0 : Iirr G) = 0.\n\n(*This lemma states that if an irreducible character of a group is linear, then the irreducible character of a subgroup obtained through the index restriction operation is identical to the direct restriction of the original character to that subgroup.*)\nLemma lin_Res_IirrE i : 'chi[G]_i 1%g = 1 -> 'chi_(Res_Iirr H i) = 'Res 'chi_i.\n\nEnd Restrict.\n\nArguments Res_Iirr {gT A%_g} B%_g i%_R.\n\nSection MoreConstt.\n\nVariables (gT : finGroupType) (G H : {group gT}).\n\n(*This lemma provides the Frobenius Reciprocity theorem, stating that an irreducible character of a group is a constituent of a character induced from a subgroup's irreducible character if and only if the subgroup's irreducible character is a constituent of the restriction of the group's irreducible character.*)\nLemma constt_Ind_Res i j :\n i \\in irr_constt ('Ind[G] 'chi_j) = (j \\in irr_constt ('Res[H] 'chi_i)).\n\n(*This lemma states that for any character of a group, if a specific irreducible character is one of its constituents, then the inner product of the restriction of this constituent with a subgroup's irreducible character is less than or equal to the inner product of the restriction of the original character with that same subgroup's irreducible character.*)\nLemma cfdot_Res_ge_constt i j psi :\n psi \\is a character -> j \\in irr_constt psi ->\n '['Res[H, G] 'chi_j, 'chi_i] <= '['Res[H] psi, 'chi_i].\n\n(*This lemma states that for any character of a group, if a specific irreducible character is one of its constituents, then the set of irreducible constituents resulting from restricting this constituent to a subgroup is a subset of the irreducible constituents resulting from restricting the original character to the same subgroup.*)\nLemma constt_Res_trans j psi :\n psi \\is a character -> j \\in irr_constt psi ->\n {subset irr_constt ('Res[H, G] 'chi_j) <= irr_constt ('Res[H] psi)}.\n\nEnd MoreConstt.\n\nSection Morphim.\n\nVariables (aT rT : finGroupType) (G D : {group aT}) (f : {morphism D >-> rT}).\nImplicit Type chi : 'CF(f @* G).\n\n(*This lemma asserts that the character of a representation transformed by a group morphism is equal to the class function obtained by transforming the character of the original representation with the same morphism.*)\nLemma cfRepr_morphim n (rfG : mx_representation algC (f @* G) n) sGD :\n cfRepr (morphim_repr rfG sGD) = cfMorph (cfRepr rfG).\n\n(*This lemma states that if a given class function is a character, then the new class function created by composing it with a group morphism is also a character.*)\nLemma cfMorph_char chi : chi \\is a character -> cfMorph chi \\is a character.\n\n(*This lemma states that if a given class function is a linear character, then the new class function created by composing it with a group morphism is also a linear character.*)\nLemma cfMorph_lin_char chi :\n chi \\is a linear_char -> cfMorph chi \\is a linear_char.\n\n(*This lemma establishes that, given an injective group morphism, a class function transformed by this morphism is a character if and only if the original class function was a character.*)\nLemma cfMorph_charE chi :\n G \\subset D -> (cfMorph chi \\is a character) = (chi \\is a character).\n\n(*This lemma establishes that, given an injective group morphism, a class function transformed by this morphism is a linear character if and only if the original class function was a linear character.*)\nLemma cfMorph_lin_charE chi :\n G \\subset D -> (cfMorph chi \\is a linear_char) = (chi \\is a linear_char).\n\n(*This lemma states that, under an injective group morphism, a class function transformed by the morphism is an irreducible character of the target group if and only if the original class function was an irreducible character of the source group.*)\nLemma cfMorph_irr chi :\n G \\subset D -> (cfMorph chi \\in irr G) = (chi \\in irr (f @* G)).\n\n(*This definition provides a mapping between the indices of irreducible characters across a group morphism. It computes the index of the transformed character in the target group, starting from the index of an irreducible character in the source group.*)\nDefinition morph_Iirr i := cfIirr (cfMorph 'chi[f @* G]_i).\n\n(*This lemma states that the transformation of irreducible character indices via a group morphism maps the index of the trivial character, which is zero, to itself.*)\nLemma morph_Iirr0 : morph_Iirr 0 = 0.\n\nHypothesis sGD : G \\subset D.\n\n(*This lemma asserts that, for an injective group morphism, the irreducible character corresponding to a transformed index is identical to the character obtained by directly transforming the original irreducible character with the morphism.*)\nLemma morph_IirrE i : 'chi_(morph_Iirr i) = cfMorph 'chi_i.\n\n(*This lemma states that the mapping of irreducible character indices through an injective group morphism is injective, meaning distinct indices map to distinct indices.*)\nLemma morph_Iirr_inj : injective morph_Iirr.\n\n(*This lemma states that for an injective group morphism, the transformation of an irreducible character's index results in the index zero if and only if the original index was zero.*)\nLemma morph_Iirr_eq0 i : (morph_Iirr i == 0) = (i == 0).\n\nEnd Morphim.\n\nSection Isom.\n\nVariables (aT rT : finGroupType) (G : {group aT}) (f : {morphism G >-> rT}).\nVariables (R : {group rT}) (isoGR : isom G R f).\nImplicit Type chi : 'CF(G).\n\n(*This lemma states that a class function is a character if and only if its image under an isomorphism of class functions is also a character.*)\nLemma cfIsom_char chi :\n (cfIsom isoGR chi \\is a character) = (chi \\is a character).\n\n(*This lemma states that a class function is a linear character if and only if its image under an isomorphism of class functions is also a linear character.*)\nLemma cfIsom_lin_char chi :\n (cfIsom isoGR chi \\is a linear_char) = (chi \\is a linear_char).\n\n(*This lemma states that a class function is an irreducible character of a group if and only if its image under an isomorphism of class functions is an irreducible character of the isomorphic group.*)\nLemma cfIsom_irr chi : (cfIsom isoGR chi \\in irr R) = (chi \\in irr G).\n\n(*This definition provides a function that maps the index of an irreducible character of a group to the index of the corresponding irreducible character in an isomorphic group.*)\nDefinition isom_Iirr i := cfIirr (cfIsom isoGR 'chi_i).\n\n(*This lemma states that the irreducible character of a target group at an index obtained via an isomorphism map is equal to the original irreducible character transformed by the class function isomorphism.*)\nLemma isom_IirrE i : 'chi_(isom_Iirr i) = cfIsom isoGR 'chi_i.\n\n(*This lemma states that the function which maps indices of irreducible characters of a group to their corresponding indices in an isomorphic group is injective.*)\nLemma isom_Iirr_inj : injective isom_Iirr.\n\n(*This lemma states that the function mapping irreducible character indices between isomorphic groups maps an index to zero if and only if the original index is zero.*)\nLemma isom_Iirr_eq0 i : (isom_Iirr i == 0) = (i == 0).\n\n(*This lemma states that the function mapping irreducible character indices between isomorphic groups maps the index zero to the index zero.*)\nLemma isom_Iirr0 : isom_Iirr 0 = 0.\n\nEnd Isom.\n\nArguments isom_Iirr_inj {aT rT G f R} isoGR [i1 i2] : rename.\n\nSection IsomInv.\n\nVariables (aT rT : finGroupType) (G : {group aT}) (f : {morphism G >-> rT}).\nVariables (R : {group rT}) (isoGR : isom G R f).\n\n(*This lemma states that the irreducible character index map associated with a group isomorphism is a left inverse to the index map associated with the inverse isomorphism.*)\nLemma isom_IirrK : cancel (isom_Iirr isoGR) (isom_Iirr (isom_sym isoGR)).\n\n(*This lemma states that the irreducible character index map associated with the inverse of a group isomorphism is a left inverse to the index map associated with the original isomorphism.*)\nLemma isom_IirrKV : cancel (isom_Iirr (isom_sym isoGR)) (isom_Iirr isoGR).\n\nEnd IsomInv.\n\nSection Sdprod.\n\nVariables (gT : finGroupType) (K H G : {group gT}).\nHypothesis defG : K ><| H = G.\n(*This hypothesis states that a group G is a subgroup of the normalizer of a subgroup K.*)\nLet nKG: G \\subset 'N(K). \n\n(*This lemma states that a class function on a subgroup of a semidirect product is a character if and only if its lift to the entire group is also a character.*)\nLemma cfSdprod_char chi :\n (cfSdprod defG chi \\is a character) = (chi \\is a character).\n\n(*This lemma states that a class function on a subgroup of a semidirect product is a linear character if and only if its lift to the entire group is also a linear character.*)\nLemma cfSdprod_lin_char chi :\n (cfSdprod defG chi \\is a linear_char) = (chi \\is a linear_char).\n\n(*This lemma states that a class function on a subgroup of a semidirect product is an irreducible character if and only if its lift to the entire group is an irreducible character.*)\nLemma cfSdprod_irr chi : (cfSdprod defG chi \\in irr G) = (chi \\in irr H).\n\n(*This definition provides a function that maps the index of an irreducible character of a subgroup in a semidirect product to the index of the corresponding lifted irreducible character in the whole group.*)\nDefinition sdprod_Iirr j := cfIirr (cfSdprod defG 'chi_j).\n\n(*This lemma states that the irreducible character of a group at an index obtained by lifting from a subgroup in a semidirect product is equal to the lifted character itself.*)\nLemma sdprod_IirrE j : 'chi_(sdprod_Iirr j) = cfSdprod defG 'chi_j.\n\n(*This lemma states that the function which lifts an irreducible character index from a subgroup is a left inverse to the function which restricts an irreducible character index to that subgroup.*)\nLemma sdprod_IirrK : cancel sdprod_Iirr (Res_Iirr H).\n\n(*This lemma states that the function which maps an irreducible character index from a subgroup in a semidirect product to the index of its lift in the whole group is injective.*)\nLemma sdprod_Iirr_inj : injective sdprod_Iirr.\n\n(*This lemma states that the function lifting irreducible character indices from a subgroup to a semidirect product group maps an index to zero if and only if the original index is zero.*)\nLemma sdprod_Iirr_eq0 i : (sdprod_Iirr i == 0) = (i == 0).\n\n(*This lemma states that the function lifting irreducible character indices from a subgroup to a semidirect product group maps the index zero to the index zero.*)\nLemma sdprod_Iirr0 : sdprod_Iirr 0 = 0.\n\n(*This lemma states that if an irreducible character of a semidirect product group contains the normal subgroup in its kernel, then the restriction of this character to the other subgroup is an irreducible character of that subgroup.*)\nLemma Res_sdprod_irr phi :\n K \\subset cfker phi -> phi \\in irr G -> 'Res phi \\in irr H.\n\n(*This lemma states that if the kernel of an irreducible character of a semidirect product group contains the normal subgroup, then the character at the restricted index is equal to the restriction of the original character.*)\nLemma sdprod_Res_IirrE i :\n K \\subset cfker 'chi[G]_i -> 'chi_(Res_Iirr H i) = 'Res 'chi_i.\n\n(*This lemma states that if the kernel of an irreducible character of a semidirect product group contains the normal subgroup, then lifting the restricted character index back to the full group recovers the original character index.*)\nLemma sdprod_Res_IirrK i :\n K \\subset cfker 'chi_i -> sdprod_Iirr (Res_Iirr H i) = i.\n\nEnd Sdprod.\n\nArguments sdprod_Iirr_inj {gT K H G} defG [i1 i2] : rename.\n\nSection DProd.\n\nVariables (gT : finGroupType) (G K H : {group gT}).\nHypothesis KxH : K \\x H = G.\n\n(*This lemma states that for a direct product group where the right factor is abelian, the operation of forming a product character from a fixed character of the right factor and the restriction of a character to the left factor acts as an identity map.*)\nLemma cfDprodKl_abelian j : abelian H -> cancel ((cfDprod KxH)^~ 'chi_j) 'Res.\n\n(*This lemma states that for a direct product group where the left factor is abelian, the operation of forming a product character from a fixed character of the left factor and the restriction of a character to the right factor acts as an identity map.*)\nLemma cfDprodKr_abelian i : abelian K -> cancel (cfDprod KxH 'chi_i) 'Res.\n\n(*This lemma states that the inflation of a class function from the left factor of a direct product is a character if and only if the original class function is a character.*)\nLemma cfDprodl_char phi :\n (cfDprodl KxH phi \\is a character) = (phi \\is a character).\n\n(*This lemma states that the inflation of a class function from the right factor of a direct product is a character if and only if the original class function is a character.*)\nLemma cfDprodr_char psi :\n (cfDprodr KxH psi \\is a character) = (psi \\is a character).\n\n(*This lemma states that if two class functions from the component groups of a direct product are both characters, then their product is a character of the direct product group.*)\nLemma cfDprod_char phi psi :\n phi \\is a character -> psi \\is a character ->\n cfDprod KxH phi psi \\is a character.\n\n(*This lemma states that for two characters from the component groups of a direct product, their product character is the trivial character if and only if both original characters are trivial.*)\nLemma cfDprod_eq1 phi psi :\n phi \\is a character -> psi \\is a character ->\n (cfDprod KxH phi psi == 1) = (phi == 1) && (psi == 1).\n\n(*This lemma states that a class function inflated from the left factor of a direct product is a linear character if and only if the original class function is a linear character.*)\nLemma cfDprodl_lin_char phi :\n (cfDprodl KxH phi \\is a linear_char) = (phi \\is a linear_char).\n\n(*This lemma states that a character lifted from a group H to the direct product group K times H is a linear character if and only if the original character on H is a linear character.*)\nLemma cfDprodr_lin_char psi :\n (cfDprodr KxH psi \\is a linear_char) = (psi \\is a linear_char).\n\n(*This lemma states that if a character from a group K and a character from a group H are both linear, then their tensor product character on the direct product group K times H is also a linear character.*)\nLemma cfDprod_lin_char phi psi :\n phi \\is a linear_char -> psi \\is a linear_char ->\n cfDprod KxH phi psi \\is a linear_char.\n\n(*This lemma states that a character lifted from a group K to the direct product group K times H is an irreducible character if and only if the original character on K is an irreducible character.*)\nLemma cfDprodl_irr chi : (cfDprodl KxH chi \\in irr G) = (chi \\in irr K).\n\n(*This lemma states that a character lifted from a group H to the direct product group K times H is an irreducible character if and only if the original character on H is an irreducible character.*)\nLemma cfDprodr_irr chi : (cfDprodr KxH chi \\in irr G) = (chi \\in irr H).\n\n(*This definition provides a function that computes the index of the irreducible character on the direct product group K times H that corresponds to lifting an irreducible character from group K, given the index of the original character.*)\nDefinition dprodl_Iirr i := cfIirr (cfDprodl KxH 'chi_i).\n\n(*This lemma states that the irreducible character of the direct product group K times H at the index computed by lifting an irreducible character index from K is equal to the character obtained by directly lifting the corresponding irreducible character from K.*)\nLemma dprodl_IirrE i : 'chi_(dprodl_Iirr i) = cfDprodl KxH 'chi_i.\n\n(*This lemma states that the function which lifts an irreducible character index from group K to the direct product group and the function which restricts an irreducible character index from the direct product group back to K are inverses of each other.*)\nLemma dprodl_IirrK : cancel dprodl_Iirr (Res_Iirr K).\n\n(*This lemma states that the index of a lifted character from group K is zero if and only if the index of the original character in K is zero.*)\nLemma dprodl_Iirr_eq0 i : (dprodl_Iirr i == 0) = (i == 0).\n\n(*This lemma states that lifting the index of the trivial character of group K, which is zero, results in the index of the trivial character of the direct product group, which is also zero.*)\nLemma dprodl_Iirr0 : dprodl_Iirr 0 = 0.\n\n(*This definition provides a function that computes the index of the irreducible character on the direct product group K times H that corresponds to lifting an irreducible character from group H, given the index of the original character.*)\nDefinition dprodr_Iirr j := cfIirr (cfDprodr KxH 'chi_j).\n\n(*This lemma states that the irreducible character of the direct product group K times H at the index computed by lifting an irreducible character index from H is equal to the character obtained by directly lifting the corresponding irreducible character from H.*)\nLemma dprodr_IirrE j : 'chi_(dprodr_Iirr j) = cfDprodr KxH 'chi_j.\n\n(*This lemma states that the function which lifts an irreducible character index from group H to the direct product group and the function which restricts an irreducible character index from the direct product group back to H are inverses of each other.*)\nLemma dprodr_IirrK : cancel dprodr_Iirr (Res_Iirr H).\n\n(*This lemma states that the index of a lifted character from group H is zero if and only if the index of the original character in H is zero.*)\nLemma dprodr_Iirr_eq0 j : (dprodr_Iirr j == 0) = (j == 0).\n\n(*This lemma states that lifting the index of the trivial character of group H, which is zero, results in the index of the trivial character of the direct product group, which is also zero.*)\nLemma dprodr_Iirr0 : dprodr_Iirr 0 = 0.\n\n(*This lemma states that the tensor product of an irreducible character from group K and an irreducible character from group H is an irreducible character of their direct product group.*)\nLemma cfDprod_irr i j : cfDprod KxH 'chi_i 'chi_j \\in irr G.\n\n(*This definition provides a function that maps a pair of indices of irreducible characters from groups K and H to the index of their tensor product irreducible character in the direct product group K times H.*)\nDefinition dprod_Iirr ij := cfIirr (cfDprod KxH 'chi_ij.1 'chi_ij.2).\n\n(*This lemma states that the irreducible character of the direct product group at the index corresponding to a given pair of indices is equal to the tensor product of the irreducible characters from the component groups K and H at those original indices.*)\nLemma dprod_IirrE i j : 'chi_(dprod_Iirr (i, j)) = cfDprod KxH 'chi_i 'chi_j.\n\n(*This lemma states that the tensor product of an irreducible character from group K with the trivial character from group H yields the same character as lifting the irreducible character from K to the direct product group.*)\nLemma dprod_IirrEl i : 'chi_(dprod_Iirr (i, 0)) = cfDprodl KxH 'chi_i.\n\n(*This lemma states that the tensor product of the trivial character from group K with an irreducible character from group H yields the same character as lifting the irreducible character from H to the direct product group.*)\nLemma dprod_IirrEr j : 'chi_(dprod_Iirr (0, j)) = cfDprodr KxH 'chi_j.\n\n(*This lemma states that the function mapping a pair of irreducible character indices from groups K and H to the index of their tensor product character is injective, meaning that distinct pairs of component irreducible characters yield distinct irreducible characters on the direct product group.*)\nLemma dprod_Iirr_inj : injective dprod_Iirr.\n\n(*This lemma states that the index of the tensor product of the trivial character from group K and the trivial character from group H is the index of the trivial character in the direct product group, which is zero.*)\nLemma dprod_Iirr0 : dprod_Iirr (0, 0) = 0.\n\n(*This lemma states that the index of the tensor product of the trivial character of group K and an irreducible character of group H is the same as the index of that irreducible character of H lifted to the direct product group.*)\nLemma dprod_Iirr0l j : dprod_Iirr (0, j) = dprodr_Iirr j.\n\n(*This lemma states that the index of the tensor product of an irreducible character of group K and the trivial character of group H is the same as the index of that irreducible character of K lifted to the direct product group.*)\nLemma dprod_Iirr0r i : dprod_Iirr (i, 0) = dprodl_Iirr i.\n\n(*This lemma states that the index of a tensor product character is zero if and only if the indices of both component characters are zero.*)\nLemma dprod_Iirr_eq0 i j : (dprod_Iirr (i, j) == 0) = (i == 0) && (j == 0).\n\n(*This lemma establishes the orthogonality relation for irreducible characters of a direct product group, stating that the inner product of two such characters is one if and only if their corresponding component characters from the factor groups are identical, and zero otherwise.*)\nLemma cfdot_dprod_irr i1 i2 j1 j2 :\n '['chi_(dprod_Iirr (i1, j1)), 'chi_(dprod_Iirr (i2, j2))]\n = ((i1 == i2) && (j1 == j2))%:R.\n\n(*This lemma states that the function which computes the index of a tensor product character is surjective, meaning that every irreducible character of the direct product group is a tensor product of irreducible characters from the component groups.*)\nLemma dprod_Iirr_onto k : k \\in codom dprod_Iirr.\n\n(*This definition provides the inverse function for the mapping from pairs of component character indices to their product character index. Given an index of an irreducible character on the direct product group, this function returns the pair of indices of the component characters that form it.*)\nDefinition inv_dprod_Iirr i := iinv (dprod_Iirr_onto i).\n\n(*This lemma states that if one takes an index of an irreducible character on the direct product group, finds the pair of component indices that produce it, and then computes the product index from that pair, one gets back the original index.*)\nLemma dprod_IirrK : cancel dprod_Iirr inv_dprod_Iirr.\n\n(*This lemma states that if one takes a pair of indices of component irreducible characters, computes the index of their tensor product character, and then applies the inverse mapping, one gets back the original pair of indices.*)\nLemma inv_dprod_IirrK : cancel inv_dprod_Iirr dprod_Iirr.\n\n(*This lemma states that the inverse mapping of the trivial character index of the direct product group, which is zero, is the pair of trivial character indices of the component groups, which are both zero.*)\nLemma inv_dprod_Iirr0 : inv_dprod_Iirr 0 = (0, 0).\n\nEnd DProd.\n\nArguments dprod_Iirr_inj {gT G K H} KxH [i1 i2] : rename.\n\n(*This lemma states that for a finite group which is the internal direct product of two subgroups K and H, the index of an irreducible character constructed from a pair of character indices for the product K times H is the same as the index constructed from the reversed pair of indices for the product H times K.*)\nLemma dprod_IirrC (gT : finGroupType) (G K H : {group gT})\n (KxH : K \\x H = G) (HxK : H \\x K = G) i j :\n dprod_Iirr KxH (i, j) = dprod_Iirr HxK (j, i).\n\nSection BigDprod.\n\nVariables (gT : finGroupType) (I : finType) (P : pred I).\nVariables (A : I -> {group gT}) (G : {group gT}).\nHypothesis defG : \\big[dprod/1%g]_(i | P i) A i = G.\n\n(*This definition provides the embedding of an individual group from a family of groups into the larger group that is defined as their internal direct product.*)\nLet sAG i : P i -> A i \\subset G.\n\n(*This lemma states that inflating a class function from a component group to the entire direct product group preserves the property of being a character.*)\nLemma cfBigdprodi_char i (phi : 'CF(A i)) :\n phi \\is a character -> cfBigdprodi defG phi \\is a character.\n\n(*This lemma states that for any given component group in an internal direct product, the inflation of one of its class functions to the total group is a character if and only if the original class function is a character.*)\nLemma cfBigdprodi_charE i (phi : 'CF(A i)) :\n P i -> (cfBigdprodi defG phi \\is a character) = (phi \\is a character).\n\n(*This lemma states that the tensor product of a family of class functions, each defined on a component group of a direct product, is a character of the total group, provided that every class function in the family is itself a character.*)\nLemma cfBigdprod_char phi :\n (forall i, P i -> phi i \\is a character) ->\n cfBigdprod defG phi \\is a character.\n\n(*This lemma states that the inflation of a linear character from a component group to the entire direct product group results in a linear character on the total group.*)\nLemma cfBigdprodi_lin_char i (phi : 'CF(A i)) :\n phi \\is a linear_char -> cfBigdprodi defG phi \\is a linear_char.\n\n(*This lemma states that for any given component group in an internal direct product, the inflation of one of its class functions to the total group is a linear character if and only if the original class function is a linear character.*)\nLemma cfBigdprodi_lin_charE i (phi : 'CF(A i)) :\n P i -> (cfBigdprodi defG phi \\is a linear_char) = (phi \\is a linear_char).\n\n(*This lemma states that the tensor product of a family of linear characters, each defined on a component group of a direct product, is a linear character of the total group.*)\nLemma cfBigdprod_lin_char phi :\n (forall i, P i -> phi i \\is a linear_char) ->\n cfBigdprod defG phi \\is a linear_char.\n\n(*This lemma states that for any given component group in an internal direct product, the inflation of one of its class functions to the total group is an irreducible character if and only if the original class function is an irreducible character of the component group.*)\nLemma cfBigdprodi_irr i chi :\n P i -> (cfBigdprodi defG chi \\in irr G) = (chi \\in irr (A i)).\n\n(*This lemma states that the tensor product of a family of class functions is an irreducible character of the total group, provided that every class function in the family is an irreducible character of its corresponding component group.*)\nLemma cfBigdprod_irr chi :\n (forall i, P i -> chi i \\in irr (A i)) -> cfBigdprod defG chi \\in irr G.\n\n(*This lemma states that, given a family where each element is a character of a corresponding component group, their tensor product class function on the total group is equal to the principal character if and only if every character in the family is the principal character of its respective component group.*)\nLemma cfBigdprod_eq1 phi :\n (forall i, P i -> phi i \\is a character) ->\n (cfBigdprod defG phi == 1) = [forall (i | P i), phi i == 1].\n\n(*This lemma states that if a class function on a total group is a linear character, then it is equal to the tensor product of its restrictions to each of the component groups in the direct product.*)\nLemma cfBigdprod_Res_lin chi :\n chi \\is a linear_char -> cfBigdprod defG (fun i => 'Res[A i] chi) = chi.\n\n(*This lemma states that for a family of linear characters, the restriction of their tensor product character to any component group is equal to the original linear character for that component.*)\nLemma cfBigdprodKlin phi :\n (forall i, P i -> phi i \\is a linear_char) ->\n forall i, P i -> 'Res (cfBigdprod defG phi) = phi i.\n\n(*This lemma states that for an abelian group formed as an internal direct product, if a character is constructed as the tensor product of irreducible characters from each component group, its restriction to any given component group yields the original irreducible character for that component.*)\nLemma cfBigdprodKabelian Iphi (phi := fun i => 'chi_(Iphi i)) :\n abelian G -> forall i, P i -> 'Res (cfBigdprod defG phi) = 'chi_(Iphi i).\n\nEnd BigDprod.\n\nSection Aut.\n\nVariables (gT : finGroupType) (G : {group gT}).\nImplicit Type u : {rmorphism algC -> algC}.\n\n(*This lemma states that for any character of a finite group and any field automorphism of the complex numbers, the complex conjugate of the automorphic image of a character value is equal to the automorphic image of the complex conjugate of that character value.*)\nLemma conjC_charAut u (chi : 'CF(G)) x :\n chi \\is a character -> (u (chi x))^* = u (chi x)^*.\n\n(*This lemma states that for any irreducible character of a finite group and any field automorphism of the complex numbers, the complex conjugate of the automorphic image of a character value is equal to the automorphic image of the complex conjugate of that character value.*)\nLemma conjC_irrAut u i x : (u ('chi[G]_i x))^* = u ('chi_i x)^*.\n\n(*This lemma states that, provided one of the class functions is a character, the inner product of the automorphic images of two class functions is equal to the automorphic image of their original inner product.*)\nLemma cfdot_aut_char u (phi chi : 'CF(G)) :\n chi \\is a character -> '[cfAut u phi, cfAut u chi] = u '[phi, chi].\n\n(*This lemma states that the inner product of the automorphic image of a class function and the automorphic image of an irreducible character is equal to the automorphic image of their original inner product.*)\nLemma cfdot_aut_irr u phi i :\n '[cfAut u phi, cfAut u 'chi[G]_i] = u '[phi, 'chi_i].\n\n(*This lemma states that applying a field automorphism to the values of a class function preserves the property of being an irreducible character; the transformed function is an irreducible character if and only if the original was.*)\nLemma cfAut_irr u chi : (cfAut u chi \\in irr G) = (chi \\in irr G).\n\n(*This lemma states that the class function obtained by taking the complex conjugate of the values of an irreducible character is also an irreducible character.*)\nLemma cfConjC_irr i : (('chi_i)^%CF \\in irr G.\n\n(*This lemma states that the set of irreducible characters of a finite group is closed under the operation of applying a field automorphism to the character values.*)\nLemma irr_aut_closed u : cfAut_closed u (irr G).\n\n(*This definition provides the index of the irreducible character that results from applying a given field automorphism to the values of an existing irreducible character specified by its index.*)\nDefinition aut_Iirr u i := cfIirr (cfAut u 'chi[G]_i).\n\n(*This lemma states that the irreducible character identified by the transformed index computed by the aut_Iirr function is precisely the automorphic image of the original irreducible character at the given index.*)\nLemma aut_IirrE u i : 'chi_(aut_Iirr u i) = cfAut u 'chi_i.\n\n(*This definition provides the index of the irreducible character that is the complex conjugate of an existing irreducible character specified by its index.*)\nDefinition conjC_Iirr := aut_Iirr conjC.\n\n(*This lemma states that the irreducible character corresponding to the index transformed by complex conjugation is equal to the complex conjugate of the original irreducible character.*)\nLemma conjC_IirrE i : 'chi[G]_(conjC_Iirr i) = ('chi_i)^*%CF.\n\n(*This lemma states that the permutation on irreducible character indices induced by complex conjugation is involutive, meaning that applying it twice results in the identity permutation.*)\nLemma conjC_IirrK : involutive conjC_Iirr.\n\n(*This lemma states that the index of the principal character, which is zero, is a fixed point for the permutation of indices induced by any field automorphism.*)\nLemma aut_Iirr0 u : aut_Iirr u 0 = 0 :> Iirr G.\n\n(*This lemma states that the index of the principal character, which is zero, is a fixed point for the permutation of indices induced by complex conjugation.*)\nLemma conjC_Iirr0 : conjC_Iirr 0 = 0 :> Iirr G.\n\n(*This lemma states that the permutation of irreducible character indices induced by a field automorphism maps an index to zero if and only if that index was originally zero.*)\nLemma aut_Iirr_eq0 u i : (aut_Iirr u i == 0) = (i == 0).\n\n(*This lemma states that the permutation of irreducible character indices induced by complex conjugation maps an index to zero if and only if that index was originally zero.*)\nLemma conjC_Iirr_eq0 i : (conjC_Iirr i == 0 :> Iirr G) = (i == 0).\n\n(*This lemma states that the permutation of irreducible characters of a group induced by a group automorphism is an injective function.*)\nLemma aut_Iirr_inj u : injective (aut_Iirr u).\n\nEnd Aut.\n\nArguments aut_Iirr_inj {gT G} u [i1 i2] : rename.\nArguments conjC_IirrK {gT G} i : rename.\n\nSection Coset.\n\nVariable (gT : finGroupType).\n\nImplicit Types G H : {group gT}.\n\n(*This lemma states that if a given class function on a group is a character, then its restriction to a quotient group is also a character of the quotient group.*)\nLemma cfQuo_char G H (chi : 'CF(G)) :\n chi \\is a character -> (chi / H)%CF \\is a character.\n\n(*This lemma states that if a given class function on a group is a linear character, then its restriction to a quotient group is also a linear character of the quotient group.*)\nLemma cfQuo_lin_char G H (chi : 'CF(G)) :\n chi \\is a linear_char -> (chi / H)%CF \\is a linear_char.\n\n(*This lemma states that if a class function on a quotient group is a character, then its inflation to the parent group is also a character.*)\nLemma cfMod_char G H (chi : 'CF(G / H)) :\n chi \\is a character -> (chi %% H)%CF \\is a character.\n\n(*This lemma states that if a class function on a quotient group is a linear character, then its inflation to the parent group is also a linear character.*)\nLemma cfMod_lin_char G H (chi : 'CF(G / H)) :\n chi \\is a linear_char -> (chi %% H)%CF \\is a linear_char.\n\n(*This lemma states that for a normal subgroup, the inflation of a class function from the quotient group is a character if and only if the original class function is a character.*)\nLemma cfMod_charE G H (chi : 'CF(G / H)) :\n H <| G -> (chi %% H \\is a character)%CF = (chi \\is a character).\n\n(*This lemma states that for a normal subgroup, the inflation of a class function from the quotient group is a linear character if and only if the original class function is a linear character.*)\nLemma cfMod_lin_charE G H (chi : 'CF(G / H)) :\n H <| G -> (chi %% H \\is a linear_char)%CF = (chi \\is a linear_char).\n\n(*This lemma states that for a normal subgroup which is contained in the kernel of a class function on the parent group, the restriction of the class function to the quotient group is a character if and only if the original class function is a character.*)\nLemma cfQuo_charE G H (chi : 'CF(G)) :\n H <| G -> H \\subset cfker chi ->\n (chi / H \\is a character)%CF = (chi \\is a character).\n\n(*This lemma states that for a normal subgroup which is contained in the kernel of a class function on the parent group, the restriction of the class function to the quotient group is a linear character if and only if the original class function is a linear character.*)\nLemma cfQuo_lin_charE G H (chi : 'CF(G)) :\n H <| G -> H \\subset cfker chi ->\n (chi / H \\is a linear_char)%CF = (chi \\is a linear_char).\n\n(*This lemma states that for a normal subgroup, the inflation of a character from the quotient group is an irreducible character of the parent group if and only if the original character is an irreducible character of the quotient group.*)\nLemma cfMod_irr G H chi :\n H <| G -> (chi %% H \\in irr G)%CF = (chi \\in irr (G / H)).\n\n(*This definition provides a mapping from the index of an irreducible character of a quotient group to the index of the corresponding inflated irreducible character in the parent group.*)\nDefinition mod_Iirr G H i := cfIirr ('chi[G / H]_i %% H)%CF.\n\n(*This lemma states that the inflation of the trivial irreducible character of a quotient group results in the trivial irreducible character of the parent group.*)\nLemma mod_Iirr0 G H : mod_Iirr (0 : Iirr (G / H)) = 0.\n\n(*This lemma states that for a normal subgroup, the irreducible character of the parent group corresponding to the index obtained by inflating an irreducible character from the quotient group is equal to that inflated character.*)\nLemma mod_IirrE G H i : H <| G -> 'chi_(mod_Iirr i) = ('chi[G / H]_i %% H)%CF.\n\n(*This lemma states that for a normal subgroup, the inflation of an irreducible character from the quotient group yields the trivial character of the parent group if and only if the original character was the trivial character of the quotient group.*)\nLemma mod_Iirr_eq0 G H i :\n H <| G -> (mod_Iirr i == 0) = (i == 0 :> Iirr (G / H)).\n\n(*This lemma states that for a normal subgroup contained in the kernel of a character, the restriction of that character to the quotient group is an irreducible character if and only if the original character is an irreducible character of the parent group.*)\nLemma cfQuo_irr G H chi :\n H <| G -> H \\subset cfker chi ->\n ((chi / H)%CF \\in irr (G / H)) = (chi \\in irr G).\n\n(*This definition provides a mapping from the index of an irreducible character of a group to the index of the corresponding restricted character in a quotient group.*)\nDefinition quo_Iirr G H i := cfIirr ('chi[G]_i / H)%CF.\n\n(*This lemma states that restricting the trivial irreducible character of a group to a quotient group results in the trivial irreducible character of that quotient group.*)\nLemma quo_Iirr0 G H : quo_Iirr H (0 : Iirr G) = 0.\n\n(*This lemma states that for a normal subgroup contained in the kernel of an irreducible character, the irreducible character of the quotient group corresponding to the index obtained by restriction is equal to that restricted character.*)\nLemma quo_IirrE G H i :\n H <| G -> H \\subset cfker 'chi[G]_i -> 'chi_(quo_Iirr H i) = ('chi_i / H)%CF.\n\n(*This lemma states that for a normal subgroup contained in the kernel of an irreducible character, restricting the character to the quotient group yields the trivial character if and only if the original character was the trivial character of the parent group.*)\nLemma quo_Iirr_eq0 G H i :\n H <| G -> H \\subset cfker 'chi[G]_i -> (quo_Iirr H i == 0) = (i == 0).\n\n(*This lemma states that for a normal subgroup, the inflation map on irreducible characters is a left inverse to the restriction map on irreducible characters whose kernel contains the subgroup.*)\nLemma mod_IirrK G H : H <| G -> cancel (@mod_Iirr G H) (@quo_Iirr G H).\n\n(*This lemma states that for a normal subgroup contained in the kernel of an irreducible character, inflating the character after restricting it to the quotient group returns the original irreducible character.*)\nLemma quo_IirrK G H i :\n H <| G -> H \\subset cfker 'chi[G]_i -> mod_Iirr (quo_Iirr H i) = i.\n\n(*This lemma states that for a normal subgroup, inflating an irreducible character after restricting it to the quotient group yields the original character if and only if the subgroup is contained in the kernel of the original character.*)\nLemma quo_IirrKeq G H :\n H <| G ->\n forall i, (mod_Iirr (quo_Iirr H i) == i) = (H \\subset cfker 'chi[G]_i).\n\n(*This lemma states that for a normal subgroup, the inflation map establishes a bijection between the set of irreducible characters of the quotient group and the set of irreducible characters of the parent group whose kernel contains the subgroup.*)\nLemma mod_Iirr_bij H G :\n H <| G -> {on [pred i | H \\subset cfker 'chi_i], bijective (@mod_Iirr G H)}.\n\n(*This lemma states that for an element of a group and a normal subgroup, the sum of the squared norms of the values of all irreducible characters of the quotient group evaluated at the element's coset is equal to the sum of the squared norms of the values of all irreducible characters of the parent group whose kernel contains the subgroup, evaluated at that element.*)\nLemma sum_norm_irr_quo H G x :\n x \\in G -> H <| G ->\n \\sum_i `|'chi[G / H]_i (coset H x)| ^+ 2\n = \\sum_(i | H \\subset cfker 'chi_i) `|'chi[G]_i x| ^+ 2.\n\n(*This lemma states that for a normal subgroup, the intersection of the kernels of all irreducible characters of the parent group that contain the subgroup is equal to the subgroup itself.*)\nLemma cap_cfker_normal G H :\n H <| G -> \\bigcap_(i | H \\subset cfker 'chi[G]_i) (cfker 'chi_i) = H.\n\n(*This lemma states that for a normal subgroup, the kernel of the inflation of the regular character of the quotient group is equal to the subgroup itself.*)\nLemma cfker_reg_quo G H : H <| G -> cfker (cfReg (G / H)%g %% H) = H.\n\nEnd Coset.\n\nSection DerivedGroup.\n\nVariable gT : finGroupType.\nImplicit Types G H : {group gT}.\n\n(*This lemma states that an irreducible character of a group is a linear character if and only if its kernel contains the derived subgroup of the group.*)\nLemma lin_irr_der1 G i :\n ('chi_i \\is a linear_char) = (G^`(1)%g \\subset cfker 'chi[G]_i).\n\n(*This lemma states that an entire group is contained in the kernel of an irreducible character if and only if that character is the trivial character.*)\nLemma subGcfker G i : (G \\subset cfker 'chi[G]_i) = (i == 0).\n\n(*This lemma states that for a group of prime order, any non-trivial irreducible character is an injective function.*)\nLemma irr_prime_injP G i :\n prime #|G| -> reflect {in G &, injective 'chi[G]_i} (i != 0).\n\n(*This lemma states that the intersection of the kernels of all linear irreducible characters of a group is equal to the derived subgroup of that group.*)\nLemma cap_cfker_lin_irr G :\n \\bigcap_(i | 'chi[G]_i \\is a linear_char) (cfker 'chi_i) = G^`(1)%g.\n\n(*This lemma states that for a given finite group, the number of its irreducible characters that are also linear characters is equal to the index of its derived subgroup.*)\nLemma card_lin_irr G :\n #|[pred i | 'chi[G]_i \\is a linear_char]| = #|G : G^`(1)%g|.\n\n(*This lemma states that any non-trivial solvable finite group possesses a non-trivial linear character.*)\nLemma solvable_has_lin_char G :\n G :!=: 1%g -> solvable G ->\n exists2 i, 'chi[G]_i \\is a linear_char & 'chi_i != 1.\n\n(*This lemma asserts the existence of a finite group that is isomorphic to the group of linear characters of a given finite group. This isomorphism is established by a function that maps group elements to linear characters, preserving the group structure such as identity, products, powers, and inverses, and is also monotonic with respect to element orders.*)\nLemma lin_char_group G :\n {linG : finGroupType & {cF : linG -> 'CF(G) |\n [/\\ injective cF, #|linG| = #|G : G^`(1)|,\n forall u, cF u \\is a linear_char\n & forall phi, phi \\is a linear_char -> exists u, phi = cF u]\n & [/\\ cF 1%g = 1%R,\n {morph cF : u v / (u * v)%g >-> (u * v)%R},\n forall k, {morph cF : u / (u^+ k)%g >-> u ^+ k},\n {morph cF: u / u^-1%g >-> u^-1%CF}\n & {mono cF: u / #[u]%g >-> #[u]%CF} ]}}.\n\n(*This lemma states that for a finite group of prime order, any non-trivial irreducible character can be expressed as a power of any other non-trivial irreducible character, where the exponent is coprime to the order of the base character.*)\nLemma cfExp_prime_transitive G (i j : Iirr G) :\n prime #|G| -> i != 0 -> j != 0 ->\n exists2 k, coprime k #['chi_i]%CF & 'chi_j = 'chi_i ^+ k.\n\n(*This lemma states that for any element in a finite group and any normal subgroup, the size of the centralizer of the corresponding coset in the quotient group is less than or equal to the size of the centralizer of the element in the original group.*)\nLemma card_subcent1_coset G H x :\n x \\in G -> H <| G -> (#|'C_(G / H)[coset H x]| <= #|'C_G[x]|)%N.\n\nEnd DerivedGroup.\n\nArguments irr_prime_injP {gT G i}.\n\nSection DetRepr.\n\nVariables (gT : finGroupType) (G : {group gT}).\nVariables (n : nat) (rG : mx_representation algC G n).\n\n(*This definition constructs a one-dimensional matrix representation from a given matrix representation of a finite group by taking the determinant of the matrix associated with each group element.*)\nDefinition det_repr_mx x : 'M_1 := (\\det (rG x))%:M.\n\n(*This fact asserts that the function which maps each element of a finite group to the determinant of its matrix representation is itself a valid matrix representation.*)\nFact det_is_repr : mx_repr G det_repr_mx.\n\nCanonical det_repr := MxRepresentation det_is_repr.\n(*This definition provides the class function corresponding to the one-dimensional matrix representation obtained by taking the determinant of a given matrix representation.*)\nDefinition detRepr := cfRepr det_repr.\n\n(*This lemma states that the class function derived from the determinant of a matrix representation is a linear character.*)\nLemma detRepr_lin_char : detRepr \\is a linear_char.\n\nEnd DetRepr.\n\nHB.lock\n(*This definition computes the determinant of a given class function. It is defined as the product, taken over all irreducible representations, of the determinants of these irreducible representations, each raised to a power equal to the multiplicity of the corresponding irreducible character in the given class function.*)\nDefinition cfDet (gT : finGroupType) (G : {group gT}) phi :=\n \\prod_i detRepr 'Chi_i ^+ Num.truncn '[phi, 'chi[G]_i].\nCanonical cfDet_unlockable := Unlockable cfDet.unlock.\n\nSection DetOrder.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This definition specifies the determinant of a class function, which acts as a linear character. For a character associated with a representation, this determinant corresponds to the determinant of that representation.*)\nLocal Notation cfDet := (@cfDet gT G).\n\n(*This lemma states that the determinant of any class function is a linear character.*)\nLemma cfDet_lin_char phi : cfDet phi \\is a linear_char.\n\n(*This lemma states that the determinant of a sum of two characters is equal to the product of their individual determinants.*)\nLemma cfDetD :\n {in character &, {morph cfDet : phi psi / phi + psi >-> phi * psi}}.\n\n(*This lemma states that the determinant of the zero class function is the trivial character, which maps all group elements to one.*)\nLemma cfDet0 : cfDet 0 = 1.\n\n(*This lemma states that the determinant of a character multiplied by a natural number is equal to the determinant of the original character raised to the power of that natural number.*)\nLemma cfDetMn k :\n {in character, {morph cfDet : phi / phi *+ k >-> phi ^+ k}}.\n\n(*This lemma states that the determinant of the character associated with a matrix representation is equal to the character corresponding to the determinant of that representation.*)\nLemma cfDetRepr n rG : cfDet (cfRepr rG) = @detRepr _ _ n rG.\n\n(*This lemma states that if a class function is a linear character, then its determinant is the character itself.*)\nLemma cfDet_id xi : xi \\is a linear_char -> cfDet xi = xi.\n\n(*This definition specifies the order of the determinant of a class function, which is the multiplicative order of the resulting linear character.*)\nDefinition cfDet_order phi := #[cfDet phi]%CF.\n\n(*This definition states that for a linear character, its determinant order is simply its own multiplicative order.*)\nDefinition cfDet_order_lin xi :\n xi \\is a linear_char -> cfDet_order xi = #[xi]%CF.\n\n(*This definition states that the order of the determinant of a class function over a finite group divides the order of that group.*)\nDefinition cfDet_order_dvdG phi : cfDet_order phi %| #|G|.\n\nEnd DetOrder.\n\n(*This notation provides a shorthand for the order of the determinant of a class function.*)\nNotation \"''o' ( phi )\" := (cfDet_order phi)\n (at level 8, format \"''o' ( phi )\") : cfun_scope.\n\nSection CfDetOps.\n\nImplicit Types gT aT rT : finGroupType.\n\n(*This lemma states that for a character of a group, the determinant of its restriction to a subgroup is equal to the restriction of its determinant to that subgroup.*)\nLemma cfDetRes gT (G H : {group gT}) phi :\n phi \\is a character -> cfDet ('Res[H, G] phi) = 'Res (cfDet phi).\n\n(*This lemma states that for a character defined on the image of a group morphism, the determinant of the lifted character is equal to the lift of the character's determinant.*)\nLemma cfDetMorph aT rT (D G : {group aT}) (f : {morphism D >-> rT})\n (phi : 'CF(f @* G)) :\n phi \\is a character -> cfDet (cfMorph phi) = cfMorph (cfDet phi).\n\n(*This lemma states that transferring a character across a group isomorphism and then taking its determinant yields the same result as taking the determinant first and then transferring it across the isomorphism.*)\nLemma cfDetIsom aT rT (G : {group aT}) (R : {group rT})\n (f : {morphism G >-> rT}) (isoGR : isom G R f) phi :\n cfDet (cfIsom isoGR phi) = cfIsom isoGR (cfDet phi).\n\n(*This lemma states that the determinant of the product of a linear character and another character is equal to the product of two terms: the linear character raised to the power of the degree of the second character, and the determinant of the second character.*)\nLemma cfDet_mul_lin gT (G : {group gT}) (lambda phi : 'CF(G)) :\n lambda \\is a linear_char -> phi \\is a character ->\n cfDet (lambda * phi) = lambda ^+ Num.truncn (phi 1%g) * cfDet phi.\n\nEnd CfDetOps.\n\n(*This definition specifies the center of a class function. For a character, it is the set of group elements for which the absolute value of the character's value is equal to the character's degree. For a non-character class function, it defaults to the character's kernel.*)\nDefinition cfcenter (gT : finGroupType) (G : {set gT}) (phi : 'CF(G)) :=\n if phi \\is a character then [set g in G | `|phi g| == phi 1%g] else cfker phi.\n\n(*This notation provides a shorthand for the center of a class function.*)\nNotation \"''Z' ( phi )\" := (cfcenter phi) : cfun_scope.\n\nSection Center.\n\nVariable (gT : finGroupType) (G : {group gT}).\nImplicit Types (phi chi : 'CF(G)) (H : {group gT}).\n\n(*This lemma states that the center of the character associated with a matrix representation is equal to the center of the representation itself.*)\nLemma cfcenter_repr n (rG : mx_representation algC G n) :\n 'Z(cfRepr rG)%CF = rcenter rG.\n\n(*This fact states that the center of a class function forms a group.*)\nFact cfcenter_group_set phi : group_set ('Z(phi))%CF.\n\nCanonical cfcenter_group f := Group (cfcenter_group_set f).\n\n(*This lemma provides an explicit condition for an element of a group to be in the center of a character: its membership is equivalent to the absolute value of the character at that element being equal to the character's degree.*)\nLemma char_cfcenterE chi x :\n chi \\is a character -> x \\in G ->\n (x \\in ('Z(chi))%CF) = (`|chi x| == chi 1%g).\n\n(*This lemma provides an explicit condition for a group element to be in the center of an irreducible character: its membership is equivalent to the absolute value of the character at that element being equal to the character's degree.*)\nLemma irr_cfcenterE i x :\n x \\in G -> (x \\in 'Z('chi[G]_i)%CF) = (`|'chi_i x| == 'chi_i 1%g).\n\n(*This lemma states that the center of a class function is a subset of the underlying group.*)\nLemma cfcenter_sub phi : ('Z(phi))%CF \\subset G.\n\n(*This lemma states that the kernel of a class function is a normal subgroup of the center of that same class function.*)\nLemma cfker_center_normal phi : cfker phi <| 'Z(phi)%CF.\n\n(*This lemma states that the center of a class function is a normal subgroup of the containing group.*)\nLemma cfcenter_normal phi : 'Z(phi)%CF <| G.\n\n(*This lemma states that the restriction of a character to its own center is equal to the product of the character's degree and some linear character defined on that center.*)\nLemma cfcenter_Res chi :\n exists2 chi1, chi1 \\is a linear_char & 'Res['Z(chi)%CF] chi = chi 1%g *: chi1.\n\n(*This lemma states that the quotient group formed by the center of a character and its kernel is a cyclic group.*)\nLemma cfcenter_cyclic chi : cyclic ('Z(chi)%CF / cfker chi)%g.\n\n(*This lemma states that the quotient of the center of a character by its kernel is a subgroup of the center of the quotient of the original group by the character's kernel.*)\nLemma cfcenter_subset_center chi :\n ('Z(chi)%CF / cfker chi)%g \\subset 'Z(G / cfker chi)%g.\n\n(*This lemma states that for an irreducible character, the quotient of its center by its kernel is equal to the center of the quotient of the group by the character's kernel.*)\nLemma cfcenter_eq_center (i : Iirr G) :\n ('Z('chi_i)%CF / cfker 'chi_i)%g = 'Z(G / cfker 'chi_i)%g.\n\n(*This lemma states that the intersection of the centers of all irreducible characters of a group is equal to the center of the group itself.*)\nLemma cap_cfcenter_irr : \\bigcap_i 'Z('chi[G]_i)%CF = 'Z(G).\n\n(*This lemma provides a condition establishing an inequality involving the norm of a class function when it is restricted to a subgroup.*)\nLemma cfnorm_Res_leif H phi :\n H \\subset G ->\n '['Res[H] phi] <= #|G : H|%:R * '[phi] ?= iff (phi \\in 'CF(G, H)).\n\n(*This lemma states that for any irreducible character of a finite group, the square of its degree is less than or equal to the index of the character's center subgroup in the group. It also provides a condition for when this inequality becomes an equality, which is if and only if the character is constant on the cosets of its center.*)\nLemma irr1_bound (i : Iirr G) :\n ('chi_i 1%g) ^+ 2 <= #|G : 'Z('chi_i)%CF|%:R\n ?= iff ('chi_i \\in 'CF(G, 'Z('chi_i)%CF)).\n\n(*This lemma states that for an irreducible character of a finite group, if the quotient of the group by the character's center subgroup is abelian, then the square of the character's degree is equal to the index of its center subgroup.*)\nLemma irr1_abelian_bound (i : Iirr G) :\n abelian (G / 'Z('chi_i)%CF) -> ('chi_i 1%g) ^+ 2 = #|G : 'Z('chi_i)%CF|%:R.\n\n(*This lemma states that if a finite group possesses a faithful irreducible character, then the center of that group must be a cyclic group.*)\nLemma irr_faithful_center i : cfaithful 'chi[G]_i -> cyclic 'Z(G).\n\n(*This lemma states that for any faithful irreducible character of a finite group, the character's center subgroup is equal to the center of the group.*)\nLemma cfcenter_fful_irr i : cfaithful 'chi[G]_i -> 'Z('chi_i)%CF = 'Z(G).\n\n(*This lemma states that for any p-group with a cyclic center, where p is a prime number, there exists at least one faithful irreducible character.*)\nLemma pgroup_cyclic_faithful (p : nat) :\n p.-group G -> cyclic 'Z(G) -> exists i, cfaithful 'chi[G]_i.\n\nEnd Center.\n\nSection Induced.\n\nVariables (gT : finGroupType) (G H : {group gT}).\nImplicit Types (phi : 'CF(G)) (chi : 'CF(H)).\n\n(*This lemma states that if a class function on a subgroup is a character, then the class function induced on the parent group is also a character.*)\nLemma cfInd_char chi : chi \\is a character -> 'Ind[G] chi \\is a character.\n\n(*This lemma states that for a character of a subgroup, the character induced on the parent group is the zero character if and only if the original character on the subgroup was the zero character.*)\nLemma cfInd_eq0 chi :\n H \\subset G -> chi \\is a character -> ('Ind[G] chi == 0) = (chi == 0).\n\n(*This lemma states that inducing an irreducible character from a subgroup to a parent group always results in a non-zero character on the parent group.*)\nLemma Ind_irr_neq0 i : H \\subset G -> 'Ind[G, H] 'chi_i != 0.\n\n(*This definition provides a shorthand for the character obtained by inducing an irreducible character from a subgroup to a parent group, specifically for cases where the resulting induced character is also known to be irreducible.*)\nDefinition Ind_Iirr (A B : {set gT}) i := cfIirr ('Ind[B, A] 'chi_i).\n\n(*This lemma asserts the existence of at least one irreducible constituent for the character that results from restricting an irreducible character of a group to one of its subgroups.*)\nLemma constt_cfRes_irr i : {j | j \\in irr_constt ('Res[H, G] 'chi_i)}.\n\n(*This lemma asserts the existence of at least one irreducible constituent for the character that is induced on a group from an irreducible character of one of its subgroups.*)\nLemma constt_cfInd_irr i :\n H \\subset G -> {j | j \\in irr_constt ('Ind[G, H] 'chi_i)}.\n\n(*This lemma states that for any character of a group, the kernel of its restriction to a subgroup is equal to the intersection of that subgroup with the kernel of the original character.*)\nLemma cfker_Res phi :\n H \\subset G -> phi \\is a character -> cfker ('Res[H] phi) = H :&: cfker phi.\n\n(*This lemma states that for any non-zero character of a subgroup, the kernel of the character induced on the parent group is equal to the largest normal subgroup of the parent group that is contained within the kernel of the original character.*)\nLemma cfker_Ind chi :\n H \\subset G -> chi \\is a character -> chi != 0 ->\n cfker ('Ind[G, H] chi) = gcore (cfker chi) G.\n\n(*This lemma states that the kernel of a character induced from an irreducible character of a subgroup to a larger group is equal to the core of the original character's kernel within the larger group.*)\nLemma cfker_Ind_irr i :\n H \\subset G -> cfker ('Ind[G, H] 'chi_i) = gcore (cfker 'chi_i) G.\n\nEnd Induced.", - "character.mxrepresentation": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div choice fintype tuple finfun bigop prime.\nFrom mathcomp Require Import ssralg poly polydiv finset fingroup morphism.\nFrom mathcomp Require Import perm automorphism quotient finalg action zmodp.\nFrom mathcomp Require Import commutator cyclic center pgroup matrix mxalgebra.\nFrom mathcomp Require Import mxalgebra mxpoly.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope irrType_scope.\nDeclare Scope group_ring_scope.\n\nImport GroupScope GRing.Theory.\nLocal Open Scope ring_scope.\n\nReserved Notation \"''n_' i\" (at level 8, i at level 2, format \"''n_' i\").\nReserved Notation \"''R_' i\" (at level 8, i at level 2, format \"''R_' i\").\nReserved Notation \"''e_' i\" (at level 8, i at level 2, format \"''e_' i\").\n\nDelimit Scope irrType_scope with irr.\n\nSection RingRepr.\n\nVariable R : comUnitRingType.\n\nSection OneRepresentation.\n\nVariable gT : finGroupType.\n\n(*This definition specifies the properties of a matrix representation of a group. A function from a group to a set of square matrices qualifies as a matrix representation if it maps the group's identity element to the identity matrix and preserves the group's multiplication operation for all elements within a given subset of the group, meaning the matrix of a product of two group elements is the matrix product of their respective matrices.*)\nDefinition mx_repr (G : {set gT}) n (r : gT -> 'M[R]_n) :=\n r 1%g = 1%:M /\\ {in G &, {morph r : x y / (x * y)%g >-> x *m y}}.\n\n(*This structure defines a matrix representation of a group. It encapsulates a function mapping group elements to square matrices, along with the proof that this function correctly represents the group structure.*)\nStructure mx_representation G n :=\n MxRepresentation { repr_mx :> gT -> 'M_n; _ : mx_repr G repr_mx }.\n\nVariables (G : {group gT}) (n : nat) (rG : mx_representation G n).\nArguments rG _%_group_scope : extra scopes.\n\n(*This lemma states that a matrix representation of a group maps the group's identity element to the identity matrix.*)\nLemma repr_mx1 : rG 1 = 1%:M.\n\n(*This lemma states that for any two elements in the group, applying the matrix representation to their product is equivalent to multiplying the matrices of the individual representations.*)\nLemma repr_mxM : {in G &, {morph rG : x y / (x * y)%g >-> x *m y}}.\n\n(*This lemma states that for any element in the group, left-multiplication of a matrix by the representation of that element can be cancelled by left-multiplying with the representation of its inverse.*)\nLemma repr_mxK m x :\n x \\in G -> cancel ((@mulmx R m n n)^~ (rG x)) (mulmx^~ (rG x^-1)).\n\n(*This lemma states that for any element in the group, left-multiplication of a matrix by the representation of its inverse can be cancelled by left-multiplying with the representation of the original element.*)\nLemma repr_mxKV m x :\n x \\in G -> cancel ((@mulmx R m n n)^~ (rG x^-1)) (mulmx^~ (rG x)).\n\n(*This lemma states that the matrix corresponding to any element of the group under a given representation is an invertible matrix.*)\nLemma repr_mx_unit x : x \\in G -> rG x \\in unitmx.\n\n(*This lemma states that for any element in the group, the matrix representation of its inverse is equal to the matrix inverse of its representation.*)\nLemma repr_mxV : {in G, {morph rG : x / x^-1%g >-> invmx x}}.\n\n(*This definition constructs a matrix by stacking the vectorized forms of the matrix representations of each element of a finite group. Each row of the resulting matrix corresponds to the flattened matrix representation of one group element.*)\nDefinition enveloping_algebra_mx := \\matrix_(i < #|G|) mxvec (rG (enum_val i)).\n\nSection Stabiliser.\n\nVariables (m : nat) (U : 'M[R]_(m, n)).\n\n(*This definition creates the stabilizer set of a given matrix under a group's matrix representation. The set contains all group elements whose corresponding matrix representation, when right-multiplied with the given matrix, leaves the matrix unchanged.*)\nDefinition rstab := [set x in G | U *m rG x == U].\n\n(*This lemma states that the stabilizer set of a matrix under a representation is a subset of the original group.*)\nLemma rstab_sub : rstab \\subset G.\n\n(*This lemma states that the stabilizer set of a matrix under a group representation forms a group.*)\nLemma rstab_group_set : group_set rstab.\n\nCanonical rstab_group := Group rstab_group_set.\n\nEnd Stabiliser.\n\nSection CentHom.\n\nVariable f : 'M[R]_n.\n\n(*This definition creates the centralizer set of a given matrix with respect to a group's matrix representation. The set contains all group elements whose corresponding matrix representation commutes with the given matrix.*)\nDefinition rcent := [set x in G | f *m rG x == rG x *m f].\n\n(*This lemma states that the centralizer set of a matrix with respect to a group representation is a subset of the original group.*)\nLemma rcent_sub : rcent \\subset G.\n\n(*This lemma states that the centralizer set of a matrix with respect to a group representation forms a group.*)\nLemma rcent_group_set : group_set rcent.\n\nCanonical rcent_group := Group rcent_group_set.\n\n(*This definition expresses the property that a given matrix commutes with the matrix representation of every element in the group.*)\nDefinition centgmx := G \\subset rcent.\n\n(*This lemma provides a reflection between a boolean property and the logical proposition that a given matrix commutes with the matrix representation of every element in the group.*)\nLemma centgmxP : reflect (forall x, x \\in G -> f *m rG x = rG x *m f) centgmx.\n\nEnd CentHom.\n\n(*This definition defines the kernel of a matrix representation as the set of group elements that are mapped to the identity matrix.*)\nDefinition rker := rstab 1%:M.\nCanonical rker_group := Eval hnf in [group of rker].\n\n(*This lemma provides a reflection between a boolean property and the logical proposition that a group element belongs to the kernel of a representation, which holds if the element is in the group and its representation is the identity matrix.*)\nLemma rkerP x : reflect (x \\in G /\\ rG x = 1%:M) (x \\in rker).\n\n(*This lemma states that the entire group is contained within the normalizer of the kernel of its matrix representation.*)\nLemma rker_norm : G \\subset 'N(rker).\n\n(*This lemma states that the kernel of a group's matrix representation is a normal subgroup of that group.*)\nLemma rker_normal : rker <| G.\n\n(*This definition specifies that a matrix representation is faithful if its kernel consists solely of the group's identity element.*)\nDefinition mx_faithful := rker \\subset [1].\n\n(*This lemma states that if a matrix representation is faithful, then the function mapping group elements to matrices is injective on the group.*)\nLemma mx_faithful_inj : mx_faithful -> {in G &, injective rG}.\n\n(*This lemma states that for a one-dimensional matrix representation, the commutator subgroup of the group is contained within the kernel of the representation.*)\nLemma rker_linear : n = 1 -> G^`(1)%g \\subset rker.\n\n(*This definition identifies the center of a group representation as the set of group elements whose corresponding matrix representation is a scalar matrix.*)\nDefinition rcenter := [set g in G | is_scalar_mx (rG g)].\n\n(*This fact states that the center of a group representation forms a group.*)\nFact rcenter_group_set : group_set rcenter.\n\nCanonical rcenter_group := Group rcenter_group_set.\n\n(*This lemma states that the center of a group representation is a normal subgroup of the original group.*)\nLemma rcenter_normal : rcenter <| G.\n\nEnd OneRepresentation.\n\nArguments rkerP {gT G n rG x}.\n\nSection Proper.\n\nVariables (gT : finGroupType) (G : {group gT}) (n' : nat).\n(*This notation defines `n` as the successor of a natural number, which is a common way to represent a positive natural number.*)\nLocal Notation n := n'.+1.\nVariable rG : mx_representation G n.\n\n(*This lemma states that for any two elements in the group, the matrix representation of their group product is equal to the matrix product of their individual representations.*)\nLemma repr_mxMr : {in G &, {morph rG : x y / (x * y)%g >-> x * y}}.\n\n(*This lemma states that for any element in the group, the matrix representation of its group inverse is equal to the matrix inverse of its representation.*)\nLemma repr_mxVr : {in G, {morph rG : x / (x^-1)%g >-> x^-1}}.\n\n(*This lemma states that for any element of a group, its image under a given matrix representation is an invertible matrix.*)\nLemma repr_mx_unitr x : x \\in G -> rG x \\is a GRing.unit.\n\n(*This lemma states that for any group element, a given matrix representation maps the conjugation of that element by another element to the conjugation of their respective matrix images.*)\nLemma repr_mxX m : {in G, {morph rG : x / (x ^+ m)%g >-> x ^+ m}}.\n\nEnd Proper.\n\nSection ChangeGroup.\n\nVariables (gT : finGroupType) (G H : {group gT}) (n : nat).\nVariables (rG : mx_representation G n).\n\nSection SubGroup.\n\nHypothesis sHG : H \\subset G.\n\n(*This lemma states that a matrix representation of a group can also serve as a matrix representation for any of its subgroups.*)\nLemma subg_mx_repr : mx_repr H rG.\n\n(*This definition creates a formal matrix representation for a subgroup by restricting the matrix representation of its parent group.*)\nDefinition subg_repr := MxRepresentation subg_mx_repr.\n(*This notation provides a local alias for the matrix representation of a subgroup, which is derived from the representation of its parent group.*)\nLocal Notation rH := subg_repr.\n\n(*This lemma states that the centralizer of a given set of matrices with respect to a subgroup's representation is the intersection of the subgroup itself with the centralizer of the same set of matrices with respect to the parent group's representation.*)\nLemma rcent_subg U : rcent rH U = H :&: rcent rG U.\n\nSection Stabiliser.\n\nVariables (m : nat) (U : 'M[R]_(m, n)).\n\n(*This lemma states that the stabilizer of a given matrix under a subgroup's representation is the intersection of the subgroup itself with the stabilizer of the same matrix under the parent group's representation.*)\nLemma rstab_subg : rstab rH U = H :&: rstab rG U.\n\nEnd Stabiliser.\n\n(*This lemma states that the kernel of a subgroup's representation is the intersection of the subgroup itself with the kernel of the parent group's representation.*)\nLemma rker_subg : rker rH = H :&: rker rG. \n\n(*This lemma states that if a matrix representation of a group is faithful, then its restriction to any subgroup is also a faithful representation.*)\nLemma subg_mx_faithful : mx_faithful rG -> mx_faithful rH.\n\nEnd SubGroup.\n\nSection SameGroup.\n\nHypothesis eqGH : G :==: H.\n\n(*This lemma states that if two groups are equal as sets, then the second group is a subset of the first group.*)\nLemma eqg_repr_proof : H \\subset G. \n\n(*This definition creates a matrix representation for a group by considering it as a subgroup of an identical group, which allows for the reuse of the subgroup representation constructor.*)\nDefinition eqg_repr := subg_repr eqg_repr_proof.\n(*A local definition for a matrix representation of a group, constructed by re-interpreting a representation of another group under the premise that the two groups are identical.*)\nLocal Notation rH := eqg_repr.\n\n(*This lemma states that for two groups that are equal, the centralizer of a given matrix with respect to the matrix representation of the first group is identical to the centralizer of the same matrix with respect to the matrix representation of the second group.*)\nLemma rcent_eqg U : rcent rH U = rcent rG U.\n\nSection Stabiliser.\n\nVariables (m : nat) (U : 'M[R]_(m, n)).\n\n(*This lemma states that if two groups are equal, the stabilizer of a given matrix under the action of the first group's matrix representation is the same as the stabilizer under the second group's representation.*)\nLemma rstab_eqg : rstab rH U = rstab rG U.\n\nEnd Stabiliser.\n\n(*This lemma states that the kernel of the matrix representation of a group is equal to the kernel of the representation of another group, provided the two groups are the same.*)\nLemma rker_eqg : rker rH = rker rG. \n\n(*This lemma states that a matrix representation of a group is faithful if and only if the matrix representation of an equal group is also faithful.*)\nLemma eqg_mx_faithful : mx_faithful rH = mx_faithful rG.\n\nEnd SameGroup.\n\nEnd ChangeGroup.\n\nSection Morphpre.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\nVariables (G : {group rT}) (n : nat) (rG : mx_representation G n).\n\n(*This lemma states that composing a matrix representation of a group with a group morphism results in a valid matrix representation for the preimage group.*)\nLemma morphpre_mx_repr : mx_repr (f @*^-1 G) (rG \\o f).\n\nCanonical morphpre_repr := MxRepresentation morphpre_mx_repr.\n(*This notation refers to the matrix representation of the preimage of a group under a group morphism. This representation is constructed by composing the original group's representation with the morphism.*)\nLocal Notation rGf := morphpre_repr.\n\nSection Stabiliser.\n\nVariables (m : nat) (U : 'M[R]_(m, n)).\n\n(*This lemma states that the stabilizer of a matrix under a representation of a preimage group is equal to the preimage, under the corresponding group morphism, of the stabilizer of the same matrix under the original group's representation.*)\nLemma rstab_morphpre : rstab rGf U = f @*^-1 (rstab rG U).\n\nEnd Stabiliser.\n\n(*This lemma states that the kernel of a matrix representation of a preimage group is the preimage, under the corresponding group morphism, of the kernel of the original group's representation.*)\nLemma rker_morphpre : rker rGf = f @*^-1 (rker rG).\n\nEnd Morphpre.\n\nSection Morphim.\n\nVariables (aT rT : finGroupType) (G D : {group aT}) (f : {morphism D >-> rT}).\nVariables (n : nat) (rGf : mx_representation (f @* G) n).\n\n(*This definition describes a function that constructs a matrix representation for a subgroup. It operates by taking an element from the subgroup, mapping it to its image in another group via a given morphism, and then applying the matrix representation defined on that image group.*)\nDefinition morphim_mx of G \\subset D := fun x => rGf (f x).\n\nHypothesis sGD : G \\subset D.\n\n(*This lemma asserts that applying the matrix representation constructed for a subgroup to one of its elements is equivalent to first mapping the element to its image via a group morphism and then applying the representation of the image group.*)\nLemma morphim_mxE x : morphim_mx sGD x = rGf (f x). \n\n(*This lemma states that for any function, a given group is a subset of the preimage of its image under that function.*)\nLet sG_f'fG : G \\subset f @*^-1 (f @* G).\n\n(*This lemma states that the function constructed by mapping a subgroup's elements to their images and then applying a representation of the image group constitutes a valid matrix representation for the original subgroup.*)\nLemma morphim_mx_repr : mx_repr G (morphim_mx sGD).\n\nCanonical morphim_repr := MxRepresentation morphim_mx_repr.\n(*This notation refers to a matrix representation of a group that is derived from a representation of its image under a group morphism.*)\nLocal Notation rG := morphim_repr.\n\nSection Stabiliser.\nVariables (m : nat) (U : 'M[R]_(m, n)).\n\n(*This lemma states that the stabilizer of a matrix, under a representation derived from an image group, is the intersection of the original group with the preimage of the stabilizer in the image group's representation.*)\nLemma rstab_morphim : rstab rG U = G :&: f @*^-1 rstab rGf U.\n\nEnd Stabiliser.\n\n(*This lemma states that the kernel of a group representation derived from its image is the intersection of the group itself with the preimage of the kernel of the image representation.*)\nLemma rker_morphim : rker rG = G :&: f @*^-1 (rker rGf).\n\nEnd Morphim.\n\nSection Conjugate.\n\nVariables (gT : finGroupType) (G : {group gT}) (n : nat).\nVariables (rG : mx_representation G n) (B : 'M[R]_n).\n\n(*This definition describes a function that creates a new matrix representation by conjugating an existing representation with a given invertible matrix.*)\nDefinition rconj_mx of B \\in unitmx := fun x => B *m rG x *m invmx B.\n\nHypothesis uB : B \\in unitmx.\n\n(*This lemma states that conjugating a valid matrix representation of a group by an invertible matrix yields another valid matrix representation for the same group.*)\nLemma rconj_mx_repr : mx_repr G (rconj_mx uB).\n\nCanonical rconj_repr := MxRepresentation rconj_mx_repr.\n(*This notation refers to the matrix representation obtained by conjugating an existing matrix representation with an invertible matrix.*)\nLocal Notation rGB := rconj_repr.\n\n(*This lemma asserts that applying a conjugate matrix representation to a group element is equivalent to taking the original representation's matrix for that element and conjugating it by the specified invertible matrix.*)\nLemma rconj_mxE x : rGB x = B *m rG x *m invmx B.\n\n(*This lemma provides a computational rule stating that for any given matrix, left-multiplying by it the result of a conjugate representation and then right-multiplying by the conjugating matrix is equivalent to first right-multiplying the given matrix by the conjugating matrix and then left-multiplying by the result of the original representation.*)\nLemma rconj_mxJ m (W : 'M_(m, n)) x : W *m rGB x *m B = W *m B *m rG x.\n\n(*This lemma states that the centralizer of a matrix under a conjugate representation is equal to the centralizer, under the original representation, of that matrix after it has been conjugated by the inverse of the conjugating matrix.*)\nLemma rcent_conj A : rcent rGB A = rcent rG (invmx B *m A *m B).\n\n(*This lemma states that the stabilizer of a matrix under a conjugate representation is equal to the stabilizer, under the original representation, of the matrix that results from right-multiplying the original matrix by the conjugating matrix.*)\nLemma rstab_conj m (U : 'M_(m, n)) : rstab rGB U = rstab rG (U *m B).\n\n(*This lemma states that the kernel of a matrix representation is unchanged by conjugation with an invertible matrix.*)\nLemma rker_conj : rker rGB = rker rG.\n\n(*This lemma states that a conjugate matrix representation is faithful if and only if the original matrix representation is faithful.*)\nLemma conj_mx_faithful : mx_faithful rGB = mx_faithful rG.\n\nEnd Conjugate.\n\nSection Quotient.\n\nVariables (gT : finGroupType) (G : {group gT}) (n : nat).\nVariable rG : mx_representation G n.\n\n(*This definition describes a function that constructs a matrix representation for a quotient group. It maps a coset to the matrix representation of any of its representative elements, under the condition that the normal subgroup used for the quotient is contained within the kernel of the original representation.*)\nDefinition quo_mx (H : {set gT}) of H \\subset rker rG & G \\subset 'N(H) :=\n fun Hx : coset_of H => rG (repr Hx).\n\nSection SubQuotient.\n\nVariable H : {group gT}.\nHypotheses (krH : H \\subset rker rG) (nHG : G \\subset 'N(H)).\n(*This definition creates a propositional version of a boolean predicate that determines membership in a subset of a group.*)\nLet nHGs := subsetP nHG.\n\n(*This lemma states that applying the quotient group representation to a coset containing a specific group element yields the same matrix as applying the original group's representation directly to that element.*)\nLemma quo_mx_coset x : x \\in G -> quo_mx krH nHG (coset H x) = rG x.\n\n(*This lemma states that the function mapping cosets to the matrix representation of their representatives forms a valid matrix representation for the quotient group.*)\nLemma quo_mx_repr : mx_repr (G / H)%g (quo_mx krH nHG).\n\nCanonical quo_repr := MxRepresentation quo_mx_repr.\n(*This notation refers to the matrix representation of a quotient group, induced by the matrix representation of the original group.*)\nLocal Notation rGH := quo_repr.\n\n(*This lemma states that for any element in the group, the matrix representation of its corresponding coset in the quotient group is equal to the original matrix representation of that element.*)\nLemma quo_repr_coset x : x \\in G -> rGH (coset H x) = rG x.\n\n(*This lemma states that the centralizer of a set of matrices with respect to the matrix representation of a quotient group is equal to the quotient group formed by the centralizer of the same set with respect to the original group representation and the normalizer subgroup.*)\nLemma rcent_quo A : rcent rGH A = (rcent rG A / H)%g.\n\n(*This lemma states that the stabilizer of a matrix with respect to the matrix representation of a quotient group is equal to the quotient group formed by the stabilizer of the same matrix with respect to the original group representation and the normalizer subgroup.*)\nLemma rstab_quo m (U : 'M_(m, n)) : rstab rGH U = (rstab rG U / H)%g.\n\n(*This lemma states that the kernel of a matrix representation of a quotient group is equal to the quotient group formed by the kernel of the original group representation and the normalizer subgroup.*)\nLemma rker_quo : rker rGH = (rker rG / H)%g.\n\nEnd SubQuotient.\n\n(*This definition creates the matrix representation for the quotient group formed by dividing the original group by the kernel of its given matrix representation.*)\nDefinition kquo_mx := quo_mx (subxx (rker rG)) (rker_norm rG).\n(*This lemma states the definitional equality of the kernel quotient matrix representation, which itself is the matrix representation for the quotient group formed by dividing the original group by the kernel of its given matrix representation.*)\nLemma kquo_mxE : kquo_mx = quo_mx (subxx (rker rG)) (rker_norm rG).\n\nCanonical kquo_repr := @MxRepresentation _ _ _ kquo_mx (quo_mx_repr _ _).\n\n(*This lemma states that for an element in the group, its matrix representation is equal to the matrix representation of its corresponding coset in the quotient group formed by the kernel of the original representation.*)\nLemma kquo_repr_coset x :\n x \\in G -> kquo_repr (coset (rker rG) x) = rG x.\n\n(*This lemma states that the matrix representation of a group quotiented by its representation kernel is faithful, meaning that distinct elements of the quotient group are mapped to distinct matrices.*)\nLemma kquo_mx_faithful : mx_faithful kquo_repr.\n\nEnd Quotient.\n\nSection Regular.\n\nVariables (gT : finGroupType) (G : {group gT}).\n(*This definition assigns the name 'gcard' to the cardinality, or number of elements, of the group.*)\nDefinition gcard := #|G|. \n(*This notation provides a shorthand for the cardinality of the group.*)\nLocal Notation nG := gcard.\n\n(*This definition provides a unique natural number index for each element of the group, corresponding to its position in a canonical enumeration of the group's elements.*)\nDefinition gring_index (x : gT) := enum_rank_in (group1 G) x.\n\n(*This lemma states that retrieving the group element corresponding to a given index, where the index was obtained from that same group element, yields the original element.*)\nLemma gring_valK : cancel enum_val gring_index.\n\n(*This lemma states that for any valid index corresponding to a group element, retrieving the element at that index and then computing its index results in the original index.*)\nLemma gring_indexK : {in G, cancel gring_index enum_val}.\n\n(*This definition constructs the matrix for the right regular representation of a group element. The resulting square matrix has a size equal to the group's cardinality, and its entries are such that a one appears at a given row and column if the group element for that column is the product of the group element for that row and the input element, and zero otherwise.*)\nDefinition regular_mx x : 'M[R]_nG :=\n \\matrix_i delta_mx 0 (gring_index (enum_val i * x)).\n\n(*This lemma formalizes that the function which maps each group element to its regular representation matrix is a valid matrix representation, meaning it respects the group's multiplication structure.*)\nLemma regular_mx_repr : mx_repr G regular_mx.\n\nCanonical regular_repr := MxRepresentation regular_mx_repr.\n(*This notation provides a shorthand for the canonical structure of the regular matrix representation of the group.*)\nLocal Notation aG := regular_repr.\n\n(*This definition constructs the group ring as the enveloping algebra of the group's regular matrix representation, which consists of all linear combinations of the representation matrices with coefficients from the base ring.*)\nDefinition group_ring := enveloping_algebra_mx aG.\n(*This notation provides a shorthand for the group ring constructed from the group's regular matrix representation.*)\nLocal Notation R_G := group_ring.\n\n(*This definition creates a function that, given a matrix from the group ring, extracts the row corresponding to the identity element of the group.*)\nDefinition gring_row : 'M[R]_nG -> 'rV_nG := row (gring_index 1).\nHB.instance Definition _ := GRing.Linear.on gring_row.\n\n(*This lemma states that extracting the row associated with the group's identity element from a matrix product is equivalent to first extracting that same row from the left-hand matrix and then multiplying it by the right-hand matrix.*)\nLemma gring_row_mul A B : gring_row (A *m B) = gring_row A *m B.\n\n(*This definition constructs a projection function for each group element. When applied to a matrix from the group ring, this function extracts the coefficient corresponding to the specified group element in the canonical basis expansion.*)\nDefinition gring_proj x := row (gring_index x) \\o trmx \\o gring_row.\n(*This lemma specifies the behavior of the group ring projection function. It states that for any two group elements, applying the projection associated with the first element to the regular representation matrix of the second element yields one if the elements are equal, and zero otherwise.*)\nLemma gring_projE : {in G &, forall x y, gring_proj x (aG y) = (x == y)%:R}.\n\n(*This lemma asserts that the regular matrix representation of the group is faithful, meaning that distinct group elements are mapped to distinct matrices.*)\nLemma regular_mx_faithful : mx_faithful aG.\n\nSection GringMx.\n\nVariables (n : nat) (rG : mx_representation G n).\n\n(*This definition creates a function that transforms a row vector, representing an element of the group ring, into a matrix in a different representation. This effectively maps an element from the abstract group ring to its concrete action on the module associated with the given matrix representation.*)\nDefinition gring_mx := vec_mx \\o mulmxr (enveloping_algebra_mx rG).\n(*This lemma describes the interaction between the group ring transformation function and right multiplication by a group element. It states that transforming the product of a group ring element and a group basis element is equivalent to first transforming the group ring element and then multiplying the result by the matrix representation of the group basis element.*)\nLemma gring_mxJ a x :\n x \\in G -> gring_mx (a *m aG x) = gring_mx a *m rG x.\n\nEnd GringMx.\n\n(*This lemma states that the process of extracting the identity-element row from a group ring matrix and then reconstructing a matrix from that row using the regular representation yields the original matrix.*)\nLemma gring_mxK : cancel (gring_mx aG) gring_row.\n\nSection GringOp.\n\nVariables (n : nat) (rG : mx_representation G n).\n\n(*This definition creates an operator that maps a matrix from the regular representation's enveloping algebra to a matrix in a different group representation. It achieves this by first extracting the row corresponding to the group's identity element and then using that row to construct the target representation matrix.*)\nDefinition gring_op := gring_mx rG \\o gring_row.\n(*This lemma provides the definitional expansion of the group ring operator, stating that its application to a matrix is equivalent to first extracting the row corresponding to the group identity and then applying the group ring transformation function to that row.*)\nLemma gring_opE a : gring_op a = gring_mx rG (gring_row a).\n\n(*This lemma demonstrates that the group ring operator acts as a change of representation map. It states that applying the operator to the regular representation matrix of a group element yields the matrix of that same element in the target representation.*)\nLemma gring_opG x : x \\in G -> gring_op (aG x) = rG x.\n\n(*This lemma states that the group ring operator preserves the identity element, mapping the identity matrix of the source algebra to the identity matrix of the target algebra.*)\nLemma gring_op1 : gring_op 1%:M = 1%:M.\n\n(*This lemma states that applying the group ring operator to the product of a matrix and the matrix representation of a group ring element is equivalent to multiplying the group ring operator of the matrix by the regular matrix representation of that same group ring element.*)\nLemma gring_opJ A b :\n gring_op (A *m gring_mx aG b) = gring_op A *m gring_mx rG b.\n\n(*This lemma states that applying the group ring operator to the matrix representation of a group ring element in one representation context yields the matrix representation of that same element in a different representation context, specifically the regular representation.*)\nLemma gring_op_mx b : gring_op (gring_mx aG b) = gring_mx rG b.\n\n(*This lemma asserts that the regular matrix representation of the action of one group ring element on another is equal to the matrix product of their individual regular matrix representations.*)\nLemma gring_mxA a b :\n gring_mx rG (a *m gring_mx aG b) = gring_mx rG a *m gring_mx rG b.\n\nEnd GringOp.\n\nEnd Regular.\n\nEnd RingRepr.\n\nArguments mx_representation R {gT} G%_g n%_N.\nArguments mx_repr {R gT} G%_g {n%_N} r.\nArguments group_ring R {gT} G%_g.\nArguments regular_repr R {gT} G%_g.\n\nArguments centgmxP {R gT G n rG f}.\nArguments rkerP {R gT G n rG x}.\nArguments repr_mxK {R gT G%_G n%_N} rG {m%_N} [x%_g] Gx.\nArguments repr_mxKV {R gT G%_G n%_N} rG {m%_N} [x%_g] Gx.\nArguments gring_valK {gT G%_G} i%_R : rename.\nArguments gring_indexK {gT G%_G} x%_g.\nArguments gring_mxK {R gT G%_G} v%_R : rename.\n\nSection ChangeOfRing.\n\nVariables (aR rR : comUnitRingType) (f : {rmorphism aR -> rR}).\n(**)\nLocal Notation \"A ^f\" := (map_mx (GRing.RMorphism.sort f) A) : ring_scope.\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that applying a ring morphism to the regular matrix representation of a group element over one ring yields the regular matrix representation of that same group element over the target ring of the morphism.*)\nLemma map_regular_mx x : (regular_mx aR G x)^f = regular_mx rR G x.\n\n(*This lemma states that applying a ring morphism to a group ring element derived from a matrix is equivalent to first applying the morphism to the matrix and then deriving the group ring element.*)\nLemma map_gring_row (A : 'M_#|G|) : (gring_row A)^f = gring_row A^f.\n\n(*This lemma asserts that applying a ring morphism to the coefficient of a group element extracted from a matrix is equivalent to extracting the coefficient of the same group element from the matrix after the morphism has been applied to its entries.*)\nLemma map_gring_proj x (A : 'M_#|G|) : (gring_proj x A)^f = gring_proj x A^f.\n\nSection OneRepresentation.\n\nVariables (n : nat) (rG : mx_representation aR G n).\n\n(*This definition constructs a new matrix representation of a group by applying a given ring morphism to each entry of the matrices from an existing representation.*)\nDefinition map_repr_mx (f0 : aR -> rR) rG0 (g : gT) : 'M_n := map_mx f0 (rG0 g).\n\n(*This lemma confirms that applying a ring morphism to the matrices of a valid group representation results in a new, valid group representation.*)\nLemma map_mx_repr : mx_repr G (map_repr_mx f rG).\n\nCanonical map_repr := MxRepresentation map_mx_repr.\n(*This is a local notation for the matrix representation obtained by applying a ring morphism to an existing group representation.*)\nLocal Notation rGf := map_repr.\n\n(*This lemma states that the matrix for a group element in the morphism-mapped representation is equal to the matrix of that same element in the original representation with the morphism applied to its entries.*)\nLemma map_reprE x : rGf x = (rG x)^f. \n\n(*This lemma states that applying a ring morphism to the product of a matrix and a representation matrix is equivalent to the product of the morphism-applied matrix and the corresponding matrix from the morphism-mapped representation.*)\nLemma map_reprJ m (A : 'M_(m, n)) x : (A *m rG x)^f = A^f *m rGf x.\n\n(*This lemma asserts that applying a ring morphism to the matrix representing the basis of a representation's enveloping algebra is equivalent to computing the basis matrix for the enveloping algebra of the morphism-mapped representation.*)\nLemma map_enveloping_algebra_mx :\n (enveloping_algebra_mx rG)^f = enveloping_algebra_mx rGf.\n\n(*This lemma states that applying a ring morphism to the matrix representation of a group ring element is equivalent to computing the matrix representation, in the morphism-mapped context, of the group ring element after the morphism has been applied to its coefficients.*)\nLemma map_gring_mx a : (gring_mx rG a)^f = gring_mx rGf a^f.\n\n(*This lemma shows that the group ring operator commutes with applying a ring morphism; applying the morphism after the operator is the same as applying the operator in the morphism-mapped context to the morphism-mapped matrix.*)\nLemma map_gring_op A : (gring_op rG A)^f = gring_op rGf A^f.\n\nEnd OneRepresentation.\n\n(*This lemma states that applying a ring morphism to the regular representation of a group over a given ring yields a representation equivalent to the regular representation of that same group over the target ring.*)\nLemma map_regular_repr : map_repr (regular_repr aR G) =1 regular_repr rR G.\n\n(*This lemma states that applying a ring morphism to the matrix algebra corresponding to a group ring over one ring results in the matrix algebra corresponding to the group ring over the target ring.*)\nLemma map_group_ring : (group_ring aR G)^f = group_ring rR G.\n\nEnd ChangeOfRing.\n\nSection FieldRepr.\n\nVariable F : fieldType.\n\nSection OneRepresentation.\n\nVariable gT : finGroupType.\n\nVariables (G : {group gT}) (n : nat) (rG : mx_representation F G n).\nArguments rG _%_group_scope : extra scopes.\n\n(*This notation defines `E_G` as the enveloping algebra of a given matrix representation, which is the matrix algebra generated by the images of the group elements under the representation.*)\nLocal Notation E_G := (enveloping_algebra_mx rG).\n\n(*This lemma asserts that for any element in the group, its corresponding representation matrix has linearly independent rows.*)\nLemma repr_mx_free x : x \\in G -> row_free (rG x).\n\nSection Stabilisers.\n\nVariables (m : nat) (U : 'M[F]_(m, n)).\n\n(*This definition specifies the right stabilizer of a given matrix as the set of group elements whose corresponding representation matrices, when right-multiplied with the given matrix, produce a result whose row space is a subspace of the original matrix's row space.*)\nDefinition rstabs := [set x in G | U *m rG x <= U]%MS.\n\n(*This lemma states that the right stabilizer set of a matrix is a subset of the group.*)\nLemma rstabs_sub : rstabs \\subset G.\n\n(*This lemma asserts that the right stabilizer set of a matrix forms a group, making it a subgroup of the original group.*)\nLemma rstabs_group_set : group_set rstabs.\n\nCanonical rstabs_group := Group rstabs_group_set.\n\n(*This lemma states that if a group element belongs to the strict right stabilizer of a matrix, then any matrix whose row space is a subspace of that matrix's row space remains unchanged when right-multiplied by the group element's representation matrix.*)\nLemma rstab_act x m1 (W : 'M_(m1, n)) :\n x \\in rstab rG U -> (W <= U)%MS -> W *m rG x = W.\n\n(*This lemma states that if a group element belongs to the right stabilizer of a matrix, then for any other matrix whose row space is contained within the first matrix's row space, right-multiplying it by the group element's representation matrix results in a matrix whose row space is also contained within the original matrix's row space.*)\nLemma rstabs_act x m1 (W : 'M_(m1, n)) :\n x \\in rstabs -> (W <= U)%MS -> (W *m rG x <= U)%MS.\n\n(*This definition specifies the property that a matrix's row space forms a module for a group representation, which holds if the right stabilizer of the matrix is the entire group.*)\nDefinition mxmodule := G \\subset rstabs.\n\n(*This lemma provides a boolean reflection of the property that a matrix's row space is a module, stating that this is equivalent to the condition that for every group element, multiplying the matrix by the element's representation matrix yields a result whose row space is a subspace of the original matrix's row space.*)\nLemma mxmoduleP : reflect {in G, forall x, U *m rG x <= U}%MS mxmodule.\n\nEnd Stabilisers.\nArguments mxmoduleP {m U}.\n\n(*This lemma states that if the row space of one matrix is a subspace of the row space of a second matrix, then the strict right stabilizer group of the second matrix is a subgroup of the strict right stabilizer group of the first matrix.*)\nLemma rstabS m1 m2 (U : 'M_(m1, n)) (V : 'M_(m2, n)) :\n (U <= V)%MS -> rstab rG V \\subset rstab rG U.\n\n(*This lemma asserts that if two matrices have the same row space, then their corresponding strict right stabilizer groups are equal.*)\nLemma eqmx_rstab m1 m2 (U : 'M_(m1, n)) (V : 'M_(m2, n)) :\n (U :=: V)%MS -> rstab rG U = rstab rG V.\n\n(*This lemma asserts that if two matrices share the same row space, then their corresponding right stabilizer sets are equal.*)\nLemma eqmx_rstabs m1 m2 (U : 'M_(m1, n)) (V : 'M_(m2, n)) :\n (U :=: V)%MS -> rstabs U = rstabs V.\n\n(*This lemma states that if two matrices have the same row space, then one constitutes a module for a group representation if and only if the other one does as well.*)\nLemma eqmx_module m1 m2 (U : 'M_(m1, n)) (V : 'M_(m2, n)) :\n (U :=: V)%MS -> mxmodule U = mxmodule V.\n\n(*This lemma states that the zero matrix with a given number of rows and columns represents a submodule.*)\nLemma mxmodule0 m : mxmodule (0 : 'M_(m, n)).\n\n(*This lemma states that the identity matrix represents a submodule.*)\nLemma mxmodule1 : mxmodule 1%:M.\n\n(*This lemma states that if a matrix `U` represents a submodule and another matrix `W` represents a submodule of `U`, then the matrix resulting from the action of a group element on `W` also represents a submodule of `U`.*)\nLemma mxmodule_trans m1 m2 (U : 'M_(m1, n)) (W : 'M_(m2, n)) x :\n mxmodule U -> x \\in G -> (W <= U -> W *m rG x <= U)%MS.\n\n(*This lemma states that any submodule represented by a matrix of rank one can be expressed as the row space of a single row vector, and this vector is a common eigenvector for the matrix representations of all elements in the associated group.*)\nLemma mxmodule_eigenvector m (U : 'M_(m, n)) :\n mxmodule U -> \\rank U = 1 ->\n {u : 'rV_n & {a | (U :=: u)%MS & {in G, forall x, u *m rG x = a x *: u}}}.\n\n(*This lemma states that the sum of two submodules, each represented by a matrix, is also a submodule.*)\nLemma addsmx_module m1 m2 U V :\n @mxmodule m1 U -> @mxmodule m2 V -> mxmodule (U + V)%MS.\n\n(*This lemma states that the sum of a finite collection of submodules, where each is represented by a matrix, is also a submodule.*)\nLemma sumsmx_module I r (P : pred I) U :\n (forall i, P i -> mxmodule (U i)) -> mxmodule (\\sum_(i <- r | P i) U i)%MS.\n\n(*This lemma states that the intersection of two submodules, each represented by a matrix, is also a submodule.*)\nLemma capmx_module m1 m2 U V :\n @mxmodule m1 U -> @mxmodule m2 V -> mxmodule (U :&: V)%MS.\n\n(*This lemma states that the intersection of a finite collection of submodules, where each is represented by a matrix, is also a submodule.*)\nLemma bigcapmx_module I r (P : pred I) U :\n (forall i, P i -> mxmodule (U i)) -> mxmodule (\\bigcap_(i <- r | P i) U i)%MS.\n\nSection Submodule.\n\nVariable U : 'M[F]_n.\n\n(*This definition specifies a function that maps a matrix of coordinate vectors relative to a submodule's basis into the ambient vector space by post-multiplying it with the submodule's basis matrix.*)\nDefinition val_submod m : 'M_(m, \\rank U) -> 'M_(m, n) := mulmxr (row_base U).\n(*This definition specifies a function that projects a matrix from the ambient vector space onto the coordinate system of a given submodule.*)\nDefinition in_submod m : 'M_(m, n) -> 'M_(m, \\rank U) :=\n mulmxr (invmx (row_ebase U) *m pid_mx (\\rank U)).\nHB.instance Definition _ m := GRing.Linear.on (@val_submod m).\nHB.instance Definition _ m := GRing.Linear.on (@in_submod m).\n\n(*This lemma states that embedding a matrix into the ambient space using a submodule's basis is equivalent to post-multiplying that matrix by the embedded identity matrix.*)\nLemma val_submodE m W : @val_submod m W = W *m val_submod 1%:M.\n\n(*This lemma states that projecting a matrix onto a submodule's coordinate system is equivalent to post-multiplying that matrix by the projected identity matrix.*)\nLemma in_submodE m W : @in_submod m W = W *m in_submod 1%:M.\n\n(*This lemma states that embedding the identity matrix into the ambient space using a submodule's basis yields a matrix whose row space is identical to that submodule.*)\nLemma val_submod1 : (val_submod 1%:M :=: U)%MS.\n\n(*This lemma states that the row space of any matrix embedded into the ambient space from a submodule's coordinate system is itself contained within that submodule.*)\nLemma val_submodP m W : (@val_submod m W <= U)%MS.\n\n(*This lemma states that embedding a matrix from a submodule's coordinate system into the ambient space and then projecting it back yields the original matrix, meaning the projection is a left inverse of the embedding.*)\nLemma val_submodK m : cancel (@val_submod m) (@in_submod m).\n\n(*This lemma states that the embedding function from a submodule's coordinate system into the ambient space is injective.*)\nLemma val_submod_inj m : injective (@val_submod m).\n\n(*This lemma states that for any two matrices in a submodule's coordinate system, one represents a subspace of the other if and only if their embeddings into the ambient space exhibit the same subspace relationship.*)\nLemma val_submodS m1 m2 (V : 'M_(m1, \\rank U)) (W : 'M_(m2, \\rank U)) :\n (val_submod V <= val_submod W)%MS = (V <= W)%MS.\n\n(*This lemma states that for any matrix whose row space is contained within a given submodule, projecting it into that submodule's coordinate system and then embedding it back into the ambient space recovers the original matrix.*)\nLemma in_submodK m W : (W <= U)%MS -> val_submod (@in_submod m W) = W.\n\n(*This lemma states that a matrix embedded from a submodule's coordinate system into the ambient space is the zero matrix if and only if the original coordinate matrix is the zero matrix.*)\nLemma val_submod_eq0 m W : (@val_submod m W == 0) = (W == 0).\n\n(*This lemma states that the projection of a matrix from the ambient space onto a submodule's coordinate system is the zero matrix if and only if the row space of the matrix is contained in the orthogonal complement of the submodule.*)\nLemma in_submod_eq0 m W : (@in_submod m W == 0) = (W <= U^C)%MS.\n\n(*This lemma states that if a matrix's row space is contained within a given submodule, then the rank of that matrix is equal to the rank of its projection into the submodule's coordinate system.*)\nLemma mxrank_in_submod m (W : 'M_(m, n)) :\n (W <= U)%MS -> \\rank (in_submod W) = \\rank W.\n\n(*This definition specifies a function that maps a matrix representing coordinates in a quotient module to a matrix of canonical representatives in the ambient vector space.*)\nDefinition val_factmod m : _ -> 'M_(m, n) :=\n mulmxr (row_base (cokermx U) *m row_ebase U).\n(*This definition specifies a function that maps a matrix from the ambient vector space to its corresponding representation in the coordinate system of a quotient module, effectively performing a quotient projection.*)\nDefinition in_factmod m : 'M_(m, n) -> _ := mulmxr (col_base (cokermx U)).\nHB.instance Definition _ m := GRing.Linear.on (@val_factmod m).\n(*This lemma states that mapping a matrix from quotient module coordinates to its representative in the ambient space is equivalent to post-multiplying that matrix by the representative of the identity matrix.*)\nLemma val_factmodE m W : @val_factmod m W = W *m val_factmod 1%:M.\n\n(*This lemma states that mapping a matrix from the ambient space to its representation in quotient module coordinates is equivalent to post-multiplying that matrix by the coordinate representation of the identity matrix.*)\nLemma in_factmodE m W : @in_factmod m W = W *m in_factmod 1%:M.\n\n(*This lemma states that the row space of any representative matrix, obtained by mapping from quotient module coordinates, is contained within the orthogonal complement of the original submodule.*)\nLemma val_factmodP m W : (@val_factmod m W <= U^C)%MS.\n\n(*This lemma states that mapping a matrix from quotient module coordinates to its representative in the ambient space and then projecting it back to the quotient module yields the original coordinate matrix.*)\nLemma val_factmodK m : cancel (@val_factmod m) (@in_factmod m).\n\n(*This lemma states that the mapping from a quotient module's coordinate system to representatives in the ambient space is injective.*)\nLemma val_factmod_inj m : injective (@val_factmod m).\n\n(*This lemma states that for any two matrices in a quotient module's coordinate system, one represents a subspace of the other if and only if their representatives in the ambient space exhibit the same subspace relationship.*)\nLemma val_factmodS m1 m2 (V : 'M_(m1, _)) (W : 'M_(m2, _)) :\n (val_factmod V <= val_factmod W)%MS = (V <= W)%MS.\n\n(*This lemma states that the representative of a matrix from a quotient module's coordinate system is the zero matrix if and only if the original coordinate matrix is the zero matrix.*)\nLemma val_factmod_eq0 m W : (@val_factmod m W == 0) = (W == 0).\n\n(*This lemma states that the image of a matrix in the factor module is zero if and only if the submodule represented by that matrix is contained within the basis submodule U.*)\nLemma in_factmod_eq0 m (W : 'M_(m, n)) : (in_factmod W == 0) = (W <= U)%MS.\n\n(*This lemma provides a cancellation property, stating that for a matrix representing a submodule contained in the complement of the basis submodule U, projecting its image from the factor module back to the original space yields the original matrix.*)\nLemma in_factmodK m (W : 'M_(m, n)) :\n (W <= U^C)%MS -> val_factmod (in_factmod W) = W.\n\n(*This lemma states that the image of the sum of the basis submodule U and another submodule represented by a matrix W in the factor module is definitionally equal to the image of W alone.*)\nLemma in_factmod_addsK m (W : 'M_(m, n)) :\n (in_factmod (U + W)%MS :=: in_factmod W)%MS.\n\n(*This lemma asserts that any matrix can be decomposed into the sum of its projection onto the basis submodule U and its projection onto the corresponding factor module.*)\nLemma add_sub_fact_mod m (W : 'M_(m, n)) :\n val_submod (in_submod W) + val_factmod (in_factmod W) = W.\n\n(*This lemma states that the projection of a matrix onto the factor module results in a submodule that is contained within the sum of the basis submodule U and the submodule represented by the original matrix.*)\nLemma proj_factmodS m (W : 'M_(m, n)) :\n (val_factmod (in_factmod W) <= U + W)%MS.\n\n(*This lemma states that if the basis submodule U is contained within the submodule represented by a matrix W, then W is definitionally equal to the sum of U and the projection of W onto the factor module.*)\nLemma in_factmodsK m (W : 'M_(m, n)) :\n (U <= W)%MS -> (U + val_factmod (in_factmod W) :=: W)%MS.\n\n(*This lemma provides a formula relating the ranks of submodules, stating that the rank of the sum of the basis submodule U and another submodule W is equal to the sum of the rank of U and the rank of the image of W in the factor module.*)\nLemma mxrank_in_factmod m (W : 'M_(m, n)) :\n (\\rank (in_factmod W) + \\rank U)%N = \\rank (U + W).\n\n(*This definition specifies a matrix that represents how a group element acts on the basis submodule U. It is computed by applying the group element's representation matrix to the part of the identity matrix that lies in U, and then representing this result as a matrix in the submodule's coordinate system.*)\nDefinition submod_mx of mxmodule U :=\n fun x => in_submod (val_submod 1%:M *m rG x).\n\n(*This definition specifies a matrix that represents how a group element acts on the factor module relative to U. It is computed by applying the group element's representation matrix to the part of the identity matrix that lies in the factor module, and then representing this result as a matrix in the factor module's coordinate system.*)\nDefinition factmod_mx of mxmodule U :=\n fun x => in_factmod (val_factmod 1%:M *m rG x).\n\nHypothesis Umod : mxmodule U.\n\n(*This lemma states that for a matrix representing a submodule contained within the basis submodule U, the injection into the submodule representation commutes with the group action; applying the group action before injection is equivalent to applying the submodule-specific group action after injection.*)\nLemma in_submodJ m (W : 'M_(m, n)) x :\n (W <= U)%MS -> in_submod (W *m rG x) = in_submod W *m submod_mx Umod x.\n\n(*This lemma states that for any group element, the projection from the submodule representation commutes with the group action; applying the submodule-specific group action before projection is equivalent to applying the standard group action after projection.*)\nLemma val_submodJ m (W : 'M_(m, \\rank U)) x :\n x \\in G -> val_submod (W *m submod_mx Umod x) = val_submod W *m rG x.\n\n(*This lemma asserts that the function defining the group action on the basis submodule U constitutes a valid matrix representation of the group.*)\nLemma submod_mx_repr : mx_repr G (submod_mx Umod).\n\nCanonical submod_repr := MxRepresentation submod_mx_repr.\n\n(*This lemma states that for any group element, the injection into the factor module representation commutes with the group action; applying the group action before injection is equivalent to applying the factor-module-specific group action after injection.*)\nLemma in_factmodJ m (W : 'M_(m, n)) x :\n x \\in G -> in_factmod (W *m rG x) = in_factmod W *m factmod_mx Umod x.\n\n(*This lemma states that for a matrix in the factor module's coordinate system, applying the factor module's group action and then projecting to a canonical matrix representative gives the same result as projecting the matrix first, applying the standard group action, and then projecting the resulting matrix into the space of canonical representatives.*)\nLemma val_factmodJ m (W : 'M_(m, \\rank (cokermx U))) x :\n x \\in G ->\n val_factmod (W *m factmod_mx Umod x) =\n val_factmod (in_factmod (val_factmod W *m rG x)).\n\n(*This lemma asserts that the function defining the group action on the factor module constitutes a valid matrix representation of the group.*)\nLemma factmod_mx_repr : mx_repr G (factmod_mx Umod).\n\nCanonical factmod_repr := MxRepresentation factmod_mx_repr.\n\n(*This lemma states that the trace of a group representation matrix for a given group element is equal to the sum of the traces of its corresponding sub-representation and factor-representation matrices.*)\nLemma mxtrace_sub_fact_mod x :\n \\tr (submod_repr x) + \\tr (factmod_repr x) = \\tr (rG x).\n\nEnd Submodule.\n\n(*This lemma states that for any group element, its corresponding matrix representation is an element of the submodule representing the enveloping algebra.*)\nLemma envelop_mx_id x : x \\in G -> (rG x \\in E_G)%MS.\n\n(*This lemma states that the identity matrix is an element of the submodule representing the enveloping algebra.*)\nLemma envelop_mx1 : (1%:M \\in E_G)%MS.\n\n(*This lemma provides the definition of the enveloping algebra's submodule, stating that a matrix belongs to this submodule if and only if it can be expressed as a scalar-weighted sum of the matrix representations of all group elements.*)\nLemma envelop_mxP A :\n reflect (exists a, A = \\sum_(x in G) a x *: rG x) (A \\in E_G)%MS.\n\n(*This lemma states that the submodule representing the enveloping algebra is closed under matrix multiplication.*)\nLemma envelop_mxM A B : (A \\in E_G -> B \\in E_G -> A *m B \\in E_G)%MS.\n\n(*This lemma states that if a matrix U represents a module over the enveloping algebra, and another matrix A has rows belonging to that algebra, then multiplying any submodule W of U by A results in a submodule that is still contained within U.*)\nLemma mxmodule_envelop m1 m2 (U : 'M_(m1, n)) (W : 'M_(m2, n)) A :\n (mxmodule U -> mxvec A <= E_G -> W <= U -> W *m A <= U)%MS.\n\n(*This definition specifies the domain of a matrix homomorphism associated with a given matrix f as the kernel of a complex linear map constructed from the centralizer of f with respect to the enveloping algebra.*)\nDefinition dom_hom_mx f : 'M_n :=\n kermx (lin1_mx (mxvec \\o mulmx (cent_mx_fun E_G f) \\o lin_mul_row)).\n\n(*This lemma provides a practical characterization for membership in a matrix homomorphism's domain, stating that a submodule belongs to this domain if and only if its multiplication with a group representation matrix commutes with its multiplication by the homomorphism's matrix f.*)\nLemma hom_mxP m f (W : 'M_(m, n)) :\n reflect (forall x, x \\in G -> W *m rG x *m f = W *m f *m rG x)\n (W <= dom_hom_mx f)%MS.\n\nArguments hom_mxP {m f W}.\n\n(*This lemma extends the commutation property of a homomorphism's domain, stating that if a submodule is in the domain, its multiplication with any matrix from the enveloping algebra commutes with its multiplication by the homomorphism's matrix f.*)\nLemma hom_envelop_mxC m f (W : 'M_(m, n)) A :\n (W <= dom_hom_mx f -> A \\in E_G -> W *m A *m f = W *m f *m A)%MS.\n\n(*This lemma relates the homomorphism domain of an invertible matrix to the domain of its inverse, stating that the domain for the inverse matrix is definitionally equal to the submodule obtained by multiplying the domain of the original matrix by the original matrix itself.*)\nLemma dom_hom_invmx f :\n f \\in unitmx -> (dom_hom_mx (invmx f) :=: dom_hom_mx f *m f)%MS.\n\n(*This lemma asserts that the domain of a matrix homomorphism f is itself a module over the group algebra.*)\nLemma dom_hom_mx_module f : mxmodule (dom_hom_mx f).\n\n(*This lemma states that if a matrix U represents a module and is contained within the domain of a homomorphism f, then the matrix product of U and f also represents a module.*)\nLemma hom_mxmodule m (U : 'M_(m, n)) f :\n (U <= dom_hom_mx f)%MS -> mxmodule U -> mxmodule (U *m f).\n\n(*This lemma states that if a matrix U represents a module and is contained within the domain of a homomorphism f, then the intersection of the submodule U with the kernel of f also represents a module.*)\nLemma kermx_hom_module m (U : 'M_(m, n)) f :\n (U <= dom_hom_mx f)%MS -> mxmodule U -> mxmodule (U :&: kermx f)%MS.\n\n(*This lemma states that any submodule is contained within the homomorphism domain associated with any scalar matrix, as scalar matrices commute with all other matrices.*)\nLemma scalar_mx_hom a m (U : 'M_(m, n)) : (U <= dom_hom_mx a%:M)%MS.\n\n(*This lemma states that if a matrix U represents a module and is a direct summand of a larger module represented by V, then V is contained within the homomorphism domain of the projection matrix onto U.*)\nLemma proj_mx_hom (U V : 'M_n) :\n (U :&: V = 0)%MS -> mxmodule U -> mxmodule V ->\n (U + V <= dom_hom_mx (proj_mx U V))%MS.\n\n(*This definition constructs the submodule of elements that are fixed by the action of every group element in a given set.*)\nDefinition rfix_mx (H : {set gT}) :=\n let commrH := \\matrix_(i < #|H|) mxvec (rG (enum_val i) - 1%:M) in\n kermx (lin1_mx (mxvec \\o mulmx commrH \\o lin_mul_row)).\n\n(*This lemma states that a matrix belongs to the submodule of fixed points of a set of group elements if and only if that matrix is unchanged when right-multiplied by the group representation of any element from the set.*)\nLemma rfix_mxP m (W : 'M_(m, n)) (H : {set gT}) :\n reflect (forall x, x \\in H -> W *m rG x = W) (W <= rfix_mx H)%MS.\n\nArguments rfix_mxP {m W}.\n\n(*This lemma states that the submodule of fixed points for a set of group elements is itself invariant under right-multiplication by the group representation of any element from that set.*)\nLemma rfix_mx_id (H : {set gT}) x : x \\in H -> rfix_mx H *m rG x = rfix_mx H.\n\n(*This lemma states that if a set of group elements is a subset of another, then the submodule of fixed points for the larger set is a submodule of the fixed points for the smaller set.*)\nLemma rfix_mxS (H K : {set gT}) : H \\subset K -> (rfix_mx K <= rfix_mx H)%MS.\n\n(*This lemma states that for a given set of group elements and another group element, the submodule of fixed points of the conjugate set is equal to the submodule of fixed points of the original set right-multiplied by the group representation of the conjugating element.*)\nLemma rfix_mx_conjsg (H : {set gT}) x :\n x \\in G -> H \\subset G -> (rfix_mx (H :^ x) :=: rfix_mx H *m rG x)%MS.\n\n(*This lemma states that for a given subset of a group, the normalizer of that subset is contained within the right stabilizer of the submodule of fixed points corresponding to that subset.*)\nLemma norm_sub_rstabs_rfix_mx (H : {set gT}) :\n H \\subset G -> 'N_G(H) \\subset rstabs (rfix_mx H).\n\n(*This lemma states that if a subgroup is normal in a larger group, then its corresponding submodule of fixed points is a module over the group algebra of the larger group.*)\nLemma normal_rfix_mx_module H : H <| G -> mxmodule (rfix_mx H).\n\n(*This lemma states that the submodule of elements fixed by all elements of the entire group is a module over the group algebra.*)\nLemma rfix_mx_module : mxmodule (rfix_mx G).\n\n(*This lemma states that for a given set of group elements and a matrix, the condition that the set is contained in the right stabilizer of the matrix is equivalent to the matrix being a submodule of the fixed points submodule associated with that set.*)\nLemma rfix_mx_rstabC (H : {set gT}) m (U : 'M[F]_(m, n)) :\n H \\subset G -> (H \\subset rstab rG U) = (U <= rfix_mx H)%MS.\n\n(*This definition constructs the cyclic submodule generated by a given row vector, which consists of all elements that can be obtained by applying linear transformations from the group algebra to that vector.*)\nDefinition cyclic_mx u := <>%MS.\n\n(*This lemma provides the characteristic property of a cyclic submodule, stating that a vector is an element of the cyclic submodule generated by another vector if and only if it can be expressed as the generating vector right-multiplied by some matrix from the group algebra.*)\nLemma cyclic_mxP u v :\n reflect (exists2 A, A \\in E_G & v = u *m A)%MS (v <= cyclic_mx u)%MS.\n\nArguments cyclic_mxP {u v}.\n\n(*This lemma states that the generating vector of a cyclic submodule is itself an element of that submodule.*)\nLemma cyclic_mx_id u : (u <= cyclic_mx u)%MS.\n\n(*This lemma states that the cyclic submodule generated by a vector is the zero submodule if and only if the generating vector itself is the zero vector.*)\nLemma cyclic_mx_eq0 u : (cyclic_mx u == 0) = (u == 0).\n\n(*This lemma states that the cyclic module generated by a vector is a valid module over the group algebra.*)\nLemma cyclic_mx_module u : mxmodule (cyclic_mx u).\n\n(*This lemma states that if a module over the group algebra contains a specific vector, then it must also contain the entire cyclic submodule generated by that vector.*)\nLemma cyclic_mx_sub m u (W : 'M_(m, n)) :\n mxmodule W -> (u <= W)%MS -> (cyclic_mx u <= W)%MS.\n\n(*This lemma states that for a module homomorphism, the image of a cyclic submodule is equal to the cyclic submodule generated by the image of the original generator, provided the generator is in the homomorphism's domain.*)\nLemma hom_cyclic_mx u f :\n (u <= dom_hom_mx f)%MS -> (cyclic_mx u *m f :=: cyclic_mx (u *m f))%MS.\n\n(*This definition specifies the annihilator of a row vector as the set of all elements in the group algebra that, when right-multiplied with the vector, result in the zero vector.*)\nDefinition annihilator_mx u := (E_G :&: kermx (lin_mul_row u))%MS.\n\n(*This lemma provides the characteristic property of the annihilator of a vector, stating that a matrix belongs to the annihilator if and only if it is an element of the group algebra and its right-multiplication with the vector yields the zero vector.*)\nLemma annihilator_mxP u A :\n reflect (A \\in E_G /\\ u *m A = 0)%MS (A \\in annihilator_mx u)%MS.\n\n(*This definition constructs the submodule consisting of all vectors that can be the image of a given vector under some module homomorphism.*)\nDefinition row_hom_mx u :=\n (\\bigcap_j kermx (vec_mx (row j (annihilator_mx u))))%MS.\n\n(*This lemma provides the characteristic property of the homomorphism image submodule, stating that a vector belongs to this submodule if and only if there exists a module homomorphism that maps the original generating vector to it.*)\nLemma row_hom_mxP u v :\n reflect (exists2 f, u <= dom_hom_mx f & u *m f = v)%MS (v <= row_hom_mx u)%MS.\n\n(*This inductive proposition defines an isomorphism between two submodules, which holds if there exists an invertible matrix that acts as a module homomorphism from the first submodule to the second, mapping the first submodule exactly onto the second.*)\nVariant mx_iso (U V : 'M_n) : Prop :=\n MxIso f of f \\in unitmx & (U <= dom_hom_mx f)%MS & (U *m f :=: V)%MS.\n\n(*This lemma states that if two submodules are equal, then they are isomorphic.*)\nLemma eqmx_iso U V : (U :=: V)%MS -> mx_iso U V.\n\n(*This lemma states that submodule isomorphism is reflexive, meaning any submodule is isomorphic to itself.*)\nLemma mx_iso_refl U : mx_iso U U.\n\n(*This lemma states that submodule isomorphism is symmetric, meaning if a first submodule is isomorphic to a second, then the second is isomorphic to the first.*)\nLemma mx_iso_sym U V : mx_iso U V -> mx_iso V U.\n\n(*This lemma states that submodule isomorphism is transitive, meaning if a first submodule is isomorphic to a second, and the second is isomorphic to a third, then the first is isomorphic to the third.*)\nLemma mx_iso_trans U V W : mx_iso U V -> mx_iso V W -> mx_iso U W.\n\n(*This lemma states that two isomorphic submodules have the same rank.*)\nLemma mxrank_iso U V : mx_iso U V -> \\rank U = \\rank V.\n\n(*This lemma states that if two matrix spaces are isomorphic and one is a module over the group algebra, then the other is also a module over the group algebra.*)\nLemma mx_iso_module U V : mx_iso U V -> mxmodule U -> mxmodule V.\n\n(*This definition describes a simple or irreducible submodule as a non-zero module over the group algebra whose only non-zero submodules are the module itself.*)\nDefinition mxsimple (V : 'M_n) :=\n [/\\ mxmodule V, V != 0 &\n forall U : 'M_n, mxmodule U -> (U <= V)%MS -> U != 0 -> (V <= U)%MS].\n\n(*This definition describes a non-simple submodule as one that contains at least one non-zero proper submodule, where properness is indicated by having a strictly smaller rank.*)\nDefinition mxnonsimple (U : 'M_n) :=\n exists V : 'M_n, [&& mxmodule V, (V <= U)%MS, V != 0 & \\rank V < \\rank U].\n\n(*This lemma provides the full characterization of a simple module, stating that it must be a non-zero module that does not contain any proper non-zero submodules.*)\nLemma mxsimpleP U :\n [/\\ mxmodule U, U != 0 & ~ mxnonsimple U] <-> mxsimple U.\n\n(*This lemma states that any simple module is also a module.*)\nLemma mxsimple_module U : mxsimple U -> mxmodule U.\n\n(*This lemma states that, under classical logic, any non-zero module contains a simple submodule.*)\nLemma mxsimple_exists m (U : 'M_(m, n)) :\n mxmodule U -> U != 0 -> classically (exists2 V, mxsimple V & V <= U)%MS.\n\n(*This lemma states that if two modules are isomorphic and one is simple, then the other is also simple.*)\nLemma mx_iso_simple U V : mx_iso U V -> mxsimple U -> mxsimple V.\n\n(*This lemma states that any simple module is equal to the cyclic module generated by any of its non-zero elements.*)\nLemma mxsimple_cyclic u U :\n mxsimple U -> u != 0 -> (u <= U)%MS -> (U :=: cyclic_mx u)%MS.\n\n(*This lemma, a part of Schur's Lemma, states that a module homomorphism from any module to a simple module is surjective if its image is non-zero.*)\nLemma mx_Schur_onto m (U : 'M_(m, n)) V f :\n mxmodule U -> mxsimple V -> (U <= dom_hom_mx f)%MS ->\n (U *m f <= V)%MS -> U *m f != 0 -> (U *m f :=: V)%MS.\n\n(*This lemma, a part of Schur's Lemma, states that a non-zero module homomorphism from a simple module is injective, meaning its kernel intersects the domain only at the zero module.*)\nLemma mx_Schur_inj U f :\n mxsimple U -> (U <= dom_hom_mx f)%MS -> U *m f != 0 -> (U :&: kermx f)%MS = 0.\n\n(*This lemma, derived from Schur's Lemma, states that a non-zero module homomorphism from a simple module induces a module isomorphism between its domain and its image.*)\nLemma mx_Schur_inj_iso U f :\n mxsimple U -> (U <= dom_hom_mx f)%MS -> U *m f != 0 -> mx_iso U (U *m f).\n\n(*This lemma states the full version of Schur's Lemma: any non-zero module homomorphism between two simple modules is a module isomorphism.*)\nLemma mx_Schur_iso U V f :\n mxsimple U -> mxsimple V -> (U <= dom_hom_mx f)%MS ->\n (U *m f <= V)%MS -> U *m f != 0 -> mx_iso U V.\n\n(*This lemma states that a matrix representing a simple module must contain at least one non-zero row.*)\nLemma nz_row_mxsimple U : mxsimple U -> nz_row U != 0.\n\n(*This definition provides a predicate to test if two square matrices, representing modules, are isomorphic, under the assumption that the first matrix represents a simple module. The test involves checking that the second is a module, has a non-zero intersection with a specific map derived from a non-zero row of the first, and has a rank less than or equal to the first's rank.*)\nDefinition mxsimple_iso (U V : 'M_n) :=\n [&& mxmodule V, (V :&: row_hom_mx (nz_row U))%MS != 0 & \\rank V <= \\rank U].\n\n(*This lemma states that for a given simple module, the predicate for isomorphism between it and another module is logically equivalent to them being formally isomorphic as modules.*)\nLemma mxsimple_isoP U V :\n mxsimple U -> reflect (mx_iso U V) (mxsimple_iso U V).\n\n(*This lemma states that if a module is simple, any other module satisfying the specific isomorphism predicate with it is also simple.*)\nLemma mxsimple_iso_simple U V :\n mxsimple_iso U V -> mxsimple U -> mxsimple V.\n\nImplicit Type I : finType.\n\n(*This definition introduces a variant type to certify that a module is semisimple, by providing evidence that it is equal to a direct sum of a family of simple modules.*)\nVariant mxsemisimple (V : 'M_n) :=\n MxSemisimple I U (W := (\\sum_(i : I) U i)%MS) of\n forall i, mxsimple (U i) & (W :=: V)%MS & mxdirect W.\n\n(*This lemma states that if a module is a submodule of a direct sum of simple modules, then a subset of those simple modules can be chosen to form a direct sum complement to the submodule within the larger sum.*)\nLemma sum_mxsimple_direct_compl m I W (U : 'M_(m, n)) :\n let V := (\\sum_(i : I) W i)%MS in\n (forall i : I, mxsimple (W i)) -> mxmodule U -> (U <= V)%MS ->\n {J : {set I} | let S := U + \\sum_(i in J) W i in S :=: V /\\ mxdirect S}%MS.\n\n(*This lemma states that if a module is equal to a sum of a family of simple modules, then a sub-family can be selected whose sum is direct and still equals the original module.*)\nLemma sum_mxsimple_direct_sub I W (V : 'M_n) :\n (forall i : I, mxsimple (W i)) -> (\\sum_i W i :=: V)%MS ->\n {J : {set I} | let S := \\sum_(i in J) W i in S :=: V /\\ mxdirect S}%MS.\n\n(*This lemma states that the zero module is a semisimple module.*)\nLemma mxsemisimple0 : mxsemisimple 0.\n\n(*This lemma provides a method to prove a module is semisimple by showing it is equal to a sum of non-zero simple modules.*)\nLemma intro_mxsemisimple (I : Type) r (P : pred I) W V :\n (\\sum_(i <- r | P i) W i :=: V)%MS ->\n (forall i, P i -> W i != 0 -> mxsimple (W i)) ->\n mxsemisimple V.\n\n(*This lemma states that any simple module is also a semisimple module.*)\nLemma mxsimple_semisimple U : mxsimple U -> mxsemisimple U.\n\n(*This lemma states that the sum of two semisimple modules is itself a semisimple module.*)\nLemma addsmx_semisimple U V :\n mxsemisimple U -> mxsemisimple V -> mxsemisimple (U + V)%MS.\n\n(*This lemma states that any finite sum of semisimple modules is also a semisimple module.*)\nLemma sumsmx_semisimple (I : finType) (P : pred I) V :\n (forall i, P i -> mxsemisimple (V i)) -> mxsemisimple (\\sum_(i | P i) V i)%MS.\n\n(*This lemma states that if two modules are equal and one is semisimple, then the other is also semisimple.*)\nLemma eqmx_semisimple U V : (U :=: V)%MS -> mxsemisimple U -> mxsemisimple V.\n\n(*This lemma states that the image of a semisimple module under a module homomorphism is also a semisimple module.*)\nLemma hom_mxsemisimple (V f : 'M_n) :\n mxsemisimple V -> (V <= dom_hom_mx f)%MS -> mxsemisimple (V *m f).\n\n(*This lemma states that any semisimple module is also a module.*)\nLemma mxsemisimple_module U : mxsemisimple U -> mxmodule U.\n\n(*This definition introduces a variant type to certify that a submodule splits from a larger module, by providing a complement module such that their direct sum equals the larger module.*)\nVariant mxsplits (V U : 'M_n) :=\n MxSplits (W : 'M_n) of mxmodule W & (U + W :=: V)%MS & mxdirect (U + W).\n\n(*This definition specifies that a module is completely reducible if every one of its submodules is a direct summand, meaning each has a complement.*)\nDefinition mx_completely_reducible V :=\n forall U, mxmodule U -> (U <= V)%MS -> mxsplits V U.\n\n(*This lemma states that any submodule of a completely reducible module is also completely reducible.*)\nLemma mx_reducibleS U V :\n mxmodule U -> (U <= V)%MS ->\n mx_completely_reducible V -> mx_completely_reducible U.\n\n(*This lemma states Maschke's Theorem: if the characteristic of the underlying field does not divide the order of the group, then the associated group algebra module is completely reducible.*)\nLemma mx_Maschke_pchar : [pchar F]^'.-group G -> mx_completely_reducible 1%:M.\n\n(*This lemma states that every semisimple module is also completely reducible.*)\nLemma mxsemisimple_reducible V : mxsemisimple V -> mx_completely_reducible V.\n\n(*This lemma states that, under classical logic, any completely reducible module is also a semisimple module.*)\nLemma mx_reducible_semisimple V :\n mxmodule V -> mx_completely_reducible V -> classically (mxsemisimple V).\n\n(*This lemma states that any submodule of a semisimple module is also semisimple.*)\nLemma mxsemisimpleS U V :\n mxmodule U -> (U <= V)%MS -> mxsemisimple V -> mxsemisimple U.\n\n(*This lemma states that if a simple matrix module `U` is a submodule of the image of a direct sum `V` of simple matrix modules under a homomorphism `f`, and `V` is contained in the domain of `f`, then `U` must be isomorphic to one of the non-zero simple components of `V`.*)\nLemma hom_mxsemisimple_iso I P U W f :\n let V := (\\sum_(i : I | P i) W i)%MS in\n mxsimple U -> (forall i, P i -> W i != 0 -> mxsimple (W i)) ->\n (V <= dom_hom_mx f)%MS -> (U <= V *m f)%MS ->\n {i | P i & mx_iso (W i) U}.\n\nSection Components.\n\n(*This fact defines a unique key of unit type used to lock the definition of the isotypic component, making it opaque and preventing its automatic unfolding during proofs.*)\nFact component_mx_key : unit. \n(*This definition specifies an expression for a matrix module, defined as the internal direct sum of cyclic matrix modules. Each cyclic module is generated by a row of the matrix representation of the row homomorphism associated with the first non-zero row of the input matrix module.*)\nDefinition component_mx_expr (U : 'M[F]_n) :=\n (\\sum_i cyclic_mx (row i (row_hom_mx (nz_row U))))%MS.\n(*This definition provides an opaque representation of the isotypic component associated with a simple matrix module. It is defined as a specific direct sum of cyclic modules but is locked to prevent unfolding, forcing proofs to rely on its abstract properties.*)\nDefinition component_mx := locked_with component_mx_key component_mx_expr.\nCanonical component_mx_unfoldable := [unlockable fun component_mx].\n\nVariable U : 'M[F]_n.\nHypothesis simU : mxsimple U.\n\n(*This definition assigns a local name to the first non-zero row found in the given simple matrix module.*)\nLet u := nz_row U.\n(*This definition assigns a local name to the row homomorphism matrix derived from a specific non-zero row of a matrix module.*)\nLet iso_u := row_hom_mx u.\n(*This definition provides a proof that the chosen row from the simple matrix module is not the zero row vector.*)\nLet nz_u : u != 0 := nz_row_mxsimple simU.\n(*This definition establishes that the submodule generated by a specific non-zero row is contained within the original simple matrix module.*)\nLet Uu : (u <= U)%MS := nz_row_sub U.\n(*This definition establishes that a simple matrix module is equal to the cyclic module generated by its first non-zero row.*)\nLet defU : (U :=: cyclic_mx u)%MS := mxsimple_cyclic simU nz_u Uu.\n(*This notation provides a local shorthand for the isotypic component of a given simple matrix module.*)\nLocal Notation compU := (component_mx U).\n\n(*This lemma states that the isotypic component associated with a simple matrix module is itself a matrix module.*)\nLemma component_mx_module : mxmodule compU.\n\n(*This lemma states that the submodule generated by the elements of an isotypic component is equal to the isotypic component itself.*)\nLemma genmx_component : <>%MS = compU.\n\n(*This lemma states that the isotypic component of a simple matrix module is equal to a direct sum of a finite collection of matrix modules, each of which is isomorphic to the original simple module.*)\nLemma component_mx_def : {I : finType & {W : I -> 'M_n |\n forall i, mx_iso U (W i) & compU = \\sum_i W i}}%MS.\n\n(*This lemma states that the isotypic component associated with a simple matrix module is a semisimple matrix module.*)\nLemma component_mx_semisimple : mxsemisimple compU.\n\n(*This lemma states that if a matrix module is isomorphic to a given simple matrix module, then it is a submodule of the isotypic component associated with that simple module.*)\nLemma mx_iso_component V : mx_iso U V -> (V <= compU)%MS.\n\n(*This lemma states that a simple matrix module is a submodule of its own isotypic component.*)\nLemma component_mx_id : (U <= compU)%MS.\n\n(*This lemma states that if a simple matrix module `V` is a submodule of the image of an isotypic component under a module homomorphism, and the isotypic component is contained in the domain of the homomorphism, then `V` must be isomorphic to the simple module that defines the isotypic component.*)\nLemma hom_component_mx_iso f V :\n mxsimple V -> (compU <= dom_hom_mx f)%MS -> (V <= compU *m f)%MS ->\n mx_iso U V.\n\n(*This lemma states that any simple matrix module that is a submodule of the isotypic component of another simple module must be isomorphic to that simple module.*)\nLemma component_mx_iso V : mxsimple V -> (V <= compU)%MS -> mx_iso U V.\n\n(*This lemma states that if the domain of a module homomorphism contains an isotypic component, then the image of that isotypic component under the homomorphism is a submodule of the original isotypic component.*)\nLemma hom_component_mx f :\n (compU <= dom_hom_mx f)%MS -> (compU *m f <= compU)%MS.\n\nEnd Components.\n\n(*This lemma establishes an equivalence: two simple matrix modules are isomorphic if and only if their corresponding isotypic components are equal as matrix modules.*)\nLemma component_mx_isoP U V :\n mxsimple U -> mxsimple V ->\n reflect (mx_iso U V) (component_mx U == component_mx V).\n\n(*This lemma states that if two simple matrix modules have different isotypic components, then the intersection of these two components is the zero module.*)\nLemma component_mx_disjoint U V :\n mxsimple U -> mxsimple V -> component_mx U != component_mx V ->\n (component_mx U :&: component_mx V = 0)%MS.\n\nSection Socle.\n\n(*This record defines a structure that provides a complete set of representatives for the isomorphism classes of simple matrix modules. It consists of a sequence of simple matrix modules such that any simple module is isomorphic to exactly one module in the sequence.*)\nRecord socleType := EnumSocle {\n socle_base_enum : seq 'M[F]_n;\n _ : forall M, M \\in socle_base_enum -> mxsimple M;\n _ : forall M, mxsimple M -> has (mxsimple_iso M) socle_base_enum\n}.\n\n(*This lemma asserts the classical existence of a structure that provides a complete set of representatives for the isomorphism classes of all simple matrix modules.*)\nLemma socle_exists : classically socleType.\n\nSection SocleDef.\n\nVariable sG0 : socleType.\n\n(*This definition creates a sequence of isotypic components by applying the `component_mx` function to each simple matrix module in the base enumeration provided by a `socleType` structure.*)\nDefinition socle_enum := map component_mx (socle_base_enum sG0).\n\n(*This lemma states that for any simple matrix module, its corresponding isotypic component is an element of the enumerated sequence of all canonical isotypic components.*)\nLemma component_socle M : mxsimple M -> component_mx M \\in socle_enum.\n\n(**)\nInductive socle_sort : predArgType := PackSocle W of W \\in socle_enum.\n\n(*This notation provides a local shorthand for the inductive type that enumerates the distinct isotypic components of a module.*)\nLocal Notation sG := socle_sort.\n(*This notation provides a local shorthand for the base sequence of simple matrix module representatives provided by a `socleType` structure.*)\nLocal Notation e0 := (socle_base_enum sG0).\n\n(*This definition retrieves the simple matrix module representative that corresponds to a given isotypic component from the socle enumeration. It does this by finding the index of the component and using it to access the base sequence of simple representatives.*)\nDefinition socle_base W := let: PackSocle W _ := W in e0`_(index W socle_enum).\n\nCoercion socle_val W : 'M[F]_n := component_mx (socle_base W).\n\n(*This definition computes the multiplicity of a simple matrix module within its corresponding isotypic component by dividing the rank of the component by the rank of the simple module representative.*)\nDefinition socle_mult (W : sG) := (\\rank W %/ \\rank (socle_base W))%N.\n\n(*This lemma states that the matrix module representative associated with an isotypic component via the `socle_base` definition is a simple module.*)\nLemma socle_simple W : mxsimple (socle_base W).\n\n(*This definition defines the simple module associated with a given simple module type.*)\nDefinition socle_module (W : sG) := mxsimple_module (socle_simple W).\n\n(*This definition provides a submodule representation for the simple module corresponding to a given simple module type.*)\nDefinition socle_repr W := submod_repr (socle_module W).\n\n(*This lemma states that the matrix representation of any simple module from the socle type is a non-zero matrix.*)\nLemma nz_socle (W : sG) : W != 0 :> 'M_n.\n\n(*This lemma states that the matrix representation of any simple module from the socle type belongs to the enumeration of all socle simple modules.*)\nLemma socle_mem (W : sG) : (W : 'M_n) \\in socle_enum.\n\n(*This lemma states that packing a simple module's matrix representation into its abstract type and then coercing it back to a matrix yields the original matrix.*)\nLemma PackSocleK W e0W : @PackSocle W e0W = W :> 'M_n.\n\nHB.instance Definition _ := isSub.Build _ _ sG socle_sort_rect PackSocleK.\nHB.instance Definition _ := [Choice of sG by <:].\n\n(*This lemma states that the boolean equality test for two simple module types accurately reflects their propositional equality.*)\nLemma socleP (W W' : sG) : reflect (W = W') (W == W')%MS.\n\n(*This fact establishes a cancellation property between mapping a simple module type to its enumeration index and reconstructing the simple module type from that index, which is used to prove that the type of simple modules is countable and finite.*)\nFact socle_can_subproof :\n cancel (fun W => SeqSub (socle_mem W)) (fun s => PackSocle (valP s)).\n\nHB.instance Definition _ := isCountable.Build sG\n (pcan_pickleK (can_pcan socle_can_subproof)).\n(*A notation for the direct sum of all simple modules of a given socle type that satisfy a specific predicate.*)\nNotation S := (\\sum_(W : sG | P W) socle_val W)%MS.\n\n(*This lemma states that the direct sum of a collection of simple modules satisfying a given predicate forms a module.*)\nLemma subSocle_module : mxmodule S.\n\n(*This lemma states that the direct sum of a collection of simple modules satisfying a given predicate is a semisimple module.*)\nLemma subSocle_semisimple : mxsemisimple S.\n\n(*A local notation that serves as an abbreviation for the proof that a submodule formed by a sum of simple modules is semisimple.*)\nLocal Notation ssimS := subSocle_semisimple.\n\n(*This lemma states that any simple submodule of a direct sum of simple modules is isomorphic to one of those simple modules in the sum.*)\nLemma subSocle_iso M :\n mxsimple M -> (M <= S)%MS -> {W : sG | P W & mx_iso (socle_base W) M}.\n\n(*This lemma states that the intersection of a module with a direct sum of simple modules is equal to the direct sum of the intersections of the module with each of those simple modules.*)\nLemma capmx_subSocle m (M : 'M_(m, n)) :\n mxmodule M -> (M :&: S :=: \\sum_(W : sG | P W) (M :&: W))%MS.\n\nEnd SubSocle.\n\n(*This lemma states that the sum of a collection of simple modules satisfying a given predicate is a direct sum.*)\nLemma subSocle_direct P : mxdirect (\\sum_(W : sG | P W) W).\n\n(*This definition specifies the socle of a representation as the direct sum of all its simple submodules.*)\nDefinition Socle := (\\sum_(W : sG) W)%MS.\n\n(*This lemma states that any simple module is a submodule of the socle.*)\nLemma simple_Socle M : mxsimple M -> (M <= Socle)%MS.\n\n(*This lemma states that any semisimple module is a submodule of the socle.*)\nLemma semisimple_Socle U : mxsemisimple U -> (U <= Socle)%MS.\n\n(*This lemma states that any completely reducible module is a submodule of the socle.*)\nLemma reducible_Socle U :\n mxmodule U -> mx_completely_reducible U -> (U <= Socle)%MS.\n\n(*This lemma states that the module generated by the elements of the socle is the socle itself.*)\nLemma genmx_Socle : <>%MS = Socle.\n\n(*This lemma states that if the entire module is completely reducible, then the socle is equal to the entire module.*)\nLemma reducible_Socle1 : mx_completely_reducible 1%:M -> Socle = 1%:M.\n\n(*This lemma states that the socle itself forms a module.*)\nLemma Socle_module : mxmodule Socle. \n\n(*This lemma states that the socle is a semisimple module.*)\nLemma Socle_semisimple : mxsemisimple Socle.\n\n(*This lemma states that the socle is constructed as a direct sum of its simple components.*)\nLemma Socle_direct : mxdirect Socle. \n\n(*This lemma states that any simple module is isomorphic to one of the canonical simple modules that constitute the socle.*)\nLemma Socle_iso M : mxsimple M -> {W : sG | mx_iso (socle_base W) M}.\n\nEnd Socle.\n\nSection CentHom.\n\nVariable f : 'M[F]_n.\n\n(*This lemma states that the homomorphism domain of a matrix covers the entire space if and only if that matrix commutes with the group representation.*)\nLemma row_full_dom_hom : row_full (dom_hom_mx f) = centgmx rG f.\n\n(*This lemma states that a matrix being in the centralizer of the enveloping algebra is equivalent to that matrix commuting with the group representation.*)\nLemma memmx_cent_envelop : (f \\in 'C(E_G))%MS = centgmx rG f.\n\n(*This lemma states that if a matrix commutes with a group representation, then the kernel of that matrix is a submodule.*)\nLemma kermx_centg_module : centgmx rG f -> mxmodule (kermx f).\n\n(*This lemma states that if a matrix commutes with a group representation, then any given submodule is also a submodule of a specific module associated with the homomorphism domain of that matrix.*)\nLemma centgmx_hom m (U : 'M_(m, n)) : centgmx rG f -> (U <= dom_hom_mx f)%MS.\n\nEnd CentHom.\n\n(*This definition specifies that a module is irreducible if the entire space itself is a simple module, meaning it has no non-trivial submodules.*)\nDefinition mx_irreducible := mxsimple 1%:M.\n\n(*This lemma provides a reflection property, connecting the propositional statement of a module's irreducibility with a corresponding boolean computation.*)\nLemma mx_irrP :\n mx_irreducible <-> n > 0 /\\ (forall U, @mxmodule n U -> U != 0 -> row_full U).\n\n(*This lemma states that for an irreducible matrix representation, any non-zero matrix that commutes with all matrices in the representation is invertible.*)\nLemma mx_Schur :\n mx_irreducible -> forall f, centgmx rG f -> f != 0 -> f \\in unitmx.\n\n(*This definition specifies that a matrix representation is absolutely irreducible if it has a positive dimension and its enveloping algebra spans the entire space of matrices of that dimension.*)\nDefinition mx_absolutely_irreducible := (n > 0) && row_full E_G.\n\n(*This lemma provides an equivalent logical condition for a matrix representation to be absolutely irreducible, relating the property to the positive dimension of the representation and the spanning property of its enveloping algebra.*)\nLemma mx_abs_irrP :\n reflect (n > 0 /\\ exists a_, forall A, A = \\sum_(x in G) a_ x A *: rG x)\n mx_absolutely_irreducible.\n\n(*This lemma states that for an absolutely irreducible matrix representation, any matrix that commutes with all matrices in the representation must be a scalar matrix.*)\nLemma mx_abs_irr_cent_scalar :\n mx_absolutely_irreducible -> forall A, centgmx rG A -> is_scalar_mx A.\n\n(*This lemma states that any absolutely irreducible matrix representation is also an irreducible matrix representation.*)\nLemma mx_abs_irrW : mx_absolutely_irreducible -> mx_irreducible.\n\n(*This lemma states that any one-dimensional matrix representation is absolutely irreducible.*)\nLemma linear_mx_abs_irr : n = 1 -> mx_absolutely_irreducible.\n\n(*This lemma states that for a representation of an abelian group, being absolutely irreducible is equivalent to having a dimension of one.*)\nLemma abelian_abs_irr : abelian G -> mx_absolutely_irreducible = (n == 1).\n\nEnd OneRepresentation.\n\nArguments mxmoduleP {gT G n rG m U}.\nArguments envelop_mxP {gT G n rG A}.\nArguments hom_mxP {gT G n rG m f W}.\nArguments rfix_mxP {gT G n rG m W}.\nArguments cyclic_mxP {gT G n rG u v}.\nArguments annihilator_mxP {gT G n rG u A}.\nArguments row_hom_mxP {gT G n rG u v}.\nArguments mxsimple_isoP {gT G n rG U V}.\nArguments socleP {gT G n rG sG0 W W'}.\nArguments mx_abs_irrP {gT G n rG}.\n\nArguments val_submod {n U m} W.\nArguments in_submod {n} U {m} W.\nArguments val_submodK {n U m} W : rename.\nArguments in_submodK {n U m} [W] sWU.\nArguments val_submod_inj {n U m} [W1 W2] : rename.\n\nArguments val_factmod {n U m} W.\nArguments in_factmod {n} U {m} W.\nArguments val_factmodK {n U m} W : rename.\nArguments in_factmodK {n} U {m} [W] sWU.\nArguments val_factmod_inj {n U m} [W1 W2] : rename.\n\nSection Proper.\n\nVariables (gT : finGroupType) (G : {group gT}) (n' : nat).\n(*This notation defines `n` as the successor of a natural number, which is a common way to represent a positive natural number.*)\nLocal Notation n := n'.+1.\nVariable rG : mx_representation F G n.\n\n(*This lemma asserts that the enveloping algebra of a matrix representation forms a matrix ring.*)\nLemma envelop_mx_ring : mxring (enveloping_algebra_mx rG).\n\nEnd Proper.\n\nSection JacobsonDensity.\n\nVariables (gT : finGroupType) (G : {group gT}) (n : nat).\nVariable rG : mx_representation F G n.\nHypothesis irrG : mx_irreducible rG.\n\n(*This notation defines `E_G` as the enveloping algebra of a given matrix representation, which is the matrix algebra generated by the images of the group elements under the representation.*)\nLocal Notation E_G := (enveloping_algebra_mx rG).\n(*A local notation for the centralizer of the enveloping algebra of a group representation, which corresponds to the algebra of endomorphisms of the associated module.*)\nLocal Notation Hom_G := 'C(E_G)%MS.\n\n(*This lemma states a version of the Jacobson density theorem, asserting that the bicommutant of the enveloping algebra of an irreducible representation is a sub-algebra of the enveloping algebra itself.*)\nLemma mx_Jacobson_density : ('C(Hom_G) <= E_G)%MS.\n\n(*This lemma provides a criterion for absolute irreducibility, stating that a matrix representation is absolutely irreducible if the dimension of its commuter algebra is at most one.*)\nLemma cent_mx_scalar_abs_irr : \\rank Hom_G <= 1 -> mx_absolutely_irreducible rG.\n\nEnd JacobsonDensity.\n\nSection ChangeGroup.\n\nVariables (gT : finGroupType) (G H : {group gT}) (n : nat).\nVariables (rG : mx_representation F G n).\n\nSection SubGroup.\n\nHypothesis sHG : H \\subset G.\n\n(*A local notation for a matrix representation of a group named H, typically derived from a representation of another group G by restriction or isomorphism.*)\nLocal Notation rH := (subg_repr rG sHG).\n\n(*This lemma states that the subspace of fixed points of a group representation is identical to the subspace of fixed points for the same representation restricted to a subgroup.*)\nLemma rfix_subg : rfix_mx rH = rfix_mx rG. \n\nSection Stabilisers.\n\nVariables (m : nat) (U : 'M[F]_(m, n)).\n\n(*This lemma states that the stabilizer of a matrix under a representation restricted to a subgroup is equal to the intersection of that subgroup with the stabilizer of the matrix under the original representation.*)\nLemma rstabs_subg : rstabs rH U = H :&: rstabs rG U.\n\n(*This lemma states that if the row space of a matrix forms a submodule for a group representation, it also forms a submodule for the same representation restricted to any subgroup.*)\nLemma mxmodule_subg : mxmodule rG U -> mxmodule rH U.\n\nEnd Stabilisers.\n\n(*This lemma states that if a matrix space is a module for a group representation and is simple when considered as a module for the representation restricted to a subgroup, then it is also a simple module for the original group representation.*)\nLemma mxsimple_subg M : mxmodule rG M -> mxsimple rH M -> mxsimple rG M.\n\n(*This lemma states that if a matrix representation restricted to a subgroup is irreducible, then the original group representation is also irreducible.*)\nLemma subg_mx_irr : mx_irreducible rH -> mx_irreducible rG.\n\n(*This lemma states that if a matrix representation restricted to a subgroup is absolutely irreducible, then the original group representation is also absolutely irreducible.*)\nLemma subg_mx_abs_irr :\n mx_absolutely_irreducible rH -> mx_absolutely_irreducible rG.\n\nEnd SubGroup.\n\nSection SameGroup.\n\nHypothesis eqGH : G :==: H.\n\n(*This notation introduces `rH` as a matrix representation for a group, derived from another representation of a group that has been proven to be identical.*)\nLocal Notation rH := (eqg_repr rG eqGH).\n\n(*This lemma states that if two matrix representations of a group are equivalent, their corresponding fixed-point subspaces are equal.*)\nLemma rfix_eqg : rfix_mx rH = rfix_mx rG. \n\nSection Stabilisers.\n\nVariables (m : nat) (U : 'M[F]_(m, n)).\n\n(*This lemma states that for a given matrix, its stabilizer subgroup under a group representation is equal to its stabilizer subgroup under any equivalent representation.*)\nLemma rstabs_eqg : rstabs rH U = rstabs rG U.\n\n(*This lemma states that the module generated by a given matrix under a group representation is equal to the module generated by the same matrix under any equivalent representation.*)\nLemma mxmodule_eqg : mxmodule rH U = mxmodule rG U.\n\nEnd Stabilisers.\n\n(*This lemma states that a given module is simple with respect to a group representation if and only if it is simple with respect to any equivalent representation.*)\nLemma mxsimple_eqg M : mxsimple rH M <-> mxsimple rG M.\n\n(*This lemma states that a matrix representation of a group is irreducible if and only if any equivalent representation is also irreducible.*)\nLemma eqg_mx_irr : mx_irreducible rH <-> mx_irreducible rG.\n\n(*This lemma states that the property of a matrix representation of a group being absolutely irreducible is equivalent for any two equivalent representations.*)\nLemma eqg_mx_abs_irr :\n mx_absolutely_irreducible rH = mx_absolutely_irreducible rG.\n\nEnd SameGroup.\n\nEnd ChangeGroup.\n\nSection Morphpre.\n\nVariables (aT rT : finGroupType) (D : {group aT}) (f : {morphism D >-> rT}).\nVariables (G : {group rT}) (n : nat) (rG : mx_representation F G n).\n\n(*A notation for the matrix representation obtained by pre-composing a given group representation with a given group morphism.*)\nLocal Notation rGf := (morphpre_repr f rG).\n\nSection Stabilisers.\nVariables (m : nat) (U : 'M[F]_(m, n)).\n\n(*This lemma states that the stabilizer subgroup of a matrix under a representation pre-composed with a group morphism is the preimage under that morphism of the stabilizer subgroup of the same matrix under the original representation.*)\nLemma rstabs_morphpre : rstabs rGf U = f @*^-1 (rstabs rG U).\n\n(*This lemma states that if the image of a group morphism contains the group associated with a representation, then the module generated by a matrix under the original representation is equal to the module generated by that same matrix under the representation pre-composed with the morphism.*)\nLemma mxmodule_morphpre : G \\subset f @* D -> mxmodule rGf U = mxmodule rG U.\n\nEnd Stabilisers.\n\n(*This lemma states that for a representation pre-composed with a group morphism, the fixed-point subspace of a subset of the domain group is equal to the fixed-point subspace of the image of that subset under the original representation.*)\nLemma rfix_morphpre (H : {set aT}) :\n H \\subset D -> (rfix_mx rGf H :=: rfix_mx rG (f @* H))%MS.\n\n(*This lemma states that if the image of a group morphism contains the group of a representation, then the representation pre-composed with the morphism is irreducible if and only if the original representation is irreducible.*)\nLemma morphpre_mx_irr :\n G \\subset f @* D -> (mx_irreducible rGf <-> mx_irreducible rG).\n\n(*This lemma states that if the image of a group morphism contains the group of a representation, then the property of the representation pre-composed with the morphism being absolutely irreducible is equivalent to the original representation being absolutely irreducible.*)\nLemma morphpre_mx_abs_irr :\n G \\subset f @* D ->\n mx_absolutely_irreducible rGf = mx_absolutely_irreducible rG.\n\nEnd Morphpre.\n\nSection Morphim.\n\nVariables (aT rT : finGroupType) (G D : {group aT}) (f : {morphism D >-> rT}).\nVariables (n : nat) (rGf : mx_representation F (f @* G) n).\n\nHypothesis sGD : G \\subset D.\n\n(*This declaration establishes the fact that a subgroup is contained within the preimage of its image under a group morphism.*)\nLet sG_f'fG : G \\subset f @*^-1 (f @* G).\n\n(*A notation for the matrix representation of a subgroup obtained by restricting a representation of its image under a group morphism.*)\nLocal Notation rG := (morphim_repr rGf sGD).\n\nSection Stabilisers.\nVariables (m : nat) (U : 'M[F]_(m, n)).\n\n(*This lemma states that the stabilizer subgroup of a matrix under a restricted representation is the intersection of the subgroup with the preimage of the stabilizer under the original image representation.*)\nLemma rstabs_morphim : rstabs rG U = G :&: f @*^-1 rstabs rGf U.\n\n(*This lemma states that the module generated by a matrix under a representation restricted to a subgroup is equal to the module generated by that matrix under the representation of the image of the subgroup.*)\nLemma mxmodule_morphim : mxmodule rG U = mxmodule rGf U.\n\nEnd Stabilisers.\n\n(*This lemma states that the fixed-point subspace of a subset of a subgroup under a restricted representation is equal to the fixed-point subspace of the image of that subset under the representation of the image group.*)\nLemma rfix_morphim (H : {set aT}) :\n H \\subset D -> (rfix_mx rG H :=: rfix_mx rGf (f @* H))%MS.\n\n(*This lemma states that a module is simple with respect to a representation restricted to a subgroup if and only if it is simple with respect to the representation of the image of that subgroup.*)\nLemma mxsimple_morphim M : mxsimple rG M <-> mxsimple rGf M.\n\n(*This lemma states that a representation restricted to a subgroup is irreducible if and only if the representation of the image of that subgroup is irreducible.*)\nLemma morphim_mx_irr : (mx_irreducible rG <-> mx_irreducible rGf).\n\n(*This lemma states that the property of a representation restricted to a subgroup being absolutely irreducible is equivalent to the property of the representation of the image of that subgroup being absolutely irreducible.*)\nLemma morphim_mx_abs_irr :\n mx_absolutely_irreducible rG = mx_absolutely_irreducible rGf.\n\nEnd Morphim.\n\nSection Submodule.\n\nVariables (gT : finGroupType) (G : {group gT}) (n : nat).\nVariables (rG : mx_representation F G n) (U : 'M[F]_n) (Umod : mxmodule rG U).\n(*A notation for the subrepresentation corresponding to a given submodule of a matrix representation space.*)\nLocal Notation rU := (submod_repr Umod).\n(*A notation for the quotient representation corresponding to a given submodule of a matrix representation space.*)\nLocal Notation rU' := (factmod_repr Umod).\n\n(*This lemma states that the fixed-point subspace for a subrepresentation is the intersection of the submodule with the fixed-point subspace of the original representation, embedded within the submodule.*)\nLemma rfix_submod (H : {set gT}) :\n H \\subset G -> (rfix_mx rU H :=: in_submod U (U :&: rfix_mx rG H))%MS.\n\n(*This lemma states that the projection of the fixed-point subspace of a representation onto a factor module is a subspace of the fixed-point subspace of the corresponding quotient representation.*)\nLemma rfix_factmod (H : {set gT}) :\n H \\subset G -> (in_factmod U (rfix_mx rG H) <= rfix_mx rU' H)%MS.\n\n(*This lemma states that the stabilizer of a matrix under a subrepresentation is equal to the stabilizer of the embedding of that matrix into the original representation space.*)\nLemma rstab_submod m (W : 'M_(m, \\rank U)) :\n rstab rU W = rstab rG (val_submod W).\n\n(*This lemma states that the stabilizer subgroup of a matrix under a subrepresentation is equal to the stabilizer subgroup of the embedding of that matrix into the original representation space.*)\nLemma rstabs_submod m (W : 'M_(m, \\rank U)) :\n rstabs rU W = rstabs rG (val_submod W).\n\n(*This lemma states that the module generated by the embedding of a matrix into a submodule under the original representation is equal to the module generated by that matrix under the subrepresentation.*)\nLemma val_submod_module m (W : 'M_(m, \\rank U)) :\n mxmodule rG (val_submod W) = mxmodule rU W.\n\n(*This lemma states that if a matrix is contained within a submodule, then the module it generates under the original representation is equal to the module generated by its coordinate representation under the subrepresentation.*)\nLemma in_submod_module m (V : 'M_(m, n)) :\n (V <= U)%MS -> mxmodule rU (in_submod U V) = mxmodule rG V.\n\n(*This lemma establishes a relationship between the stabilizer of a matrix in the ambient representation space and the stabilizer of its projection into the factor module under the quotient representation.*)\nLemma rstab_factmod m (W : 'M_(m, n)) :\n rstab rG W \\subset rstab rU' (in_factmod U W).\n\n(*This lemma states that the stabilizer subgroup for a submodule under a quotient representation is equal to the stabilizer subgroup for the corresponding lifted submodule under the original representation.*)\nLemma rstabs_factmod m (W : 'M_(m, \\rank (cokermx U))) :\n rstabs rU' W = rstabs rG (U + val_factmod W)%MS.\n\n(*This lemma states that the module generated from a lifted submodule under the original group representation is the same as the module generated from the original submodule under the quotient representation.*)\nLemma val_factmod_module m (W : 'M_(m, \\rank (cokermx U))) :\n mxmodule rG (U + val_factmod W)%MS = mxmodule rU' W.\n\n(*This lemma states that the module generated by the projection of a submodule into a quotient space under the quotient representation is equal to the module generated by the sum of the original submodules under the original group representation.*)\nLemma in_factmod_module m (V : 'M_(m, n)) :\n mxmodule rU' (in_factmod U V) = mxmodule rG (U + V)%MS.\n\n(*This lemma states that the kernel of a subrepresentation defined by a submodule is identical to the stabilizer of that submodule within the larger group.*)\nLemma rker_submod : rker rU = rstab rG U.\n\n(*This lemma states that the stabilizer of a submodule is normalized by the entire group.*)\nLemma rstab_norm : G \\subset 'N(rstab rG U).\n\n(*This lemma states that the stabilizer of a submodule under a group representation is a normal subgroup of the acting group.*)\nLemma rstab_normal : rstab rG U <| G.\n\n(*This lemma states that if a subrepresentation associated with a submodule is faithful, then the original group representation is also faithful.*)\nLemma submod_mx_faithful : mx_faithful rU -> mx_faithful rG.\n\n(*This lemma states that the kernel of a group representation is a subgroup of the kernel of the corresponding quotient representation.*)\nLemma rker_factmod : rker rG \\subset rker rU'.\n\n(*This lemma states that if a quotient representation is faithful, then the original group representation must also be faithful.*)\nLemma factmod_mx_faithful : mx_faithful rU' -> mx_faithful rG.\n\n(*This lemma states that a subrepresentation is irreducible if and only if its corresponding submodule is a simple module under the action of the group.*)\nLemma submod_mx_irr : mx_irreducible rU <-> mxsimple rG U.\n\nEnd Submodule.\n\nSection Conjugate.\n\nVariables (gT : finGroupType) (G : {group gT}) (n : nat).\nVariables (rG : mx_representation F G n) (B : 'M[F]_n).\n\nHypothesis uB : B \\in unitmx.\n\n(*A notation for the matrix representation obtained by conjugating an existing representation by a given invertible matrix.*)\nLocal Notation rGB := (rconj_repr rG uB).\n\n(*This lemma states that the fixed-point submodule for a subgroup under a conjugated representation is equal to the submodule obtained by conjugating the fixed-point submodule of the original representation by the same matrix.*)\nLemma rfix_conj (H : {set gT}) :\n (rfix_mx rGB H :=: B *m rfix_mx rG H *m invmx B)%MS.\n\n(*This lemma states that the stabilizer subgroup of a submodule under a conjugated representation is the same as the stabilizer subgroup of the submodule transformed by the conjugating matrix under the original representation.*)\nLemma rstabs_conj m (U : 'M_(m, n)) : rstabs rGB U = rstabs rG (U *m B).\n\n(*This lemma states that the module generated from a submodule under a conjugated representation is equal to the module generated from the submodule transformed by the conjugating matrix under the original representation.*)\nLemma mxmodule_conj m (U : 'M_(m, n)) : mxmodule rGB U = mxmodule rG (U *m B).\n\n(*This lemma states that a matrix representation is irreducible if and only if any representation conjugate to it is also irreducible.*)\nLemma conj_mx_irr : mx_irreducible rGB <-> mx_irreducible rG.\n\nEnd Conjugate.\n\nSection Quotient.\n\nVariables (gT : finGroupType) (G : {group gT}) (n : nat).\nVariables (rG : mx_representation F G n) (H : {group gT}).\nHypotheses (krH : H \\subset rker rG) (nHG : G \\subset 'N(H)).\n(*This defines a boolean-valued predicate derived from the proof that a group is a subgroup of the normalizer of another group, effectively checking the normality condition.*)\nLet nHGs := subsetP nHG.\n\n(*A notation for the quotient representation on a quotient group, derived from an original group representation whose kernel contains the normal subgroup.*)\nLocal Notation rGH := (quo_repr krH nHG).\n\nLocal Notation E_ r := (enveloping_algebra_mx r).\n(*This lemma states that the enveloping algebra generated by the matrices of a quotient representation is the same as the enveloping algebra generated by the matrices of the original representation.*)\nLemma quo_mx_quotient : (E_ rGH :=: E_ rG)%MS.\n\n(*This lemma states that for any subgroup of the original group, the fixed-point submodule for the corresponding quotient subgroup under the quotient representation is equal to the fixed-point submodule for the original subgroup under the original representation.*)\nLemma rfix_quo (K : {group gT}) :\n K \\subset G -> (rfix_mx rGH (K / H)%g :=: rfix_mx rG K)%MS.\n\n(*This lemma states that the stabilizer of a submodule under a quotient representation is the quotient group formed by the stabilizer of that same submodule under the original representation and the normal subgroup used for the quotient.*)\nLemma rstabs_quo m (U : 'M_(m, n)) : rstabs rGH U = (rstabs rG U / H)%g.\n\n(*This lemma states that the module generated from a submodule under a quotient representation is the same as the module generated from that submodule under the original representation.*)\nLemma mxmodule_quo m (U : 'M_(m, n)) : mxmodule rGH U = mxmodule rG U.\n\n(*This lemma states that a group representation is irreducible if and only if its corresponding quotient representation is also irreducible.*)\nLemma quo_mx_irr : mx_irreducible rGH <-> mx_irreducible rG.\n\nEnd Quotient.\n\nSection SplittingField.\n\nImplicit Type gT : finGroupType.\n\n(*This definition describes the property of a field being a splitting field for a given group, which holds if every irreducible matrix representation of the group over that field is also absolutely irreducible.*)\nDefinition group_splitting_field gT (G : {group gT}) :=\n forall n (rG : mx_representation F G n),\n mx_irreducible rG -> mx_absolutely_irreducible rG.\n\n(*This definition describes the property of a field being a group closure field, which holds if it is a splitting field for every group of a given finite group type.*)\nDefinition group_closure_field gT :=\n forall G : {group gT}, group_splitting_field G.\n\n(*This lemma states that if a field is a splitting field for a group, it is also a splitting field for any of its quotient groups.*)\nLemma quotient_splitting_field gT (G : {group gT}) (H : {set gT}) :\n G \\subset 'N(H) -> group_splitting_field G -> group_splitting_field (G / H).\n\n(*This lemma states that if a field is a group closure field for a given finite group type, it is also a group closure field for any corresponding coset group type.*)\nLemma coset_splitting_field gT (H : {set gT}) :\n group_closure_field gT -> group_closure_field (coset_of H).\n\nEnd SplittingField.\n\nSection Abelian.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that if a group admits a faithful and irreducible matrix representation, then the center of that group must be cyclic.*)\nLemma mx_faithful_irr_center_cyclic n (rG : mx_representation F G n) :\n mx_faithful rG -> mx_irreducible rG -> cyclic 'Z(G).\n\n(*This lemma states that if an abelian group admits a faithful and irreducible matrix representation, then the group itself must be cyclic.*)\nLemma mx_faithful_irr_abelian_cyclic n (rG : mx_representation F G n) :\n mx_faithful rG -> mx_irreducible rG -> abelian G -> cyclic G.\n\nHypothesis splitG : group_splitting_field G.\n\n(*This lemma states that over a splitting field for a group, any irreducible matrix representation of that group, if it is abelian, must be one-dimensional.*)\nLemma mx_irr_abelian_linear n (rG : mx_representation F G n) :\n mx_irreducible rG -> abelian G -> n = 1.\n\n(*This lemma states that for an abelian group acting over a splitting field, any simple module under a group representation must have a rank of one.*)\nLemma mxsimple_abelian_linear n (rG : mx_representation F G n) M :\n abelian G -> mxsimple rG M -> \\rank M = 1.\n\n(*This lemma states that for a matrix representation of an abelian group, any matrix module with a rank equal to one is a simple module.*)\nLemma linear_mxsimple n (rG : mx_representation F G n) (M : 'M_n) :\n mxmodule rG M -> \\rank M = 1 -> mxsimple rG M.\n\nEnd Abelian.\n\nSection AbelianQuotient.\n\nVariables (gT : finGroupType) (G : {group gT}).\nVariables (n : nat) (rG : mx_representation F G n).\n\n(*This lemma states that if a matrix representation of a finite group is irreducible, then the center of the quotient group formed by the original group and the kernel of the representation is a cyclic group.*)\nLemma center_kquo_cyclic : mx_irreducible rG -> cyclic 'Z(G / rker rG)%g.\n\n(*This lemma states that for an irreducible matrix representation of a finite group over a splitting field, the commutator subgroup is a subset of the kernel of the representation if and only if the dimension of the representation is equal to one.*)\nLemma der1_sub_rker :\n group_splitting_field G -> mx_irreducible rG ->\n (G^`(1) \\subset rker rG)%g = (n == 1)%N.\n\nEnd AbelianQuotient.\n\nSection Similarity.\n\nVariables (gT : finGroupType) (G : {group gT}).\n(*This notation defines `reprG` as a shorthand for the type of matrix representations of a given group over a given field.*)\nLocal Notation reprG := (mx_representation F G).\n\n(*This proposition defines the similarity of two matrix representations. Two representations are similar if they have the same dimension and there exists an invertible matrix that intertwines the representations for every element of the group.*)\nVariant mx_rsim n1 (rG1 : reprG n1) n2 (rG2 : reprG n2) : Prop :=\n MxReprSim B of n1 = n2 & row_free B\n & forall x, x \\in G -> rG1 x *m B = B *m rG2 x.\n\n(*This lemma states that two similar matrix representations must have the same dimension.*)\nLemma mxrank_rsim n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n mx_rsim rG1 rG2 -> n1 = n2.\n\n(*This lemma states that the matrix representation similarity relation is reflexive, meaning any matrix representation is similar to itself.*)\nLemma mx_rsim_refl n (rG : reprG n) : mx_rsim rG rG.\n\n(*This lemma states that the matrix representation similarity relation is symmetric, meaning if a first representation is similar to a second one, then the second representation is also similar to the first.*)\nLemma mx_rsim_sym n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n mx_rsim rG1 rG2 -> mx_rsim rG2 rG1.\n\n(*This lemma states that the matrix representation similarity relation is transitive, meaning if a first representation is similar to a second, and the second is similar to a third, then the first representation is similar to the third.*)\nLemma mx_rsim_trans n1 n2 n3\n (rG1 : reprG n1) (rG2 : reprG n2) (rG3 : reprG n3) :\n mx_rsim rG1 rG2 -> mx_rsim rG2 rG3 -> mx_rsim rG1 rG3.\n\n(*This lemma provides a characterization of matrix representation similarity, stating that if two representations are similar, then there exists an invertible matrix such that the matrices of the first representation can be obtained by conjugating the matrices of the second representation by this invertible matrix.*)\nLemma mx_rsim_def n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n mx_rsim rG1 rG2 ->\n exists B, exists2 B', B' *m B = 1%:M &\n forall x, x \\in G -> rG1 x = B *m rG2 x *m B'.\n\n(*This lemma states that the sub-representations induced by two matrix modules are similar if and only if the two matrix modules are isomorphic.*)\nLemma mx_rsim_iso n (rG : reprG n) (U V : 'M_n)\n (modU : mxmodule rG U) (modV : mxmodule rG V) :\n mx_rsim (submod_repr modU) (submod_repr modV) <-> mx_iso rG U V.\n\n(*This lemma states that if two matrix representations are similar and one of them is irreducible, then the other representation is also irreducible.*)\nLemma mx_rsim_irr n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n mx_rsim rG1 rG2 -> mx_irreducible rG1 -> mx_irreducible rG2.\n\n(*This lemma states that if two matrix representations are similar, then one is absolutely irreducible if and only if the other is also absolutely irreducible.*)\nLemma mx_rsim_abs_irr n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n mx_rsim rG1 rG2 ->\n mx_absolutely_irreducible rG1 = mx_absolutely_irreducible rG2.\n\n(*This lemma states that similar matrix representations have the same kernel.*)\nLemma rker_mx_rsim n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n mx_rsim rG1 rG2 -> rker rG1 = rker rG2.\n\n(*This lemma states that if two matrix representations are similar, then one is faithful if and only if the other is also faithful.*)\nLemma mx_rsim_faithful n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n mx_rsim rG1 rG2 -> mx_faithful rG1 = mx_faithful rG2.\n\n(*This lemma states that if two matrix modules form a direct sum decomposition of the entire space, then the representation on the quotient module by one submodule is similar to the sub-representation on the other submodule.*)\nLemma mx_rsim_factmod n (rG : reprG n) U V\n (modU : mxmodule rG U) (modV : mxmodule rG V) :\n (U + V :=: 1%:M)%MS -> mxdirect (U + V) ->\n mx_rsim (factmod_repr modV) (submod_repr modU).\n\n(*This lemma states that similar matrix representations have the same character, which means that the trace of the matrix corresponding to any given group element is the same for both representations.*)\nLemma mxtrace_rsim n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) :\n mx_rsim rG1 rG2 -> {in G, forall x, \\tr (rG1 x) = \\tr (rG2 x)}.\n\n(*This lemma states that if two matrix representations are similar, and one maps a group element to a scalar matrix, then the other representation must map the same group element to the same scalar matrix.*)\nLemma mx_rsim_scalar n1 n2 (rG1 : reprG n1) (rG2 : reprG n2) x c :\n x \\in G -> mx_rsim rG1 rG2 -> rG1 x = c%:M -> rG2 x = c%:M.\n\nEnd Similarity.\n\nSection Socle.\n\nVariables (gT : finGroupType) (G : {group gT}).\nVariables (n : nat) (rG : mx_representation F G n) (sG : socleType rG).\n\n(*This lemma states that the matrix representation corresponding to any simple component of the socle of a module is irreducible.*)\nLemma socle_irr (W : sG) : mx_irreducible (socle_repr W).\n\n(*This lemma establishes that two simple components of a module's socle are equal if and only if their corresponding matrix representations are similar.*)\nLemma socle_rsimP (W1 W2 : sG) :\n reflect (mx_rsim (socle_repr W1) (socle_repr W2)) (W1 == W2).\n\nLocal Notation mG U := (mxmodule rG U).\nLocal Notation sr modV := (submod_repr modV).\n\n(*This lemma states that if a matrix module is contained in another, its sub-representation with respect to the global representation is similar to its sub-representation with respect to the larger module's own sub-representation.*)\nLemma mx_rsim_in_submod U V (modU : mG U) (modV : mG V) :\n let U' := <>%MS in\n (U <= V)%MS ->\n exists modU' : mxmodule (sr modV) U', mx_rsim (sr modU) (sr modU').\n\n(*This lemma states that if a matrix submodule is equal to the entire module space, then its corresponding sub-representation is similar to the original representation.*)\nLemma rsim_submod1 U (modU : mG U) : (U :=: 1%:M)%MS -> mx_rsim (sr modU) rG.\n\n(*This lemma states that if a matrix submodule is equal to the entire module space, its character is identical to the character of the original representation.*)\nLemma mxtrace_submod1 U (modU : mG U) :\n (U :=: 1%:M)%MS -> {in G, forall x, \\tr (sr modU x) = \\tr (rG x)}.\n\n(*This lemma states that if a matrix module is a direct sum of two other matrix modules, then its character is the sum of the characters of the sub-representations corresponding to the two summands.*)\nLemma mxtrace_dadd_mod U V W (modU : mG U) (modV : mG V) (modW : mG W) :\n (U + V :=: W)%MS -> mxdirect (U + V) ->\n {in G, forall x, \\tr (sr modU x) + \\tr (sr modV x) = \\tr (sr modW x)}.\n\n(*This lemma states that if a matrix module is a direct sum of a finite collection of submodules, then its character is the sum of the characters of the sub-representations corresponding to each submodule in the collection.*)\nLemma mxtrace_dsum_mod (I : finType) (P : pred I) U W\n (modU : forall i, mG (U i)) (modW : mG W) :\n let S := (\\sum_(i | P i) U i)%MS in (S :=: W)%MS -> mxdirect S ->\n {in G, forall x, \\sum_(i | P i) \\tr (sr (modU i) x) = \\tr (sr modW x)}.\n\n(*This lemma states that the character of the representation on an isotypic component is equal to the character of the corresponding simple sub-representation multiplied by the multiplicity of that simple module, calculated as the ratio of the ranks of the component and the simple module.*)\nLemma mxtrace_component U (simU : mxsimple rG U) :\n let V := component_mx rG U in\n let modV := component_mx_module rG U in let modU := mxsimple_module simU in\n {in G, forall x, \\tr (sr modV x) = \\tr (sr modU x) *+ (\\rank V %/ \\rank U)}.\n\n(*This lemma states that the character of the representation on the socle of a module is the sum of the characters of its simple components, where each component's character is weighted by its multiplicity in the socle.*)\nLemma mxtrace_Socle : let modS := Socle_module sG in\n {in G, forall x,\n \\tr (sr modS x) = \\sum_(W : sG) \\tr (socle_repr W x) *+ socle_mult W}.\n\nEnd Socle.\n\nSection Clifford.\n\nVariables (gT : finGroupType) (G H : {group gT}).\nHypothesis nsHG : H <| G.\nVariables (n : nat) (rG : mx_representation F G n).\n(*This definition establishes a term for a subgroup, derived from a proof that it is a normal subgroup of a larger group.*)\nLet sHG := normal_sub nsHG.\n(*This definition establishes a term for a normal subgroup, capturing its properties as normal, derived from a corresponding proof of normality.*)\nLet nHG := normal_norm nsHG.\n(*This definition introduces `rH` as the matrix representation of a subgroup `H`, obtained by restricting the matrix representation `rG` of the larger group `G`.*)\nLet rH := subg_repr rG sHG.\n\n(*This lemma states that if a matrix `M` represents a simple module for the representation of a subgroup `H`, then for any element `x` from the parent group `G`, the matrix obtained by multiplying `M` with the matrix representation of `x` also represents a simple module for the representation of the subgroup `H`.*)\nLemma Clifford_simple M x : mxsimple rH M -> x \\in G -> mxsimple rH (M *m rG x).\n\n(*This lemma states that for any element `x` belonging to the centralizer of a subgroup `H` within a group `G`, a given matrix `U` represents a submodule within the domain of the matrix homomorphism defined by the representation of `H` and the matrix representation of `x`.*)\nLemma Clifford_hom x m (U : 'M_(m, n)) :\n x \\in 'C_G(H) -> (U <= dom_hom_mx rH (rG x))%MS.\n\n(*This lemma states that if an element `x` belongs to the centralizer of a subgroup `H` in a group `G`, then any module represented by a matrix `U` is isomorphic, under the representation of `H`, to the module represented by the matrix `U` multiplied by the matrix representation of `x`.*)\nLemma Clifford_iso x U : x \\in 'C_G(H) -> mx_iso rH U (U *m rG x).\n\n(*This lemma states that if two modules, represented by matrices `U` and `V`, are isomorphic under the representation of a subgroup `H`, then for any element `x` in the parent group `G`, the modules obtained by respectively multiplying `U` and `V` with the matrix representation of `x` are also isomorphic under the representation of `H`.*)\nLemma Clifford_iso2 x U V :\n mx_iso rH U V -> x \\in G -> mx_iso rH (U *m rG x) (V *m rG x).\n\n(*This lemma states that for a simple module `M` under the representation of a subgroup `H` and an element `x` from the parent group `G`, the matrix component of the module obtained by multiplying `M` with the matrix representation of `x` is equal to the matrix component of `M` itself multiplied by the matrix representation of `x`.*)\nLemma Clifford_componentJ M x :\n mxsimple rH M -> x \\in G ->\n (component_mx rH (M *m rG x) :=: component_mx rH M *m rG x)%MS.\n\nHypothesis irrG : mx_irreducible rG.\n\n(*This lemma states that for any simple module `M` under the representation of a subgroup `H`, there exists a subset of elements from the parent group `G` such that the sum of modules obtained by multiplying `M` with the matrix representation of each of these elements forms a direct sum that is equal to the identity matrix.*)\nLemma Clifford_basis M : mxsimple rH M ->\n {X : {set gT} | X \\subset G &\n let S := \\sum_(x in X) M *m rG x in S :=: 1%:M /\\ mxdirect S}%MS.\n\nVariable sH : socleType rH.\n\n(*This definition constructs the action of a group element on an element from the socle of a representation. The resulting socle element is derived from the socle component of a simple module that is twisted by the matrix representation of the acting group element.*)\nDefinition Clifford_act (W : sH) x :=\n let Gx := subgP (subg G x) in\n PackSocle (component_socle sH (Clifford_simple (socle_simple W) Gx)).\n\n(*This helper lemma establishes that the defined Clifford action of a group element on a socle element `W` yields a module that is equal to the matrix multiplication of `W` with the matrix representation of the group element.*)\nLet valWact W x : (Clifford_act W x :=: W *m rG (sgval (subg G x)))%MS.\n\n(*This fact asserts that the 'Clifford_act' operation satisfies the defining properties of a group action for the group `G` over the set of socle components.*)\nFact Clifford_is_action : is_action G Clifford_act.\n\n(*This definition formalizes the Clifford action by packaging the 'Clifford_act' operation with the proof that it constitutes a valid group action.*)\nDefinition Clifford_action := Action Clifford_is_action.\n\n(*A notation for the Clifford action, which defines the action of a group on the socle of a module. The action of a group element on a socle component corresponds to right matrix multiplication by the matrix representation of that group element.*)\nLocal Notation \"'Cl\" := Clifford_action (at level 8) : action_scope.\n\n(*This lemma states that for any element `x` in the group `G`, applying the Clifford action of `x` to a socle element `W` results in a module equal to the matrix product of `W` and the matrix representation of `x`.*)\nLemma val_Clifford_act W x : x \\in G -> ('Cl%act W x :=: W *m rG x)%MS.\n\n(*This lemma asserts that the Clifford action of the group `G` on the set of its socle components is transitive, which means that any socle component can be transformed into any other socle component by the action of some element from the group.*)\nLemma Clifford_atrans : [transitive G, on [set: sH] | 'Cl].\n\n(*This lemma states that the socle of the representation of the subgroup `H`, which is the sum of all its simple submodules, is equal to the identity matrix, implying the representation is completely reducible.*)\nLemma Clifford_Socle1 : Socle sH = 1%:M.\n\n(*This lemma provides a dimension-counting formula, stating that the product of the number of socle components and the rank of any single socle component `W` equals the total dimension `n` of the representation space.*)\nLemma Clifford_rank_components (W : sH) : (#|sH| * \\rank W)%N = n.\n\n(*This theorem asserts that for any simple module `M` under a subgroup representation, there exists a natural number `t` and a function that maps each socle component `W` and an index up to `t` to a group element, such that `W` can be expressed as a direct sum of modules created by multiplying `M` with the matrix representations of these group elements.*)\nTheorem Clifford_component_basis M : mxsimple rH M ->\n {t : nat & {x_ : sH -> 'I_t -> gT |\n forall W, let sW := (\\sum_j M *m rG (x_ W j))%MS in\n [/\\ forall j, x_ W j \\in G, (sW :=: W)%MS & mxdirect sW]}}.\n\n(*This lemma states that the central product of the subgroup `H` and its centralizer within the group `G` is a subgroup of the stabilizer of the set of all socle components under the Clifford action.*)\nLemma Clifford_astab : H <*> 'C_G(H) \\subset 'C([set: sH] | 'Cl).\n\n(*This lemma identifies the stabilizer of a single socle component `W` under the Clifford action as being equal to the representation stabilizer of `W` with respect to the main group representation `rG`.*)\nLemma Clifford_astab1 (W : sH) : 'C[W | 'Cl] = rstabs rG W.\n\n(*This lemma states that any socle component `W` forms a simple module when considered under the matrix representation restricted to its own representation stabilizer subgroup.*)\nLemma Clifford_rstabs_simple (W : sH) :\n mxsimple (subg_repr rG (rstabs_sub rG W)) W.\n\nEnd Clifford.\n\nSection JordanHolder.\n\nVariables (gT : finGroupType) (G : {group gT}).\nVariables (n : nat) (rG : mx_representation F G n).\n(*This notation introduces `modG` as a predicate to verify that a given square matrix of a particular size is a submodule for the group representation `rG`.*)\nLocal Notation modG := ((mxmodule rG) n).\n\n(*This lemma states that for two modules `U` and `V` where `U` is a submodule of `V`, the image of `V` within the quotient module formed with respect to `U` is itself a module under the corresponding quotient representation.*)\nLemma section_module (U V : 'M_n) (modU : modG U) (modV : modG V) :\n mxmodule (factmod_repr modU) <>%MS.\n\n(*This definition creates the matrix representation for a section module, which corresponds to the quotient of a module `V` by a submodule `U`. This is achieved by taking the representation of the section viewed as a submodule within a larger quotient space.*)\nDefinition section_repr U V (modU : modG U) (modV : modG V) :=\n submod_repr (section_module modU modV).\n\n(*This lemma asserts that the representation of a section module, formed by taking the quotient of the entire module space by a submodule `U`, is similar to the representation of the quotient module defined directly by `U`.*)\nLemma mx_factmod_sub U modU :\n mx_rsim (@section_repr U _ modU (mxmodule1 rG)) (factmod_repr modU).\n\n(*This definition specifies the property that a module `U` is a maximal submodule of another module `V`. This condition holds if `U` is a proper submodule of `V` and no other submodule `W` exists that is strictly larger than `U` and strictly smaller than `V`.*)\nDefinition max_submod (U V : 'M_n) :=\n (U < V)%MS /\\ (forall W, ~ [/\\ modG W, U < W & W < V])%MS.\n\n(*This lemma establishes an equivalence for modules `U` and `V` where `U` is a submodule of `V`. It states that `U` is a maximal submodule of `V` if and only if the representation on the corresponding section module, which is the quotient of `V` by `U`, is irreducible.*)\nLemma max_submodP U V (modU : modG U) (modV : modG V) :\n (U <= V)%MS -> (max_submod U V <-> mx_irreducible (section_repr modU modV)).\n\n(*This lemma asserts that the property of a module being a maximal submodule of another is preserved under matrix equality. Specifically, if `U1` is a maximal submodule of `V1`, and matrices `U1` and `V1` are respectively equal to matrices `U2` and `V2`, then `U2` is also a maximal submodule of `V2`.*)\nLemma max_submod_eqmx U1 U2 V1 V2 :\n (U1 :=: U2)%MS -> (V1 :=: V2)%MS -> max_submod U1 V1 -> max_submod U2 V2.\n\n(*This definition introduces a predicate to determine if a given list of matrices represents a valid subseries. A list qualifies as a subseries if every matrix in the list represents a submodule under the given group representation.*)\nDefinition mx_subseries := all modG.\n\n(*This definition specifies that a sequence of modules is a composition series if it constitutes a subseries where for each index, the module at the preceding position is a maximal submodule of the module at the current position, ensuring all factor modules are simple.*)\nDefinition mx_composition_series V :=\n mx_subseries V /\\ (forall i, i < size V -> max_submod (0 :: V)`_i V`_i).\n(*This notation provides a local shorthand for `mx_composition_series`, which represents a composition series of modules.*)\nLocal Notation mx_series := mx_composition_series.\n\n(*This fact states that for a given sequence of modules that forms a subseries, any module at a specific index within that sequence is itself a module.*)\nFact mx_subseries_module V i : mx_subseries V -> mxmodule rG V`_i.\n\n(*This fact states that for a sequence of modules forming a subseries, any module at a specific index within the sequence prefixed by the zero module is also a module.*)\nFact mx_subseries_module' V i : mx_subseries V -> mxmodule rG (0 :: V)`_i.\n\n(*This definition constructs a representation for a factor module of a given subseries at a specific index. The factor module is the quotient of the module at that index by the module at the preceding index in the series.*)\nDefinition subseries_repr V i (modV : all modG V) :=\n section_repr (mx_subseries_module' i modV) (mx_subseries_module i modV).\n\n(*This definition constructs a representation of a factor module from a composition series at a given index, by specializing the representation for a general subseries.*)\nDefinition series_repr V i (compV : mx_composition_series V) :=\n subseries_repr i (proj1 compV).\n\n(*This lemma states that a composition series forms a strictly increasing chain of submodules ordered by proper inclusion, starting from the zero module.*)\nLemma mx_series_lt V : mx_composition_series V -> path ltmx 0 V.\n\n(*This lemma states that for any strictly increasing chain of submodules starting from the zero module, the length of the chain is at most the rank of the final module in the chain.*)\nLemma max_size_mx_series (V : seq 'M[F]_n) :\n path ltmx 0 V -> size V <= \\rank (last 0 V).\n\n(*This lemma asserts that for any valid index within a given composition series, the corresponding factor module representation is irreducible.*)\nLemma mx_series_repr_irr V i (compV : mx_composition_series V) :\n i < size V -> mx_irreducible (series_repr i compV).\n\n(*This lemma provides a condition for extending a composition series with an additional module. It states that appending a module to an existing series results in a new composition series if and only if the original sequence is a composition series, the new element is a module, and the last module of the original series is a maximal submodule of the new module.*)\nLemma mx_series_rcons U V :\n mx_series (rcons U V) <-> [/\\ mx_series U, modG V & max_submod (last 0 U) V].\n\n(*This theorem states that under classical logic, any given subseries of modules that forms a strictly increasing chain from the zero module contains a composition series as a subsequence, where this composition series terminates at the total module.*)\nTheorem mx_Schreier U :\n mx_subseries U -> path ltmx 0 U ->\n classically (exists V, [/\\ mx_series V, last 0 V :=: 1%:M & subseq U V])%MS.\n\n(*This lemma, an instance of the Second Isomorphism Theorem for modules, states that for any two modules, the quotient of the first module by their intersection is isomorphic to the quotient of their sum by the second module.*)\nLemma mx_second_rsim U V (modU : modG U) (modV : modG V) :\n let modI := capmx_module modU modV in let modA := addsmx_module modU modV in\n mx_rsim (section_repr modI modU) (section_repr modV modA).\n\n(*This lemma states a condition for isomorphism of quotient modules. Given two pairs of modules, if the submodules are equal and the sums of the module and submodule in each pair are also equal, then their corresponding quotient modules are isomorphic.*)\nLemma section_eqmx_add U1 U2 V1 V2 modU1 modU2 modV1 modV2 :\n (U1 :=: U2)%MS -> (U1 + V1 :=: U2 + V2)%MS ->\n mx_rsim (@section_repr U1 V1 modU1 modV1) (@section_repr U2 V2 modU2 modV2).\n\n(*This lemma states that if two pairs of modules are respectively equal, then the quotient module formed by the first pair is isomorphic to the quotient module formed by the second pair.*)\nLemma section_eqmx U1 U2 V1 V2 modU1 modU2 modV1 modV2\n (eqU : (U1 :=: U2)%MS) (eqV : (V1 :=: V2)%MS) :\n mx_rsim (@section_repr U1 V1 modU1 modV1) (@section_repr U2 V2 modU2 modV2).\n\n(*This lemma, related to the Butterfly Lemma, states that if two distinct modules are both maximal submodules of a third module, then their intersection is a maximal submodule of the first, and the quotient of the third module by the second is isomorphic to the quotient of the first module by their intersection.*)\nLemma mx_butterfly U V W modU modV modW :\n ~~ (U == V)%MS -> max_submod U W -> max_submod V W ->\n let modUV := capmx_module modU modV in\n max_submod (U :&: V)%MS U\n /\\ mx_rsim (@section_repr V W modV modW) (@section_repr _ U modUV modU).\n\n(*This lemma asserts the existence of a new composition series derived from an existing one. It states that if a given module is a maximal submodule of the final module in a composition series, then there exists another composition series whose final module is that given module.*)\nLemma mx_JordanHolder_exists U V :\n mx_composition_series U -> modG V -> max_submod V (last 0 U) ->\n {W : seq 'M_n | mx_composition_series W & last 0 W = V}.\n\n(*This lemma states that when a composition series is extended by one module, the factor modules corresponding to the original part of the series remain isomorphic to their counterparts in the new, extended series.*)\nLet rsim_rcons U V compU compUV i : i < size U ->\n mx_rsim (@series_repr U i compU) (@series_repr (rcons U V) i compUV).\n\n(*This definition establishes that the final module in a non-empty composition series is itself a well-formed module.*)\nLet last_mod U (compU : mx_series U) : modG (last 0 U).\n\n(*This lemma states that the final factor module of a composition series extended by one element is isomorphic to the quotient module formed by the new final module and the previous final module.*)\nLet rsim_last U V modUm modV compUV :\n mx_rsim (@section_repr (last 0 U) V modUm modV)\n (@series_repr (rcons U V) (size U) compUV).\n\n(*This notation provides a shorthand for the transitivity property of the module isomorphism relation, which states that if a first module is isomorphic to a second, and the second is isomorphic to a third, then the first is isomorphic to the third.*)\nLocal Notation rsimT := mx_rsim_trans.\n(*This notation provides a shorthand for the symmetry property of the module isomorphism relation, which states that if a first module is isomorphic to a second module, then the second module is also isomorphic to the first.*)\nLocal Notation rsimC := mx_rsim_sym.\n\n(*This lemma, which is the Jordan-Holder Theorem for modules, states that any two composition series for the same module have the same length, and their factor modules are isomorphic to each other up to a permutation.*)\nLemma mx_JordanHolder U V compU compV :\n let m := size U in (last 0 U :=: last 0 V)%MS ->\n m = size V /\\ (exists p : 'S_m, forall i : 'I_m,\n mx_rsim (@series_repr U i compU) (@series_repr V (p i) compV)).\n\n(*This lemma states that for any composition series of the total module, any irreducible quotient module is necessarily isomorphic to one of the factor modules of that composition series.*)\nLemma mx_JordanHolder_max U (m := size U) V compU modV :\n (last 0 U :=: 1%:M)%MS -> mx_irreducible (@factmod_repr _ G n rG V modV) ->\n exists i : 'I_m, mx_rsim (factmod_repr modV) (@series_repr U i compU).\n\nEnd JordanHolder.\n\nBind Scope irrType_scope with socle_sort.\n\nSection Regular.\n\nVariables (gT : finGroupType) (G : {group gT}).\n(*This notation defines a shorthand for the order, or number of elements, of the underlying group.*)\nLocal Notation nG := #|pred_of_set (gval G)|.\n\n(*This notation provides a shorthand for the regular representation of a given group over a field.*)\nLocal Notation aG := (regular_repr F G).\n(*This notation provides a shorthand for the group ring formed from a given group and a field.*)\nLocal Notation R_G := (group_ring F G).\n\n(*This lemma states that the canonical basis for the group ring is row-free, establishing that the group ring is a free module.*)\nLemma gring_free : row_free R_G.\n\n(*This lemma states that applying the group ring operation, defined via the regular group representation, to an element of the group ring results in that same element.*)\nLemma gring_op_id A : (A \\in R_G)%MS -> gring_op aG A = A.\n\n(*This lemma states that for any matrix in the group ring, applying the group ring matrix constructor to its corresponding group ring row representation yields the original matrix.*)\nLemma gring_rowK A : (A \\in R_G)%MS -> gring_mx aG (gring_row A) = A.\n\n(*This lemma states that a group ring matrix constructed from a row vector belongs to the right module generated by another matrix if and only if the original row vector is pointwise less than or equal to that matrix.*)\nLemma mem_gring_mx m a (M : 'M_(m, nG)) :\n (gring_mx aG a \\in M *m R_G)%MS = (a <= M)%MS.\n\n(*This lemma states that a given matrix is a member of the right module generated by a second matrix if and only if the given matrix is an element of the group ring and its group ring row representation is pointwise less than or equal to the second matrix.*)\nLemma mem_sub_gring m A (M : 'M_(m, nG)) :\n (A \\in M *m R_G)%MS = (A \\in R_G)%MS && (gring_row A <= M)%MS.\n\nSection GringMx.\n\nVariables (n : nat) (rG : mx_representation F G n).\n\n(*This lemma states that a group ring matrix constructed from a row vector is an element of the enveloping algebra associated with the given matrix representation.*)\nLemma gring_mxP a : (gring_mx rG a \\in enveloping_algebra_mx rG)%MS.\n\n(*This lemma states that the group ring operator applied to the matrix product of two matrices is equal to the matrix product of the aformentioned operator applied to each matrix individually, provided the second matrix belongs to the group ring.*)\nLemma gring_opM A B :\n (B \\in R_G)%MS -> gring_op rG (A *m B) = gring_op rG A *m gring_op rG B.\n\nHypothesis irrG : mx_irreducible rG.\n\n(*This lemma asserts the existence of a matrix that forms a module, such that the representation of the corresponding factor module is similar to a given matrix representation.*)\nLemma rsim_regular_factmod :\n {U : 'M_nG & {modU : mxmodule aG U & mx_rsim rG (factmod_repr modU)}}.\n\n(*This lemma states that for any composition series of a module whose last element is the identity matrix, there exists a factor in the series whose representation is similar to a given matrix representation.*)\nLemma rsim_regular_series U (compU : mx_composition_series aG U) :\n (last 0 U :=: 1%:M)%MS ->\n exists i : 'I_(size U), mx_rsim rG (series_repr i compU).\n\nHypothesis F'G : [pchar F]^'.-group G.\n\n(*This lemma asserts that, under the condition that the group is a p-prime group for the given field, there exists a matrix that forms a module, such that the representation of that submodule is similar to a given matrix representation.*)\nLemma rsim_regular_submod_pchar :\n {U : 'M_nG & {modU : mxmodule aG U & mx_rsim rG (submod_repr modU)}}.\n\nEnd GringMx.\n\n(*This definition specifies a matrix as the sum of the regular representations of all elements within a given set of group elements.*)\nDefinition gset_mx (A : {set gT}) := \\sum_(x in A) aG x.\n\n(*This notation defines a natural number that represents the count of conjugacy classes within a group.*)\nLocal Notation tG := #|pred_of_set (classes (gval G))|.\n\n(*This definition constructs a matrix whose rows are the matrix representations of the conjugacy classes of a group, enumerated in order.*)\nDefinition classg_base := \\matrix_(k < tG) mxvec (gset_mx (enum_val k)).\n\n(*This lemma is a prerequisite asserting that for any element in a group, its conjugacy class is a subset of that group.*)\nLet groupCl : {in G, forall x, {subset x ^: G <= G}}.\n\n(*This lemma states that the rows of the matrix formed from the conjugacy classes of a group are linearly independent.*)\nLemma classg_base_free : row_free classg_base.\n\n(*This lemma states that the matrix constructed from the conjugacy classes of a group forms a basis for the center of the group ring.*)\nLemma classg_base_center : (classg_base :=: 'Z(R_G))%MS.\n\n(*This lemma states that a matrix forms a module under the regular representation if and only if the right module generated by that matrix constitutes a right ideal of the group ring.*)\nLemma regular_module_ideal m (M : 'M_(m, nG)) :\n mxmodule aG M = right_mx_ideal R_G (M *m R_G).\n\n(*This definition establishes an alias for the type that enumerates the simple submodules, or irreducible components, of the regular representation.*)\nDefinition irrType := socleType aG.\nIdentity Coercion type_of_irrType : irrType >-> socleType.\n\nVariable sG : irrType.\n\n(*This definition specifies the degree of an irreducible representation as the rank of the matrix that forms its socle basis.*)\nDefinition irr_degree (i : sG) := \\rank (socle_base i).\n(*This notation provides a shorthand for expressing the degree of a given irreducible representation.*)\nLocal Notation \"'n_ i\" := (irr_degree i) : group_ring_scope.\nLocal Open Scope group_ring_scope.\n\n(*This lemma states that the notation for the degree of an irreducible representation is equal to the rank of the matrix that forms its socle basis.*)\nLemma irr_degreeE i : 'n_i = \\rank (socle_base i). \n(*This lemma states that the degree of any irreducible representation is a positive number.*)\nLemma irr_degree_gt0 i : 'n_i > 0.\n\n(*This definition provides the irreducible matrix representation corresponding to a given simple submodule, which is defined as its socle representation.*)\nDefinition irr_repr i : mx_representation F G 'n_i := socle_repr i.\n(*This lemma states that applying an irreducible representation to a group element is equivalent to computing the submodule matrix of the corresponding socle module for that same group element.*)\nLemma irr_reprE i x : irr_repr i x = submod_mx (socle_module i) x.\n\n(*This lemma states that the matrix of fixed points of the regular representation forms a basis equivalent to the group ring row derived from the sum of all group elements.*)\nLemma rfix_regular : (rfix_mx aG G :=: gring_row (gset_mx G))%MS.\n\n(*This lemma states that the matrix of fixed points of the regular representation forms a simple module.*)\nLemma principal_comp_subproof : mxsimple aG (rfix_mx aG G).\n\n(*This definition introduces a unique, opaque key used to lock the definition of the principal component, preventing its automatic unfolding during proofs.*)\nFact principal_comp_key : unit. \n(*This definition constructs the principal component as an element of the type of irreducible components, by packaging the socle component identified by the proof that the matrix of fixed points is a simple module.*)\nDefinition principal_comp_def :=\n PackSocle (component_socle sG principal_comp_subproof).\n(*This definition establishes the principal component as an opaque constant by locking its underlying construction with a key, ensuring it is treated abstractly in proofs.*)\nDefinition principal_comp := locked_with principal_comp_key principal_comp_def.\n(*This notation assigns the numeral one as a shorthand for the principal component within the scope of irreducible representation types.*)\nLocal Notation \"1\" := principal_comp : irrType_scope.\n\n(*This lemma states that the principal component forms a basis for the matrix of fixed points of the regular representation.*)\nLemma irr1_rfix : (1%irr :=: rfix_mx aG G)%MS.\n\n(*This lemma states that the rank of the matrix corresponding to the principal component is equal to one.*)\nLemma rank_irr1 : \\rank 1%irr = 1.\n\n(*This lemma states that the degree of the trivial irreducible representation is equal to one.*)\nLemma degree_irr1 : 'n_1 = 1.\n\n(*This definition constructs the Wedderburn component corresponding to a given simple module as the submodule generated by the action of that simple module on the group ring.*)\nDefinition Wedderburn_subring (i : sG) := <>%MS.\n\n(*This notation provides a shorthand for the Wedderburn component corresponding to a given simple module index.*)\nLocal Notation \"''R_' i\" := (Wedderburn_subring i) : group_ring_scope.\n\n(*This lemma states that the internal direct sum of all the Wedderburn components is equal to the submodule generated by the action of the socle of simple modules on the group ring.*)\nLet sums_R : (\\sum_i 'R_i :=: Socle sG *m R_G)%MS.\n\n(*This lemma states that each Wedderburn component is a two-sided ideal of the group ring.*)\nLemma Wedderburn_ideal i : mx_ideal R_G 'R_i.\n\n(*This lemma states that the sum of the Wedderburn components is a direct sum of submodules.*)\nLemma Wedderburn_direct : mxdirect (\\sum_i 'R_i)%MS.\n\n(*This lemma states that for any two distinct simple module indices, the intersection of their corresponding Wedderburn components is the zero submodule.*)\nLemma Wedderburn_disjoint i j : i != j -> ('R_i :&: 'R_j)%MS = 0.\n\n(*This lemma states that for any two distinct simple module indices, the product of their corresponding Wedderburn component ideals is the zero submodule.*)\nLemma Wedderburn_annihilate i j : i != j -> ('R_i * 'R_j)%MS = 0.\n\n(*This lemma states that the product of an element from one Wedderburn component with an element from a different Wedderburn component is the zero element.*)\nLemma Wedderburn_mulmx0 i j A B :\n i != j -> (A \\in 'R_i)%MS -> (B \\in 'R_j)%MS -> A *m B = 0.\n\nHypothesis F'G : [pchar F]^'.-group G.\n\n(*This lemma asserts that the sum of the primitive central idempotents associated with each simple module in a prime characteristic setting is equal to the multiplicative identity of the group ring.*)\nLemma irr_mx_sum_pchar : (\\sum_(i : sG) i = 1%:M)%MS.\n\n(*This lemma states that in a prime characteristic setting, the group ring is equal to the direct sum of all its Wedderburn components.*)\nLemma Wedderburn_sum_pchar : (\\sum_i 'R_i :=: R_G)%MS.\n\n(*This definition constructs the identity element for a specific Wedderburn component subring. This element is obtained by projecting the multiplicative identity of the whole group ring onto that component along the direct sum of all other components.*)\nDefinition Wedderburn_id i :=\n vec_mx (mxvec 1%:M *m proj_mx 'R_i (\\sum_(j | j != i) 'R_j)%MS).\n\n(*This notation provides a shorthand for the identity element of a specific Wedderburn component, which is also a primitive central idempotent.*)\nLocal Notation \"''e_' i\" := (Wedderburn_id i) : group_ring_scope.\n\n(*This lemma states that the sum of the identity elements from all the Wedderburn components is equal to the multiplicative identity of the full group ring.*)\nLemma Wedderburn_sum_id_pchar : \\sum_i 'e_i = 1%:M.\n\n(*This lemma states that the identity element of a given Wedderburn component is a member of that same component.*)\nLemma Wedderburn_id_mem i : ('e_i \\in 'R_i)%MS.\n\n(*This lemma asserts that the constructed element for a given Wedderburn component serves as the multiplicative identity for that component as a ring.*)\nLemma Wedderburn_is_id_pchar i : mxring_id 'R_i 'e_i.\n\n(*This lemma states that each Wedderburn component is an idempotent ideal, meaning that the product of the component with itself as a submodule yields the component itself.*)\nLemma Wedderburn_closed_pchar i : ('R_i * 'R_i = 'R_i)%MS.\n\n(*This lemma asserts that each Wedderburn component, when viewed as a submodule, forms a ring under the inherited matrix multiplication and addition.*)\nLemma Wedderburn_is_ring_pchar i : mxring 'R_i.\n\n(*This lemma states that each Wedderburn component is a minimal two-sided ideal of the group ring. Specifically, any non-zero two-sided ideal that is a submodule of a Wedderburn component must be equal to that component.*)\nLemma Wedderburn_min_ideal_pchar m i (E : 'A_(m, nG)) :\n E != 0 -> (E <= 'R_i)%MS -> mx_ideal R_G E -> (E :=: 'R_i)%MS.\n\nSection IrrComponent.\n\nVariables (n : nat) (rG : mx_representation F G n).\n(*This is a local notation for the matrix whose rows form a basis for the enveloping algebra of a given group representation.*)\nLocal Notation E_G := (enveloping_algebra_mx rG).\n\n(*This lemma states that if a matrix representation is similar to a specific simple representation, then any element from a different, non-corresponding Wedderburn component of the group ring will map to the zero matrix under that representation.*)\nLet not_rsim_op0_pchar (iG j : sG) A :\n mx_rsim rG (socle_repr iG) -> iG != j -> (A \\in 'R_j)%MS ->\n gring_op rG A = 0.\n\n(*This definition identifies the unique simple module component associated with a given irreducible representation. It is defined as the index of the unique primitive central idempotent that does not annihilate the representation.*)\nDefinition irr_comp := odflt 1%irr [pick i | gring_op rG 'e_i != 0].\n(*This notation serves as a shorthand for the index of the unique simple module component associated with a given irreducible representation.*)\nLocal Notation iG := irr_comp.\n\nHypothesis irrG : mx_irreducible rG.\n\n(*This lemma asserts that any irreducible matrix representation is similar to the canonical irreducible representation associated with its own unique simple module component.*)\nLemma rsim_irr_comp_pchar : mx_rsim rG (irr_repr iG).\n\n(*This lemma states that for an irreducible representation, any element from a Wedderburn component not corresponding to the representation's own simple module component will be mapped to the zero matrix by the representation.*)\nLemma irr_comp'_op0_pchar j A : j != iG -> (A \\in 'R_j)%MS -> gring_op rG A = 0.\n\n(*This lemma states that the enveloping algebra of an irreducible representation is precisely the image of its corresponding Wedderburn component under the representation map.*)\nLemma irr_comp_envelop_pchar : ('R_iG *m lin_mx (gring_op rG) :=: E_G)%MS.\n\n(*This lemma states that the kernel of an irreducible representation map has a trivial intersection with the corresponding Wedderburn component of the group ring, which implies the representation map is injective when restricted to that component.*)\nLemma ker_irr_comp_op_pchar : ('R_iG :&: kermx (lin_mx (gring_op rG)))%MS = 0.\n\n(*This lemma explicitly states that the representation map associated with an irreducible representation is injective when its domain is restricted to the corresponding Wedderburn component.*)\nLemma regular_op_inj_pchar :\n {in [pred A | (A \\in 'R_iG)%MS] &, injective (gring_op rG)}.\n\n(*This lemma states that the rank, or vector space dimension, of the Wedderburn component corresponding to an irreducible representation is equal to the rank of that representation's enveloping algebra.*)\nLemma rank_irr_comp_pchar : \\rank 'R_iG = \\rank E_G.\n\nEnd IrrComponent.\n\n(*This lemma states that if two regular representations of a group are similar, then their corresponding irreducible components are identical.*)\nLemma irr_comp_rsim_pchar n1 n2 rG1 rG2 :\n @mx_rsim _ G n1 rG1 n2 rG2 -> irr_comp rG1 = irr_comp rG2.\n\n(*This lemma states that the irreducible component of the i-th irreducible representation is the index i itself.*)\nLemma irr_reprK_pchar i : irr_comp (irr_repr i) = i.\n\n(*This lemma states that applying the i-th irreducible representation to any matrix belonging to the j-th Wedderburn component results in the zero matrix, provided that the indices i and j are different.*)\nLemma irr_repr'_op0_pchar i j A :\n j != i -> (A \\in 'R_j)%MS -> gring_op (irr_repr i) A = 0.\n\n(*This lemma states that the i-th irreducible representation maps the i-th central primitive idempotent of the group algebra to the identity matrix.*)\nLemma op_Wedderburn_id_pchar i : gring_op (irr_repr i) 'e_i = 1%:M.\n\n(*This lemma states that for any simple module contained within the i-th isotypic component of the regular representation, the irreducible component of its corresponding submodule representation is equal to the index i.*)\nLemma irr_comp_id_pchar (M : 'M_nG) (modM : mxmodule aG M) (iM : sG) :\n mxsimple aG M -> (M <= iM)%MS -> irr_comp (submod_repr modM) = iM.\n\n(*This lemma states that the trivial irreducible representation maps every element of the group to the multiplicative identity of the underlying field.*)\nLemma irr1_repr x : x \\in G -> irr_repr 1 x = 1%:M.\n\nHypothesis splitG : group_splitting_field G.\n\n(*This lemma states that the rank, or vector space dimension, of the i-th Wedderburn subring is equal to the square of the degree of the i-th irreducible representation.*)\nLemma rank_Wedderburn_subring_pchar i : \\rank 'R_i = ('n_i ^ 2)%N.\n\n(*This lemma states that the sum of the squares of the degrees of all irreducible representations of the group is equal to the order of the group.*)\nLemma sum_irr_degree_pchar : (\\sum_i 'n_i ^ 2 = nG)%N.\n\n(*This lemma states that the multiplicity of the i-th simple module in the socle of the regular representation is equal to the degree of the i-th irreducible representation.*)\nLemma irr_mx_mult_pchar i : socle_mult i = 'n_i.\n\n(*This lemma states that for any group element, the trace of its matrix in the regular representation is equal to the sum, over all irreducible representations, of the product of the trace of its matrix in that irreducible representation and the degree of that representation.*)\nLemma mxtrace_regular_pchar :\n {in G, forall x, \\tr (aG x) = \\sum_i \\tr (socle_repr i x) *+ 'n_i}.\n\n(*This definition specifies the set of all indices corresponding to irreducible representations of degree one, also known as linear representations.*)\nDefinition linear_irr := [set i | 'n_i == 1].\n\n(*This lemma states that if the group is abelian, then the degree of every irreducible representation is one.*)\nLemma irr_degree_abelian : abelian G -> forall i, 'n_i = 1.\n\n(*This lemma states that if the degree of the i-th irreducible representation is one, then its corresponding irreducible component is equivalent to its socle base.*)\nLemma linear_irr_comp_pchar i : 'n_i = 1 -> (i :=: socle_base i)%MS.\n\n(*This lemma states that the center of the i-th Wedderburn subring is the one-dimensional vector space spanned by the i-th central primitive idempotent.*)\nLemma Wedderburn_subring_center_pchar i : ('Z('R_i) :=: mxvec 'e_i)%MS.\n\n(*This lemma states that the center of the group algebra is the vector space spanned by the set of all central primitive idempotents.*)\nLemma Wedderburn_center_pchar :\n ('Z(R_G) :=: \\matrix_(i < #|sG|) mxvec 'e_(enum_val i))%MS.\n\n(*This lemma states that the number of distinct irreducible representations of a group is equal to the number of conjugacy classes of that group.*)\nLemma card_irr_pchar : #|sG| = tG.\n\nSection CenterMode.\n\nVariable i : sG.\n\n(*This definition provides a valid ordinal index derived from the proof that the degree of the i-th irreducible representation is positive, suitable for indexing matrix entries.*)\nLet i0 := Ordinal (irr_degree_gt0 i).\n\n(*This definition specifies a function that, for a given group element, returns a specific diagonal entry of its matrix in the i-th irreducible representation.*)\nDefinition irr_mode x := irr_repr i x i0 i0.\n\n(*This lemma states that the distinguished diagonal entry of the matrix for the group's identity element, as given by the `irr_mode` function, is the multiplicative identity of the field.*)\nLemma irr_mode1 : irr_mode 1 = 1.\n\n(*This lemma, a consequence of Schur's Lemma, states that for any element in the center of the group, its i-th irreducible representation is a scalar matrix, with the scalar value being determined by the `irr_mode` function.*)\nLemma irr_center_scalar : {in 'Z(G), forall x, irr_repr i x = (irr_mode x)%:M}.\n\n(*This lemma states that the `irr_mode` function is a group homomorphism from the center of the group to the multiplicative group of the underlying field.*)\nLemma irr_modeM : {in 'Z(G) &, {morph irr_mode : x y / (x * y)%g >-> x * y}}.\n\n(*This lemma states that for any element in the center of the group and any natural number exponent, the `irr_mode` function maps the group power of the element to the field power of its image.*)\nLemma irr_modeX n : {in 'Z(G), {morph irr_mode : x / (x ^+ n)%g >-> x ^+ n}}.\n\n(*This lemma states that for any element in the center of the group, its image under the `irr_mode` function is a unit, meaning it is a non-zero element of the field.*)\nLemma irr_mode_unit : {in 'Z(G), forall x, irr_mode x \\is a GRing.unit}.\n\n(*This lemma asserts that the `irr_mode` function maps any element from the center of the group to a non-zero field element.*)\nLemma irr_mode_neq0 : {in 'Z(G), forall x, irr_mode x != 0}.\n\n(*This lemma states that for any element in the center of the group, the `irr_mode` function maps the group inverse of the element to the multiplicative inverse of its image in the field.*)\nLemma irr_modeV : {in 'Z(G), {morph irr_mode : x / (x^-1)%g >-> x^-1}}.\n\nEnd CenterMode.\n\n(*This lemma states that for any group element, its `irr_mode` with respect to the trivial irreducible representation is always equal to one.*)\nLemma irr1_mode x : x \\in G -> irr_mode 1 x = 1.\n\nEnd Regular.\n\n(*This notation provides a shorthand for the principal component, which corresponds to the trivial irreducible representation.*)\nLocal Notation \"[ 1 sG ]\" := (principal_comp sG) : irrType_scope.\n\nSection LinearIrr.\n\nVariables (gT : finGroupType) (G : {group gT}).\n\n(*This lemma states that, over a splitting field, the number of linear irreducible representations of a group is equal to the index of its commutator subgroup, which is the order of the group's abelianization.*)\nLemma card_linear_irr (sG : irrType G) :\n [pchar F]^'.-group G -> group_splitting_field G ->\n #|linear_irr sG| = #|G : G^`(1)|%g.\n\n(*This lemma states that if a field contains a primitive root of unity for the order of a given abelian group, then that field is a splitting field for the group.*)\nLemma primitive_root_splitting_abelian (z : F) :\n #|G|.-primitive_root z -> abelian G -> group_splitting_field G.\n\n(*This lemma describes the structure of representations for cyclic groups, likely relating the representation of a generator to its eigenvalues or character values.*)\nLemma cycle_repr_structure_pchar x (sG : irrType G) :\n G :=: <[x]> -> [pchar F]^'.-group G -> group_splitting_field G ->\n exists2 w : F, #|G|.-primitive_root w &\n exists iphi : 'I_#|G| -> sG,\n [/\\ bijective iphi,\n #|sG| = #|G|,\n forall i, irr_mode (iphi i) x = w ^+ i\n & forall i, irr_repr (iphi i) x = (w ^+ i)%:M].\n\n(*This lemma states that for a cyclic group and a field, if the field's characteristic does not divide the order of the group and the field is a splitting field for the group, then there classically exists an element in the field that is a primitive root of unity whose order is the size of the group.*)\nLemma splitting_cyclic_primitive_root_pchar :\n cyclic G -> [pchar F]^'.-group G -> group_splitting_field G ->\n classically {z : F | #|G|.-primitive_root z}.\n\nEnd LinearIrr.\n\nEnd FieldRepr.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use mx_Maschke_pchar instead.\")]\n(*A deprecated notation for `mx_Maschke_pchar`, which refers to the Maschke matrix. This matrix acts as a projection onto the subspace of invariants of a group representation in a context where the characteristic of the base field does not divide the order of the group.*)\nNotation mx_Maschke := (mx_Maschke_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use rsim_regular_submod_pchar instead.\")]\n(*A deprecated notation for `rsim_regular_submod_pchar`, which identifies a specific submodule within the regular representation of a group, defined in a context where the characteristic of the field does not divide the group's order.*)\nNotation rsim_regular_submod := (rsim_regular_submod_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use irr_mx_sum_pchar instead.\")]\n(*A deprecated notation for `irr_mx_sum_pchar`, which represents a sum constructed from the matrices of irreducible representations, typically used in the decomposition of the group algebra.*)\nNotation irr_mx_sum := (irr_mx_sum_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use Wedderburn_sum_pchar instead.\")]\n(*A deprecated notation for `Wedderburn_sum_pchar`, which denotes a sum related to the Wedderburn decomposition of a semisimple group algebra into a direct product of matrix algebras.*)\nNotation Wedderburn_sum := (Wedderburn_sum_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Wedderburn_sum_id_pchar instead.\")]\n(*A deprecated notation for `Wedderburn_sum_id_pchar`, which represents a sum derived from the Wedderburn decomposition that resolves to an identity element or identity matrix.*)\nNotation Wedderburn_sum_id := (Wedderburn_sum_id_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Wedderburn_is_id_pchar instead.\")]\n(*A deprecated notation for `Wedderburn_is_id_pchar`, which represents a property asserting that a specific sum related to the Wedderburn decomposition evaluates to an identity element.*)\nNotation Wedderburn_is_id:= (Wedderburn_is_id_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Wedderburn_closed_pchar instead.\")]\n(*A deprecated notation for `Wedderburn_closed_pchar`, representing a property that a set or structure associated with the Wedderburn decomposition is closed under certain algebraic operations.*)\nNotation Wedderburn_closed := (Wedderburn_closed_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Wedderburn_is_ring_pchar instead.\")]\n(*A deprecated notation for `Wedderburn_is_ring_pchar`, which represents a property asserting that a specific structure associated with the Wedderburn decomposition forms a ring.*)\nNotation Wedderburn_is_ring := (Wedderburn_is_ring_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Wedderburn_min_ideal_pchar instead.\")]\n(*A deprecated notation for `Wedderburn_min_ideal_pchar`, which refers to a minimal two-sided ideal within the Wedderburn decomposition of a semisimple group algebra.*)\nNotation Wedderburn_min_ideal := (Wedderburn_min_ideal_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use rsim_irr_comp_pchar instead.\")]\n(*A deprecated notation for `rsim_irr_comp_pchar`, representing a component of the regular representation that corresponds to a specific irreducible representation of a group.*)\nNotation rsim_irr_comp := (rsim_irr_comp_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use irr_comp'_op0_pchar instead.\")]\n(*A deprecated notation for `irr_comp'_op0_pchar`, which likely relates to a property of an operator acting on an irreducible component of a representation, possibly concerning its behavior on the zero element.*)\nNotation irr_comp'_op0 := (irr_comp'_op0_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use irr_comp_envelop_pchar instead.\")]\n(*A deprecated notation for `irr_comp_envelop_pchar`, which refers to the enveloping algebra generated by the image of an irreducible component of a group representation.*)\nNotation irr_comp_envelop := (irr_comp_envelop_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use ker_irr_comp_op_pchar instead.\")]\n(*A deprecated notation for `ker_irr_comp_op_pchar`, which represents the kernel of a linear operator associated with an irreducible component of a group representation.*)\nNotation ker_irr_comp_op := (ker_irr_comp_op_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use regular_op_inj_pchar instead.\")]\n(*A deprecated notation for `regular_op_inj_pchar`, which represents a property asserting that a specific operator associated with the regular representation of a group is injective.*)\nNotation regular_op_inj := (regular_op_inj_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use rank_irr_comp_pchar instead.\")]\n(*A deprecated notation for `rank_irr_comp_pchar`, which represents the rank of a matrix or linear operator associated with an irreducible component of a group representation.*)\nNotation rank_irr_comp := (rank_irr_comp_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use irr_comp_rsim_pchar instead.\")]\n(*A deprecated notation for `irr_comp_rsim_pchar`, which likely establishes a relationship between an irreducible component and the regular representation of a group.*)\nNotation irr_comp_rsim := (irr_comp_rsim_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use irr_reprK_pchar instead.\")]\n(*A deprecated notation for `irr_reprK_pchar`, which represents an irreducible representation, possibly one defined over a specific field or given a particular canonical structure.*)\nNotation irr_reprK := (irr_reprK_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use irr_repr'_op0_pchar instead.\")]\n(*A deprecated notation for `irr_repr'_op0_pchar`, which likely corresponds to a property of an operator tied to an irreducible representation, possibly concerning its action on the zero element.*)\nNotation irr_repr'_op0 := (irr_repr'_op0_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use op_Wedderburn_id_pchar instead.\")]\n(*A deprecated notation for `op_Wedderburn_id_pchar`, which represents an operator derived from the Wedderburn decomposition that functions as an identity transformation.*)\nNotation op_Wedderburn_id := (op_Wedderburn_id_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use irr_comp_id_pchar instead.\")]\n(*A deprecated notation for `irr_comp_id_pchar`, which represents an identity element or operator associated with an irreducible component of a group representation.*)\nNotation irr_comp_id := (irr_comp_id_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use rank_Wedderburn_subring_pchar instead.\")]\n(*A deprecated notation for `rank_Wedderburn_subring_pchar`, which represents the rank or dimension of a subring, typically a matrix algebra, that appears as a component in the Wedderburn decomposition of a group algebra.*)\nNotation rank_Wedderburn_subring := (rank_Wedderburn_subring_pchar)\n (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use sum_irr_degree_pchar instead.\")]\n(*A deprecated notation for `sum_irr_degree_pchar`, which represents a value or formula related to the sum of the degrees of the irreducible representations of a group.*)\nNotation sum_irr_degree := (sum_irr_degree_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use irr_mx_mult_pchar instead.\")]\n(*A deprecated notation for `irr_mx_mult_pchar`, which refers to the multiplication operation for matrices associated with irreducible representations.*)\nNotation irr_mx_mult := (irr_mx_mult_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use mxtrace_regular_pchar instead.\")]\n(*A deprecated notation for `mxtrace_regular_pchar`, which represents the trace of the matrix of an element in the regular representation of a group, corresponding to the character of that representation.*)\nNotation mxtrace_regular := (mxtrace_regular_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use linear_irr_comp_pchar instead.\")]\n(*A deprecated notation for `linear_irr_comp_pchar`, which refers to an irreducible component associated with a linear, or one-dimensional, representation of a group.*)\nNotation linear_irr_comp := (linear_irr_comp_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Wedderburn_subring_center_pchar instead.\")]\n(*A deprecated notation for `Wedderburn_subring_center_pchar`, which refers to the center of a subring, typically a matrix algebra, that is a component in the Wedderburn decomposition of a group algebra.*)\nNotation Wedderburn_subring_center := (Wedderburn_subring_center_pchar)\n (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use Wedderburn_center_pchar instead.\")]\n(*A deprecated notation for `Wedderburn_center_pchar`, which refers to the center of an entire ring, typically a group algebra, as described by the Wedderburn structure theorem.*)\nNotation Wedderburn_center := (Wedderburn_center_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Use card_irr_pchar instead.\")]\n(*A deprecated notation for `card_irr_pchar`, which represents the cardinality of the set of non-isomorphic irreducible representations of a group.*)\nNotation card_irr := (card_irr_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use cycle_repr_structure_pchar instead.\")]\n(*A deprecated notation for `cycle_repr_structure_pchar`, which refers to a structure or theorem describing the representations of a cyclic group.*)\nNotation cycle_repr_structure := (cycle_repr_structure_pchar) (only parsing).\n#[deprecated(since=\"mathcomp 2.4.0\",\n note=\"Use splitting_cyclic_primitive_root_pchar instead.\")]\n(*This notation is a deprecated, parsing-only alias for `splitting_cyclic_primitive_root_pchar`, which relates to a field being a splitting field for a cyclic group's primitive root in the context of character theory.*)\nNotation splitting_cyclic_primitive_root :=\n (splitting_cyclic_primitive_root_pchar) (only parsing).\n\nArguments rfix_mx {F gT G%_g n%_N} rG H%_g.\nArguments gset_mx F {gT} G%_g A%_g.\nArguments classg_base F {gT} G%_g _%_g : extra scopes.\nArguments irrType F {gT} G%_g.\nArguments mxmoduleP {F gT G n rG m U}.\nArguments envelop_mxP {F gT G n rG A}.\nArguments hom_mxP {F gT G n rG m f W}.\nArguments mx_Maschke_pchar [F gT G n] rG _ [U].\nArguments rfix_mxP {F gT G n rG m W}.\nArguments cyclic_mxP {F gT G n rG u v}.\nArguments annihilator_mxP {F gT G n rG u A}.\nArguments row_hom_mxP {F gT G n rG u v}.\nArguments mxsimple_isoP {F gT G n rG U V}.\nArguments socle_exists [F gT G n].\nArguments socleP {F gT G n rG sG0 W W'}.\nArguments mx_abs_irrP {F gT G n rG}.\nArguments socle_rsimP {F gT G n rG sG W1 W2}.\n\nArguments val_submod {F n U m} W.\nArguments in_submod {F n} U {m} W.\nArguments val_submodK {F n U m} W : rename.\nArguments in_submodK {F n U m} [W] sWU.\nArguments val_submod_inj {F n U m} [W1 W2] : rename.\n\nArguments val_factmod {F n U m} W.\nArguments in_factmod {F n} U {m} W.\nArguments val_factmodK {F n U m} W : rename.\nArguments in_factmodK {F n} U {m} [W] sWU.\nArguments val_factmod_inj {F n U m} [W1 W2] : rename.\n\n(*This notation represents the Clifford action, which defines the conjugation action of a group on the irreducible characters of one of its normal subgroups.*)\nNotation \"'Cl\" := (Clifford_action _) : action_scope.\n\nArguments gring_row {R gT G} A.\nArguments gring_rowK {F gT G} [A] RG_A.\n\nBind Scope irrType_scope with socle_sort.\n(*This notation designates the principal component of a socle, which is the isotypic component corresponding to the trivial irreducible representation.*)\nNotation \"[ 1 sG ]\" := (principal_comp sG) : irrType_scope.\nArguments irr_degree {F gT G%_G sG} i%_irr.\nArguments irr_repr {F gT G%_G sG} i%_irr _%_g : extra scopes.\nArguments irr_mode {F gT G%_G sG} i%_irr z%_g : rename.\n(*This notation denotes the degree of a given irreducible representation, which corresponds to the dimension of the vector space implementing the representation.*)\nNotation \"''n_' i\" := (irr_degree i) : group_ring_scope.\n(*This notation represents the Wedderburn subring associated with a given irreducible representation, which is a simple component in the Wedderburn decomposition of the group algebra.*)\nNotation \"''R_' i\" := (Wedderburn_subring i) : group_ring_scope.\n(*This notation refers to the central idempotent element associated with a given irreducible representation, which serves as the multiplicative identity within the corresponding Wedderburn subring.*)\nNotation \"''e_' i\" := (Wedderburn_id i) : group_ring_scope.\n\nSection DecideRed.\n\nImport MatrixFormula.\n(*This notation serves as a local alias for a formal term, which represents a symbolic expression within a generic ring structure used for formal computations and decision procedures.*)\nLocal Notation term := GRing.term.\n(*A notation that establishes `True` as an alias for the canonical true proposition within a specific scope, typically used for boolean reflection.*)\nLocal Notation True := GRing.True.\n(*This notation is a local, parsing-only alias representing the logical conjunction operator that combines two formal formulas over a ring.*)\nLocal Notation And := GRing.And (only parsing).\nLocal Notation morphAnd f := ((big_morph f) true andb).\n(*This notation is a local alias for the evaluation function that computes the concrete value of a formal ring expression by substituting its variables with values from a given environment.*)\nLocal Notation eval := GRing.eval.\n(*This notation is a local alias for a predicate that asserts a formal logical formula over a ring is true under a given evaluation of its variables.*)\nLocal Notation holds := GRing.holds.\n(*This notation is a local alias for the type representing quantifier-free formulas within the logical framework for ring expressions.*)\nLocal Notation qf_form := GRing.qf_form.\n(*This notation is a local alias for the function that computes the boolean value of a quantifier-free formula by substituting its variables with values from a given environment.*)\nLocal Notation qf_eval := GRing.qf_eval.\n\nSection Definitions.\n\nVariables (F : fieldType) (gT : finGroupType) (G : {group gT}) (n : nat).\nVariable rG : mx_representation F G n.\n\n(*This definition constructs a logical formula asserting that a matrix of formal terms constitutes a matrix module for a group representation. The formula is a conjunction over all group elements, verifying that the module is closed under the action of each corresponding representation matrix.*)\nDefinition mxmodule_form (U : 'M[term F]_n) :=\n \\big[And/True]_(x in G) submx_form (mulmx_term U (mx_term (rG x))) U.\n\n(*This lemma states that the logical formula generated to represent a matrix module is quantifier-free.*)\nLemma mxmodule_form_qf U : qf_form (mxmodule_form U).\n\n(*This lemma states that evaluating the logical formula for a symbolic matrix module with a specific variable assignment is equivalent to testing the module property on the concrete matrix resulting from that assignment.*)\nLemma eval_mxmodule U e :\n qf_eval e (mxmodule_form U) = mxmodule rG (eval_mx e U).\n\n(*This definition creates a logical formula that asserts a matrix module is not simple. The formula expresses the existence of a proper, non-zero submodule.*)\nDefinition mxnonsimple_form (U : 'M[term F]_n) :=\n let V := vec_mx (row_var F (n * n) 0) in\n let nzV := (~ mxrank_form 0 V)%T in\n let properVU := (submx_form V U /\\ ~ submx_form U V)%T in\n (Exists_row_form (n * n) 0 (mxmodule_form V /\\ nzV /\\ properVU))%T.\n\nEnd Definitions.\n\nVariables (F : decFieldType) (gT : finGroupType) (G : {group gT}) (n : nat).\nVariable rG : mx_representation F G n.\n\n(*This definition provides a computable boolean predicate to determine if a matrix module is non-simple by checking the satisfiability of the logical formula that asserts the existence of a proper, non-zero submodule.*)\nDefinition mxnonsimple_sat U :=\n GRing.sat (@row_env _ (n * n) [::]) (mxnonsimple_form rG (mx_term U)).\n\n(*This lemma states that for a non-zero matrix module, the computable predicate for non-simplicity accurately reflects the mathematical property of a module being non-simple.*)\nLemma mxnonsimpleP U :\n U != 0 -> reflect (mxnonsimple rG U) (mxnonsimple_sat U).\n\n(*This lemma provides a constructive proof that for any non-zero matrix module over a decidable field, a simple submodule contained within it can be found.*)\nLemma dec_mxsimple_exists (U : 'M_n) :\n mxmodule rG U -> U != 0 -> {V | mxsimple rG V & V <= U}%MS.\n\n(*This lemma states that any completely reducible matrix module over a decidable field is also a semisimple module.*)\nLemma dec_mx_reducible_semisimple U :\n mxmodule rG U -> mx_completely_reducible rG U -> mxsemisimple rG U.\n\n(*This lemma establishes that a socle type structure, which facilitates reasoning about the sum of all simple submodules, can be defined for any matrix representation over a decidable field.*)\nLemma DecSocleType : socleType rG.\n\nEnd DecideRed.\n\nPrenex Implicits mxmodule_form mxnonsimple_form mxnonsimple_sat.\n\nSection ChangeOfField.\n\nVariables (aF rF : fieldType) (f : {rmorphism aF -> rF}).\n(*This notation represents the application of a ring morphism to a matrix, resulting in a new matrix where each entry is the image of the corresponding entry in the original matrix under the given morphism.*)\nLocal Notation \"A ^f\" := (map_mx (GRing.RMorphism.sort f) A) : ring_scope.\nVariables (gT : finGroupType) (G : {group gT}).\n\nSection OneRepresentation.\n\nVariables (n : nat) (rG : mx_representation aF G n).\n(*This notation defines a new group representation that is obtained by applying a given ring morphism to all the matrices of an existing representation, thereby changing its underlying field.*)\nLocal Notation rGf := (map_repr f rG).\n\n(*This lemma states that changing the field of the matrix of fixed points of a group action yields the same result as first changing the field of the representation and then computing the fixed points.*)\nLemma map_rfix_mx H : (rfix_mx rG H)^f = rfix_mx rGf H.\n\n(*This lemma states that the centralizer of a matrix with respect to a group representation is unchanged when a ring morphism is used to change the underlying field of both the matrix and the representation.*)\nLemma rcent_map A : rcent rGf A^f = rcent rG A.\n\n(*This lemma states that the stabilizer of a matrix under a group representation action remains the same when a ring morphism changes the underlying field of both the matrix and the representation.*)\nLemma rstab_map m (U : 'M_(m, n)) : rstab rGf U^f = rstab rG U.\n\n(*This lemma states that the pointwise stabilizer of a matrix under a group representation is invariant with respect to a change of the underlying field applied to both the matrix and the representation via a ring morphism.*)\nLemma rstabs_map m (U : 'M_(m, n)) : rstabs rGf U^f = rstabs rG U.\n\n(*This lemma states that the centralizer of a matrix within the algebra generated by a group representation remains unchanged when a ring morphism is applied to both the matrix and the representation to change their field.*)\nLemma centgmx_map A : centgmx rGf A^f = centgmx rG A.\n\n(*This lemma states that a matrix has the module property with respect to a group representation if and only if the corresponding field-changed matrix has the module property with respect to the field-changed representation.*)\nLemma mxmodule_map m (U : 'M_(m, n)) : mxmodule rGf U^f = mxmodule rG U.\n\n(*This lemma states that if a matrix module transformed by a field morphism is simple with respect to the transformed group representation, then the original matrix module is simple with respect to the original group representation.*)\nLemma mxsimple_map (U : 'M_n) : mxsimple rGf U^f -> mxsimple rG U.\n\n(*This lemma states that if a matrix representation of a group transformed by a field morphism is irreducible, then the original representation is also irreducible.*)\nLemma mx_irr_map : mx_irreducible rGf -> mx_irreducible rG.\n\n(*This lemma states that the kernel of a matrix representation of a group remains unchanged when the representation is transformed by a field morphism.*)\nLemma rker_map : rker rGf = rker rG.\n\n(*This lemma states that a matrix representation of a group transformed by a field morphism is faithful if and only if the original representation is faithful.*)\nLemma map_mx_faithful : mx_faithful rGf = mx_faithful rG.\n\n(*This lemma states that a matrix representation of a group transformed by a field morphism is absolutely irreducible if and only if the original representation is absolutely irreducible.*)\nLemma map_mx_abs_irr :\n mx_absolutely_irreducible rGf = mx_absolutely_irreducible rG.\n\nEnd OneRepresentation.\n\n(*This lemma states that if two matrix representations of a group are similar, then their corresponding representations transformed by a field morphism are also similar.*)\nLemma mx_rsim_map n1 n2 rG1 rG2 :\n @mx_rsim _ _ G n1 rG1 n2 rG2 -> mx_rsim (map_repr f rG1) (map_repr f rG2).\n\n(*This lemma states that the matrix representation corresponding to a quotient module, when transformed by a field morphism, is similar to the matrix representation constructed from the quotient of the transformed modules.*)\nLemma map_section_repr n (rG : mx_representation aF G n) rGf U V\n (modU : mxmodule rG U) (modV : mxmodule rG V)\n (modUf : mxmodule rGf U^f) (modVf : mxmodule rGf V^f) :\n map_repr f rG =1 rGf ->\n mx_rsim (map_repr f (section_repr modU modV)) (section_repr modUf modVf).\n\n(*This lemma states that a matrix representation derived from a specific factor in a module's composition series, when transformed by a field morphism, is similar to the representation derived from the corresponding factor in the transformed series.*)\nLemma map_regular_subseries U i (modU : mx_subseries (regular_repr aF G) U)\n (modUf : mx_subseries (regular_repr rF G) [seq M^f | M <- U]) :\n mx_rsim (map_repr f (subseries_repr i modU)) (subseries_repr i modUf).\n\n(*This lemma states that if a field is a splitting field for a given group, then any extension of that field is also a splitting field for the same group.*)\nLemma extend_group_splitting_field :\n group_splitting_field aF G -> group_splitting_field rF G.\n\nEnd ChangeOfField.\n\nModule Import MatrixGenField.\n\n(*This record defines a type for elements of a field extension generated by a matrix that commutes with an irreducible group representation. An element of this type is represented by a row vector corresponding to the coefficients of a polynomial.*)\nRecord gen_of {F : fieldType} {gT : finGroupType} {G : {group gT}} {n' : nat}\n {rG : mx_representation F G n'.+1} {A : 'M[F]_n'.+1}\n (irrG : mx_irreducible rG) (cGA : centgmx rG A) :=\n Gen {rVval : 'rV[F]_(degree_mxminpoly A)}.\n\nLocal Arguments rVval {F gT G%_G n'%_N rG A%_R irrG cGA} x%_R : rename.\nBind Scope ring_scope with gen_of.\n\nSection GenField.\n\nVariables (F : fieldType) (gT : finGroupType) (G : {group gT}) (n' : nat).\n(*This notation defines `n` as the successor of a natural number, which is a common way to represent a positive natural number.*)\nLocal Notation n := n'.+1.\nVariables (rG : mx_representation F G n) (A : 'M[F]_n).\n\n(*This notation defines `d` as the degree of the minimal polynomial associated with a given square matrix.*)\nLocal Notation d := (degree_mxminpoly A).\n(*This notation defines `Ad` as the matrix resulting from raising a given square matrix to the power of a specified natural number.*)\nLocal Notation Ad := (powers_mx A d).\n(*This notation represents the minimal polynomial of a given matrix.*)\nLocal Notation pA := (mxminpoly A).\n(*This definition provides a proof that the degree of the minimal polynomial of a given matrix is strictly greater than zero, which follows from the fact that the minimal polynomial is non-constant.*)\nLet d_gt0 := mxminpoly_nonconstant A.\n(*This notation provides a shorthand for the property that a matrix representation of a group is irreducible.*)\nLocal Notation irr := mx_irreducible.\n\nHypotheses (irrG : irr rG) (cGA : centgmx rG A).\n\n(*This notation defines `FA` as the submodule generated by a specific element under the action of an irreducible group representation.*)\nNotation FA := (gen_of irrG cGA).\n(*This definition provides a constructor function for creating an element of the generated field extension type from a row vector of coefficients.*)\nLet inFA := Gen irrG cGA.\n\n#[export, hnf] HB.instance Definition _ := [isNew for rVval : FA -> 'rV_d].\n#[export] HB.instance Definition _ := [Choice of FA by <:].\n\n(*This definition specifies the zero element of the generated field extension, corresponding to the zero polynomial.*)\nDefinition gen0 := inFA 0.\n(*This definition specifies the additive inverse of an element in the generated field extension, obtained by negating the coefficient vector of the corresponding polynomial.*)\nDefinition genN (x : FA) := inFA (- val x).\n(*This definition specifies the addition of two elements in the generated field extension, which corresponds to the component-wise addition of their polynomial coefficient vectors.*)\nDefinition genD (x y : FA) := inFA (val x + val y).\n\n(*This lemma states that the addition operation defined on the generated field extension is associative.*)\nLemma gen_addA : associative genD.\n\n(*This lemma states that the addition operation defined on the generated field extension is commutative.*)\nLemma gen_addC : commutative genD.\n\n(*This lemma states that the zero element of the generated field extension acts as a left identity for the addition operation.*)\nLemma gen_add0r : left_id gen0 genD.\n\n(*This lemma states that for any element in the generated field extension, its additive inverse acts as a left inverse with respect to the addition operation.*)\nLemma gen_addNr : left_inverse gen0 genN genD.\n\n#[export] HB.instance Definition _ := GRing.isZmodule.Build FA\n gen_addA gen_addC gen_add0r gen_addNr.\n\n(*This definition specifies a function that converts an element of the generated field extension into its corresponding polynomial representation by interpreting its coefficient vector.*)\nDefinition pval (x : FA) := rVpoly (val x).\n\n(*This definition specifies a function that evaluates the polynomial corresponding to an element of the generated field extension at a given matrix, yielding a matrix result.*)\nDefinition mxval (x : FA) := horner_mx A (pval x).\n\n(*This definition specifies a function that embeds an element from the base field into the generated field extension by treating it as a constant polynomial.*)\nDefinition gen (x : F) := inFA (poly_rV x%:P).\n\n(*This lemma states that embedding a scalar from the base field into the generated field extension and then evaluating it as a matrix yields the original scalar represented as a scalar matrix.*)\nLemma genK x : mxval (gen x) = x%:M.\n\n(*This lemma states that the function which evaluates an element of the generated field extension at a given matrix is injective, meaning distinct elements map to distinct matrices.*)\nLemma mxval_inj : injective mxval.\n\n(*This lemma states that the matrix evaluation of the zero element of the field algebra is the zero matrix.*)\nLemma mxval0 : mxval 0 = 0.\n\n(*This lemma states that the matrix evaluation function preserves additive negation, meaning the evaluation of the negative of a field algebra element is the negative of its matrix evaluation.*)\nLemma mxvalN : {morph mxval : x / - x}.\n\n(*This lemma states that the matrix evaluation function is a morphism for addition, meaning it maps the sum of two field algebra elements to the sum of their individual matrix evaluations.*)\nLemma mxvalD : {morph mxval : x y / x + y}.\n\n(*This definition establishes that the matrix evaluation function is a morphism for large sums, meaning the evaluation of a sum of field algebra elements is equal to the sum of their individual matrix evaluations.*)\nDefinition mxval_sum := big_morph mxval mxvalD mxval0.\n\n(*This definition specifies the multiplicative identity element of the field algebra, constructed from the constant polynomial with value one.*)\nDefinition gen1 := inFA (poly_rV 1).\n(*This definition specifies the multiplication operation for the field algebra. It is defined by taking two field algebra elements, multiplying their corresponding polynomial representations, and reducing the resulting polynomial modulo a fixed polynomial.*)\nDefinition genM x y := inFA (poly_rV (pval x * pval y %% pA)).\n(*This definition specifies a function that computes a candidate for the multiplicative inverse of a field algebra element. This is achieved by evaluating the element as a matrix, inverting the matrix, and then using a Horner-scheme-based method to convert the inverse matrix back into a field algebra element.*)\nDefinition genV x := inFA (poly_rV (mx_inv_horner A (mxval x)^-1)).\n\n(*This lemma states that the matrix evaluation of the multiplicative identity element of the field algebra is the identity matrix.*)\nLemma mxval_gen1 : mxval gen1 = 1%:M.\n\n(*This lemma states that the matrix evaluation function is a morphism for multiplication, mapping the product of two field algebra elements under the defined multiplication to the matrix product of their individual evaluations.*)\nLemma mxval_genM : {morph mxval : x y / genM x y >-> x *m y}.\n\n(*This lemma states that the matrix evaluation of the multiplicative inverse candidate of a field algebra element is equal to the matrix inverse of the evaluation of the original element.*)\nLemma mxval_genV : {morph mxval : x / genV x >-> invmx x}.\n\n(*This lemma states that the defined multiplication operation on the field algebra is associative.*)\nLemma gen_mulA : associative genM.\n\n(*This lemma states that the defined multiplication operation on the field algebra is commutative.*)\nLemma gen_mulC : commutative genM.\n\n(*This lemma states that the defined multiplicative identity element for the field algebra acts as a left identity for the multiplication operation.*)\nLemma gen_mul1r : left_id gen1 genM.\n\n(*This lemma states that the defined multiplication operation on the field algebra left-distributes over addition.*)\nLemma gen_mulDr : left_distributive genM +%R.\n\n(*This lemma states that the multiplicative identity element of the field algebra is not equal to the additive identity element.*)\nLemma gen_ntriv : gen1 != 0.\n\n#[export] HB.instance Definition _ := GRing.Zmodule_isComNzRing.Build FA\n gen_mulA gen_mulC gen_mul1r gen_mulDr gen_ntriv.\n\n(*This lemma states that the matrix evaluation of the multiplicative unit of the field algebra is the identity matrix.*)\nLemma mxval1 : mxval 1 = 1%:M. \n\n(*This lemma states that the matrix evaluation function preserves multiplication, mapping the product of two field algebra elements to the matrix product of their evaluations.*)\nLemma mxvalM : {morph mxval : x y / x * y >-> x *m y}.\n\n(*This lemma establishes that the matrix evaluation function is a Z-module morphism, meaning it preserves the structure of addition and the zero element.*)\nLemma mxval_is_zmod_morphism : zmod_morphism mxval.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `mxval_is_zmod_morphism` instead\")]\n(*This definition is a deprecated alias for the lemma stating that the matrix evaluation function is a Z-module morphism.*)\nDefinition mxval_sub := mxval_is_zmod_morphism.\n\n#[export] HB.instance Definition _ :=\n GRing.isZmodMorphism.Build FA 'M[F]_n mxval mxval_is_zmod_morphism.\n\n(*This lemma establishes that the matrix evaluation function is a monoid morphism, meaning it preserves the multiplication operation and the multiplicative identity element.*)\nLemma mxval_is_monoid_morphism : monoid_morphism mxval.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `mxval_is_monoid_morphism` instead\")]\n(*This definition is a deprecated alias for the lemma stating that the matrix evaluation function is a monoid morphism.*)\nDefinition mxval_is_multiplicative :=\n (fun g => (g.2,g.1)) mxval_is_monoid_morphism.\n\n#[export] HB.instance Definition _ :=\n GRing.isMonoidMorphism.Build FA 'M[F]_n mxval mxval_is_monoid_morphism.\n\n(*This lemma states that the matrix evaluation of any field algebra element commutes with the generators of the rational companion matrix group, implying the resulting matrix is in the centralizer of that group.*)\nLemma mxval_centg x : centgmx rG (mxval x).\n\n(*This lemma states that for any non-zero element in the field algebra, multiplying it on the left by its candidate inverse yields the multiplicative identity.*)\nLemma gen_mulVr x : x != 0 -> genV x * x = 1.\n\n(*This lemma states that the candidate multiplicative inverse of the zero element in the field algebra is the zero element itself.*)\nLemma gen_invr0 : genV 0 = 0.\n\n#[export] HB.instance Definition _ := GRing.ComNzRing_isField.Build FA\n gen_mulVr gen_invr0.\n\n(*This lemma states that the matrix evaluation function preserves multiplicative inversion, mapping the inverse of a field algebra element to the matrix inverse of its evaluation.*)\nLemma mxvalV : {morph mxval : x / x^-1 >-> invmx x}.\n\n(*This lemma establishes that the generator function, which embeds elements from a base field into the field algebra, is a Z-module morphism, thus preserving addition and the zero element.*)\nLemma gen_is_zmod_morphism : zmod_morphism gen.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `gen_is_zmod_morphism` instead\")]\n(*This definition is a deprecated alias for the lemma stating that the generator function is a Z-module morphism.*)\nDefinition gen_is_additive := gen_is_zmod_morphism.\n\n(*This lemma establishes that the generator function, which embeds elements from a base field into the field algebra, is a monoid morphism, thus preserving multiplication and the multiplicative identity.*)\nLemma gen_is_monoid_morphism : monoid_morphism gen.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\", deprecated(since=\"mathcomp 2.5.0\",\n note=\"use `gen_is_monoid_morphism` instead\")]\n(*This definition is a deprecated alias for the lemma stating that the generator function is a monoid morphism.*)\nDefinition gen_is_multiplicative :=\n (fun g => (g.2,g.1)) gen_is_monoid_morphism.\n\n#[export] HB.instance Definition _ := GRing.isZmodMorphism.Build F FA gen\n gen_is_zmod_morphism.\n(*This definition specifies the generic root element in the field algebra, which corresponds to the indeterminate of the polynomial ring, reduced modulo a fixed polynomial.*)\nDefinition groot := inFA (poly_rV ('X %% pA)).\n\n(*This lemma states that the evaluation of a specific polynomial at the generalized companion matrix `groot` results in the companion matrix `A`.*)\nLemma mxval_groot : mxval groot = A.\n\n(*This lemma states that for any natural number exponent, evaluating a specific polynomial at the generalized companion matrix `groot` raised to that exponent yields the same result as raising the companion matrix `A` to that same exponent.*)\nLemma mxval_grootXn k : mxval (groot ^+ k) = A ^+ k.\n\n(*This lemma states that the generalized companion matrix `groot` is a root of the polynomial obtained by applying a generator map `gen` to the coefficients of the minimal polynomial of the companion matrix `A`.*)\nLemma map_mxminpoly_groot : (map_poly gen pA).[groot] = 0.\n\n(*This lemma states that if the degree `d` is greater than one, the matrix representation constructed from the generator `gen` is not simple, as demonstrated by the identity matrix.*)\nLemma non_linear_gen_reducible : d > 1 -> mxnonsimple (map_repr gen rG) 1%:M.\n\n(*This definition specifies a function that constructs a matrix, called a subbase, from a given row vector and a natural number. The resulting matrix is formed by arranging blocks, where each block is derived from an element of the input vector and successive powers of the companion matrix `A`.*)\nDefinition subbase nA (B : 'rV_nA) : 'M_(nA * d, n) :=\n \\matrix_ik mxvec (\\matrix_(i, k) (row (B 0 i) (A ^+ k))) 0 ik.\n\n(*This lemma proves that there exists a natural number `nA` and a corresponding row vector `B` for which the subbase matrix derived from `B` has linearly independent rows.*)\nLemma gen_dim_ex_proof : exists nA, [exists B : 'rV_nA, row_free (subbase B)].\n\n(*This lemma establishes that if a row vector exists for a given natural number `nA` such that the corresponding subbase matrix has linearly independent rows, then `nA` must be less than or equal to the ambient dimension `n`.*)\nLemma gen_dim_ub_proof nA :\n [exists B : 'rV_nA, row_free (subbase B)] -> (nA <= n)%N.\n\n(*This definition specifies the generator dimension, `gen_dim`, as the maximum natural number for which it is possible to construct a subbase matrix with linearly independent rows.*)\nDefinition gen_dim := ex_maxn gen_dim_ex_proof gen_dim_ub_proof.\n(*This notation introduces `nA` as an alias for the generator dimension, `gen_dim`.*)\nNotation nA := gen_dim.\n\n(*This definition specifies the generator base as a specific row vector of dimension `nA` that is chosen because it yields a subbase matrix with linearly independent rows.*)\nDefinition gen_base : 'rV_nA := odflt 0 [pick B | row_free (subbase B)].\n(*This definition specifies the base matrix, which is the subbase matrix constructed from the generator base vector `gen_base`.*)\nDefinition base := subbase gen_base.\n\n(*This lemma states that the defined base matrix has linearly independent rows.*)\nLemma base_free : row_free base.\n\n(*This lemma states that the defined base matrix has full row rank.*)\nLemma base_full : row_full base.\n\n(*This lemma states that the product of the generator dimension `nA` and the degree `d` is equal to the ambient space dimension `n`.*)\nLemma gen_dim_factor : (nA * d)%N = n.\n\n(*This lemma states that the generator dimension `nA` is greater than zero.*)\nLemma gen_dim_gt0 : nA > 0.\n\nSection Bijection.\n\nVariable m : nat.\n\n(*This definition specifies a function that transforms a matrix over a base field into a matrix over an extension field by applying a change of basis using the pseudoinverse of the base matrix.*)\nDefinition in_gen (W : 'M[F]_(m, n)) : 'M[FA]_(m, nA) :=\n \\matrix_(i, j) inFA (row j (vec_mx (row i W *m pinvmx base))).\n\n(*This definition specifies a function that transforms a matrix over an extension field back into a matrix over the base field by applying a change of basis using the base matrix.*)\nDefinition val_gen (W : 'M[FA]_(m, nA)) : 'M[F]_(m, n) :=\n \\matrix_i (mxvec (\\matrix_j val (W i j)) *m base).\n\n(*This lemma states that the `in_gen` function is a right inverse of the `val_gen` function, meaning that applying `in_gen` followed by `val_gen` returns the original matrix.*)\nLemma in_genK : cancel in_gen val_gen.\n\n(*This lemma states that the `val_gen` function is a right inverse of the `in_gen` function, meaning that applying `val_gen` followed by `in_gen` returns the original matrix.*)\nLemma val_genK : cancel val_gen in_gen.\n\n(*This lemma states that the `in_gen` transformation maps a zero matrix to a zero matrix.*)\nLemma in_gen0 : in_gen 0 = 0.\n\n(*This lemma states that the `val_gen` transformation maps a zero matrix to a zero matrix.*)\nLemma val_gen0 : val_gen 0 = 0.\n\n(*This lemma states that the `in_gen` transformation is a morphism with respect to matrix addition, meaning the transformation of a sum of matrices equals the sum of their transformations.*)\nLemma in_genD : {morph in_gen : U V / U + V}.\n\n(*This lemma states that the `val_gen` transformation is a morphism with respect to matrix addition, meaning the transformation of a sum of matrices equals the sum of their transformations.*)\nLemma val_genD : {morph val_gen : U V / U + V}.\n\n(*This lemma states that the `in_gen` a transformation preserves additive inverses, meaning the transformation of the negative of a matrix is the negative of its transformation.*)\nLemma in_genN : {morph in_gen : W / - W}.\n\n(*This lemma states that the `val_gen` a transformation preserves additive inverses, meaning the transformation of the negative of a matrix is the negative of its transformation.*)\nLemma val_genN : {morph val_gen : W / - W}.\n\n(*This definition establishes that the `in_gen` transformation commutes with indexed summations of matrices.*)\nDefinition in_gen_sum := big_morph in_gen in_genD in_gen0.\n(*This definition establishes that the `val_gen` transformation commutes with indexed summations of matrices.*)\nDefinition val_gen_sum := big_morph val_gen val_genD val_gen0.\n\n(*This lemma states that the `in_gen` transformation is compatible with scalar multiplication, where scaling a matrix before transformation is equivalent to scaling the transformed matrix by the generator representation of the scalar.*)\nLemma in_genZ a : {morph in_gen : W / a *: W >-> gen a *: W}.\n\nEnd Bijection.\n\nPrenex Implicits val_genK in_genK.\n\n(*This lemma provides a specialized formula for applying the `val_gen` transformation to a single row vector, which involves transforming its components and multiplying by the base matrix.*)\nLemma val_gen_rV (w : 'rV_nA) :\n val_gen w = mxvec (\\matrix_j val (w 0 j)) *m base.\n\nSection Bijection2.\n\nVariable m : nat.\n\n(*This lemma states that the `val_gen` transformation commutes with an operation that selects a row from a matrix, meaning transforming a specific row of a matrix yields the same result as selecting that same row from the already transformed matrix.*)\nLemma val_gen_row W (i : 'I_m) : val_gen (row i W) = row i (val_gen W).\n\n(*This lemma states that the embedding `in_gen` of a row of a matrix is equal to the corresponding row of the embedded matrix.*)\nLemma in_gen_row W (i : 'I_m) : in_gen (row i W) = row i (in_gen W).\n\n(*This lemma states that a row of the matrix obtained by applying the `val_gen` transformation is equal to a weighted sum of basis rows, where the weights are derived from the entries of the corresponding row in the original matrix.*)\nLemma row_gen_sum_mxval W (i : 'I_m) :\n row i (val_gen W) = \\sum_j row (gen_base 0 j) (mxval (W i j)).\n\n(*This lemma asserts that the `val_gen` transformation is a morphism, meaning it correctly maps a matrix scaled by a value `x` to the transformed matrix multiplied by a matrix representation of `x`.*)\nLemma val_genZ x : {morph @val_gen m : W / x *: W >-> W *m mxval x}.\n\nEnd Bijection2.\n\n(*This lemma states that the embedding transformation `in_gen` is monotonic with respect to the submatrix relation, meaning that if one matrix is a submatrix of another, their embedded versions preserve this relationship.*)\nLemma submx_in_gen m1 m2 (U : 'M_(m1, n)) (V : 'M_(m2, n)) :\n (U <= V -> in_gen U <= in_gen V)%MS.\n\n(*This lemma states that under the condition that a matrix `V` is stable under right multiplication by another matrix `A`, the submatrix relation between an embedded matrix `in_gen U` and an embedded matrix `in_gen V` is equivalent to the submatrix relation between the original matrices `U` and `V`.*)\nLemma submx_in_gen_eq m1 m2 (U : 'M_(m1, n)) (V : 'M_(m2, n)) :\n (V *m A <= V -> (in_gen U <= in_gen V) = (U <= V))%MS.\n\n(*This definition specifies a matrix, for a given group element, constructed by embedding each row of the matrix representation of that group element applied to a basis matrix.*)\nDefinition gen_mx g := \\matrix_i in_gen (row (gen_base 0 i) (rG g)).\n\n(*This lemma establishes that for any group element, the `val_gen` transformation acts as a morphism, converting right multiplication by the generated matrix `gen_mx` into right multiplication by the original group representation matrix `rG`.*)\nLet val_genJmx m :\n {in G, forall g, {morph @val_gen m : W / W *m gen_mx g >-> W *m rG g}}.\n\n(*This lemma proves that the mapping from group elements to the generated matrices `gen_mx` constitutes a valid matrix representation for the group.*)\nLemma gen_mx_repr : mx_repr G gen_mx.\n\nCanonical gen_repr := MxRepresentation gen_mx_repr.\n(*A local notation for the canonical matrix representation derived from the generated matrices `gen_mx`, which itself is constructed using the original representation `rG` and a commuting matrix `A`.*)\nLocal Notation rGA := gen_repr.\n\n(*This lemma states that for any group element, the `val_gen` transformation acts as a morphism, mapping right multiplication by a matrix from the `rGA` representation to right multiplication by the corresponding matrix from the `rG` representation.*)\nLemma val_genJ m :\n {in G, forall g, {morph @val_gen m : W / W *m rGA g >-> W *m rG g}}.\n\n(*This lemma states that for any group element, the embedding `in_gen` acts as a morphism, mapping right multiplication by a matrix from the `rG` representation to right multiplication by the corresponding matrix from the `rGA` representation.*)\nLemma in_genJ m :\n {in G, forall g, {morph @in_gen m : v / v *m rG g >-> v *m rGA g}}.\n\n(*This lemma states that for any subset of the group, the right fixed-point space of the `rGA` representation is equivalent to the `in_gen` embedding of the right fixed-point space of the original `rG` representation.*)\nLemma rfix_gen (H : {set gT}) :\n H \\subset G -> (rfix_mx rGA H :=: in_gen (rfix_mx rG H))%MS.\n\n(*This definition specifies a transformation called `rowval_gen` that constructs a new matrix by taking rows of a `val_gen`-transformed input matrix, multiplying them by successive powers of a matrix `A`, and arranging the results into a new matrix.*)\nDefinition rowval_gen m U :=\n <<\\matrix_ik\n mxvec (\\matrix_(i < m, k < d) (row i (val_gen U) *m A ^+ k)) 0 ik>>%MS.\n\n(*This lemma provides an equivalence, stating that one matrix is a submatrix of the `rowval_gen` transformation of a second matrix if and only if the `in_gen` embedding of the first matrix is a submatrix of the second matrix.*)\nLemma submx_rowval_gen m1 m2 (U : 'M_(m1, n)) (V : 'M_(m2, nA)) :\n (U <= rowval_gen V)%MS = (in_gen U <= V)%MS.\n\n(*This lemma states that the `rowval_gen` transformation is a right inverse to the `in_gen` embedding, meaning that embedding the result of a `rowval_gen` transformation yields the original matrix.*)\nLemma rowval_genK m (U : 'M_(m, nA)) : (in_gen (rowval_gen U) :=: U)%MS.\n\n(*This lemma establishes that any matrix produced by the `rowval_gen` transformation is stable under right multiplication by the matrix `A`, meaning the result of the multiplication is a submatrix of the original transformed matrix.*)\nLemma rowval_gen_stable m (U : 'M_(m, nA)) :\n (rowval_gen U *m A <= rowval_gen U)%MS.\n\n(*This lemma states that the stabilizer subgroup for an embedded matrix under the `rGA` representation is the same as the stabilizer subgroup for the original matrix under the `rG` representation.*)\nLemma rstab_in_gen m (U : 'M_(m, n)) : rstab rGA (in_gen U) = rstab rG U.\n\n(*This lemma states that the embedding under `in_gen` of the stable module generated from a matrix by the `rG` representation is a submodule of the stable module generated from the embedded matrix by the `rGA` representation.*)\nLemma rstabs_in_gen m (U : 'M_(m, n)) :\n rstabs rG U \\subset rstabs rGA (in_gen U).\n\n(*This lemma shows that the stable module generated from a `rowval_gen`-transformed matrix by the `rG` representation is equal to the stable module generated from the original matrix by the `rGA` representation.*)\nLemma rstabs_rowval_gen m (U : 'M_(m, nA)) :\n rstabs rG (rowval_gen U) = rstabs rGA U.\n\n(*This lemma states that the matrix module generated from a `rowval_gen`-transformed matrix by the `rG` representation is equal to the matrix module generated from the original matrix by the `rGA` representation.*)\nLemma mxmodule_rowval_gen m (U : 'M_(m, nA)) :\n mxmodule rG (rowval_gen U) = mxmodule rGA U.\n\n(*This lemma proves that the generated matrix representation `rGA` is irreducible.*)\nLemma gen_mx_irr : mx_irreducible rGA.\n\n(*This lemma states that the kernel of the generated matrix representation `rGA` is equal to the kernel of the original representation `rG`.*)\nLemma rker_gen : rker rGA = rker rG.\n\n(*This lemma establishes that the generated matrix representation `rGA` is faithful if and only if the original representation `rG` is faithful.*)\nLemma gen_mx_faithful : mx_faithful rGA = mx_faithful rG.\n\nEnd GenField.\n\nSection DecideGenField.\n\nImport MatrixFormula.\n\nVariable F : decFieldType.\n\n(*A local notation for the term representing the boolean value false within the generalized ring formula language.*)\nLocal Notation False := GRing.False.\n(*A local notation for the term representing the boolean value true within the generalized ring formula language.*)\nLocal Notation True := GRing.True.\nLocal Notation Bool b := (GRing.Bool b%bool).\n(*A local notation for the type of symbolic expressions, or terms, defined over a decidable field.*)\nLocal Notation term := (GRing.term F).\n(*A local notation for the type of symbolic logical formulas defined over a decidable field.*)\nLocal Notation form := (GRing.formula F).\n\nLocal Notation morphAnd f := ((big_morph f) true andb).\n\nVariables (gT : finGroupType) (G : {group gT}) (n' : nat).\n(*This notation defines `n` as the successor of a natural number, which is a common way to represent a positive natural number.*)\nLocal Notation n := n'.+1.\nVariables (rG : mx_representation F G n) (A : 'M[F]_n).\nHypotheses (irrG : mx_irreducible rG) (cGA : centgmx rG A).\n(*A local notation for the field extension generated by a matrix `A` that commutes with an irreducible matrix representation `rG`.*)\nLocal Notation FA := (gen_of irrG cGA).\n(*A local notation for the canonical generator of the field extension `FA`.*)\nLocal Notation inFA := (Gen irrG cGA).\n\n(*This notation specifies the degree of the minimal polynomial of a given matrix.*)\nLocal Notation d := (degree_mxminpoly A).\n(*This lemma states that the degree of the minimal polynomial of the given matrix is greater than zero.*)\nLet d_gt0 : d > 0 := mxminpoly_nonconstant A.\n(*This notation defines a sequence of matrices representing the powers of a given matrix, from the identity matrix up to the power one less than a specified natural number.*)\nLocal Notation Ad := (powers_mx A d).\n\n(*This definition specifies a function that converts a row vector of coefficients into the corresponding matrix representation of an element in the generated field extension. The resulting matrix is a linear combination of the powers of the generator matrix, with coefficients taken from the input vector.*)\nLet mxT (u : 'rV_d) := vec_mx (mulmx_term u (mx_term Ad)).\n\n(*This lemma states that evaluating the matrix representation of a field element, which is constructed from a vector of term coefficients, yields the same matrix as first evaluating the coefficient vector to a field element and then obtaining its canonical matrix representation.*)\nLet eval_mxT e u : eval_mx e (mxT u) = mxval (inFA (eval_mx e u)).\n\n(*This definition introduces `Ad'T` as a term representing the pseudo-inverse of the matrix whose rows are the powers of the generator matrix.*)\nLet Ad'T := mx_term (pinvmx Ad).\n(*This definition provides a function for multiplying two elements of the generated field, which are represented by their coefficient vectors. The multiplication is performed by converting the vectors to their matrix representations, multiplying the matrices, and then converting the resulting product matrix back into a coefficient vector.*)\nLet mulT (u v : 'rV_d) := mulmx_term (mxvec (mulmx_term (mxT u) (mxT v))) Ad'T.\n\n(*This lemma states that evaluating the coefficient vector resulting from the multiplication of two coefficient vector terms is equivalent to first evaluating each term to obtain its corresponding field element, multiplying these elements within the field, and then retrieving the value of the product.*)\nLemma eval_mulT e u v :\n eval_mx e (mulT u v) = val (inFA (eval_mx e u) * inFA (eval_mx e v)).\n\n(*This recursive function `gen_term` translates a formal ring expression into its concrete representation as a coefficient vector within the generated matrix field. It handles variables, constants, and standard ring operations like addition, multiplication, and exponentiation by mapping them to corresponding vector and matrix operations.*)\nFixpoint gen_term t := match t with\n| 'X_k => row_var _ d k\n| x%:T => mx_term (val (x : FA))\n| n1%:R => mx_term (val (n1%:R : FA))%R\n| t1 + t2 => \\row_i (gen_term t1 0%R i + gen_term t2 0%R i)\n| - t1 => \\row_i (- gen_term t1 0%R i)\n| t1 *+ n1 => mulmx_term (mx_term n1%:R%:M)%R (gen_term t1)\n| t1 * t2 => mulT (gen_term t1) (gen_term t2)\n| t1^-1 => gen_term t1\n| t1 ^+ n1 => iter n1 (mulT (gen_term t1)) (mx_term (val (1%R : FA)))\nend%T.\n\n(*This definition specifies a function `gen_env` that converts an environment, given as a sequence of field elements, into an evaluation environment suitable for matrix-based expressions by extracting the underlying values from each element in the sequence.*)\nDefinition gen_env (e : seq FA) := row_env (map val e).\n\n(*This lemma states that accessing the j-th element of a sequence, after applying a value-extraction function to every element, is equivalent to first accessing the j-th element of the original sequence and then applying the value-extraction function.*)\nLemma nth_map_rVval (e : seq FA) j : (map val e)`_j = val e`_j.\n\n(*This lemma states that updating the j-th element of a sequence of values is equivalent to updating the corresponding element in the original sequence of field elements and then extracting the values from the modified sequence.*)\nLemma set_nth_map_rVval (e : seq FA) j v :\n set_nth 0 (map val e) j v = map val (set_nth 0 e j (inFA v)).\n\n(*This lemma guarantees the correctness of the term translation by stating that for any valid ring term, evaluating its generated matrix representation within a translated environment yields the same value as evaluating the original term in the original environment.*)\nLemma eval_gen_term e t :\n GRing.rterm t -> eval_mx (gen_env e) (gen_term t) = val (GRing.eval e t).\n\n(*This recursive function `gen_form` translates a logical formula over a generic ring into a corresponding logical formula over matrices. It handles atoms like equality and unit checks by converting them into matrix rank conditions, and recursively translates logical connectives and quantifiers.*)\nFixpoint gen_form f := match f with\n| Bool b => Bool b\n| t1 == t2 => mxrank_form 0 (gen_term (t1 - t2))\n| GRing.Unit t1 => mxrank_form 1 (gen_term t1)\n| f1 /\\ f2 => gen_form f1 /\\ gen_form f2\n| f1 \\/ f2 => gen_form f1 \\/ gen_form f2\n| f1 ==> f2 => gen_form f1 ==> gen_form f2\n| ~ f1 => ~ gen_form f1\n| ('exists 'X_k, f1) => Exists_row_form d k (gen_form f1)\n| ('forall 'X_k, f1) => ~ Exists_row_form d k (~ (gen_form f1))\nend%T.\n\n(*This lemma establishes the semantic correctness of the formula translation by stating that a given generic ring formula holds true in an environment if and only if its translated matrix-based formula is satisfied in the corresponding translated environment.*)\nLemma sat_gen_form e f : GRing.rformula f ->\n reflect (GRing.holds e f) (GRing.sat (gen_env e) (gen_form f)).\n\n(*This definition provides a satisfiability predicate `gen_sat` for a given formula in a given environment. It operates by translating both the formula and the environment into their matrix-based counterparts and then applying a base satisfiability checker.*)\nDefinition gen_sat e f := GRing.sat (gen_env e) (gen_form (GRing.to_rform f)).\n\n(*This lemma asserts that the defined satisfiability predicate fulfills the decidability axiom required by the theory of decidable fields, which enables the construction of a decidable field structure.*)\nLemma gen_satP :\n GRing.MathCompCompatDecidableField.DecidableField.axiom gen_sat.\n\n(*A local notation for a natural number defined as one greater than another natural number `n'`, ensuring it is positive.*)\nLocal Notation n := n'.+1.\nVariables (rG : mx_representation F G n) (A : 'M[F]_n).\nHypotheses (irrG : mx_irreducible rG) (cGA : centgmx rG A).\n(*This notation defines a shorthand for the type representing elements of a field extension generated by a matrix, under the assumptions that the group representation is irreducible and the matrix commutes with the representation.*)\nNotation FA := (gen_of irrG cGA).\n\n#[export] HB.instance Definition _ := [Finite of FA by <:].\n(*This lemma states that the cardinality of the generated finite field is equal to the cardinality of the base field raised to the power of the degree of the minimal polynomial of the generator matrix.*)\nLemma card_gen : #|{:FA}| = (#|F| ^ degree_mxminpoly A)%N.\n\nEnd FiniteGenField.\n\nEnd MatrixGenField.\n\nModule MatrixGenFieldExports.\n\nHB.reexport.\n\nEnd MatrixGenFieldExports.\n\nExport MatrixGenFieldExports.\n\nBind Scope ring_scope with gen_of.\nArguments rVval {F gT G%_G n'%_N rG A%_R irrG cGA} x%_R : rename.\nPrenex Implicits gen_of Gen rVval pval mxval gen groot.\nArguments subbase {F n'} A {nA}.\nPrenex Implicits gen_dim gen_base base val_gen gen_mx rowval_gen.\nArguments in_gen {F gT G n' rG A} irrG cGA {m} W.\nArguments in_genK {F gT G n' rG A} irrG cGA {m} W : rename.\nArguments val_genK {F gT G n' rG A irrG cGA m} W : rename.\nPrenex Implicits gen_env gen_term gen_form gen_sat.\n\nSection BuildSplittingField.\n\nImplicit Type gT : finGroupType.\nImplicit Type F : fieldType.\n\n(*This lemma asserts, under classical assumptions, the existence of a splitting field for any given group over a specified base field. It guarantees that there is an extension field where all irreducible representations of the group are completely reducible into one-dimensional representations, along with a morphism from the base field into this extension.*)\nLemma group_splitting_field_exists gT (G : {group gT}) F :\n classically {Fs : fieldType & {rmorphism F -> Fs}\n & group_splitting_field Fs G}.\n\n(*This lemma asserts, under classical assumptions, the existence of a group closure field for a given finite group type over a specified base field. This means there is a field extension that serves as a splitting field for every possible group structure on that finite type, along with a morphism from the base field into the extension.*)\nLemma group_closure_field_exists gT F :\n classically {Fs : fieldType & {rmorphism F -> Fs}\n & group_closure_field Fs gT}.\n\n(*This lemma states that any field that is a closed field type is also a group closure field for any given finite group type, meaning it already serves as a splitting field for all groups of that type.*)\nLemma group_closure_closed_field (F : closedFieldType) gT :\n group_closure_field F gT.", - "ssreflect.all_ssreflect": "Attributes deprecated(since=\"mathcomp 2.5.0\",\n note=\"Use 'all_boot' and/or 'all_order' instead.\").\n\nFrom mathcomp Require Export all_boot.\nFrom mathcomp Require Export preorder.", - "boot.ssrnotations": "Reserved Notation \"e .[ x ]\" (left associativity, format \"e .[ x ]\").\n\nReserved Notation \"e .[ x1 , x2 , .. , xn ]\" (left associativity,\n format \"e '[ ' .[ x1 , '/' x2 , '/' .. , '/' xn ] ']'\").\n\nReserved Notation \"s `_ i\" (at level 3, i at level 2, left associativity,\n format \"s `_ i\").\nReserved Notation \"x ^-1\" (left associativity, format \"x ^-1\").\n\nReserved Notation \"x *+ n\" (at level 40, left associativity).\nReserved Notation \"x *- n\" (at level 40, left associativity).\nReserved Notation \"x ^+ n\" (at level 29, left associativity).\nReserved Notation \"x ^- n\" (at level 29, left associativity).\n\nReserved Notation \"x *: A\" (at level 40).\nReserved Notation \"A :* x\" (at level 40).\n\nReserved Notation \"x ^*\" (format \"x ^*\", left associativity).\n\nReserved Notation \"A :&: B\" (at level 48, left associativity).\nReserved Notation \"A :|: B\" (at level 52, left associativity).\nReserved Notation \"a |: A\" (at level 52, left associativity).\nReserved Notation \"A :\\: B\" (at level 50, left associativity).\nReserved Notation \"A :\\ b\" (at level 50, left associativity).\n\nReserved Notation \"<< A >>\" (format \"<< A >>\").\nReserved Notation \"<[ a ] >\" (format \"<[ a ] >\").\n\nReserved Notation \"#[ x ]\" (format \"#[ x ]\").\n\nReserved Notation \"''C' [ x ]\" (format \"''C' [ x ]\").\nReserved Notation \"''C_' A [ x ]\" (A at level 2, format \"''C_' A [ x ]\").\nReserved Notation \"''C' ( A )\" (format \"''C' ( A )\").\nReserved Notation \"''C_' B ( A )\" (B at level 2, format \"''C_' B ( A )\").\nReserved Notation \"''Z' ( A )\" (format \"''Z' ( A )\").\n\nReserved Notation \"''C_' ( A ) [ x ]\".\nReserved Notation \"''C_' ( B ) ( A )\".\n\nReserved Notation \"m %/ d\" (at level 40, no associativity).\nReserved Notation \"m %% d\" (at level 40, no associativity).\nReserved Notation \"m %| d\" (at level 70, no associativity).\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"m = n %[mod d ]\"\n (format \"'[hv ' m '/' = n '/' %[mod d ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"m == n %[mod d ]\" (at level 70, n at next level,\n format \"'[hv ' m '/' == n '/' %[mod d ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"m <> n %[mod d ]\"\n (format \"'[hv ' m '/' <> n '/' %[mod d ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"m != n %[mod d ]\" (at level 70, n at next level,\n format \"'[hv ' m '/' != n '/' %[mod d ] ']'\").\n\nReserved Notation \"a ^` ()\" (format \"a ^` ()\").\nReserved Notation \"a ^` ( n )\" (format \"a ^` ( n )\").\n\nReserved Notation \"`| x |\" (x at level 99, format \"`| x |\").\n\nReserved Notation \"x <= y ?= 'iff' c\" (c at next level,\n format \"x '[hv' <= y '/' ?= 'iff' c ']'\").\n\nReserved Notation \"x <= y :> T\".\nReserved Notation \"x >= y :> T\".\nReserved Notation \"x < y :> T\".\nReserved Notation \"x > y :> T\".\nReserved Notation \"x <= y ?= 'iff' c :> T\" (c at next level,\n format \"x '[hv' <= y '/' ?= 'iff' c :> T ']'\").\n\nReserved Notation \"'[ u , v ]\" (format \"'[hv' ''[' u , '/ ' v ] ']'\").", - "boot.ssrmatching": "", - "boot.nmodule": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype choice ssrnat seq.\nFrom mathcomp Require Import bigop fintype finfun monoid.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope ring_scope.\nDelimit Scope ring_scope with R.\nLocal Open Scope ring_scope.\n\nReserved Notation \"+%R\" (at level 0).\nReserved Notation \"-%R\" (at level 0).\nReserved Notation \"n %:R\" (at level 1, left associativity, format \"n %:R\").\nReserved Notation \"\\0\" (at level 0).\nReserved Notation \"f \\+ g\" (at level 50, left associativity).\nReserved Notation \"f \\- g\" (at level 50, left associativity).\nReserved Notation \"\\- f\" (at level 35, f at level 35).\n\nReserved Notation \"'{' 'additive' U '->' V '}'\"\n (at level 0, U at level 98, V at level 99,\n format \"{ 'additive' U -> V }\").\n\nModule Import Algebra.\n\n(*A mixin record that equips a type with a binary addition operation.*)\nHB.mixin Record hasAdd V := {\n add : V -> V -> V\n}.\n\n#[short(type=\"baseAddMagmaType\")]\n(*A structure for a type equipped with a binary addition operation, forming a basic additive magma.*)\nHB.structure Definition BaseAddMagma := {V of hasAdd V}.\n\nModule BaseAddMagmaExports.\nBind Scope ring_scope with BaseAddMagma.sort.\nEnd BaseAddMagmaExports.\nHB.export BaseAddMagmaExports. \n\n(*A structure for a type that is both a basic additive magma and has a choice property, allowing for the selection of a canonical inhabitant from any non-empty subset.*)\nHB.structure Definition ChoiceBaseAddMagma := {V of BaseAddMagma V & Choice V}.\n\nModule ChoiceBaseAddMagmaExports.\nBind Scope ring_scope with ChoiceBaseAddMagma.sort.\nEnd ChoiceBaseAddMagmaExports.\nHB.export ChoiceBaseAddMagmaExports. \n\n(*A notation representing the binary addition function itself, typically used in higher-order contexts where the function is passed as an argument.*)\nLocal Notation \"+%R\" := (@add _) : function_scope.\n(*A notation for the infix binary addition operation between two elements of a type.*)\nLocal Notation \"x + y\" := (add x y) : ring_scope.\n\n(*This definition provides an identity function on types, used as a mechanism to formally bridge additive algebraic structures with their multiplicative counterparts, enabling the reuse of definitions and proofs.*)\nDefinition to_multiplicative := @id Type.\n\n#[export]\nHB.instance Definition _ (V : choiceType) := Choice.on (to_multiplicative V).\n#[export]\nHB.instance Definition _ (V : baseAddMagmaType) :=\n hasMul.Build (to_multiplicative V) (@add V).\n\n#[export]\nHB.instance Definition _ (V : ChoiceBaseAddMagma.type) :=\n Magma.on (to_multiplicative V).\n\nSection BaseAddMagmaTheory.\nVariables V : baseAddMagmaType.\n\nSection ClosedPredicates.\n\nVariable S : {pred V}.\n\n(*This definition specifies the property that a given subset of an additive structure is closed under addition, which holds if the sum of any two elements within the subset also belongs to the subset.*)\nDefinition addr_closed := {in S &, forall u v, u + v \\in S}.\n\nEnd ClosedPredicates.\nEnd BaseAddMagmaTheory.\n\n(*A mixin record that enriches a basic additive magma with the property that its addition operation is commutative.*)\nHB.mixin Record BaseAddMagma_isAddMagma V of BaseAddMagma V := {\n addrC : commutative (@add V)\n}.\n\n#[short(type=\"addMagmaType\")]\n(*A structure for a type equipped with a commutative binary addition operation and a choice property, forming a commutative additive magma.*)\nHB.structure Definition AddMagma :=\n {V of BaseAddMagma_isAddMagma V & ChoiceBaseAddMagma V}.\n\n(*A factory record used to construct a commutative additive magma structure from a type with a choice property, by providing a binary addition operation and a proof of its commutativity.*)\nHB.factory Record isAddMagma V of Choice V := {\n add : V -> V -> V;\n addrC : commutative add\n}.\n\nHB.builders Context V of isAddMagma V.\nHB.instance Definition _ := hasAdd.Build V add.\nHB.instance Definition _ := BaseAddMagma_isAddMagma.Build V addrC.\nHB.end.\n\nModule AddMagmaExports.\nBind Scope ring_scope with AddMagma.sort.\nEnd AddMagmaExports.\nHB.export AddMagmaExports.\n\nSection AddMagmaTheory.\nVariables V : addMagmaType.\n\n(*This lemma states that for any two elements in a commutative additive magma, their sum is the same regardless of their order, effectively rephrasing additive commutativity in its corresponding multiplicative view.*)\nLemma commuteT x y : @commute (to_multiplicative V) x y.\n\nEnd AddMagmaTheory.\n\n(*A mixin record that enriches a commutative additive magma with the property that its addition operation is associative.*)\nHB.mixin Record AddMagma_isAddSemigroup V of AddMagma V := {\n addrA : associative (@add V)\n}.\n\n#[short(type=\"addSemigroupType\")]\n(*A structure for a type with an addition that is commutative and associative, and which has a choice property, forming a commutative additive semigroup.*)\nHB.structure Definition AddSemigroup :=\n {V of AddMagma_isAddSemigroup V & AddMagma V}.\n\n(*A factory record used to construct a commutative additive semigroup structure from a type with a choice property, by providing a binary addition operation along with proofs of its commutativity and associativity.*)\nHB.factory Record isAddSemigroup V of Choice V := {\n add : V -> V -> V;\n addrC : commutative add;\n addrA : associative add\n}.\n\nHB.builders Context V of isAddSemigroup V.\nHB.instance Definition _ := isAddMagma.Build V addrC.\nHB.instance Definition _ := AddMagma_isAddSemigroup.Build V addrA.\nHB.end.\n\nModule AddSemigroupExports.\nBind Scope ring_scope with AddSemigroup.sort.\nEnd AddSemigroupExports.\nHB.export AddSemigroupExports.\n\n#[export]\nHB.instance Definition _ (V : addSemigroupType) :=\n Magma_isSemigroup.Build (to_multiplicative V) addrA.\n\nSection AddSemigroupTheory.\nVariables V : addSemigroupType.\n\n(*This lemma states that for any three elements in a commutative additive semigroup, the sum of the first element with the sum of the second and third is equal to the sum of the second element with the sum of the first and third.*)\nLemma addrCA : @left_commutative V V +%R.\n\n(*This lemma states that for any three elements in a commutative additive semigroup, the sum of the sum of the first two elements with the third is equal to the sum of the sum of the first and third elements with the second.*)\nLemma addrAC : @right_commutative V V +%R.\n\n(*This lemma states that for any four elements in a commutative additive semigroup, the sum of the sum of the first two and the sum of the last two is equal to the sum of the sum of the first and third and the sum of the second and fourth.*)\nLemma addrACA : @interchange V +%R +%R.\n\nEnd AddSemigroupTheory.\n\n(*A mixin record that equips a type with a distinguished element designated as zero.*)\nHB.mixin Record hasZero V := {\n zero : V\n}.\n\n#[short(type=\"baseAddUMagmaType\")]\n(*A structure for a type equipped with a binary addition operation and a zero element, forming a basic additive magma with a unit.*)\nHB.structure Definition BaseAddUMagma :=\n {V of hasZero V & BaseAddMagma V}.\n\nModule BaseAddUMagmaExports.\nBind Scope ring_scope with BaseAddUMagma.sort.\nEnd BaseAddUMagmaExports.\nHB.export BaseAddUMagmaExports.\n\n(*A structure for a type that is a basic additive magma with a unit and also has a choice property.*)\nHB.structure Definition ChoiceBaseAddUMagma :=\n {V of BaseAddUMagma V & Choice V}.\n\nModule ChoiceBaseAddUMagmaExports.\nBind Scope ring_scope with ChoiceBaseAddUMagma.sort.\nEnd ChoiceBaseAddUMagmaExports.\nHB.export ChoiceBaseAddUMagmaExports.\n\n(*A notation for the zero element in an additive structure.*)\nLocal Notation \"0\" := (@zero _) : ring_scope.\n\n(*This definition provides a function that computes the repeated sum of an element of an additive magma with a unit with itself a given number of times, where the number of repetitions is a natural number.*)\nDefinition natmul (V : baseAddUMagmaType) (x : V) n : V := iterop n +%R x 0.\nArguments natmul : simpl never.\n\n(*A notation representing the repeated addition of an element with itself a given number of times, where the number is a natural number.*)\nLocal Notation \"x *+ n\" := (natmul x n) : ring_scope.\n\n#[export]\nHB.instance Definition _ (V : baseAddUMagmaType) :=\n hasOne.Build (to_multiplicative V) (@zero V).\n\n#[export]\nHB.instance Definition _ (V : ChoiceBaseAddUMagma.type) :=\n BaseUMagma.on (to_multiplicative V).\n\nSection BaseAddUMagmaTheory.\nVariable V : baseAddUMagmaType.\nImplicit Types x : V.\n\n(*This lemma states that repeatedly adding any element with itself zero times results in the zero element.*)\nLemma mulr0n x : x *+ 0 = 0. \n(*This lemma states that repeatedly adding any element with itself one time results in the element itself.*)\nLemma mulr1n x : x *+ 1 = x. \n(*This lemma states that repeatedly adding any element with itself two times is equivalent to the sum of the element with itself.*)\nLemma mulr2n x : x *+ 2 = x + x. \n(*This lemma states that repeatedly adding an element a number of times corresponding to a boolean value is equivalent to the element itself if the boolean is true, and the zero element if the boolean is false.*)\nLemma mulrb x (b : bool) : x *+ b = (if b then x else 0).\n\n(*This lemma provides a recursive formula stating that adding an element a given number of times plus two is equal to the sum of that element with the result of adding it the same number of times plus one.*)\nLemma mulrSS x n : x *+ n.+2 = x + x *+ n.+1. \n\nSection ClosedPredicates.\n\nVariable S : {pred V}.\n\n(*This definition specifies the property that a given subset of an additive magma with a unit is closed. This holds if the subset contains the zero element and is also closed under addition.*)\nDefinition addumagma_closed := 0 \\in S /\\ addr_closed S.\n\nEnd ClosedPredicates.\n\nEnd BaseAddUMagmaTheory.\n\n(*A mixin record that enriches a basic additive magma with a unit by asserting that its addition operation is commutative.*)\nHB.mixin Record BaseAddUMagma_isAddUMagma V of BaseAddUMagma V := {\n add0r : left_id zero (@add V)\n}.\n\n(*A record that defines the structure for a type with a commutative binary operation and a left identity element for that operation.*)\nHB.factory Record isAddUMagma V of Choice V := {\n add : V -> V -> V;\n zero : V;\n addrC : commutative add;\n add0r : left_id zero add\n}.\n\nHB.builders Context V of isAddUMagma V.\nHB.instance Definition _ := isAddMagma.Build V addrC.\nHB.instance Definition _ := hasZero.Build V zero.\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := BaseAddUMagma_isAddUMagma.Build V add0r.\nHB.end.\n\n#[short(type=\"addUMagmaType\")]\n(*A structure representing a type equipped with a commutative binary addition operation and a corresponding identity element, also known as a commutative monoid.*)\nHB.structure Definition AddUMagma := {V of isAddUMagma V & Choice V}.\n\n(*This lemma states that for any element in a type with a commutative addition and a left identity, adding the identity element on the right results in the original element, establishing it as a right identity as well.*)\nLemma addr0 (V : addUMagmaType) : right_id (@zero V) add.\n\n(*A notation for the sum of the results of a function applied to all elements of a finite sequence that satisfy a given predicate.*)\nLocal Notation \"\\sum_ ( i <- r | P ) F\" := (\\big[+%R/0]_(i <- r | P) F).\n(*A notation for the sum of the results of a function applied to a contiguous range of natural numbers, starting from a lower bound and ending just before an upper bound.*)\nLocal Notation \"\\sum_ ( m <= i < n ) F\" := (\\big[+%R/0]_(m <= i < n) F).\n(*A notation for the sum of the results of a function applied to the sequence of natural numbers less than a given upper bound.*)\nLocal Notation \"\\sum_ ( i < n ) F\" := (\\big[+%R/0]_(i < n) F).\n(*A notation for the sum of the results of a function applied to all elements of a given finite set.*)\nLocal Notation \"\\sum_ ( i 'in' A ) F\" := (\\big[+%R/0]_(i in A) F).\n\nImport Monoid.Theory.\n\n#[export]\nHB.instance Definition _ (V : addUMagmaType) :=\n Magma_isUMagma.Build (to_multiplicative V) add0r (@addr0 V).\n\n(*A record that defines the structure of a module over the semiring of natural numbers, requiring an associative and commutative addition operation with a left identity element.*)\nHB.factory Record isNmodule V of Choice V := {\n zero : V;\n add : V -> V -> V;\n addrA : associative add;\n addrC : commutative add;\n add0r : left_id zero add\n}.\n\nHB.builders Context V of isNmodule V.\nHB.instance Definition _ := isAddUMagma.Build V addrC add0r.\nHB.instance Definition _ := AddMagma_isAddSemigroup.Build V addrA.\nHB.end.\n\nModule AddUMagmaExports.\nBind Scope ring_scope with AddUMagma.sort.\nEnd AddUMagmaExports.\nHB.export AddUMagmaExports.\n\n#[short(type=\"nmodType\")]\n(*A structure representing a module over the semiring of natural numbers, which is a set equipped with an associative and commutative addition that has an identity element.*)\nHB.structure Definition Nmodule := {V of isNmodule V & Choice V}.\n\nModule NmoduleExports.\nBind Scope ring_scope with Nmodule.sort.\nEnd NmoduleExports.\nHB.export NmoduleExports.\n\n#[export]\nHB.instance Definition _ (V : nmodType) :=\n UMagma_isMonoid.Build (to_multiplicative V) addrA.\n\n#[export]\nHB.instance Definition _ (V : nmodType) :=\n Monoid.isComLaw.Build V 0%R +%R addrA addrC add0r.\n\nSection NmoduleTheory.\n\nVariable V : nmodType.\nImplicit Types x y : V.\n\n(*This definition creates a type with a multiplicative structure from a given type with an additive structure. The multiplication in the new type corresponds to the addition in the original type, and its multiplicative identity corresponds to the original additive identity.*)\nLet G := to_multiplicative V.\n\n(*This lemma states that multiplying an element by the successor of a natural number is equivalent to adding the element to the result of multiplying it by the original natural number.*)\nLemma mulrS x n : x *+ n.+1 = x + (x *+ n).\n\n(*This lemma states that multiplying an element by the successor of a natural number is equivalent to adding the result of multiplying the element by the original natural number to the element itself.*)\nLemma mulrSr x n : x *+ n.+1 = x *+ n + x.\n\n(*This lemma states that multiplying the additive identity element of an N-module by any natural number results in the additive identity element.*)\nLemma mul0rn n : 0 *+ n = 0 :> V.\n\n(*This lemma states that the operation of multiplying elements by a fixed natural number distributes over the addition of those elements in an N-module.*)\nLemma mulrnDl n : {morph (fun x => x *+ n) : x y / x + y}.\n\n(*This lemma states that multiplying an element by the sum of two natural numbers is equivalent to the sum of multiplying the element by each natural number separately.*)\nLemma mulrnDr x m n : x *+ (m + n) = x *+ m + x *+ n.\n\n(*This lemma states that multiplying an element by the product of two natural numbers is equivalent to first multiplying by one natural number and then multiplying the result by the other.*)\nLemma mulrnA x m n : x *+ (m * n) = x *+ m *+ n.\n\n(*This lemma states that the order of repeated scalar multiplication by two natural numbers can be interchanged without changing the final result.*)\nLemma mulrnAC x m n : x *+ m *+ n = x *+ n *+ m.\n\n(*This lemma states that iterating the addition of a specific element a given number of times, starting from an initial value, is equivalent to adding the scalar product of that element and the number of iterations to the initial value.*)\nLemma iter_addr n x y : iter n (+%R x) y = x *+ n + y.\n\n(*This lemma states that iterating the addition of a specific element a given number of times, starting from the additive identity, yields the scalar product of that element and the number of iterations.*)\nLemma iter_addr_0 n x : iter n (+%R x) 0 = x *+ n.\n\n(*This lemma states that the sum of elements, each individually multiplied by a fixed natural number, is equal to the product of the total sum of the original elements and that natural number.*)\nLemma sumrMnl I r P (F : I -> V) n :\n \\sum_(i <- r | P i) F i *+ n = (\\sum_(i <- r | P i) F i) *+ n.\n\n(*This lemma states that the sum of a fixed element multiplied by a series of different natural numbers is equal to that element multiplied by the sum of those natural numbers.*)\nLemma sumrMnr x I r P (F : I -> nat) :\n \\sum_(i <- r | P i) x *+ F i = x *+ (\\sum_(i <- r | P i) F i).\n\n(*This lemma states that the sum of a constant element over all members of a finite set is equivalent to multiplying that element by the number of members in the set.*)\nLemma sumr_const (I : finType) (A : pred I) x : \\sum_(i in A) x = x *+ #|A|.\n\n(*This lemma states that the sum of a constant element over a range of natural numbers from a start value to just before an end value is equivalent to multiplying the element by the difference between the end and start values.*)\nLemma sumr_const_nat m n x : \\sum_(n <= i < m) x = x *+ (m - n).\n\nEnd NmoduleTheory.\n(*This notation provides an alias for the property that a subset is closed under the additive operations of an N-module.*)\nNotation nmod_closed := addumagma_closed.\n\n(*A record that enriches a type with a unary operation for the additive inverse, or negation.*)\nHB.mixin Record hasOpp V := {\n opp : V -> V\n}.\n\n#[short(type=\"baseZmodType\")]\n(*A structure for types equipped with a commutative addition, an additive identity, and a unary negation operation.*)\nHB.structure Definition BaseZmodule := {V of hasOpp V & BaseAddUMagma V}.\n\nModule BaseZmodExports.\nBind Scope ring_scope with BaseZmodule.sort.\nEnd BaseZmodExports.\nHB.export BaseZmodExports.\n\n(*A notation for the unary additive inverse, or negation, operator within the ring scope.*)\nLocal Notation \"-%R\" := (@opp _) : ring_scope.\n(*A notation for the unary additive inverse, or negation, of an element.*)\nLocal Notation \"- x\" := (opp x) : ring_scope.\n(*A notation defining the subtraction of one element from another as the addition of the first element to the additive inverse of the second.*)\nLocal Notation \"x - y\" := (x + - y) : ring_scope.\n(*A notation for the additive inverse of the result of multiplying an element by a natural number, effectively representing scalar multiplication by the corresponding negative integer.*)\nLocal Notation \"x *- n\" := (- (x *+ n)) : ring_scope.\n\nSection ClosedPredicates.\n\nVariable (U : baseZmodType) (S : {pred U}).\n\n(*This definition specifies a property for a subset of an algebraic structure, stating that the subset is closed under the additive inverse operation, meaning that for any element in the subset, its additive inverse is also in the subset.*)\nDefinition oppr_closed := {in S, forall u, - u \\in S}.\n(*This definition specifies a property for a subset of an algebraic structure, stating that the subset is closed under subtraction, meaning that for any two elements in the subset, their difference is also in the subset.*)\nDefinition subr_closed := {in S &, forall u v, u - v \\in S}.\n(*This definition specifies a property for a subset of an algebraic structure with an additive identity, stating that the subset contains the additive identity and is closed under subtraction.*)\nDefinition zmod_closed := 0 \\in S /\\ subr_closed.\n\nEnd ClosedPredicates.\n\n(*This record defines a mixin that equips a structure with an addition, its identity, and an opposition function, with the property that adding the opposition of an element to the element itself results in the additive identity.*)\nHB.mixin Record BaseZmoduleNmodule_isZmodule V of BaseZmodule V := {\n addNr : left_inverse zero opp (@add V)\n}.\n\n#[short(type=\"zmodType\")]\n(*This structure defines a Z-module, which is an algebraic structure equivalent to an abelian group. It consists of a type equipped with an associative and commutative addition, an additive identity element, and an additive inverse for each element.*)\nHB.structure Definition Zmodule :=\n {V of BaseZmoduleNmodule_isZmodule V & BaseZmodule V & Nmodule V}.\n\n(*This factory record provides the components needed to upgrade a commutative monoid structure to an abelian group structure by supplying an opposition function and the axiom asserting it provides a left inverse for the addition operation.*)\nHB.factory Record Nmodule_isZmodule V of Nmodule V := {\n opp : V -> V;\n addNr : left_inverse zero opp add\n}.\n\nHB.builders Context V of Nmodule_isZmodule V.\nHB.instance Definition _ := hasOpp.Build V opp.\nHB.instance Definition _ := BaseZmoduleNmodule_isZmodule.Build V addNr.\nHB.end.\n\n(*This factory record specifies all the components and axioms required to define an abelian group structure on a given type, including the additive identity, the opposition function, the addition operation, and properties of associativity, commutativity, identity, and inverse.*)\nHB.factory Record isZmodule V of Choice V := {\n zero : V;\n opp : V -> V;\n add : V -> V -> V;\n addrA : associative add;\n addrC : commutative add;\n add0r : left_id zero add;\n addNr : left_inverse zero opp add\n}.\n\nHB.builders Context V of isZmodule V.\n\nHB.instance Definition _ := isNmodule.Build V addrA addrC add0r.\nHB.instance Definition _ := Nmodule_isZmodule.Build V addNr.\n\nHB.end.\n\nModule ZmoduleExports.\nBind Scope ring_scope with Zmodule.sort.\nEnd ZmoduleExports.\nHB.export ZmoduleExports.\n\n(*This lemma states that for any element in an abelian group, adding its additive inverse to it results in the additive identity.*)\nLemma addrN (V : zmodType) : @right_inverse V V V 0 -%R +%R.\n\n#[export]\nHB.instance Definition _ (V : baseZmodType) :=\n hasInv.Build (to_multiplicative V) (@opp V).\n#[export]\nHB.instance Definition _ (V : zmodType) :=\n Monoid_isGroup.Build (to_multiplicative V) addNr (@addrN V).\n\nSection ZmoduleTheory.\n\nVariable V : zmodType.\nImplicit Types x y : V.\n\n(*This definition provides a local alias for the multiplicative representation of an abelian group, allowing theorems for multiplicative groups to be applied to the additive group structure.*)\nLet G := to_multiplicative V.\n\n(*This definition is an alias for the lemma stating that subtracting any element of an abelian group from itself results in the additive identity.*)\nDefinition subrr := addrN.\n\n(*This lemma states that for any two elements in an abelian group, adding the first element to the difference of the second and first elements results in the second element.*)\nLemma addKr : @left_loop V V -%R +%R.\n\n(*This lemma states that for any two elements in an abelian group, adding the additive inverse of the first element to the sum of the two elements results in the second element.*)\nLemma addNKr : @rev_left_loop V V -%R +%R.\n\n(*This lemma states that for any two elements in an abelian group, adding the second element to the result of subtracting it from the first element yields the first element.*)\nLemma addrK : @right_loop V V -%R +%R.\n\n(*This lemma states that for any two elements in an abelian group, adding the additive inverse of the second element to their sum results in the first element.*)\nLemma addrNK : @rev_right_loop V V -%R +%R.\n\n(*This definition is an alias for the lemma stating the right cancellation property for addition, which asserts that subtracting an element from a sum containing that element removes it.*)\nDefinition subrK := addrNK.\n(*This lemma states that for any fixed element in an abelian group, the function that subtracts its input from that fixed element is an involution, meaning applying the function twice returns the original input.*)\nLemma subKr x : involutive (fun y => x - y).\n\n(*This lemma states that the addition operation in an abelian group has the right cancellation property, meaning that if adding the same element to two different elements results in the same value, then the original two elements must have been equal.*)\nLemma addrI : @right_injective V V V +%R.\n\n(*This lemma states that the addition operation in an abelian group has the left cancellation property, meaning that if two different elements are added to the same element and result in the same value, then the original two elements must have been equal.*)\nLemma addIr : @left_injective V V V +%R.\n\n(*This lemma states that the subtraction operation in an abelian group is right injective. This means that if subtracting the same element from two different elements yields the same result, then the two original elements must be equal.*)\nLemma subrI : right_injective (fun x y => x - y).\n\n(*This lemma states that the subtraction operation in an abelian group is left injective. This means that if subtracting two different elements from the same element yields the same result, then the two original elements must be equal.*)\nLemma subIr : left_injective (fun x y => x - y).\n\n(*This lemma states that the additive inverse operation in an abelian group is an involution, meaning that taking the additive inverse of the additive inverse of an element returns the original element.*)\nLemma opprK : @involutive V -%R.\n\n(*This lemma states that the additive inverse operation in an abelian group is injective, meaning that if two elements have the same additive inverse, they must be equal.*)\nLemma oppr_inj : @injective V V -%R.\n\n(*This lemma states that the additive inverse of the additive identity in an abelian group is the additive identity itself.*)\nLemma oppr0 : -0 = 0 :> V.\n\n(*This lemma states that for any element in an abelian group, the boolean statement that its additive inverse is equal to the additive identity is equivalent to the boolean statement that the element itself is equal to the additive identity.*)\nLemma oppr_eq0 x : (- x == 0) = (x == 0).\n\n(*This lemma states that subtracting the additive identity from any element in an abelian group results in the original element.*)\nLemma subr0 x : x - 0 = x. \n(*This lemma states that subtracting any element from the additive identity in an abelian group results in the additive inverse of that element.*)\nLemma sub0r x : 0 - x = - x. \n\n(*This lemma states that for any two elements in an abelian group, the additive inverse of their difference is equal to the difference of the elements in the reverse order.*)\nLemma opprB x y : - (x - y) = y - x.\n\n(*This lemma states that the additive inverse operation in an abelian group distributes over addition, meaning the additive inverse of a sum of two elements is equal to the sum of their additive inverses.*)\nLemma opprD : {morph -%R: x y / x + y : V}.\n\n(*This lemma states that for any three elements in an abelian group, subtracting the sum of the second and third from the sum of the first and second is equivalent to subtracting the third from the first.*)\nLemma addrKA z x y : (x + z) - (z + y) = x - y.\n\n(*This lemma states that for any three elements in an abelian group, adding the sum of the second and third to the difference of the first and second is equivalent to the sum of the first and third.*)\nLemma subrKA z x y : (x - z) + (z + y) = x + y.\n\n(*This lemma states that if the sum of two elements in an additive group is zero, then the additive inverse of the first element is equal to the second element.*)\nLemma addr0_eq x y : x + y = 0 -> - x = y.\n\n(*This lemma states that if the difference between two elements in an additive group is zero, then the two elements are equal.*)\nLemma subr0_eq x y : x - y = 0 -> x = y.\n\n(*This lemma states that the boolean equality asserting that the difference of a first and a third element equals a second element is equivalent to the boolean equality asserting that the first element equals the sum of the second and third elements.*)\nLemma subr_eq x y z : (x - z == y) = (x == y + z).\n\n(*This lemma states that the boolean equality asserting that the difference of two elements is zero is equivalent to the boolean equality asserting that the two elements are equal.*)\nLemma subr_eq0 x y : (x - y == 0) = (x == y).\n\n(*This lemma states that the boolean equality asserting that the sum of two elements is zero is equivalent to the boolean equality asserting that the first element is equal to the additive inverse of the second element.*)\nLemma addr_eq0 x y : (x + y == 0) = (x == - y).\n\n(*This lemma states that the boolean equality asserting that the additive inverses of two elements are equal is equivalent to the boolean equality asserting that the original two elements are equal.*)\nLemma eqr_opp x y : (- x == - y) = (x == y).\n\n(*This lemma states that the boolean equality asserting that the additive inverse of a first element is equal to a second element is equivalent to the boolean equality asserting that the first element is equal to the additive inverse of the second.*)\nLemma eqr_oppLR x y : (- x == y) = (x == - y).\n\n(*This lemma states that scaling the additive inverse of an element by a natural number yields the same result as scaling the original element by the corresponding negative integer.*)\nLemma mulNrn x n : (- x) *+ n = x *- n.\n\n(*This lemma states that for any natural number, the function that scales an element of a Z-module by that number is a morphism with respect to subtraction.*)\nLemma mulrnBl n : {morph (fun x => x *+ n) : x y / x - y}.\n\n(*This lemma states that, for two natural numbers where the first is less than or equal to the second, scaling an element of a Z-module by their difference is equal to the difference of scaling the element by the second number and scaling it by the first.*)\nLemma mulrnBr x m n : n <= m -> x *+ (m - n) = x *+ m - x *+ n.\n\n(*This lemma states that the sum over a finite sequence of the additive inverses of the values of a function is equal to the additive inverse of the sum of the function's values.*)\nLemma sumrN I r P (F : I -> V) :\n (\\sum_(i <- r | P i) - F i = - (\\sum_(i <- r | P i) F i)).\n\n(*This lemma states that the sum over a finite sequence of the differences of two functions' values is equal to the difference between the sum of the first function's values and the sum of the second function's values.*)\nLemma sumrB I r (P : pred I) (F1 F2 : I -> V) :\n \\sum_(i <- r | P i) (F1 i - F2 i)\n = \\sum_(i <- r | P i) F1 i - \\sum_(i <- r | P i) F2 i.\n\n(*This lemma states that for a function from natural numbers to an additive group, the sum of differences between consecutive function values over a range of natural numbers is equal to the difference between the function's value at the end of the range and its value at the start.*)\nLemma telescope_sumr n m (f : nat -> V) : n <= m ->\n \\sum_(n <= k < m) (f k.+1 - f k) = f m - f n.\n\n(*This lemma provides a rule for telescoping sums, stating that if a given function's value at each natural number in a range is equal to the difference of a second function's values at consecutive numbers, then the sum of the first function over that range equals the difference of the second function's values at the range's endpoints.*)\nLemma telescope_sumr_eq n m (f u : nat -> V) : n <= m ->\n (forall k, (n <= k < m)%N -> u k = f k.+1 - f k) ->\n \\sum_(n <= k < m) u k = f m - f n.\n\nSection ClosedPredicates.\n\nVariable (S : {pred V}).\n\n(*This lemma states that if a predicate on a Z-module is closed under scaling by any integer, then it is also closed under taking the additive inverse.*)\nLemma zmod_closedN : zmod_closed S -> oppr_closed S.\n\n(*This lemma states that if a predicate on a Z-module is closed under scaling by any integer, then it is also closed under addition.*)\nLemma zmod_closedD : zmod_closed S -> addr_closed S.\n\n(*This lemma states that if a predicate on a Z-module is closed under scaling by any integer, then it is also closed under scaling by any natural number.*)\nLemma zmod_closed0D : zmod_closed S -> nmod_closed S.\n\nEnd ClosedPredicates.\n\nEnd ZmoduleTheory.\n\nArguments addrI {V} y [x1 x2].\nArguments addIr {V} x [x1 x2].\nArguments opprK {V}.\nArguments oppr_inj {V} [x1 x2].\n\n(*This definition specifies the properties of a function that acts as a morphism between two additive unital magmas, requiring that the function maps the zero element of the source to the zero element of the target and that it preserves the addition operation.*)\nDefinition nmod_morphism (U V : baseAddUMagmaType) (f : U -> V) : Prop :=\n (f 0 = 0) * {morph f : x y / x + y}.\n#[deprecated(since=\"mathcomp 2.5.0\", note=\"use `nmod_morphism` instead\")]\n(*This definition is a deprecated alias for an nmod-morphism, which describes a function that preserves both the zero element and the addition operation between two additive unital magmas.*)\nDefinition semi_additive := nmod_morphism.\n\n(*This record provides a mixin for bundling a function between two additive unital magmas with a proof that it is an nmod-morphism, meaning it preserves both the zero element and addition.*)\nHB.mixin Record isNmodMorphism (U V : baseAddUMagmaType) (apply : U -> V) := {\n nmod_morphism_subproof : nmod_morphism apply;\n}.\n\nModule isSemiAdditive.\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"Use isNmodMorphism.Build instead.\")]\nNotation Build U V apply := (isNmodMorphism.Build U V apply) (only parsing).\nEnd isSemiAdditive.\n\n#[mathcomp(axiom=\"nmod_morphism\")]\n(*This definition introduces a structure that bundles a function between two additive unital magmas with the property of being an nmod-morphism, effectively representing a homomorphism that preserves zero and addition.*)\nHB.structure Definition Additive (U V : baseAddUMagmaType) :=\n {f of isNmodMorphism U V f}.\n\n(*This definition specifies the property of a function acting as a morphism between two Z-modules, which requires the function to preserve the subtraction operation.*)\nDefinition zmod_morphism (U V : zmodType) (f : U -> V) :=\n {morph f : x y / x - y}.\n\n#[deprecated(since=\"mathcomp 2.5.0\", note=\"use `zmod_morphism` instead\")]\n(*This definition is a deprecated alias for a zmod-morphism, describing a function between two Z-modules that preserves the subtraction operation.*)\nDefinition additive := zmod_morphism.\n\n(*This record provides a factory for bundling a function between two Z-modules with an accompanying proof that it is a zmod-morphism, meaning it preserves subtraction.*)\nHB.factory Record isZmodMorphism (U V : zmodType) (apply : U -> V) := {\n zmod_morphism_subproof : zmod_morphism apply;\n}.\n\nModule isAdditive.\n#[deprecated(since=\"mathcomp 2.5.0\",\n note=\"Use isZmodMorphism.Build instead.\")]\nNotation Build U V apply := (isZmodMorphism.Build U V apply) (only parsing).\nEnd isAdditive.\n\nHB.builders Context U V apply of isZmodMorphism U V apply.\n(*This lemma states that an additive function between two additive unital magmas maps the zero element of the source to the zero element of the target.*)\nLocal Lemma raddf0 : apply 0 = 0.\n\n(*This lemma states that a function between two Z-modules that preserves subtraction also preserves addition.*)\nLocal Lemma raddfD : {morph apply : x y / x + y}.\n\nHB.instance Definition _ := isNmodMorphism.Build U V apply (conj raddf0 raddfD).\n\nHB.end.\n\nModule AdditiveExports.\n(*This notation represents the type of all additive functions from a source additive unital magma to a target additive unital magma, where an additive function is one that preserves both zero and addition.*)\nNotation \"{ 'additive' U -> V }\" := (Additive.type U%type V%type) : type_scope.\nEnd AdditiveExports.\nHB.export AdditiveExports.\n\nSection AdditiveTheory.\nVariables (U V : baseAddUMagmaType) (f : {additive U -> V}).\n\n(*This lemma asserts that an additive function maps the zero element of its domain to the zero element of its codomain.*)\nLemma raddf0 : f 0 = 0.\n\n(*This lemma states that an additive function distributes over addition; that is, applying the function to the sum of two elements yields the same result as summing the function's applications to each element individually.*)\nLemma raddfD :\n {morph f : x y / x + y}.\n\nEnd AdditiveTheory.\n\n(*This definition provides a type-level coercion that reinterprets a function between two types with additive structures as a function between the corresponding types viewed with multiplicative structures. It does not change the function itself.*)\nDefinition to_fmultiplicative U V :=\n @id (to_multiplicative U -> to_multiplicative V).\n\n#[export]\nHB.instance Definition _ U V (f : {additive U -> V}) :=\n isMultiplicative.Build (to_multiplicative U) (to_multiplicative V)\n (to_fmultiplicative f) (@raddfD _ _ f).\n#[export]\nHB.instance Definition _ (U V : baseAddUMagmaType) (f : {additive U -> V}) :=\n Multiplicative_isUMagmaMorphism.Build\n (to_multiplicative U) (to_multiplicative V) (to_fmultiplicative f)\n (@raddf0 _ _ f).\n\nSection LiftedAddMagma.\nVariables (U : Type) (V : baseAddMagmaType).\n(*This definition specifies the pointwise addition of two functions. The resulting function, when applied to an input, evaluates to the sum of the results of applying each of the original functions to that same input.*)\nDefinition add_fun (f g : U -> V) x := f x + g x.\nEnd LiftedAddMagma.\nSection LiftedNmod.\nVariables (U : Type) (V : baseAddUMagmaType).\n(*This definition specifies the constant zero function, which maps every element from a given source type to the zero element of a target type that has a zero.*)\nDefinition null_fun of U : V := 0.\nEnd LiftedNmod.\nSection LiftedZmod.\nVariables (U : Type) (V : baseZmodType).\n(*This definition specifies the pointwise additive inverse of a function. The resulting function, when applied to an input, evaluates to the additive inverse of the result of applying the original function to that same input.*)\nDefinition opp_fun (f : U -> V) x := - f x.\n(*This definition specifies the pointwise subtraction of two functions. The resulting function, when applied to an input, evaluates to the result of subtracting the value of the second function from the value of the first function at that same input.*)\nDefinition sub_fun (f g : U -> V) x := f x - g x.\nEnd LiftedZmod.\n\nArguments null_fun {_} V _ /.\nArguments add_fun {_ _} f g _ /.\nArguments opp_fun {_ _} f _ /.\nArguments sub_fun {_ _} f g _ /.\n\n(*This notation represents the constant zero function, which maps any input to the zero element of its codomain.*)\nLocal Notation \"\\0\" := (null_fun _) : function_scope.\n(*This notation represents the pointwise addition of two functions, yielding a new function whose value at any point is the sum of the values of the original two functions at that point.*)\nLocal Notation \"f \\+ g\" := (add_fun f g) : function_scope.\n(*This notation represents the pointwise additive inverse of a function, yielding a new function whose value at any point is the additive inverse of the value of the original function at that point.*)\nLocal Notation \"\\- f\" := (opp_fun f) : function_scope.\n(*This notation represents the pointwise subtraction of two functions, yielding a new function whose value at any point is the result of subtracting the second function's value from the first function's value at that point.*)\nLocal Notation \"f \\- g\" := (sub_fun f g) : function_scope.\n\nSection Nmod.\nVariables (U V : addUMagmaType) (f : {additive U -> V}).\n(*This definition creates a multiplicative function from a given additive function. The new function preserves multiplication in the same way the original function preserves addition.*)\nLet g := to_fmultiplicative f.\n\n(*This lemma states that for any injective additive function, the function maps an element to zero if and only if that element is itself zero.*)\nLemma raddf_eq0 x : injective f -> (f x == 0) = (x == 0).\n\n(*This lemma states that an additive function commutes with scalar multiplication by a natural number. Applying the function to an element scaled by a natural number is equivalent to scaling the function's result by the same natural number.*)\nLemma raddfMn n : {morph f : x / x *+ n}.\n\n(*This lemma states that an additive function distributes over a finite sum. Applying the function to the sum of a sequence of elements is equivalent to summing the results of applying the function to each element individually.*)\nLemma raddf_sum I r (P : pred I) E :\n f (\\sum_(i <- r | P i) E i) = \\sum_(i <- r | P i) f (E i).\n\n(*This lemma states that if a function has a two-sided inverse, and the original function is a morphism of modules over the natural numbers, then its inverse is also a morphism of modules over the natural numbers.*)\nLemma can2_nmod_morphism f' : cancel f f' -> cancel f' f -> nmod_morphism f'.\n\n#[deprecated(since=\"mathcomp 2.5.0\", note=\"use `can2_nmod_morphism` instead\")]\n(*This definition provides a deprecated alias for a lemma which asserts that the two-sided inverse of a morphism of modules over the natural numbers is also such a morphism.*)\nDefinition can2_semi_additive := can2_nmod_morphism.\n\nEnd Nmod.\n\nSection Zmod.\nVariables (U V : zmodType) (f : {additive U -> V}).\n(*Represents an additive function from one additive magma to another, which preserves the zero element and the addition operation.*)\nLet g := to_fmultiplicative f.\n\n(*This lemma states that the function which maps an element of a z-module to its additive inverse is an additive morphism.*)\nLemma raddfN : {morph f : x / - x}.\n\n(*This lemma states that the subtraction function, which maps a pair of elements from a z-module to their difference, is an additive morphism from the product z-module.*)\nLemma raddfB : {morph f : x y / x - y}.\n\n(*This lemma states that an additive morphism is an injective function if it maps only the zero element to the zero element.*)\nLemma raddf_inj : (forall x, f x = 0 -> x = 0) -> injective f.\n\n(*This lemma states that for any natural number, the function that multiplies an element of a z-module by that number is an additive morphism.*)\nLemma raddfMNn n : {morph f : x / x *- n}.\n\n(*This lemma states that a function is a z-module morphism if it commutes under composition with a given z-module endomorphism.*)\nLemma can2_zmod_morphism f' : cancel f f' -> cancel f' f -> zmod_morphism f'.\n\n#[warning=\"-deprecated-since-mathcomp-2.5.0\",\n deprecated(since=\"mathcomp 2.5.0\", note=\"use `can2_zmod_morphism` instead\")]\n(*This is a deprecated definition, serving as an alias for `can2_zmod_morphism`.*)\nDefinition can2_additive := can2_zmod_morphism.\nEnd Zmod.\n\nSection AdditiveTheory.\nSection AddCFun.\nVariables (U : baseAddUMagmaType) (V : nmodType).\nImplicit Types (f g : {additive U -> V}).\n\n(*This fact states that the pointwise sum of two n-module morphisms is also an n-module morphism.*)\nFact add_fun_nmod_morphism f g : nmod_morphism (add_fun f g).\n\n#[export]\n(*This fact states that the identity function on an n-module is an n-module morphism.*)\nFact idfun_is_nmod_morphism : nmod_morphism (@idfun U).\n\n#[export]\nHB.instance Definition _ := isNmodMorphism.Build U U idfun\n idfun_is_nmod_morphism.\n\n(*This fact states that the composition of two n-module morphisms is also an n-module morphism.*)\nFact comp_is_nmod_morphism : nmod_morphism (f \\o g).\n\n#[export]\nHB.instance Definition _ := isNmodMorphism.Build U W (f \\o g)\n comp_is_nmod_morphism.\n\nEnd AddFun.\nSection AddFun.\nVariables (U : baseAddUMagmaType) (V : addUMagmaType) (W : nmodType).\nVariables (f g : {additive U -> W}).\n\n(*This fact states that the function that maps every element of its domain to the zero element of its codomain is an n-module morphism.*)\nFact null_fun_is_nmod_morphism : nmod_morphism (\\0 : U -> V).\n\n#[export]\n(*This fact states that the additive inverse function on a z-module is a z-module morphism.*)\nFact opp_is_zmod_morphism : zmod_morphism (-%R : V -> V).\n\n#[export]\nHB.instance Definition _ :=\n isZmodMorphism.Build V V -%R opp_is_zmod_morphism.\n\n(*This fact states that the pointwise additive inverse of an n-module morphism into a z-module is also an n-module morphism.*)\nFact opp_fun_is_zmod_morphism : nmod_morphism (\\- f).\n\n#[export]\nHB.instance Definition _ :=\n isNmodMorphism.Build U V (opp_fun f) opp_fun_is_zmod_morphism.\n\n(*This fact states that the pointwise difference of two n-module morphisms mapping into a z-module is also an n-module morphism.*)\nFact sub_fun_is_zmod_morphism :\n nmod_morphism (f \\- g).\n\n#[export]\n(*This record defines the property of a subset of an additive magma being closed under the addition operation and containing the zero element.*)\nHB.mixin Record isAddClosed (V : baseAddUMagmaType) (S : {pred V}) := {\n nmod_closed_subproof : addumagma_closed S\n}.\n\n(*This record defines the property of a subset of a z-module being closed under the additive inverse operation.*)\nHB.mixin Record isOppClosed (V : zmodType) (S : {pred V}) := {\n oppr_closed_subproof : oppr_closed S\n}.\n\n#[short(type=\"addrClosed\")]\n(*This structure represents a subset of an additive magma that is closed under addition and contains the zero element.*)\nHB.structure Definition AddClosed V := {S of isAddClosed V S}.\n\n#[short(type=\"opprClosed\")]\n(*This structure represents a subset of a z-module that is closed under the additive inverse operation.*)\nHB.structure Definition OppClosed V := {S of isOppClosed V S}.\n\n#[short(type=\"zmodClosed\")]\n(*This structure represents a subset of a z-module that is closed under addition, contains the zero element, and is closed under additive inverse.*)\nHB.structure Definition ZmodClosed V := {S of OppClosed V S & AddClosed V S}.\n\n(*This record provides a factory for constructing a z-module closed subset from a proof that the subset is closed under addition and additive inverse.*)\nHB.factory Record isZmodClosed (V : zmodType) (S : V -> bool) := {\n zmod_closed_subproof : zmod_closed S\n}.\n\nHB.builders Context V S of isZmodClosed V S.\nHB.instance Definition _ := isOppClosed.Build V S\n (zmod_closedN zmod_closed_subproof).\nHB.instance Definition _ := isAddClosed.Build V S\n (zmod_closed0D zmod_closed_subproof).\nHB.end.\n\n(*This definition provides a way to view a predicate over an additive structure as a predicate over the corresponding multiplicative structure, by acting as a type-casting identity function.*)\nDefinition to_pmultiplicative (T : Type) := @id {pred to_multiplicative T}.\n\n#[export]\nHB.instance Definition _ (U : baseAddUMagmaType) (S : addrClosed U) :=\n isMulClosed.Build (to_multiplicative U) (to_pmultiplicative S)\n (snd nmod_closed_subproof).\n#[export]\nHB.instance Definition _ (U : baseAddUMagmaType) (S : addrClosed U) :=\n isMul1Closed.Build (to_multiplicative U) (to_pmultiplicative S)\n (fst nmod_closed_subproof).\n#[export]\nHB.instance Definition _ (U : zmodType) (S : opprClosed U) :=\n isInvClosed.Build (to_multiplicative U) (to_pmultiplicative S)\n oppr_closed_subproof.\n\n#[export]\nHB.instance Definition _ (U : zmodType) (S : zmodClosed U) :=\n InvClosed.on (to_pmultiplicative S).\n\nSection BaseAddUMagmaPred.\nVariables (V : baseAddUMagmaType).\n\nSection BaseAddUMagmaPred.\nVariables S : addrClosed V.\n\n(*This lemma states that the zero element is a member of any additively closed subset.*)\nLemma rpred0 : 0 \\in S.\n\n(*This lemma states that the sum of any two elements belonging to an additively closed subset is also a member of that subset.*)\nLemma rpredD : {in S &, forall u v, u + v \\in S}.\n\n(*This lemma confirms that a subset with an `addrClosed` structure is closed under the operations of its underlying additive magma, meaning it contains the zero element and is closed under addition.*)\nLemma rpred0D : addumagma_closed S.\n\n(*This lemma states that for any element in an additively closed subset, its multiple by any natural number also belongs to that subset.*)\nLemma rpredMn n : {in S, forall u, u *+ n \\in S}.\n\n(*This lemma states that if all elements produced by a function over a given domain are in an additively closed subset, then their sum over a finite sequence of inputs is also in that subset.*)\nLemma rpred_sum I r (P : pred I) F :\n (forall i, P i -> F i \\in S) -> \\sum_(i <- r | P i) F i \\in S.\n\nEnd BaseAddUMagmaPred.\nEnd BaseAddUMagmaPred.\n\nSection ZmodPred.\nVariables (V : zmodType).\n\nSection Opp.\n\nVariable S : opprClosed V.\n\n(*This lemma states that for any element belonging to a subset that is closed under opposition, its additive inverse also belongs to that subset.*)\nLemma rpredNr : {in S, forall u, - u \\in S}.\n\n(*This lemma states that the property of belonging to a subset closed under opposition is preserved by the additive inverse operation.*)\nLemma rpredN : {mono -%R: u / u \\in S}.\n\nEnd Opp.\n\nSection Zmod.\nVariables S : zmodClosed V.\n(*An alias that reinterprets a z-module closed subset as a subset of the corresponding multiplicative structure.*)\nLet T := to_pmultiplicative S.\n\n(*This lemma states that the difference of any two elements belonging to a z-module closed subset is also a member of that subset.*)\nLemma rpredB : {in S &, forall u v, u - v \\in S}.\n\n(*This lemma states that for a predicate on an additive abelian group, the difference of two elements belongs to the predicate if and only if the additive inverse of that difference also belongs to the predicate.*)\nLemma rpredBC u v : u - v \\in S = (v - u \\in S).\n\n(*This lemma asserts that for a given integer, every element within a predicate that defines a submodule remains within that predicate after being scaled by that integer.*)\nLemma rpredMNn n: {in S, forall u, u *- n \\in S}.\n\n(*This lemma states that for a predicate defining a subgroup, adding a member of the subgroup to any element on the right preserves membership in the subgroup.*)\nLemma rpredDr x y : x \\in S -> (y + x \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate defining a subgroup, adding a member of the subgroup to any element on the left preserves membership in the subgroup.*)\nLemma rpredDl x y : x \\in S -> (x + y \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate defining a subgroup, subtracting a member of the subgroup from any element preserves membership in the subgroup.*)\nLemma rpredBr x y : x \\in S -> (y - x \\in S) = (y \\in S).\n\n(*This lemma states that for a predicate defining a subgroup, an element belongs to the subgroup if and only if subtracting it from a known member of the subgroup results in another member of the subgroup.*)\nLemma rpredBl x y : x \\in S -> (x - y \\in S) = (y \\in S).\n\n(*This lemma states that a given predicate on an additive abelian group is closed under the structure of a module over the integers, meaning it contains the zero element and is closed under addition, additive inverse, and scalar multiplication by integers.*)\nLemma zmodClosedP : zmod_closed S.\n\nEnd Zmod.\nEnd ZmodPred. \n\n(*A mixin record that specifies that a subtype equipped with an additive unital magma structure is a sub-magma. It requires the inclusion map from the subtype to the parent type to be a morphism that preserves both addition and the zero element.*)\nHB.mixin Record isSubBaseAddUMagma (V : baseAddUMagmaType) (S : pred V) U\n of SubType V S U & BaseAddUMagma U := {\n valD0_subproof : nmod_morphism (val : U -> V)\n}.\n\n#[short(type=\"subBaseAddUMagma\")]\n(*This definition bundles the structure for a subtype that is itself an additive unital magma, where the operations on the subtype are compatible with the parent type's structure. This represents a sub-additive-unital-magma.*)\nHB.structure Definition SubBaseAddUMagma (V : baseAddUMagmaType) S :=\n { U of SubChoice V S U & BaseAddUMagma U & isSubBaseAddUMagma V S U }.\n\n#[short(type=\"subAddUMagma\")]\n(*This definition bundles the structure for a subtype that is itself a commutative additive unital magma, where the operations on the subtype are compatible with the parent type's structure. This represents a sub-commutative-additive-unital-magma.*)\nHB.structure Definition SubAddUMagma (V : addUMagmaType) S :=\n { U of SubChoice V S U & AddUMagma U & isSubBaseAddUMagma V S U }.\n\n#[short(type=\"subNmodType\")]\n(*This definition bundles the structure for a subtype that is a module over the natural numbers, where the operations on the subtype (addition, zero, and scalar multiplication) are compatible with the parent module's structure. This represents a submodule over the natural numbers.*)\nHB.structure Definition SubNmodule (V : nmodType) S :=\n { U of SubChoice V S U & Nmodule U & isSubBaseAddUMagma V S U}.\n\nSection subBaseAddUMagma.\nContext (V : baseAddUMagmaType) (S : pred V) (U : subBaseAddUMagma S).\n(*A notation providing a shorthand for the coercion function that maps an element from a subtype to its corresponding value in the ambient type.*)\nNotation val := (val : U -> V).\n#[export]\n(*This lemma states that the inclusion map from a sub-magma to its parent magma preserves addition; applying the map to a sum of two elements is the same as summing the results of applying the map to each element individually.*)\nLemma valD : {morph val : x y / x + y}. \n(*This lemma states that the inclusion map from a sub-magma to its parent magma preserves the zero element.*)\nLemma val0 : val 0 = 0. \nEnd subBaseAddUMagma.\n\n(*A factory record used to automatically construct a commutative additive unital sub-magma structure on a subtype. It requires a proof that the underlying predicate contains the zero element and is closed under addition.*)\nHB.factory Record SubChoice_isSubAddUMagma (V : addUMagmaType) S U\n of SubChoice V S U := {\n addumagma_closed_subproof : addumagma_closed S\n}.\n\nHB.builders Context V S U of SubChoice_isSubAddUMagma V S U.\n\nHB.instance Definition _ := isAddClosed.Build V S addumagma_closed_subproof.\n\nLet inU v Sv : U := Sub v Sv.\n(*This definition specifies the addition operation on a subtype. It is defined by taking two elements from the subtype, projecting them to the parent type, performing the addition in the parent type, and then embedding the result back into the subtype.*)\nLet addU (u1 u2 : U) := inU (rpredD (valP u1) (valP u2)).\n(*This definition specifies the zero element for a subtype. It is defined by taking the zero element from the parent type and embedding it into the subtype, using the proof that the subtype predicate contains zero.*)\nLet oneU := inU (fst addumagma_closed_subproof).\n\n(*This lemma states that the addition operation defined on the subtype is commutative.*)\nLemma addrC : commutative addU.\n\n(*This lemma states that the defined zero element for the subtype acts as a left identity for the subtype's addition operation.*)\nLemma add0r : left_id oneU addU.\n\nHB.instance Definition _ := isAddUMagma.Build U addrC add0r.\n\nLemma valD0 : nmod_morphism (val : U -> V).\n\nHB.instance Definition _ := isSubBaseAddUMagma.Build V S U valD0.\n\nHB.end.\n\n(*A factory record used to automatically construct a submodule structure over the natural numbers on a subtype. It requires a proof that the underlying predicate contains the zero element and is closed under both addition and scalar multiplication by natural numbers.*)\nHB.factory Record SubChoice_isSubNmodule (V : nmodType) S U\n of SubChoice V S U := {\n nmod_closed_subproof : nmod_closed S\n}.\n\nHB.builders Context V S U of SubChoice_isSubNmodule V S U.\n\nHB.instance Definition _ :=\n SubChoice_isSubAddUMagma.Build V S U nmod_closed_subproof.\n\n(*This lemma states that the addition operation defined on the subtype is associative.*)\nLemma addrA : associative (@add U).\n\nHB.instance Definition _ := AddMagma_isAddSemigroup.Build U addrA.\n\nHB.end.\n\n#[short(type=\"subZmodType\")]\n(*This definition bundles the structure for a subtype that is a module over the integers, also known as an abelian subgroup. It requires the subtype to be equipped with a compatible structure of an additive abelian group where the inclusion map preserves the group operations.*)\nHB.structure Definition SubZmodule (V : zmodType) S :=\n { U of SubChoice V S U & Zmodule U & isSubBaseAddUMagma V S U}.\n\nSection zmod_morphism.\nContext (V : zmodType) (S : pred V) (U : SubZmodule.type S).\n(*A notation for the canonical inclusion map that takes an element from a subtype and returns the corresponding element in the larger parent type.*)\nNotation val := (val : U -> V).\n(*This lemma states that the canonical embedding from a Z-module substructure to its ambient Z-module preserves the subtraction operation.*)\nLemma valB : {morph val : x y / x - y}. \n(*This lemma states that the canonical embedding from a Z-module substructure to its ambient Z-module preserves the additive inverse operation.*)\nLemma valN : {morph val : x / - x}. \nEnd zmod_morphism.\n\n(*This factory constructs a record that packages the properties of a Z-module substructure, which includes the subset choice and a proof that the canonical embedding into the ambient Z-module is a Z-module morphism.*)\nHB.factory Record isSubZmodule (V : zmodType) S U\n of SubChoice V S U & Zmodule U := {\n valB_subproof : zmod_morphism (val : U -> V)\n}.\n\nHB.builders Context V S U of isSubZmodule V S U.\n\n(*This fact asserts that the canonical embedding from a submodule to its ambient module is an N-module morphism, meaning it preserves the zero element and the addition operation.*)\nFact valD0 : nmod_morphism (val : U -> V).\n\nHB.instance Definition _ := isSubBaseAddUMagma.Build V S U valD0.\n\nHB.end.\n\n(*This factory constructs a record for a Z-module substructure from a subchoice, given a proof that the underlying set is closed under the Z-module operations of zero, addition, and negation.*)\nHB.factory Record SubChoice_isSubZmodule (V : zmodType) S U\n of SubChoice V S U := {\n zmod_closed_subproof : zmod_closed S\n}.\n\nHB.builders Context V S U of SubChoice_isSubZmodule V S U.\n\nHB.instance Definition _ := isZmodClosed.Build V S zmod_closed_subproof.\nHB.instance Definition _ :=\n SubChoice_isSubNmodule.Build V S U nmod_closed_subproof.\n\n(*This function constructs an element of a subtype from an element of the ambient type and a proof that this element belongs to the defining subset of the subtype.*)\nLet inU v Sv : U := Sub v Sv.\n(*This function defines the additive inverse operation on a submodule. It computes the inverse of an element by taking its underlying value in the ambient module, negating it there, and then lifting the result back into the submodule.*)\nLet oppU (u : U) := inU (rpredNr (valP u)).\n\nHB.instance Definition _ := hasOpp.Build U oppU.\n\n(*This lemma states that adding the additive inverse of an element to the element itself results in the zero element of the module, establishing the left inverse property for addition.*)\nLemma addNr : left_inverse 0 oppU (@add U).\n\n(*This notation provides a convenient way to construct an N-module substructure from a given subtype, by automatically inferring the proof that the subtype is closed under zero and addition.*)\nNotation \"[ 'SubChoice_isSubNmodule' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubNmodule.Build _ _ U rpred0D)\n (at level 0, format \"[ 'SubChoice_isSubNmodule' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation offers a shorthand to construct a Z-module substructure from a specified subtype, automatically deriving the proof that the subtype is closed under zero, addition, and additive inverse.*)\nNotation \"[ 'SubChoice_isSubZmodule' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubZmodule.Build _ _ U (zmodClosedP _))\n (at level 0, format \"[ 'SubChoice_isSubZmodule' 'of' U 'by' <: ]\")\n : form_scope.\n\nEnd SubExports.\nHB.export SubExports.\n\nModule AllExports. HB.reexport. End AllExports.\n\nEnd Algebra.\n\nExport AllExports.\n\n(*This notation represents the additive identity element, or zero, within the context of a ring or a module.*)\nNotation \"0\" := (@zero _) : ring_scope.\n(*This notation represents the curried function for the additive inverse operation within the context of a ring.*)\nNotation \"-%R\" := (@opp _) : ring_scope.\n(*This notation represents the additive inverse, or opposite, of a given element within the context of a ring or a module.*)\nNotation \"- x\" := (opp x) : ring_scope.\n(*This notation represents the curried function for the binary addition operation, typically used for higher-order programming with functions.*)\nNotation \"+%R\" := (@add _) : function_scope.\n(*This notation represents the sum of two elements using the binary addition operation of a ring or a module.*)\nNotation \"x + y\" := (add x y) : ring_scope.\n(*This notation represents the subtraction of one element from another, defined as the addition of the first element with the additive inverse of the second.*)\nNotation \"x - y\" := (add x (- y)) : ring_scope.\nArguments natmul : simpl never.\n(*This notation represents the multiplication of an element of an additive group by a natural number, defined as the repeated addition of the element to itself for the specified number of times.*)\nNotation \"x *+ n\" := (natmul x n) : ring_scope.\n(*This notation represents the multiplication of an element of an additive group by the negative of a natural number, defined as the additive inverse of the result of multiplying the element by the natural number.*)\nNotation \"x *- n\" := (opp (x *+ n)) : ring_scope.\n(*This notation accesses the element at a specified index in a sequence, returning the zero element of the ring if the index is out of bounds.*)\nNotation \"s `_ i\" := (seq.nth 0%R s%R i) : ring_scope.\n(*This notation refers to the support of a function or sequence, defined as the set of indices for which the corresponding value is not the zero element.*)\nNotation support := 0.-support.\n\n(*This notation represents the multiplicative identity element, or one, within the context of a ring.*)\nNotation \"1\" := (@one _) : ring_scope.\n(*This notation represents the additive inverse of the multiplicative identity element within a ring.*)\nNotation \"- 1\" := (opp 1) : ring_scope.\n\n(*This notation provides a standard way to embed a natural number into a ring, by computing the sum of the ring's multiplicative identity with itself the specified number of times.*)\nNotation \"n %:R\" := (natmul 1 n) : ring_scope.\n\n(*This notation represents the sum of a given expression over all indices from a specified finite range that satisfy a given boolean predicate.*)\nNotation \"\\sum_ ( i <- r | P ) F\" :=\n (\\big[+%R/0%R]_(i <- r | P%B) F%R) : ring_scope.\n(*This notation represents the sum of a given expression over all indices in a specified finite range.*)\nNotation \"\\sum_ ( i <- r ) F\" :=\n (\\big[+%R/0%R]_(i <- r) F%R) : ring_scope.\n(*This notation represents the sum of a given expression over a range of natural numbers from a start value up to but not including an end value, for all indices that also satisfy a given boolean predicate.*)\nNotation \"\\sum_ ( m <= i < n | P ) F\" :=\n (\\big[+%R/0%R]_(m <= i < n | P%B) F%R) : ring_scope.\n(*This notation represents the sum of a given expression over a range of natural numbers from a start value up to but not including an end value.*)\nNotation \"\\sum_ ( m <= i < n ) F\" :=\n (\\big[+%R/0%R]_(m <= i < n) F%R) : ring_scope.\n(*This notation represents the sum of a given expression over all elements of a finite type that satisfy a given boolean predicate.*)\nNotation \"\\sum_ ( i | P ) F\" :=\n (\\big[+%R/0%R]_(i | P%B) F%R) : ring_scope.\n(*This notation represents the sum of a given expression over all elements of a finite type.*)\nNotation \"\\sum_ i F\" :=\n (\\big[+%R/0%R]_i F%R) : ring_scope.\n(*This notation represents the sum of a series of terms given by a function, indexed by elements of a specific type that also satisfy a given predicate. The sum is computed using the addition and zero element from the underlying ring structure.*)\nNotation \"\\sum_ ( i : t | P ) F\" :=\n (\\big[+%R/0%R]_(i : t | P%B) F%R) (only parsing) : ring_scope.\n(*This notation represents the sum of a series of terms given by a function, indexed over all elements of a specific type. The sum is computed using the addition and zero element from the underlying ring structure.*)\nNotation \"\\sum_ ( i : t ) F\" :=\n (\\big[+%R/0%R]_(i : t) F%R) (only parsing) : ring_scope.\n(*This notation represents the sum of a series of terms given by a function, indexed by natural numbers strictly less than a given bound that also satisfy a given predicate. The sum is computed using the addition and zero element from the underlying ring structure.*)\nNotation \"\\sum_ ( i < n | P ) F\" :=\n (\\big[+%R/0%R]_(i < n | P%B) F%R) : ring_scope.\n(*This notation represents the sum of a series of terms given by a function, indexed by all natural numbers strictly less than a given bound. The sum is computed using the addition and zero element from the underlying ring structure.*)\nNotation \"\\sum_ ( i < n ) F\" :=\n (\\big[+%R/0%R]_(i < n) F%R) : ring_scope.\n(*This notation represents the sum of a series of terms given by a function, indexed by elements belonging to a specific finite set that also satisfy a given predicate. The sum is computed using the addition and zero element from the underlying ring structure.*)\nNotation \"\\sum_ ( i 'in' A | P ) F\" :=\n (\\big[+%R/0%R]_(i in A | P%B) F%R) : ring_scope.\n(*This notation represents the sum of a series of terms given by a function, indexed by all elements belonging to a specific finite set. The sum is computed using the addition and zero element from the underlying ring structure.*)\nNotation \"\\sum_ ( i 'in' A ) F\" :=\n (\\big[+%R/0%R]_(i in A) F%R) : ring_scope.\n\nSection FinFunBaseAddMagma.\nVariable (aT : finType) (rT : baseAddMagmaType).\nImplicit Types f g : {ffun aT -> rT}.\n\n(*This definition specifies the addition of two functions from a finite type to a type with addition. The resulting function, when applied to an element from the domain, yields the sum of the values of the two original functions at that same element.*)\nDefinition ffun_add f g := [ffun a => f a + g a].\n\n(*This lemma states that the pointwise addition of functions from a finite type to a type with a commutative addition is itself a commutative operation.*)\nFact ffun_addrC : commutative (@ffun_add aT rT).\n\n(*This lemma states that the pointwise addition of functions from a finite type to a type with an associative addition is itself an associative operation.*)\nFact ffun_addrA : associative (@ffun_add aT rT).\n\n(*This definition specifies the zero function for functions from a finite type to a type with a zero element. This function maps every element in its domain to the zero element of its codomain.*)\nDefinition ffun_zero := [ffun a : aT => (0 : rT)].\n\n(*This lemma states that the zero function acts as a left identity for the pointwise addition of functions. Adding the zero function to any other function results in that other function unchanged.*)\nFact ffun_add0r : left_id (@ffun_zero aT rT) (@ffun_add aT rT).\n\n(*This lemma states that evaluating a function scaled by a natural number at a given point is equivalent to first evaluating the function at that point and then scaling the resulting value by the same natural number.*)\nLemma ffunMnE f n x : (f *+ n) x = f x *+ n.\n\nSection Sum.\n\nVariables (I : Type) (r : seq I) (P : pred I) (F : I -> {ffun aT -> rT}).\n\n(*This lemma states that evaluating a sum of functions at a specific point is equivalent to summing the evaluations of each of these functions at that same point.*)\nLemma sum_ffunE x : (\\sum_(i <- r | P i) F i) x = \\sum_(i <- r | P i) F i x.\n\n(*This lemma provides an extensional equality for the sum of functions, stating that the resulting function is one that maps each element of the domain to the sum of the values of the individual functions at that element.*)\nLemma sum_ffun :\n \\sum_(i <- r | P i) F i = [ffun x => \\sum_(i <- r | P i) F i x].\n\nEnd Sum.\n\nEnd FinFunNmod.\n\nSection FinFunZmod.\n\nVariable (aT : finType) (rT : zmodType).\nImplicit Types f g : {ffun aT -> rT}.\n\n(*This definition specifies the additive inverse of a function from a finite type to a type with an additive inverse operation. The resulting function, when applied to an element, yields the additive inverse of the value of the original function at that element.*)\nDefinition ffun_opp f := [ffun a => - f a].\n\nHB.instance Definition _ := hasOpp.Build {ffun aT -> rT} ffun_opp.\n\n(*This lemma states that the pointwise additive inverse of a function is a true left inverse for pointwise function addition with respect to the zero function.*)\nFact ffun_addNr : left_inverse 0 ffun_opp +%R.\n\n(*This definition specifies the addition of two pairs as the component-wise sum of their elements, creating a new pair where the first element is the sum of the first elements of the input pairs, and the second element is the sum of their second elements.*)\nDefinition add_pair (a b : U * V) := (a.1 + b.1, a.2 + b.2).\n\n(*This lemma states that the component-wise addition of pairs is commutative, provided that the addition operations on the components are themselves commutative.*)\nFact pair_addrC : commutative (@add_pair U V).\n\n(*This lemma states that the component-wise addition of pairs is associative, provided that the addition operations on the components are themselves associative.*)\nFact pair_addrA : associative (@add_pair U V).\n\n(*This definition specifies the zero element for a product type as the pair consisting of the zero elements from each of the component types.*)\nDefinition pair_zero : U * V := (0, 0).\n\nHB.instance Definition _ := hasZero.Build (U * V)%type pair_zero.\n\n(*This lemma states that the function which projects onto the first component of a pair is a module morphism, preserving the structure of addition and scalar multiplication.*)\nFact fst_is_zmod_morphism : nmod_morphism (@fst U V). \n(*This lemma states that the function which projects onto the second component of a pair is a module morphism, preserving the structure of addition and scalar multiplication.*)\nFact snd_is_zmod_morphism : nmod_morphism (@snd U V). \n\nHB.instance Definition _ :=\n isNmodMorphism.Build _ _ (@fst U V) fst_is_zmod_morphism.\n(*This lemma states that the zero pair, where both components are zero, acts as a left identity for the component-wise addition of pairs.*)\nFact pair_add0r : left_id (@pair_zero U V) (@add_pair U V).\n\n(*This definition specifies the additive inverse of a pair as the pair formed by taking the additive inverses of each component individually.*)\nDefinition pair_opp (a : U * V) := (- a.1, - a.2).\n\nHB.instance Definition _ := hasOpp.Build (U * V)%type pair_opp.\n\n(*This lemma states that the component-wise additive inverse of a pair is a true left inverse for component-wise pair addition with respect to the zero pair.*)\nFact pair_addNr : left_inverse 0 pair_opp +%R.\n\n(*This lemma states that the generic zero element is equal to the specific zero element of the natural numbers.*)\nLemma natr0E : 0 = 0%N. \n(*This lemma states that the standard addition of two natural numbers is equal to their sum when interpreted within the algebraic structure of the natural numbers.*)\nLemma natrDE n m : n + m = (n + m)%N. \n(*This definition bundles two lemmas, one establishing the correspondence for the zero element and the other for the addition operation, to demonstrate that the identity function on natural numbers preserves the basic additive structure.*)", - "boot.seq": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope seq_scope.\n\nReserved Notation \"[ '<->' P0 ; P1 ; .. ; Pn ]\"\n (format \"[ '<->' '[' P0 ; '/' P1 ; '/' .. ; '/' Pn ']' ]\").\n\nDelimit Scope seq_scope with SEQ.\nOpen Scope seq_scope.\n\n(*A notation that establishes `seq` as an alias for the built-in list type, used to represent finite sequences of elements.*)\nNotation seq := list.\nBind Scope seq_scope with list.\nArguments cons {T%_type} x s%_SEQ : rename.\nArguments nil {T%_type} : rename.\nNotation Cons T := (@cons T) (only parsing).\nNotation Nil T := (@nil T) (only parsing).\n\nInfix \"::\" := cons : seq_scope.\n\n(*A notation for the empty sequence.*)\nNotation \"[ :: ]\" := nil (format \"[ :: ]\") : seq_scope.\n\n(*A notation for a sequence containing a single element.*)\nNotation \"[ :: x1 ]\" := (x1 :: [::]) (format \"[ :: x1 ]\") : seq_scope.\n\n(*A notation for constructing a new sequence by prepending a given element to an existing sequence.*)\nNotation \"[ :: x & s ]\" := (x :: s) (only parsing) : seq_scope.\n\n(*A notation for constructing a new sequence by prepending a variable number of specified elements to an existing sequence.*)\nNotation \"[ :: x1 , x2 , .. , xn & s ]\" := (x1 :: x2 :: .. (xn :: s) ..)\n (format\n \"'[hv' [ :: '[' x1 , '/' x2 , '/' .. , '/' xn ']' '/ ' & s ] ']'\"\n ) : seq_scope.\n\n(*A notation for constructing a sequence from a variable number of specified elements.*)\nNotation \"[ :: x1 ; x2 ; .. ; xn ]\" := (x1 :: x2 :: .. [:: xn] ..)\n (format \"[ :: '[' x1 ; '/' x2 ; '/' .. ; '/' xn ']' ]\"\n ) : seq_scope.\n\nSection Sequences.\n\nVariable n0 : nat. \nVariable T : Type. \nVariable x0 : T. \n\nImplicit Types x y z : T.\nImplicit Types m n : nat.\nImplicit Type s : seq T.\n\n(*This function computes the length of a finite sequence, returning the count of its elements as a natural number.*)\nFixpoint size s := if s is _ :: s' then (size s').+1 else 0.\n\n(*This lemma states that if the size of a sequence is zero, then the sequence must be the empty sequence.*)\nLemma size0nil s : size s = 0 -> s = [::]. \n\n(*This definition provides a boolean test to check if a sequence is empty by comparing its size to zero.*)\nDefinition nilp s := size s == 0.\n\n(*This lemma establishes the logical equivalence between a sequence being equal to the empty sequence and the boolean test for an empty sequence evaluating to true.*)\nLemma nilP s : reflect (s = [::]) (nilp s).\n\n(*This definition retrieves the first element of a sequence, returning it as an optional value which is none if the sequence is empty.*)\nDefinition ohead s := if s is x :: _ then Some x else None.\n(*This definition retrieves the first element of a sequence, returning a specified default value if the sequence is empty.*)\nDefinition head s := if s is x :: _ then x else x0.\n\n(*This definition returns a new sequence containing all elements of the input sequence except the first one, or returns the empty sequence if the input sequence is already empty.*)\nDefinition behead s := if s is _ :: s' then s' else [::].\n\n(*This lemma states that the size of a sequence after removing its first element is one less than the size of the original sequence.*)\nLemma size_behead s : size (behead s) = (size s).-1.\n\n(*This definition constructs a new sequence by prepending a given element a specified number of times to the front of an existing sequence.*)\nDefinition ncons n x := iter n (cons x).\n(*This definition creates a new sequence of a specified length, containing only repetitions of a single given element.*)\nDefinition nseq n x := ncons n x [::].\n\n(*This lemma states that the size of a sequence created by prepending an element a given number of times to an original sequence is the sum of that number and the size of the original sequence.*)\nLemma size_ncons n x s : size (ncons n x s) = n + size s.\n\n(*This lemma states that the size of a sequence created by repeating a given element a certain number of times is equal to that number.*)\nLemma size_nseq n x : size (nseq n x) = n.\n\n(*This definition describes the type of a curried function that takes a specified number of arguments and returns a sequence. For a non-zero number of arguments, it is a function type; for zero arguments, it is the type of a sequence.*)\nFixpoint seqn_type n := if n is n'.+1 then T -> seqn_type n' else seq T.\n\n(*This definition provides a recursive way to build a curried function of a specified arity from a base function that operates on a sequence. The resulting function takes the specified number of arguments, constructs a sequence from them, and then applies the base function to that sequence.*)\nFixpoint seqn_rec f n : seqn_type n :=\n if n is n'.+1 return seqn_type n then\n fun x => seqn_rec (fun s => f (x :: s)) n'\n else f [::].\n(*This definition creates a curried function of a specified arity that takes a number of arguments and constructs a sequence containing exactly those arguments in the order they were provided.*)\nDefinition seqn := seqn_rec id.\n\n(*This function concatenates two sequences, producing a new sequence containing all elements of the first sequence followed by all elements of the second sequence.*)\nFixpoint cat s1 s2 := if s1 is x :: s1' then x :: s1' ++ s2 else s2\nwhere \"s1 ++ s2\" := (cat s1 s2) : seq_scope.\n\n(*This lemma states that concatenating an empty sequence with any given sequence results in the given sequence unchanged.*)\nLemma cat0s s : [::] ++ s = s. \n(*This lemma states that concatenating a sequence containing a single element with a second sequence is equivalent to prepending that single element to the second sequence.*)\nLemma cat1s x s : [:: x] ++ s = x :: s. \n(*This lemma states that concatenating a non-empty sequence with another sequence is equivalent to prepending the first element of the non-empty sequence to the result of concatenating its tail with the other sequence.*)\nLemma cat_cons x s1 s2 : (x :: s1) ++ s2 = x :: s1 ++ s2. \n\n(*This lemma states that concatenating a sequence of repeated elements with another sequence is equivalent to prepending those repeated elements to the other sequence.*)\nLemma cat_nseq n x s : nseq n x ++ s = ncons n x s.\n\n(*This lemma states that a sequence formed by repeating an element a number of times equal to a sum is the same as concatenating two sequences where the element is repeated a number of times corresponding to each term of the sum.*)\nLemma nseqD n1 n2 x : nseq (n1 + n2) x = nseq n1 x ++ nseq n2 x.\n\n(*This lemma states that concatenating any sequence with an empty sequence results in the original sequence unchanged.*)\nLemma cats0 s : s ++ [::] = s.\n\n(*This lemma states that sequence concatenation is associative.*)\nLemma catA s1 s2 s3 : s1 ++ s2 ++ s3 = (s1 ++ s2) ++ s3.\n\n(*This lemma states that the size of the concatenation of two sequences is the sum of their individual sizes.*)\nLemma size_cat s1 s2 : size (s1 ++ s2) = size s1 + size s2.\n\n(*This lemma states that a concatenation of two finite sequences is empty if and only if both original finite sequences are empty.*)\nLemma cat_nilp s1 s2 : nilp (s1 ++ s2) = nilp s1 && nilp s2.\n\n(*This function constructs a new finite sequence by appending a given element to the end of an existing finite sequence.*)\nFixpoint rcons s z := if s is x :: s' then x :: rcons s' z else [:: z].\n\n(*This lemma states that appending an element to a non-empty finite sequence is equivalent to prepending the first element of the original sequence to the result of appending that element to the tail of the original sequence.*)\nLemma rcons_cons x s z : rcons (x :: s) z = x :: rcons s z.\n\n(*This lemma states that concatenating a finite sequence with a singleton finite sequence containing a specific element is equivalent to appending that element to the first finite sequence.*)\nLemma cats1 s z : s ++ [:: z] = rcons s z.\n\n(*This function returns the last element of a non-empty finite sequence formed by prepending a given element to another sequence; if the latter sequence is empty, it returns the prepended element.*)\nFixpoint last x s := if s is x' :: s' then last x' s' else x.\n(*This function returns a new finite sequence containing all but the last element of a sequence formed by prepending a given element to another sequence; if the latter sequence is empty, it returns an empty sequence.*)\nFixpoint belast x s := if s is x' :: s' then x :: (belast x' s') else [::].\n\n(*This lemma states that any non-empty finite sequence can be reconstructed by appending its last element to the finite sequence of its preceding elements.*)\nLemma lastI x s : x :: s = rcons (belast x s) (last x s).\n\n(*This lemma states that the last element of a finite sequence constructed by prepending two elements is the same as the last element of the finite sequence constructed by prepending only the second element to the tail.*)\nLemma last_cons x y s : last x (y :: s) = last y s.\n\n(*This lemma states that the size of a finite sequence created by appending an element is one greater than the size of the original finite sequence.*)\nLemma size_rcons s x : size (rcons s x) = (size s).+1.\n\n(*This lemma states that the size of a finite sequence containing all but the last element of a sequence constructed by prepending an element is equal to the size of the original sequence tail.*)\nLemma size_belast x s : size (belast x s) = size s.\n\n(*This lemma states that the last element of the concatenation of two finite sequences is the last element of the second sequence, using the last element of the first sequence as the default value for the computation.*)\nLemma last_cat x s1 s2 : last x (s1 ++ s2) = last (last x s1) s2.\n\n(*This lemma states that the last element of a finite sequence constructed by appending a specific element is that specific element.*)\nLemma last_rcons x s z : last x (rcons s z) = z.\n\n(*This lemma states that removing the last element from a concatenation of two finite sequences results in the concatenation of two parts: the first sequence with its last element removed, and the second sequence with its last element removed, where the latter operation uses the last element of the first sequence as its initial value.*)\nLemma belast_cat x s1 s2 :\n belast x (s1 ++ s2) = belast x s1 ++ belast (last x s1) s2.\n\n(*This lemma states that removing the last element from a sequence formed by appending an element results in the original sequence, prepended with a given initial element.*)\nLemma belast_rcons x s z : belast x (rcons s z) = x :: s.\n\n(*This lemma states that concatenating a sequence formed by appending an element with a second sequence is equivalent to concatenating the original first sequence with the second sequence having that element prepended.*)\nLemma cat_rcons x s1 s2 : rcons s1 x ++ s2 = s1 ++ x :: s2.\n\n(*This lemma states that appending an element to the concatenation of two finite sequences is equivalent to concatenating the first sequence with the result of appending the element to the second sequence.*)\nLemma rcons_cat x s1 s2 : rcons (s1 ++ s2) x = s1 ++ rcons s2 x.\n\n(*This inductive proposition formalizes the property that a given value is the last element of a finite sequence.*)\nVariant last_spec : seq T -> Type :=\n(*A constructor for an inductive specification of an operation that retrieves the last element of a sequence, representing the case where the input sequence is empty and thus has no last element.*)\n | LastNil : last_spec [::]\n(**)\n | LastRcons s x : last_spec (rcons s x).\n\n(*This lemma states that any finite sequence is either empty or can be constructed by appending one element to the end of another finite sequence.*)\nLemma lastP s : last_spec s.\n\n(*This lemma provides an induction principle for finite sequences, allowing a property to be proven for all finite sequences by showing it holds for the empty sequence and that it is preserved when an element is appended to a sequence for which the property already holds.*)\nLemma last_ind P :\n P [::] -> (forall s x, P s -> P (rcons s x)) -> forall s, P s.\n\n(*This function retrieves the element at a specified natural number index from a finite sequence; if the index is out of bounds, it returns a globally specified default element.*)\nFixpoint nth s n {struct n} :=\n if s is x :: s' then if n is n'.+1 then @nth s' n' else x else x0.\n\n(*This function produces a new finite sequence by replacing the element at a given index with a new value. If the index is out of bounds, the original sequence is first extended with default elements as needed.*)\nFixpoint set_nth s n y {struct n} :=\n if s is x :: s' then if n is n'.+1 then x :: @set_nth s' n' y else y :: s'\n else ncons n x0 [:: y].\n\n(*This lemma states that retrieving the element at index zero from a finite sequence is equivalent to getting the head of that sequence.*)\nLemma nth0 s : nth s 0 = head s. \n\n(*This lemma states that retrieving an element from a finite sequence at an index greater than or equal to its size will return the default element.*)\nLemma nth_default s n : size s <= n -> nth s n = x0.\n\n(*This lemma asserts that a conditional expression, which returns the element at a specific index if a boolean is true and a default value otherwise, is equal to simply getting the element at that index, provided that either the boolean is true or the index is out of the sequence's bounds.*)\nLemma if_nth s b n : b || (size s <= n) ->\n (if b then nth s n else x0) = nth s n.\n\n(*This lemma states that retrieving an element from an empty finite sequence at any index returns the default element.*)\nLemma nth_nil n : nth [::] n = x0.\n\n(*This lemma states that retrieving an element from a singleton finite sequence at a given index returns the element itself if the index is zero, and the default element otherwise.*)\nLemma nth_seq1 n x : nth [:: x] n = if n == 0 then x else x0.\n\n(*This lemma states that the last element of a sequence constructed by prepending an element is the same as the element at the index equal to the size of the original tail.*)\nLemma last_nth x s : last x s = nth (x :: s) (size s).\n\n(*This lemma states that the element at the index preceding the size of a non-empty finite sequence is its last element, when calculated with a default initial value.*)\nLemma nth_last s : nth s (size s).-1 = last x0 s.\n\n(*This lemma states that the element at a given index in the tail of a finite sequence is the same as the element at the subsequent index in the original sequence.*)\nLemma nth_behead s n : nth (behead s) n = nth s n.+1.\n\n(*This lemma states that the element at a given index in the concatenation of two finite sequences is the element at that same index in the first sequence if the index is within its bounds; otherwise, it is the element in the second sequence at an index adjusted by the size of the first sequence.*)\nLemma nth_cat s1 s2 n :\n nth (s1 ++ s2) n = if n < size s1 then nth s1 n else nth s2 (n - size s1).\n\n(*This lemma states that retrieving an element at a given index from a sequence formed by appending an element will return the appended element if the index is the last position, the element from the original sequence if the index is within the original bounds, or a default value for any other index.*)\nLemma nth_rcons s x n :\n nth (rcons s x) n =\n if n < size s then nth s n else if n == size s then x else x0.\n\n(*This lemma states that retrieving an element at a given index from a sequence extended with a default element is equivalent to retrieving the element at the same index from the original sequence.*)\nLemma nth_rcons_default s i : nth (rcons s x0) i = nth s i.\n\n(*This lemma states that accessing an element at a given index from a sequence that has been prepended with multiple copies of a value results in that value if the index is within the prepended block, and otherwise corresponds to accessing an element in the original sequence at a shifted index.*)\nLemma nth_ncons m x s n :\n nth (ncons m x s) n = if n < m then x else nth s (n - m).\n\n(*This lemma states that accessing an element at a given index from a sequence composed of a repeated value results in that value if the index is within the sequence's bounds, and a default value otherwise.*)\nLemma nth_nseq m x n : nth (nseq m x) n = (if n < m then x else x0).\n\n(*This lemma asserts the principle of extensionality for sequences, stating that two sequences are equal if they have the same size and their corresponding elements at all valid indices are equal.*)\nLemma eq_from_nth s1 s2 :\n size s1 = size s2 -> (forall i, i < size s1 -> nth s1 i = nth s2 i) ->\n s1 = s2.\n\n(*This lemma states that the size of a sequence after setting or updating an element at a given index is the maximum of the original sequence's size and one plus the given index.*)\nLemma size_set_nth s n y : size (set_nth s n y) = maxn n.+1 (size s).\n\n(*This lemma states that setting an element at a given index in an empty sequence is equivalent to creating a new sequence by prepending the required number of default elements to a singleton sequence containing the new element.*)\nLemma set_nth_nil n y : set_nth [::] n y = ncons n x0 [:: y].\n\n(*This lemma states that the function for accessing elements of a sequence modified at a specific index is extensionally equal to a function that returns the new value at that index and otherwise behaves like the access function for the original sequence.*)\nLemma nth_set_nth s n y : nth (set_nth s n y) =1 [eta nth s with n |-> y].\n\n(*This lemma states that if a sequence is updated at the same index twice, the second update overwrites the first; otherwise, the two updates are independent and their order does not matter.*)\nLemma set_set_nth s n1 y1 n2 y2 (s2 := set_nth s n2 y2) :\n set_nth (set_nth s n1 y1) n2 y2 = if n1 == n2 then s2 else set_nth s2 n1 y1.\n\nSection SeqFind.\n\nVariable a : pred T.\n\n(*This function defines a search operation that returns the index of the first element in a sequence satisfying a given predicate, or the size of the sequence if no such element exists.*)\nFixpoint find s := if s is x :: s' then if a x then 0 else (find s').+1 else 0.\n\n(*This function defines an operation that creates a new sequence containing only those elements from an input sequence that satisfy a given predicate, preserving their original relative order.*)\nFixpoint filter s :=\n if s is x :: s' then if a x then x :: filter s' else filter s' else [::].\n\n(*This function defines an operation that counts the number of elements in a sequence that satisfy a given predicate.*)\nFixpoint count s := if s is x :: s' then a x + count s' else 0.\n\n(*This function defines a boolean check that determines whether at least one element in a sequence satisfies a given predicate.*)\nFixpoint has s := if s is x :: s' then a x || has s' else false.\n\n(*This function defines a boolean check that determines whether all elements in a sequence satisfy a given predicate.*)\nFixpoint all s := if s is x :: s' then a x && all s' else true.\n\n(*This lemma states that the size of a sequence resulting from a filter operation is equal to the count of elements that satisfy the filtering predicate in the original sequence.*)\nLemma size_filter s : size (filter s) = count s.\n\n(*This lemma states that a sequence contains an element satisfying a given predicate if and only if the count of such elements is greater than zero.*)\nLemma has_count s : has s = (0 < count s).\n\n(*This lemma states that the number of elements in a sequence satisfying a given predicate is always less than or equal to the total size of the sequence.*)\nLemma count_size s : count s <= size s.\n\n(*This lemma states that all elements of a sequence satisfy a predicate if and only if the count of elements satisfying the predicate is equal to the size of the sequence.*)\nLemma all_count s : all s = (count s == size s).\n\n(*This lemma states that after filtering a sequence with a given predicate, all elements in the resulting sequence will satisfy that same predicate.*)\nLemma filter_all s : all (filter s).\n\n(*This lemma provides a reflection property, stating that filtering a sequence with a given predicate results in the original sequence if and only if all elements of the original sequence satisfy that predicate.*)\nLemma all_filterP s : reflect (filter s = s) (all s).\n\n(*This lemma states that the filter operation is idempotent, meaning that applying the same filter twice to a sequence yields the same result as applying it once.*)\nLemma filter_id s : filter (filter s) = filter s.\n\n(*This lemma connects the existence of an element satisfying a predicate with the result of a search, stating that such an element exists if and only if the index returned by the find operation is less than the size of the sequence.*)\nLemma has_find s : has s = (find s < size s).\n\n(*This lemma states that the index returned by the find operation on a sequence is always less than or equal to the size of that sequence.*)\nLemma find_size s : find s <= size s.\n\n(*This lemma describes how the find operation behaves on a concatenated sequence: if an element satisfying the predicate exists in the first sequence, the result is its index; otherwise, the result is the size of the first sequence plus the index of the element found in the second sequence.*)\nLemma find_cat s1 s2 :\n find (s1 ++ s2) = if has s1 then find s1 else size s1 + find s2.\n\n(*This lemma states that a check for the existence of an element satisfying a predicate on an empty sequence always evaluates to false.*)\nLemma has_nil : has [::] = false. \n\n(*This lemma states that for a sequence with a single element, checking for an element that satisfies a predicate is equivalent to applying the predicate directly to that single element.*)\nLemma has_seq1 x : has [:: x] = a x.\n\n(*This lemma states that a sequence composed of repeated instances of a value has an element satisfying a given predicate if and only if the sequence is non-empty and the value itself satisfies the predicate.*)\nLemma has_nseq n x : has (nseq n x) = (0 < n) && a x.\n\n(*This lemma states that for a sequence whose creation from an element depends on a boolean flag, the check for an element satisfying a predicate is true if and only if the flag is true and the element itself satisfies the predicate.*)\nLemma has_seqb (b : bool) x : has (nseq b x) = b && a x.\n\n(*This lemma states that a check for whether all elements of an empty sequence satisfy a predicate always evaluates to true.*)\nLemma all_nil : all [::] = true. \n\n(*This lemma states that for a sequence with a single element, checking if all elements satisfy a predicate is equivalent to applying the predicate directly to that single element.*)\nLemma all_seq1 x : all [:: x] = a x.\n\n(*This lemma states that for a sequence composed of repeated instances of a value, all elements satisfy a given predicate if and only if the sequence is empty or the value itself satisfies the predicate.*)\nLemma all_nseq n x : all (nseq n x) = (n == 0) || a x.\n\n(*This lemma relates the `all` operation on a conditional sequence to a boolean implication. It states that determining if a predicate holds for all members of a sequence\u2014which is either a singleton sequence containing a given element, or an empty sequence, depending on a boolean\u2014is equivalent to the logical implication from that boolean to the predicate applied to the element.*)\nLemma all_nseqb (b : bool) x : all (nseq b x) = b ==> a x.\n\n(*This lemma asserts that filtering a sequence of a given number of identical elements results in a new sequence of the same element, where the length is the original number if the predicate holds for the element, and zero otherwise.*)\nLemma filter_nseq n x : filter (nseq n x) = nseq (a x * n) x.\n\n(*This lemma states that the number of elements satisfying a predicate in a sequence of a given number of identical elements is equal to that number if the predicate is true for that element, and zero otherwise.*)\nLemma count_nseq n x : count (nseq n x) = a x * n.\n\n(*This lemma states that the index of the first element satisfying a predicate in a sequence of a given number of identical elements is zero if the predicate holds for that element, and the sequence's length if it does not.*)\nLemma find_nseq n x : find (nseq n x) = ~~ a x * n.\n\n(*This lemma asserts that if a sequence contains at least one element satisfying a given predicate, then applying the predicate to the element found at the first matching index will yield true.*)\nLemma nth_find s : has s -> a (nth s (find s)).\n\n(*This lemma states that for any index that is less than the index of the first element satisfying a predicate in a sequence, the predicate applied to the element at that index will be false.*)\nLemma before_find s i : i < find s -> a (nth s i) = false.\n\n(*This lemma states that if a sequence has no elements that satisfy a given predicate, then the `find` operation on that sequence will return the size of the sequence.*)\nLemma hasNfind s : ~~ has s -> find s = size s.\n\n(*This lemma states that filtering the concatenation of two sequences is equivalent to concatenating the results of filtering each sequence individually.*)\nLemma filter_cat s1 s2 : filter (s1 ++ s2) = filter s1 ++ filter s2.\n\n(*This lemma describes how filtering works on a sequence with an element appended. The result is the filtered original sequence, with the appended element also included if it satisfies the predicate; otherwise, it is just the filtered original sequence.*)\nLemma filter_rcons s x :\n filter (rcons s x) = if a x then rcons (filter s) x else filter s.\n\n(*This lemma states that the number of elements satisfying a predicate in the concatenation of two sequences is the sum of the counts from each individual sequence.*)\nLemma count_cat s1 s2 : count (s1 ++ s2) = count s1 + count s2.\n\n(*This lemma states that a concatenated sequence has an element satisfying a predicate if and only if at least one of the original sequences has such an element.*)\nLemma has_cat s1 s2 : has (s1 ++ s2) = has s1 || has s2.\n\n(*This lemma asserts that a sequence with an element appended to it contains an element satisfying a predicate if and only if the appended element itself satisfies the predicate or the original sequence already contained such an element.*)\nLemma has_rcons s x : has (rcons s x) = a x || has s.\n\n(*This lemma states that a predicate holds for all elements of a concatenated sequence if and only if it holds for all elements of both original sequences.*)\nLemma all_cat s1 s2 : all (s1 ++ s2) = all s1 && all s2.\n\n(*This lemma asserts that a predicate holds for all elements of a sequence with an element appended if and only if the predicate holds for the appended element and for all elements of the original sequence.*)\nLemma all_rcons s x : all (rcons s x) = a x && all s.\n\nEnd SeqFind.\n\n(*This lemma states that finding the first element in a sequence that satisfies a predicate that is always false will always result in returning the size of the sequence.*)\nLemma find_pred0 s : find pred0 s = size s. \n\n(*This lemma states that finding the first element in a sequence that satisfies a predicate that is always true will always return the index zero.*)\nLemma find_predT s : find predT s = 0.\n\n(*This lemma states that if two predicates are pointwise equal, then the `find` operation using either predicate will be pointwise equal, meaning it will return the same index for any given sequence.*)\nLemma eq_find a1 a2 : a1 =1 a2 -> find a1 =1 find a2.\n\n(*This lemma states that if two predicates are pointwise equal, then the `filter` operation using either predicate will be pointwise equal, meaning it will produce the same output sequence for any given input sequence.*)\nLemma eq_filter a1 a2 : a1 =1 a2 -> filter a1 =1 filter a2.\n\n(*This lemma states that if two predicates are pointwise equal, then the `count` operation using either predicate will be pointwise equal, meaning it will return the same count for any given sequence.*)\nLemma eq_count a1 a2 : a1 =1 a2 -> count a1 =1 count a2.\n\n(*This lemma states that if two predicates are pointwise equal, then the `has` operation using either predicate will be pointwise equal, meaning it will return the same boolean result for any given sequence.*)\nLemma eq_has a1 a2 : a1 =1 a2 -> has a1 =1 has a2.\n\n(*This lemma states that if two predicates are pointwise equal, then the `all` operation using either predicate will be pointwise equal, meaning it will return the same boolean result for any given sequence.*)\nLemma eq_all a1 a2 : a1 =1 a2 -> all a1 =1 all a2.\n\n(*This lemma states that checking if a first predicate holds for all elements of a sequence filtered by a second predicate is equivalent to checking if all elements in the original unfiltered sequence satisfy the boolean implication from the second predicate to the first.*)\nLemma all_filter (p q : pred T) xs :\n all p (filter q xs) = all [pred i | q i ==> p i] xs.\n\nSection SubPred.\n\nVariable (a1 a2 : pred T).\nHypothesis s12 : subpred a1 a2.\n\n(*This lemma asserts that if a first predicate implies a second predicate, then for any sequence, the index of the first element satisfying the second predicate will be less than or equal to the index of the first element satisfying the first predicate.*)\nLemma sub_find s : find a2 s <= find a1 s.\n\n(*This lemma states that if a first predicate implies a second predicate, then the existence of an element in a sequence satisfying the first predicate implies the existence of an element satisfying the second.*)\nLemma sub_has s : has a1 s -> has a2 s.\n\n(*This lemma asserts that if a first predicate implies a second predicate, then for any sequence, the number of elements satisfying the first predicate is less than or equal to the number of elements satisfying the second.*)\nLemma sub_count s : count a1 s <= count a2 s.\n\n(*This lemma states that if a first predicate implies a second predicate, and the first predicate holds for all elements of a sequence, then the second predicate must also hold for all elements of that sequence.*)\nLemma sub_all s : all a1 s -> all a2 s.\n\nEnd SubPred.\n\n(*This lemma states that filtering a sequence with a predicate that is always false results in an empty sequence.*)\nLemma filter_pred0 s : filter pred0 s = [::]. \n\n(*This lemma states that filtering a sequence with a predicate that is always true results in the original sequence unchanged.*)\nLemma filter_predT s : filter predT s = s.\n\n(*This lemma states that filtering a sequence with a predicate formed by the logical conjunction of two other predicates is equivalent to filtering the sequence with the second predicate, and then filtering the resulting sequence with the first predicate.*)\nLemma filter_predI a1 a2 s : filter (predI a1 a2) s = filter a1 (filter a2 s).\n\n(*This lemma states that counting the number of elements in a sequence that satisfy a predicate that is always false will always result in zero.*)\nLemma count_pred0 s : count pred0 s = 0.\n\n(*This lemma states that counting the elements of a sequence that satisfy the universally true predicate is equivalent to computing the size of the sequence.*)\nLemma count_predT s : count predT s = size s.\n\n(*This lemma states that for any two predicates and a sequence, the sum of the count of elements satisfying their disjunction and the count of elements satisfying their conjunction equals the sum of the counts of elements satisfying each predicate individually.*)\nLemma count_predUI a1 a2 s :\n count (predU a1 a2) s + count (predI a1 a2) s = count a1 s + count a2 s.\n\n(*This lemma states that for any given predicate and sequence, the sum of the number of elements satisfying the predicate and the number of elements satisfying its complement is equal to the total size of the sequence.*)\nLemma count_predC a s : count a s + count (predC a) s = size s.\n\n(*This lemma states that counting the elements that satisfy a first predicate within a sequence filtered by a second predicate is equivalent to counting the elements in the original sequence that satisfy the conjunction of both predicates.*)\nLemma count_filter a1 a2 s : count a1 (filter a2 s) = count (predI a1 a2) s.\n\n(*This lemma states that a sequence never has an element that satisfies the universally false predicate.*)\nLemma has_pred0 s : has pred0 s = false.\n\n(*This lemma states that a sequence contains an element satisfying the universally true predicate if and only if the size of the sequence is greater than zero.*)\nLemma has_predT s : has predT s = (0 < size s).\n\n(*This lemma states that a sequence has an element satisfying the complement of a given predicate if and only if it is not the case that all elements of the sequence satisfy the original predicate.*)\nLemma has_predC a s : has (predC a) s = ~~ all a s.\n\n(*This lemma states that a sequence contains an element satisfying the disjunction of two predicates if and only if it contains an element satisfying the first predicate or it contains an element satisfying the second predicate.*)\nLemma has_predU a1 a2 s : has (predU a1 a2) s = has a1 s || has a2 s.\n\n(*This lemma states that all elements of a sequence satisfy the universally false predicate if and only if the sequence is empty.*)\nLemma all_pred0 s : all pred0 s = (size s == 0).\n\n(*This lemma states that for any sequence, all of its elements satisfy the universally true predicate.*)\nLemma all_predT s : all predT s.\n\n(*This lemma states that if a given predicate holds for all values of a type, then it also holds for all elements in any sequence of that type.*)\nLemma allT (a : pred T) s : (forall x, a x) -> all a s.\n\n(*This lemma states that all elements of a sequence satisfy the complement of a given predicate if and only if it is not the case that the sequence has an element satisfying the original predicate.*)\nLemma all_predC a s : all (predC a) s = ~~ has a s.\n\n(*This lemma states that all elements of a sequence satisfy the conjunction of two predicates if and only if all elements satisfy the first predicate and all elements satisfy the second predicate.*)\nLemma all_predI a1 a2 s : all (predI a1 a2) s = all a1 s && all a2 s.\n\n(*This function removes a specified number of elements from the beginning of a finite sequence, returning the rest of the sequence.*)\nFixpoint drop n s {struct s} :=\n match s, n with\n | _ :: s', n'.+1 => drop n' s'\n | _, _ => s\n end.\n\n(*This lemma states that dropping a given number of elements from the front of a sequence is equivalent to repeatedly applying the function that removes the first element, for that given number of times.*)\nLemma drop_behead : drop n0 =1 iter n0 behead.\n\n(*This lemma states that dropping zero elements from a sequence results in the original sequence.*)\nLemma drop0 s : drop 0 s = s. \n\n(*This lemma states that the function that drops one element from a sequence is equivalent to the function that removes the head of the sequence.*)\nLemma drop1 : drop 1 =1 behead. \n\n(*This lemma states that if the number of elements to drop from a sequence is greater than or equal to the size of the sequence, the result is an empty sequence.*)\nLemma drop_oversize n s : size s <= n -> drop n s = [::].\n\n(*This lemma states that dropping a number of elements from a sequence equal to its size results in an empty sequence.*)\nLemma drop_size s : drop (size s) s = [::].\n\n(*This lemma describes the behavior of the drop function on a non-empty sequence. If the number of elements to drop is positive, it decrements the number and applies the drop function to the tail of the sequence; otherwise, if the number is zero, it returns the original sequence.*)\nLemma drop_cons x s :\n drop n0 (x :: s) = if n0 is n.+1 then drop n s else x :: s.\n\n(*This lemma states that the size of a sequence resulting from a drop operation is the original size of the sequence decreased by the number of elements dropped. If the number of elements to drop is greater than the sequence size, the resulting size is zero.*)\nLemma size_drop s : size (drop n0 s) = size s - n0.\n\n(*This lemma states that dropping a number of elements from the concatenation of two sequences is equivalent to either dropping that number from the first sequence and appending the second, if the number is less than the size of the first sequence, or dropping the remaining number of elements from the second sequence otherwise.*)\nLemma drop_cat s1 s2 :\n drop n0 (s1 ++ s2) =\n if n0 < size s1 then drop n0 s1 ++ s2 else drop (n0 - size s1) s2.\n\n(*This lemma states that if a number of elements equal to the size of a first sequence is dropped from the concatenation of the first sequence with a second sequence, the result is the second sequence.*)\nLemma drop_size_cat n s1 s2 : size s1 = n -> drop n (s1 ++ s2) = s2.\n\n(*This lemma states a cancellation property between prepending elements and dropping them. Specifically, if a sequence is extended by prepending an element a certain number of times, subsequently dropping the same number of elements from the front of the new sequence restores the original sequence.*)\nLemma nconsK n x : cancel (ncons n x) (drop n).\n\n(*This lemma states that dropping a number of elements from a sequence, and then dropping another number of elements from the result, is equivalent to dropping the sum of those two numbers of elements from the original sequence.*)\nLemma drop_drop s n1 n2 : drop n1 (drop n2 s) = drop (n1 + n2) s.\n\n(*This function returns a new finite sequence composed of the first specified number of elements from a given sequence.*)\nFixpoint take n s {struct s} :=\n match s, n with\n | x :: s', n'.+1 => x :: take n' s'\n | _, _ => [::]\n end.\n\n(*This lemma states that taking zero elements from a sequence results in an empty sequence.*)\nLemma take0 s : take 0 s = [::]. \n\n(*This lemma states that taking a number of elements from a sequence that is greater than or equal to the sequence's length results in the original sequence.*)\nLemma take_oversize n s : size s <= n -> take n s = s.\n\n(*This lemma states that taking a number of elements from a sequence equal to its length results in the original sequence.*)\nLemma take_size s : take (size s) s = s.\n\n(*This lemma states that taking a given number of elements from a non-empty sequence results in the first element prepended to the result of taking one less element from the tail of the sequence, provided the number is positive; otherwise, it results in an empty sequence.*)\nLemma take_cons x s :\n take n0 (x :: s) = if n0 is n.+1 then x :: (take n s) else [::].\n\n(*This lemma states that dropping a given number of elements from a sequence that has an element appended to its end is equivalent to first dropping that number of elements from the original sequence and then appending the element, provided the number of elements to drop is not greater than the original sequence's length.*)\nLemma drop_rcons s : n0 <= size s ->\n forall x, drop n0 (rcons s x) = rcons (drop n0 s) x.\n\n(*This lemma states that concatenating the prefix of a sequence of a given length with the suffix of the sequence starting after that prefix results in the original sequence.*)\nLemma cat_take_drop s : take n0 s ++ drop n0 s = s.\n\n(*This lemma states that the length of the sequence resulting from taking a given number of elements from another sequence is equal to that number, provided the number is less than or equal to the original sequence's length.*)\nLemma size_takel s : n0 <= size s -> size (take n0 s) = n0.\n\n(*This lemma states that the length of the sequence resulting from taking a given number of elements from another sequence is equal to that number if it is less than the original sequence's length, and is equal to the original sequence's length otherwise.*)\nLemma size_take s : size (take n0 s) = if n0 < size s then n0 else size s.\n\n(*This lemma states that the length of a sequence obtained by taking a specified number of elements from an original sequence is the minimum of that number and the length of the original sequence.*)\nLemma size_take_min s : size (take n0 s) = minn n0 (size s).\n\n(*This lemma states how to take a prefix of a given length from the concatenation of two sequences: if the length is less than the length of the first sequence, it is equivalent to taking that prefix from the first sequence; otherwise, it is the first sequence concatenated with a prefix of the second sequence, where the length of that prefix is the original desired length minus the length of the first sequence.*)\nLemma take_cat s1 s2 :\n take n0 (s1 ++ s2) =\n if n0 < size s1 then take n0 s1 else s1 ++ take (n0 - size s1) s2.\n\n(*This lemma states that taking a prefix from the concatenation of two sequences, where the length of the prefix is equal to the length of the first sequence, results in the first sequence.*)\nLemma take_size_cat n s1 s2 : size s1 = n -> take n (s1 ++ s2) = s1.\n\n(*This lemma states that taking a prefix of a given length from the concatenation of two sequences is equivalent to taking a prefix of the same length from the first sequence, provided that the length is less than or equal to the length of the first sequence.*)\nLemma takel_cat s1 s2 : n0 <= size s1 -> take n0 (s1 ++ s2) = take n0 s1.\n\n(*This lemma states that the element at a given index in a sequence, from which an initial prefix has been dropped, is equivalent to the element at the index offset by the length of the dropped prefix in the original sequence.*)\nLemma nth_drop s i : nth (drop n0 s) i = nth s (n0 + i).\n\n(*This lemma states that if a predicate holds for at least one element within a prefix of a given length of a sequence, then the index of the first element in the entire sequence that satisfies the predicate is less than that length.*)\nLemma find_ltn p s i : has p (take i s) -> find p s < i.\n\n(*This lemma states that, for a sequence containing an element that satisfies a given predicate, the property of having such an element within a prefix of a given length is equivalent to the index of the first such element being less than that length.*)\nLemma has_take p s i : has p s -> has p (take i s) = (find p s < i).\n\n(*This lemma states that for a prefix of a given length taken from a sequence, the existence of an element satisfying a predicate within that prefix is equivalent to the index of the first such element in the whole sequence being less than that length, provided the length of the prefix does not exceed the sequence's length.*)\nLemma has_take_leq (p : pred T) (s : seq T) i : i <= size s ->\n has p (take i s) = (find p s < i).\n\n(*This lemma states that the element at a given index within a prefix of a sequence is the same as the element at that same index in the original sequence, provided the index is less than the length of the prefix.*)\nLemma nth_take i : i < n0 -> forall s, nth (take n0 s) i = nth s i.\n\n(*This lemma states that taking a prefix of a sequence, with a length equal to the minimum of two natural numbers, is equivalent to sequentially taking a prefix of the second number's length and then taking a prefix of the first number's length from the result.*)\nLemma take_min i j s : take (minn i j) s = take i (take j s).\n\n(*This lemma states that if a first natural number is less than or equal to a second one, taking a prefix of the first number's length from a prefix of the second number's length of a sequence is equivalent to just taking a prefix of the first number's length from the original sequence.*)\nLemma take_takel i j s : i <= j -> take i (take j s) = take i s.\n\n(*This lemma states that if a second natural number is less than or equal to a first one, taking a prefix of the first number's length from a prefix of the second number's length of a sequence results in the prefix of the second number's length.*)\nLemma take_taker i j s : j <= i -> take i (take j s) = take j s.\n\n(*This lemma states that taking a prefix of a given length from a sequence after dropping an initial segment is equivalent to first taking a longer prefix, whose length is the sum of the two lengths, and then dropping an initial segment of the second length from the result.*)\nLemma take_drop i j s : take i (drop j s) = drop j (take (i + j) s).\n\n(*This lemma provides a way to decompose a prefix of a sequence. It states that taking a prefix of a length equal to the sum of two numbers is equivalent to concatenating a prefix of the first number's length with a prefix of the second number's length taken from the sequence after dropping the first prefix.*)\nLemma takeD i j s : take (i + j) s = take i s ++ take j (drop i s).\n\n(*This lemma states that the operation of taking a prefix of a sequence is commutative, meaning the order in which two nested take operations are applied does not change the final result.*)\nLemma takeC i j s : take i (take j s) = take j (take i s).\n\n(*This lemma states that taking a prefix of a given length from a sequence composed of repeated instances of a single element results in a new sequence of that same element, with a length equal to the prefix length, provided the prefix length is less than or equal to the original sequence's length.*)\nLemma take_nseq i j x : i <= j -> take i (nseq j x) = nseq i x.\n\n(*This lemma states that dropping an initial segment of a given length from a sequence composed of repeated instances of a single element results in a new sequence of that same element, with a length equal to the original length minus the length of the dropped segment.*)\nLemma drop_nseq i j x : drop i (nseq j x) = nseq (j - i) x.\n\n(*This lemma provides a recursive characterization of dropping a prefix from a sequence. It states that dropping a prefix of a given length, where the length is a valid index, is equivalent to taking the element at that index and prepending it to the sequence that results from dropping a prefix that is one element longer.*)\nLemma drop_nth n s : n < size s -> drop n s = nth s n :: drop n.+1 s.\n\n(*This lemma provides a recursive characterization of taking a prefix from a sequence. It states that taking a prefix of length one greater than a given natural number, where that number is a valid index, is equivalent to appending the element at that index to the prefix of that number's length.*)\nLemma take_nth n s : n < size s -> take n.+1 s = rcons (take n s) (nth s n).\n\n(*This definition describes the rotation of a sequence by a given number of positions, which is achieved by moving the prefix of that length to the end of the sequence.*)\nDefinition rot n s := drop n s ++ take n s.\n\n(*This lemma states that rotating a sequence by zero positions results in the original sequence.*)\nLemma rot0 s : rot 0 s = s.\n\n(*This lemma states that the length of a sequence remains unchanged after it has been rotated.*)\nLemma size_rot s : size (rot n0 s) = size s.\n\n(*This lemma states that rotating a sequence by a number of positions that is greater than or equal to its length results in the original sequence.*)\nLemma rot_oversize n s : size s <= n -> rot n s = s.\n\n(*This lemma states that rotating a finite sequence by a number of positions equal to its own length results in the original sequence.*)\nLemma rot_size s : rot (size s) s = s.\n\n(*This lemma states that checking for the presence of an element in a finite sequence yields the same boolean result whether the check is performed on the original sequence or on any rotated version of that sequence.*)\nLemma has_rot s a : has a (rot n0 s) = has a s.\n\n(*This lemma states that if two finite sequences are concatenated, and the resulting sequence is rotated to the left by a number of positions equal to the length of the first sequence, the result is the same as concatenating the second sequence with the first.*)\nLemma rot_size_cat s1 s2 : rot (size s1) (s1 ++ s2) = s2 ++ s1.\n\n(*This definition specifies the right rotation of a finite sequence by a given number of positions. It is defined as a left rotation by the difference between the sequence's length and the given number of positions.*)\nDefinition rotr n s := rot (size s - n) s.\n\n(*This lemma states that the left rotation operation cancels the right rotation operation. Applying a left rotation of a given number of positions to a finite sequence that has already been right-rotated by the same number of positions will restore the original sequence.*)\nLemma rotK : cancel (rot n0) (rotr n0).\n\n(*This lemma states that the function which rotates a finite sequence by a fixed number of positions is injective, meaning that two distinct sequences will always result in two distinct rotated sequences.*)\nLemma rot_inj : injective (rot n0). \n\n(*This definition provides a tail-recursive function that reverses a first finite sequence and prepends it to a second finite sequence.*)\nFixpoint catrev s1 s2 := if s1 is x :: s1' then catrev s1' (x :: s2) else s2.\n\n(*This definition specifies the operation for reversing a finite sequence, implemented by applying a tail-recursive reversal-concatenation function to the input sequence and an empty sequence.*)\nDefinition rev s := catrev s [::].\n\n(*This lemma states that reversing and prepending the concatenation of two finite sequences to a third sequence is equivalent to first reversing and prepending the first sequence to the third, and then reversing and prepending the second sequence to the result.*)\nLemma catrev_catl s t u : catrev (s ++ t) u = catrev t (catrev s u).\n\n(*This lemma states that combining a reversed first finite sequence with the concatenation of a second and third sequence is equivalent to first combining the reversed first sequence with the second, and then concatenating the result with the third sequence.*)\nLemma catrev_catr s t u : catrev s (t ++ u) = catrev s t ++ u.\n\n(*This lemma states that the operation of reversing a first finite sequence and prepending it to a second is equivalent to first reversing the first sequence and then concatenating the result with the second sequence.*)\nLemma catrevE s t : catrev s t = rev s ++ t.\n\n(*This lemma states that reversing a finite sequence constructed by prepending an element is equivalent to first reversing the original tail of the sequence and then appending that element to the end of the result.*)\nLemma rev_cons x s : rev (x :: s) = rcons (rev s) x.\n\n(*This lemma states that the length of a finite sequence remains the same after it has been reversed.*)\nLemma size_rev s : size (rev s) = size s.\n\n(*This lemma states that a finite sequence is empty if and only if its reversed version is also empty.*)\nLemma rev_nilp s : nilp (rev s) = nilp s.\n\n(*This lemma states that reversing the concatenation of two finite sequences is equivalent to concatenating the reversed second sequence with the reversed first sequence.*)\nLemma rev_cat s t : rev (s ++ t) = rev t ++ rev s.\n\n(*This lemma states that reversing a finite sequence constructed by appending an element is equivalent to first reversing the original head of the sequence and then prepending that element to the front of the result.*)\nLemma rev_rcons s x : rev (rcons s x) = x :: rev s.\n\n(*This lemma states that the sequence reversal operation is an involution, meaning that applying the reversal operation twice to any finite sequence restores the original sequence.*)\nLemma revK : involutive rev.\n\n(*This lemma states that for any valid index, the element at that index in a reversed finite sequence is the same as the element in the original sequence at the index calculated by subtracting the given index plus one from the total length of the sequence.*)\nLemma nth_rev n s : n < size s -> nth (rev s) n = nth s (size s - n.+1).\n\n(*This lemma states that filtering the elements of a reversed finite sequence based on a given predicate yields the same result as first filtering the original sequence with that predicate and then reversing the resulting sequence.*)\nLemma filter_rev a s : filter a (rev s) = rev (filter a s).\n\n(*This lemma states that the number of elements in a finite sequence that satisfy a given predicate is the same for both the original sequence and its reversed version.*)\nLemma count_rev a s : count a (rev s) = count a s.\n\n(*This lemma states that checking for the presence of a given element in a finite sequence yields the same boolean result whether the check is performed on the original sequence or on its reversed version.*)\nLemma has_rev a s : has a (rev s) = has a s.\n\n(*This lemma states that a predicate holds for all elements of a finite sequence if and only if it also holds for all elements of the reversed sequence.*)\nLemma all_rev a s : all a (rev s) = all a s.\n\n(*This lemma states that reversing a finite sequence composed of multiple copies of the same element results in the original sequence.*)\nLemma rev_nseq n x : rev (nseq n x) = nseq n x.\n\nEnd Sequences.\n\nPrenex Implicits size ncons nseq head ohead behead last rcons belast.\nArguments seqn {T} n.\nPrenex Implicits cat take drop rot rotr catrev.\nPrenex Implicits find count nth all has filter.\nArguments rev {T} s : simpl never.\nArguments nth : simpl nomatch.\nArguments set_nth : simpl nomatch.\nArguments take : simpl nomatch.\nArguments drop : simpl nomatch.\n\nArguments nilP {T s}.\nArguments all_filterP {T a s}.\nArguments rotK n0 {T} s : rename.\nArguments rot_inj {n0 T} [s1 s2] eq_rot_s12 : rename.\nArguments revK {T} s : rename.\n\nNotation count_mem x := (count (pred_of_simpl (pred1 x))).\n\nInfix \"++\" := cat : seq_scope.\n\n(*This notation provides a sequence comprehension syntax for creating a new finite sequence by filtering an existing one. It includes all elements from the original sequence for which a given boolean condition is satisfied.*)\nNotation \"[ 'seq' x <- s | C ]\" := (filter (fun x => C%B) s)\n (x at level 99,\n format \"[ '[hv' 'seq' x <- s '/ ' | C ] ']'\") : seq_scope.\n(*This notation provides a sequence comprehension syntax for creating a new finite sequence by filtering an existing one based on the conjunction of two boolean conditions.*)\nNotation \"[ 'seq' x <- s | C1 & C2 ]\" := [seq x <- s | C1 && C2]\n (format \"[ '[hv' 'seq' x <- s '/ ' | C1 '/ ' & C2 ] ']'\") : seq_scope.\n(*This notation provides a sequence comprehension syntax that uses a strict pattern for the element variable. It creates a new finite sequence by filtering an existing one, including all elements for which a given boolean condition is satisfied.*)\nNotation \"[ 'seq' ' x <- s | C ]\" := (filter (fun x => C%B) s)\n (x strict pattern,\n format \"[ '[hv' 'seq' ' x <- s '/ ' | C ] ']'\") : seq_scope.\n(*This notation provides a sequence comprehension syntax that uses a strict pattern for the element variable. It creates a new finite sequence by filtering an existing one based on the conjunction of two boolean conditions.*)\nNotation \"[ 'seq' ' x <- s | C1 & C2 ]\" := [seq x <- s | C1 && C2]\n (x strict pattern,\n format \"[ '[hv' 'seq' ' x <- s '/ ' | C1 '/ ' & C2 ] ']'\") : seq_scope.\n(*This notation provides a parsing-only sequence comprehension syntax that allows specifying the type of the element variable. It creates a new finite sequence by filtering an existing one based on a given boolean condition.*)\nNotation \"[ 'seq' x : T <- s | C ]\" := (filter (fun x : T => C%B) s)\n (only parsing).\n(*This notation provides a parsing-only sequence comprehension syntax that allows specifying the type of the element variable. It creates a new finite sequence by filtering an existing one based on the conjunction of two boolean conditions.*)\nNotation \"[ 'seq' x : T <- s | C1 & C2 ]\" := [seq x : T <- s | C1 && C2]\n (only parsing).\n\n(*This lemma provides a principle of simultaneous induction over two finite sequences. It can be used to prove a property that holds for a pair of sequences by handling cases for when both are empty, when one is empty and the other is not, and when both are non-empty.*)\nLemma seq_ind2 {S T} (P : seq S -> seq T -> Type) :\n P [::] [::] ->\n (forall x y s t, size s = size t -> P s t -> P (x :: s) (y :: t)) ->\n forall s t, size s = size t -> P s t.\n\nSection AllIff.\n\n(*This inductive type defines a proposition that holds if and only if two given propositions both hold. It serves as a building block for chains of logical equivalences.*)\nInductive all_iff_and (P Q : Prop) : Prop := AllIffConj of P & Q.\n\n(*This definition constructs a single proposition which asserts that a given initial proposition and all propositions in a given sequence are mutually equivalent. This is achieved by creating a cycle of implications where each proposition implies the next, and the last proposition implies the first.*)\nDefinition all_iff (P0 : Prop) (Ps : seq Prop) : Prop :=\n let fix loop (P : Prop) (Qs : seq Prop) : Prop :=\n if Qs is Q :: Qs then all_iff_and (P -> Q) (loop Q Qs) else P -> P0 in\n loop P0 Ps.\n\n(*This lemma states that if a collection of propositions are mutually equivalent as defined by 'all_iff', then any proposition in the collection implies any other proposition in the same collection.*)\nLemma all_iffLR P0 Ps : all_iff P0 Ps ->\n forall m n, nth P0 (P0 :: Ps) m -> nth P0 (P0 :: Ps) n.\n\n(*This lemma states that if a collection of propositions are mutually equivalent as defined by 'all_iff', then any two propositions in that collection are logically equivalent to each other.*)\nLemma all_iffP P0 Ps :\n all_iff P0 Ps -> forall m n, nth P0 (P0 :: Ps) m <-> nth P0 (P0 :: Ps) n.\n\nEnd AllIff.\nArguments all_iffLR {P0 Ps}.\nArguments all_iffP {P0 Ps}.\nCoercion all_iffP : all_iff >-> Funclass.\n\n(*This notation provides a convenient syntax for asserting that a list of propositions are all mutually equivalent. It expands to the 'all_iff' definition, which creates a cycle of implications among the propositions.*)\nNotation \"[ '<->' P0 ; P1 ; .. ; Pn ]\" :=\n (all_iff P0 (@cons Prop P1 (.. (@cons Prop Pn nil) ..))) : form_scope.\n\n(*This tactic is used to solve goals that assert a conjunction of two propositions, a structure that commonly appears in proofs about chains of logical equivalences. It operates by breaking the conjunctive goal into two separate subgoals.*)\nLtac tfae := do !apply: AllIffConj.\n\nSection FindSpec.\nVariable (T : Type) (a : {pred T}) (s : seq T).\n\n(*This inductive proposition specifies the correct outcome of a search for the first element that satisfies a given predicate within a finite sequence.*)\nVariant find_spec : bool -> nat -> Type :=\n(*A constructor for an inductive specification of a search operation, representing the outcome where no element in the sequence satisfies the given predicate.*)\n| NotFound of ~~ has a s : find_spec false (size s)\n(**)\n| Found (i : nat) of i < size s & (forall x0, a (nth x0 s i)) &\n (forall x0 j, j < i -> a (nth x0 s j) = false) : find_spec true i.\n\n(*This lemma provides the correctness specification for the 'find' function. It asserts that the result of searching for an element satisfying a given predicate in a sequence corresponds to one of two cases: either no such element is found, or an element is found at a specific index, with the guarantee that it is the first such occurrence.*)\nLemma findP : find_spec (has a s) (find a s).\n\nEnd FindSpec.\nArguments findP {T}.\n\nSection RotRcons.\n\nVariable T : Type.\nImplicit Types (x : T) (s : seq T).\n\n(*This lemma states that rotating a non-empty sequence one position to the left is equivalent to moving its first element to the end of the sequence.*)\nLemma rot1_cons x s : rot 1 (x :: s) = rcons s x.\n\n(*This lemma establishes the injectivity of the 'rcons' operation, which appends an element to the end of a sequence. It states that if two sequences created by 'rcons' are equal, then their original sequences and the appended elements must also be respectively equal.*)\nLemma rcons_inj s1 s2 x1 x2 :\n rcons s1 x1 = rcons s2 x2 :> seq T -> (s1, x1) = (s2, x2).\n\n(*This lemma states that for a fixed element, the function that appends this element to the end of a sequence is injective. In other words, if appending the same element to two different sequences results in the same final sequence, then the two original sequences must have been identical.*)\nLemma rcons_injl x : injective (rcons^~ x).\n\n(*This lemma states that for a fixed sequence, the function that appends an element to its end is injective. This means that if appending two different elements to the same sequence results in the same final sequence, then the two elements must have been identical.*)\nLemma rcons_injr s : injective (rcons s).\n\nEnd RotRcons.\n\nArguments rcons_inj {T s1 x1 s2 x2} eq_rcons : rename.\nArguments rcons_injl {T} x [s1 s2] eq_rcons : rename.\nArguments rcons_injr {T} s [x1 x2] eq_rcons : rename.\n\nSection EqSeq.\n\nVariables (n0 : nat) (T : eqType) (x0 : T).\n(*This local notation defines a shorthand for accessing an element of a sequence by its index, using a pre-determined default value for out-of-bounds access.*)\nLocal Notation nth := (nth x0).\nImplicit Types (x y z : T) (s : seq T).\n\n(*This function recursively checks if two sequences are equal by comparing their elements pointwise. It returns true if both sequences have the same length and their corresponding elements are equal, and false otherwise.*)\nFixpoint eqseq s1 s2 {struct s2} :=\n match s1, s2 with\n | [::], [::] => true\n | x1 :: s1', x2 :: s2' => (x1 == x2) && eqseq s1' s2'\n | _, _ => false\n end.\n\n(*This lemma states that the 'eqseq' function, which performs pointwise comparison of sequences, defines a proper equality relation. This means it is reflexive, symmetric, and transitive.*)\nLemma eqseqP : Equality.axiom eqseq.\n\n(*This lemma states that the 'eqseq' function is equivalent to the canonical equality operator for its type. This allows for the use of the generic equality notation when comparing two sequences.*)\nLemma eqseqE : eqseq = eq_op. \n\n(*This lemma states that two non-empty sequences are equal if and only if both their first elements are equal and their remaining subsequences are equal.*)\nLemma eqseq_cons x1 x2 s1 s2 :\n (x1 :: s1 == x2 :: s2) = (x1 == x2) && (s1 == s2).\n\n(*This lemma states that for two pairs of concatenated sequences, where the first sequence in each pair has the same size, the concatenated results are equal if and only if the corresponding component sequences are pairwise equal.*)\nLemma eqseq_cat s1 s2 s3 s4 :\n size s1 = size s2 -> (s1 ++ s3 == s2 ++ s4) = (s1 == s2) && (s3 == s4).\n\n(*This lemma states that two sequences constructed by appending a final element are equal if and only if the initial sequences are equal and the appended elements are equal.*)\nLemma eqseq_rcons s1 s2 x1 x2 :\n (rcons s1 x1 == rcons s2 x2) = (s1 == s2) && (x1 == x2).\n\n(*This lemma states that a sequence has a size of zero if and only if it is the empty sequence.*)\nLemma size_eq0 s : (size s == 0) = (s == [::]).\n\n(*This lemma states that the predicate for checking if a sequence is empty is equivalent to comparing the sequence for equality with the empty sequence.*)\nLemma nilpE s : nilp s = (s == [::]). \n\n(*This lemma states that checking if a sequence contains an element satisfying a given predicate is equivalent to checking if filtering the sequence by that predicate results in a non-empty sequence.*)\nLemma has_filter a s : has a s = (filter a s != [::]).\n\n(*This function converts a sequence into a predicate that is satisfied by any element present in the sequence. It effectively represents the set of elements contained within the sequence.*)\nFixpoint mem_seq (s : seq T) :=\n if s is y :: s' then xpredU1 y (mem_seq s') else xpred0.\n\n(*This definition provides an alias for the sequence type, intended for use when viewing a sequence as a collection of elements, akin to a multiset, to support set-theoretic operations and predicates.*)\nDefinition seq_eqclass := seq T.\nIdentity Coercion seq_of_eqclass : seq_eqclass >-> seq.\nCoercion pred_of_seq (s : seq_eqclass) : {pred T} := mem_seq s.\n\nCanonical seq_predType := PredType (pred_of_seq : seq T -> pred T).\n\nCanonical mem_seq_predType := PredType mem_seq.\n\n(*This lemma states that an element belongs to a non-empty sequence if and only if it is equal to the first element of the sequence or it belongs to the rest of the sequence.*)\nLemma in_cons y s x : (x \\in y :: s) = (x == y) || (x \\in s).\n\n(*This lemma states that the check for membership of any element in an empty sequence always evaluates to false.*)\nLemma in_nil x : (x \\in [::]) = false.\n\n(*This lemma states that an element belongs to a sequence containing a single element if and only if it is equal to that single element.*)\nLemma mem_seq1 x y : (x \\in [:: y]) = (x == y).\n\n \n(*This definition provides a collection of elimination rules for reasoning about element membership in a sequence, packaging lemmas for singleton sequences and non-empty sequences for use by automated tactics.*)\nLet inE := (mem_seq1, in_cons, inE).\n\n(*This lemma states that a property holds for all elements of a non-empty sequence if and only if the property holds for the first element and also holds for all elements in the rest of the sequence.*)\nLemma forall_cons {P : T -> Prop} {a s} :\n {in a::s, forall x, P x} <-> P a /\\ {in s, forall x, P x}.\n\n(*This lemma states that there exists an element satisfying a given property within a non-empty sequence if and only if the first element satisfies the property or an element satisfying the property exists in the rest of the sequence.*)\nLemma exists_cons {P : T -> Prop} {a s} :\n (exists2 x, x \\in a::s & P x) <-> P a \\/ exists2 x, x \\in s & P x.\n\n(*This lemma states that an element is a member of a two-element sequence if and only if it is equal to either the first or the second element of that sequence.*)\nLemma mem_seq2 x y z : (x \\in [:: y; z]) = xpred2 y z x.\n\n(*This lemma states that an element is a member of a three-element sequence if and only if that element is equal to one of the three elements in the sequence.*)\nLemma mem_seq3 x y z t : (x \\in [:: y; z; t]) = xpred3 y z t x.\n\n(*This lemma states that an element is a member of a four-element sequence if and only if that element is equal to one of the four elements in the sequence.*)\nLemma mem_seq4 x y z t u : (x \\in [:: y; z; t; u]) = xpred4 y z t u x.\n\n(*This lemma states that an element is a member of the concatenation of two sequences if and only if it is a member of the first sequence or a member of the second sequence.*)\nLemma mem_cat x s1 s2 : (x \\in s1 ++ s2) = (x \\in s1) || (x \\in s2).\n\n(*This lemma states that a sequence formed by appending an element to the end of another sequence contains the same multiset of elements as the sequence formed by prepending that same element to the original sequence.*)\nLemma mem_rcons s y : rcons s y =i y :: s.\n\n(*This lemma states that the head element of a non-empty sequence is a member of that sequence.*)\nLemma mem_head x s : x \\in x :: s.\n\n(*This lemma states that the last element of a non-empty sequence is a member of that sequence.*)\nLemma mem_last x s : last x s \\in x :: s.\n\n(*This lemma states that the sequence resulting from removing the first element of a given sequence is a subset of the original sequence.*)\nLemma mem_behead s : {subset behead s <= s}.\n\n(*This lemma asserts that the set of elements from a given sequence, excluding its last element, is a subset of the set of elements in the sequence formed by prepending an arbitrary element to the original sequence.*)\nLemma mem_belast s y : {subset belast y s <= y :: s}.\n\n(*This lemma states that if a given natural number is a valid index for a sequence, meaning it is less than its size, then the element at that index is a member of the sequence.*)\nLemma mem_nth s n : n < size s -> nth s n \\in s.\n\n(*This lemma states that if an element is a member of a prefix of a sequence, then it is also a member of the original sequence.*)\nLemma mem_take s x : x \\in take n0 s -> x \\in s.\n\n(*This lemma states that if an element is a member of a suffix of a sequence, obtained by dropping a prefix, then it is also a member of the original sequence.*)\nLemma mem_drop s x : x \\in drop n0 s -> x \\in s.\n\n(*This lemma states that for a given sequence, the boolean result of comparing its last element with a given value is independent of the default value used for the last element operation, provided that both the original and the new default values are not equal to the comparison value.*)\nLemma last_eq s z x y : x != y -> z != y -> (last x s == y) = (last z s == y).\n\nSection Filters.\n\nImplicit Type a : pred T.\n\n(*This lemma provides a reflective equivalence, stating that the boolean result of checking if any element in a sequence satisfies a given predicate corresponds to the proposition that such an element exists in the sequence.*)\nLemma hasP {a s} : reflect (exists2 x, x \\in s & a x) (has a s).\n\n(*This lemma provides a reflective equivalence, stating that the boolean result of checking if all elements in a sequence satisfy a given predicate corresponds to the proposition that every element in the sequence indeed satisfies that predicate.*)\nLemma allP {a s} : reflect {in s, forall x, a x} (all a s).\n\n(*This lemma states that a boolean predicate being false for all elements of a sequence is propositionally equivalent to the boolean statement that there is no element in the sequence for which the predicate is true.*)\nLemma hasPn a s : reflect {in s, forall x, ~~ a x} (~~ has a s).\n\n(*This lemma states that the existence of an element in a sequence for which a given boolean predicate is false is propositionally equivalent to the boolean statement that not all elements in the sequence satisfy the predicate.*)\nLemma allPn a s : reflect (exists2 x, x \\in s & ~~ a x) (~~ all a s).\n\n(*This lemma states that for any given sequence, the predicate representing membership in that same sequence holds for all elements of that sequence.*)\nLemma allss s : all [in s] s. \n\n(*This lemma states that an element is a member of a sequence filtered by a predicate if and only if the element satisfies the predicate and is a member of the original sequence.*)\nLemma mem_filter a x s : (x \\in filter a s) = a x && (x \\in s).\n\nVariables (a : pred T) (s : seq T) (A : T -> Prop).\nHypothesis aP : forall x, reflect (A x) (a x).\n\n(*This lemma states that, given a boolean predicate that reflects a proposition, the boolean check for the existence of an element in a sequence satisfying the predicate is reflectively equivalent to the proposition that there exists an element in the sequence for which the proposition holds.*)\nLemma hasPP : reflect (exists2 x, x \\in s & A x) (has a s).\n\n(*This lemma states that, given a boolean predicate that reflects a proposition, the boolean check that all elements in a sequence satisfy the predicate is reflectively equivalent to the proposition that the proposition holds for all elements of the sequence.*)\nLemma allPP : reflect {in s, forall x, A x} (all a s).\n\nEnd Filters.\n\nSection EqIn.\n\nVariables a1 a2 : pred T.\n\n(*This lemma states that if two predicates are equivalent for all elements within a given sequence, then filtering the sequence with either predicate produces the exact same resulting sequence.*)\nLemma eq_in_filter s : {in s, a1 =1 a2} -> filter a1 s = filter a2 s.\n\n(*This lemma states that if two predicates are equivalent for all elements within a given sequence, then finding the first element in the sequence that satisfies the predicate will yield the same result for both predicates.*)\nLemma eq_in_find s : {in s, a1 =1 a2} -> find a1 s = find a2 s.\n\n(*This lemma states that if two predicates are equivalent for all elements within a given sequence, then counting the number of elements in the sequence that satisfy the predicate will yield the same count for both predicates.*)\nLemma eq_in_count s : {in s, a1 =1 a2} -> count a1 s = count a2 s.\n\n(*This lemma states that if two predicates are equivalent for all elements within a given sequence, then checking if all elements of the sequence satisfy the predicate will produce the same boolean result for both predicates.*)\nLemma eq_in_all s : {in s, a1 =1 a2} -> all a1 s = all a2 s.\n\n(*This lemma states that if two predicates are equivalent for all elements within a given sequence, then checking if there exists an element in the sequence that satisfies the predicate will produce the same boolean result for both predicates.*)\nLemma eq_in_has s : {in s, a1 =1 a2} -> has a1 s = has a2 s.\n\nEnd EqIn.\n\n(*This lemma states that if two sequences are equivalent as multisets, then the higher-order functions that check for the existence of an element satisfying a given predicate are pointwise equal for both sequences.*)\nLemma eq_has_r s1 s2 : s1 =i s2 -> has^~ s1 =1 has^~ s2.\n\n(*This lemma states that if two sequences are equivalent as multisets, then the higher-order functions that check if all elements satisfy a given predicate are pointwise equal for both sequences.*)\nLemma eq_all_r s1 s2 : s1 =i s2 -> all^~ s1 =1 all^~ s2.\n\n(*This lemma states that checking for the existence of a common element between two sequences is a symmetric operation; that is, checking if any element of the first sequence is in the second gives the same boolean result as checking if any element of the second sequence is in the first.*)\nLemma has_sym s1 s2 : has [in s1] s2 = has [in s2] s1.\n\n(*This lemma states that checking if a sequence contains an element satisfying the predicate of being equal to a specific value is equivalent to checking for the membership of that value in the sequence.*)\nLemma has_pred1 x s : has (pred1 x) s = (x \\in s).\n\n(*This lemma states that a reversed sequence is equivalent to the original sequence as a multiset, meaning they both contain the exact same elements with the same frequencies.*)\nLemma mem_rev s : rev s =i s.\n\n(*This definition checks whether all elements in a given finite sequence are identical. It returns true if the sequence is empty or if all of its elements are equal to each other, and false otherwise.*)\nDefinition constant s := if s is x :: s' then all (pred1 x) s' else true.\n\n(*This lemma states that the property of all elements in a finite sequence being equal to a given value is logically equivalent to the sequence being equal to a new sequence of the same length, composed solely of that given value.*)\nLemma all_pred1P x s : reflect (s = nseq (size s) x) (all (pred1 x) s).\n\n(*This lemma states that if all elements in a finite sequence are equal to a given value, then the sequence is considered constant, meaning all its elements are identical.*)\nLemma all_pred1_constant x s : all (pred1 x) s -> constant s.\n\n(*This lemma states that for any given value and any natural number length, a sequence constructed by repeating that value for the specified length will satisfy the property that all its elements are equal to that value.*)\nLemma all_pred1_nseq x n : all (pred1 x) (nseq n x).\n\n(*This lemma states that an element is a member of a sequence created by repeating a specific value a certain number of times if and only if the sequence is not empty and the element is equal to that specific value.*)\nLemma mem_nseq n x y : (y \\in nseq n x) = (0 < n) && (y == x).\n\n(*This lemma provides a logical equivalence, stating that an element is a member of a sequence constructed by repeating a given value a certain number of times if and only if the element is equal to the given value and the number of repetitions is greater than zero.*)\nLemma nseqP n x y : reflect (y = x /\\ n > 0) (y \\in nseq n x).\n\n(*This lemma states that any sequence created by repeating a specific value a given number of times is a constant sequence, meaning all its elements are identical.*)\nLemma constant_nseq n x : constant (nseq n x).\n\n(*This lemma provides a logical equivalence, stating that a finite sequence is constant if and only if there exists some value such that the sequence is identical to a new sequence of the same length composed entirely of that value.*)\nLemma constantP s : reflect (exists x, s = nseq (size s) x) (constant s).\n\n(*This definition checks whether a finite sequence contains any duplicate elements. It returns true if all elements in the sequence are distinct, and false otherwise.*)\nFixpoint uniq s := if s is x :: s' then (x \\notin s') && uniq s' else true.\n\n(*This lemma states that a new sequence formed by prepending an element to an existing sequence has unique elements if and only if the original sequence has unique elements and the new element is not present in the original sequence.*)\nLemma cons_uniq x s : uniq (x :: s) = (x \\notin s) && uniq s.\n\n(*This lemma states that the concatenation of two finite sequences has unique elements if and only if each of the original sequences has unique elements and no element from the second sequence is present in the first sequence.*)\nLemma cat_uniq s1 s2 :\n uniq (s1 ++ s2) = [&& uniq s1, ~~ has [in s1] s2 & uniq s2].\n\n(*This lemma states that the property of having unique elements is commutative for sequence concatenation; the concatenation of a first and second sequence has unique elements if and only if the concatenation of the second and first sequence has unique elements.*)\nLemma uniq_catC s1 s2 : uniq (s1 ++ s2) = uniq (s2 ++ s1).\n\n(*This lemma states that for three finite sequences, the property of uniqueness is preserved when the first two sequences are swapped before concatenating with the third. Specifically, the concatenation of the first, second, and third sequences has unique elements if and only if the concatenation of the second, first, and third has unique elements.*)\nLemma uniq_catCA s1 s2 s3 : uniq (s1 ++ s2 ++ s3) = uniq (s2 ++ s1 ++ s3).\n\n(*This lemma states that a new sequence formed by appending an element to the end of an existing sequence has unique elements if and only if the original sequence has unique elements and the new element is not present in the original sequence.*)\nLemma rcons_uniq s x : uniq (rcons s x) = (x \\notin s) && uniq s.\n\n(*This lemma states that if a finite sequence contains no duplicate elements, then any new sequence created by filtering the original one based on a predicate will also contain no duplicate elements.*)\nLemma filter_uniq s a : uniq s -> uniq (filter a s).\n\n(*This lemma states that rotating a finite sequence by any number of positions preserves its property of having unique elements. The rotated sequence has unique elements if and only if the original sequence does.*)\nLemma rot_uniq s : uniq (rot n0 s) = uniq s.\n\n(*This lemma states that reversing a finite sequence preserves its property of having unique elements. The reversed sequence has unique elements if and only if the original sequence does.*)\nLemma rev_uniq s : uniq (rev s) = uniq s.\n\n(*This lemma provides a logical equivalence, stating that the count of a given element in a finite sequence is zero if and only if that element is not a member of the sequence.*)\nLemma count_memPn x s : reflect (count_mem x s = 0) (x \\notin s).\n\n(*This lemma states that for a finite sequence with unique elements, the number of occurrences of a given element is one if the element is present in the sequence, and zero if it is not.*)\nLemma count_uniq_mem s x : uniq s -> count_mem x s = (x \\in s).\n\n(*This lemma states that for a finite sequence with unique elements and a second finite sequence, the implication that an element's presence in the first sequence requires its presence in the second is logically equivalent to the count of that element in the first sequence being less than or equal to its count in the second sequence.*)\nLemma leq_uniq_countP x s1 s2 : uniq s1 ->\n reflect (x \\in s1 -> x \\in s2) (count_mem x s1 <= count_mem x s2).\n\n(*This lemma states that if a first finite sequence has unique elements and is a subset of a second finite sequence, then for every element, its count in the first sequence is less than or equal to its count in the second sequence.*)\nLemma leq_uniq_count s1 s2 : uniq s1 -> {subset s1 <= s2} ->\n (forall x, count_mem x s1 <= count_mem x s2).\n\n(*This lemma states that if a finite sequence has unique elements and contains a specific element, filtering that sequence to keep only instances of that specific element results in a singleton sequence containing just that element.*)\nLemma filter_pred1_uniq s x : uniq s -> x \\in s -> filter (pred1 x) s = [:: x].\n\n(*This definition removes duplicate elements from a finite sequence, producing a new sequence where each element from the original sequence appears exactly once, preserving the order of first appearances.*)\nFixpoint undup s :=\n if s is x :: s' then if x \\in s' then undup s' else x :: undup s' else [::].\n\n(*This lemma states that the length of a sequence after removing duplicate elements is less than or equal to the length of the original sequence.*)\nLemma size_undup s : size (undup s) <= size s.\n\n(*This lemma states that the sequence resulting from removing duplicates from an original finite sequence contains the exact same set of elements as the original sequence.*)\nLemma mem_undup s : undup s =i s.\n\n(*This lemma states that applying the duplicate removal operation to any finite sequence results in a new sequence that has no duplicate elements.*)\nLemma undup_uniq s : uniq (undup s).\n\n(*This lemma states that if a finite sequence already has unique elements, applying the duplicate removal operation to it will return the original sequence unchanged.*)\nLemma undup_id s : uniq s -> undup s = s.\n\n(*This lemma states that the length of a sequence after removing duplicates is strictly less than its original length if and only if the original sequence contained at least one duplicate element.*)\nLemma ltn_size_undup s : (size (undup s) < size s) = ~~ uniq s.\n\n(*This lemma states that filtering a sequence after removing its duplicates is equivalent to removing duplicates from the sequence after it has been filtered.*)\nLemma filter_undup p s : filter p (undup s) = undup (filter p s).\n\n(*This lemma states that if removing duplicates from a finite sequence results in an empty sequence, then the original sequence must also have been empty.*)\nLemma undup_nil s : undup s = [::] -> s = [::].\n\n(*This lemma states that removing duplicate elements from the concatenation of two finite sequences is equivalent to first filtering the unique elements of the first sequence to keep only those not present in the second sequence, and then concatenating this result with the unique elements of the second sequence.*)\nLemma undup_cat s t :\n undup (s ++ t) = [seq x <- undup s | x \\notin t] ++ undup t.\n\n(*This lemma states that removing duplicate elements from a finite sequence that has a new element appended to its end is equivalent to first removing all occurrences of that new element from the unique elements of the original sequence, and then appending the new element to the result.*)\nLemma undup_rcons s x : undup (rcons s x) = rcons [seq y <- undup s | y != x] x.\n\n(*This lemma states that the number of elements in a finite sequence satisfying a given boolean predicate after duplicate elements have been removed is less than or equal to the count of such elements in the original sequence.*)\nLemma count_undup s p : count p (undup s) <= count p s.\n\n(*This lemma states that checking if at least one element in a finite sequence satisfies a given boolean predicate yields the same result whether it is checked on the original sequence or on the sequence with duplicate elements removed.*)\nLemma has_undup p s : has p (undup s) = has p s.\n\n(*This lemma states that checking if all elements in a finite sequence satisfy a given boolean predicate yields the same result whether it is checked on the original sequence or on the sequence with duplicate elements removed.*)\nLemma all_undup p s : all p (undup s) = all p s.\n\n(*This definition specifies a function that, for a given element, returns the zero-based position of its first occurrence in a finite sequence.*)\nDefinition index x := find (pred1 x).\n\n(*This lemma states that the position of the first occurrence of an element in a finite sequence is always a natural number less than or equal to the length of the sequence.*)\nLemma index_size x s : index x s <= size s.\n\n(*This lemma states that an element is a member of a finite sequence if and only if the position of its first occurrence is strictly less than the length of the sequence.*)\nLemma index_mem x s : (index x s < size s) = (x \\in s).\n\n(*This lemma states that if an element is not a member of a finite sequence, then the function for finding its position will return the length of the sequence.*)\nLemma memNindex x s : x \\notin s -> index x s = size s.\n\n(*This lemma states that if an element is present in a finite sequence, retrieving the element at the position of its first occurrence returns the element itself.*)\nLemma nth_index x s : x \\in s -> nth s (index x s) = x.\n\n(*This lemma states that for any given finite sequence, the function that maps each element present in the sequence to the position of its first occurrence is injective.*)\nLemma index_inj s : {in s &, injective (index ^~ s)}.\n\n(*This lemma states that the position of an element's first occurrence in the concatenation of two finite sequences is its position in the first sequence if it is present there; otherwise, it is the length of the first sequence plus the element's position in the second sequence.*)\nLemma index_cat x s1 s2 :\n index x (s1 ++ s2) = if x \\in s1 then index x s1 else size s1 + index x s2.\n\n(*This lemma states that if an element is a member of a prefix of a given length taken from a finite sequence, then the position of its first occurrence in the original sequence is a natural number strictly less than that length.*)\nLemma index_ltn x s i : x \\in take i s -> index x s < i.\n\n(*This lemma states that for an element known to be in a finite sequence, its membership in a prefix of a given length is equivalent to its first occurrence position being strictly less than that length.*)\nLemma in_take x s i : x \\in s -> (x \\in take i s) = (index x s < i).\n\n(*This lemma states that, provided a given length is not greater than the length of a finite sequence, an element belongs to the prefix of that given length if and only if the position of its first occurrence in the whole sequence is strictly less than the given length.*)\nLemma in_take_leq x s i : i <= size s -> (x \\in take i s) = (index x s < i).\n\n(*This lemma states that for any valid position in a finite sequence, the first occurrence of the element at that position is at a position less than or equal to the given one.*)\nLemma index_nth i s : i < size s -> index (nth s i) s <= i.\n\n(*This lemma states that for a finite sequence with no duplicate elements, retrieving an element at a certain position and then finding the position of that element's first occurrence yields the original position.*)\nLemma nthK s: uniq s -> {in gtn (size s), cancel (nth s) (index^~ s)}.\n\n(*This lemma states that for a finite sequence with no duplicate elements, the first occurrence of the element at a specified valid position is at that exact position.*)\nLemma index_uniq i s : i < size s -> uniq s -> index (nth s i) s = i.\n\n(*This lemma states that the position of the first occurrence of an element in a finite sequence that begins with that same element is zero.*)\nLemma index_head x s : index x (x :: s) = 0.\n\n(*This lemma states that in a finite sequence with no duplicate elements formed by prepending an element to another sequence, the position of the last element of the resulting sequence is equal to the length of the original sequence.*)\nLemma index_last x s : uniq (x :: s) -> index (last x s) (x :: s) = size s.\n\n(*This lemma states that in a finite sequence with no duplicate elements, the elements at two distinct valid positions are themselves distinct, and elements at the same position are identical.*)\nLemma nth_uniq s i j :\n i < size s -> j < size s -> uniq s -> (nth s i == nth s j) = (i == j).\n\n(*This lemma provides a reflection property, stating that a finite sequence lacks unique elements if and only if there exist two different positions within the sequence, with the first being smaller than the second, that hold identical elements.*)\nLemma uniqPn s :\n reflect (exists i j, [/\\ i < j, j < size s & nth s i = nth s j]) (~~ uniq s).\n\n(*This lemma provides a reflection property, stating that a finite sequence has unique elements if and only if the function mapping a valid position to its corresponding element is injective.*)\nLemma uniqP s : reflect {in gtn (size s) &, injective (nth s)} (uniq s).\n\n(*This lemma states that cyclically rotating a finite sequence by a given number of positions results in a new sequence that contains the same multiset of elements as the original sequence.*)\nLemma mem_rot s : rot n0 s =i s.\n\n(*This lemma states that two finite sequences are identical if and only if the sequences resulting from cyclically rotating both by the same number of positions are also identical.*)\nLemma eqseq_rot s1 s2 : (rot n0 s1 == rot n0 s2) = (s1 == s2).\n\n(*This lemma states that if an element is present in a finite sequence, removing the prefix of the sequence up to the position of that element's first occurrence results in a new sequence that starts with that element.*)\nLemma drop_index s (n := index x0 s) : x0 \\in s -> drop n s = x0 :: drop n.+1 s.\n\n(*This lemma states that for a finite sequence constructed by concatenating a first sequence, a pivot element, and a second sequence, if the pivot element does not appear in the first sequence, then the position of the pivot's first occurrence in the combined sequence is equal to the length of the first sequence.*)\nLemma index_pivot x s1 s2 (s := s1 ++ x :: s2) : x \\notin s1 ->\n index x s = size s1.\n\n(*This lemma states that for a finite sequence constructed by concatenating a first sequence, a pivot element, and a second sequence, if the pivot element does not appear in the first sequence, then taking the prefix of the combined sequence up to the pivot's position results in the first sequence.*)\nLemma take_pivot x s2 s1 (s := s1 ++ x :: s2) : x \\notin s1 ->\n take (index x s) s = s1.\n\n(*This lemma states that reversing a finite sequence constructed by concatenating a first sequence, a pivot element, and a second sequence is equivalent to concatenating the reversed second sequence, the pivot element, and the reversed first sequence.*)\nLemma rev_pivot x s1 s2 : rev (s1 ++ x :: s2) = rev s2 ++ x :: rev s1.\n\n(*This lemma states that if two finite sequences are equal, where each is constructed by sandwiching a common pivot element between a prefix and a suffix, and the pivot does not appear in either prefix, then their respective prefixes must be equal and their respective suffixes must also be equal.*)\nLemma eqseq_pivot2l x s1 s2 s3 s4 : x \\notin s1 -> x \\notin s3 ->\n (s1 ++ x :: s2 == s3 ++ x :: s4) = (s1 == s3) && (s2 == s4).\n\n(*This lemma states that given two sequences formed by concatenating a first part, a pivot element, and a second part, their equality is equivalent to the pairwise equality of their corresponding parts, provided the pivot element does not appear in either of the second parts.*)\nLemma eqseq_pivot2r x s1 s2 s3 s4 : x \\notin s2 -> x \\notin s4 ->\n (s1 ++ x :: s2 == s3 ++ x :: s4) = (s1 == s3) && (s2 == s4).\n\n(*This lemma states that the equality of two sequences, each formed by concatenating a first part, a pivot element, and a second part, is equivalent to the pairwise equality of their corresponding first and second parts, provided the pivot element does not appear in either part of the first composite sequence.*)\nLemma eqseq_pivotl x s1 s2 s3 s4 : x \\notin s1 -> x \\notin s2 ->\n (s1 ++ x :: s2 == s3 ++ x :: s4) = (s1 == s3) && (s2 == s4).\n\n(*This lemma states that the equality of two sequences, each formed by concatenating a first part, a pivot element, and a second part, is equivalent to the pairwise equality of their corresponding first and second parts, provided the pivot element does not appear in either part of the second composite sequence.*)\nLemma eqseq_pivotr x s1 s2 s3 s4 : x \\notin s3 -> x \\notin s4 ->\n (s1 ++ x :: s2 == s3 ++ x :: s4) = (s1 == s3) && (s2 == s4).\n\n(*This lemma states that if a sequence constructed by concatenating a first part, a pivot element, and a second part contains no duplicate elements, then its equality with another similarly constructed sequence is equivalent to the pairwise equality of their respective first and second parts.*)\nLemma uniq_eqseq_pivotl x s1 s2 s3 s4 : uniq (s1 ++ x :: s2) ->\n (s1 ++ x :: s2 == s3 ++ x :: s4) = (s1 == s3) && (s2 == s4).\n\n(*This lemma states that if the second of two sequences, each constructed by concatenating a first part, a pivot element, and a second part, contains no duplicate elements, then the equality of the two composite sequences is equivalent to the pairwise equality of their respective first and second parts.*)\nLemma uniq_eqseq_pivotr x s1 s2 s3 s4 : uniq (s3 ++ x :: s4) ->\n (s1 ++ x :: s2 == s3 ++ x :: s4) = (s1 == s3) && (s2 == s4).\n\nEnd EqSeq.\nArguments eqseq : simpl nomatch.\n\n(*This notation provides a syntax to check if at least one element in a collection possesses a specific property, or 'view'.*)\nNotation \"'has_ view\" := (hasPP _ (fun _ => view))\n (at level 4, right associativity, format \"''has_' view\").\n(*This notation provides a syntax to check if all elements in a collection possess a specific property, or 'view'.*)\nNotation \"'all_ view\" := (allPP _ (fun _ => view))\n (at level 4, right associativity, format \"''all_' view\").\n\nSection RotIndex.\nVariables (T : eqType).\nImplicit Types x y z : T.\n\n(*This lemma states that if an element is present in a sequence, rotating the sequence by the index of that element brings the element to the front, followed by the part of the sequence originally after it, and then the part originally before it.*)\nLemma rot_index s x (i := index x s) : x \\in s ->\n rot i s = x :: (drop i.+1 s ++ take i s).\n\n(*This is a specification type that encapsulates a proof that a given sequence can be rotated by some index to produce a new sequence with a specific element at its head.*)\nVariant rot_to_spec s x := RotToSpec i s' of rot i s = x :: s'.\n\n(*This lemma proves that if an element is present in a sequence, then an instance of the rotation specification exists, demonstrating that the sequence can be rotated to place that element at the beginning.*)\nLemma rot_to s x : x \\in s -> rot_to_spec s x.\n\nEnd RotIndex.\n\n(*This definition bundles together the key elimination rules for reasoning about element membership in a sequence, including membership in a singleton sequence and in a sequence constructed with a head and a tail.*)\nDefinition inE := (mem_seq1, in_cons, inE).\n\nPrenex Implicits mem_seq1 constant uniq undup index.\n\nArguments eqseq {T} !_ !_.\nArguments pred_of_seq {T} s x /.\nArguments eqseqP {T x y}.\nArguments hasP {T a s}.\nArguments hasPn {T a s}.\nArguments allP {T a s}.\nArguments allPn {T a s}.\nArguments nseqP {T n x y}.\nArguments count_memPn {T x s}.\nArguments uniqPn {T} x0 {s}.\nArguments uniqP {T} x0 {s}.\nArguments forall_cons {T P a s}.\nArguments exists_cons {T P a s}.\n\n#[export] Hint Extern 0 (is_true (all _ _)) =>\n apply: (allss : forall T s, all (mem_seq s) s) : core.\n\nSection NthTheory.\n\n(*This lemma establishes a reflective equivalence between an element being a member of a sequence and the existence of an index within the sequence's bounds at which that element can be found.*)\nLemma nthP (T : eqType) (s : seq T) x x0 :\n reflect (exists2 i, i < size s & nth x0 s i = x) (x \\in s).\n\nVariable T : Type.\nImplicit Types (a : pred T) (x : T).\n\n(*This lemma establishes a reflective equivalence between a sequence having at least one element that satisfies a given predicate and the existence of an index within the sequence's bounds where the element at that position satisfies the predicate.*)\nLemma has_nthP a s x0 :\n reflect (exists2 i, i < size s & a (nth x0 s i)) (has a s).\n\n(*This lemma establishes a reflective equivalence between all elements of a sequence satisfying a given predicate and the fact that for every valid index, the element at that position satisfies the predicate.*)\nLemma all_nthP a s x0 :\n reflect (forall i, i < size s -> a (nth x0 s i)) (all a s).\n\n(*This lemma explains how updating a sequence at a given index works: if the index is within the sequence's bounds, the element at that index is replaced; otherwise, the sequence is padded with default values up to the specified index, and the new element is appended.*)\nLemma set_nthE s x0 n x :\n set_nth x0 s n x = if n < size s\n then take n s ++ x :: drop n.+1 s\n else s ++ ncons (n - size s) x0 [:: x].\n\n(*This lemma provides a formula for the number of elements satisfying a predicate in a sequence that has been updated at a specific index. The new count is calculated from the old count by adjusting for the new element, the old element if it was replaced, and any default elements added as padding.*)\nLemma count_set_nth a s x0 n x :\n count a (set_nth x0 s n x) =\n count a s + a x - a (nth x0 s n) * (n < size s) + (a x0) * (n - size s).\n\n(*This lemma provides a simplified formula for the number of elements satisfying a predicate in a sequence after an update, specifically for the case where the update index is within the sequence's original bounds. The new count is the old count plus one if the new element satisfies the predicate, minus one if the replaced element satisfied it.*)\nLemma count_set_nth_ltn a s x0 n x : n < size s ->\n count a (set_nth x0 s n x) = count a s + a x - a (nth x0 s n).\n\n(*This lemma provides a simplified formula for counting elements that satisfy a predicate in an updated sequence, under the condition that the default padding element does not satisfy the predicate. The new count is calculated by adjusting the original count based on whether the new element and the replaced element satisfy the predicate.*)\nLemma count_set_nthF a s x0 n x : ~~ a x0 ->\n count a (set_nth x0 s n x) = count a s + a x - a (nth x0 s n).\n\nEnd NthTheory.\n\n(*This lemma states that the element retrieved from a sequence at an index within its bounds is the same regardless of the default value supplied to the access function.*)\nLemma set_nth_default T s (y0 x0 : T) n : n < size s -> nth x0 s n = nth y0 s n.\n\n(*This lemma states that a sequence formed by appending an element to its end can be equivalently represented as that sequence's head prepended to its tail.*)\nLemma headI T s (x : T) : rcons s x = head x s :: behead (rcons s x).\n\nArguments nthP {T s x}.\nArguments has_nthP {T a s}.\nArguments all_nthP {T a s}.\n\n(*This definition introduces `bitseq` as an alias for a finite sequence of boolean values and equips it with default structures for equality and predicate evaluation.*)\nDefinition bitseq := seq bool.\n(*This is a specification type that certifies that a sequence can be decomposed around the first element satisfying a given predicate. It guarantees the existence of a prefix containing no elements that satisfy the predicate, the element itself which does, and the remaining suffix.*)\nVariant split_find_nth_spec p : seq T -> seq T -> seq T -> T -> Type :=\n FindNth x s1 s2 of p x & ~~ has p s1 :\n split_find_nth_spec p (rcons s1 x ++ s2) s1 s2 x.\n\n(*This lemma proves that if a sequence contains at least one element satisfying a given predicate, then the sequence can be formally split into a prefix, the first matching element, and a suffix, thereby satisfying the corresponding split specification.*)\nLemma split_find_nth x0 p s (i := find p s) :\n has p s -> split_find_nth_spec p s (take i s) (drop i.+1 s) (nth x0 s i).\n\n(*This is a specification type that certifies that a sequence can be partitioned into a prefix and a suffix around the first element that satisfies a given predicate, without explicitly identifying the element itself.*)\nVariant split_find_spec p : seq T -> seq T -> seq T -> Type :=\n FindSplit x s1 s2 of p x & ~~ has p s1 :\n split_find_spec p (rcons s1 x ++ s2) s1 s2.\n\n(*This lemma proves that if a sequence has at least one element satisfying a predicate, it can be split into a prefix and a suffix around the first such element, fulfilling the corresponding split specification.*)\nLemma split_find p s (i := find p s) :\n has p s -> split_find_spec p s (take i s) (drop i.+1 s).\n\n(*This lemma states that if a sequence is constructed by placing an element that satisfies a certain predicate immediately after a prefix that contains no such elements, then searching for the first element satisfying that predicate in the combined sequence will return the element that was just placed.*)\nLemma nth_rcons_cat_find x0 p s1 s2 x (s := rcons s1 x ++ s2) :\n p x -> ~~ has p s1 -> nth x0 s (find p s) = x.\n\nEnd FindNth.\n\n(*This function increments the value of a sequence of natural numbers at a specified index. If the index is out of bounds, the sequence is first extended with zeros up to that index, and the value at that position is set to one.*)\nFixpoint incr_nth v i {struct i} :=\n if v is n :: v' then if i is i'.+1 then n :: incr_nth v' i' else n.+1 :: v'\n else ncons i 0 [:: 1].\nArguments incr_nth : simpl nomatch.\n\n(*This lemma states that accessing the element at a given index in a sequence modified by the `incr_nth` function yields a value that is one greater than the original value if the access index matches the increment index, and is identical to the original value otherwise.*)\nLemma nth_incr_nth v i j : nth 0 (incr_nth v i) j = (i == j) + nth 0 v j.\n\n(*This lemma states that the size of a sequence resulting from an increment operation remains unchanged if the incremented index is within the original bounds, and becomes one greater than the index if the index was out of bounds.*)\nLemma size_incr_nth v i :\n size (incr_nth v i) = if i < size v then size v else i.+1.\n\n(*This lemma states that for a given sequence of natural numbers, the function that increments an element at a specified index is injective; that is, incrementing the sequence at two different indices will always produce two distinct resulting sequences.*)\nLemma incr_nth_inj v : injective (incr_nth v).\n\n(*This lemma states that for a sequence of numbers, the operation of incrementing the element at a given index and then incrementing the element at another index is commutative.*)\nLemma incr_nthC v i j :\n incr_nth (incr_nth v i) j = incr_nth (incr_nth v j) i.\n\nSection PermSeq.\n\nVariable T : eqType.\nImplicit Type s : seq T.\n\n(*This definition establishes an equivalence relation between two finite sequences, which holds if and only if every element occurs with the same frequency in both sequences.*)\nDefinition perm_eq s1 s2 :=\n all [pred x | count_mem x s1 == count_mem x s2] (s1 ++ s2).\n\n(*This lemma states that two finite sequences are permutations of each other if and only if the functions that count the occurrences of each element in the sequences are equal.*)\nLemma permP s1 s2 : reflect (count^~ s1 =1 count^~ s2) (perm_eq s1 s2).\n\n(*This lemma states that any finite sequence is a permutation of itself.*)\nLemma perm_refl s : perm_eq s s.\n\nHint Resolve perm_refl : core.\n\n(*This lemma states that the permutation equivalence relation is symmetric; if a first finite sequence is a permutation of a second, then the second is also a permutation of the first.*)\nLemma perm_sym : symmetric perm_eq.\n\n(*This lemma states that the permutation equivalence relation is transitive; if a first finite sequence is a permutation of a second, and the second is a permutation of a third, then the first is a permutation of the third.*)\nLemma perm_trans : transitive perm_eq.\n\nNotation perm_eql s1 s2 := (perm_eq s1 =1 perm_eq s2).\nNotation perm_eqr s1 s2 := (perm_eq^~ s1 =1 perm_eq^~ s2).\n\n(*This lemma states that if the boolean test for permutation equivalence between two finite sequences evaluates to true, then the two sequences are propositionally proven to be permutations of each other.*)\nLemma permEl s1 s2 : perm_eql s1 s2 -> perm_eq s1 s2. \n\n(*This lemma states that the boolean test for permutation equivalence between two finite sequences is true if and only if the sequences are permutations of each other.*)\nLemma permPl s1 s2 : reflect (perm_eql s1 s2) (perm_eq s1 s2).\n\n(*This lemma states that a boolean test for permutation equivalence, potentially with reversed arguments, holds if and only if the two finite sequences are permutations of each other.*)\nLemma permPr s1 s2 : reflect (perm_eqr s1 s2) (perm_eq s1 s2).\n\n(*This lemma states that concatenating a first finite sequence with a second finite sequence results in a sequence that is a permutation of the sequence obtained by concatenating the second with the first.*)\nLemma perm_catC s1 s2 : perm_eql (s1 ++ s2) (s2 ++ s1).\n\n(*This lemma provides a left cancellation rule for permutation equivalence over concatenation, stating that two concatenated sequences with a common prefix are permutations of each other if and only if their differing suffixes are permutations of each other.*)\nLemma perm_cat2l s1 s2 s3 : perm_eq (s1 ++ s2) (s1 ++ s3) = perm_eq s2 s3.\n\n(*This lemma states that if two finite sequences are permutations of each other, then prefixing both sequences with the same third sequence results in two new sequences that are also permutations of each other.*)\nLemma perm_catl s t1 t2 : perm_eq t1 t2 -> perm_eql (s ++ t1) (s ++ t2).\n\n(*This lemma provides a cancellation rule for a common head element, stating that two sequences are permutations of each other if and only if their tails are permutations of each other, given they share the same head element.*)\nLemma perm_cons x s1 s2 : perm_eq (x :: s1) (x :: s2) = perm_eq s1 s2.\n\n(*This lemma provides a right cancellation rule for permutation equivalence over concatenation, stating that two concatenated sequences with a common suffix are permutations of each other if and only if their differing prefixes are permutations of each other.*)\nLemma perm_cat2r s1 s2 s3 : perm_eq (s2 ++ s1) (s3 ++ s1) = perm_eq s2 s3.\n\n(*This lemma states that if two finite sequences are permutations of each other, then appending the same third sequence to both results in two new sequences that are also permutations of each other.*)\nLemma perm_catr s1 s2 t : perm_eq s1 s2 -> perm_eql (s1 ++ t) (s2 ++ t).\n\n(*This lemma states that permutation equivalence is a congruence with respect to sequence concatenation; if two pairs of finite sequences are each permutations of one another, then their pairwise concatenations are also permutations of each other.*)\nLemma perm_cat s1 s2 t1 t2 :\n perm_eq s1 s2 -> perm_eq t1 t2 -> perm_eq (s1 ++ t1) (s2 ++ t2).\n\n(*This lemma states that for any three finite sequences, concatenating the first two and then the third results in a sequence that is a permutation of concatenating the first with the third, and then with the second.*)\nLemma perm_catAC s1 s2 s3 : perm_eql ((s1 ++ s2) ++ s3) ((s1 ++ s3) ++ s2).\n\n(*This lemma states that for any three finite sequences, the concatenation of the first with the second and then the third is a permutation of the concatenation of the second with the first and then the third.*)\nLemma perm_catCA s1 s2 s3 : perm_eql (s1 ++ s2 ++ s3) (s2 ++ s1 ++ s3).\n\n(*This lemma states that for any four finite sequences, the concatenation of the first two with the concatenation of the last two is a permutation of the sequence formed by concatenating the first with the third, and then with the concatenation of the second and fourth.*)\nLemma perm_catACA s1 s2 s3 s4 :\n perm_eql ((s1 ++ s2) ++ (s3 ++ s4)) ((s1 ++ s3) ++ (s2 ++ s4)).\n\n(*This lemma states that appending an element to the end of a finite sequence results in a sequence that is a permutation of the sequence formed by prepending the same element to it.*)\nLemma perm_rcons x s : perm_eql (rcons s x) (x :: s).\n\n(*This lemma states that rotating a finite sequence by any number of positions results in a sequence that is a permutation of the original sequence.*)\nLemma perm_rot n s : perm_eql (rot n s) s.\n\n(*This lemma states that rotating a finite sequence to the right by any number of positions results in a sequence that is a permutation of the original sequence.*)\nLemma perm_rotr n s : perm_eql (rotr n s) s.\n\n(*This lemma states that reversing a finite sequence results in a sequence that is a permutation of the original sequence.*)\nLemma perm_rev s : perm_eql (rev s) s.\n\n(*This lemma states that if two finite sequences are permutations of each other, then filtering both sequences with the same predicate produces two new sequences that are also permutations of each other.*)\nLemma perm_filter s1 s2 a :\n perm_eq s1 s2 -> perm_eq (filter a s1) (filter a s2).\n\n(*This lemma states that for any finite sequence and any predicate, the concatenation of the subsequence of elements that satisfy the predicate with the subsequence of elements that do not is a permutation of the original sequence.*)\nLemma perm_filterC a s : perm_eql (filter a s ++ filter (predC a) s) s.\n\n(*This lemma states that if two finite sequences are permutations of each other, then they must have the same length.*)\nLemma perm_size s1 s2 : perm_eq s1 s2 -> size s1 = size s2.\n\n(*This lemma states that if two finite sequences are permutations of each other, then they contain the same set of elements, irrespective of order or multiplicity.*)\nLemma perm_mem s1 s2 : perm_eq s1 s2 -> s1 =i s2.\n\n(*This lemma states that a finite sequence is a permutation of the empty sequence if and only if that sequence is itself empty.*)\nLemma perm_nilP s : reflect (s = [::]) (perm_eq s [::]).\n\n(*This lemma states that a finite sequence is a permutation of another sequence constructed by prepending an element if and only if the first sequence can be rotated to place that same element at its head, with the remainder being a permutation of the tail of the second sequence.*)\nLemma perm_consP x s t :\n reflect (exists i u, rot i t = x :: u /\\ perm_eq u s)\n (perm_eq t (x :: s)).\n\n(*This lemma states that if two finite sequences are permutations of each other, then checking for the existence of an element satisfying a given predicate yields the same boolean result for both sequences.*)\nLemma perm_has s1 s2 a : perm_eq s1 s2 -> has a s1 = has a s2.\n\n(*This lemma states that if two finite sequences are permutations of each other, then the boolean result of checking whether a given predicate holds for all elements is the same for both sequences.*)\nLemma perm_all s1 s2 a : perm_eq s1 s2 -> all a s1 = all a s2.\n\n(*This lemma states that if a finite sequence is a permutation of another finite sequence whose size is at most one, then the two sequences are equal.*)\nLemma perm_small_eq s1 s2 : size s2 <= 1 -> perm_eq s1 s2 -> s1 = s2.\n\n(*This lemma states that if a finite sequence has no duplicate elements and its elements form a subset of the elements of a second finite sequence, then the size of the first sequence is less than or equal to the size of the second sequence.*)\nLemma uniq_leq_size s1 s2 : uniq s1 -> {subset s1 <= s2} -> size s1 <= size s2.\n\n(*This lemma states that if a first finite sequence with no duplicate elements has its elements as a subset of a second finite sequence, and the size of the second sequence is less than or equal to the size of the first, then the second sequence also has no duplicate elements.*)\nLemma leq_size_uniq s1 s2 :\n uniq s1 -> {subset s1 <= s2} -> size s2 <= size s1 -> uniq s2.\n\n(*This lemma states that if a first finite sequence has no duplicate elements and is equivalent as a multiset to a second finite sequence, then the second sequence has no duplicate elements if and only if their sizes are equal.*)\nLemma uniq_size_uniq s1 s2 :\n uniq s1 -> s1 =i s2 -> uniq s2 = (size s2 == size s1).\n\n(*This lemma states that if a first finite sequence with no duplicate elements has its elements as a subset of a second finite sequence, and the size of the second is less than or equal to the size of the first, then their sizes are equal and they are equivalent as multisets.*)\nLemma uniq_min_size s1 s2 :\n uniq s1 -> {subset s1 <= s2} -> size s2 <= size s1 ->\n (size s1 = size s2) * (s1 =i s2).\n\n(*This lemma states that if two finite sequences have the same size and are equivalent as multisets, then the property of having no duplicate elements is equivalent for both sequences.*)\nLemma eq_uniq s1 s2 : size s1 = size s2 -> s1 =i s2 -> uniq s1 = uniq s2.\n\n(*This lemma states that if two finite sequences are permutations of each other, then one has no duplicate elements if and only if the other one does.*)\nLemma perm_uniq s1 s2 : perm_eq s1 s2 -> uniq s1 = uniq s2.\n\n(*This lemma states that if two finite sequences both have no duplicate elements and are equivalent as multisets, then they are permutations of each other.*)\nLemma uniq_perm s1 s2 : uniq s1 -> uniq s2 -> s1 =i s2 -> perm_eq s1 s2.\n\n(*This lemma states that if two finite sequences are equivalent as multisets, then the sequences resulting from removing all duplicate elements from each are permutations of each other.*)\nLemma perm_undup s1 s2 : s1 =i s2 -> perm_eq (undup s1) (undup s2).\n\n(*This lemma states that if, for every element, the number of its occurrences in a finite sequence is equal to the boolean indicating its membership, then that sequence contains no duplicate elements.*)\nLemma count_mem_uniq s : (forall x, count_mem x s = (x \\in s)) -> uniq s.\n\n(*This lemma states that if two finite sequences are equivalent as multisets with respect to a given set of elements, then the number of occurrences of a given element in the sequence of unique elements derived from the first sequence is equal to the number of occurrences of that same element in the sequence of unique elements derived from the second.*)\nLemma eq_count_undup a s1 s2 :\n {in a, s1 =i s2} -> count a (undup s1) = count a (undup s2).\n\n(*This lemma provides an induction principle for permutations, stating that if a property of finite sequences is preserved when any two adjacent subsequences are swapped within a larger sequence, then that property holds for any sequence that is a permutation of another sequence for which the property holds.*)\nLemma catCA_perm_ind P :\n (forall s1 s2 s3, P (s1 ++ s2 ++ s3) -> P (s2 ++ s1 ++ s3)) ->\n (forall s1 s2, perm_eq s1 s2 -> P s1 -> P s2).\n\n(*This lemma states that if a function from finite sequences to some type gives an equal result when applied to a sequence and to the version of that sequence where two adjacent subsequences are swapped, then that function will produce equal results for any two sequences that are permutations of each other.*)\nLemma catCA_perm_subst R F :\n (forall s1 s2 s3, F (s1 ++ s2 ++ s3) = F (s2 ++ s1 ++ s3) :> R) ->\n (forall s1 s2, perm_eq s1 s2 -> F s1 = F s2).\n\nEnd PermSeq.\n\nNotation perm_eql s1 s2 := (perm_eq s1 =1 perm_eq s2).\nNotation perm_eqr s1 s2 := (perm_eq^~ s1 =1 perm_eq^~ s2).\n\nArguments permP {T s1 s2}.\nArguments permPl {T s1 s2}.\nArguments permPr {T s1 s2}.\nPrenex Implicits perm_eq.\n#[global] Hint Resolve perm_refl : core.\n\nSection RotrLemmas.\n\nVariables (n0 : nat) (T : Type) (T' : eqType).\nImplicit Types (x : T) (s : seq T).\n\n(*This lemma states that rotating a finite sequence to the right by a given number of positions does not change its size.*)\nLemma size_rotr s : size (rotr n0 s) = size s.\n\n(*This lemma states that rotating a finite sequence to the right results in a new sequence that is equivalent to the original as a multiset.*)\nLemma mem_rotr (s : seq T') : rotr n0 s =i s.\n\n(*This lemma states that rotating the concatenation of two finite sequences to the right by an amount equal to the size of the second sequence results in the concatenation of the second sequence followed by the first.*)\nLemma rotr_size_cat s1 s2 : rotr (size s2) (s1 ++ s2) = s2 ++ s1.\n\n(*This lemma states that rotating a finite sequence, which is formed by appending an element to another sequence, one position to the right is equivalent to prepending that element to the original sequence.*)\nLemma rotr1_rcons x s : rotr 1 (rcons s x) = x :: s.\n\n(*This lemma states that checking for the presence of a given element in a finite sequence yields the same boolean result before and after the sequence is rotated to the right.*)\nLemma has_rotr a s : has a (rotr n0 s) = has a s.\n\n(*This lemma states that the property of a finite sequence having no duplicate elements is preserved under right rotation.*)\nLemma rotr_uniq (s : seq T') : uniq (rotr n0 s) = uniq s.\n\n(*This lemma states that the right rotation operation is the left inverse of the left rotation operation for any given number of positions, meaning that rotating left and then rotating right by the same amount restores the original finite sequence.*)\nLemma rotrK : cancel (@rotr T n0) (rot n0).\n\n(*This lemma states that the function that rotates a finite sequence to the right by a given number of positions is injective, meaning that distinct sequences map to distinct rotated sequences.*)\nLemma rotr_inj : injective (@rotr T n0).\n\n(*This lemma states that taking a prefix of a given length from a reversed finite sequence is equivalent to reversing the suffix of the original sequence that starts after a number of elements equal to the total size minus the given length.*)\nLemma take_rev s : take n0 (rev s) = rev (drop (size s - n0) s).\n\n(*This lemma states that reversing a prefix of a given length from a finite sequence is equivalent to dropping a prefix from the reversed sequence, where the length of the prefix to drop is the total size minus the given length.*)\nLemma rev_take s : rev (take n0 s) = drop (size s - n0) (rev s).\n\n(*This lemma states that dropping a prefix of a given length from a reversed finite sequence is equivalent to reversing the prefix of the original sequence whose length is the total size minus the given length.*)\nLemma drop_rev s : drop n0 (rev s) = rev (take (size s - n0) s).\n\n(*This lemma states that reversing the suffix of a finite sequence that remains after dropping a prefix of a given length is equivalent to taking a prefix from the reversed sequence, where the prefix length is the total size minus the given length.*)\nLemma rev_drop s : rev (drop n0 s) = take (size s - n0) (rev s).\n\n(*This lemma states that reversing a finite sequence after a right rotation is equivalent to performing a left rotation on the reversed sequence by the same amount.*)\nLemma rev_rotr s : rev (rotr n0 s) = rot n0 (rev s).\n\n(*This lemma states that reversing a finite sequence after a left rotation is equivalent to performing a right rotation on the reversed sequence by the same amount.*)\nLemma rev_rot s : rev (rot n0 s) = rotr n0 (rev s).\n\nEnd RotrLemmas.\n\nArguments rotrK n0 {T} s : rename.\nArguments rotr_inj {n0 T} [s1 s2] eq_rotr_s12 : rename.\n\nSection RotCompLemmas.\n\nVariable T : Type.\nImplicit Type s : seq T.\n\n(*This lemma states that rotating a finite sequence to the left by the sum of two natural numbers is equivalent to performing two successive left rotations, first by one number and then by the other, provided that the sum of the rotation amounts is less than or equal to the length of the sequence.*)\nLemma rotD m n s : m + n <= size s -> rot (m + n) s = rot m (rot n s).\n\n(*This lemma states that rotating a finite sequence to the left by the successor of a natural number is equivalent to rotating it to the left by one position and then rotating the result to the left by that natural number, provided the number is strictly less than the sequence's length.*)\nLemma rotS n s : n < size s -> rot n.+1 s = rot 1 (rot n s).\n\n(*This lemma states that performing two successive left rotations on a finite sequence is equivalent to a single left rotation by an amount calculated from the sum of the two rotation numbers. If this sum is less than or equal to the sequence length, the new rotation amount is just the sum; otherwise, it is the sum minus the sequence length. This holds when both initial rotation amounts are less than or equal to the sequence length.*)\nLemma rot_add_mod m n s : n <= size s -> m <= size s ->\n rot m (rot n s) = rot (if m + n <= size s then m + n else m + n - size s) s.\n\n(*This lemma states that rotating a finite sequence to the left by a given natural number produces the same result as rotating it by the minimum of that number and the length of the sequence.*)\nLemma rot_minn n s : rot n s = rot (minn n (size s)) s.\n\n(*This definition computes a combined rotation amount for a finite sequence from two given natural numbers. It first takes the minimum of each number and the sequence length, adds these two results, and if this sum exceeds the sequence length, it subtracts the sequence length to wrap around.*)\nDefinition rot_add s n m (k := size s) (p := minn m k + minn n k) :=\n locked (if p <= k then p else p - k).\n\n(*This lemma states that the combined rotation amount for a finite sequence, as computed by the `rot_add` operation, is always less than or equal to the length of the sequence.*)\nLemma leq_rot_add n m s : rot_add s n m <= size s.\n\n(*This lemma states that the `rot_add` operation, which computes a combined rotation amount for a finite sequence from two natural numbers, is commutative with respect to its two numerical inputs.*)\nLemma rot_addC n m s : rot_add s n m = rot_add s m n.\n\n(*This lemma states that applying two successive left rotations to a finite sequence is equivalent to applying a single left rotation by the combined amount computed by the `rot_add` operation.*)\nLemma rot_rot_add n m s : rot m (rot n s) = rot (rot_add s n m) s.\n\n(*This lemma states that for any finite sequence, the order of applying two successive left rotations does not affect the final result; that is, rotating first by one amount and then by a second is the same as rotating first by the second amount and then by the first.*)\nLemma rot_rot m n s : rot m (rot n s) = rot n (rot m s).\n\n(*This lemma states that for any finite sequence, a left rotation and a right rotation commute; the result is the same whether the left rotation is applied before or after the right rotation.*)\nLemma rot_rotr m n s : rot m (rotr n s) = rotr n (rot m s).\n\n(*This lemma states that for any finite sequence, the order of applying two successive right rotations does not affect the final result; that is, rotating right first by one amount and then by a second is the same as rotating right first by the second amount and then by the first.*)\nLemma rotr_rotr m n s : rotr m (rotr n s) = rotr n (rotr m s).\n\nEnd RotCompLemmas.\n\nSection Mask.\n\nVariables (n0 : nat) (T : Type).\nImplicit Types (m : bitseq) (s : seq T).\n\n(*This definition describes a function that filters a finite sequence of elements based on a corresponding finite sequence of booleans, called a mask. The resulting sequence contains only those elements from the original sequence whose corresponding boolean value in the mask is true.*)\nFixpoint mask m s {struct m} :=\n match m, s with\n | b :: m', x :: s' => if b then x :: mask m' s' else mask m' s'\n | _, _ => [::]\n end.\n\n(*This lemma states that applying a mask composed entirely of false booleans to any finite sequence results in an empty sequence.*)\nLemma mask_false s n : mask (nseq n false) s = [::].\n\n(*This lemma states that if a finite sequence is filtered using a mask composed entirely of true booleans, and the mask is at least as long as the sequence, the result is the original sequence unchanged.*)\nLemma mask_true s n : size s <= n -> mask (nseq n true) s = s.\n\n(*This lemma states that applying any boolean mask to an empty finite sequence results in an empty finite sequence.*)\nLemma mask0 m : mask m [::] = [::].\n\n(*This lemma states that applying an empty boolean mask to any finite sequence results in an empty finite sequence.*)\nLemma mask0s s : mask [::] s = [::]. \n\n(*This lemma states that masking a singleton sequence with a singleton boolean mask results in a sequence containing the single element if the boolean is true, and an empty sequence if the boolean is false.*)\nLemma mask1 b x : mask [:: b] [:: x] = nseq b x.\n\n(*This lemma states that applying a mask to a sequence can be computed recursively: the result is the concatenation of the sequence formed by the first element, if its corresponding boolean is true, and the result of masking the rest of the sequence with the rest of the mask.*)\nLemma mask_cons b m x s : mask (b :: m) (x :: s) = nseq b x ++ mask m s.\n\n(*This lemma states that when a finite sequence is filtered by a boolean mask of the same length, the length of the resulting sequence is equal to the number of true values in the mask.*)\nLemma size_mask m s : size m = size s -> size (mask m s) = count id m.\n\n(*This lemma states that masking the concatenation of two finite sequences with the concatenation of two corresponding boolean masks is equivalent to masking each sequence with its corresponding mask separately and then concatenating the two results, provided the first mask and the first sequence have the same length.*)\nLemma mask_cat m1 m2 s1 s2 :\n size m1 = size s1 -> mask (m1 ++ m2) (s1 ++ s2) = mask m1 s1 ++ mask m2 s2.\n\n(*This lemma provides a right-to-left recursive property for the mask operation. It states that masking a sequence extended with one element at the end is equivalent to masking the initial sequence and then appending the new element if its corresponding boolean is true, provided the initial mask and sequence have the same length.*)\nLemma mask_rcons b m x s : size m = size s ->\n mask (rcons m b) (rcons s x) = mask m s ++ nseq b x.\n\n(*This lemma states that if a given predicate is true for every element in a finite sequence, then the predicate will also be true for every element in any sequence that results from filtering the original sequence with a boolean mask.*)\nLemma all_mask a m s : all a s -> all a (mask m s).\n\n(*This lemma states that for a non-empty sequence and mask, checking if any element in the masked sequence satisfies a given predicate is equivalent to checking two conditions: either the first boolean of the mask is true and the first element of the sequence satisfies the predicate, or an element satisfying the predicate exists in the result of masking the rest of the sequence with the rest of the mask.*)\nLemma has_mask_cons a b m x s :\n has a (mask (b :: m) (x :: s)) = b && a x || has a (mask m s).\n\n(*This lemma states that if at least one element in a masked finite sequence satisfies a given predicate, then at least one element in the original, unmasked finite sequence must also satisfy that same predicate.*)\nLemma has_mask a m s : has a (mask m s) -> has a s.\n\n(*This lemma states that reversing the result of a mask operation on a finite sequence is equivalent to applying a mask composed of the reversed boolean sequence to the reversed original sequence, provided the mask and the sequence have the same length.*)\nLemma rev_mask m s : size m = size s -> rev (mask m s) = mask (rev m) (rev s).\n\n(*This lemma states that masking a rotated finite sequence with a rotated boolean mask of the same length is equivalent to first masking the original sequence with the original mask, and then rotating the resulting filtered sequence. The amount of this final rotation is equal to the number of true values in the initial segment of the mask that was moved during the first rotation.*)\nLemma mask_rot m s : size m = size s ->\n mask (rot n0 m) (rot n0 s) = rot (count id (take n0 m)) (mask m s).\n\n(*This lemma asserts that for any given boolean mask and finite sequence, there exists another boolean mask that has the same length as the sequence and produces the exact same filtered result when applied to that sequence.*)\nLemma resize_mask m s : {m1 | size m1 = size s & mask m s = mask m1 s}.\n\n(*This lemma states that taking the first few elements from a finite sequence is equivalent to filtering that sequence with a boolean mask that begins with a corresponding number of true values.*)\nLemma takeEmask i s : take i s = mask (nseq i true) s.\n\n(*This lemma states that dropping the first given number of elements from a finite sequence is equivalent to applying a specific boolean mask to that sequence. The mask is constructed by concatenating a sequence of false values, whose length is the number of dropped elements, with a sequence of true values for the remainder of the length.*)\nLemma dropEmask i s :\n drop i s = mask (nseq i false ++ nseq (size s - i) true) s.\n\nEnd Mask.\nArguments mask _ !_ !_.\n\nSection EqMask.\n\nVariables (n0 : nat) (T : eqType).\nImplicit Types (s : seq T) (m : bitseq).\n\n(*This lemma provides a rule for determining membership in a filtered sequence. It states that an element is a member of a sequence that is filtered by a boolean mask, where both the sequence and mask are built by prepending an element, if and only if one of two conditions holds: either the prepended boolean is true and the element equals the prepended sequence element, or the element is a member of the tail of the sequence filtered by the tail of the mask.*)\nLemma mem_mask_cons x b m y s :\n (x \\in mask (b :: m) (y :: s)) = b && (x == y) || (x \\in mask m s).\n\n(*This lemma states that if an element is a member of a sequence that has been filtered by a boolean mask, then that element must also be a member of the original, unfiltered sequence.*)\nLemma mem_mask x m s : x \\in mask m s -> x \\in s.\n\n(*This lemma provides a condition for an element's membership in a filtered sequence, given that the original sequence has no duplicate elements. It states that an element belongs to the filtered sequence if and only if it is present in the original sequence and the boolean value in the corresponding mask at the element's index within the original sequence is true.*)\nLemma in_mask x m s :\n uniq s -> x \\in mask m s = (x \\in s) && nth false m (index x s).\n\n(*This lemma states that if a finite sequence contains no duplicate elements, then any sequence resulting from filtering it with any boolean mask will also be free of duplicates.*)\nLemma mask_uniq s : uniq s -> forall m, uniq (mask m s).\n\n(*This lemma relates filtering to rotation. It states that for a boolean mask and a finite sequence of the same size, filtering the sequence after it has been rotated by a certain number of positions with the mask also rotated by the same amount, yields a sequence that is a permutation of the one obtained by filtering the original sequence with the original mask.*)\nLemma mem_mask_rot m s :\n size m = size s -> mask (rot n0 m) (rot n0 s) =i mask m s.\n\nEnd EqMask.\n\nSection Subseq.\n\nVariable T : eqType.\nImplicit Type s : seq T.\n\n(*This function determines whether a first finite sequence can be obtained from a second finite sequence by deleting zero or more of its elements.*)\nFixpoint subseq s1 s2 :=\n if s2 is y :: s2' then\n if s1 is x :: s1' then subseq (if x == y then s1' else s1) s2' else true\n else s1 == [::].\n\n(*This lemma states that the empty sequence is a subsequence of any other finite sequence.*)\nLemma sub0seq s : subseq [::] s. \n\n(*This lemma states that a finite sequence is a subsequence of the empty sequence if and only if that sequence is itself empty.*)\nLemma subseq0 s : subseq s [::] = (s == [::]). \n\n(*This lemma states that any finite sequence is a subsequence of itself, establishing the reflexivity of the subsequence relation.*)\nLemma subseq_refl s : subseq s s.\n\nHint Resolve subseq_refl : core.\n\n(*This lemma provides an alternative definition of the subsequence relation. It states that a first finite sequence is a subsequence of a second one if and only if there exists a boolean mask, having the same length as the second sequence, such that the first sequence is identical to the result of filtering the second sequence with that mask.*)\nLemma subseqP s1 s2 :\n reflect (exists2 m, size m = size s2 & s1 = mask m s2) (subseq s1 s2).\n\n(*This lemma states that filtering a finite sequence with any boolean mask always produces a result that is a subsequence of the original sequence.*)\nLemma mask_subseq m s : subseq (mask m s) s.\n\n(*This lemma asserts that the subsequence relation is transitive, meaning if a first sequence is a subsequence of a second, and the second is a subsequence of a third, then the first is also a subsequence of the third.*)\nLemma subseq_trans : transitive subseq.\n\n(*This lemma describes how the subsequence property interacts with concatenation. It states that if a first sequence is a subsequence of a third, and a second sequence is a subsequence of a fourth, then concatenating the first and second sequences results in a subsequence of the concatenation of the third and fourth sequences.*)\nLemma cat_subseq s1 s2 s3 s4 :\n subseq s1 s3 -> subseq s2 s4 -> subseq (s1 ++ s2) (s3 ++ s4).\n\n(*This lemma states that a first finite sequence is always a subsequence of any sequence formed by concatenating the first sequence with a second one.*)\nLemma prefix_subseq s1 s2 : subseq s1 (s1 ++ s2).\n\n(*This lemma states that a second finite sequence is always a subsequence of any sequence formed by concatenating a first sequence with the second one.*)\nLemma suffix_subseq s1 s2 : subseq s2 (s1 ++ s2).\n\n(*This lemma states that the prefix of a finite sequence, obtained by taking a specified number of initial elements, is a subsequence of the original sequence.*)\nLemma take_subseq s i : subseq (take i s) s.\n\n(*This lemma states that the suffix of a finite sequence, obtained by dropping a specified number of initial elements, is a subsequence of the original sequence.*)\nLemma drop_subseq s i : subseq (drop i s) s.\n\n(*This lemma states that if a first finite sequence is a subsequence of a second one, then the set of elements contained in the first sequence is a subset of the set of elements in the second.*)\nLemma mem_subseq s1 s2 : subseq s1 s2 -> {subset s1 <= s2}.\n\n(*This lemma states that a sequence containing a single, specific element is a subsequence of another sequence if and only if that element is a member of the other sequence.*)\nLemma sub1seq x s : subseq [:: x] s = (x \\in s).\n\n(*This lemma states that if a first finite sequence is a subsequence of a second, then the length of the first sequence is less than or equal to the length of the second.*)\nLemma size_subseq s1 s2 : subseq s1 s2 -> size s1 <= size s2.\n\n(*This lemma states that if a finite sequence is a subsequence of another and they have the same length, then the two sequences must be identical.*)\nLemma size_subseq_leqif s1 s2 :\n subseq s1 s2 -> size s1 <= size s2 ?= iff (s1 == s2).\n\n(*This lemma asserts that the subsequence relation is antisymmetric. This means that if a first finite sequence is a subsequence of a second, and the second is also a subsequence of the first, then the two sequences must be equal.*)\nLemma subseq_anti : antisymmetric subseq.\n\n(*This lemma states that any finite sequence is a subsequence of the new sequence created by prepending an arbitrary element to it.*)\nLemma subseq_cons s x : subseq s (x :: s).\n\n(*This lemma states that if a sequence formed by prepending an element to a given sequence is a subsequence of a second sequence, then the given sequence without the prepended element is also a subsequence of that second sequence.*)\nLemma cons_subseq s1 s2 x : subseq (x :: s1) s2 -> subseq s1 s2.\n\n(*This lemma states that any finite sequence is a subsequence of the new sequence created by appending an arbitrary element to its end.*)\nLemma subseq_rcons s x : subseq s (rcons s x).\n\n(*This lemma states that if a finite sequence is a subsequence of a second sequence that has no duplicate elements, then the first sequence must also be free of duplicates.*)\nLemma subseq_uniq s1 s2 : subseq s1 s2 -> uniq s2 -> uniq s1.\n\n(*This lemma states that if a finite sequence contains no duplicate elements, then any prefix of that sequence, formed by taking some number of initial elements, will also contain no duplicate elements.*)\nLemma take_uniq s n : uniq s -> uniq (take n s).\n\n(*This lemma states that if a finite sequence contains no duplicate elements, then any suffix of that sequence, formed by dropping some number of initial elements, will also contain no duplicate elements.*)\nLemma drop_uniq s n : uniq s -> uniq (drop n s).\n\n(*This lemma states that the sequence resulting from the removal of all duplicate elements from a given finite sequence is a subsequence of the original sequence.*)\nLemma undup_subseq s : subseq (undup s) s.\n\n(*This lemma states that the boolean indicating whether the reverse of a first finite sequence is a subsequence of the reverse of a second finite sequence is equal to the boolean indicating whether the first sequence is a subsequence of the second.*)\nLemma subseq_rev s1 s2 : subseq (rev s1) (rev s2) = subseq s1 s2.\n\n(*This lemma states that the subsequence relationship between two finite sequences, each formed by prepending a common prefix sequence, is equivalent to the subsequence relationship between the original two sequences without the common prefix.*)\nLemma subseq_cat2l s s1 s2 : subseq (s ++ s1) (s ++ s2) = subseq s1 s2.\n\n(*This lemma states that the subsequence relationship between two finite sequences, each formed by appending a common suffix sequence, is equivalent to the subsequence relationship between the original two sequences without the common suffix.*)\nLemma subseq_cat2r s s1 s2 : subseq (s1 ++ s) (s2 ++ s) = subseq s1 s2.\n\n(*This lemma states that if a first finite sequence is a subsequence of a second one, then for any rotation of the second sequence by a given natural number, there exists a smaller or equal rotation of the first sequence that is a subsequence of the rotated second sequence.*)\nLemma subseq_rot p s n :\n subseq p s -> exists2 k, k <= n & subseq (rot k p) (rot n s).\n\nEnd Subseq.\n\nPrenex Implicits subseq.\nArguments subseqP {T s1 s2}.\n\n#[global] Hint Resolve subseq_refl : core.\n\nSection Rem.\n\nVariables (T : eqType) (x : T).\n\n(*This fixpoint defines a function that removes the first occurrence of a given element from a finite sequence. If the element is not found, the original sequence is returned.*)\nFixpoint rem s := if s is y :: t then (if y == x then t else y :: rem t) else s.\n\n(*This lemma provides the computational rule for removing a specific element from a non-empty finite sequence. If the head of the sequence is the element to be removed, the result is the tail of the sequence; otherwise, the result is the head of the sequence prepended to the result of removing the element from the tail.*)\nLemma rem_cons y s : rem (y :: s) = if y == x then s else y :: rem s.\n\n(*This lemma states that removing the first occurrence of a given element from a finite sequence is equivalent to concatenating the part of the sequence before that element's first occurrence with the part of the sequence that starts one position after it.*)\nLemma remE s : rem s = take (index x s) s ++ drop (index x s).+1 s.\n\n(*This lemma states that if an element is not a member of a finite sequence, then applying the operation to remove that element results in the original sequence unchanged.*)\nLemma rem_id s : x \\notin s -> rem s = s.\n\n(*This lemma states that if an element is a member of a finite sequence, then the original sequence is a permutation of the sequence formed by prepending the element to the result of removing its first occurrence from the original sequence.*)\nLemma perm_to_rem s : x \\in s -> perm_eq s (x :: rem s).\n\n(*This lemma states that if an element is a member of a finite sequence, the size of the sequence after removing the first occurrence of that element is one less than the size of the original sequence.*)\nLemma size_rem s : x \\in s -> size (rem s) = (size s).-1.\n\n(*This lemma states that a finite sequence resulting from removing the first occurrence of an element is always a subsequence of the original sequence.*)\nLemma rem_subseq s : subseq (rem s) s.\n\n(*This lemma states that if a finite sequence contains no duplicate elements, then the sequence resulting from removing the first occurrence of an element will also contain no duplicate elements.*)\nLemma rem_uniq s : uniq s -> uniq (rem s).\n\n(*This lemma states that the set of elements in a finite sequence after removing the first occurrence of a specific element is a subset of the set of elements in the original sequence.*)\nLemma mem_rem s : {subset rem s <= s}.\n\n(*This lemma states that if a given element is present in a finite sequence, and this element is not equal to the specific element being removed, then it will also be present in the resulting sequence after the removal operation.*)\nLemma rem_mem y s : y != x -> y \\in s -> y \\in rem s.\n\n(*This lemma states that for a finite sequence with unique elements, removing a specific element is equivalent to filtering the sequence to keep only those elements that are not equal to the specified element.*)\nLemma rem_filter s : uniq s -> rem s = filter (predC1 x) s.\n\n(*This lemma states that for a finite sequence with unique elements, the sequence resulting from removing a specific element is a permutation of the sequence of elements that are members of the original sequence but are not the element being removed.*)\nLemma mem_rem_uniq s : uniq s -> rem s =i [predD1 s & x].\n\n(*This lemma states that if a finite sequence contains no duplicate elements, then after removing a specific element, that element will no longer be a member of the resulting sequence.*)\nLemma mem_rem_uniqF s : uniq s -> x \\in rem s = false.\n\n(*This lemma states that the number of elements satisfying a given predicate in a sequence after removing a specific element is equal to the original count of such elements, decremented by one if the removed element was present and satisfied the predicate.*)\nLemma count_rem P s : count P (rem s) = count P s - (x \\in s) && P x.\n\n(*This lemma states that the number of occurrences of a given element in a finite sequence after removing another specific element is equal to the original count of occurrences, decremented by one if the element being counted is the same as the element that was removed.*)\nLemma count_mem_rem y s : count_mem y (rem s) = count_mem y s - (x == y).\n\nEnd Rem.\n\nSection Map.\n\nVariables (n0 : nat) (T1 : Type) (x1 : T1).\nVariables (T2 : Type) (x2 : T2) (f : T1 -> T2).\n\n(*This fixpoint defines a function that applies a given function to each element of a finite sequence, producing a new finite sequence of the results.*)\nFixpoint map s := if s is x :: s' then f x :: map s' else [::].\n\n(*This lemma provides the computational rule for mapping a function over a non-empty finite sequence, stating that the result is the head of the sequence with the function applied to it, prepended to the result of mapping the function over the tail.*)\nLemma map_cons x s : map (x :: s) = f x :: map s.\n\n(*This lemma states that mapping a function over a finite sequence consisting of a specified number of repetitions of a single element results in a new sequence with the same number of repetitions of the element that results from applying the function to the original element.*)\nLemma map_nseq x : map (nseq n0 x) = nseq n0 (f x).\n\n(*This lemma states that mapping a function over the concatenation of two finite sequences is equivalent to concatenating the results of mapping the function over each sequence individually.*)\nLemma map_cat s1 s2 : map (s1 ++ s2) = map s1 ++ map s2.\n\n(*This lemma states that the size of a finite sequence resulting from mapping a function over an original sequence is equal to the size of the original sequence.*)\nLemma size_map s : size (map s) = size s.\n\n(*This lemma states that taking the tail of a finite sequence which has been transformed by a map operation is equivalent to first taking the tail of the original sequence and then applying the map operation to it.*)\nLemma behead_map s : behead (map s) = map (behead s).\n\n(*This lemma states that for a valid index, the element at that index in a mapped finite sequence is equal to the result of applying the map's function to the element at the same index in the original sequence.*)\nLemma nth_map n s : n < size s -> nth x2 (map s) n = f (nth x1 s n).\n\n(*This lemma states that mapping a function over a finite sequence that has had an element appended to it is equivalent to first mapping the function over the original sequence and then appending the result of applying the function to the element.*)\nLemma map_rcons s x : map (rcons s x) = rcons (map s) (f x).\n\n(*This lemma states that the last element of a finite sequence transformed by a map operation is equal to the result of applying the map's function to the last element of the original sequence.*)\nLemma last_map s x : last (f x) (map s) = f (last x s).\n\n(*This lemma states that removing the last element from a finite sequence that has been transformed by a map operation is equivalent to first removing the last element of the original sequence and then applying the map operation to the result.*)\nLemma belast_map s x : belast (f x) (map s) = map (belast x s).\n\n(*This lemma states that filtering a mapped finite sequence with a given predicate is equivalent to mapping the function over the original sequence after it has been filtered by a predicate that checks if the function's output on an element satisfies the original predicate.*)\nLemma filter_map a s : filter a (map s) = map (filter (preim f a) s).\n\n(*This lemma states that finding the first element in a sequence transformed by a function that satisfies a given predicate is equivalent to finding the first element in the original sequence whose image under the function satisfies that predicate.*)\nLemma find_map a s : find a (map s) = find (preim f a) s.\n\n(*This lemma states that determining whether a sequence transformed by a function contains an element satisfying a given predicate is equivalent to determining whether the original sequence contains an element whose image under that function satisfies the predicate.*)\nLemma has_map a s : has a (map s) = has (preim f a) s.\n\n(*This lemma states that checking if all elements in a sequence transformed by a function satisfy a given predicate is equivalent to checking if all elements in the original sequence have images under that function that satisfy the predicate.*)\nLemma all_map a s : all a (map s) = all (preim f a) s.\n\n(*This lemma states that if a given predicate holds for the image of every possible element under a function, then that predicate will also hold for all elements in a sequence that has been transformed by that function.*)\nLemma all_mapT (a : pred T2) s : (forall x, a (f x)) -> all a (map s).\n\n(*This lemma states that the number of elements satisfying a given predicate in a sequence transformed by a function is equal to the number of elements in the original sequence whose images under that function satisfy the predicate.*)\nLemma count_map a s : count a (map s) = count (preim f a) s.\n\n(*This lemma states that applying a function to each element of a prefix of a given length from a sequence yields the same result as first applying the function to the entire sequence and then taking the prefix of the same length.*)\nLemma map_take s : map (take n0 s) = take n0 (map s).\n\n(*This lemma states that applying a function to the suffix of a sequence that remains after dropping a specified number of initial elements is equivalent to first applying the function to the entire sequence and then dropping the same number of initial elements from the result.*)\nLemma map_drop s : map (drop n0 s) = drop n0 (map s).\n\n(*This lemma states that applying a function to each element of a sequence that has been rotated to the left by a certain number of positions is equivalent to first applying the function to the entire sequence and then rotating the resulting sequence by the same number of positions.*)\nLemma map_rot s : map (rot n0 s) = rot n0 (map s).\n\n(*This lemma states that applying a function to each element of a sequence that has been rotated to the right by a certain number of positions is equivalent to first applying the function to the entire sequence and then rotating the resulting sequence to the right by the same number of positions.*)\nLemma map_rotr s : map (rotr n0 s) = rotr n0 (map s).\n\n(*This lemma states that applying a function to each element of a reversed sequence is equivalent to first applying the function to the original sequence and then reversing the resulting sequence.*)\nLemma map_rev s : map (rev s) = rev (map s).\n\n(*This lemma states that applying a function to elements of a sequence that are selected by a boolean mask is equivalent to first applying the function to the entire sequence and then selecting elements from the transformed sequence using the same boolean mask.*)\nLemma map_mask m s : map (mask m s) = mask m (map s).\n\n(*This lemma states that if a given function is injective, meaning it maps distinct inputs to distinct outputs, then the corresponding function that applies it element-wise to sequences is also injective.*)\nLemma inj_map : injective f -> injective map.\n\n(*This lemma states that if a function is injective on a given subset of its domain, then the element-wise mapping of that function is also injective when applied to sequences whose elements are all drawn from that subset.*)\nLemma inj_in_map (A : {pred T1}) :\n {in A &, injective f} -> {in [pred s | all [in A] s] &, injective map}.\n\nEnd Map.\n\nSection onth.\n\nVariable T : Type.\n\nImplicit Types x y z : T.\nImplicit Types m n : nat.\nImplicit Type s : seq T.\n\n(*This function retrieves an element from a finite sequence at a specified zero-based index, returning the element if the index is valid, or a special null value if the index is out of bounds.*)\nFixpoint onth s n {struct n} : option T :=\n if s isn't x :: s then None else\n if n isn't n.+1 then Some x else onth s n.\n\n(*This lemma states that providing a default value to the result of a safe indexed access on a sequence is equivalent to performing an unsafe indexed access on the same sequence with the same default value.*)\nLemma odflt_onth x0 s n : odflt x0 (onth s n) = nth x0 s n.\n\n(*This lemma states that safely accessing an element at a given index in a sequence is equivalent to unsafely accessing an element at the same index in a transformed sequence where each original element has been wrapped as a potentially present value, with the default for out-of-bounds access being a null value.*)\nLemma onthE s : onth s =1 nth None (map Some s).\n\n(*This lemma states that if a safe indexed access on a sequence at a given position succeeds and returns a specific value, then an unsafe indexed access at the same position, regardless of the default value supplied, will also return that same value.*)\nLemma onth_nth x0 x t n : onth t n = Some x -> nth x0 t n = x.\n\n(*This lemma states that attempting to access an element at any index in an empty sequence will always result in a null value.*)\nLemma onth0n n : onth [::] n = None. \n\n(*This lemma states that for a sequence with a single element, successfully accessing a value at a given index is equivalent to the index being zero and the accessed value being equal to the single element of the sequence.*)\nLemma onth1P x y n : onth [:: x] n = Some y <-> n = 0 /\\ x = y.\n\n(*This lemma states that a safe indexed access on a sequence yields a value if and only if the specified index is strictly less than the size of the sequence.*)\nLemma onthTE s n : onth s n = (n < size s) :> bool.\n\n(*This lemma states that a safe indexed access on a sequence results in a null value if and only if the specified index is greater than or equal to the size of the sequence.*)\nLemma onthNE s n: ~~ onth s n = (size s <= n).\n\n(*This lemma states that if a given index is greater than or equal to the size of a sequence, then attempting a safe access at that index will yield a null value.*)\nLemma onth_default n s : size s <= n -> onth s n = None.\n\n(*This lemma states that accessing an element at a given index in the concatenation of two sequences is resolved by either accessing the element in the first sequence if the index is within its bounds, or by accessing the element in the second sequence at a correspondingly shifted index.*)\nLemma onth_cat s1 s2 n :\n onth (s1 ++ s2) n = if n < size s1 then onth s1 n else onth s2 (n - size s1).\n\n(*This lemma states that when accessing an element at a given index in a sequence composed of a repeated value, the result is that value if the index is within the sequence's length, and a null value otherwise.*)\nLemma onth_nseq x n m : onth (nseq n x) m = if m < n then Some x else None.\n\n(*This lemma states the equivalence of three conditions for two sequences being identical: first, that they are explicitly equal; second, that accessing elements at any index up to the maximum of their lengths yields the same result for both; and third, that accessing elements at any index whatsoever yields the same result for both.*)\nLemma eq_onthP {s1 s2} :\n [<-> s1 = s2;\n forall i : nat, i < maxn (size s1) (size s2) -> onth s1 i = onth s2 i;\n forall i : nat, onth s1 i = onth s2 i].\n\n(*This lemma states that if two sequences produce the same optional value for every possible natural number index, then the sequences themselves must be equal.*)\nLemma eq_from_onth [s1 s2 : seq T] :\n (forall i : nat, onth s1 i = onth s2 i) -> s1 = s2.\n\n(*This lemma states that if two sequences produce the same optional value for every index up to the maximum of their respective lengths, then the sequences must be equal.*)\nLemma eq_from_onth_le [s1 s2 : seq T] :\n (forall i : nat, i < maxn (size s1) (size s2) -> onth s1 i = onth s2 i) ->\n s1 = s2.\n\nEnd onth.\n\n(*This lemma states that accessing an element at a specific index in a sequence that has been transformed by a function is equivalent to first accessing the element at that index in the original sequence and then applying the function to the resulting optional value.*)\nLemma onth_map {T S} n (s : seq T) (f : T -> S) :\n onth (map f s) n = omap f (onth s n).\n\n(*This lemma states that for an injective function, if accessing an index in a transformed sequence yields the image of an element, then accessing the same index in the original sequence must yield the original element.*)\nLemma inj_onth_map {T S} n (s : seq T) (f : T -> S) x :\n injective f -> onth (map f s) n = Some (f x) -> onth s n = Some x.\n\nSection onthEqType.\n\nVariables T : eqType.\n\nImplicit Types x y z : T.\nImplicit Types i m n : nat.\nImplicit Type s : seq T.\n\n(*This lemma states that an element is a member of a sequence if and only if there exists some index at which a safe access returns that specific element.*)\nLemma onthP s x : reflect (exists i, onth s i = Some x) (x \\in s).\n\n(*This lemma states that an element is not a member of a given sequence if and only if for every valid index, the element at that index is not equal to the given element.*)\nLemma onthPn s x : reflect (forall i, onth s i != Some x) (x \\notin s).\n\n(*This lemma states that for any sequence with unique elements, if the elements at two valid indices are identical, then those indices must also be identical.*)\nLemma onth_inj s n m : uniq s -> minn m n < size s ->\n onth s n = onth s m -> n = m.\n\nEnd onthEqType.\n\nArguments onthP {T s x}.\nArguments onthPn {T s x}.\nArguments onth_nth {T}.\nArguments onth_inj {T}.\n\n(*This notation provides a sequence comprehension syntax to create a new sequence by applying a given expression to each element of an input sequence.*)\nNotation \"[ 'seq' E | i <- s ]\" := (map (fun i => E) s)\n (i binder, format \"[ '[hv' 'seq' E '/ ' | i <- s ] ']'\") : seq_scope.\n\n(*This notation provides a sequence comprehension syntax to create a new sequence by first filtering an input sequence based on a given condition, and then applying a specified expression to each of the remaining elements.*)\nNotation \"[ 'seq' E | i <- s & C ]\" := [seq E | i <- [seq i <- s | C]]\n (i binder,\n format \"[ '[hv' 'seq' E '/ ' | i <- s '/ ' & C ] ']'\") : seq_scope.\n\n(*This notation provides a sequence comprehension syntax for creating a new sequence by applying an expression to each element of an input sequence, where the resulting sequence is explicitly specified to have elements of a given type. This notation is for parsing only.*)\nNotation \"[ 'seq' E : R | i <- s ]\" := (@map _ R (fun i => E) s)\n (i binder, only parsing) : seq_scope.\n\n(*This notation provides a sequence comprehension syntax for creating a new sequence by filtering an input sequence with a condition and then applying an expression to each element, where the resulting sequence is explicitly specified to have elements of a given type. This notation is for parsing only.*)\nNotation \"[ 'seq' E : R | i <- s & C ]\" := [seq E : R | i <- [seq i <- s | C]]\n (i binder, only parsing) : seq_scope.\n\n(*This lemma states that filtering a sequence with a predicate is equivalent to first mapping the predicate over the sequence to produce a boolean mask, and then applying that mask to the original sequence.*)\nLemma filter_mask T a (s : seq T) : filter a s = mask (map a s) s.\n\n(*This lemma states that if a predicate holds for every element in a sequence, then there exists a corresponding sequence of elements of the dependent sum type, from which the original sequence can be reconstructed by extracting the values.*)\nLemma all_sigP T a (s : seq T) : all a s -> {s' : seq (sig a) | s = map sval s'}.\n\nSection MiscMask.\n\n(*This lemma states that the number of elements satisfying a given predicate in a sequence after applying a boolean mask is less than or equal to the number of such elements in the original sequence.*)\nLemma leq_count_mask T (P : {pred T}) m s : count P (mask m s) <= count P s.\n\nVariable (T : eqType).\nImplicit Types (s : seq T) (m : bitseq).\n\n(*This lemma states that for a sequence with unique elements, applying a boolean mask is equivalent to filtering the original sequence to keep only those elements that are members of the resulting masked sequence.*)\nLemma mask_filter s m : uniq s -> mask m s = [seq i <- s | i \\in mask m s].\n\n(*This lemma states that if a sequence is a subsequence of another, then the count of elements satisfying any given predicate in the first sequence is less than or equal to the count of such elements in the second sequence.*)\nLemma leq_count_subseq P s1 s2 : subseq s1 s2 -> count P s1 <= count P s2.\n\n(*This lemma states that for any two sequences, the multiplicity of every element in the first sequence being less than or equal to its multiplicity in the second sequence is equivalent to the existence of a boolean mask of the same size as the second sequence, such that the first sequence is a permutation of the result of applying this mask to the second sequence.*)\nLemma count_maskP s1 s2 :\n (forall x, count_mem x s1 <= count_mem x s2) <->\n exists2 m : bitseq, size m = size s2 & perm_eq s1 (mask m s2).\n\n(*This lemma states that for any two sequences, the condition that the multiplicity of every element in the first sequence is less than or equal to its multiplicity in the second is equivalent to the existence of a third sequence that is both a subsequence of the second sequence and a permutation of the first.*)\nLemma count_subseqP s1 s2 :\n (forall x, count_mem x s1 <= count_mem x s2) <->\n exists2 s, subseq s s2 & perm_eq s1 s.\n\nEnd MiscMask.\n\nSection FilterSubseq.\n\nVariable T : eqType.\nImplicit Types (s : seq T) (a : pred T).\n\n(*This lemma states that for any sequence and any predicate, the sequence resulting from filtering the original sequence with the predicate is a subsequence of the original sequence.*)\nLemma filter_subseq a s : subseq (filter a s) s.\n\n(*This lemma states that a boolean value indicating whether a first sequence is a subsequence of a filtered second sequence is equal to the boolean conjunction of two conditions: first, that a given predicate holds for all elements of the first sequence, and second, that the first sequence is a subsequence of the second, unfiltered sequence.*)\nLemma subseq_filter s1 s2 a :\n subseq s1 (filter a s2) = all a s1 && subseq s1 s2.\n\n(*This lemma states that if a sequence `s2` contains unique elements, then another sequence `s1` is a subsequence of `s2` if and only if `s1` is identical to the sequence obtained by filtering `s2` to keep only the elements that are members of `s1`.*)\nLemma subseq_uniqP s1 s2 :\n uniq s2 -> reflect (s1 = filter [in s1] s2) (subseq s1 s2).\n\n(*This lemma states that if a sequence is formed by concatenating a sequence `s3`, a pivot element `x`, and another sequence `s4`, and all elements in the resulting sequence are unique, then a sequence formed by `s1` followed by `x` and `s2` is a subsequence of the first sequence if and only if `s1` is a subsequence of `s3` and `s2` is a subsequence of `s4`.*)\nLemma uniq_subseq_pivot x (s1 s2 s3 s4 : seq T) (s := s3 ++ x :: s4) :\n uniq s -> subseq (s1 ++ x :: s2) s = (subseq s1 s3 && subseq s2 s4).\n\n(*This lemma states that if a sequence is a subsequence of another, then there exists a third sequence such that the second sequence is a permutation of the first sequence concatenated with the third sequence.*)\nLemma perm_to_subseq s1 s2 :\n subseq s1 s2 -> {s3 | perm_eq s2 (s1 ++ s3)}.\n\n(*This lemma states that the operation of removing the first occurrence of an element from a sequence is a homomorphism with respect to the subsequence relation; that is, if one sequence is a subsequence of another, then removing an element from the first results in a subsequence of the sequence obtained by removing the same element from the second.*)\nLemma subseq_rem x : {homo rem x : s1 s2 / @subseq T s1 s2}.\n\nEnd FilterSubseq.\n\nArguments subseq_uniqP [T s1 s2].\n\nSection EqMap.\n\nVariables (n0 : nat) (T1 : eqType) (x1 : T1).\nVariables (T2 : eqType) (x2 : T2) (f : T1 -> T2).\nImplicit Type s : seq T1.\n\n(*This lemma states that if an element is a member of a sequence, then applying a function to that element yields a result that is a member of the sequence obtained by mapping the function over the original sequence.*)\nLemma map_f s x : x \\in s -> f x \\in map f s.\n\n(*This lemma states that an element is a member of a sequence created by mapping a function over an original sequence if and only if there exists an element in the original sequence that maps to it under the function.*)\nLemma mapP s y : reflect (exists2 x, x \\in s & y = f x) (y \\in map f s).\n\n(*This lemma states that a sequence `s'` is a multiset-subset of the sequence resulting from mapping a function `f` over a sequence `s` if and only if there exists a sequence `t` whose elements are all members of `s`, such that `s'` is exactly the result of mapping `f` over `t`.*)\nLemma subset_mapP (s : seq T1) (s' : seq T2) :\n {subset s' <= map f s} <-> exists2 t, all (mem s) t & s' = map f t.\n\n(*This lemma states that if the sequence resulting from mapping a function over an original sequence contains no duplicate elements, then the original sequence must also contain no duplicate elements.*)\nLemma map_uniq s : uniq (map f s) -> uniq s.\n\n(*This lemma states that if a function is injective on the elements of a given sequence, then the property of containing unique elements holds for the sequence resulting from mapping the function if and only if it holds for the original sequence.*)\nLemma map_inj_in_uniq s : {in s &, injective f} -> uniq (map f s) = uniq s.\n\n(*This lemma states that the mapping operation preserves the subsequence relation; that is, if one sequence is a subsequence of another, then mapping a function over the first sequence results in a subsequence of the sequence obtained by mapping the same function over the second.*)\nLemma map_subseq s1 s2 : subseq s1 s2 -> subseq (map f s1) (map f s2).\n\n(*This lemma states that if a function is injective on the members of a sequence and an element is present in that sequence, then finding the index of the function's application to the element in the mapped sequence and using that index to access an element in the original sequence will retrieve the original element.*)\nLemma nth_index_map s x0 x :\n {in s &, injective f} -> x \\in s -> nth x0 s (index (f x) (map f s)) = x.\n\n(*This lemma states that the sequence mapping operation is homomorphic with respect to the permutation equivalence relation, meaning if two sequences are permutations of each other, their images under the mapping of a function will also be permutations of each other.*)\nLemma perm_map s t : perm_eq s t -> perm_eq (map f s) (map f t).\n\n(*This lemma states that the sequence mapping operation preserves the multiset-subset relation; if the multiset of elements in a first sequence is a subset of the multiset of elements in a second sequence, then the same relation holds for the sequences obtained after mapping a function over them.*)\nLemma sub_map s1 s2 : {subset s1 <= s2} -> {subset map f s1 <= map f s2}.\n\n(*This lemma states that if two sequences are composed of the same set of elements, irrespective of order or multiplicity, then the two sequences resulting from mapping a function over them will also be composed of the same set of elements.*)\nLemma eq_mem_map s1 s2 : s1 =i s2 -> map f s1 =i map f s2.\n\nHypothesis Hf : injective f.\n\n(*This lemma states that if a function is injective, then the result of applying the function to an element is a member of the mapped sequence if and only if the original element is a member of the original sequence.*)\nLemma mem_map s x : (f x \\in map f s) = (x \\in s).\n\n(*This lemma states that for an injective function, the index of an element in a sequence is the same as the index of its image in the sequence resulting from mapping the function over the original sequence.*)\nLemma index_map s x : index (f x) (map f s) = index x s.\n\n(*This lemma states that mapping an injective function over a sequence preserves the property of having unique elements; the resulting sequence has unique elements if and only if the original sequence does.*)\nLemma map_inj_uniq s : uniq (map f s) = uniq s.\n\n(*This lemma states that for an injective function, removing duplicate elements from a sequence that has been transformed by the function is equivalent to first removing duplicates from the original sequence and then applying the map.*)\nLemma undup_map_inj s : undup (map f s) = map f (undup s).\n\n(*This lemma states that if mapping an injective function over two sequences results in new sequences that are permutations of each other, then the original sequences must also be permutations of each other.*)\nLemma perm_map_inj s t : perm_eq (map f s) (map f t) -> perm_eq s t.\n\nEnd EqMap.\n\nArguments mapP {T1 T2 f s y}.\nArguments subset_mapP {T1 T2}.\n\n(*This lemma asserts the existence of a function that transforms a given sequence into another specified sequence, provided that the original sequence contains unique elements and both sequences have the same length.*)\nLemma map_of_seq (T1 : eqType) T2 (s : seq T1) (fs : seq T2) (y0 : T2) :\n {f | uniq s -> size fs = size s -> map f s = fs}.\n\nSection MapComp.\n\nVariable S T U : Type.\n\n(*This lemma states that mapping the identity function over a sequence results in the original sequence unchanged.*)\nLemma map_id (s : seq T) : map id s = s.\n\n(*This lemma states that if two functions are extensionally equal, then mapping these functions over any sequence will also produce extensionally equal sequence-transforming functions.*)\nLemma eq_map (f g : S -> T) : f =1 g -> map f =1 map g.\n\n(*This lemma states that mapping a composition of two functions over a sequence is equivalent to first mapping the second function, and then mapping the first function over the resulting sequence.*)\nLemma map_comp (f : T -> U) (g : S -> T) s : map (f \\o g) s = map f (map g s).\n\n(*This lemma states that if one function is a right inverse for another, then the operation of mapping the first function over a sequence is a right inverse for the operation of mapping the second function over a sequence.*)\nLemma mapK (f : S -> T) (g : T -> S) : cancel f g -> cancel (map f) (map g).\n\n(*This lemma states that if a function cancels another function on a given predicate, then mapping the first function will cancel mapping the second function for all sequences whose elements satisfy that predicate.*)\nLemma mapK_in (A : {pred S}) (f : S -> T) (g : T -> S) :\n {in A, cancel f g} -> {in [pred s | all [in A] s], cancel (map f) (map g)}.\n\nEnd MapComp.\n\n(*This lemma states that mapping two functions over a sequence yields the same resulting sequence if and only if the two functions are equal for all elements present in the original sequence.*)\nLemma eq_in_map (S : eqType) T (f g : S -> T) (s : seq S) :\n {in s, f =1 g} <-> map f s = map g s.\n\n(*This lemma states that if a function behaves as the identity function for all elements within a given sequence, then mapping that function over the sequence results in the original sequence.*)\nLemma map_id_in (T : eqType) f (s : seq T) : {in s, f =1 id} -> map f s = s.\n\nSection Pmap.\n\nVariables (aT rT : Type) (f : aT -> option rT) (g : rT -> aT).\n\n(*This function, known as a partial map, applies a function that returns an optional value to each element of a sequence and constructs a new sequence containing only the values from the successful applications.*)\nFixpoint pmap s :=\n if s is x :: s' then let r := pmap s' in oapp (cons^~ r) r (f x) else [::].\n\n(*This lemma states that if a function partially inverts a second function, then partially mapping the first function over a sequence that has been transformed by the second function recovers the original sequence.*)\nLemma map_pK : pcancel g f -> cancel (map g) pmap.\n\n(*This lemma states that the size of a sequence produced by a partial map is equal to the number of elements in the original sequence for which the applied function returned a successful result.*)\nLemma size_pmap s : size (pmap s) = count [eta f] s.\n\n(*This lemma states that wrapping each element of a sequence from a partial map in 'Some' is equivalent to first filtering the original sequence to keep only elements for which the partial function succeeds, and then mapping the function over a filtered sequence.*)\nLemma pmapS_filter s : map some (pmap s) = map f (filter [eta f] s).\n\nHypothesis fK : ocancel f g.\n\n(*This lemma states that, given two functions that are partial inverses of each other, mapping the second function over the result of partially mapping the first function is equivalent to filtering the original sequence to keep only elements for which the first function yields a value.*)\nLemma pmap_filter s : map g (pmap s) = filter [eta f] s.\n\n(*This lemma states that applying a partial map over the concatenation of two sequences is equivalent to concatenating the results of applying the partial map to each sequence individually.*)\nLemma pmap_cat s t : pmap (s ++ t) = pmap s ++ pmap t.\n\n(*This lemma states that checking if a predicate holds for all elements of a sequence produced by a partial map is equivalent to checking that for every element of the original sequence, either the partial function fails or the predicate holds for its result.*)\nLemma all_pmap (p : pred rT) s :\n all p (pmap s) = all [pred i | oapp p true (f i)] s.\n\nEnd Pmap.\n\n(*This lemma states that if two partial functions are equal for all elements present in a given sequence, then applying a partial map with either function to that sequence produces the same result.*)\nLemma eq_in_pmap (aT : eqType) rT (f1 f2 : aT -> option rT) s :\n {in s, f1 =1 f2} -> pmap f1 s = pmap f2 s.\n\n(*This lemma states that if two partial functions are extensionally equal, then the corresponding partial map operations are also extensionally equal, producing the same output sequence for any given input sequence.*)\nLemma eq_pmap aT rT (f1 f2 : aT -> option rT) :\n f1 =1 f2 -> pmap f1 =1 pmap f2.\n\nSection EqPmap.\n\nVariables (aT rT : eqType) (f : aT -> option rT) (g : rT -> aT).\n\n(*This lemma states that an element is a member of the sequence resulting from a partial map if and only if the 'Some' of that element is a member of the sequence resulting from mapping the same partial function over the original sequence.*)\nLemma mem_pmap s u : (u \\in pmap f s) = (Some u \\in map f s).\n\nHypothesis fK : ocancel f g.\n\n(*This lemma states that, under a partial cancellation condition between two functions, an element is present in the sequence resulting from the partial map of the first function if and only if the image of that element under the second function is present in the original sequence.*)\nLemma can2_mem_pmap : pcancel g f -> forall s u, (u \\in pmap f s) = (g u \\in s).\n\n(*This lemma states that for an injective partial function, if the original sequence contains unique elements, then the sequence resulting from the partial map will also contain unique elements.*)\nLemma pmap_uniq s : uniq s -> uniq (pmap f s).\n\n(*This lemma states that if two sequences are permutations of each other, then the sequences resulting from applying a partial map to each of them will also be permutations of each other.*)\nLemma perm_pmap s t : perm_eq s t -> perm_eq (pmap f s) (pmap f t).\n\nEnd EqPmap.\n\nSection PmapSub.\n\nVariables (T : Type) (p : pred T) (sT : subType p).\n\n(*This lemma states that the size of the sequence obtained by partially mapping the subtype inclusion function over a sequence is equal to the count of elements in the original sequence that satisfy the subtype's predicate.*)\nLemma size_pmap_sub s : size (pmap (insub : T -> option sT) s) = count p s.\n\nEnd PmapSub.\n\nSection EqPmapSub.\n\nVariables (T : eqType) (p : pred T) (sT : subEqType p).\n\n(*This definition creates a local alias for the `insub` function, which attempts to cast an element of a general type into a subtype, returning an optional value.*)\nLet insT : T -> option sT := insub.\n\n(*This lemma states that an element of a subtype is a member of the sequence produced by partially mapping the subtype inclusion function if and only if the underlying value of that subtype element is a member of the original sequence.*)\nLemma mem_pmap_sub s u : (u \\in pmap insT s) = (val u \\in s).\n\n(*This lemma states that if a sequence consists of unique elements, then the sequence of subtype elements obtained by partially mapping the subtype inclusion function over it will also consist of unique elements.*)\nLemma pmap_sub_uniq s : uniq s -> uniq (pmap insT s).\n\nEnd EqPmapSub.\n\n(*This function generates a sequence of a given length containing consecutive natural numbers, starting from a specified initial number.*)\nFixpoint iota m n := if n is n'.+1 then m :: iota m.+1 n' else [::].\n\n(*This lemma states that the size of the sequence of consecutive natural numbers starting from a given number is equal to the specified length.*)\nLemma size_iota m n : size (iota m n) = n.\n\n(*This lemma states that a sequence of consecutive natural numbers of a length equal to the sum of two numbers is equivalent to the concatenation of two smaller such sequences: the first having a length equal to the first number and the original starting point, and the second having a length equal to the second number and starting where the first sequence concluded.*)\nLemma iotaD m n1 n2 : iota m (n1 + n2) = iota m n1 ++ iota (m + n1) n2.\n\n(*This lemma states that creating a sequence of consecutive natural numbers starting from the sum of two numbers is equivalent to creating a sequence starting from the second number and then adding the first number to each element.*)\nLemma iotaDl m1 m2 n : iota (m1 + m2) n = map (addn m1) (iota m2 n).\n\n(*This lemma states that for any given valid index, the element at that index in a sequence of consecutive natural numbers starting from a given number is equal to the starting number plus the index.*)\nLemma nth_iota p m n i : i < n -> nth p (iota m n) i = m + i.\n\n(*This lemma provides an equivalence for membership of a natural number in a sequence of consecutive natural numbers: a number is in the sequence if and only if it is greater than or equal to the starting number and strictly less than the starting number plus the length of the sequence.*)\nLemma mem_iota m n i : (i \\in iota m n) = (m <= i < m + n).\n\n(*This lemma states that a sequence of consecutive natural numbers generated from a starting point contains no duplicate elements.*)\nLemma iota_uniq m n : uniq (iota m n).\n\n(*This lemma states that taking a specified number of initial elements from a sequence of consecutive natural numbers is equivalent to generating a new sequence of consecutive numbers with the same start, but with a length equal to the minimum of the specified number and the original sequence's length.*)\nLemma take_iota k m n : take k (iota m n) = iota m (minn k n).\n\n(*This lemma states that removing a specified number of initial elements from a sequence of consecutive natural numbers results in a new sequence of consecutive numbers that starts at the original start plus the number of removed elements, and has a length equal to the original length minus the number of removed elements.*)\nLemma drop_iota k m n : drop k (iota m n) = iota (m + k) (n - k).\n\n(*This lemma states that filtering a sequence of consecutive natural numbers to keep only those elements strictly less than the sum of the starting number and a given bound results in a new sequence of consecutive numbers starting at the same point, with a length equal to that bound, provided the bound does not exceed the original sequence's length.*)\nLemma filter_iota_ltn m n j : j <= n ->\n [seq i <- iota m n | i < m + j] = iota m j.\n\n(*This lemma states that filtering a sequence of consecutive natural numbers to keep only those elements less than or equal to the sum of the starting number and a given bound results in a new sequence of consecutive numbers starting at the same point, with a length equal to that bound plus one, provided the bound is strictly less than the original sequence's length.*)\nLemma filter_iota_leq n m j : j < n ->\n [seq i <- iota m n | i <= m + j] = iota m j.+1.\n\nSection MakeSeq.\n\nVariables (T : Type) (x0 : T).\n\n(*This definition constructs a finite sequence of a given length by applying a specified function from natural numbers to elements of a given type to each natural number from zero up to the length minus one.*)\nDefinition mkseq f n : seq T := map f (iota 0 n).\n\n(*This lemma states that the size of a sequence constructed by applying a function to a range of natural numbers is equal to the specified length of that range.*)\nLemma size_mkseq f n : size (mkseq f n) = n.\n\n(*This lemma provides a recursive characterization for constructing a sequence, stating that creating a sequence of a certain length plus one is equivalent to creating a sequence of that certain length and then appending the result of applying the generating function to that length.*)\nLemma mkseqS f n :\n mkseq f n.+1 = rcons (mkseq f n) (f n).\n\n(*This lemma states that if two functions from natural numbers to a generic type produce the same output for every input, then the finite sequences of any given length generated from these functions will also be identical.*)\nLemma eq_mkseq f g : f =1 g -> mkseq f =1 mkseq g.\n\n(*This lemma states that for a valid index, the element at that index in a sequence constructed by applying a function to a range of natural numbers is equal to the function applied to that index.*)\nLemma nth_mkseq f n i : i < n -> nth x0 (mkseq f n) i = f i.\n\n(*This lemma states that any given finite sequence is equal to a new sequence constructed by applying the element-accessor function of the original sequence to the natural numbers from zero up to its size minus one.*)\nLemma mkseq_nth s : mkseq (nth x0 s) (size s) = s.\n\n(*This variant type defines a property for a finite sequence, which holds if the sequence can be expressed as the result of mapping a generating function over a sequence of consecutive natural numbers starting from zero.*)\nVariant mkseq_spec s : seq T -> Type :=\n(**)\n| MapIota n f : s = mkseq f n -> mkseq_spec s (mkseq f n).\n\n(*This lemma states that every finite sequence satisfies the property that it can be represented as the result of mapping a generating function over a sequence of consecutive natural numbers.*)\nLemma mkseqP s : mkseq_spec s s.\n\n(*This lemma states that the sequence formed by applying the element-accessor function of a given sequence to the natural numbers from zero up to a specified bound minus one is identical to the prefix of the original sequence of length equal to that bound, provided the bound does not exceed the size of the original sequence.*)\nLemma map_nth_iota0 s i :\n i <= size s -> [seq nth x0 s j | j <- iota 0 i] = take i s.\n\n(*This lemma states that the sequence formed by applying the element-accessor function of a given sequence to a range of consecutive natural numbers is equivalent to a sub-sequence of the original sequence. This sub-sequence is obtained by first dropping a number of initial elements equal to the start of the range, and then taking a number of elements equal to the length of the range, provided this operation is valid given the sequence's size.*)\nLemma map_nth_iota s i j : j <= size s - i ->\n [seq nth x0 s k | k <- iota i j] = take j (drop i s).\n\nEnd MakeSeq.\n\nSection MakeEqSeq.\n\nVariable T : eqType.\n\n(*This lemma establishes a logical equivalence, stating that a finite sequence generated by applying a function over an initial range of natural numbers has unique elements if and only if the function is injective on that same range.*)\nLemma mkseq_uniqP (f : nat -> T) n :\n reflect {in gtn n &, injective f} (uniq (mkseq f n)).\n\n(*This lemma states that if a function from natural numbers to a given type is injective, then any sequence generated by applying this function to a range of natural numbers will contain no duplicate elements.*)\nLemma mkseq_uniq (f : nat -> T) n : injective f -> uniq (mkseq f n).\n\n(*This lemma establishes an equivalence for sequence permutation: two sequences are permutations of each other if and only if the first sequence can be constructed by reordering the elements of the second sequence according to some permutation of its indices.*)\nLemma perm_iotaP {s t : seq T} x0 (It := iota 0 (size t)) :\n reflect (exists2 Is, perm_eq Is It & s = map (nth x0 t) Is) (perm_eq s t).\n\nEnd MakeEqSeq.\n\nArguments perm_iotaP {T s t}.\n\nSection FoldRight.\n\nVariables (T : Type) (R : Type) (f : T -> R -> R) (z0 : R).\n\n(*This fixpoint defines a right-fold operation, which processes a finite sequence from right to left by recursively applying a given binary function to each element and an accumulator, starting with an initial value for the empty sequence.*)\nFixpoint foldr s := if s is x :: s' then f x (foldr s') else z0.\n\nEnd FoldRight.\n\nSection FoldRightComp.\n\nVariables (T1 T2 : Type) (h : T1 -> T2).\nVariables (R : Type) (f : T2 -> R -> R) (z0 : R).\n\n(*This lemma states that applying a right-fold to the concatenation of two sequences is equivalent to first folding over the second sequence with an initial value, and then using that result as the initial value for a fold over the first sequence.*)\nLemma foldr_cat s1 s2 : foldr f z0 (s1 ++ s2) = foldr f (foldr f z0 s2) s1.\n\n(*This lemma states that performing a right-fold on a sequence with an element appended to its end is equivalent to performing a right-fold on the original sequence, using as the initial value the result of applying the folding function to the appended element and the original initial value.*)\nLemma foldr_rcons s x : foldr f z0 (rcons s x) = foldr f (f x z0) s.\n\n(*This lemma states that performing a right-fold over a sequence that has been transformed by a mapping function is equivalent to performing a right-fold over the original sequence using a new folding function that incorporates the mapping.*)\nLemma foldr_map s : foldr f z0 (map h s) = foldr (fun x z => f (h x) z) z0 s.\n\nEnd FoldRightComp.\n\n(*This definition computes the sum of all natural numbers in a finite sequence by folding over the sequence with the addition operation, starting from zero.*)\nDefinition sumn := foldr addn 0.\n\n(*This lemma states that the sum of a sequence formed by prepending a specified number of copies of a given natural number to another sequence is equal to the product of the number and the count, plus the sum of the original sequence.*)\nLemma sumn_ncons x n s : sumn (ncons n x s) = x * n + sumn s.\n\n(*This lemma states that the sum of a sequence consisting of a specified number of repetitions of a single natural number is equal to the product of that number and the count of repetitions.*)\nLemma sumn_nseq x n : sumn (nseq n x) = x * n.\n\n(*This lemma states that the sum of the elements in the concatenation of two sequences of natural numbers is equal to the sum of the sums of the elements in each individual sequence.*)\nLemma sumn_cat s1 s2 : sumn (s1 ++ s2) = sumn s1 + sumn s2.\n\n(*This lemma states that summing a sequence of natural numbers generated by applying a boolean predicate to each element of another sequence, where true maps to one and false to zero, is equivalent to counting the number of elements in the original sequence that satisfy the predicate.*)\nLemma sumn_count T (a : pred T) s : sumn [seq a i : nat | i <- s] = count a s.\n\n(*This lemma states that the sum of the elements in a sequence of natural numbers with a new natural number appended to the end is equal to the sum of the elements in the original sequence plus the appended number.*)\nLemma sumn_rcons s n : sumn (rcons s n) = sumn s + n.\n\n(*This lemma states that if two sequences of natural numbers are permutations of each other, then the sum of their elements is equal.*)\nLemma perm_sumn s1 s2 : perm_eq s1 s2 -> sumn s1 = sumn s2.\n\n(*This lemma states that the sum of the elements in a sequence of natural numbers remains unchanged after the sequence is cyclically rotated by any number of positions.*)\nLemma sumn_rot s n : sumn (rot n s) = sumn s.\n\n(*This lemma states that the sum of the elements in a sequence of natural numbers is equal to the sum of the elements in the reversed sequence.*)\nLemma sumn_rev s : sumn (rev s) = sumn s.\n\n(*This lemma establishes the equivalence between the sum of elements in a sequence of natural numbers being zero and the sequence itself being composed exclusively of zeros.*)\nLemma natnseq0P s : reflect (s = nseq (size s) 0) (sumn s == 0).\n\n(*This lemma provides a formula for the sum of a sequence of natural numbers after updating an element at a given index. The new sum is calculated by taking the original sum, adding the new value, subtracting the old value if the index was within the sequence bounds, and accounting for any default padding values added if the index was out of bounds.*)\nLemma sumn_set_nth s x0 n x :\n sumn (set_nth x0 s n x) =\n sumn s + x - (nth x0 s n) * (n < size s) + x0 * (n - size s).\n\n(*This lemma states that when an element of a sequence of natural numbers is updated at an index that is within the bounds of the sequence, the new sum of the sequence's elements is equal to the original sum plus the new value minus the original value at that index.*)\nLemma sumn_set_nth_ltn s x0 n x : n < size s ->\n sumn (set_nth x0 s n x) = sumn s + x - nth x0 s n.\n\n(*This lemma provides a simplified formula for the sum of a sequence of natural numbers after updating an element using a default value of zero for out-of-bounds access. The new sum is the original sum plus the new value minus the value that was previously at the target index, which is zero if the index was out-of-bounds.*)\nLemma sumn_set_nth0 s n x : sumn (set_nth 0 s n x) = sumn s + x - nth 0 s n.\n\nSection FoldLeft.\n\nVariables (T R : Type) (f : R -> T -> R).\n\n(*This function defines a left-associative fold, which iterates through a sequence from left to right, applying a given binary function to an accumulator and each element of the sequence in turn. The process starts with an initial value for the accumulator.*)\nFixpoint foldl z s := if s is x :: s' then foldl (f z x) s' else z.\n\n(*This lemma states that performing a left-associative fold over a reversed sequence is equivalent to performing a right-associative fold over the original sequence, using a binary function with its arguments swapped.*)\nLemma foldl_rev z s : foldl z (rev s) = foldr (fun x z => f z x) z s.\n\n(*This lemma states that a left-associative fold over the concatenation of two sequences is equivalent to first folding over the first sequence, and then using that result as the initial value to fold over the second sequence.*)\nLemma foldl_cat z s1 s2 : foldl z (s1 ++ s2) = foldl (foldl z s1) s2.\n\n(*This lemma states that a left-associative fold over a sequence with an element appended to its end is equivalent to first folding over the initial sequence and then applying the binary function to the result and the appended element.*)\nLemma foldl_rcons z s x : foldl z (rcons s x) = f (foldl z s) x.\n\nEnd FoldLeft.\n\nSection Folds.\n\nVariables (T : Type) (f : T -> T -> T).\n\nHypotheses (fA : associative f) (fC : commutative f).\n\n(*This lemma states that for a binary operation that is both associative and commutative, performing a left-associative fold or a right-associative fold over a sequence with the same initial value yields the same result.*)\nLemma foldl_foldr x0 l : foldl f x0 l = foldr f x0 l.\n\nEnd Folds.\n\nSection Scan.\n\nVariables (T1 : Type) (x1 : T1) (T2 : Type) (x2 : T2).\nVariables (f : T1 -> T1 -> T2) (g : T1 -> T2 -> T1).\n\n(*This function generates a new sequence by applying a binary function to adjacent pairs of elements. It processes a given sequence by using an initial value as the first element of the first pair, and subsequently using each element of the sequence as the first element of the next pair.*)\nFixpoint pairmap x s := if s is y :: s' then f x y :: pairmap y s' else [::].\n\n(*This lemma states that the length of a sequence generated by the pairmap function is equal to the length of the original input sequence.*)\nLemma size_pairmap x s : size (pairmap x s) = size s.\n\n(*This lemma states that applying the pairmap function to the concatenation of two sequences is equivalent to concatenating the result of pairmap on the first sequence with the result of pairmap on the second sequence, where the latter is initialized with the last element of the first sequence.*)\nLemma pairmap_cat x s1 s2 :\n pairmap x (s1 ++ s2) = pairmap x s1 ++ pairmap (last x s1) s2.\n\n(*This lemma states that for any valid index, the element at that index in the sequence produced by pairmap is the result of applying its binary function to the elements at the same and the next index of the original sequence, which has been prepended with the initial value.*)\nLemma nth_pairmap s n : n < size s ->\n forall x, nth x2 (pairmap x s) n = f (nth x1 (x :: s) n) (nth x1 s n).\n\n(*This function defines a left-associative scan, which generates a sequence of the successive accumulated values that result from applying a binary function to an initial value and each element of an input sequence, in order from left to right.*)\nFixpoint scanl x s :=\n if s is y :: s' then let x' := g x y in x' :: scanl x' s' else [::].\n\n(*This lemma states that the length of the sequence produced by a left-associative scan is equal to the length of the input sequence.*)\nLemma size_scanl x s : size (scanl x s) = size s.\n\n(*This lemma states that performing a left-associative scan over the concatenation of two sequences is equivalent to concatenating the scan of the first sequence with the scan of the second, where the scan of the second sequence is initialized with the final accumulated value from processing the first sequence.*)\nLemma scanl_cat x s1 s2 :\n scanl x (s1 ++ s2) = scanl x s1 ++ scanl (foldl g x s1) s2.\n\n(*This lemma states that a left-associative scan of a sequence with a new element appended to its end is equal to the scan of the original sequence with one final accumulated value appended, which is the result of folding over the entire new sequence.*)\nLemma scanl_rcons x s1 y :\n scanl x (rcons s1 y) = rcons (scanl x s1) (foldl g x (rcons s1 y)).\n\n(*This lemma states that any element in the sequence of intermediate accumulated values produced by a left scan, including the initial value, is equal to the result of a left fold over the corresponding prefix of the original input sequence.*)\nLemma nth_cons_scanl s n : n <= size s ->\n forall x, nth x1 (x :: scanl x s) n = foldl g x (take n s).\n\n(*This lemma states that for any valid index, the element at that index in the sequence produced by a left scan is equal to the result of a left fold over the prefix of the input sequence that includes all elements up to that index.*)\nLemma nth_scanl s n : n < size s ->\n forall x, nth x1 (scanl x s) n = foldl g x (take n.+1 s).\n\n(*This lemma states that if a function `g` is a left inverse to a function `f` for corresponding states, then the `scanl` function built from `g` is a left inverse to the `pairmap` function built from `f`.*)\nLemma scanlK :\n (forall x, cancel (g x) (f x)) -> forall x, cancel (scanl x) (pairmap x).\n\n(*This lemma states that if a function `f` is a left inverse to a function `g` for corresponding states, then the `pairmap` function built from `f` is a left inverse to the `scanl` function built from `g`.*)\nLemma pairmapK :\n (forall x, cancel (f x) (g x)) -> forall x, cancel (pairmap x) (scanl x).\n\nEnd Scan.\n\nPrenex Implicits mask map pmap foldr foldl scanl pairmap.\n\nSection Zip.\n\nVariables (S T : Type) (r : S -> T -> bool).\n\n(*This function takes two sequences and combines them into a single sequence of pairs. Each pair contains the elements from the same position in the input sequences, and the resulting sequence is truncated to the length of the shorter input sequence.*)\nFixpoint zip (s : seq S) (t : seq T) {struct t} :=\n match s, t with\n | x :: s', y :: t' => (x, y) :: zip s' t'\n | _, _ => [::]\n end.\n\n(*This definition specifies a function that takes a sequence of pairs and produces a new sequence containing only the first component of each pair.*)\nDefinition unzip1 := map (@fst S T).\n(*This definition specifies a function that takes a sequence of pairs and produces a new sequence containing only the second component of each pair.*)\nDefinition unzip2 := map (@snd S T).\n\n(*This function checks if a given binary relation holds for all corresponding pairs of elements in two finite sequences. It returns true if and only if both sequences have the same length and the relation is true for each element pair, and false otherwise.*)\nFixpoint all2 s t :=\n match s, t with\n | [::], [::] => true\n | x :: s, y :: t => r x y && all2 s t\n | _, _ => false\n end.\n\n(*This lemma states that zipping the two sequences of components obtained by unzipping a sequence of pairs results in the original sequence of pairs.*)\nLemma zip_unzip s : zip (unzip1 s) (unzip2 s) = s.\n\n(*This lemma states that if the length of a first finite sequence is less than or equal to the length of a second finite sequence, then extracting the sequence of first components from the result of zipping the two sequences yields the original first sequence.*)\nLemma unzip1_zip s t : size s <= size t -> unzip1 (zip s t) = s.\n\n(*This lemma states that if the length of a second finite sequence is less than or equal to the length of a first finite sequence, then extracting the sequence of second components from the result of zipping the two sequences yields the original second sequence.*)\nLemma unzip2_zip s t : size t <= size s -> unzip2 (zip s t) = t.\n\n(*This lemma states that if the length of a first finite sequence is less than or equal to the length of a second finite sequence, then the length of the sequence formed by zipping them is equal to the length of the first sequence.*)\nLemma size1_zip s t : size s <= size t -> size (zip s t) = size s.\n\n(*This lemma states that if the length of a second finite sequence is less than or equal to the length of a first finite sequence, then the length of the sequence formed by zipping them is equal to the length of the second sequence.*)\nLemma size2_zip s t : size t <= size s -> size (zip s t) = size t.\n\n(*This lemma states that the length of the finite sequence created by zipping two sequences is the minimum of their respective lengths.*)\nLemma size_zip s t : size (zip s t) = minn (size s) (size t).\n\n(*This lemma states that if two initial finite sequences have the same length, zipping their concatenations with two other sequences is equivalent to concatenating the results of zipping the initial sequences and the other sequences separately.*)\nLemma zip_cat s1 s2 t1 t2 :\n size s1 = size t1 -> zip (s1 ++ s2) (t1 ++ t2) = zip s1 t1 ++ zip s2 t2.\n\n(*This lemma states that, given two finite sequences of equal length, the element at a given index in their zipped sequence is a pair formed by the elements at that same index in the original sequences. If the index is out of bounds, a default pair is returned.*)\nLemma nth_zip x y s t i :\n size s = size t -> nth (x, y) (zip s t) i = (nth x s i, nth y t i).\n\n(*This lemma states that accessing the element at a given index in the sequence formed by zipping two sequences results in a pair of elements from the original sequences at that index if the index is within the bounds of the zipped sequence; otherwise, it returns a given default pair.*)\nLemma nth_zip_cond p s t i :\n nth p (zip s t) i\n = (if i < size (zip s t) then (nth p.1 s i, nth p.2 t i) else p).\n\n(*This lemma states that for two finite sequences of equal length, zipping the sequences that result from appending a new element to each is equivalent to appending a pair of these new elements to the zipped sequence of the original sequences.*)\nLemma zip_rcons s t x y :\n size s = size t -> zip (rcons s x) (rcons t y) = rcons (zip s t) (x, y).\n\n(*This lemma states that for two finite sequences of equal length, reversing their zipped sequence is equivalent to zipping their reversed versions.*)\nLemma rev_zip s t : size s = size t -> rev (zip s t) = zip (rev s) (rev t).\n\n(*This lemma provides an equivalent characterization for checking if a binary relation holds for all corresponding pairs of elements in two finite sequences. It asserts that this is true if and only if the sequences have equal length and the relation holds for every pair in the zipped sequence.*)\nLemma all2E s t :\n all2 s t = (size s == size t) && all [pred xy | r xy.1 xy.2] (zip s t).\n\n(*This lemma states that zipping two finite sequences, which are themselves the results of applying two different functions to the same initial sequence, yields a sequence of pairs where each pair is the result of applying the two functions to the corresponding element of the initial sequence.*)\nLemma zip_map I f g (s : seq I) :\n zip (map f s) (map g s) = [seq (f i, g i) | i <- s].\n\n(*This lemma states that for two finite sequences of equal length, taking the first components of a sequence of elements selected by index from their zipped version is equivalent to taking the elements at those same indices directly from the first original sequence.*)\nLemma unzip1_map_nth_zip x y s t l :\n size s = size t -> \n unzip1 [seq nth (x, y) (zip s t) i | i <- l] = [seq nth x s i | i <- l].\n\n(*This lemma states that for two finite sequences of equal length, taking the second components of a sequence of elements selected by index from their zipped version is equivalent to taking the elements at those same indices directly from the second original sequence.*)\nLemma unzip2_map_nth_zip x y s t l :\n size s = size t -> \n unzip2 [seq nth (x, y) (zip s t) i | i <- l] = [seq nth y t i | i <- l].\n\nEnd Zip.\n\n(*This lemma states that if the first input sequence to a zip operation contains no duplicate elements, then the resulting sequence of pairs will also contain no duplicate elements.*)\nLemma zip_uniql (S T : eqType) (s : seq S) (t : seq T) : \n uniq s -> uniq (zip s t).\n\n(*This lemma states that if the second input sequence to a zip operation contains no duplicate elements, then the resulting sequence of pairs will also contain no duplicate elements.*)\nLemma zip_uniqr (S T : eqType) (s : seq S) (t : seq T) : \n uniq t -> uniq (zip s t).\n\n(*This lemma states that if two finite sequences of pairs, each formed by zipping two sequences, are permutations of each other, then the sequences of pairs formed by swapping the components within each pair are also permutations of each other.*)\nLemma perm_zip_sym (S T : eqType) (s1 s2 : seq S) (t1 t2 : seq T) : \n perm_eq (zip s1 t1) (zip s2 t2) -> perm_eq (zip t1 s1) (zip t2 s2).\n\n(*This lemma states that if two finite sequences of pairs are permutations of each other, and both were formed by zipping sequences of equal length, then their respective first-component sequences are also permutations of each other.*)\nLemma perm_zip1 {S T : eqType} (t1 t2 : seq T) (s1 s2 : seq S): \n size s1 = size t1 -> size s2 = size t2 -> \n perm_eq (zip s1 t1) (zip s2 t2) -> perm_eq s1 s2.\n\n(*This lemma states that if two finite sequences of pairs are permutations of each other, and both were formed by zipping sequences of equal length, then their respective second-component sequences are also permutations of each other.*)\nLemma perm_zip2 {S T : eqType} (s1 s2 : seq S) (t1 t2 : seq T) :\n size s1 = size t1 -> size s2 = size t2 ->\n perm_eq (zip s1 t1) (zip s2 t2) -> perm_eq t1 t2.\n\nPrenex Implicits zip unzip1 unzip2 all2.\n\n(*This lemma states that two finite sequences are equal if and only if they have the same length and all their corresponding elements are pairwise equal.*)\nLemma eqseq_all (T : eqType) (s t : seq T) : (s == t) = all2 eq_op s t.\n\n(*This lemma states that two finite sequences, generated by mapping two different functions over a common source sequence, are equal if and only if the two functions produce an equal result for every element in the source sequence.*)\nLemma eq_map_all I (T : eqType) (f g : I -> T) (s : seq I) :\n (map f s == map g s) = all [pred xy | xy.1 == xy.2] [seq (f i, g i) | i <- s].\n\nSection Flatten.\n\nVariable T : Type.\nImplicit Types (s : seq T) (ss : seq (seq T)).\n\n(*This definition specifies a function that combines a finite sequence of sequences into a single sequence by concatenating them in order.*)\nDefinition flatten := foldr cat (Nil T).\n(*This definition specifies a function that computes the shape of a sequence of sequences by returning a sequence of natural numbers, where each number is the length of the corresponding inner sequence.*)\nDefinition shape := map (@size T).\n(*This function reconstructs a nested sequence structure by taking a flat sequence and a sequence of lengths, called a shape. It successively splits the flat sequence into segments corresponding to the given lengths.*)\nFixpoint reshape sh s :=\n if sh is n :: sh' then take n s :: reshape sh' (drop n s) else [::].\n\n(*This definition provides a function to calculate the linear index within a flattened sequence that corresponds to a given 'row' and 'column' index in a nested sequence structure, based on the structure's shape. The 'row' index specifies which inner sequence to access, and the 'column' index specifies the position within that inner sequence.*)\nDefinition flatten_index sh r c := sumn (take r sh) + c.\n(*This definition computes the outer index, or row index, within a reshaped structure, given a shape sequence and an index from the original flattened sequence.*)\nDefinition reshape_index sh i := find (pred1 0) (scanl subn i.+1 sh).\n(*This definition computes the inner index, or column offset, within a sub-sequence of a reshaped structure, given a shape sequence and an index from the original flattened sequence.*)\nDefinition reshape_offset sh i := i - sumn (take (reshape_index sh i) sh).\n\n(*This lemma states that the total number of elements in a flattened sequence of sequences is equal to the sum of the lengths of all the individual inner sequences.*)\nLemma size_flatten ss : size (flatten ss) = sumn (shape ss).\n\n(*This lemma states that flattening the concatenation of two sequences of sequences yields the same result as concatenating the flattened versions of each sequence of sequences individually.*)\nLemma flatten_cat ss1 ss2 : flatten (ss1 ++ ss2) = flatten ss1 ++ flatten ss2.\n\n(*This lemma states that the number of inner sequences in a reshaped structure is equal to the length of the provided shape sequence.*)\nLemma size_reshape sh s : size (reshape sh s) = size sh.\n\n(*This lemma states that the n-th inner sequence of a reshaped sequence can be obtained by dropping a number of elements from the original flat sequence equal to the sum of the lengths of the preceding shapes, and then taking a number of elements equal to the n-th length specified in the shape sequence.*)\nLemma nth_reshape (sh : seq nat) l n :\n nth [::] (reshape sh l) n = take (nth 0 sh n) (drop (sumn (take n sh)) l).\n\n(*This lemma states that reshaping a flattened sequence of sequences using its original shape sequence restores the original sequence of sequences.*)\nLemma flattenK ss : reshape (shape ss) (flatten ss) = ss.\n\n(*This lemma states that if a sequence has a length less than or equal to the total size specified by a shape sequence, then flattening the sequence after it has been reshaped will yield the original sequence.*)\nLemma reshapeKr sh s : size s <= sumn sh -> flatten (reshape sh s) = s.\n\n(*This lemma states that if a sequence has a length greater than or equal to the total size specified by a shape sequence, then the shape of the reshaped sequence will be identical to the given shape sequence.*)\nLemma reshapeKl sh s : size s >= sumn sh -> shape (reshape sh s) = sh.\n\n(*This lemma states that flattening a sequence of sequences, to which another sequence has been appended at the end, is equivalent to appending that sequence to the flattened result of the original sequence of sequences.*)\nLemma flatten_rcons ss s : flatten (rcons ss s) = flatten ss ++ s.\n\n(*This lemma states that flattening a sequence of singleton sequences, where each singleton contains one element from an original sequence, recovers the original sequence.*)\nLemma flatten_seq1 s : flatten [seq [:: x] | x <- s] = s.\n\n(*This lemma states that counting the elements that satisfy a given predicate in a flattened sequence of sequences is equivalent to summing the counts of such elements within each of the individual inner sequences.*)\nLemma count_flatten ss P :\n count P (flatten ss) = sumn [seq count P x | x <- ss].\n\n(*This lemma states that filtering a flattened sequence of sequences with a predicate is equivalent to first filtering each inner sequence with that predicate and then flattening the resulting sequence of filtered sequences.*)\nLemma filter_flatten ss (P : pred T) :\n filter P (flatten ss) = flatten [seq filter P i | i <- ss].\n\n(*This lemma states that reversing a flattened sequence of sequences is equivalent to applying a reverse operation to each inner sequence, then reversing the order of the resulting inner sequences, and finally flattening the result.*)\nLemma rev_flatten ss :\n rev (flatten ss) = flatten (rev (map rev ss)).\n\n(*This lemma states that the i-th element of the shape sequence of a sequence of sequences, using a default value of zero, is equal to the size of the i-th inner sequence, which defaults to an empty sequence.*)\nLemma nth_shape ss i : nth 0 (shape ss) i = size (nth [::] ss i).\n\n(*This lemma states that the shape of a reversed sequence of sequences is the reverse of the shape of the original sequence of sequences.*)\nLemma shape_rev ss : shape (rev ss) = rev (shape ss).\n\n(*This lemma states that two sequences of sequences are equal if their flattened forms are equal and their shape sequences are also equal.*)\nLemma eq_from_flatten_shape ss1 ss2 :\n flatten ss1 = flatten ss2 -> shape ss1 = shape ss2 -> ss1 = ss2.\n\n(*This lemma states that, provided a sequence has a length exactly equal to the total size specified by a shape sequence, reversing the reshaped sequence is equivalent to reshaping the reversed sequence with the reversed shape and then mapping a reverse operation over the resulting sequence of sequences.*)\nLemma rev_reshape sh s :\n size s = sumn sh -> rev (reshape sh s) = map rev (reshape (rev sh) (rev s)).\n\n(*This lemma states that if a sequence's length is the sum of a total shape size and an additional length, then reshaping the sequence with a shape extended by that additional length is equivalent to appending the tail of the sequence to the result of reshaping its head with the original shape.*)\nLemma reshape_rcons s sh n (m := sumn sh) :\n m + n = size s ->\n reshape (rcons sh n) s = rcons (reshape sh (take m s)) (drop m s).\n\n(*This lemma asserts that if a given inner index is valid for its corresponding outer index within a given shape, then the computed flattened index will be less than the total size specified by the shape sequence.*)\nLemma flatten_indexP sh r c :\n c < nth 0 sh r -> flatten_index sh r c < sumn sh.\n\n(*This lemma states that if a given index is less than the total size specified by a shape sequence, then the computed outer index for reshaping will be less than the length of the shape sequence itself.*)\nLemma reshape_indexP sh i : i < sumn sh -> reshape_index sh i < size sh.\n\n(*This lemma states that if a given index is less than the total size specified by a shape sequence, then the computed inner offset for reshaping will be less than the length of the sub-sequence corresponding to its computed outer index.*)\nLemma reshape_offsetP sh i :\n i < sumn sh -> reshape_offset sh i < nth 0 sh (reshape_index sh i).\n\n(*This lemma states that converting a flattened index into its corresponding outer and inner indices and then converting them back to a flattened index yields the original flattened index.*)\nLemma reshape_indexK sh i :\n flatten_index sh (reshape_index sh i) (reshape_offset sh i) = i.\n\n(*This lemma states that, for a valid pair of outer and inner indices, converting them to a flattened index and then computing the outer index from that flattened index returns the original outer index.*)\nLemma flatten_indexKl sh r c :\n c < nth 0 sh r -> reshape_index sh (flatten_index sh r c) = r.\n\n(*This lemma states that, for a valid pair of outer and inner indices, converting them to a flattened index and then computing the inner offset from that flattened index returns the original inner offset.*)\nLemma flatten_indexKr sh r c :\n c < nth 0 sh r -> reshape_offset sh (flatten_index sh r c) = c.\n\n(*This lemma states that the i-th element of a flattened sequence of sequences is equal to the element at a specific inner offset within a specific inner sequence, where both the inner sequence's index and the inner offset are determined by the index i and the shape of the original structure.*)\nLemma nth_flatten x0 ss i (r := reshape_index (shape ss) i) :\n nth x0 (flatten ss) i = nth x0 (nth [::] ss r) (reshape_offset (shape ss) i).\n\n(*This lemma states that the comparison of two indices in a flattened sequence is equivalent to the lexicographical comparison of their corresponding pairs of outer and inner indices in the reshaped structure.*)\nLemma reshape_leq sh i1 i2\n (r1 := reshape_index sh i1) (c1 := reshape_offset sh i1)\n (r2 := reshape_index sh i2) (c2 := reshape_offset sh i2) :\n (i1 <= i2) = ((r1 < r2) || ((r1 == r2) && (c1 <= c2))).\n\nEnd Flatten.\n\nPrenex Implicits flatten shape reshape.\n\n(*This lemma states that applying a function to each element of a flattened sequence of sequences is equivalent to first applying the function to every element within each inner sequence and then flattening the resulting structure.*)\nLemma map_flatten S T (f : T -> S) ss :\n map f (flatten ss) = flatten (map (map f) ss).\n\n(*This lemma states that flattening a sequence composed of singletons, where each singleton is the result of applying a function to an element of an original sequence, is equivalent to simply mapping that function over the original sequence.*)\nLemma flatten_map1 (S T : Type) (f : S -> T) s :\n flatten [seq [:: f x] | x <- s] = map f s.\n\n(*This lemma states that, for any positive natural number, removing duplicates from a sequence formed by flattening a structure of multiple copies of a given sequence is equivalent to removing duplicates from the original sequence itself.*)\nLemma undup_flatten_nseq n (T : eqType) (s : seq T) : 0 < n ->\n undup (flatten (nseq n s)) = undup s.\n\n(*This lemma states that the sum of all natural numbers in a flattened sequence of sequences is equal to the sum of the individual sums of each inner sequence.*)\nLemma sumn_flatten (ss : seq (seq nat)) :\n sumn (flatten ss) = sumn (map sumn ss).\n\n(*This lemma states that applying a function to each element within each inner sequence of a reshaped sequence is equivalent to first applying the function to all elements of the original flat sequence and then reshaping the result.*)\nLemma map_reshape T S (f : T -> S) sh s :\n map (map f) (reshape sh s) = reshape sh (map f s).\n\nSection EqFlatten.\n\nVariables S T : eqType.\n\n(*This lemma provides a boolean reflection of the property that an element belongs to a flattened sequence of sequences if and only if there exists an inner sequence containing that element.*)\nLemma flattenP (A : seq (seq T)) x :\n reflect (exists2 s, s \\in A & x \\in s) (x \\in flatten A).\n\nArguments flattenP {A x}.\n\n(*This lemma provides a boolean reflection of the property that an element belongs to the flattened sequence resulting from applying a sequence-producing function to each element of an input sequence, if and only if there is an element in the input sequence that maps to an inner sequence containing the target element.*)\nLemma flatten_mapP (A : S -> seq T) s y :\n reflect (exists2 x, x \\in s & y \\in A x) (y \\in flatten (map A s)).\n\n(*This lemma states that if two sequences of sequences are permutations of each other, then their corresponding flattened sequences are also permutations of each other.*)\nLemma perm_flatten (ss1 ss2 : seq (seq T)) :\n perm_eq ss1 ss2 -> perm_eq (flatten ss1) (flatten ss2).\n\nEnd EqFlatten.\n\nArguments flattenP {T A x}.\nArguments flatten_mapP {S T A s y}.\n\n(*A notation for creating a flattened sequence by iterating over two input sequences. For each element from the first sequence and each element from the second sequence, an expression is computed and all results are collected into a single, flat sequence.*)\nNotation \"[ 'seq' E | x <- s , y <- t ]\" :=\n (flatten [seq [seq E | y <- t] | x <- s])\n (x binder, y binder,\n format \"[ '[hv' 'seq' E '/ ' | x <- s , '/ ' y <- t ] ']'\")\n : seq_scope.\n(*A notation for creating a flattened sequence of a specified type by iterating over two input sequences. For each element from the first sequence and each element from the second sequence, an expression is computed and all results are collected into a single, flat sequence of the specified type.*)\nNotation \"[ 'seq' E : R | x <- s , y <- t ]\" :=\n (flatten [seq [seq E : R | y <- t] | x <- s])\n (x binder, y binder, only parsing) : seq_scope.\n\nSection PrefixSuffixInfix.\n\nVariables T : eqType.\nImplicit Type s : seq T.\n\n(*This definition recursively checks if a given finite sequence is a prefix of another finite sequence, meaning the second sequence starts with all the elements of the first in the same order.*)\nFixpoint prefix s1 s2 {struct s2} :=\n if s1 isn't x :: s1' then true else\n if s2 isn't y :: s2' then false else\n (x == y) && prefix s1' s2'.\n\n(*This lemma states that a finite sequence is a prefix of another if and only if taking a number of elements from the start of the second sequence, equal to the length of the first, results in a sequence identical to the first.*)\nLemma prefixE s1 s2 : prefix s1 s2 = (take (size s1) s2 == s1).\n\n(*This lemma states that any finite sequence is a prefix of itself, establishing the reflexivity of the prefix relation.*)\nLemma prefix_refl s : prefix s s. \n\n(*This lemma states that a finite sequence is a prefix of the empty sequence if and only if that sequence is itself empty.*)\nLemma prefixs0 s : prefix s [::] = (s == [::]). \n\n(*This lemma states that the empty sequence is a prefix of any finite sequence.*)\nLemma prefix0s s : prefix [::] s. \n\n(*This lemma states that a non-empty sequence starting with a given element is a prefix of another non-empty sequence if and only if their first elements are equal and the remainder of the first sequence is a prefix of the remainder of the second.*)\nLemma prefix_cons s1 s2 x y :\n prefix (x :: s1) (y :: s2) = (x == y) && prefix s1 s2.\n\n(*This lemma states that given two pairs of concatenated finite sequences where the first parts have equal length, the first concatenated sequence is a prefix of the second if and only if their first parts are identical and the second part of the first sequence is a prefix of the second part of the second sequence.*)\nLemma prefix_catr s1 s2 s1' s3 : size s1 = size s1' ->\n prefix (s1 ++ s2) (s1' ++ s3) = (s1 == s1') && prefix s2 s3.\n\n(*This lemma states that any finite sequence is a prefix of the sequence formed by concatenating it with another finite sequence.*)\nLemma prefix_prefix s1 s2 : prefix s1 (s1 ++ s2).\n\nHint Resolve prefix_prefix : core.\n\n(*This lemma provides a boolean reflection of the property that a finite sequence is a prefix of another if and only if the second sequence can be expressed as the concatenation of the first sequence and some other sequence.*)\nLemma prefixP {s1 s2} :\n reflect (exists s2' : seq T, s2 = s1 ++ s2') (prefix s1 s2).\n\n(*This lemma states that the prefix relation on finite sequences is transitive.*)\nLemma prefix_trans : transitive prefix.\n\n(*This lemma states that a finite sequence is a prefix of a single-element sequence if and only if it is either the empty sequence or the single-element sequence itself.*)\nLemma prefixs1 s x : prefix s [:: x] = (s == [::]) || (s == [:: x]).\n\n(*This lemma states that if the concatenation of two finite sequences is a prefix of a third sequence, then the first of the two concatenated sequences is also a prefix of that third sequence.*)\nLemma catl_prefix s1 s2 s3 : prefix (s1 ++ s3) s2 -> prefix s1 s2.\n\n(*This lemma states that if a finite sequence is a prefix of a second sequence, it is also a prefix of any sequence formed by concatenating the second sequence with a third one.*)\nLemma prefix_catl s1 s2 s3 : prefix s1 s2 -> prefix s1 (s2 ++ s3).\n\n(*This lemma states that any finite sequence is a prefix of the sequence created by appending an element to its end.*)\nLemma prefix_rcons s x : prefix s (rcons s x).\n\n(*This definition states that a finite sequence is a suffix of another if and only if the reversed first sequence is a prefix of the reversed second sequence.*)\nDefinition suffix s1 s2 := prefix (rev s1) (rev s2).\n\n(*This lemma states that a finite sequence is a suffix of another if and only if dropping a number of elements from the start of the second sequence, equal to the difference in their lengths, results in a sequence identical to the first.*)\nLemma suffixE s1 s2 : suffix s1 s2 = (drop (size s2 - size s1) s2 == s1).\n\n(*This lemma states that any finite sequence is a suffix of itself, establishing the reflexivity of the suffix relation.*)\nLemma suffix_refl s : suffix s s.\n\n(*This lemma states that a finite sequence is a suffix of the empty sequence if and only if that sequence is itself empty.*)\nLemma suffixs0 s : suffix s [::] = (s == [::]).\n\n(*This lemma states that the empty sequence is a suffix of any finite sequence.*)\nLemma suffix0s s : suffix [::] s.\n\n(*This lemma states that checking if the reversal of a first finite sequence is a prefix of the reversal of a second is equivalent to checking if the first sequence is a suffix of the second.*)\nLemma prefix_rev s1 s2 : prefix (rev s1) (rev s2) = suffix s1 s2.\n\n(*This lemma states that checking if the reversal of a first finite sequence is a prefix of a second sequence is equivalent to checking if the first sequence is a suffix of the reversal of the second.*)\nLemma prefix_revLR s1 s2 : prefix (rev s1) s2 = suffix s1 (rev s2).\n\n(*This lemma states that checking if the reversal of a first finite sequence is a suffix of the reversal of a second is equivalent to checking if the first sequence is a prefix of the second.*)\nLemma suffix_rev s1 s2 : suffix (rev s1) (rev s2) = prefix s1 s2.\n\n(*This lemma states that checking if the reversal of a first finite sequence is a suffix of a second sequence is equivalent to checking if the first sequence is a prefix of the reversal of the second.*)\nLemma suffix_revLR s1 s2 : suffix (rev s1) s2 = prefix s1 (rev s2).\n\n(*This lemma states that for any two finite sequences, the second sequence is a suffix of the sequence formed by concatenating the first sequence with the second.*)\nLemma suffix_suffix s1 s2 : suffix s2 (s1 ++ s2).\n\nHint Resolve suffix_suffix : core.\n\n(*This lemma provides an equivalence between the boolean check for a suffix and a propositional statement, asserting that one finite sequence is a suffix of another if and only if the second sequence can be expressed as the concatenation of some prefix sequence and the first sequence.*)\nLemma suffixP {s1 s2} :\n reflect (exists s2' : seq T, s2 = s2' ++ s1) (suffix s1 s2).\n\n(*This lemma states that the suffix relation on finite sequences is transitive, meaning if a first sequence is a suffix of a second, and the second is a suffix of a third, then the first is also a suffix of the third.*)\nLemma suffix_trans : transitive suffix.\n\n(*This lemma states that a finite sequence constructed by appending an element to a first base sequence is a suffix of another sequence constructed by appending an element to a second base sequence if and only if the appended elements are equal and the first base sequence is a suffix of the second.*)\nLemma suffix_rcons s1 s2 x y :\n suffix (rcons s1 x) (rcons s2 y) = (x == y) && suffix s1 s2.\n\n(*This lemma asserts that, given two pairs of finite sequences to be concatenated where the second sequence in each pair has the same size, the first concatenated sequence is a suffix of the second if and only if the second components of the concatenations are equal and the first component of the first concatenation is a suffix of the first component of the second.*)\nLemma suffix_catl s1 s2 s3 s3' : size s3 = size s3' ->\n suffix (s1 ++ s3) (s2 ++ s3') = (s3 == s3') && suffix s1 s2.\n\n(*This lemma states that if a finite sequence is a suffix of a second sequence, it is also a suffix of any new sequence formed by concatenating a third sequence to the front of the second sequence.*)\nLemma suffix_catr s1 s2 s3 : suffix s1 s2 -> suffix s1 (s3 ++ s2).\n\n(*This lemma states that if the concatenation of two finite sequences is a suffix of a third sequence, then the second sequence of the concatenation is also a suffix of the third sequence.*)\nLemma catl_suffix s s1 s2 : suffix (s ++ s1) s2 -> suffix s1 s2.\n\n(*This lemma states that a finite sequence is always a suffix of the sequence formed by prepending any single element to it.*)\nLemma suffix_cons s x : suffix s (x :: s).\n\n(*This definition specifies recursively that a first finite sequence is an infix of a second if the second is empty and the first is also empty, or if the second is non-empty and the first is either a prefix of the second or an infix of the tail of the second.*)\nFixpoint infix s1 s2 :=\n if s2 is y :: s2' then prefix s1 s2 || infix s1 s2' else s1 == [::].\n\n(*This definition computes the starting index of the first occurrence of a finite sequence as a contiguous sub-sequence within another. It returns zero if the first sequence is a prefix of the second. If not, it recursively searches the tail of the second sequence, incrementing the index. If the second sequence is exhausted without a match, it returns a value greater than the length of the second sequence.*)\nFixpoint infix_index s1 s2 :=\n if prefix s1 s2 then 0\n else if s2 is y :: s2' then (infix_index s1 s2').+1 else 1.\n\n(*This lemma states that the empty finite sequence is an infix of any finite sequence.*)\nLemma infix0s s : infix [::] s. \n\n(*This lemma states that a finite sequence is an infix of the empty sequence if and only if that sequence is also empty.*)\nLemma infixs0 s : infix s [::] = (s == [::]). \n\n(*This lemma expands the definition of the infix relation, stating that a first finite sequence is an infix of a non-empty second sequence if and only if the first sequence is a prefix of the second, or it is an infix of the tail of the second.*)\nLemma infix_consl s1 y s2 :\n infix s1 (y :: s2) = prefix s1 (y :: s2) || infix s1 s2.\n\n(*This lemma states that the starting index of a finite sequence as an infix of itself is always zero.*)\nLemma infix_indexss s : infix_index s s = 0.\n\n(*This lemma states that the starting index of a first finite sequence within a second is always less than or equal to the size of the second sequence plus one.*)\nLemma infix_index_le s1 s2 : infix_index s1 s2 <= (size s2).+1.\n\n(*This lemma establishes an equivalence between a finite sequence being an infix of another and its computed starting index being within the bounds of the containing sequence's length. Specifically, the infix relation holds if and only if the infix index is less than or equal to the size of the containing sequence.*)\nLemma infixTindex s1 s2 : (infix_index s1 s2 <= size s2) = infix s1 s2.\n\n(*This lemma provides a reflection property, stating that a finite sequence is not an infix of another if and only if its computed starting index is exactly one greater than the size of the sequence being searched.*)\nLemma infixPn s1 s2 :\n reflect (infix_index s1 s2 = (size s2).+1) (~~ infix s1 s2).\n\n(*This lemma states that the starting index of the empty finite sequence as an infix of any other finite sequence is always zero.*)\nLemma infix_index0s s : infix_index [::] s = 0.\n\n(*This lemma states that the starting index of a finite sequence within the empty sequence is one if the sequence is non-empty, and zero if it is empty.*)\nLemma infix_indexs0 s : infix_index s [::] = (s != [::]).\n\n(*This lemma provides an equational characterization of the infix property. It asserts that a first finite sequence is an infix of a second if and only if extracting a sub-sequence from the second, starting at the calculated infix index and having the same length as the first sequence, results in a sequence identical to the first.*)\nLemma infixE s1 s2 : infix s1 s2 =\n (take (size s1) (drop (infix_index s1 s2) s2) == s1).\n\n(*This lemma states that any finite sequence is an infix of itself.*)\nLemma infix_refl s : infix s s.\n\n(*This lemma states that if a finite sequence is a prefix of another, it is also an infix of that sequence.*)\nLemma prefixW s1 s2 : prefix s1 s2 -> infix s1 s2.\n\n(*This lemma states that for any two finite sequences, the first sequence is an infix of their concatenation.*)\nLemma prefix_infix s1 s2 : infix s1 (s1 ++ s2).\n\nHint Resolve prefix_infix : core.\n\n(*This lemma states that for any three finite sequences, the second sequence is an infix of their successive concatenation.*)\nLemma infix_infix s1 s2 s3 : infix s2 (s1 ++ s2 ++ s3).\n\nHint Resolve infix_infix : core.\n\n(*This lemma states that for any two finite sequences, the second sequence is an infix of their concatenation.*)\nLemma suffix_infix s1 s2 : infix s2 (s1 ++ s2).\n\nHint Resolve suffix_infix : core.\n\n(*This lemma provides an equivalence between the boolean check for an infix and a propositional statement, asserting that one finite sequence is an infix of another if and only if the second sequence can be decomposed into the concatenation of some prefix, the first sequence, and some suffix.*)\nLemma infixP {s1 s2} :\n reflect (exists s s' : seq T, s2 = s ++ s1 ++ s') (infix s1 s2).\n\n(*This lemma states that a first finite sequence is an infix of a second if and only if the reverse of the first sequence is an infix of the reverse of the second.*)\nLemma infix_rev s1 s2 : infix (rev s1) (rev s2) = infix s1 s2.\n\n(*This lemma states that if a finite sequence is a suffix of another, it is also an infix of that sequence.*)\nLemma suffixW s1 s2 : suffix s1 s2 -> infix s1 s2.\n\n(*This lemma states that the infix relation on finite sequences is transitive, meaning if a first sequence is an infix of a second, and the second is an infix of a third, then the first is also an infix of the third.*)\nLemma infix_trans : transitive infix.\n\n(*This lemma states that the reverse of a first finite sequence is an infix of a second finite sequence if and only if the first sequence is an infix of the reverse of the second sequence.*)\nLemma infix_revLR s1 s2 : infix (rev s1) s2 = infix s1 (rev s2).\n\n(*This lemma states that a first finite sequence is an infix of a second finite sequence extended by one element at its end, if and only if the first sequence is either a suffix of the extended second sequence or was already an infix of the original second sequence.*)\nLemma infix_rconsl s1 s2 y :\n infix s1 (rcons s2 y) = suffix s1 (rcons s2 y) || infix s1 s2.\n\n(*This lemma states that any finite sequence is an infix of the sequence formed by prepending an element to it.*)\nLemma infix_cons s x : infix s (x :: s).\n\n(*This lemma states that a finite sequence is an infix of a singleton sequence containing a specific element if and only if the sequence is either empty or is the singleton sequence itself.*)\nLemma infixs1 s x : infix s [:: x] = (s == [::]) || (s == [:: x]).\n\n(*This lemma states that if the concatenation of a first finite sequence and a second finite sequence is an infix of a third finite sequence, then the second sequence is also an infix of the third sequence.*)\nLemma catl_infix s s1 s2 : infix (s ++ s1) s2 -> infix s1 s2.\n\n(*This lemma states that if the concatenation of a first finite sequence and a second finite sequence is an infix of a third finite sequence, then the first sequence is also an infix of the third sequence.*)\nLemma catr_infix s s1 s2 : infix (s1 ++ s) s2 -> infix s1 s2.\n\n(*This lemma states that if a finite sequence constructed by prepending an element to a first sequence is an infix of a second sequence constructed by prepending the same element to another sequence, then the first sequence is an infix of the other sequence.*)\nLemma cons2_infix s1 s2 x : infix (x :: s1) (x :: s2) -> infix s1 s2.\n\n(*This lemma states that if a finite sequence constructed by appending an element to a first sequence is an infix of a second sequence constructed by appending the same element to another sequence, then the first sequence is an infix of the other sequence.*)\nLemma rcons2_infix s1 s2 x : infix (rcons s1 x) (rcons s2 x) -> infix s1 s2.\n\n(*This lemma states that if the concatenation of a common prefix sequence with a first sequence is an infix of the concatenation of that same common prefix with a second sequence, then the first sequence is an infix of the second sequence.*)\nLemma catr2_infix s s1 s2 : infix (s ++ s1) (s ++ s2) -> infix s1 s2.\n\n(*This lemma states that if the concatenation of a first sequence with a common suffix sequence is an infix of the concatenation of a second sequence with that same common suffix, then the first sequence is an infix of the second sequence.*)\nLemma catl2_infix s s1 s2 : infix (s1 ++ s) (s2 ++ s) -> infix s1 s2.\n\n(*This lemma states that if a first finite sequence is an infix of a second finite sequence, then the first sequence is also an infix of any sequence formed by concatenating a third sequence before the second sequence.*)\nLemma infix_catl s1 s2 s3 : infix s1 s2 -> infix s1 (s3 ++ s2).\n\n(*This lemma states that if a first finite sequence is an infix of a second finite sequence, then the first sequence is also an infix of any sequence formed by concatenating the second sequence with a third sequence.*)\nLemma infix_catr s1 s2 s3 : infix s1 s2 -> infix s1 (s2 ++ s3).\n\n(*This lemma states that if a first finite sequence is a prefix of a second finite sequence, and the second sequence is an infix of a third finite sequence, then the first sequence is an infix of the third sequence.*)\nLemma prefix_infix_trans s2 s1 s3 :\n prefix s1 s2 -> infix s2 s3 -> infix s1 s3.\n\n(*This lemma states that if a first finite sequence is a suffix of a second finite sequence, and the second sequence is an infix of a third finite sequence, then the first sequence is an infix of the third sequence.*)\nLemma suffix_infix_trans s2 s1 s3 :\n suffix s1 s2 -> infix s2 s3 -> infix s1 s3.\n\n(*This lemma states that if a first finite sequence is an infix of a second finite sequence, and the second sequence is a prefix of a third finite sequence, then the first sequence is an infix of the third sequence.*)\nLemma infix_prefix_trans s2 s1 s3 :\n infix s1 s2 -> prefix s2 s3 -> infix s1 s3.\n\n(*This lemma states that if a first finite sequence is an infix of a second finite sequence, and the second sequence is a suffix of a third finite sequence, then the first sequence is an infix of the third sequence.*)\nLemma infix_suffix_trans s2 s1 s3 :\n infix s1 s2 -> suffix s2 s3 -> infix s1 s3.\n\n(*This lemma states that if a first finite sequence is a prefix of a second finite sequence, and the second sequence is a suffix of a third finite sequence, then the first sequence is an infix of the third sequence.*)\nLemma prefix_suffix_trans s2 s1 s3 :\n prefix s1 s2 -> suffix s2 s3 -> infix s1 s3.\n\n(*This lemma states that if a first finite sequence is a suffix of a second finite sequence, and the second sequence is a prefix of a third finite sequence, then the first sequence is an infix of the third sequence.*)\nLemma suffix_prefix_trans s2 s1 s3 :\n suffix s1 s2 -> prefix s2 s3 -> infix s1 s3.\n\n(*This lemma states that if a first finite sequence is an infix of a second finite sequence, then the first sequence is also a subsequence of the second sequence.*)\nLemma infixW s1 s2 : infix s1 s2 -> subseq s1 s2.\n\n(*This lemma states that if a first finite sequence is an infix of a second finite sequence, then the multiset of elements in the first sequence is a sub-multiset of the elements in the second sequence.*)\nLemma mem_infix s1 s2 : infix s1 s2 -> {subset s1 <= s2}.\n\n(*This lemma states that a singleton sequence containing a specific element is an infix of a second finite sequence if and only if that element is a member of the second sequence.*)\nLemma infix1s s x : infix [:: x] s = (x \\in s).\n\n(*This lemma states that if a singleton sequence containing a specific element is a prefix of a second finite sequence, then that element is a member of the second sequence.*)\nLemma prefix1s s x : prefix [:: x] s -> x \\in s.\n\n(*This lemma states that if a singleton sequence containing a specific element is a suffix of a second finite sequence, then that element is a member of the second sequence.*)\nLemma suffix1s s x : suffix [:: x] s -> x \\in s.\n\n(*This lemma states that any finite sequence is an infix of the sequence formed by appending an element to it.*)\nLemma infix_rcons s x : infix s (rcons s x).\n\n(*This lemma states that if a first finite sequence is an infix of a second finite sequence and all elements in the second sequence are unique, then all elements in the first sequence are also unique.*)\nLemma infix_uniq s1 s2 : infix s1 s2 -> uniq s2 -> uniq s1.\n\n(*This lemma states that if a first finite sequence is a prefix of a second finite sequence and all elements in the second sequence are unique, then all elements in the first sequence are also unique.*)\nLemma prefix_uniq s1 s2 : prefix s1 s2 -> uniq s2 -> uniq s1.\n\n(*This lemma states that if a first finite sequence is a suffix of a second finite sequence and all elements in the second sequence are unique, then all elements in the first sequence are also unique.*)\nLemma suffix_uniq s1 s2 : suffix s1 s2 -> uniq s2 -> uniq s1.\n\n(*This lemma states that for any finite sequence and a natural number, the sequence consisting of the initial elements up to the given number is a prefix of the original sequence.*)\nLemma prefix_take s i : prefix (take i s) s.\n\n(*This lemma states that for any finite sequence and a natural number, the sequence obtained by removing the initial elements up to the given number is a suffix of the original sequence.*)\nLemma suffix_drop s i : suffix (drop i s) s.\n\n(*This lemma states that for any finite sequence and a natural number, the sequence consisting of the initial elements up to the given number is an infix of the original sequence.*)\nLemma infix_take s i : infix (take i s) s.\n\n(*This lemma states that if the sequence resulting from dropping a certain number of initial elements from a given sequence is not a prefix of the original sequence, then the number of elements dropped must have been greater than zero.*)\nLemma prefix_drop_gt0 s i : ~~ prefix (drop i s) s -> i > 0.\n\n(*This lemma states that for any finite sequence and any natural number, the subsequence obtained by removing the first few elements is an infix of the original sequence.*)\nLemma infix_drop s i : infix (drop i s) s.\n\n(*This lemma states that if a sequence beginning with a specific element is an infix of a second sequence, then the singleton sequence containing just that element is also an infix of the second sequence.*)\nLemma consr_infix s1 s2 x : infix (x :: s1) s2 -> infix [:: x] s2.\n\n(*This lemma states that if a sequence formed by prepending an element to a first sequence is an infix of a second sequence, then the first sequence itself is also an infix of the second sequence.*)\nLemma consl_infix s1 s2 x : infix (x :: s1) s2 -> infix s1 s2.\n\n(*This lemma states that if a finite sequence is a prefix of another finite sequence, then its starting index as an infix is zero.*)\nLemma prefix_index s1 s2 : prefix s1 s2 -> infix_index s1 s2 = 0.\n\n(*This lemma states that if a finite sequence is an infix of another finite sequence, its length is less than or equal to the length of the other sequence.*)\nLemma size_infix s1 s2 : infix s1 s2 -> size s1 <= size s2.\n\n(*This lemma states that if a finite sequence is a prefix of another finite sequence, its length is less than or equal to the length of the other sequence.*)\nLemma size_prefix s1 s2 : prefix s1 s2 -> size s1 <= size s2.\n\n(*This lemma states that if a finite sequence is a suffix of another finite sequence, its length is less than or equal to the length of the other sequence.*)\nLemma size_suffix s1 s2 : suffix s1 s2 -> size s1 <= size s2.\n\nEnd PrefixSuffixInfix.\n\nSection AllPairsDep.\n\nVariables (S S' : Type) (T T' : S -> Type) (R : Type).\nImplicit Type f : forall x, T x -> R.\n\n(*This definition constructs a new finite sequence by applying a two-argument function to all pairs of elements, where the first element of each pair comes from an initial sequence and the second element comes from a dependent sequence that is determined by the first element.*)\nDefinition allpairs_dep f s t := [seq f x y | x <- s, y <- t x].\n\n(*This lemma states that the length of the sequence formed by applying a function to all dependent pairs is equal to the sum of the lengths of all the inner, dependent sequences.*)\nLemma size_allpairs_dep f s t :\n size [seq f x y | x <- s, y <- t x] = sumn [seq size (t x) | x <- s].\n\n(*This lemma states that forming all dependent pairs from an empty outer sequence results in an empty sequence.*)\nLemma allpairs0l f t : [seq f x y | x <- [::], y <- t x] = [::].\n\n(*This lemma states that if for every element in an outer sequence, the corresponding inner dependent sequence is empty, then the sequence of all dependent pairs is also empty.*)\nLemma allpairs0r f s : [seq f x y | x <- s, y <- [::]] = [::].\n\n(*This lemma states that if the outer sequence contains a single element, the sequence of all dependent pairs is equivalent to mapping the function over the single corresponding inner sequence.*)\nLemma allpairs1l f x t :\n [seq f x y | x <- [:: x], y <- t x] = [seq f x y | y <- t x].\n\n(*This lemma states that if each inner dependent sequence contains exactly one element, the sequence of all dependent pairs is equivalent to mapping a function over the outer sequence, applying it to each outer element and its corresponding single inner element.*)\nLemma allpairs1r f s y :\n [seq f x y | x <- s, y <- [:: y x]] = [seq f x (y x) | x <- s].\n\n(*This lemma states that generating all dependent pairs from an outer sequence constructed by prepending an element is equivalent to concatenating the sequence of pairs from that first element with the sequence of pairs from the rest of the outer sequence.*)\nLemma allpairs_cons f x s t :\n [seq f x y | x <- x :: s, y <- t x] =\n [seq f x y | y <- t x] ++ [seq f x y | x <- s, y <- t x].\n\n(*This lemma states that if two functions are pointwise equal for all inputs, then the sequences of all dependent pairs generated by applying each of these functions are identical.*)\nLemma eq_allpairs (f1 f2 : forall x, T x -> R) s t :\n (forall x, f1 x =1 f2 x) ->\n [seq f1 x y | x <- s, y <- t x] = [seq f2 x y | x <- s, y <- t x].\n\n(*This lemma states that if two mappings from elements to dependent sequences are identical, then the sequences of all dependent pairs generated using these mappings will also be identical.*)\nLemma eq_allpairsr (f : forall x, T x -> R) s t1 t2 : (forall x, t1 x = t2 x) ->\n [seq f x y | x <- s, y <- t1 x] = [seq f x y | x <- s, y <- t2 x].\n\n(*This lemma states that generating all dependent pairs from the concatenation of two outer sequences is equivalent to concatenating the results of generating pairs from each outer sequence individually.*)\nLemma allpairs_cat f s1 s2 t :\n [seq f x y | x <- s1 ++ s2, y <- t x] =\n [seq f x y | x <- s1, y <- t x] ++ [seq f x y | x <- s2, y <- t x].\n\n(*This lemma states that generating all dependent pairs from an outer sequence formed by appending an element is equivalent to concatenating the pairs from the original sequence with the pairs from the appended element.*)\nLemma allpairs_rcons f x s t :\n [seq f x y | x <- rcons s x, y <- t x] =\n [seq f x y | x <- s, y <- t x] ++ [seq f x y | y <- t x].\n\n(*This lemma provides a fusion rule, stating that creating a sequence of dependent pairs from a mapped outer sequence is equivalent to creating the pairs from the original outer sequence while composing the function and the dependent sequence lookup with the mapping function.*)\nLemma allpairs_mapl f (g : S' -> S) s t :\n [seq f x y | x <- map g s, y <- t x] = [seq f (g x) y | x <- s, y <- t (g x)].\n\n(*This lemma provides a fusion rule, stating that creating a sequence of dependent pairs where each inner sequence is mapped by a function is equivalent to creating the pairs from the original inner sequences and composing the main function with the inner mapping function.*)\nLemma allpairs_mapr f (g : forall x, T' x -> T x) s t :\n [seq f x y | x <- s, y <- map (g x) (t x)] =\n [seq f x (g x y) | x <- s, y <- t x].\n\nEnd AllPairsDep.\n\nArguments allpairs_dep {S T R} f s t /.\n\n(*This lemma states that mapping a function over a sequence of dependent pairs is equivalent to composing that function with the generating function inside the pair creation.*)\nLemma map_allpairs S T R R' (g : R' -> R) f s t :\n map g [seq f x y | x : S <- s, y : T x <- t x] =\n [seq g (f x y) | x <- s, y <- t x].\n\nSection AllPairsNonDep.\n\nVariables (S T R : Type) (f : S -> T -> R).\nImplicit Types (s : seq S) (t : seq T).\n\n(*This definition constructs a new finite sequence by applying a two-argument function to all pairs of elements, where the first element of each pair comes from a first sequence and the second element comes from a second, independent sequence.*)\nDefinition allpairs s t := [seq f x y | x <- s, y <- t].\n\n(*This lemma states that the length of the sequence formed by applying a function to all pairs from two independent sequences is equal to the product of the lengths of the two input sequences.*)\nLemma size_allpairs s t : size [seq f x y | x <- s, y <- t] = size s * size t.\n\nEnd AllPairsNonDep.\n\nArguments allpairs {S T R} f s t /.\n\nSection EqAllPairsDep.\n\nVariables (S : eqType) (T : S -> eqType).\nImplicit Types (R : eqType) (s : seq S) (t : forall x, seq (T x)).\n\n(*This lemma provides a boolean reflection property, stating that an element is a member of a sequence of dependent pairs if and only if it is the result of applying the generating function to some element from the outer sequence and a corresponding element from its dependent inner sequence.*)\nLemma allpairsPdep R (f : forall x, T x -> R) s t (z : R) :\n reflect (exists x y, [/\\ x \\in s, y \\in t x & z = f x y])\n (z \\in [seq f x y | x <- s, y <- t x]).\n\nVariable R : eqType.\nImplicit Type f : forall x, T x -> R.\n\n(*This lemma states that if an element is a member of the outer sequence and a second element is a member of the corresponding inner dependent sequence, then the result of applying the generating function to these two elements is a member of the sequence of all dependent pairs.*)\nLemma allpairs_f_dep f s t x y :\n x \\in s -> y \\in t x -> f x y \\in [seq f x y | x <- s, y <- t x].\n\n(*This lemma states that two sequences of all dependent pairs, generated by two different functions, are equal if and only if for every element in the outer sequence, the two functions produce the same output for all corresponding elements in the inner dependent sequence.*)\nLemma eq_in_allpairs_dep f1 f2 s t :\n {in s, forall x, {in t x, f1 x =1 f2 x}} <->\n [seq f1 x y : R | x <- s, y <- t x] = [seq f2 x y | x <- s, y <- t x].\n\n(*This lemma states that if two outer sequences are permutations of each other, and for any given element its corresponding dependent inner sequences are also permutations of each other, then the two resulting sequences of all dependent pairs are permutations of each other.*)\nLemma perm_allpairs_dep f s1 t1 s2 t2 :\n perm_eq s1 s2 -> {in s1, forall x, perm_eq (t1 x) (t2 x)} ->\n perm_eq [seq f x y | x <- s1, y <- t1 x] [seq f x y | x <- s2, y <- t2 x].\n\n(*This lemma states that if two outer sequences are equivalent as multisets, and for each element the corresponding inner dependent sequences are also equivalent as multisets, then the resulting sequences of all dependent pairs are also equivalent as multisets.*)\nLemma mem_allpairs_dep f s1 t1 s2 t2 :\n s1 =i s2 -> {in s1, forall x, t1 x =i t2 x} ->\n [seq f x y | x <- s1, y <- t1 x] =i [seq f x y | x <- s2, y <- t2 x].\n\n(*This lemma provides conditions for the sequence of all dependent pairs to contain no duplicate elements. It requires that the outer sequence has no duplicates, each inner dependent sequence has no duplicates, and the generating function is injective when applied to the collection of all pairs.*)\nLemma allpairs_uniq_dep f s t (st := [seq Tagged T y | x <- s, y <- t x]) :\n let g (p : {x : S & T x}) : R := f (tag p) (tagged p) in\n uniq s -> {in s, forall x, uniq (t x)} -> {in st &, injective g} ->\n uniq [seq f x y | x <- s, y <- t x].\n\nEnd EqAllPairsDep.\n\nArguments allpairsPdep {S T R f s t z}.\n\nSection MemAllPairs.\n\nVariables (S : Type) (T : S -> Type) (R : eqType).\nImplicit Types (f : forall x, T x -> R) (s : seq S).\n\n(*This lemma asserts a distributivity property up to permutation. It states that generating a sequence of dependent pairs where each inner sequence is a concatenation of two parts produces a sequence that is a permutation of the concatenation of two other sequences: one generated using the first parts of the inner sequences, and one generated using the second parts.*)\nLemma perm_allpairs_catr f s t1 t2 :\n perm_eql [seq f x y | x <- s, y <- t1 x ++ t2 x]\n ([seq f x y | x <- s, y <- t1 x] ++ [seq f x y | x <- s, y <- t2 x]).\n\n(*This lemma states that the multiset of elements obtained by applying a two-argument function to pairs from a sequence and a family of concatenated sequences is the same as the multiset of elements from concatenating the results of applying the function to pairs from the original sequence and each component of the family of sequences.*)\nLemma mem_allpairs_catr f s y0 t :\n [seq f x y | x <- s, y <- y0 x ++ t x] =i\n [seq f x y | x <- s, y <- y0 x] ++ [seq f x y | x <- s, y <- t x].\n\n(*This lemma states that the sequence generated by applying a function to pairs where the first element is from a sequence and the second is from a family of prepended sequences is a permutation of the sequence formed by applying the function to all pairs with the new head elements, concatenated with the sequence generated from the tail sequences.*)\nLemma perm_allpairs_consr f s y0 t :\n perm_eql [seq f x y | x <- s, y <- y0 x :: t x]\n ([seq f x (y0 x) | x <- s] ++ [seq f x y | x <- s, y <- t x]).\n\n(*This lemma states that the multiset of elements generated by applying a function to pairs from a sequence and a family of prepended sequences is identical to the multiset formed by concatenating the results from applying the function to pairs with the new head elements and subsequently to pairs from the tail sequences.*)\nLemma mem_allpairs_consr f s t y0 :\n [seq f x y | x <- s, y <- y0 x :: t x] =i\n [seq f x (y0 x) | x <- s] ++ [seq f x y | x <- s, y <- t x].\n\n(*This lemma states that the sequence generated by applying a function to pairs where the first element is from a sequence and the second is from a family of appended sequences is a permutation of the sequence formed by concatenating the results from the original sequences with the results from the appended elements.*)\nLemma allpairs_rconsr f s y0 t :\n perm_eql [seq f x y | x <- s, y <- rcons (t x) (y0 x)]\n ([seq f x y | x <- s, y <- t x] ++ [seq f x (y0 x) | x <- s]).\n\n(*This lemma states that the multiset of elements generated by applying a function to pairs where the first element is from a sequence and the second is from a family of appended sequences is identical to the multiset obtained by concatenating results from the original sequences with results from the appended elements.*)\nLemma mem_allpairs_rconsr f s t y0 :\n [seq f x y | x <- s, y <- rcons (t x) (y0 x)] =i\n ([seq f x y | x <- s, y <- t x] ++ [seq f x (y0 x) | x <- s]).\n\nEnd MemAllPairs.\n\n(*This lemma provides a reflection property, stating that a given predicate holds for all elements in a sequence generated from all pairs of elements from an outer sequence and a corresponding family of inner sequences, if and only if the predicate holds for the function's result for every pair of elements where the first is in the outer sequence and the second is in its corresponding inner sequence.*)\nLemma all_allpairsP\n (S : eqType) (T : S -> eqType) (R : Type)\n (p : pred R) (f : forall x : S, T x -> R)\n (s : seq S) (t : forall x : S, seq (T x)) :\n reflect (forall (x : S) (y : T x), x \\in s -> y \\in t x -> p (f x y))\n (all p [seq f x y | x <- s, y <- t x]).\n\nArguments all_allpairsP {S T R p f s t}.\n\nSection EqAllPairs.\n\nVariables S T R : eqType.\nImplicit Types (f : S -> T -> R) (s : seq S) (t : seq T).\n\n(*This lemma provides a reflection property, stating that a given element is a member of the sequence generated by applying a function to all pairs from two sequences, if and only if there exists a pair of elements, one from each input sequence, such that applying the function to this pair yields the given element.*)\nLemma allpairsP f s t (z : R) :\n reflect (exists p, [/\\ p.1 \\in s, p.2 \\in t & z = f p.1 p.2])\n (z \\in [seq f x y | x <- s, y <- t]).\n\n(*This lemma states that if an element is a member of a first sequence and another element is a member of a second sequence, then the result of applying a given function to these two elements will be a member of the sequence generated from all pairs of elements from the two input sequences.*)\nLemma allpairs_f f s t x y :\n x \\in s -> y \\in t -> f x y \\in [seq f x y | x <- s, y <- t].\n\n(*This lemma states that two sequences generated by applying two different functions to all pairs of elements from two given input sequences are identical if and only if the two functions produce the same result for all pairs of elements where the first element of the pair is in the first input sequence and the second element is in the second input sequence.*)\nLemma eq_in_allpairs f1 f2 s t :\n {in s & t, f1 =2 f2} <->\n [seq f1 x y : R | x <- s, y <- t] = [seq f2 x y | x <- s, y <- t].\n\n(*This lemma states that if a first pair of input sequences are permutations of a second pair of input sequences, then the sequence generated by applying a function to all pairs from the first pair of sequences is a permutation of the sequence generated from the second pair.*)\nLemma perm_allpairs f s1 t1 s2 t2 :\n perm_eq s1 s2 -> perm_eq t1 t2 ->\n perm_eq [seq f x y | x <- s1, y <- t1] [seq f x y | x <- s2, y <- t2].\n\n(*This lemma states that if two pairs of input sequences contain the same elements as multisets, then the sequences generated by applying a function to all pairs from each pair of input sequences will also contain the same elements as multisets.*)\nLemma mem_allpairs f s1 t1 s2 t2 :\n s1 =i s2 -> t1 =i t2 ->\n [seq f x y | x <- s1, y <- t1] =i [seq f x y | x <- s2, y <- t2].\n\n(*This lemma states that the sequence generated by applying a function to all pairs from two input sequences will contain no duplicate elements if both input sequences are free of duplicates and the function is injective when applied to pairs of elements drawn from the respective input sequences.*)\nLemma allpairs_uniq f s t (st := [seq (x, y) | x <- s, y <- t]) :\n uniq s -> uniq t -> {in st &, injective (uncurry f)} ->\n uniq [seq f x y | x <- s, y <- t].\n\nEnd EqAllPairs.\n\nArguments allpairsP {S T R f s t z}.\nArguments perm_nilP {T s}.\nArguments perm_consP {T x s t}.\n\nSection AllRel.\n\nVariables (T S : Type) (r : T -> S -> bool).\nImplicit Types (x : T) (y : S) (xs : seq T) (ys : seq S).\n\n(*This definition specifies a boolean value that is true if and only if a given binary boolean relation holds for every pair of elements, where the first element is taken from a first sequence and the second element is taken from a second sequence.*)\nDefinition allrel xs ys := all [pred x | all (r x) ys] xs.\n\n(*This lemma states that a binary boolean relation holds for all pairs of elements taken from an empty first sequence and any second sequence.*)\nLemma allrel0l ys : allrel [::] ys. \n\n(*This lemma states that a binary boolean relation holds for all pairs of elements taken from any first sequence and an empty second sequence.*)\nLemma allrel0r xs : allrel xs [::]. \n\n(*This lemma states that a binary boolean relation holds for all pairs from a prepended sequence and a second sequence if and only if the relation holds for all pairs formed by the new head element and the second sequence, and it also holds for all pairs from the original tail sequence and the second sequence.*)\nLemma allrel_consl x xs ys : allrel (x :: xs) ys = all (r x) ys && allrel xs ys.\n\n(*This lemma states that a binary boolean relation holds for all pairs from a first sequence and a prepended second sequence if and only if the relation holds for all pairs formed by elements of the first sequence and the new head of the second, and it also holds for all pairs from the first sequence and the original tail of the second.*)\nLemma allrel_consr xs y ys :\n allrel xs (y :: ys) = all (r^~ y) xs && allrel xs ys.\n\n(*This lemma states that a binary boolean relation holds across two prepended sequences if and only if four conditions are met: the relation holds for the two head elements, the relation holds between the first head and all elements of the second tail, the relation holds between all elements of the first tail and the second head, and the relation holds across the two tail sequences.*)\nLemma allrel_cons2 x y xs ys :\n allrel (x :: xs) (y :: ys) =\n [&& r x y, all (r x) ys, all (r^~ y) xs & allrel xs ys].\n\n(*This lemma states that a binary boolean relation holds between a singleton sequence and a second sequence if and only if the relation holds between the single element of the first sequence and every element of the second sequence.*)\nLemma allrel1l x ys : allrel [:: x] ys = all (r x) ys. \n\n(*This lemma states that a binary boolean relation holds between a first sequence and a singleton sequence if and only if the relation holds between every element of the first sequence and the single element of the second sequence.*)\nLemma allrel1r xs y : allrel xs [:: y] = all (r^~ y) xs.\n\n(*This lemma states that a binary boolean relation holds between a concatenated first sequence and a second sequence if and only if it holds between each of the constituent parts of the first sequence and the second sequence.*)\nLemma allrel_catl xs xs' ys :\n allrel (xs ++ xs') ys = allrel xs ys && allrel xs' ys.\n\n(*This lemma states that a binary boolean relation holds between a first sequence and a concatenated second sequence if and only if it holds between the first sequence and each of the constituent parts of the second sequence.*)\nLemma allrel_catr xs ys ys' :\n allrel xs (ys ++ ys') = allrel xs ys && allrel xs ys'.\n\n(*This lemma states that if a binary boolean relation holds for all pairs of elements from two sequences, then it also holds for all pairs from a subsequence of the first sequence, selected by a boolean mask, and the original second sequence.*)\nLemma allrel_maskl m xs ys : allrel xs ys -> allrel (mask m xs) ys.\n\n(*This lemma states that if a binary boolean relation holds for all pairs of elements from two sequences, then it also holds for all pairs from the original first sequence and a subsequence of the second sequence, selected by a boolean mask.*)\nLemma allrel_maskr m xs ys : allrel xs ys -> allrel xs (mask m ys).\n\n(*This lemma states that if a binary boolean relation holds for all pairs of elements from two sequences, then it also holds for all pairs from a subsequence of the first sequence, filtered by a predicate, and the original second sequence.*)\nLemma allrel_filterl a xs ys : allrel xs ys -> allrel (filter a xs) ys.\n\n(*This lemma states that if a binary boolean relation holds for all pairs of elements from two sequences, then it also holds for all pairs from the original first sequence and a subsequence of the second sequence, filtered by a predicate.*)\nLemma allrel_filterr a xs ys : allrel xs ys -> allrel xs (filter a ys).\n\n(*This lemma states that a binary boolean relation holds for all pairs of elements from two sequences if and only if a boolean test for truth holds for all elements in the sequence of booleans generated by applying the relation to every pair of elements from the two input sequences.*)\nLemma allrel_allpairsE xs ys :\n allrel xs ys = all id [seq r x y | x <- xs, y <- ys].\n\nEnd AllRel.\n\nArguments allrel {T S} r xs ys : simpl never.\nArguments allrel0l {T S} r ys.\nArguments allrel0r {T S} r xs.\nArguments allrel_consl {T S} r x xs ys.\nArguments allrel_consr {T S} r xs y ys.\nArguments allrel1l {T S} r x ys.\nArguments allrel1r {T S} r xs y.\nArguments allrel_catl {T S} r xs xs' ys.\nArguments allrel_catr {T S} r xs ys ys'.\nArguments allrel_maskl {T S} r m xs ys.\nArguments allrel_maskr {T S} r m xs ys.\nArguments allrel_filterl {T S} r a xs ys.\nArguments allrel_filterr {T S} r a xs ys.\nArguments allrel_allpairsE {T S} r xs ys.\n\nNotation all2rel r xs := (allrel r xs xs).\n\n(*This lemma states that if a first binary boolean relation implies a second one for all pairs of elements satisfying given predicates, then for any two sequences whose elements satisfy these respective predicates, if the first relation holds for all pairs from the sequences, the second relation also holds.*)\nLemma sub_in_allrel\n {T S : Type} (P : {pred T}) (Q : {pred S}) (r r' : T -> S -> bool) :\n {in P & Q, forall x y, r x y -> r' x y} ->\n forall xs ys, all P xs -> all Q ys -> allrel r xs ys -> allrel r' xs ys.\n\n(*This lemma states that if a first binary boolean relation implies a second one for all possible pairs of elements, then for any two sequences, if the first relation holds for all pairs from the sequences, the second relation also holds.*)\nLemma sub_allrel {T S : Type} (r r' : T -> S -> bool) :\n (forall x y, r x y -> r' x y) ->\n forall xs ys, allrel r xs ys -> allrel r' xs ys.\n\n(*This lemma asserts that if two binary boolean relations are equivalent for all pairs of elements satisfying given predicates, then for any two sequences whose elements satisfy these respective predicates, the property of the first relation holding for all pairs from the sequences is equivalent to the property of the second relation holding for all pairs.*)\nLemma eq_in_allrel {T S : Type} (P : {pred T}) (Q : {pred S}) r r' :\n {in P & Q, r =2 r'} ->\n forall xs ys, all P xs -> all Q ys -> allrel r xs ys = allrel r' xs ys.\n\n(*This lemma states that if two binary boolean relations are pointwise equal, then the `allrel` predicate, which checks if the relation holds for all pairs of elements from two sequences, is also pointwise equal for any pair of sequences.*)\nLemma eq_allrel {T S : Type} (r r' : T -> S -> bool) :\n r =2 r' -> allrel r =2 allrel r'.\n\n(*This lemma states that checking if a binary boolean relation holds for all pairs of elements between a first and a second sequence is equivalent to checking if the converse of that relation holds for all pairs between the second and the first sequence.*)\nLemma allrelC {T S : Type} (r : T -> S -> bool) xs ys :\n allrel r xs ys = allrel (fun y => r^~ y) ys xs.\n\n(*This lemma states that applying a binary boolean relation between a sequence transformed by a function and a second sequence is equivalent to applying a new relation, which incorporates the function application on its first argument, between the original two sequences.*)\nLemma allrel_mapl {T T' S : Type} (f : T' -> T) (r : T -> S -> bool) xs ys :\n allrel r (map f xs) ys = allrel (fun x => r (f x)) xs ys.\n\n(*This lemma states that applying a binary boolean relation between a first sequence and a second sequence transformed by a function is equivalent to applying a new relation, which incorporates the function application on its second argument, between the original two sequences.*)\nLemma allrel_mapr {T S S' : Type} (f : S' -> S) (r : T -> S -> bool) xs ys :\n allrel r xs (map f ys) = allrel (fun x y => r x (f y)) xs ys.\n\n(*This lemma provides a reflection property for `allrel`. It states that the boolean result of `allrel` on a binary relation and two sequences accurately reflects the proposition that the relation holds for every pair of elements, where the first element is from the first sequence and the second element is from the second sequence.*)\nLemma allrelP {T S : eqType} {r : T -> S -> bool} {xs ys} :\n reflect {in xs & ys, forall x y, r x y} (allrel r xs ys).\n\n(*This lemma states that the `allrel` predicate, when applied with a relation that is always true, will always evaluate to true for any two sequences.*)\nLemma allrelT {T S : Type} (xs : seq T) (ys : seq S) :\n allrel (fun _ _ => true) xs ys = true.\n\n(*This lemma states that applying `allrel` with a relation formed by the boolean conjunction of two other relations is equivalent to taking the boolean conjunction of applying `allrel` with each relation individually.*)\nLemma allrel_relI {T S : Type} (r r' : T -> S -> bool) xs ys :\n allrel (fun x y => r x y && r' x y) xs ys = allrel r xs ys && allrel r' xs ys.\n\n(*This lemma states that the result of `allrel` is unchanged if the first input sequence is reversed, because `allrel` depends only on the set of elements in the sequence, not their order.*)\nLemma allrel_revl {T S : Type} (r : T -> S -> bool) (s1 : seq T) (s2 : seq S) :\n allrel r (rev s1) s2 = allrel r s1 s2.\n\n(*This lemma states that the result of `allrel` is unchanged if the second input sequence is reversed, because `allrel` depends only on the set of elements in the sequence, not their order.*)\nLemma allrel_revr {T S : Type} (r : T -> S -> bool) (s1 : seq T) (s2 : seq S) :\n allrel r s1 (rev s2) = allrel r s1 s2.\n\n(*This lemma states that the result of `allrel` is unchanged if both input sequences are reversed.*)\nLemma allrel_rev2 {T S : Type} (r : T -> S -> bool) (s1 : seq T) (s2 : seq S) :\n allrel r (rev s1) (rev s2) = allrel r s1 s2.\n\n(*This lemma states that if two sequences have the same multiset of elements, the `allrel` predicate will produce the same boolean result when each is used as the first sequence argument with a given binary relation and a second sequence.*)\nLemma eq_allrel_meml {T : eqType} {S} (r : T -> S -> bool) (s1 s1' : seq T) s2 :\n s1 =i s1' -> allrel r s1 s2 = allrel r s1' s2.\n\n(*This lemma states that if two sequences have the same multiset of elements, the `allrel` predicate will produce the same boolean result when each is used as the second sequence argument with a given binary relation and a first sequence.*)\nLemma eq_allrel_memr {T} {S : eqType} (r : T -> S -> bool) s1 (s2 s2' : seq S) :\n s2 =i s2' -> allrel r s1 s2 = allrel r s1 s2'.\n\n(*This lemma states that the result of `allrel` on two pairs of sequences is the same if the sequences in the first pair have the same multiset of elements as their counterparts in the second pair.*)\nLemma eq_allrel_mem2 {T S : eqType} (r : T -> S -> bool)\n (s1 s1' : seq T) (s2 s2' : seq S) :\n s1 =i s1' -> s2 =i s2' -> allrel r s1 s2 = allrel r s1' s2'.\n\nSection All2Rel.\n\nVariable (T : nonPropType) (r : rel T).\nImplicit Types (x y z : T) (xs : seq T).\nHypothesis (rsym : symmetric r).\n\n(*This lemma states that for a symmetric binary relation, applying `all2rel` to a singleton sequence containing one element is equivalent to applying the relation to that element with itself.*)\nLemma all2rel1 x : all2rel r [:: x] = r x x.\n\n(*This lemma states that for a symmetric binary relation, applying `all2rel` to a sequence of two distinct elements is equivalent to the boolean conjunction of the relation applied to the first element with itself, the second with itself, and the first with the second.*)\nLemma all2rel2 x y : all2rel r [:: x; y] = r x x && r y y && r x y.\n\n(*This lemma provides a recursive definition for `all2rel` on a non-empty sequence with a symmetric binary relation. It states that the result is the boolean conjunction of three conditions: the relation holds for the head element with itself, the relation holds between the head element and every element in the tail, and `all2rel` holds for the tail sequence.*)\nLemma all2rel_cons x xs :\n all2rel r (x :: xs) = [&& r x x, all (r x) xs & all2rel r xs].\n\nEnd All2Rel.\n\nSection Pairwise.\n\nVariables (T : Type) (r : T -> T -> bool).\nImplicit Types (x y : T) (xs ys : seq T).\n\n(*This definition specifies a boolean predicate `pairwise` that checks if a given binary relation holds for every pair of elements in a sequence where the first element of the pair appears earlier in the sequence than the second.*)\nFixpoint pairwise xs : bool :=\n if xs is x :: xs then all (r x) xs && pairwise xs else true.\n\n(*This lemma provides the recursive evaluation rule for the `pairwise` predicate on a non-empty sequence. It states that `pairwise` holds if and only if the given relation holds between the head of the sequence and every element of its tail, and `pairwise` also holds for the tail itself.*)\nLemma pairwise_cons x xs : pairwise (x :: xs) = all (r x) xs && pairwise xs.\n\n(*This lemma states that the `pairwise` predicate holds for the concatenation of two sequences if and only if it holds for each sequence individually, and the governing relation also holds for every pair of elements where the first is from the first sequence and the second is from the second sequence.*)\nLemma pairwise_cat xs ys :\n pairwise (xs ++ ys) = [&& allrel r xs ys, pairwise xs & pairwise ys].\n\n(*This lemma describes the behavior of the `pairwise` predicate when an element is appended to a sequence. It holds if and only if the `pairwise` predicate held for the original sequence and the given relation holds for every pair formed by an element from the original sequence and the new final element.*)\nLemma pairwise_rcons xs x :\n pairwise (rcons xs x) = all (r^~ x) xs && pairwise xs.\n\n(*This lemma states that for a sequence of exactly two elements, the `pairwise` predicate is equivalent to applying the underlying binary relation to the first and second elements in that order.*)\nLemma pairwise2 x y : pairwise [:: x; y] = r x y.\n\n(*This lemma states that if the `pairwise` predicate holds for a sequence, it also holds for any subsequence created by applying a boolean mask.*)\nLemma pairwise_mask m xs : pairwise xs -> pairwise (mask m xs).\n\n(*This lemma states that if the `pairwise` predicate holds for a sequence, it will also hold for any subsequence obtained by filtering the original sequence with a predicate.*)\nLemma pairwise_filter a xs : pairwise xs -> pairwise (filter a xs).\n\n(*This lemma provides a reflection property for the `pairwise` predicate. It states that the boolean result of `pairwise` on a sequence is equivalent to the proposition that for any two indices where the first is less than the second, the underlying binary relation holds for the elements of the sequence at those indices.*)\nLemma pairwiseP x0 xs :\n reflect {in gtn (size xs) &, {homo nth x0 xs : i j / i < j >-> r i j}}\n (pairwise xs).\n\n(*This lemma states that for a binary relation that is both reflexive and symmetric, the `pairwise` predicate on a sequence is equivalent to the `all2rel` predicate on the same sequence.*)\nLemma pairwise_all2rel :\n reflexive r -> symmetric r -> forall xs, pairwise xs = all2rel r xs.\n\nEnd Pairwise.\n\nArguments pairwise {T} r xs.\nArguments pairwise_cons {T} r x xs.\nArguments pairwise_cat {T} r xs ys.\nArguments pairwise_rcons {T} r xs x.\nArguments pairwise2 {T} r x y.\nArguments pairwise_mask {T r} m {xs}.\nArguments pairwise_filter {T r} a {xs}.\nArguments pairwiseP {T r} x0 {xs}.\nArguments pairwise_all2rel {T r} r_refl r_sym xs.\n\n(*This lemma states that if a binary relation implies another relation for all elements satisfying a certain predicate, then for any sequence whose elements all satisfy that predicate, if the `pairwise` predicate holds for the first relation, it must also hold for the second.*)\nLemma sub_in_pairwise {T : Type} (P : {pred T}) (r r' : rel T) :\n {in P &, subrel r r'} ->\n forall xs, all P xs -> pairwise r xs -> pairwise r' xs.\n\n(*This lemma states that if a binary relation implies another relation everywhere, then for any sequence, if the `pairwise` predicate holds for the first relation, it must also hold for the second.*)\nLemma sub_pairwise {T : Type} (r r' : rel T) xs :\n subrel r r' -> pairwise r xs -> pairwise r' xs.\n\n(*This lemma states that if two binary relations are pointwise equivalent for all elements satisfying a certain predicate, then for any sequence whose elements all satisfy that predicate, the `pairwise` predicate will yield the same boolean result for both relations.*)\nLemma eq_in_pairwise {T : Type} (P : {pred T}) (r r' : rel T) :\n {in P &, r =2 r'} -> forall xs, all P xs -> pairwise r xs = pairwise r' xs.\n\n(*This lemma states that if two binary relations are pointwise equal, then their corresponding `pairwise` predicates are also pointwise equal for any input sequence.*)\nLemma eq_pairwise {T : Type} (r r' : rel T) :\n r =2 r' -> pairwise r =i pairwise r'.\n\n(*This lemma states that applying the `pairwise` predicate to a sequence transformed by a function is equivalent to applying it to the original sequence with a new relation that is pre-composed with the function on both of its arguments.*)\nLemma pairwise_map {T T' : Type} (f : T' -> T) (r : rel T) xs :\n pairwise r (map f xs) = pairwise (relpre f r) xs.\n\n(*This lemma states that the pairwise property for a combined relation, defined as the logical conjunction of two individual relations, holds for a given finite sequence if and only if the pairwise property holds for each of the individual relations separately over that same sequence.*)\nLemma pairwise_relI {T : Type} (r r' : rel T) (s : seq T) :\n pairwise [rel x y | r x y && r' x y] s = pairwise r s && pairwise r' s.\n\nSection EqPairwise.\n\nVariables (T : eqType) (r : T -> T -> bool).\nImplicit Types (xs ys : seq T).\n\n(*This lemma states that if a finite sequence has the property that a given binary relation holds for all pairs of its elements, then any subsequence of that sequence also has this property.*)\nLemma subseq_pairwise xs ys : subseq xs ys -> pairwise r ys -> pairwise r xs.\n\n(*This lemma states that a finite sequence consists of unique elements if and only if the 'not equal to' relation holds for every pair of elements within that sequence.*)\nLemma uniq_pairwise xs : uniq xs = pairwise [rel x y | x != y] xs.\n\n(*This lemma states that if a binary relation is irreflexive, meaning no element relates to itself, and this relation holds for all pairs of elements in a finite sequence, then all elements in that sequence must be unique.*)\nLemma pairwise_uniq xs : irreflexive r -> pairwise r xs -> uniq xs.\n\n(*This lemma states that for an antisymmetric binary relation, if two finite sequences are permutations of each other and the relation holds pairwise for the elements within each sequence, then the two sequences must be identical.*)\nLemma pairwise_eq : antisymmetric r ->\n forall xs ys, pairwise r xs -> pairwise r ys -> perm_eq xs ys -> xs = ys.\n\n(*This lemma states that if an antisymmetric binary relation holds for all pairs of elements in a given finite sequence, then that relation is also transitive when restricted to the elements present in that sequence.*)\nLemma pairwise_trans s : antisymmetric r ->\n pairwise r s -> {in s & &, transitive r}.\n\nEnd EqPairwise.\n\nArguments subseq_pairwise {T r xs ys}.\nArguments uniq_pairwise {T} xs.\nArguments pairwise_uniq {T r xs}.\nArguments pairwise_eq {T r} r_asym {xs ys}.\n\nSection Permutations.\n\nVariable T : eqType.\nImplicit Types (x : T) (s t : seq T) (bs : seq (T * nat)) (acc : seq (seq T)).\n\n(*This function takes a finite sequence of element-count pairs and an element, and returns an updated sequence of pairs. If the element already exists in the input sequence, its corresponding count is incremented; otherwise, a new pair containing the element and a count of one is added.*)\nFixpoint incr_tally bs x :=\n if bs isn't b :: bs then [:: (x, 1)] else\n if x == b.1 then (x, b.2.+1) :: bs else b :: incr_tally bs x.\n\n(*This definition computes the frequency of each element in a given finite sequence, returning the result as a new sequence of pairs, where each pair consists of a unique element from the input sequence and its corresponding count.*)\nDefinition tally s := foldl incr_tally [::] s.\n\n(*This definition specifies the property of being a well-formed tally for a finite sequence of element-count pairs. A tally is well-formed if all the elements in the pairs are unique and all their corresponding counts are non-zero.*)\nDefinition wf_tally :=\n [qualify a bs : seq (T * nat) | uniq (unzip1 bs) && (0 \\notin unzip2 bs)].\n\n(*This definition reconstructs a finite sequence from a tally, which is a sequence of element-count pairs. It does this by creating a sequence for each pair, containing the element repeated by its count, and then concatenating all these new sequences together.*)\nDefinition tally_seq bs := flatten [seq nseq b.2 b.1 | b <- bs].\n(*A local notation that provides a shorthand for the 'tally_seq' operation, which reconstructs a finite sequence from a tally of element-count pairs.*)\nLocal Notation tseq := tally_seq.\n\n(*This lemma states that the size of a finite sequence reconstructed from an element-count tally is equal to the sum of all the counts in that tally.*)\nLemma size_tally_seq bs : size (tally_seq bs) = sumn (unzip2 bs).\n\n(*This lemma states that the 'tally' operation is a left inverse to the 'tally_seq' operation for any well-formed tally. Applying 'tally' to the sequence generated by 'tally_seq' from a well-formed tally returns the original tally.*)\nLemma tally_seqK : {in wf_tally, cancel tally_seq tally}.\n\n(*This lemma states that the 'incr_tally' function preserves the property of being a well-formed tally. If the input is a well-formed sequence of element-count pairs, the output sequence, after incrementing the count for a given element, will also be well-formed.*)\nLemma incr_tallyP x : {homo incr_tally^~ x : bs / bs \\in wf_tally}.\n\n(*This lemma states that applying the 'tally' operation to any finite sequence always produces a well-formed tally, meaning a sequence of element-count pairs where elements are unique and counts are non-zero.*)\nLemma tallyP s : tally s \\is a wf_tally.\n\n(*This lemma states that successively applying the 'tally' operation and then the 'tally_seq' operation to a finite sequence results in a new sequence that is a permutation of the original one.*)\nLemma tallyK s : perm_eq (tally_seq (tally s)) s.\n\n(*This lemma states that the sequence of unique elements obtained from the tally of a given finite sequence is a permutation of the sequence of unique elements obtained by removing duplicates from the original sequence.*)\nLemma tallyEl s : perm_eq (unzip1 (tally s)) (undup s).\n\n(*This lemma provides an equational characterization of the 'tally' operation, stating that the tally of a finite sequence is a permutation of a sequence of pairs, where each pair is formed by a unique element from the original sequence and its multiplicity.*)\nLemma tallyE s : perm_eq (tally s) [seq (x, count_mem x s) | x <- undup s].\n\n(*This lemma states that if two finite sequences are permutations of each other, then their respective tallies, which represent element frequencies, are also permutations of each other.*)\nLemma perm_tally s1 s2 : perm_eq s1 s2 -> perm_eq (tally s1) (tally s2).\n\n(*This lemma states that if two tallies of element-count pairs are permutations of each other, then the finite sequences reconstructed from them using the 'tally_seq' operation are also permutations of each other.*)\nLemma perm_tally_seq bs1 bs2 :\n perm_eq bs1 bs2 -> perm_eq (tally_seq bs1) (tally_seq bs2).\n\n(*A local notation that provides a shorthand for the 'perm_tally_seq' lemma, which states that permutation equivalence of tallies implies permutation equivalence of the reconstructed sequences.*)\nLocal Notation perm_tseq := perm_tally_seq.\n\n(*This lemma states that a finite sequence is permutation-equivalent to the sequence constructed by taking each of its unique elements, repeating it by its number of occurrences in the original sequence, and concatenating all the resulting repetitions.*)\nLemma perm_count_undup s :\n perm_eq (flatten [seq nseq (count_mem x s) x | x <- undup s]) s.\n\n(*This definition is a local, recursive helper function for generating permutations. It constructs permutations by iteratively taking an element from a tally, prepending it to a base sequence, and then recursively generating all permutations of the remaining elements to combine with the new base.*)\nLocal Fixpoint cons_perms_ perms_rec (s : seq T) bs bs2 acc :=\n if bs isn't b :: bs1 then acc else\n if b isn't (x, m.+1) then cons_perms_ perms_rec s bs1 bs2 acc else\n let acc_xs := perms_rec (x :: s) ((x, m) :: bs1 ++ bs2) acc in\n cons_perms_ perms_rec s bs1 (b :: bs2) acc_xs.\n\n(*This definition is a local, recursive worker function that generates all permutations of a multiset represented by a tally. It takes a counter, a partially built permutation, a tally of remaining elements, and an accumulator for the generated permutations, and uses a helper function to explore all insertion possibilities.*)\nLocal Fixpoint perms_rec n s bs acc :=\n if n isn't n.+1 then s :: acc else cons_perms_ (perms_rec n) s bs [::] acc.\nLocal Notation cons_perms n := (cons_perms_ (perms_rec n) [::]).\n\n(*This definition computes a finite sequence containing all unique permutations of a given input sequence. It works by first creating a tally of the elements in the input sequence and then recursively generating all possible orderings.*)\nDefinition permutations s := perms_rec (size s) [::] (tally s) [::].\n\n(*This lemma asserts the existence of properties for the arguments used to compute permutations of a finite sequence. It guarantees that the computation is based on a well-formed tally whose reconstructed sequence is a permutation of the original sequence and whose size matches the recursion depth.*)\nLet permsP s : exists n bs,\n [/\\ permutations s = perms_rec n [::] bs [::],\n size (tseq bs) == n, perm_eq (tseq bs) s & uniq (unzip1 bs)].\n\n(*This local notation provides a shorthand for a complex proof term involving permutation properties, specifically related to the associativity of concatenation and element-wise permutation.*)\nLocal Notation bsCA := (permEl (perm_catCA _ [:: _] _)).\n(*This lemma describes a key property of the permutation generation helper function. It states that generating permutations by adding a new element to the front of a base sequence is equivalent to generating permutations without that element and then appending it to the end of each resulting permutation.*)\nLet cons_permsE : forall n x bs bs1 bs2,\n let cp := cons_perms n bs bs2 in let perms s := perms_rec n s bs1 [::] in\n cp (perms [:: x]) = cp [::] ++ [seq rcons t x | t <- perms [::]].\n\n(*This lemma establishes the correctness of the 'permutations' function by stating that a given finite sequence is an element of the sequence of all permutations of an original sequence if and only if it is a permutation of that original sequence.*)\nLemma mem_permutations s t : (t \\in permutations s) = perm_eq t s.\n\n(*This lemma states that the finite sequence generated by the 'permutations' function, which contains all permutations of an input sequence, is itself free of duplicate elements.*)\nLemma permutations_uniq s : uniq (permutations s).\n\n(*A notation for the function that takes a finite sequence and returns a finite sequence whose elements are all the possible permutations of the input sequence.*)\nNotation perms := permutations.\n(*This lemma provides a recursive characterization of permutations, stating that for a non-empty finite sequence, the sequence of all its permutations is permutationally equivalent to the sequence generated by picking each unique element from the input sequence and prepending it to all permutations of the remaining elements.*)\nLemma permutationsE s :\n 0 < size s ->\n perm_eq (perms s) [seq x :: t | x <- undup s, t <- perms (rem x s)].\n\n(*This lemma states that the permutations of a sequence formed by adding a new element to the front of an existing sequence are permutationally equivalent to the sequence generated by taking each permutation of the original sequence, prepending the new element, and then collecting all possible cyclic rotations of each newly formed sequence.*)\nLemma permutationsErot x s (le_x := fun t => iota 0 (index x t + 1)) :\n perm_eq (perms (x :: s)) [seq rot i (x :: t) | t <- perms s, i <- le_x t].\n\n(*This lemma states that for a finite sequence containing no duplicate elements, the number of elements in the sequence of its permutations is equal to the factorial of the length of the original sequence.*)\nLemma size_permutations s : uniq s -> size (permutations s) = (size s)`!.\n\n(*This lemma states that if a given finite sequence contains no duplicate elements, then every sequence in the sequence of its permutations also contains no duplicate elements.*)\nLemma permutations_all_uniq s : uniq s -> all uniq (permutations s).\n\n(*This lemma states that if two finite sequences are permutations of each other, then the finite sequence of all permutations of the first sequence is a permutation of the finite sequence of all permutations of the second sequence.*)\nLemma perm_permutations s t :\n perm_eq s t -> perm_eq (permutations s) (permutations t).", - "boot.ssrfun": "From mathcomp Require Import ssreflect.\nFrom Corelib Require Export ssrfun.\nFrom mathcomp Require Export ssrnotations.\n#[export] Set Warnings \"-overwriting-delimiting-key\".\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\n#[export] Set Warnings \"-hiding-delimiting-key\".\nDelimit Scope function_scope with FUN.\nDeclare Scope fun_scope.\nClose Scope fun_scope.\n\n(*This definition specifies the property of a binary function being injective, which means that if applying the function to two different pairs of arguments yields the same result, then the corresponding components of the two pairs must be equal.*)\nDefinition injective2 (rT aT1 aT2 : Type) (f : aT1 -> aT2 -> rT) :=\n forall (x1 x2 : aT1) (y1 y2 : aT2), f x1 y1 = f x2 y2 -> (x1 = x2) * (y1 = y2).\n\nArguments injective2 [rT aT1 aT2] f.\n\n(*This lemma states that if a function is injective, then the function that maps it over optional values is also injective.*)\nLemma inj_omap {aT rT : Type} (f : aT -> rT) :\n injective f -> injective (omap f).\n\n(*This lemma states that mapping the identity function over an optional value results in the original optional value.*)\nLemma omap_id {T : Type} (x : option T) : omap id x = x.\n\n(*This lemma states that if two functions are pointwise equal, then mapping these functions over optional values results in two new functions that are also pointwise equal.*)\nLemma eq_omap {aT rT : Type} (f g : aT -> rT) : f =1 g -> omap f =1 omap g.\n\n(*This lemma states that if a function has a left inverse, then the function that maps it over optional values also has a left inverse, which is the mapping of the original left inverse over optional values.*)\nLemma omapK {aT rT : Type} (f : aT -> rT) (g : rT -> aT) :\n cancel f g -> cancel (omap f) (omap g).\n\n(*This definition specifies that a binary operation is idempotent if applying it to any element with itself as both arguments yields that same element.*)\nDefinition idempotent_op (S : Type) (op : S -> S -> S) := forall x, op x x = x.\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"use `idempotent_op` instead\")]\n(*This notation provides a deprecated alias for the property of a binary operation being idempotent, where applying the operation to an element with itself yields that same element.*)\nNotation idempotent:= idempotent_op (only parsing).\n\n(*This definition specifies that a unary function is idempotent if applying it twice to any argument produces the same result as applying it just once.*)\nDefinition idempotent_fun (U : Type) (f : U -> U) := f \\o f =1 f.\n\n(*This lemma states that the function which injects an element from the second type into a sum type is injective.*)\nLemma inr_inj {A B} : injective (@inr A B). \n\n(*This lemma states that the function which injects an element from the first type into a sum type is injective.*)\nLemma inl_inj {A B} : injective (@inl A B). \n\n(*This lemma states a cancellation property involving dependent pairs, asserting that applying the `tagged` function to a dependent pair and then applying the `Tagged` function to the result yields the original dependent pair.*)\nLemma taggedK {I : Type} (T_ : I -> Type) (s : {i : I & T_ i}) :\n Tagged T_ (tagged s) = s.\n\n(*This definition creates a new pair by swapping the positions of the two components of a given input pair.*)\nDefinition swap_pair {T1 T2 : Type} (x : T1 * T2) := (x.2, x.1).\n\n(*This lemma states that applying the `swap_pair` function, which swaps the two components of a pair, twice in succession restores the original pair.*)\nLemma swap_pairK {T1 T2 : Type} : @cancel _ (T1 * T2) swap_pair swap_pair.", - "boot.fingraph": "From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat.\nFrom mathcomp Require Import seq path fintype.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\n(*This definition converts a function, which maps each element of a type to a sequence of elements of the same type, into a binary relation. The relation holds between a first and a second element if the second element is present in the sequence associated with the first element by the function.*)\nDefinition grel (T : eqType) (g : T -> seq T) := [rel x y | y \\in g x].\n\nSection Connect.\n\nVariable T : finType.\n\nSection Dfs.\n\nVariable g : T -> seq T.\nImplicit Type v w a : seq T.\n\n(*This definition describes a bounded depth-first search traversal on a graph. Given a depth limit as a natural number, a sequence of already visited elements, and a starting element, it explores the graph from the starting element and returns an updated sequence of visited elements including all newly discovered reachable elements.*)\nFixpoint dfs n v x :=\n if x \\in v then v else\n if n is n'.+1 then foldl (dfs n') (x :: v) (g x) else v.\n\n(*This lemma states that applying a bounded depth-first search, starting iteratively from each element in a given sequence, to an initial set of visited elements results in a new set of visited elements that is a superset of the initial set.*)\nLemma subset_dfs n v a : v \\subset foldl (dfs n) v a.\n\n(*This inductive proposition defines the property of a path existing between two elements in a graph, relative to a set of 'visited' elements. The property holds if there is a path from the first to the second element using the graph edges, and this path contains no elements from the 'visited' set.*)\nInductive dfs_path v x y : Prop :=\n DfsPath p of path (grel g) x p & y = last x p & [disjoint x :: p & v].\n\n(*This lemma states that an element is found by a bounded depth-first search starting from another element if and only if there exists a path between them that is disjoint from the initially visited elements. This equivalence holds provided the search depth is sufficient to cover all unvisited elements of the finite type and the target element was not initially visited.*)\nLemma dfs_pathP n x y v :\n #|T| <= #|v| + n -> y \\notin v -> reflect (dfs_path v x y) (y \\in dfs n v x).\n\n(*This lemma states that an element is reachable from a starting element in a graph on a finite type if and only if there exists a path from the starting element to the target element. Reachability is determined by performing a depth-first search with sufficient depth to explore the entire graph.*)\nLemma dfsP x y :\n reflect (exists2 p, path (grel g) x p & y = last x p) (y \\in dfs #|T| [::] x).\n\nEnd Dfs.\n\nVariable e : rel T.\n\n(*This definition constructs an adjacency list representation for a graph from a given binary relation. For any element, it produces a sequence containing all elements that are related to it by the given relation.*)\nDefinition rgraph x := enum (e x).\n\n(*This lemma states that converting a binary relation into an adjacency list representation and then converting it back into a relation yields a relation that is extensionally equal to the original one.*)\nLemma rgraphK : grel rgraph =2 e.\n\n(*This definition specifies the connectivity relation on a finite type. Two elements are related if the second element is reachable from the first through a path in the graph defined by an underlying binary relation.*)\nDefinition connect : rel T := [rel x y | y \\in dfs rgraph #|T| [::] x].\nCanonical connect_app_pred x := ApplicativePred (connect x).\n\n(*This lemma states that two elements are connected if and only if there exists a path between them according to the underlying binary relation.*)\nLemma connectP x y :\n reflect (exists2 p, path e x p & y = last x p) (connect x y).\n\n(*This lemma states that the connectivity relation is transitive.*)\nLemma connect_trans : transitive connect.\n\n(*This lemma states that the connectivity relation is reflexive, meaning every element is connected to itself.*)\nLemma connect0 x : connect x x.\n\n(*This lemma states that if two elements are equal, then they are connected by the connectivity relation.*)\nLemma eq_connect0 x y : x = y -> connect x y.\n\n(*This lemma states that if two elements are directly related by the underlying binary relation, then they are also connected by the connectivity relation.*)\nLemma connect1 x y : e x y -> connect x y.\n\n(*This lemma states that if there is a path starting from a given element, then that element is connected to every element on the path.*)\nLemma path_connect x p : path e x p -> subpred [in x :: p] (connect x).\n\n(*This lemma states that if a sequence of elements forms a cycle according to the underlying binary relation, then any two elements within that cycle are mutually connected.*)\nLemma connect_cycle p : cycle e p -> {in p &, forall x y, connect x y}.\n\n(*This definition assigns a canonical representative, called a root, to each element of a finite type. The root of an element is a deterministically chosen element from the set of all elements reachable from it.*)\nDefinition root x := odflt x (pick (connect x)).\n\n(*This definition specifies the predicate for identifying root elements. An element is a root if it serves as its own canonical representative.*)\nDefinition roots : pred T := fun x => root x == x.\nCanonical roots_pred := ApplicativePred roots.\n\n(*This definition computes the number of connected components whose canonical representative is included in a given subset of elements. This is achieved by counting the number of root elements that belong to the given subset.*)\nDefinition n_comp_mem (m_a : mem_pred T) := #|predI roots m_a|.\n\n(*This lemma states that any element is connected to its own root representative.*)\nLemma connect_root x : connect x (root x).\n\n(*This hypothesis assumes that the connectivity relation is symmetric. This implies that if an element is connected to another, then the second element is also connected to the first, making connectivity an equivalence relation.*)\nDefinition connect_sym := symmetric connect.\n\nHypothesis sym_e : connect_sym.\n\n(*This lemma states that, under the assumption of symmetry, the connectivity relation is left-transitive. This means that if a first element is connected to both a second and a third element, then the second and third elements are also connected to each other.*)\nLemma same_connect : left_transitive connect.\n\n(*This lemma states that, under the assumption of symmetry, the connectivity relation is right-transitive. This means that if a second element is connected to a third, and a first element is also connected to that same third element, then the first and second elements are connected to each other.*)\nLemma same_connect_r : right_transitive connect.\n\n(*This lemma states that if two elements are directly linked by the underlying relation, their respective sets of connected elements are identical, assuming the connectivity relation is symmetric.*)\nLemma same_connect1 x y : e x y -> connect x =1 connect y.\n\n(*This lemma states that if two elements are directly linked by the underlying relation, then the set of elements from which the first element is reachable is identical to the set of elements from which the second is reachable, assuming the connectivity relation is symmetric.*)\nLemma same_connect1r x y : e x y -> connect^~ x =1 connect^~ y.\n\n(*This lemma establishes that two elements are connected if and only if they share the same canonical root representative, assuming the connectivity relation is symmetric.*)\nLemma rootP x y : reflect (root x = root y) (connect x y).\n\n(*This lemma states that the root function is idempotent, meaning that applying the root function to an element that is already a root yields the same root element. This property holds when the connectivity relation is symmetric.*)\nLemma root_root x : root (root x) = root x.\n\n(*This lemma states that the root representative of any element is itself a member of the set of all root elements, provided connectivity is symmetric.*)\nLemma roots_root x : roots (root x).\n\n(*This lemma states that the boolean indicating whether two elements have the same root representative is equal to the boolean indicating whether they are connected.*)\nLemma root_connect x y : (root x == root y) = connect x y.\n\n(*This definition describes a predicate on a set as being closed under a given relation, which holds if for any two elements that are directly related, their membership in the set is identical.*)\nDefinition closed_mem m_a := forall x y, e x y -> in_mem x m_a = in_mem y m_a.\n\n(*This definition constructs the closure of a given set under a relation as the set of all elements that are connected to at least one member of the original set.*)\nDefinition closure_mem m_a : pred T :=\n fun x => ~~ disjoint (mem (connect x)) m_a.\n\nEnd Connect.\nArguments rgraphK [T].\n#[global] Hint Resolve connect0 : core.\n\nNotation n_comp e a := (n_comp_mem e (mem a)).\nNotation closed e a := (closed_mem e (mem a)).\nNotation closure e a := (closure_mem e (mem a)).\n\nPrenex Implicits connect root roots.\n\nArguments dfsP {T g x y}.\nArguments connectP {T e x y}.\nArguments rootP [T e] _ {x y}.\n\nNotation fconnect f := (connect (coerced_frel f)).\nNotation froot f := (root (coerced_frel f)).\nNotation froots f := (roots (coerced_frel f)).\nNotation fcard_mem f := (n_comp_mem (coerced_frel f)).\nNotation fcard f a := (fcard_mem f (mem a)).\nNotation fclosed f a := (closed (coerced_frel f) a).\nNotation fclosure f a := (closure (coerced_frel f) a).\n\nSection EqConnect.\n\nVariable T : finType.\nImplicit Types (e : rel T) (a : {pred T}).\n\n(*This lemma states that if a given relation is a subrelation of the connectivity relation derived from a second relation, then the connectivity relation of the first relation is also a subrelation of the connectivity relation of the second.*)\nLemma connect_sub e e' :\n subrel e (connect e') -> subrel (connect e) (connect e').\n\n(*This lemma asserts that if the connectivity relations of two separate relations are both symmetric, then the connectivity relation of their union is also symmetric.*)\nLemma relU_sym e e' :\n connect_sym e -> connect_sym e' -> connect_sym (relU e e').\n\n(*This lemma states that if two relations are pointwise equivalent, then their respective connectivity relations are also pointwise equivalent.*)\nLemma eq_connect e e' : e =2 e' -> connect e =2 connect e'.\n\nArguments eq_connect [e e'].\n\n(*This lemma states that if two relations have pointwise equivalent connectivity relations, then their corresponding functions for counting the number of connected components are pointwise equivalent.*)\nLemma eq_n_comp e e' : connect e =2 connect e' -> n_comp_mem e =1 n_comp_mem e'.\n\n(*This lemma asserts that, for a given relation, if two sets are pointwise equivalent, then the number of connected components of the graph that intersect the first set is equal to the number of connected components that intersect the second set.*)\nLemma eq_n_comp_r {e} a a' : a =i a' -> n_comp e a = n_comp e a'.\n\n(*This lemma states that for any given relation and any subset of elements that is closed under the relation, the total number of connected components is the sum of the number of components within the subset and the number of components within its complement.*)\nLemma n_compC a e : n_comp e T = n_comp e a + n_comp e [predC a].\n\n(*This lemma states that if two relations are pointwise equivalent, then their corresponding functions that map an element to its canonical root representative are also pointwise equivalent.*)\nLemma eq_root e e' : e =2 e' -> root e =1 root e'.\n\n(*This lemma asserts that if two relations are pointwise equivalent, then their corresponding sets of canonical representatives for all connected components are also pointwise equivalent.*)\nLemma eq_roots e e' : e =2 e' -> roots e =1 roots e'.\n\n(*This lemma states that the connectivity relation derived from the transpose of a given relation is pointwise equivalent to the transpose of the connectivity relation of the original relation.*)\nLemma connect_rev e : connect [rel x y | e y x] =2 [rel x y | connect e y x].\n\n(*This lemma states that if a given binary relation is symmetric, then its reflexive-transitive closure, representing connectivity, is also a symmetric relation.*)\nLemma sym_connect_sym e : symmetric e -> connect_sym e.\n\nEnd EqConnect.\nArguments eq_connect [T e e'].\nArguments connect_rev [T].\n\nSection Closure.\n\nVariables (T : finType) (e : rel T).\nHypothesis sym_e : connect_sym e.\nImplicit Type a : {pred T}.\n\n(*This lemma states that for a relation with a symmetric connectivity relation, the connectivity relation is pointwise equivalent to the connectivity relation of the transposed relation.*)\nLemma same_connect_rev : connect e =2 connect [rel x y | e y x].\n\n(*This lemma states that a set is closed with respect to a relation if for any two elements directly related, membership of the first element in the set implies membership of the second element.*)\nLemma intro_closed a : (forall x y, e x y -> x \\in a -> y \\in a) -> closed e a.\n\n(*This lemma states that if a set is closed under a given relation, then for any two elements that are connected via a path, their membership in the set is equivalent.*)\nLemma closed_connect a :\n closed e a -> forall x y, connect e x y -> (x \\in a) = (y \\in a).\n\n(*This lemma asserts that for a relation with symmetric connectivity, the set of all elements connected to a given element forms a closed set.*)\nLemma connect_closed x : closed e (connect e x).\n\n(*This lemma states that if a given set is closed under a relation, then its complement is also a closed set under the same relation.*)\nLemma predC_closed a : closed e a -> closed e [predC a].\n\n(*This lemma states that the closure of any given set with respect to a relation is always a closed set.*)\nLemma closure_closed a : closed e (closure e a).\n\n(*This lemma states that any given set is a subset of its closure under a relation.*)\nLemma mem_closure a : {subset a <= closure e a}.\n\n(*This lemma states that a given set is a subset of its closure under a relation.*)\nLemma subset_closure a : a \\subset closure e a.\n\n(*This lemma states that the number of connected components intersecting the closure of a two-element set is one if the elements are connected, and two if they are not.*)\nLemma n_comp_closure2 x y :\n n_comp e (closure e (pred2 x y)) = (~~ connect e x y).+1.\n\n(*This lemma states that the number of connected components within the subgraph induced by a single connected component is exactly one.*)\nLemma n_comp_connect x : n_comp e (connect e x) = 1.\n\nEnd Closure.\nArguments same_connect_rev [T e].\n\nSection Orbit.\n\nVariables (T : finType) (f : T -> T).\n\n(*This definition specifies the order of an element with respect to a function on a finite type as the number of elements in its connected component within the function's graph, corresponding to the length of the cycle it belongs to.*)\nDefinition order x := #|fconnect f x|.\n\n(*This definition specifies the orbit of an element under a given function as the finite sequence of elements generated by iterating the function, starting from the given element, for a number of steps equal to the element's order.*)\nDefinition orbit x := traject f x (order x).\n\n(*This definition specifies the index of a given element within the orbit of another element as its zero-based position in the sequence that constitutes the orbit.*)\nDefinition findex x y := index y (orbit x).\n\n(*This definition specifies the inverse of an element under a function within its orbit, computed by iterating the function a number of times equal to the element's order minus one.*)\nDefinition finv x := iter (order x).-1 f x.\n\n(*This lemma states that for any function, an element is connected in the functional graph to the result of iterating the function on that element any given number of times.*)\nLemma fconnect_iter n x : fconnect f x (iter n f x).\n\n(*This lemma states that any element is connected in the functional graph to the element obtained by applying the function to it a single time.*)\nLemma fconnect1 x : fconnect f x (f x).\n\n(*This lemma states that any element is connected in the functional graph to its functional inverse within its orbit.*)\nLemma fconnect_finv x : fconnect f x (finv x).\n\n(*This lemma states that for any element, the successor of the predecessor of its order under a function is equal to its order, which holds because the order is always positive.*)\nLemma orderSpred x : (order x).-1.+1 = order x.\n\n(*This lemma states that for any element, the number of items in the sequence representing its orbit under a function is equal to the order of that element.*)\nLemma size_orbit x : size (orbit x) = order x.\n\n(*This lemma states that for any element, iterating a function from that element a number of times equal to its order results in the element itself.*)\nLemma looping_order x : looping f x (order x).\n\n(*This lemma states that two elements are connected by a function if and only if the second element is a member of the orbit of the first element under that function.*)\nLemma fconnect_orbit x y : fconnect f x y = (y \\in orbit x).\n\n(*This lemma states that any element is a member of its own orbit under a function.*)\nLemma in_orbit x : x \\in orbit x. \nHint Resolve in_orbit : core.\n\n(*This lemma states that the order of any element under a function is strictly greater than zero.*)\nLemma order_gt0 x : order x > 0. \nHint Resolve order_gt0 : core.\n\n(*This lemma states that the sequence representing the orbit of any element under a function contains no duplicate elements.*)\nLemma orbit_uniq x : uniq (orbit x).\n\n(*This lemma states that if two elements are connected by a function, then the index of the second element with respect to the first is strictly less than the order of the first element.*)\nLemma findex_max x y : fconnect f x y -> findex x y < order x.\n\n(*This lemma states that for any natural number strictly less than the order of an element, the index of the element resulting from iterating a function that many times from the starting element is equal to that natural number.*)\nLemma findex_iter x i : i < order x -> findex x (iter i f x) = i.\n\n(*This lemma states that if two elements are connected by a function, iterating the function from the first element a number of times equal to the index of the second element yields the second element.*)\nLemma iter_findex x y : fconnect f x y -> iter (findex x y) f x = y.\n\n(*This lemma states that the index of any element with respect to itself is zero.*)\nLemma findex0 x : findex x x = 0.\n\n(*This lemma states that the index of a second element with respect to a first element is zero if and only if the two elements are equal.*)\nLemma findex_eq0 x y : (findex x y == 0) = (x == y).\n\n(*This lemma states that if a second function is an invariant for a first function, meaning it yields the same value for an element and its image under the first function, then any two elements connected by the first function will have the same value under the second function.*)\nLemma fconnect_invariant (T' : eqType) (k : T -> T') :\n invariant f k =1 xpredT -> forall x y, fconnect f x y -> k x = k y.\n\n(*This lemma states that the property of being a member of the orbit of an element is preserved by the function defining the orbit.*)\nLemma mem_orbit x : {homo f : y / y \\in orbit x}.\n\n(*This lemma states that the set of images of all elements in the orbit of an element under a function is a subset of that same orbit.*)\nLemma image_orbit x : {subset image f (orbit x) <= orbit x}.\n\nSection orbit_in.\n\nVariable S : {pred T}.\n\nHypothesis f_in : {homo f : x / x \\in S}.\nHypothesis injf : {in S &, injective f}.\n\n(*This lemma states that if a function maps a given set to itself, its inverse function also preserves membership in that set.*)\nLemma finv_in : {homo finv : x / x \\in S}.\n\n(*This lemma states that for all elements within a given set, applying a function and then its inverse returns the original element.*)\nLemma f_finv_in : {in S, cancel finv f}.\n\n(*This lemma states that for all elements within a given set, applying the inverse of a function and then the function itself returns the original element.*)\nLemma finv_f_in : {in S, cancel f finv}.\n\n(*This lemma states that the inverse of a function is injective on a given set where the original function is also injective.*)\nLemma finv_inj_in : {in S &, injective finv}.\n\n(*This lemma states that for any two elements within a given set, connectivity under a function is symmetric, meaning the first element is connected to the second if and only if the second is connected to the first.*)\nLemma fconnect_sym_in : {in S &, forall x y, fconnect f x y = fconnect f y x}.\n\n(*This lemma states that for any element within a given set, iterating a function from that element a number of times equal to its order results in the original element.*)\nLemma iter_order_in : {in S, forall x, iter (order x) f x = x}.\n\n(*This lemma states that for any element within a given set and a natural number less than or equal to its order, iterating the inverse of a function that many times from the element is equivalent to iterating the original function a number of times equal to the difference between the order and the given natural number.*)\nLemma iter_finv_in n :\n {in S, forall x, n <= order x -> iter n finv x = iter (order x - n) f x}.\n\n(*This lemma states that for any element within a given set, the function acts as a cycle on the sequence of elements in its orbit.*)\nLemma cycle_orbit_in : {in S, forall x, (fcycle f) (orbit x)}.\n\n(*This lemma states that, for an element in a given set, a path generated by an inverse function exists if and only if a path generated by the original function exists along the reverse of the first path, starting from its endpoint, and the endpoint is also in the set.*)\nLemma fpath_finv_in p x :\n (x \\in S) && (fpath finv x p) =\n (last x p \\in S) && (fpath f (last x p) (rev (belast x p))).\n\n(*This lemma states that for any element in a given set, if a path exists from that element under an inverse function, then a corresponding path exists under the original function starting from the endpoint of the first path and following its reverse.*)\nLemma fpath_finv_f_in p : {in S, forall x,\n fpath finv x p -> fpath f (last x p) (rev (belast x p))}.\n\n(*This lemma states that if a path exists under a function starting from the endpoint of a given path sequence and following its reverse, and this endpoint is in a given set, then a path under the inverse function exists from the start of the original path sequence.*)\nLemma fpath_f_finv_in p x : last x p \\in S ->\n fpath f (last x p) (rev (belast x p)) -> fpath finv x p.\n\nEnd orbit_in.\n\n(*This lemma states that a function is injective on the orbit of an element if and only if the function acts as a cycle on that orbit.*)\nLemma injectivePcycle x :\n reflect {in orbit x &, injective f} (fcycle f (orbit x)).\n\nSection orbit_inj.\n\nHypothesis injf : injective f.\n\n(*This lemma states that applying a function and then its inverse function returns the original element, given that the function is injective.*)\nLemma f_finv : cancel finv f. \n\n(*This lemma states that applying an inverse function and then the original function returns the original element, given that the original function is injective.*)\nLemma finv_f : cancel f finv. \n\n(*This lemma states that the inverse of an injective function is bijective.*)\nLemma finv_bij : bijective finv.\n\n(*This lemma states that the inverse function `finv` is injective.*)\nLemma finv_inj : injective finv. \n\n(*This lemma states that the connectivity relation defined by a function `f` is symmetric; that is, an element `x` is connected to an element `y` if and only if `y` is connected to `x`.*)\nLemma fconnect_sym x y : fconnect f x y = fconnect f y x.\n\n(*This definition is an alias for the lemma `fconnect_sym`, which asserts the symmetry of the connectivity relation under a function `f`.*)\nLet symf := fconnect_sym.\n\n(*This lemma states that iterating a function `f` on an element `x` a number of times equal to the order of `x` results in the element `x` itself.*)\nLemma iter_order x : iter (order x) f x = x.\n\n(*This lemma states that for any natural number `n` less than or equal to the order of an element `x`, iterating the inverse function `finv` `n` times on `x` is equivalent to iterating the original function `f` on `x` for a number of times equal to the difference between the order of `x` and `n`.*)\nLemma iter_finv n x : n <= order x -> iter n finv x = iter (order x - n) f x.\n\n(*This lemma states that the orbit of any element `x` under a function `f` forms a cycle with respect to `f`.*)\nLemma cycle_orbit x : fcycle f (orbit x).\n\n(*This lemma states that a sequence `p` forms a path starting from an element `x` under the inverse function `finv` if and only if the reversed initial segment of the full path forms a path under the original function `f` starting from the final element of the path.*)\nLemma fpath_finv x p : fpath finv x p = fpath f (last x p) (rev (belast x p)).\n\n(*This lemma states that the connectivity relation induced by the inverse function `finv` is equivalent to the connectivity relation induced by the original function `f`.*)\nLemma same_fconnect_finv : fconnect finv =2 fconnect f.\n\n(*This lemma states that the function counting the number of orbits within a given set of elements is the same for the inverse function `finv` as it is for the original function `f`.*)\nLemma fcard_finv : fcard_mem finv =1 fcard_mem f.\n\n(*This definition introduces a set containing all elements of a given type whose order under a function `f` is equal to a specified natural number `n`.*)\nDefinition order_set n : pred T := [pred x | order x == n].\n\n(*This lemma states that for a given natural number `n` and a set of elements `a`, if `a` is a subset of elements with order `n` and is closed under a function `f`, then the product of the number of orbits in `a` and `n` equals the total number of elements in `a`.*)\nLemma fcard_order_set n (a : {pred T}) :\n a \\subset order_set n -> fclosed f a -> fcard f a * n = #|a|.\n\n(*This lemma states that if a set of elements `a` is closed under an injective function `f`, then an element `x` belongs to `a` if and only if its image under `f` also belongs to `a`.*)\nLemma fclosed1 (a : {pred T}) :\n fclosed f a -> forall x, (x \\in a) = (f x \\in a).\n\n(*This lemma states that the set of elements connected to an element `x` under a function `f` is the same as the set of elements connected to the image of `x` under `f`.*)\nLemma same_fconnect1 x : fconnect f x =1 fconnect f (f x).\n\n(*This lemma states that an element `x` is connected to an element `y` under a function `f` if and only if `x` is connected to the image of `y` under `f`.*)\nLemma same_fconnect1_r x y : fconnect f x y = fconnect f x (f y).\n\n(*This lemma provides a reflection property, stating that for any set of elements `a` that is closed under a function `f`, the number of orbits in `a` is greater than zero if and only if there exists an element in `a`.*)\nLemma fcard_gt0P (a : {pred T}) : \n fclosed f a -> reflect (exists x, x \\in a) (0 < fcard f a).\n\n(*This lemma provides a reflection property, stating that for any set of elements `A` that is closed under a function `f`, the number of orbits in `A` is greater than one if and only if there exist two elements in `A` that are not connected to each other by `f`.*)\nLemma fcard_gt1P (A : {pred T}) :\n fclosed f A ->\n reflect (exists2 x, x \\in A & exists2 y, y \\in A & ~~ fconnect f x y)\n (1 < fcard f A).\n\nEnd orbit_inj.\nHint Resolve orbit_uniq : core.\n\nSection fcycle_p.\nVariables (p : seq T) (f_p : fcycle f p).\n\nSection mem_cycle.\n\nVariable (Up : uniq p) (x : T) (p_x : x \\in p).\n\n(*This lemma states that for an element `x` belonging to a cycle `p`, another element `y` is connected to `x` under the function `f` if and only if `y` is also an element of the cycle `p`.*)\nLemma fconnect_cycle y : fconnect f x y = (y \\in p).\n\n(*This lemma states that the order of an element `x` belonging to a cycle `p` is less than or equal to the size of the sequence `p`.*)\nLemma order_le_cycle : order x <= size p.\n\n(*This lemma states that for an element `x` in a cycle `p` with unique elements, the order of `x` is equal to the size of the sequence `p`.*)\nLemma order_cycle : order x = size p.\n\n(*This lemma states that the orbit of an element `x` within a cycle `p` is equal to the sequence `p` rotated by a number of positions corresponding to the index of `x` in `p`.*)\nLemma orbitE : orbit x = rot (index x p) p.\n\n(*This lemma states that for an element `x` in a cycle `p`, there exists a natural number `i` such that the orbit of `x` is equal to the sequence `p` rotated by `i` positions.*)\nLemma orbit_rot_cycle : {i : nat | orbit x = rot i p}.\n\nEnd mem_cycle.\n\n(*This definition introduces a function that represents the action of a given endofunction, restricted to the elements of a specific cycle. This restricted function is injective, mapping each element of the cycle to a unique element within the same cycle.*)\nLet f_inj := inj_cycle f_p.\n(*This lemma asserts that a given endofunction maps any element of a particular cycle to another element within that same cycle.*)\nLet homo_f := mem_fcycle f_p.\n\n(*This lemma states that the set of elements in the cycle `p` is closed under the inverse function `finv`.*)\nLemma finv_cycle : {homo finv : x / x \\in p}. \n\n(*This lemma states that for any element in the cycle `p`, the composition of the function `f` with its inverse `finv` acts as the identity function.*)\nLemma f_finv_cycle : {in p, cancel finv f}. \n\n(*This lemma states that for any element in the cycle `p`, the composition of the inverse function `finv` with the function `f` acts as the identity function.*)\nLemma finv_f_cycle : {in p, cancel f finv}. \n\n(*This lemma states that the inverse function `finv` is injective when restricted to the set of elements in the cycle `p`.*)\nLemma finv_inj_cycle : {in p &, injective finv}. \n\n(*This lemma states that for any element `x` in a cycle `p` and any natural number `n` less than or equal to the order of `x`, iterating the inverse function `finv` `n` times on `x` is equivalent to iterating the original function `f` on `x` a number of times equal to the difference between the order of `x` and `n`.*)\nLemma iter_finv_cycle n :\n {in p, forall x, n <= order x -> iter n finv x = iter (order x - n) f x}.\n\n(*This lemma states that for every element `x` belonging to a cycle `p`, the orbit of `x` under the function `f` itself forms a cycle.*)\nLemma cycle_orbit_cycle : {in p, forall x, fcycle f (orbit x)}.\n\n(*This lemma provides an identity for the boolean condition that checks if a sequence `q` forms a path under the inverse function `finv` starting from an element `x` belonging to a cycle `p`.*)\nLemma fpath_finv_cycle q x : (x \\in p) && (fpath finv x q) =\n (last x q \\in p) && fpath f (last x q) (rev (belast x q)).\n\n(*This lemma states that for any element in a sequence that forms a cycle, if there is a path from that element along another sequence using the inverse function, then a path also exists using the forward function, starting from the end of the second sequence and traversing its reverse.*)\nLemma fpath_finv_f_cycle q : {in p, forall x,\n fpath finv x q -> fpath f (last x q) (rev (belast x q))}.\n\n(*This lemma provides the converse of `fpath_finv_f_cycle`, stating that if a path exists using a function `f` starting from the end of a sequence and traversing its reverse, then a path exists from the original starting point using the inverse function along the original sequence.*)\nLemma fpath_f_finv_cycle q x : last x q \\in p ->\n fpath f (last x q) (rev (belast x q)) -> fpath finv x q.\n\n(*This lemma states that for any element belonging to a sequence that is a cycle, its predecessor within the cycle is equal to its functional inverse.*)\nLemma prevE x : x \\in p -> prev p x = finv x.\n\nEnd fcycle_p.\n\nSection fcycle_cons.\nVariables (x : T) (p : seq T) (f_p : fcycle f (x :: p)).\n\n(*This lemma states that if a sequence formed by prepending an element `x` to a sequence `p` is a cycle under a function `f`, then appending `x` to this sequence results in a new sequence equal to the trajectory of `f` starting at `x` with a length of the size of `p` plus two.*)\nLemma fcycle_rconsE : rcons (x :: p) x = traject f x (size p).+2.\n\n(*This lemma states that if a sequence formed by prepending an element `x` to a sequence `p` is a cycle under a function `f`, then this sequence is equal to the trajectory of `f` starting at `x` with a length of the size of `p` plus one.*)\nLemma fcycle_consE : x :: p = traject f x (size p).+1.\n\n(*This lemma asserts that if a sequence formed by prepending an element to another sequence constitutes a cycle under a function, then there exists a natural number such that the cycle sequence is equal to repeating the orbit of the first element that many times.*)\nLemma fcycle_consEflatten : exists k, x :: p = flatten (nseq k.+1 (orbit x)).\n\n(*This lemma states that if a sequence formed by prepending an element `x` to another sequence `p` is a cycle under a function `f`, then the sequence of its unique elements is equal to the orbit of `x`.*)\nLemma undup_cycle_cons : undup (x :: p) = orbit x.\n\nEnd fcycle_cons.\n\nSection fcycle_undup.\n\nVariable (p : seq T) (f_p : fcycle f p).\n\n(*This lemma states that for any sequence `p` that is a cycle under a function `f`, there exists a natural number `k` such that `p` is equal to the concatenation of `k` copies of the sequence of unique elements of `p`.*)\nLemma fcycleEflatten : exists k, p = flatten (nseq k (undup p)).\n\n(*This lemma states that if a sequence `p` forms a cycle under a function `f`, then the sequence containing the unique elements of `p` also forms a cycle under the same function.*)\nLemma fcycle_undup : fcycle f (undup p).\n\n(*This definition provides a proof that the sequence derived from removing duplicates from a cycle `p` contains no repeated elements.*)\nLet p_undup_uniq := undup_uniq p.\n(*This definition provides a proof that the function `f` is injective on the set of elements belonging to the cycle `p`.*)\nLet f_inj := inj_cycle f_p.\n(*This definition provides a proof that the set of elements in the cycle `p` is closed under the function `f`, meaning the image of any element in `p` is also in `p`.*)\nLet homo_f := mem_fcycle f_p.\n\n(*This lemma states that for any element within a cycle, its orbit is a permutation of the cycle sequence.*)\nLemma in_orbit_cycle : {in p &, forall x, orbit x =i p}.\n\n(*This lemma states that all elements within a given cycle have the same order under the cycle's defining function.*)\nLemma eq_order_cycle : {in p &, forall x y, order y = order x}.\n\n(*This lemma states that for any two elements `x` and `y` in a cycle, applying the cycle's function to `y` a number of times equal to the order of `x` results in `y` itself.*)\nLemma iter_order_cycle : {in p &, forall x y, iter (order x) f y = y}.\n\nEnd fcycle_undup.\n\nSection fconnect.\n\n(*This lemma provides a recursive characterization for functional connectivity, stating that an element `y` is reachable from an element `x` if and only if `y` is `x` or `y` is reachable from the successor of `x`.*)\nLemma fconnect_eqVf x y : fconnect f x y = (x == y) || fconnect f (f x) y.\n\n(*This lemma establishes the equivalence of several conditions for the orbit of an element to form a cycle, such as the element being reachable from its successor, the function being injective on the orbit, or iterating the function by the order of the element returning the element itself.*)\nLemma orbitPcycle {x} : [<->\n fcycle f (orbit x);\n order (f x) = order x;\n x \\in fconnect f (f x);\n exists k, iter k.+1 f x = x;\n iter (order x) f x = x;\n {in orbit x &, injective f}].\n\n(*This lemma states that if the orbit of an element under a function forms a cycle, then the order of that element is equal to the order of its successor.*)\nLemma order_id_cycle x : fcycle f (orbit x) -> order (f x) = order x.\n\n(*This inductive type specifies the relationship between the order of an element and the order of its successor under a function. It defines two cases: one where the orbit is a cycle and orders are equal, and one where the orbit is not a cycle and the element's order is one greater than its successor's.*)\nInductive order_spec_cycle x : bool -> Type :=\n| OrderStepCycle of fcycle f (orbit x) & order x = order (f x) :\n order_spec_cycle x true\n| OrderStepNoCycle of ~~ fcycle f (orbit x) & order x = (order (f x)).+1 :\n order_spec_cycle x false.\n\n(*This lemma asserts that the relationship between the order of an element and the order of its successor is correctly determined by whether the element's orbit forms a cycle.*)\nLemma orderPcycle x : order_spec_cycle x (fcycle f (orbit x)).\n\n(*This lemma establishes that an element is reachable from its own successor under a function if and only if the orbit of that element forms a cycle.*)\nLemma fconnect_f x : fconnect f (f x) x = fcycle f (orbit x).\n\n(*This lemma provides a recursive formula for the reachability index, stating that if an element `y` is reachable from a distinct element `x`, the number of steps required is one plus the number of steps from the successor of `x` to `y`.*)\nLemma fconnect_findex x y :\n fconnect f x y -> y != x -> findex x y = (findex (f x) y).+1.\n\nEnd fconnect.\n\nEnd Orbit.\n\n#[global] Hint Resolve in_orbit mem_orbit order_gt0 orbit_uniq : core.\nPrenex Implicits order orbit findex finv order_set.\nArguments orbitPcycle {T f x}.\nArguments same_fconnect_finv [T f].\n\nSection FconnectId.\n\nVariable T : finType.\n\n(*This lemma states that for the identity function on a finite type, the predicate for connectivity from an element `x` is equivalent to the predicate that is true only for `x`.*)\nLemma fconnect_id (x : T) : fconnect id x =1 xpred1 x.\n\n(*This lemma states that under the identity function on a finite type, the order of any element is one.*)\nLemma order_id (x : T) : order id x = 1.\n\n(*This lemma states that under the identity function on a finite type, the orbit of any element is a singleton sequence containing only that element.*)\nLemma orbit_id (x : T) : orbit id x = [:: x].\n\n(*This lemma states that for the identity function on a finite type, every element is a root, meaning it is a fixed point of the function.*)\nLemma froots_id (x : T) : froots id x.\n\n(*This lemma states that for the identity function on a finite type, the root of the functional graph containing any element `x` is `x` itself.*)\nLemma froot_id (x : T) : froot id x = x.\n\n(*This lemma states that for the identity function on a finite type, the cardinality of the image of any subset of the type is equal to the cardinality of the subset itself.*)\nLemma fcard_id (a : {pred T}) : fcard id a = #|a|.\n\nEnd FconnectId.\n\nSection FconnectEq.\n\nVariables (T : finType) (f f' : T -> T).\n\n(*This lemma states that if a function `f'` acts as a left-inverse to a function `f` on its cycles, then the canonical functional inverse of `f` on those cycles is pointwise equal to `f'`.*)\nLemma finv_eq_can : cancel f f' -> finv f =1 f'.\n\nHypothesis eq_f : f =1 f'.\n(*This definition establishes that if two functions are pointwise equal, then the binary relations induced by them are also equal.*)\nLet eq_rf := eq_frel eq_f.\n\n(*This lemma states that if two endofunctions on a finite type are equivalent, then their corresponding connectivity representative functions, which map each element to a canonical member of its connected component, are pointwise equal.*)\nLemma eq_fconnect : fconnect f =2 fconnect f'.\n\n(*This lemma states that if two endofunctions on a finite type are equivalent, then the function mapping each element to the size of its orbit is pointwise equal for both endofunctions.*)\nLemma eq_fcard : fcard_mem f =1 fcard_mem f'.\n\n(*This lemma states that if two endofunctions on a finite type are equivalent, then their corresponding local inverse functions, computed on their respective cycles, are pointwise equal.*)\nLemma eq_finv : finv f =1 finv f'.\n\n(*This lemma states that if two endofunctions on a finite type are equivalent, then their respective functions that map each element to the canonical root of its cycle are pointwise equal.*)\nLemma eq_froot : froot f =1 froot f'.\n\n(*This lemma states that if two endofunctions on a finite type are equivalent, then their characteristic functions identifying the set of cycle roots are pointwise equal.*)\nLemma eq_froots : froots f =1 froots f'.\n\nEnd FconnectEq.\nArguments eq_fconnect [T f f'].\n\nSection FinvEq.\n\nVariables (T : finType) (f : T -> T).\nHypothesis injf : injective f.\n\n(*This lemma states that for an injective endofunction on a finite type, applying the local inverse operation twice yields the original function, demonstrating that the local inverse is an involution.*)\nLemma finv_inv : finv (finv f) =1 f.\n\n(*This lemma states that for an injective endofunction on a finite type, the function mapping each element to its cycle size under the local inverse is pointwise equal to the function mapping each element to its cycle size under the original function.*)\nLemma order_finv : order (finv f) =1 order f.\n\n(*This lemma states that for an injective endofunction on a finite type and any given natural number, the set of elements whose cycle length under the local inverse equals that number is identical to the set of elements with the same cycle length under the original function.*)\nLemma order_set_finv n : order_set (finv f) n =i order_set f n.\n\nEnd FinvEq.\n\nSection RelAdjunction.\n\nVariables (T T' : finType) (h : T' -> T) (e : rel T) (e' : rel T').\nHypotheses (sym_e : connect_sym e) (sym_e' : connect_sym e').\n\n(*A record that describes a relational adjunction between two finite types, each equipped with a symmetric relation, relative to a specific subset of the first type. This structure formalizes a connection where a function ensures that every element in the subset is related to an image from the second type, and the relation is preserved and reflected between the subset and its preimage.*)\nRecord rel_adjunction_mem m_a := RelAdjunction {\n rel_unit x : in_mem x m_a -> {x' : T' | connect e x (h x')};\n rel_functor x' y' :\n in_mem (h x') m_a -> connect e' x' y' = connect e (h x') (h y')\n}.\n\nVariable a : {pred T}.\nHypothesis cl_a : closed e a.\n\n(*A local notation that provides a shorthand for a relational adjunction structure where the relevant subset of the first type is specified by a given predicate.*)\nLocal Notation rel_adjunction := (rel_adjunction_mem (mem a)).\n\n(*This lemma provides a constructive proof for a relational adjunction by supplying a section function. The construction holds if this section correctly maps elements to related preimages and preserves the given relations when moving between the two types.*)\nLemma intro_adjunction (h' : forall x, x \\in a -> T') :\n (forall x a_x,\n [/\\ connect e x (h (h' x a_x))\n & forall y a_y, e x y -> connect e' (h' x a_x) (h' y a_y)]) ->\n (forall x' a_x,\n [/\\ connect e' x' (h' (h x') a_x)\n & forall y', e' x' y' -> connect e (h x') (h y')]) ->\n rel_adjunction.\n\n(*This lemma establishes the existence of a relational adjunction under the stricter conditions that the connecting function is injective, its an image that covers the specified subset, and it establishes a direct equivalence between the relations on the subset and its preimage.*)\nLemma strict_adjunction :\n injective h -> a \\subset codom h -> rel_base h e e' [predC a] ->\n rel_adjunction.\n\n(*This definition provides a local name for the property that a given subset is closed under a relation, meaning that any element related to an element of the subset must also be in the subset.*)\nLet ccl_a := closed_connect cl_a.\n\n(*This lemma states that if a relational adjunction holds, then the preimage of the specified subset under the connecting function is a closed set with respect to the relation on the second type.*)\nLemma adjunction_closed : rel_adjunction -> closed e' [preim h of a].\n\n(*This lemma states that in the presence of a relational adjunction, the number of connected components of the first relation restricted to the given subset is equal to the number of connected components of the second relation restricted to the preimage of that subset.*)\nLemma adjunction_n_comp :\n rel_adjunction -> n_comp e a = n_comp e' [preim h of a].\n\nEnd RelAdjunction.\n\nNotation rel_adjunction h e e' a := (rel_adjunction_mem h e e' (mem a)).\n(*A notation providing a fully explicit way to refer to the relational adjunction structure, specifying all type and term arguments including the types, the connecting function, the relations, and the subset, to prevent ambiguity during type inference.*)\nNotation \"@ 'rel_adjunction' T T' h e e' a\" :=\n (@rel_adjunction_mem T T' h e e' (mem a))\n (at level 10, T, T', h, e, e', a at level 8, only parsing) : type_scope.\nNotation fun_adjunction h f f' a := (rel_adjunction h (frel f) (frel f') a).\n(*A notation providing a fully explicit way to refer to a functional adjunction, which is a specialized relational adjunction where the relations are those induced by endofunctions. It requires specifying the types, connecting function, endofunctions, and the relevant subset.*)\nNotation \"@ 'fun_adjunction' T T' h f f' a\" :=\n (@rel_adjunction T T' h (frel f) (frel f') a)\n (at level 10, T, T', h, f, f', a at level 8, only parsing) : type_scope.\n\nArguments intro_adjunction [T T' h e e'] _ [a].\nArguments adjunction_n_comp [T T'] h [e e'] _ _ [a].", - "boot.finset": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat div seq.\nFrom mathcomp Require Import choice fintype finfun bigop.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope set_scope.\n\nSection SetType.\n\nVariable T : finType.\n\n(**)\nInductive set_type : predArgType := FinSet of {ffun pred T}.\n(*This definition extracts the underlying finite function, which represents the characteristic predicate, from a given set.*)\nDefinition finfun_of_set A := let: FinSet f := A in f.\n(*This definition provides an alias for the type of finite sets over a given finite base type.*)\nDefinition set_of := set_type.\nIdentity Coercion type_of_set_of : set_of >-> set_type.\n\n(*This definition establishes that the type of sets is a new subtype, defined by projecting to the underlying finite function representation.*)\nDefinition set_isSub := Eval hnf in [isNew for finfun_of_set].\nHB.instance Definition _ := set_isSub.\n(*A notation for the type of finite sets whose elements are drawn from a given finite type.*)\nNotation \"{ 'set' T }\" := (set_of T) (format \"{ 'set' T }\") : type_scope.\n\n(*A notation for the equality relation between two sets, asserting that they are the same set.*)\nNotation \"A :=: B\" := (A = B :> {set _})\n (at level 70, no associativity, only parsing) : set_scope.\n(*A notation for the inequality relation between two sets, asserting that they are not the same set.*)\nNotation \"A :<>: B\" := (A <> B :> {set _})\n (at level 70, no associativity, only parsing) : set_scope.\n(*A notation for the boolean equality test between two sets, which evaluates to a boolean value indicating whether they are equal.*)\nNotation \"A :==: B\" := (A == B :> {set _})\n (at level 70, no associativity, only parsing) : set_scope.\n(*A notation for the boolean inequality test between two sets, which evaluates to a boolean value indicating whether they are not equal.*)\nNotation \"A :!=: B\" := (A != B :> {set _})\n (at level 70, no associativity, only parsing) : set_scope.\n(*A notation for the proof-irrelevant propositional equality between two sets.*)\nNotation \"A :=P: B\" := (A =P B :> {set _})\n (at level 70, no associativity, only parsing) : set_scope.\n\nHB.lock\n(*This definition constructs a finite set over a given finite type from a decidable predicate on that type. The resulting set contains all elements for which the predicate is true.*)\nDefinition finset (T : finType) (P : pred T) : {set T} := @FinSet T (finfun P).\nCanonical finset_unlock := Unlockable finset.unlock.\n\nHB.lock\n(*This definition extracts the characteristic predicate from a given finite set. The resulting predicate returns true for elements that are members of the set and false otherwise.*)\nDefinition pred_of_set T (A : set_type T) : fin_pred_sort (predPredType T)\n:= val A.\nCanonical pred_of_set_unlock := Unlockable pred_of_set.unlock.\n\n(*A notation for defining a set by comprehension, specifying the type of the elements, the variable representing an element, and a boolean property that elements must satisfy to be included in the set.*)\nNotation \"[ 'set' x : T | P ]\" := (finset (fun x : T => P%B))\n (x at level 99, only parsing) : set_scope.\n(*A notation for defining a set by comprehension, specifying a variable representing an element and a boolean property that elements must satisfy. The element type is inferred from the context.*)\nNotation \"[ 'set' x | P ]\" := [set x : _ | P]\n (P at level 99, format \"[ 'set' x | P ]\") : set_scope.\n(*A notation that defines a new set containing all elements from a given collection.*)\nNotation \"[ 'set' x 'in' A ]\" := [set x | x \\in A]\n (format \"[ 'set' x 'in' A ]\") : set_scope.\n(*An explicitly typed notation for defining a new set containing all elements of a specified type from a given collection.*)\nNotation \"[ 'set' x : T 'in' A ]\" := [set x : T | x \\in A]\n (only parsing) : set_scope.\n(*A notation for defining a set by comprehension, specifying the type of the elements and two boolean properties connected by a logical AND, both of which must be satisfied for an element to be included.*)\nNotation \"[ 'set' x : T | P & Q ]\" := [set x : T | P && Q]\n (only parsing) : set_scope.\n(*A notation for defining a set by comprehension with two boolean properties connected by a logical AND, where the element type is inferred from the context.*)\nNotation \"[ 'set' x | P & Q ]\" := [set x | P && Q ]\n (P at level 99, format \"[ 'set' x | P & Q ]\") : set_scope.\n(*A notation for defining a set containing all elements of a specified type that are members of a given collection and also satisfy an additional boolean property.*)\nNotation \"[ 'set' x : T 'in' A | P ]\" := [set x : T | x \\in A & P]\n (only parsing) : set_scope.\n(*A notation for defining a set containing all elements that are members of a given collection and also satisfy an additional boolean property, where the element type is inferred.*)\nNotation \"[ 'set' x 'in' A | P ]\" := [set x | x \\in A & P]\n (format \"[ 'set' x 'in' A | P ]\") : set_scope.\n(*A notation for defining a set containing all elements from a given collection that also satisfy two additional boolean properties connected by a logical AND.*)\nNotation \"[ 'set' x 'in' A | P & Q ]\" := [set x in A | P && Q]\n (format \"[ 'set' x 'in' A | P & Q ]\") : set_scope.\n(*A notation for defining a set containing all elements of a specified type from a given collection that also satisfy two additional boolean properties joined by a logical AND.*)\nNotation \"[ 'set' x : T 'in' A | P & Q ]\" := [set x : T in A | P && Q]\n (only parsing) : set_scope.\n\n(*A notation for creating a finite set containing exactly the elements present in a given finite sequence. Duplicate elements in the sequence are ignored.*)\nNotation \"[ 'set' :: s ]\" := (finset [in pred_of_seq s])\n (format \"[ 'set' :: s ]\") : set_scope.\n\nCoercion pred_of_set: set_type >-> fin_pred_sort.\n\nCanonical set_predType T := @PredType _ (unkeyed (set_type T)) (@pred_of_set T).\n\nSection BasicSetTheory.\n\nVariable T : finType.\nImplicit Types (x : T) (A B : {set T}) (pA : pred T).\n\n(*This lemma states that an element is a member of a set constructed from a predicate if and only if the element satisfies that predicate.*)\nLemma in_set pA x : x \\in finset pA = pA x.\n\n(*This lemma asserts the principle of extensionality for finite sets, stating that two sets are equal if and only if they contain the same elements.*)\nLemma setP A B : A =i B <-> A = B.\n\n(*This definition provides a name for the empty set over a given finite type, defined as the set containing no elements.*)\nDefinition set0 := [set x : T | false].\n(*This definition provides a name for the universal set over a given finite type, defined as the set containing all elements of that type.*)\nDefinition setTfor := [set x : T | true].\n\n(*This lemma states that any element of a given finite type is a member of the universal set of that type.*)\nLemma in_setT x : x \\in setTfor.\n\n(*This lemma states that for any two sets, the proposition that they are equal is logically equivalent to their boolean equality test evaluating to true, and the proposition that they are not equal is logically equivalent to their boolean equality test evaluating to false.*)\nLemma eqsVneq A B : eq_xor_neq A B (B == A) (A == B).\n\n(*This lemma states that if two predicates are functionally extensional, meaning they produce the same boolean value for every input, then the finite sets constructed from these predicates are equal.*)\nLemma eq_finset (pA pB : pred T) : pA =1 pB -> finset pA = finset pB.\n\nEnd BasicSetTheory.\n\nArguments eqsVneq {T} A B, {T A B}.\n\nArguments set0 {T}.\nArguments setTfor T%_type.\nArguments eq_finset {T} [pA] pB eq_pAB.\n#[global] Hint Resolve in_setT : core.\n\n(*A notation for the universal set over a given finite type, which contains all elements of that type.*)\nNotation \"[ 'set' : T ]\" := (setTfor T) (format \"[ 'set' : T ]\") : set_scope.\n\n(*A parsing-only notation for the type of finite sets whose elements are of an inferred type.*)\nNotation setT := [set: _] (only parsing).\n\nHB.lock\n(*This definition defines a singleton set as a set containing exactly one specified element.*)\nDefinition set1 (T : finType) (a : T) := [set x | x == a].\n\nSection setOpsDefs.\n\nVariable T : finType.\nImplicit Types (a x : T) (A B D : {set T}) (P : {set {set T}}).\n\n(*This definition defines the union of two sets as a new set containing all elements present in either of the input sets.*)\nDefinition setU A B := [set x | (x \\in A) || (x \\in B)].\n(*This definition defines the intersection of two sets as a new set containing only the elements that are present in both of the input sets.*)\nDefinition setI A B := [set x in A | x \\in B].\n(*This definition defines the complement of a set as a new set containing all elements of the governing finite type that are not in the input set.*)\nDefinition setC A := [set x | x \\notin A].\n(*This definition defines the difference between two sets as a new set containing all elements that are in the first set but not in the second set.*)\nDefinition setD A B := [set x | x \\notin B & x \\in A].\n(*This definition defines an operation that filters a given set of sets, producing a new set of sets that includes only those member sets that are subsets of a specified set.*)\nDefinition ssetI P D := [set A in P | A \\subset D].\n(*This definition defines the powerset of a given set as the set of all its subsets.*)\nDefinition powerset D := [set A : {set T} | A \\subset D].\n\nEnd setOpsDefs.\n\n(*A notation for creating a singleton set containing a single specified element.*)\nNotation \"[ 'set' a ]\" := (set1 a)\n (a at level 99, format \"[ 'set' a ]\") : set_scope.\n(*A notation for creating a singleton set containing a single element, with an explicit specification of the element's type.*)\nNotation \"[ 'set' a : T ]\" := [set (a : T)]\n (a at level 99, format \"[ 'set' a : T ]\") : set_scope.\n(*A notation for the union of two sets.*)\nNotation \"A :|: B\" := (setU A B) : set_scope.\n(*A notation for adding a single element to a set.*)\nNotation \"a |: A\" := ([set a] :|: A) : set_scope.\n\n(*A notation for constructing a set from an explicit list of elements.*)\nNotation \"[ 'set' a1 ; a2 ; .. ; an ]\" := (setU .. (a1 |: [set a2]) .. [set an])\n (format \"[ 'set' a1 ; a2 ; .. ; an ]\") : set_scope.\n(*A notation for the intersection of two sets.*)\nNotation \"A :&: B\" := (setI A B) : set_scope.\n(*A notation for the complement of a set.*)\nNotation \"~: A\" := (setC A) (at level 35, right associativity) : set_scope.\n(*A notation for the complement of a singleton set, representing the set of all elements except for one specified element.*)\nNotation \"[ 'set' ~ a ]\" := (~: [set a])\n (format \"[ 'set' ~ a ]\") : set_scope.\n(*A notation for the difference between two sets, containing elements in the first set but not the second.*)\nNotation \"A :\\: B\" := (setD A B) : set_scope.\n(*A notation for removing a single element from a set.*)\nNotation \"A :\\ a\" := (A :\\: [set a]) : set_scope.\n(*A notation for selecting all sets from a given collection of sets that are subsets of a specified set.*)\nNotation \"P ::&: D\" := (ssetI P D) (at level 48) : set_scope.\n\nSection setOps.\n\nVariable T : finType.\nImplicit Types (a x : T) (A B C D : {set T}) (pA pB pC : pred T).\n\n(*This lemma states that two sets are equal if and only if the first set is a subset of the second and the second set is a subset of the first.*)\nLemma eqEsubset A B : (A == B) = (A \\subset B) && (B \\subset A).\n\n(*This lemma states that a set is a subset of another if and only if the two sets are equal or the first set is a proper subset of the second.*)\nLemma subEproper A B : A \\subset B = (A == B) || (A \\proper B).\n\n(*This lemma states that if a set is a subset of another, then either the two sets are equal or the first set is a proper subset of the second.*)\nLemma eqVproper A B : A \\subset B -> A = B \\/ A \\proper B.\n\n(*This lemma states that a set is a proper subset of another if and only if the two sets are not equal and the first set is a subset of the second.*)\nLemma properEneq A B : A \\proper B = (A != B) && (A \\subset B).\n\n(*This lemma states that if a set is a proper subset of another, then the two sets are not equal.*)\nLemma proper_neq A B : A \\proper B -> A != B.\n\n(*This lemma states that two sets are equal if and only if the first set is a subset of the second, and the first set is not a proper subset of the second.*)\nLemma eqEproper A B : (A == B) = (A \\subset B) && ~~ (A \\proper B).\n\n(*This lemma states that two sets are equal if and only if the first set is a subset of the second and the cardinality of the second set is less than or equal to the cardinality of the first.*)\nLemma eqEcard A B : (A == B) = (A \\subset B) && (#|B| <= #|A|).\n\n(*This lemma states that a set is a proper subset of another if and only if it is a subset of the second set and its cardinality is strictly less than the cardinality of the second set.*)\nLemma properEcard A B : (A \\proper B) = (A \\subset B) && (#|A| < #|B|).\n\n(*This lemma states that for a set that is a subset of another, the proposition that the first set's cardinality is less than or equal to the second's is logically equivalent to the proposition that the two sets are equal.*)\nLemma subset_leqif_cards A B : A \\subset B -> (#|A| <= #|B| ?= iff (A == B)).\n\n(*This lemma states that the proposition of an element being a member of the empty set is equivalent to false.*)\nLemma in_set0 x : x \\in set0 = false.\n\n(*This lemma states that the empty set is a subset of any given set.*)\nLemma sub0set A : set0 \\subset A.\n\n(*This lemma states that a given set is a subset of the empty set if and only if that set is itself the empty set.*)\nLemma subset0 A : (A \\subset set0) = (A == set0).\n\n(*This lemma states that the empty set is a proper subset of a given set if and only if the given set is not empty.*)\nLemma proper0 A : (set0 \\proper A) = (A != set0).\n\n(*This lemma states that if a non-empty set is a subset of another set, then the other set must also be non-empty.*)\nLemma subset_neq0 A B : A \\subset B -> A != set0 -> B != set0.\n\n(*This lemma provides a constructive proof that any given set is either equal to the empty set or it contains at least one element.*)\nLemma set_0Vmem A : (A = set0) + {x : T | x \\in A}.\n\n(*This lemma states that creating a set from the sequence of elements enumerated from a given finite set results in the original set.*)\nLemma set_enum A : [set x | x \\in enum A] = A.\n\n(*This lemma states that the enumeration of the empty set yields an empty sequence.*)\nLemma enum_set0 : enum set0 = [::] :> seq T.\n\n(*This lemma states that any given set is a subset of the universal set containing all elements of the type.*)\nLemma subsetT A : A \\subset setT.\n\n(*This lemma registers a proof hint that any given set is a subset of the universal set, which can be automatically used by proof search.*)\nLemma subsetT_hint mA : subset mA (mem [set: T]).\n\nHint Resolve subsetT_hint : core.\n\n(*This lemma states that the universal set is a subset of a given set if and only if the given set is equal to the universal set.*)\nLemma subTset A : (setT \\subset A) = (A == setT).\n\n(*This lemma states that a given set is a proper subset of the universal set if and only if the given set is not equal to the universal set.*)\nLemma properT A : (A \\proper setT) = (A != setT).\n\n(*This lemma states that an element is a member of a singleton set if and only if that element is equal to the single element contained in the set.*)\nLemma set1P x a : reflect (x = a) (x \\in [set a]).\n\n(*This lemma states that the enumeration of the universal set, which contains all elements of a finite type, is equivalent to the direct enumeration of all elements of that finite type.*)\nLemma enum_setT : enum [set: T] = Finite.enum T.\n\n(*This lemma states that the boolean proposition of an element being a member of a singleton set is equivalent to the boolean equality test between that element and the single element in the set.*)\nLemma in_set1 x a : (x \\in [set a]) = (x == a).\n\n(*This definition groups together a collection of simplification lemmas related to set membership, intended for use with rewriting tactics.*)\nDefinition inE := (in_set, in_set1, inE).\n\n(*This lemma states that any given element is a member of the singleton set containing that same element.*)\nLemma set11 x : x \\in [set x].\n\n(*This lemma states that the function that creates a singleton set from an element is injective, meaning that if two elements produce the same singleton set, the elements themselves must be equal.*)\nLemma set1_inj : injective (@set1 T).\n\n(*This lemma states that the enumeration of a singleton set containing a specific element results in a sequence containing only that element.*)\nLemma enum_set1 a : enum [set a] = [:: a].\n\n(*This lemma states that an element belongs to the union of a singleton set and another set if and only if the element is either equal to the element in the singleton set or is a member of the other set.*)\nLemma setU1P x a B : reflect (x = a \\/ x \\in B) (x \\in a |: B).\n\n(*This lemma states that the boolean proposition of an element being a member of the union of a singleton set and another set is equivalent to the boolean disjunction of two conditions: the element being equal to the singleton's element, or the element being a member of the other set.*)\nLemma in_setU1 x a B : (x \\in a |: B) = (x == a) || (x \\in B).\n\n(*This lemma states that constructing a set from an empty sequence of elements results in the empty set.*)\nLemma set_nil : [set:: nil] = @set0 T. \n\n(*This lemma states that constructing a set from a sequence containing a single element is equivalent to creating a singleton set with that same element.*)\nLemma set_seq1 a : [set:: [:: a]] = [set a].\n\n(*This lemma provides a recursive definition for constructing a set from a sequence of elements, stating that the set formed from a non-empty sequence is equal to the union of the singleton set of the first element and the set formed from the remainder of the sequence.*)\nLemma set_cons a s : [set:: a :: s] = a |: [set:: s].\n\n(*This lemma states that a given element is always a member of the set formed by the union of its own singleton set and any other set.*)\nLemma setU11 x B : x \\in x |: B.\n\n(*This lemma states that if an element is a member of a given set, it is also a member of any set formed by taking the union of that given set with a singleton set.*)\nLemma setU1r x a B : x \\in B -> x \\in a |: B.\n\n(*This lemma states that if an element is a member of a given set, it is also a member of the union of that set with any singleton set.*)\nLemma set1Ul x A b : x \\in A -> x \\in A :|: [set b].\n\n(*This lemma states that a given element is always a member of the set formed by the union of any set with the singleton set of that element.*)\nLemma set1Ur A b : b \\in A :|: [set b].\n\n(*This lemma states that the boolean proposition of an element being a member of the complement of a singleton set is equivalent to the boolean test for inequality between that element and the element in the singleton set.*)\nLemma in_setC1 x a : (x \\in [set~ a]) = (x != a).\n\n(*This lemma states that an element is never a member of the complement of its own singleton set, which is a proposition that always evaluates to false.*)\nLemma setC11 x : (x \\in [set~ x]) = false.\n\n(*This lemma states that an element belongs to the set difference between a given set and a singleton set if and only if the element is a member of the given set and is not equal to the element in the singleton set.*)\nLemma setD1P x A b : reflect (x != b /\\ x \\in A) (x \\in A :\\ b).\n\n(*This lemma states that an element is in a set from which another element has been removed if and only if the first element is not equal to the removed element and was originally in the set.*)\nLemma in_setD1 x A b : (x \\in A :\\ b) = (x != b) && (x \\in A) .\n\n(*This lemma states that an element is never a member of a set from which that same element has been removed.*)\nLemma setD11 b A : (b \\in A :\\ b) = false.\n\n(*This lemma states that if an element is a member of a given set, then adding that element back to the set after it has been removed results in the original set.*)\nLemma setD1K a A : a \\in A -> a |: (A :\\ a) = A.\n\n(*This lemma states that if an element is not a member of a given set, then removing that element from the set after it has been added results in the original set.*)\nLemma setU1K a B : a \\notin B -> (a |: B) :\\ a = B.\n\n(*This lemma provides a boolean reflection, stating that an element is a member of a two-element set if and only if it is equal to either of the two elements in that set.*)\nLemma set2P x a b : reflect (x = a \\/ x = b) (x \\in [set a; b]).\n\n(*This lemma states that the boolean property of an element being in a set containing two specific elements is equivalent to the disjunction of the boolean equality checks of the element with each of the two specific elements.*)\nLemma in_set2 x a b : (x \\in [set a; b]) = (x == a) || (x == b).\n\n(*This lemma states that the first of two specified elements is a member of the set containing only those two elements.*)\nLemma set21 a b : a \\in [set a; b].\n\n(*This lemma states that the second of two specified elements is a member of the set containing only those two elements.*)\nLemma set22 a b : b \\in [set a; b].\n\n(*This lemma provides a boolean reflection, stating that an element is in the union of two sets if and only if it is in the first set or in the second set.*)\nLemma setUP x A B : reflect (x \\in A \\/ x \\in B) (x \\in A :|: B).\n\n(*This lemma states that the boolean property of an element being in the union of two sets is equivalent to the disjunction of the boolean properties of the element being in each of the two sets.*)\nLemma in_setU x A B : (x \\in A :|: B) = (x \\in A) || (x \\in B).\n\n(*This lemma states that the union of two sets is commutative.*)\nLemma setUC A B : A :|: B = B :|: A.\n\n(*This lemma states that if a first set is a subset of a second set, then the union of a third set with the first set is a subset of the union of the third set with the second set.*)\nLemma setUS A B C : A \\subset B -> C :|: A \\subset C :|: B.\n\n(*This lemma states that if a first set is a subset of a second set, then the union of the first set with a third set is a subset of the union of the second set with the third set.*)\nLemma setSU A B C : A \\subset B -> A :|: C \\subset B :|: C.\n\n(*This lemma states that the union operation is monotonic with respect to the subset relation; if a first set is a subset of a third set and a second set is a subset of a fourth set, then the union of the first and second sets is a subset of the union of the third and fourth sets.*)\nLemma setUSS A B C D : A \\subset C -> B \\subset D -> A :|: B \\subset C :|: D.\n\n(*This lemma states that the empty set is the left identity element for the set union operation.*)\nLemma set0U A : set0 :|: A = A.\n\n(*This lemma states that the empty set is the right identity element for the set union operation.*)\nLemma setU0 A : A :|: set0 = A.\n\n(*This lemma states that the union of a set with the union of two other sets is equal to the union of all three sets, demonstrating right-associativity.*)\nLemma setUA A B C : A :|: (B :|: C) = A :|: B :|: C.\n\n(*This lemma states a commutativity property for set union, allowing the first two sets in a nested union to be exchanged.*)\nLemma setUCA A B C : A :|: (B :|: C) = B :|: (A :|: C).\n\n(*This lemma states that the last two sets in a three-set union can be exchanged.*)\nLemma setUAC A B C : A :|: B :|: C = A :|: C :|: B.\n\n(*This lemma states a mixed associativity and commutativity property for set union, showing that the union of two unions can be reordered by taking the union of the first components and the union of the second components.*)\nLemma setUACA A B C D : (A :|: B) :|: (C :|: D) = (A :|: C) :|: (B :|: D).\n\n(*This lemma states that the universal set is a left absorbing element for the set union operation.*)\nLemma setTU A : setT :|: A = setT.\n\n(*This lemma states that the universal set is a right absorbing element for the set union operation.*)\nLemma setUT A : A :|: setT = setT.\n\n(*This lemma states that the set union operation is idempotent, meaning the union of a set with itself is the set itself.*)\nLemma setUid A : A :|: A = A.\n\n(*This lemma states that a union of three sets can be re-expressed as the union of two unions, each containing the third set.*)\nLemma setUUl A B C : A :|: B :|: C = (A :|: C) :|: (B :|: C).\n\n(*This lemma states that set union distributes over itself from the right, where the union of a first set with a union of two others equals the union of the unions of the first set with each of the other two.*)\nLemma setUUr A B C : A :|: (B :|: C) = (A :|: B) :|: (A :|: C).\n\n(*This lemma provides a boolean reflection, stating that an element belongs to a set defined by the conjunction of two predicates if and only if the element satisfies both predicates.*)\nLemma setIdP x pA pB : reflect (pA x /\\ pB x) (x \\in [set y | pA y & pB y]).\n\n(*This lemma provides a boolean reflection, stating that an element belongs to a set defined by the conjunction of three predicates if and only if the element satisfies all three predicates.*)\nLemma setId2P x pA pB pC :\n reflect [/\\ pA x, pB x & pC x] (x \\in [set y | pA y & pB y && pC y]).\n\n(*This lemma states that the set of elements within a given set that satisfy a certain predicate is equal to the intersection of the given set and the set of all elements satisfying that predicate.*)\nLemma setIdE A pB : [set x in A | pB x] = A :&: [set x | pB x].\n\n(*This lemma provides a boolean reflection, stating that an element is in the intersection of two sets if and only if it is in the first set and in the second set.*)\nLemma setIP x A B : reflect (x \\in A /\\ x \\in B) (x \\in A :&: B).\n\n(*This lemma states that the boolean property of an element being in the intersection of two sets is equivalent to the conjunction of the boolean properties of the element being in each of the two sets.*)\nLemma in_setI x A B : (x \\in A :&: B) = (x \\in A) && (x \\in B).\n\n(*This lemma states that the intersection of two sets is commutative, meaning the order in which the sets are intersected does not change the result.*)\nLemma setIC A B : A :&: B = B :&: A.\n\n(*This lemma states that if a first set is a subset of a second set, then intersecting a third set with the first set results in a subset of the intersection of the third set with the second set.*)\nLemma setIS A B C : A \\subset B -> C :&: A \\subset C :&: B.\n\n(*This lemma states that if a first set is a subset of a second set, then the intersection of the first set with a third set is a subset of the intersection of the second set with the third set.*)\nLemma setSI A B C : A \\subset B -> A :&: C \\subset B :&: C.\n\n(*This lemma states that the intersection operation is monotonic with respect to the subset relation; if a first set is a subset of a third set and a second set is a subset of a fourth set, then the intersection of the first and second sets is a subset of the intersection of the third and fourth sets.*)\nLemma setISS A B C D : A \\subset C -> B \\subset D -> A :&: B \\subset C :&: D.\n\n(*This lemma states that the universal set acts as a left identity for the intersection operation; intersecting the universal set with any given set yields the given set itself.*)\nLemma setTI A : setT :&: A = A.\n\n(*This lemma states that the universal set acts as a right identity for the intersection operation; intersecting any given set with the universal set yields the given set itself.*)\nLemma setIT A : A :&: setT = A.\n\n(*This lemma states that the empty set is a left annihilator for the intersection operation; intersecting the empty set with any given set yields the empty set.*)\nLemma set0I A : set0 :&: A = set0.\n\n(*This lemma states that the empty set is a right annihilator for the intersection operation; intersecting any given set with the empty set yields the empty set.*)\nLemma setI0 A : A :&: set0 = set0.\n\n(*This lemma states that set intersection is associative, meaning that the intersection of a set with the intersection of two other sets is equivalent to the intersection of the first two sets intersected with the third.*)\nLemma setIA A B C : A :&: (B :&: C) = A :&: B :&: C.\n\n(*This lemma states a combined associativity and commutativity property for set intersection, asserting that intersecting a set with the intersection of two others is equivalent to intersecting the second set with the intersection of the first and third.*)\nLemma setICA A B C : A :&: (B :&: C) = B :&: (A :&: C).\n\n(*This lemma provides a rule for reordering a chain of three set intersections, stating that the result is unchanged if the second and third sets are swapped.*)\nLemma setIAC A B C : A :&: B :&: C = A :&: C :&: B.\n\n(*This lemma states that the intersection of two separate intersections can be re-parenthesized, such that it is equivalent to the intersection of the first sets from each pair, intersected with the intersection of the second sets from each pair.*)\nLemma setIACA A B C D : (A :&: B) :&: (C :&: D) = (A :&: C) :&: (B :&: D).\n\n(*This lemma states that set intersection is idempotent, meaning that intersecting a set with itself yields the original set.*)\nLemma setIid A : A :&: A = A.\n\n(*This lemma states that a chain of three set intersections is equivalent to the intersection of two pairs, where a common third set is intersected with each of the first two sets individually.*)\nLemma setIIl A B C : A :&: B :&: C = (A :&: C) :&: (B :&: C).\n\n(*This lemma states that intersecting a set with the intersection of two other sets is equivalent to intersecting the first set with the second, and then intersecting that result with the intersection of the first set and the third.*)\nLemma setIIr A B C : A :&: (B :&: C) = (A :&: B) :&: (A :&: C).\n\n(*This lemma states that set intersection distributes over set union from the right.*)\nLemma setIUr A B C : A :&: (B :|: C) = (A :&: B) :|: (A :&: C).\n\n(*This lemma states that set intersection distributes over set union from the left.*)\nLemma setIUl A B C : (A :|: B) :&: C = (A :&: C) :|: (B :&: C).\n\n(*This lemma states that set union distributes over set intersection from the right.*)\nLemma setUIr A B C : A :|: (B :&: C) = (A :|: B) :&: (A :|: C).\n\n(*This lemma states that the union of a third set with the intersection of a first and second set is equivalent to the intersection of two unions: the union of the first set and the third set, and the union of the second set and the third set.*)\nLemma setUIl A B C : (A :&: B) :|: C = (A :|: C) :&: (B :|: C).\n\n(*This lemma states an absorption law for sets, asserting that the intersection of a set with the union of itself and another set yields the original set.*)\nLemma setUK A B : (A :|: B) :&: A = A.\n\n(*This lemma states an absorption law for sets, asserting that intersecting a set with the union of another set and itself results in the original set.*)\nLemma setKU A B : A :&: (B :|: A) = A.\n\n(*This lemma states an absorption law for sets, asserting that the union of a set with the intersection of itself and another set yields the original set.*)\nLemma setIK A B : (A :&: B) :|: A = A.\n\n(*This lemma states an absorption law for sets, asserting that taking the union of a set with the intersection of another set and itself results in the original set.*)\nLemma setKI A B : A :|: (B :&: A) = A.\n\n(*This lemma establishes the logical equivalence between the proposition that an element is in the complement of a set and the boolean statement that the element is not in the original set.*)\nLemma setCP x A : reflect (~ x \\in A) (x \\in ~: A).\n\n(*This lemma states that an element is a member of the complement of a set if and only if that element is not a member of the original set.*)\nLemma in_setC x A : (x \\in ~: A) = (x \\notin A).\n\n(*This lemma states that the set complement operation is an involution, meaning that applying the complement operation twice to any set returns the original set.*)\nLemma setCK : involutive (@setC T).\n\n(*This lemma states that the set complement operation is injective, meaning that if two sets have the same complement, then the sets themselves must be equal.*)\nLemma setC_inj : injective (@setC T).\n\n(*This lemma states that a first set is a subset of a second set if and only if the first set and the complement of the second set are disjoint.*)\nLemma subsets_disjoint A B : (A \\subset B) = [disjoint A & ~: B].\n\n(*This lemma states that two sets are disjoint if and only if the first set is a subset of the complement of the second set.*)\nLemma disjoints_subset A B : [disjoint A & B] = (A \\subset ~: B).\n\n(*This lemma states that a first set is an element of the powerset of the complement of a second set if and only if the first and second sets are disjoint.*)\nLemma powersetCE A B : (A \\in powerset (~: B)) = [disjoint A & B].\n\n(*This lemma states that for any two sets, the complement of the first set is a subset of the complement of the second set if and only if the second set is a subset of the first.*)\nLemma setCS A B : (~: A \\subset ~: B) = (B \\subset A).\n\n(*This lemma states that for any two sets, the complement of their union is equal to the intersection of their complements.*)\nLemma setCU A B : ~: (A :|: B) = ~: A :&: ~: B.\n\n(*This lemma states that for any two sets, the complement of their intersection is equal to the union of their complements.*)\nLemma setCI A B : ~: (A :&: B) = ~: A :|: ~: B.\n\n(*This lemma states that the union of any set with its complement is equal to the universal set.*)\nLemma setUCr A : A :|: ~: A = setT.\n\n(*This lemma states that the intersection of any set with its complement is equal to the empty set.*)\nLemma setICr A : A :&: ~: A = set0.\n\n(*This lemma states that the complement of the empty set is equal to the universal set.*)\nLemma setC0 : ~: set0 = [set: T].\n\n(*This lemma states that the complement of the universal set is equal to the empty set.*)\nLemma setCT : ~: [set: T] = set0.\n\n(*This lemma states that for any two sets, the complement of the second set is a proper subset of the complement of the first set if and only if the first set is a proper subset of the second.*)\nLemma properC A B : (~: B \\proper ~: A) = (A \\proper B).\n\n(*This lemma states that an element belongs to the difference of a first and a second set if and only if the element is in the first set and not in the second set.*)\nLemma setDP A B x : reflect (x \\in A /\\ x \\notin B) (x \\in A :\\: B).\n\n(*This lemma states that the boolean check for an element's membership in the difference of a first and a second set is equivalent to checking that the element is not in the second set and is in the first set.*)\nLemma in_setD A B x : (x \\in A :\\: B) = (x \\notin B) && (x \\in A).\n\n(*This lemma states that the difference of a first set and a second set is equal to the intersection of the first set and the complement of the second set.*)\nLemma setDE A B : A :\\: B = A :&: ~: B.\n\n(*This lemma states that if a first set is a subset of a second set, then the difference of the first set and a third set is a subset of the difference of the second set and the third set.*)\nLemma setSD A B C : A \\subset B -> A :\\: C \\subset B :\\: C.\n\n(*This lemma states that if a first set is a subset of a second set, then the difference of a third set and the second set is a subset of the difference of the third set and the first set.*)\nLemma setDS A B C : A \\subset B -> C :\\: B \\subset C :\\: A.\n\n(*This lemma states that if a first set is a subset of a third set and a fourth set is a subset of a second set, then the difference of the first and second sets is a subset of the difference of the third and fourth sets.*)\nLemma setDSS A B C D : A \\subset C -> D \\subset B -> A :\\: B \\subset C :\\: D.\n\n(*This lemma states that the difference between any set and the empty set is the original set.*)\nLemma setD0 A : A :\\: set0 = A.\n\n(*This lemma states that the difference between the empty set and any other set is the empty set.*)\nLemma set0D A : set0 :\\: A = set0.\n\n(*This lemma states that the difference between any set and the universal set is the empty set.*)\nLemma setDT A : A :\\: setT = set0.\n\n(*This lemma states that the difference between the universal set and any given set is the complement of that set.*)\nLemma setTD A : setT :\\: A = ~: A.\n\n(*This lemma states that the difference of any set with itself is the empty set.*)\nLemma setDv A : A :\\: A = set0.\n\n(*This lemma states that the complement of the difference of a first and a second set is equal to the union of the complement of the first set and the second set.*)\nLemma setCD A B : ~: (A :\\: B) = ~: A :|: B.\n\n(*This lemma states that the union of the intersection of a first and second set with the difference of the first and second set is equal to the first set.*)\nLemma setID A B : A :&: B :|: A :\\: B = A.\n\n(*This lemma states that the set difference operator distributes over the set union operator from the left; that is, the difference of a union of two sets and a third set is the union of their individual differences with the third set.*)\nLemma setDUl A B C : (A :|: B) :\\: C = (A :\\: C) :|: (B :\\: C).\n\n(*This lemma states that the set difference of a first set with the union of a second and third set is equal to the intersection of two set differences: the first set minus the second, and the first set minus the third.*)\nLemma setDUr A B C : A :\\: (B :|: C) = (A :\\: B) :&: (A :\\: C).\n\n(*This lemma states that the set difference operator distributes over the set intersection operator from the left; that is, the difference of an intersection of two sets and a third set is the intersection of their individual differences with the third set.*)\nLemma setDIl A B C : (A :&: B) :\\: C = (A :\\: C) :&: (B :\\: C).\n\n(*This lemma states that intersecting a first set with the difference of a second and third set is equivalent to taking the difference between the intersection of the first and second sets, and the third set.*)\nLemma setIDA A B C : A :&: (B :\\: C) = (A :&: B) :\\: C.\n\n(*This lemma states that taking the intersection of a set difference with a third set is equivalent to first intersecting the minuend set with the third set, and then taking the difference with the subtrahend set.*)\nLemma setIDAC A B C : (A :\\: B) :&: C = (A :&: C) :\\: B.\n\n(*This lemma states that the set difference of a first set with the intersection of a second and third set is equal to the union of two set differences: the first set minus the second, and the first set minus the third.*)\nLemma setDIr A B C : A :\\: (B :&: C) = (A :\\: B) :|: (A :\\: C).\n\n(*This lemma states that taking the set difference of an initial set difference with a third set is equivalent to taking the set difference of the original minuend with the union of the two subtrahend sets.*)\nLemma setDDl A B C : (A :\\: B) :\\: C = A :\\: (B :|: C).\n\n(*This lemma states that the difference of a first set with the difference of a second and third set is equal to the union of two other sets: the difference of the first and second sets, and the intersection of the first and third sets.*)\nLemma setDDr A B C : A :\\: (B :\\: C) = (A :\\: B) :|: (A :&: C).\n\n(*This lemma states that a given set is an element of the powerset of a second set if and only if the given set is a subset of the second set.*)\nLemma powersetE A B : (A \\in powerset B) = (A \\subset B).\n\n(*This lemma states that the powerset of a first set is a subset of the powerset of a second set if and only if the first set is a subset of the second set.*)\nLemma powersetS A B : (powerset A \\subset powerset B) = (A \\subset B).\n\n(*This lemma states that the powerset of the empty set is equal to the singleton set containing the empty set.*)\nLemma powerset0 : powerset set0 = [set set0] :> {set {set T}}.\n\n(*This lemma states that the powerset of the universal set over a given type is equal to the universal set of all subsets of that type.*)\nLemma powersetT : powerset [set: T] = [set: {set T}].\n\n(*This lemma states that the intersection of a collection of sets with the powerset of a given set is equivalent to filtering the collection to retain only those sets that are subsets of the given set.*)\nLemma setI_powerset P A : P :&: powerset A = P ::&: A.\n\n(*This lemma states that the cardinality of a set constructed by enumerating all elements of an existing set is equal to the cardinality of the original set.*)\nLemma cardsE pA : #|[set x in pA]| = #|pA|.\n\n(*This lemma states that the sum of the number one over all elements satisfying a given predicate is equal to the cardinality of the set of elements that satisfy that predicate.*)\nLemma sum1dep_card pA : \\sum_(x | pA x) 1 = #|[set x | pA x]|.\n\n(*This lemma states that the sum of a constant natural number over all elements satisfying a given predicate is equal to the product of the cardinality of the set of satisfying elements and that constant natural number.*)\nLemma sum_nat_cond_const pA n : \\sum_(x | pA x) n = #|[set x | pA x]| * n.\n\n(*This lemma states that the cardinality of the empty set is zero.*)\nLemma cards0 : #|@set0 T| = 0.\n\n(*This lemma states that the cardinality of a set is equal to zero if and only if the set is the empty set.*)\nLemma cards_eq0 A : (#|A| == 0) = (A == set0).\n\n(*This lemma states that a set is non-empty if and only if there exists an element in that set.*)\nLemma set0Pn A : reflect (exists x, x \\in A) (A != set0).\n\n(*This lemma states that a set is equal to the empty set if and only if there does not exist any element in that set.*)\nLemma set0_Nexists A : (A == set0) = ~~ [exists x, x \\in A].\n\n(*This lemma states that the cardinality of a set is greater than zero if and only if the set is non-empty.*)\nLemma card_gt0 A : (0 < #|A|) = (A != set0).\n\n(*This lemma states that if the cardinality of a set is zero, then the set is equal to the empty set.*)\nLemma cards0_eq A : #|A| = 0 -> A = set0.\n\n(*This lemma states that the cardinality of a singleton set is one.*)\nLemma cards1 x : #|[set x]| = 1.\n\n(*This lemma states that for any two sets, the sum of the cardinality of their union and the cardinality of their intersection is equal to the sum of their individual cardinalities.*)\nLemma cardsUI A B : #|A :|: B| + #|A :&: B| = #|A| + #|B|.\n\n(*This lemma states that the cardinality of the union of two sets is equal to the sum of their individual cardinalities minus the cardinality of their intersection.*)\nLemma cardsU A B : #|A :|: B| = #|A| + #|B| - #|A :&: B|.\n\n(*This lemma states that the cardinality of the intersection of two sets is equal to the sum of their individual cardinalities minus the cardinality of their union.*)\nLemma cardsI A B : #|A :&: B| = #|A| + #|B| - #|A :|: B|.\n\n(*This lemma states that the cardinality of the universal set over a given finite type is equal to the cardinality of the type itself.*)\nLemma cardsT : #|[set: T]| = #|T|.\n\n(*This lemma states that the cardinality of a set is the sum of the cardinalities of its intersection with a second set and its difference with that same second set.*)\nLemma cardsID B A : #|A :&: B| + #|A :\\: B| = #|A|.\n\n(*This lemma states that the cardinality of the difference between a first set and a second set is equal to the cardinality of the first set minus the cardinality of their intersection.*)\nLemma cardsD A B : #|A :\\: B| = #|A| - #|A :&: B|.\n\n(*This lemma states that the sum of the cardinality of a set and the cardinality of its complement is equal to the cardinality of the universal set.*)\nLemma cardsC A : #|A| + #|~: A| = #|T|.\n\n(*This lemma states that the cardinality of a set is equal to the cardinality of the universal set minus the cardinality of its complement.*)\nLemma cardsCs A : #|A| = #|T| - #|~: A|.\n\n(*This lemma states that the cardinality of the union of a set with a singleton element is equal to the cardinality of the original set plus one if the element is not in the set, and equal to the cardinality of the original set otherwise.*)\nLemma cardsU1 a A : #|a |: A| = (a \\notin A) + #|A|.\n\n(*This lemma states that the cardinality of a set formed by two elements is two if the elements are distinct, and one if they are equal.*)\nLemma cards2 a b : #|[set a; b]| = (a != b).+1.\n\n(*This lemma states that the cardinality of the complement of a singleton set is equal to the cardinality of the universal set minus one.*)\nLemma cardsC1 a : #|[set~ a]| = #|T|.-1.\n\n(*This lemma states that the cardinality of a set is equal to the cardinality of the set with a specific element removed, plus one if that element was in the original set, and plus zero otherwise.*)\nLemma cardsD1 a A : #|A| = (a \\in A) + #|A :\\ a|.\n\n(*This lemma states that for any two sets, their intersection is a subset of the first set.*)\nLemma subsetIl A B : A :&: B \\subset A.\n\n(*This lemma states that for any two sets, their intersection is a subset of the second set.*)\nLemma subsetIr A B : A :&: B \\subset B.\n\n(*This lemma states that a set is a subset of its union with any other set.*)\nLemma subsetUl A B : A \\subset A :|: B.\n\n(*This lemma states that a set is a subset of the union of any other set with it.*)\nLemma subsetUr A B : B \\subset A :|: B.\n\n(*This lemma states that any given set is a subset of the union of that set and a singleton set containing any given element.*)\nLemma subsetU1 x A : A \\subset x |: A.\n\n(*This lemma states that the set difference of a first set and a second set is always a subset of the first set.*)\nLemma subsetDl A B : A :\\: B \\subset A.\n\n(*This lemma states that a set resulting from removing a single element from an original set is a subset of the original set.*)\nLemma subD1set A x : A :\\ x \\subset A.\n\n(*This lemma states that the set difference of a first set and a second set is a subset of the complement of the second set.*)\nLemma subsetDr A B : A :\\: B \\subset ~: B.\n\n(*This lemma states that the proposition that a singleton set is a subset of another set is equivalent to the proposition that the element of the singleton set is a member of the other set.*)\nLemma sub1set A x : ([set x] \\subset A) = (x \\in A).\n\n(*This variant provides a specification for the equality of a set's cardinality with a given natural number. The constructor certifies that a set formed from a finite sequence has a cardinality equal to the length of the sequence, under the condition that the sequence contains no duplicate elements.*)\nVariant cards_eq_spec A : seq T -> {set T} -> nat -> Type :=\n(**)\n| CardEq (s : seq T) & uniq s : cards_eq_spec A s [set x | x \\in s] (size s).\n\n(*This lemma provides a proof that any given finite set, its canonical enumeration as a sequence, and its cardinality together satisfy the conditions for cardinality equality.*)\nLemma cards_eqP A : cards_eq_spec A (enum A) A #|A|.\n\n(*This lemma provides a reflective equivalence between the boolean proposition that the cardinality of a set is one and the logical proposition that the set is a singleton, meaning it consists of exactly one element.*)\nLemma cards1P A : reflect (exists x, A = [set x]) (#|A| == 1).\n\n(*This lemma provides a reflective equivalence between the boolean proposition that the cardinality of a set is two and the logical proposition that the set consists of exactly two distinct elements.*)\nLemma cards2P A : reflect (exists x y : T, x != y /\\ A = [set x; y])\n (#|A| == 2).\n\n(*This lemma states that a set is a subset of a singleton set if and only if it is either equal to that singleton set or is the empty set.*)\nLemma subset1 A x : (A \\subset [set x]) = (A == [set x]) || (A == set0).\n\n(*This lemma states that the powerset of a singleton set is a set containing two elements: the empty set and the original singleton set.*)\nLemma powerset1 x : powerset [set x] = [set set0; [set x]].\n\n(*This lemma provides a reflective equivalence between the proposition that a first set is a subset of a second set and the proposition that the intersection of the two sets is equal to the first set.*)\nLemma setIidPl A B : reflect (A :&: B = A) (A \\subset B).\n\nArguments setIidPl {A B}.\n\n(*This lemma provides a reflective equivalence between the proposition that a second set is a subset of a first set and the proposition that the intersection of the two sets is equal to the second set.*)\nLemma setIidPr A B : reflect (A :&: B = B) (B \\subset A).\n\n(*This lemma states that if a second set is a subset of a first set, then the cardinality of their set difference is equal to the cardinality of the first set minus the cardinality of the second set.*)\nLemma cardsDS A B : B \\subset A -> #|A :\\: B| = #|A| - #|B|.\n\n(*This lemma provides a reflective equivalence between the proposition that a second set is a subset of a first set and the proposition that the union of the two sets is equal to the first set.*)\nLemma setUidPl A B : reflect (A :|: B = A) (B \\subset A).\n\n(*This lemma provides a reflective equivalence between the proposition that a first set is a subset of a second set and the proposition that the union of the two sets is equal to the second set.*)\nLemma setUidPr A B : reflect (A :|: B = B) (A \\subset B).\n\n(*This lemma provides a reflective equivalence between the proposition that two sets are disjoint and the proposition that the set difference of the first and second set is equal to the first set.*)\nLemma setDidPl A B : reflect (A :\\: B = A) [disjoint A & B].\n\n(*This lemma states that if a second set is a subset of a first set, or if a third set is a subset of the first set, then the intersection of the second and third sets is also a subset of the first set.*)\nLemma subIset A B C : (B \\subset A) || (C \\subset A) -> (B :&: C \\subset A).\n\n(*This lemma states that a first set is a subset of the intersection of a second and a third set if and only if the first set is a subset of the second set and also a subset of the third set.*)\nLemma subsetI A B C : (A \\subset B :&: C) = (A \\subset B) && (A \\subset C).\n\n(*This lemma provides a reflective equivalence between the proposition that a first set is a subset of the intersection of a second and third set, and the logical conjunction of the propositions that the first set is a subset of the second set and that the first set is a subset of the third set.*)\nLemma subsetIP A B C : reflect (A \\subset B /\\ A \\subset C) (A \\subset B :&: C).\n\n(*This lemma states that a first set is a subset of its intersection with a second set if and only if the first set is a subset of the second set.*)\nLemma subsetIidl A B : (A \\subset A :&: B) = (A \\subset B).\n\n(*This lemma states that a second set is a subset of its intersection with a first set if and only if the second set is a subset of the first set.*)\nLemma subsetIidr A B : (B \\subset A :&: B) = (B \\subset A).\n\n(*This lemma states that the powerset of the intersection of two sets is equal to the intersection of the powersets of those two sets.*)\nLemma powersetI A B : powerset (A :&: B) = powerset A :&: powerset B.\n\n(*This lemma states that the union of a second and a third set is a subset of a first set if and only if both the second set and the third set are individually subsets of the first set.*)\nLemma subUset A B C : (B :|: C \\subset A) = (B \\subset A) && (C \\subset A).\n\n(*This lemma states that if a first set is a subset of a second set, or if the first set is a subset of a third set, then the first set is a subset of the union of the second and third sets.*)\nLemma subsetU A B C : (A \\subset B) || (A \\subset C) -> A \\subset B :|: C.\n\n(*This lemma provides a reflective equivalence between the proposition that the union of a first and second set is a subset of a third set, and the logical conjunction of the propositions that the first set is a subset of the third set and that the second set is a subset of the third set.*)\nLemma subUsetP A B C : reflect (A \\subset C /\\ B \\subset C) (A :|: B \\subset C).\n\n(*This lemma states that a first set being a subset of the complement of a second set is equivalent to the second set being a subset of the complement of the first set.*)\nLemma subsetC A B : (A \\subset ~: B) = (B \\subset ~: A).\n\n(*This lemma states that the complement of a first set being a subset of a second set is equivalent to the complement of the second set being a subset of the first set.*)\nLemma subCset A B : (~: A \\subset B) = (~: B \\subset A).\n\n(*This lemma states that a first set is a subset of the set difference of a second and a third set if and only if the first set is a subset of the second set and is also disjoint from the third set.*)\nLemma subsetD A B C : (A \\subset B :\\: C) = (A \\subset B) && [disjoint A & C].\n\n(*This lemma states that the set difference of a first and a second set being a subset of a third set is equivalent to the first set being a subset of the union of the second and third sets.*)\nLemma subDset A B C : (A :\\: B \\subset C) = (A \\subset B :|: C).\n\n(*This lemma states that a set A is a subset of the difference of a set B and a set C if and only if A is a subset of B and A is disjoint from C.*)\nLemma subsetDP A B C :\n reflect (A \\subset B /\\ [disjoint A & C]) (A \\subset B :\\: C).\n\n(*This lemma states that the union of two sets is the empty set if and only if both sets are individually the empty set.*)\nLemma setU_eq0 A B : (A :|: B == set0) = (A == set0) && (B == set0).\n\n(*This lemma states that the difference of a set A and a set B is the empty set if and only if set A is a subset of set B.*)\nLemma setD_eq0 A B : (A :\\: B == set0) = (A \\subset B).\n\n(*This lemma states that the intersection of two sets equals the empty set if and only if the two sets are disjoint.*)\nLemma setI_eq0 A B : (A :&: B == set0) = [disjoint A & B].\n\n(*This lemma states that a given set is the empty set if and only if it is a subset of another set and also a subset of that other set's complement.*)\nLemma eq0_subset B A : (A == set0) = (A \\subset B) && (A \\subset ~: B).\n\n(*This lemma states that if two sets are disjoint, then their intersection is the empty set.*)\nLemma disjoint_setI0 A B : [disjoint A & B] -> A :&: B = set0.\n\n(*This lemma states that if two sets A and B are disjoint, then any non-empty set C that is a subset of A cannot also be a subset of B.*)\nLemma subsetC_disjoint A B : [disjoint A & B] ->\n forall C, C != set0 -> C \\subset A -> ~~ (C \\subset B).\n\n(*This lemma states that a singleton set containing an element is disjoint from another set if and only if that element is not a member of the other set.*)\nLemma disjoints1 A x : [disjoint [set x] & A] = (x \\notin A).\n\n(*This lemma states that a set A is a subset of the difference between a set B and a singleton set containing an element x if and only if A is a subset of B and x is not an element of A.*)\nLemma subsetD1 A B x : (A \\subset B :\\ x) = (A \\subset B) && (x \\notin A).\n\n(*This lemma provides a boolean reflection, stating that a set A is a subset of the difference between a set B and a singleton set containing an element x if and only if the proposition that A is a subset of B and x is not a member of A is true.*)\nLemma subsetD1P A B x : reflect (A \\subset B /\\ x \\notin A) (A \\subset B :\\ x).\n\n(*This lemma states that if an element is a member of a set, then the set resulting from removing that element is a proper subset of the original set.*)\nLemma properD1 A x : x \\in A -> A :\\ x \\proper A.\n\n(*This lemma states that if a set B is not a subset of a set A, then the intersection of A and B is a proper subset of B.*)\nLemma properIr A B : ~~ (B \\subset A) -> A :&: B \\proper B.\n\n(*This lemma states that if a set A is not a subset of a set B, then the intersection of A and B is a proper subset of A.*)\nLemma properIl A B : ~~ (A \\subset B) -> A :&: B \\proper A.\n\n(*This lemma states that if a set A is not a subset of a set B, then set B is a proper subset of the union of A and B.*)\nLemma properUr A B : ~~ (A \\subset B) -> B \\proper A :|: B.\n\n(*This lemma states that if a set B is not a subset of a set A, then set A is a proper subset of the union of A and B.*)\nLemma properUl A B : ~~ (B \\subset A) -> A \\proper A :|: B.\n\n(*This lemma states that if the singleton set containing an element is a proper subset of a given set, then that element must be a member of the given set.*)\nLemma proper1set A x : ([set x] \\proper A) -> (x \\in A).\n\n(*This lemma states that if a set B is a proper subset of a set A, or a set C is a proper subset of A, then the intersection of B and C is also a proper subset of A.*)\nLemma properIset A B C : (B \\proper A) || (C \\proper A) -> (B :&: C \\proper A).\n\n(*This lemma states that if a set is a proper subset of the intersection of two other sets, then it is a proper subset of each of those two sets individually.*)\nLemma properI A B C : (A \\proper B :&: C) -> (A \\proper B) && (A \\proper C).\n\n(*This lemma states that if the union of two sets is a proper subset of a third set, then each of the two sets is individually a proper subset of the third set.*)\nLemma properU A B C : (B :|: C \\proper A) -> (B \\proper A) && (C \\proper A).\n\n(*This lemma states that if a set A is a proper subset of the difference between set B and set C, then A is a proper subset of B and is also disjoint from C.*)\nLemma properD A B C : (A \\proper B :\\: C) -> (A \\proper B) && [disjoint A & C].\n\n(*This lemma states that a set A is a proper subset of the complement of a set B if and only if B is a proper subset of the complement of A.*)\nLemma properCr A B : (A \\proper ~: B) = (B \\proper ~: A).\n\n(*This lemma states that the complement of a set A is a proper subset of a set B if and only if the complement of B is a proper subset of A.*)\nLemma properCl A B : (~: A \\proper B) = (~: B \\proper A).\n\n(*This lemma states that the list of elements of the union of two sets is a permutation of the list created by concatenating the lists of elements from each set and then removing any duplicate elements.*)\nLemma enum_setU A B : perm_eq (enum (A :|: B)) (undup (enum A ++ enum B)).\n\n(*This lemma states that the list of elements of the intersection of two sets is a permutation of the list obtained by filtering the elements of the first set, keeping only those that are also members of the second set.*)\nLemma enum_setI A B : perm_eq (enum (A :&: B)) (filter [in B] (enum A)).\n\n(*This lemma states that checking if at least one element in a singleton set satisfies a given predicate is equivalent to applying the predicate directly to the single element of that set.*)\nLemma has_set1 pA A a : has pA (enum [set a]) = pA a.\n\n(*This lemma states that a predicate holds for at least one element in the union of two sets if and only if it holds for at least one element in the first set or for at least one element in the second set.*)\nLemma has_setU pA A B :\n has pA (enum (A :|: B)) = (has pA (enum A)) || (has pA (enum B)).\n\n(*This lemma states that checking if all elements in a singleton set satisfy a given predicate is equivalent to applying the predicate directly to the single element of that set.*)\nLemma all_set1 pA A a : all pA (enum [set a]) = pA a.\n\n(*This lemma states that a predicate holds for all elements in the union of two sets if and only if it holds for all elements in the first set and also for all elements in the second set.*)\nLemma all_setU pA A B :\n all pA (enum (A :|: B)) = (all pA (enum A)) && (all pA (enum B)).\n\nEnd setOps.\n\nArguments set1P {T x a}.\nArguments set1_inj {T} [x1 x2].\nArguments set2P {T x a b}.\nArguments setIdP {T x pA pB}.\nArguments setIP {T x A B}.\nArguments setU1P {T x a B}.\nArguments setD1P {T x A b}.\nArguments setUP {T x A B}.\nArguments setDP {T A B x}.\nArguments cards1P {T A}.\nArguments setCP {T x A}.\nArguments setIidPl {T A B}.\nArguments setIidPr {T A B}.\nArguments setUidPl {T A B}.\nArguments setUidPr {T A B}.\nArguments setDidPl {T A B}.\nArguments subsetIP {T A B C}.\nArguments subUsetP {T A B C}.\nArguments subsetDP {T A B C}.\nArguments subsetD1P {T A B x}.\nPrenex Implicits set1.\n#[global] Hint Extern 0 (is_true (subset _ (mem (pred_of_set (setTfor _))))) =>\n solve [apply: subsetT_hint] : core.\n\nSection setOpsAlgebra.\n\nImport Monoid.\n\nVariable T : finType.\n\nHB.instance Definition _ := isComLaw.Build {set T} [set: T] (@setI T)\n (@setIA T) (@setIC T) (@setTI T).\n\nHB.instance Definition _ := isMulLaw.Build {set T} set0 (@setI T)\n (@set0I T) (@setI0 T).\n\nHB.instance Definition _ := isComLaw.Build {set T} set0 (@setU T)\n (@setUA T) (@setUC T) (@set0U T).\n\nHB.instance Definition _ := isMulLaw.Build {set T} [set: T] (@setU T)\n (@setTU T) (@setUT T).\n\nHB.instance Definition _ := isAddLaw.Build {set T} (@setU T) (@setI T)\n (@setUIl T) (@setUIr T).\n\n(*This definition specifies the Cartesian product of two sets, A1 and A2, as the set of all pairs whose first element is in A1 and whose second element is in A2.*)\nDefinition setX := [set u | u.1 \\in A1 & u.2 \\in A2].\n\n(*This lemma states that a pair of elements belongs to the Cartesian product of two sets if and only if the first element of the pair is a member of the first set and the second element is a member of the second set.*)\nLemma in_setX x1 x2 : ((x1, x2) \\in setX) = (x1 \\in A1) && (x2 \\in A2).\n\n(*This lemma states the equivalence between a pair of elements belonging to a Cartesian product set and the condition that the first element belongs to the first set and the second element belongs to the second set.*)\nLemma setXP x1 x2 : reflect (x1 \\in A1 /\\ x2 \\in A2) ((x1, x2) \\in setX).\n\n(*This lemma states that the cardinality of the Cartesian product of two finite sets is equal to the product of their individual cardinalities.*)\nLemma cardsX : #|setX| = #|A1| * #|A2|.\n\nEnd CartesianProd.\n\nArguments setXP {fT1 fT2 A1 A2 x1 x2}.\n\nSection CartesianNProd.\n\nVariables (I : finType) (fT : I -> finType).\nVariables (A : forall i, {set fT i}).\nImplicit Types (x : {dffun forall i, fT i}).\n\n(*This definition constructs the n-ary Cartesian product of a family of sets indexed by a finite type. An element belongs to this product set if it is a dependent function where the component at each index belongs to the corresponding set in the family.*)\nDefinition setXn := [set x : {dffun _} in family A].\n\n(*This lemma states that a dependent function is a member of the n-ary Cartesian product set if and only if for every index, the component of the function at that index is a member of the corresponding set in the family.*)\nLemma in_setXn x : (x \\in setXn) = [forall i, x i \\in A i].\n\n(*This lemma provides a boolean reflection of the membership condition for the n-ary Cartesian product of a family of sets. It asserts that a dependent function belongs to the product set if and only if for all indices, its component at that index belongs to the corresponding set.*)\nLemma setXnP x : reflect (forall i, x i \\in A i) (x \\in setXn).\n\n(*This lemma states that the cardinality of the n-ary Cartesian product of a family of finite sets is equal to the product of the cardinalities of all sets in the indexed family.*)\nLemma cardsXn : #|setXn| = \\prod_i #|A i|.\n\nEnd CartesianNProd.\n\nArguments setXnP {I fT A x}.\n\nHB.lock\n(*This definition constructs the image of a set under a given function. The resulting set contains all elements that can be produced by applying the function to each element of the input set.*)\nDefinition imset (aT rT : finType) f mD := [set y in @image_mem aT rT f mD].\nCanonical imset_unlock := Unlockable imset.unlock.\n\nHB.lock\n(*This definition constructs the image of a set of pairs under a binary function. The pairs are formed from two input sets, where membership in the second set can depend on the element chosen from the first. The resulting set contains all values obtained by applying the function to each valid pair.*)\nDefinition imset2 (aT1 aT2 rT : finType) f (D1 : mem_pred aT1) (D2 : _ -> mem_pred aT2) :=\n [set y in @image_mem _ rT (uncurry f) (mem [pred u | D1 u.1 & D2 u.1 u.2])].\nCanonical imset2_unlock := Unlockable imset2.unlock.\n\n(*This definition constructs the preimage of a codomain set under a given function. The resulting set contains all elements from the domain type that map to an element within the specified codomain set.*)\nDefinition preimset (aT : finType) rT f (R : mem_pred rT) :=\n [set x : aT | in_mem (f x) R].\n\n(*This notation represents the preimage of a set under a function. It evaluates to the set of all elements in the function's domain that map to elements within the given set.*)\nNotation \"f @^-1: A\" := (preimset f (mem A)) (at level 24) : set_scope.\n(*This notation represents the image of a set under a function. It evaluates to the set of all elements obtained by applying the function to each element of the given set.*)\nNotation \"f @: A\" := (imset f (mem A)) (at level 24) : set_scope.\n(*This notation represents the image of the Cartesian product of two sets under a binary function. It evaluates to the set of all elements obtained by applying the function to every pair of elements, where the first element is from the first set and the second is from the second set.*)\nNotation \"f @2: ( A , B )\" := (imset2 f (mem A) (fun _ => mem B))\n (at level 24, format \"f @2: ( A , B )\") : set_scope.\n\n(*This notation provides a set-builder syntax for constructing the image of a set. It defines a new set containing the results of evaluating an expression for each element drawn from a given source set.*)\nNotation \"[ 'set' E | x 'in' A ]\" := ((fun x => E) @: A)\n (format \"[ '[hv' 'set' E '/ ' | x 'in' A ] ']'\") : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of a filtered subset. It defines a new set containing the results of evaluating an expression for each element that is drawn from a given source set and also satisfies an additional boolean property.*)\nNotation \"[ 'set' E | x 'in' A & P ]\" := [set E | x in pred_of_set [set x in A | P]]\n (format \"[ '[hv' 'set' E '/ ' | x 'in' A '/ ' & P ] ']'\") : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of a Cartesian product of two sets. It defines a new set containing the results of evaluating a binary expression for each pair of elements, where the first element is from the first set and the second is from the second set.*)\nNotation \"[ 'set' E | x 'in' A , y 'in' B ]\" :=\n (imset2 (fun x y => E) (mem A) (fun x => mem B))\n (y at level 99, format\n \"[ '[hv' 'set' E '/ ' | x 'in' A , '/ ' y 'in' B ] ']'\"\n ) : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of a filtered Cartesian product. It defines a new set by evaluating a binary expression for each pair of elements, where the first element comes from a source set, and the second element comes from another source set but is also required to satisfy a given boolean property.*)\nNotation \"[ 'set' E | x 'in' A , y 'in' B & P ]\" :=\n [set E | x in A, y in pred_of_set [set y in B | P]]\n (format\n \"[ '[hv' 'set' E '/ ' | x 'in' A , '/ ' y 'in' B '/ ' & P ] ']'\"\n ) : set_scope.\n\n(*This notation provides a parsing-only set-builder syntax for constructing the image of a set, where the bound variable is explicitly annotated with its type. It defines a set containing the results of evaluating an expression for each element from a given source set.*)\nNotation \"[ 'set' E | x : T 'in' A ]\" := ((fun x : T => E) @: A)\n (only parsing) : set_scope.\n(*This notation provides a parsing-only set-builder syntax for the image of a filtered subset, with an explicit type annotation for the bound variable. It defines a set by evaluating an expression for each element that is drawn from a source set and satisfies a boolean property.*)\nNotation \"[ 'set' E | x : T 'in' A & P ]\" :=\n [set E | x : T in [set x : T in A | P]]\n (only parsing) : set_scope.\n(*This notation provides a parsing-only set-builder syntax for the image of a Cartesian product of two sets, with explicit type annotations for both bound variables. It defines a set by evaluating a binary expression for each pair of elements from the two respective source sets.*)\nNotation \"[ 'set' E | x : T 'in' A , y : U 'in' B ]\" :=\n (imset2 (fun (x : T) (y : U) => E) (mem A) (fun (x : T) => mem B))\n (y at level 99, only parsing) : set_scope.\n(*This notation provides a parsing-only set-builder syntax for the image of a filtered Cartesian product, with explicit type annotations for both bound variables. It defines a new set by evaluating a binary expression for each pair of elements, where the first element comes from a source set, and the second element comes from another source set but is also required to satisfy a given boolean property.*)\nNotation \"[ 'set' E | x : T 'in' A , y : U 'in' B & P ]\" :=\n [set E | x : T in A, y : U in [set y : U in B | P]]\n (only parsing) : set_scope.\n\nLocal Notation predOfType T := (pred_of_simpl (@pred_of_argType T)).\n(*This notation provides a set-builder syntax for constructing the image of an entire type. It defines a new set containing the results of evaluating an expression for every element of a given type.*)\nNotation \"[ 'set' E | x : T ]\" := [set E | x : T in predOfType T]\n (format \"[ '[hv' 'set' E '/ ' | x : T ] ']'\") : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of a subset of a type defined by a property. It defines a new set containing the results of evaluating an expression for every element of a given type that also satisfies a boolean property.*)\nNotation \"[ 'set' E | x : T & P ]\" :=\n [set E | x : T in pred_of_set [set x : T | P]]\n (format \"[ '[hv' 'set' E '/ ' | x : T '/ ' & P ] ']'\") : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of the product of an entire type and a given set. It defines a new set by evaluating a binary expression for each pair of elements, where the first element is from the specified type and the second is from the specified set.*)\nNotation \"[ 'set' E | x : T , y : U 'in' B ]\" :=\n [set E | x : T in predOfType T, y : U in B]\n (y at level 99, format\n \"[ '[hv' 'set' E '/ ' | x : T , '/ ' y : U 'in' B ] ']'\")\n : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of a product of an entire type and a filtered set. It defines a new set by evaluating a binary expression for each pair of elements, where the first is from a specified type and the second is from a specified set and also satisfies a boolean property.*)\nNotation \"[ 'set' E | x : T , y : U 'in' B & P ]\" :=\n [set E | x : T, y : U in pred_of_set [set y in B | P]]\n (format\n \"[ '[hv ' 'set' E '/' | x : T , '/ ' y : U 'in' B '/' & P ] ']'\"\n ) : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of the product of a given set and an entire type. It defines a new set by evaluating a binary expression for each pair of elements, where the first element is from the specified set and the second is from the specified type.*)\nNotation \"[ 'set' E | x : T 'in' A , y : U ]\" :=\n [set E | x : T in A, y : U in predOfType U]\n (format\n \"[ '[hv' 'set' E '/ ' | x : T 'in' A , '/ ' y : U ] ']'\")\n : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of a product of a given set and a subset of a type defined by a property. It defines a new set by evaluating a binary expression for pairs where the first element is from a specified set and the second is any element of a specified type that satisfies a boolean property.*)\nNotation \"[ 'set' E | x : T 'in' A , y : U & P ]\" :=\n [set E | x : T in A, y : U in pred_of_set [set y in P]]\n (format\n \"[ '[hv' 'set' E '/ ' | x : T 'in' A , '/ ' y : U & P ] ']'\")\n : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of the Cartesian product of two entire types. It defines a new set containing the results of evaluating a binary expression for every pair of elements, with the first element drawn from the first specified type and the second from the second specified type.*)\nNotation \"[ 'set' E | x : T , y : U ]\" :=\n [set E | x : T, y : U in predOfType U]\n (format\n \"[ '[hv' 'set' E '/ ' | x : T , '/ ' y : U ] ']'\")\n : set_scope.\n(*This notation provides a set-builder syntax for constructing the image of a product of an entire type and a subset of another type defined by a property. It defines a new set by evaluating a binary expression for pairs where the first element is from a specified type and the second is any element of another specified type that satisfies a boolean property.*)\nNotation \"[ 'set' E | x : T , y : U & P ]\" :=\n [set E | x : T, y : U in pred_of_set [set y in P]]\n (format\n \"[ '[hv' 'set' E '/ ' | x : T , '/ ' y : U & P ] ']'\")\n : set_scope.\n\n(*This notation provides a parsing-only set-builder syntax for constructing the image of a product of an entire type and a given set, where the types of the bound variables are inferred. It defines a new set by evaluating a binary expression for pairs where the first element is from its inferred type and the second is from the specified set.*)\nNotation \"[ 'set' E | x , y 'in' B ]\" := [set E | x : _, y : _ in B]\n (y at level 99, only parsing) : set_scope.\n(*This notation provides a parsing-only set-builder syntax for constructing the image of a product of an entire type and a filtered set, with inferred types. It defines a new set by evaluating a binary expression for pairs where the first element is from its inferred type, and the second is from a specified set and also satisfies a boolean property.*)\nNotation \"[ 'set' E | x , y 'in' B & P ]\" := [set E | x : _, y : _ in B & P]\n (only parsing) : set_scope.\n(*This notation provides a shorthand for constructing a set where an expression is evaluated for all elements x in a given set A and another index y, with their types being inferred automatically.*)\nNotation \"[ 'set' E | x 'in' A , y ]\" := [set E | x : _ in A, y : _]\n (only parsing) : set_scope.\n(*This notation provides a shorthand for constructing a set where an expression is evaluated for all elements x in a given set A and another index y that satisfy a given predicate, with their types being inferred automatically.*)\nNotation \"[ 'set' E | x 'in' A , y & P ]\" := [set E | x : _ in A, y : _ & P]\n (only parsing) : set_scope.\n(*This notation provides a shorthand for constructing a set where an expression is evaluated for all combinations of two index variables x and y over their automatically inferred types.*)\nNotation \"[ 'set' E | x , y ]\" := [set E | x : _, y : _]\n (only parsing) : set_scope.\n(*This notation provides a shorthand for constructing a set where an expression is evaluated for all combinations of two index variables x and y that satisfy a given predicate, with their types being inferred automatically.*)\nNotation \"[ 'set' E | x , y & P ]\" := [set E | x : _, y : _ & P ]\n (only parsing) : set_scope.\n\nSection FunImage.\n\nVariables aT aT2 : finType.\n\nSection ImsetTheory.\n\nVariable rT : finType.\n\nSection ImsetProp.\n\nVariables (f : aT -> rT) (f2 : aT -> aT2 -> rT).\n\n(*This lemma states that an element belongs to the image of a set under a function if and only if it is the image of some element from the original set.*)\nLemma imsetP D y : reflect (exists2 x, in_mem x D & y = f x) (y \\in imset f D).\n\n(*This definition specifies the condition for an element to be a member of a doubly-indexed image set. An element is in such a set if it is the result of applying a binary function to a pair of elements, where the first element belongs to a given set and the second belongs to a dependent set.*)\nVariant imset2_spec D1 D2 y : Prop :=\n Imset2spec x1 x2 of in_mem x1 D1 & in_mem x2 (D2 x1) & y = f2 x1 x2.\n\n(*This lemma states that an element belongs to a doubly-indexed image set if and only if there exist two elements, one from an initial set and another from a dependent set, such that the given element is the result of applying a binary function to them.*)\nLemma imset2P D1 D2 y : reflect (imset2_spec D1 D2 y) (y \\in imset2 f2 D1 D2).\n\n(*This lemma states that for any function, the image of an element belonging to a given set is also an element of the image of that set.*)\nLemma imset_f (D : {pred aT}) x : x \\in D -> f x \\in f @: D.\n\n(*This lemma states that for an injective function, an element's image belongs to the image of a set if and only if the original element belongs to that set.*)\nLemma mem_imset (D : {pred aT}) x : injective f -> f x \\in f @: D = (x \\in D).\n\n(*This lemma states that the image of the empty set under any function is the empty set.*)\nLemma imset0 : f @: set0 = set0.\n\n(*This lemma states that the image of a set under a function is empty if and only if the original set is empty.*)\nLemma imset_eq0 (A : {set aT}) : (f @: A == set0) = (A == set0).\n\n(*This lemma states that the image of a singleton set under a function is the singleton set containing the image of that element.*)\nLemma imset_set1 x : f @: [set x] = [set f x].\n\n(*This lemma states that if a function is injective, then the operation of taking the image of a set under that function is also injective.*)\nLemma imset_inj : injective f -> injective (fun A : {set aT} => f @: A).\n\n(*This lemma states that for an injective function, the images of two sets are disjoint if and only if the original sets are disjoint.*)\nLemma imset_disjoint (A B : {pred aT}) :\n injective f -> [disjoint f @: A & f @: B] = [disjoint A & B].\n\n(*This lemma states that for a binary function, if a first element is in an initial set and a second element is in a corresponding dependent set, then the result of applying the function to these elements belongs to the doubly-indexed image set.*)\nLemma imset2_f (D : {pred aT}) (D2 : aT -> {pred aT2}) x x2 :\n x \\in D -> x2 \\in D2 x ->\n f2 x x2 \\in [set f2 y y2 | y in D, y2 in D2 y].\n\n(*This lemma states that for an injective binary function, the image of a pair of elements belongs to the doubly-indexed image set if and only if the first element belongs to its specified set and the second element belongs to its corresponding dependent set.*)\nLemma mem_imset2 (D : {pred aT}) (D2 : aT -> {pred aT2}) x x2 :\n injective2 f2 ->\n (f2 x x2 \\in [set f2 y y2 | y in D, y2 in D2 y])\n = (x \\in D) && (x2 \\in D2 x).\n\n(*This lemma states that the image of a first set under a function is a subset of a second set if and only if the first set is a subset of the preimage of the second set.*)\nLemma sub_imset_pre (A : {pred aT}) (B : {pred rT}) :\n (f @: A \\subset B) = (A \\subset f @^-1: B).\n\n(*This lemma states that the preimage operation preserves the subset relation; that is, if a first set is a subset of a second set, then the preimage of the first set under a function is a subset of the preimage of the second set.*)\nLemma preimsetS (A B : {pred rT}) :\n A \\subset B -> (f @^-1: A) \\subset (f @^-1: B).\n\n(*This lemma states that the preimage of the empty set under any function is the empty set.*)\nLemma preimset0 : f @^-1: set0 = set0.\n\n(*This lemma states that the preimage of the universal set under any function is the universal set of the function's domain.*)\nLemma preimsetT : f @^-1: setT = setT.\n\n(*This lemma states that the preimage of the intersection of two sets under a function is equal to the intersection of their individual preimages.*)\nLemma preimsetI (A B : {set rT}) :\n f @^-1: (A :&: B) = (f @^-1: A) :&: (f @^-1: B).\n\n(*This lemma states that the preimage of the union of two sets under a function is equal to the union of their individual preimages.*)\nLemma preimsetU (A B : {set rT}) :\n f @^-1: (A :|: B) = (f @^-1: A) :|: (f @^-1: B).\n\n(*This lemma states that the preimage of the difference of two sets under a function is equal to the difference of their individual preimages.*)\nLemma preimsetD (A B : {set rT}) :\n f @^-1: (A :\\: B) = (f @^-1: A) :\\: (f @^-1: B).\n\n(*This lemma states that the preimage of the complement of a set under a function is equal to the complement of its preimage.*)\nLemma preimsetC (A : {set rT}) : f @^-1: (~: A) = ~: f @^-1: A.\n\n(*This lemma states that the image operation preserves the subset relation; that is, if a first set is a subset of a second set, then the image of the first set under a function is a subset of the image of the second set.*)\nLemma imsetS (A B : {pred aT}) : A \\subset B -> f @: A \\subset f @: B.\n\n(*This lemma states that if a function is injective on a set, then the image of a proper subset of that set is a proper subset of the image of the set.*)\nLemma imset_proper (A B : {set aT}) :\n {in B &, injective f} -> A \\proper B -> f @: A \\proper f @: B.\n\n(*This lemma states that if a first set is a proper subset of a second set, and the second set is contained within the codomain of a function, then the preimage of the first set is a proper subset of the preimage of the second set.*)\nLemma preimset_proper (A B : {set rT}) :\n B \\subset codom f -> A \\proper B -> (f @^-1: A) \\proper (f @^-1: B).\n\n(*This lemma states that the image of the union of two sets under a function is equal to the union of their individual images.*)\nLemma imsetU (A B : {set aT}) : f @: (A :|: B) = (f @: A) :|: (f @: B).\n\n(*This lemma states that the image of a set extended with a new element is equal to the image of the original set extended with the image of that new element.*)\nLemma imsetU1 a (A : {set aT}) : f @: (a |: A) = f a |: (f @: A).\n\n(*This lemma states that the image of the intersection of two sets under a function is a subset of the intersection of their individual images.*)\nLemma imsetI (A B : {set aT}) :\n {in A & B, injective f} -> f @: (A :&: B) = f @: A :&: f @: B.\n\n(*This lemma states that the image of a binary function over sets is monotonic with respect to its first set argument. Specifically, if a first set is a subset of a second set, then the image of the binary function applied to the Cartesian product of the first set and a third set is a subset of the image applied to the Cartesian product of the second set and the third set.*)\nLemma imset2Sl (A B : {pred aT}) (C : {pred aT2}) :\n A \\subset B -> f2 @2: (A, C) \\subset f2 @2: (B, C).\n\n(*This lemma states that the image of a binary function over sets is monotonic with respect to its second set argument. Specifically, if a first set is a subset of a second set, then the image of the binary function applied to the Cartesian product of a third set and the first set is a subset of the image applied to the Cartesian product of the third set and the second set.*)\nLemma imset2Sr (A B : {pred aT2}) (C : {pred aT}) :\n A \\subset B -> f2 @2: (C, A) \\subset f2 @2: (C, B).\n\n(*This lemma states that the image of a binary function over sets is monotonic in both of its set arguments. If a first set is a subset of a second set, and a third set is a subset of a fourth set, then the image of the binary function applied to the Cartesian product of the first and third sets is a subset of the image applied to the Cartesian product of the second and fourth sets.*)\nLemma imset2S (A B : {pred aT}) (A2 B2 : {pred aT2}) :\n A \\subset B -> A2 \\subset B2 -> f2 @2: (A, A2) \\subset f2 @2: (B, B2).\n\nEnd ImsetProp.\n\nImplicit Types (f g : aT -> rT) (D : {pred aT}) (R : {pred rT}).\n\n(*This lemma states that if two functions are equal everywhere, then their preimages of any given set are also equal.*)\nLemma eq_preimset f g R : f =1 g -> f @^-1: R = g @^-1: R.\n\n(*This lemma states that if two functions are equal everywhere, then their images of any given set are also equal.*)\nLemma eq_imset f g D : f =1 g -> f @: D = g @: D.\n\n(*This lemma states that if two functions are equal on a given domain set, then their images of that set are equal.*)\nLemma eq_in_imset f g D : {in D, f =1 g} -> f @: D = g @: D.\n\n(*This lemma states that if two binary functions are equal over the Cartesian product of two domain sets, then their images over that product of sets are equal.*)\nLemma eq_in_imset2 (f g : aT -> aT2 -> rT) (D : {pred aT}) (D2 : {pred aT2}) :\n {in D & D2, f =2 g} -> f @2: (D, D2) = g @2: (D, D2).\n\nEnd ImsetTheory.\n\n(*This lemma states that the image of the pairing function over two sets is equal to the Cartesian product of those sets.*)\nLemma imset2_pair (A : {set aT}) (B : {set aT2}) :\n [set (x, y) | x in A, y in B] = setX A B.\n\n(*This lemma states that the Cartesian product of sets is monotonic with respect to the subset relation. If a first set is a subset of a second, and a third set is a subset of a fourth, then the Cartesian product of the first and third sets is a subset of the Cartesian product of the second and fourth.*)\nLemma setXS (A1 B1 : {set aT}) (A2 B2 : {set aT2}) :\n A1 \\subset B1 -> A2 \\subset B2 -> setX A1 A2 \\subset setX B1 B2.\n\nEnd FunImage.\n\nArguments imsetP {aT rT f D y}.\nArguments imset2P {aT aT2 rT f2 D1 D2 y}.\nArguments imset_disjoint {aT rT f A B}.\n\nSection unset1.\nVariable (I : finType).\nImplicit Types (i : I) (A : {set I}).\n\n(*This lemma states that picking an element from a singleton set containing a specific value successfully returns that same value, wrapped in an option type.*)\nLemma pick_set1 i0 : [pick x in [set i0]] = Some i0.\n\n(*This definition introduces a function that extracts the unique element from a singleton set. If the input set has exactly one element, the function returns that element wrapped in an option type; otherwise, it returns none.*)\nDefinition unset1 A : option I := if #|A| == 1 then [pick x in A] else None.\n\n(*This lemma states a left cancellation property: creating a singleton set from an element and then extracting the unique element from that set successfully returns the original element.*)\nLemma set1K : pcancel set1 unset1.\n\n(*This lemma states that for any set with exactly one element, extracting its unique element and then creating a singleton set from that element results in the original set, wrapped in an option type.*)\nLemma omap_unset1K A : #|A| = 1 -> omap set1 (unset1 A) = Some A.\n\n(*This lemma states that attempting to extract a unique element from the empty set results in none.*)\nLemma unset10 : unset1 set0 = None. \n\n(*This lemma states that attempting to extract a unique element from a set whose size is not equal to one results in none.*)\nLemma unset1N1 A : #|A| != 1 -> unset1 A = None.\n\n(*This lemma states that creating a singleton set acts as a right inverse for the operation of extracting an element from a singleton set. For any set that is a singleton, applying the extraction operation and then the singleton creation operation restores the original set.*)\nLemma unset1K : ocancel unset1 set1.\n\nEnd unset1.\nArguments unset1 {I}.\n\n(*This lemma states that the dependent Cartesian product of a family of sets is monotonic. If for each index in an index set, a corresponding set from a first family is a subset of the corresponding set from a second family, then the dependent product of the first family is a subset of the dependent product of the second family.*)\nLemma setXnS (I : finType) (T : I -> finType) (A B : forall i, {set T i}) :\n (forall i, A i \\subset B i) -> setXn A \\subset setXn B.\n\n(*This lemma establishes a congruence property for the dependent Cartesian product of a family of sets. If two families of sets are equal at every index, then their dependent Cartesian products are equal.*)\nLemma eq_setXn (I : finType) (T : I -> finType) (A B : forall i, {set T i}) :\n (forall i, A i = B i) -> setXn A = setXn B.\n\nSection BigOpsAnyOp.\n\nVariables (R : Type) (x : R) (op : R -> R -> R).\nVariables I : finType.\nImplicit Type F : I -> R.\n\n(*This lemma states that performing a large-scale associative operation over an empty set of indices results in the neutral element of the operation.*)\nLemma big_set0 F : \\big[op/x]_(i in set0) F i = x.\n\n(*This lemma states that performing a large-scale semigroup operation with an initial value over a singleton set of indices is equivalent to applying the binary operation to the function value at the single index and the initial value.*)\nLemma big_set1E j F : \\big[op/x]_(i in [set j]) F i = op (F j) x.\n\n(*This lemma states that a large-scale operation over a set of indices defined by a predicate is equivalent to performing the same operation where the domain of indices is directly restricted by that predicate in the notation.*)\nLemma big_set (A : pred I) F :\n \\big[op/x]_(i in [set i | A i]) (F i) = \\big[op/x]_(i in A) (F i).\n\nEnd BigOpsAnyOp.\n\nSection BigOpsSemiGroup.\n\nVariables (R : Type) (op : SemiGroup.com_law R).\n\nVariable (le : rel R).\nHypotheses (le_refl : reflexive le) (le_incr : forall x y, le x (op x y)).\n\nContext [x : R].\n\n(*This lemma states that, under certain conditions on a binary operation and a relation, a large-scale operation over a set of indices is monotonic with respect to set inclusion. If a first set of indices is a subset of a second, then the result of the operation over the first set is less than or equal to the result over the second set, according to the given relation.*)\nLemma subset_le_big_cond (I : finType) (A A' P P' : {pred I}) (F : I -> R) :\n [set i in A | P i] \\subset [set i in A' | P' i] ->\n le (\\big[op/x]_(i in A | P i) F i) (\\big[op/x]_(i in A' | P' i) F i).\n\n(*This lemma states that for an idempotent and commutative binary operation, a large-scale operation over the image of a set of indices under a function is equal to the large-scale operation over the original set of indices, where the indexed function is composed with the mapping function.*)\nLemma big_imset_idem [I J : finType] (h : I -> J) (A : pred I) F :\n idempotent_op op ->\n \\big[op/x]_(j in h @: A) F j = \\big[op/x]_(i in A) F (h i).\n\nEnd BigOpsSemiGroup.\n\nSection BigOps.\n\nVariables (R : Type) (idx : R).\nVariables (op : Monoid.law idx) (aop : Monoid.com_law idx).\nVariables (times : Monoid.mul_law idx) (plus : Monoid.add_law idx times).\nVariables I J : finType.\nImplicit Type A B : {set I}.\nImplicit Type h : I -> J.\nImplicit Type P : pred I.\nImplicit Type F : I -> R.\n\n(*This lemma states that performing a large-scale monoid operation over a singleton set containing a single index is equivalent to simply evaluating the indexed function at that index.*)\nLemma big_set1 a F : \\big[op/idx]_(i in [set a]) F i = F a.\n\n(*This lemma provides a decomposition for a large-scale commutative monoid operation over a set. The operation over a set can be split into the combination of the operation over its intersection with a second set and the operation over its difference with that same second set.*)\nLemma big_setID A B F :\n \\big[aop/idx]_(i in A) F i =\n aop (\\big[aop/idx]_(i in A :&: B) F i)\n (\\big[aop/idx]_(i in A :\\: B) F i).\n\n(*This lemma provides a decomposition for a conditional large-scale commutative monoid operation over a set. The operation over elements of a set that satisfy a predicate can be split into the combination of the operation over its intersection with a second set and the operation over its difference with that same second set, with the predicate applied in both sub-operations.*)\nLemma big_setIDcond A B P F :\n \\big[aop/idx]_(i in A | P i) F i =\n aop (\\big[aop/idx]_(i in A :&: B | P i) F i)\n (\\big[aop/idx]_(i in A :\\: B | P i) F i).\n\n(*This lemma states that an element can be separated from a large-scale commutative monoid operation. If an element is present in the index set, the operation over the entire set is equal to the combination of the function's value at that element with the operation over the rest of the set.*)\nLemma big_setD1 a A F : a \\in A ->\n \\big[aop/idx]_(i in A) F i = aop (F a) (\\big[aop/idx]_(i in A :\\ a) F i).\n\n(*This lemma states how to incorporate a new element into a large-scale commutative monoid operation. If an element is not already in the index set, the operation over the set extended with this new element is equal to the combination of the function's value at the new element with the operation over the original set.*)\nLemma big_setU1 a A F : a \\notin A ->\n \\big[aop/idx]_(i in a |: A) F i = aop (F a) (\\big[aop/idx]_(i in A) F i).\n\n(*This lemma states that for an idempotent commutative monoid operation, combining the result of a conditional large-scale operation over a subset with the result of the same operation over the superset yields just the result from the superset.*)\nLemma big_subset_idem_cond A B P F :\n idempotent_op aop ->\n A \\subset B ->\n aop (\\big[aop/idx]_(i in A | P i) F i) (\\big[aop/idx]_(i in B | P i) F i)\n = \\big[aop/idx]_(i in B | P i) F i.\n\n(*This lemma states that for an idempotent commutative monoid operation, combining the result of a large-scale operation over a subset with the result of the same operation over the superset is equivalent to the operation over the superset alone.*)\nLemma big_subset_idem A B F :\n idempotent_op aop ->\n A \\subset B ->\n aop (\\big[aop/idx]_(i in A) F i) (\\big[aop/idx]_(i in B) F i)\n = \\big[aop/idx]_(i in B) F i.\n\n(*This lemma states that for an idempotent associative operation, the big operation over the union of two sets with a filtering predicate is equal to applying the operation to the results of the big operation over each set individually with the same predicate.*)\nLemma big_setU_cond A B P F :\n idempotent_op aop ->\n \\big[aop/idx]_(i in A :|: B | P i) F i\n = aop (\\big[aop/idx]_(i in A | P i) F i) (\\big[aop/idx]_(i in B | P i) F i).\n\n(*This lemma states that for an idempotent associative operation, the big operation over the union of two sets is equal to applying the operation to the results of the big operation over each set individually.*)\nLemma big_setU A B F :\n idempotent_op aop ->\n \\big[aop/idx]_(i in A :|: B) F i\n = aop (\\big[aop/idx]_(i in A) F i) (\\big[aop/idx]_(i in B) F i).\n\n(*This lemma states that for a function that is injective on a given set, the big operation performed over the image of that set is equivalent to the big operation over the original set where the function is applied to the index inside the expression.*)\nLemma big_imset h (A : {pred I}) G : {in A &, injective h} ->\n \\big[aop/idx]_(j in h @: A) G j = \\big[aop/idx]_(i in A) G (h i).\n\n(*This lemma states that for a function that is injective on a given set, a filtered big operation over the image of that set is equivalent to the big operation over the original set, where the filter and the expression body are both composed with the function.*)\nLemma big_imset_cond h (A : {pred I}) (P : pred J) G : {in A &, injective h} ->\n \\big[aop/idx]_(j in h @: A | P j) G j =\n \\big[aop/idx]_(i in A | P (h i)) G (h i).\n\n(*This lemma states that a big operation over a set can be re-expressed as a nested big operation, where the outer operation iterates over the image of the set under a function, and the inner operation iterates over the subset of the original set that maps to each element of the image.*)\nLemma partition_big_imset h (A : {pred I}) F :\n \\big[aop/idx]_(i in A) F i =\n \\big[aop/idx]_(j in h @: A) \\big[aop/idx]_(i in A | h i == j) F i.\n\n(*This lemma states that a big operation over a function of sets, filtered to include only singleton sets, is equivalent to the big operation over the same function applied to the singleton set formed from each element of the underlying type.*)\nLemma big_cards1 (f : {set I} -> R) :\n \\big[aop/idx]_(A : {set I} | #|A| == 1) f A\n = \\big[aop/idx]_(i : I) f [set i].\n\nEnd BigOps.\n\n(*This lemma provides a general distributivity formula, stating that the product of sums of two functions over a finite type is equal to the sum, over all subsets of the type, of the mixed products where terms are chosen from the first function for indices in the subset and from the second function for indices outside the subset.*)\nLemma bigA_distr (R : Type) (zero one : R) (mul : Monoid.mul_law zero)\n (add : Monoid.add_law zero mul) (I : finType) (F G : I -> R) :\n \\big[mul/one]_i add (F i) (G i) =\n \\big[add/zero]_(J in {set I}) \\big[mul/one]_i (if i \\in J then F i else G i).\n\nArguments big_setID [R idx aop I A].\nArguments big_setD1 [R idx aop I] a [A F].\nArguments big_setU1 [R idx aop I] a [A F].\nArguments big_imset [R idx aop I J h A].\nArguments partition_big_imset [R idx aop I J].\n\nSection Fun2Set1.\n\nVariables aT1 aT2 rT : finType.\nVariables (f : aT1 -> aT2 -> rT).\n\n(*This lemma states that the image of a cartesian product of a singleton set and another set under a two-argument function is equivalent to the image of the second set under the partially applied function, where the first argument is fixed to the element of the singleton set.*)\nLemma imset2_set1l x1 (D2 : {pred aT2}) : f @2: ([set x1], D2) = f x1 @: D2.\n\n(*This lemma states that the image of a cartesian product of a set and a singleton set under a two-argument function is equivalent to the image of the first set under the flipped and partially applied function, where the second argument is fixed to the element of the singleton set.*)\nLemma imset2_set1r x2 (D1 : {pred aT1}) : f @2: (D1, [set x2]) = f^~ x2 @: D1.\n\nEnd Fun2Set1.\n\nSection CardFunImage.\n\nVariables aT aT2 rT : finType.\nVariables (f : aT -> rT) (g : rT -> aT) (f2 : aT -> aT2 -> rT).\nVariables (D : {pred aT}) (D2 : {pred aT}).\n\n(*This lemma states that the cardinality of the computed image of a set under a function is equal to the cardinality of the logical image of that set.*)\nLemma imset_card : #|f @: D| = #|image f D|.\n\n(*This lemma states that the cardinality of the image of a set under a function is less than or equal to the cardinality of the original set.*)\nLemma leq_imset_card : #|f @: D| <= #|D|.\n\n(*This lemma states that if a function is injective on a given set, then the cardinality of the image of that set is equal to the cardinality of the original set.*)\nLemma card_in_imset : {in D &, injective f} -> #|f @: D| = #|D|.\n\n(*This lemma states that if a function is injective on its entire domain, then the cardinality of the image of any subset of the domain is equal to the cardinality of that subset.*)\nLemma card_imset : injective f -> #|f @: D| = #|D|.\n\n(*This lemma establishes a logical equivalence between the property that a function is injective on a given set and the boolean proposition that the cardinality of the image of the set is equal to the cardinality of the set itself.*)\nLemma imset_injP : reflect {in D &, injective f} (#|f @: D| == #|D|).\n\n(*This lemma states that if two functions are inverses of each other when restricted to a given set and its image, then the image of the set under the first function is identical to the preimage of that set under the second function.*)\nLemma can2_in_imset_pre :\n {in D, cancel f g} -> {on D, cancel g & f} -> f @: D = g @^-1: D.\n\n(*This lemma states that if two functions are globally inverse to each other, then for any set, its image under the first function is identical to its preimage under the second function.*)\nLemma can2_imset_pre : cancel f g -> cancel g f -> f @: D = g @^-1: D.\n\nEnd CardFunImage.\n\nArguments imset_injP {aT rT f D}.\n\n(*This lemma states that if a function is bijective when its domain is restricted to the preimage of a given set in the codomain, then the cardinality of that preimage set is equal to the cardinality of the given set.*)\nLemma on_card_preimset (aT rT : finType) (f : aT -> rT) (R : {pred rT}) :\n {on R, bijective f} -> #|f @^-1: R| = #|R|.\n\n(*This lemma states that for a function on a finite type which has a left inverse, the image of any set under the function is equal to the preimage of that same set under its left inverse.*)\nLemma can_imset_pre (T : finType) f g (A : {set T}) :\n cancel f g -> f @: A = g @^-1: A :> {set T}.\n\n(*This lemma states that the image of a set under the identity function is the set itself.*)\nLemma imset_id (T : finType) (A : {set T}) : [set x | x in A] = A.\n\n(*This lemma states that for an injective function on a finite type, the cardinality of the preimage of any set is equal to the cardinality of that set.*)\nLemma card_preimset (T : finType) (f : T -> T) (A : {set T}) :\n injective f -> #|f @^-1: A| = #|A|.\n\n(*This lemma states that the cardinality of the powerset of a finite set is equal to two raised to the power of the cardinality of the original set.*)\nLemma card_powerset (T : finType) (A : {set T}) : #|powerset A| = 2 ^ #|A|.\n\nSection FunImageComp.\n\nVariables T T' U : finType.\n\n(*This lemma states that the image of a set under the composition of two functions is equal to the image under the first function of the image of the set under the second function.*)\nLemma imset_comp (f : T' -> U) (g : T -> T') (H : {pred T}) :\n (f \\o g) @: H = f @: (g @: H).\n\nEnd FunImageComp.\n\n(*This notation represents the union of a family of sets, where the family is generated by applying a given function to each index that is drawn from a specified range and satisfies a given predicate.*)\nNotation \"\\bigcup_ ( i <- r | P ) F\" :=\n (\\big[@setU _/set0]_(i <- r | P) F%SET) : set_scope.\n(*This notation represents the union of a family of sets, where the family is generated by applying a given function to each index drawn from a specified range.*)\nNotation \"\\bigcup_ ( i <- r ) F\" :=\n (\\big[@setU _/set0]_(i <- r) F%SET) : set_scope.\n(*This notation represents the union of a family of sets, where the family is generated by applying a given function to each natural number in a given half-open interval that also satisfies a given predicate.*)\nNotation \"\\bigcup_ ( m <= i < n | P ) F\" :=\n (\\big[@setU _/set0]_(m <= i < n | P%B) F%SET) : set_scope.\n(*This notation represents the union of a family of sets, where the family is generated by applying a given function to each natural number in a given half-open interval.*)\nNotation \"\\bigcup_ ( m <= i < n ) F\" :=\n (\\big[@setU _/set0]_(m <= i < n) F%SET) : set_scope.\n(*This notation represents the union of a family of sets, where the family is generated by applying a given function to each element of a type that satisfies a given predicate.*)\nNotation \"\\bigcup_ ( i | P ) F\" :=\n (\\big[@setU _/set0]_(i | P%B) F%SET) : set_scope.\n(*This notation represents the union of a family of sets, where the family is generated by applying a given function to every element of a given type.*)\nNotation \"\\bigcup_ i F\" :=\n (\\big[@setU _/set0]_i F%SET) : set_scope.\n(*This notation represents the union of a family of sets, where the family is generated by applying a given function to each element of a specified type that satisfies a given predicate.*)\nNotation \"\\bigcup_ ( i : t | P ) F\" :=\n (\\big[@setU _/set0]_(i : t | P%B) F%SET) (only parsing): set_scope.\n(*This notation represents the union of a family of sets, indexed by all elements of a given finite type.*)\nNotation \"\\bigcup_ ( i : t ) F\" :=\n (\\big[@setU _/set0]_(i : t) F%SET) (only parsing) : set_scope.\n(*This notation represents the union of a family of sets, indexed by natural numbers less than a given bound that also satisfy a specific predicate.*)\nNotation \"\\bigcup_ ( i < n | P ) F\" :=\n (\\big[@setU _/set0]_(i < n | P%B) F%SET) : set_scope.\n(*This notation represents the union of a family of sets, indexed by natural numbers less than a given bound.*)\nNotation \"\\bigcup_ ( i < n ) F\" :=\n (\\big[@setU _/set0]_ (i < n) F%SET) : set_scope.\n(*This notation represents the union of a family of sets, indexed by elements of a given finite set that also satisfy a specific predicate.*)\nNotation \"\\bigcup_ ( i 'in' A | P ) F\" :=\n (\\big[@setU _/set0]_(i in A | P%B) F%SET) : set_scope.\n(*This notation represents the union of a family of sets, indexed by the elements of a given finite set.*)\nNotation \"\\bigcup_ ( i 'in' A ) F\" :=\n (\\big[@setU _/set0]_(i in A) F%SET) : set_scope.\n\n(*This notation represents the intersection of a family of sets, indexed by elements of a given finite sequence that also satisfy a specific predicate.*)\nNotation \"\\bigcap_ ( i <- r | P ) F\" :=\n (\\big[@setI _/setT]_(i <- r | P%B) F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by the elements of a given finite sequence.*)\nNotation \"\\bigcap_ ( i <- r ) F\" :=\n (\\big[@setI _/setT]_(i <- r) F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by natural numbers within a given range that also satisfy a specific predicate.*)\nNotation \"\\bigcap_ ( m <= i < n | P ) F\" :=\n (\\big[@setI _/setT]_(m <= i < n | P%B) F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by natural numbers within a given range.*)\nNotation \"\\bigcap_ ( m <= i < n ) F\" :=\n (\\big[@setI _/setT]_(m <= i < n) F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by elements of a finite type that satisfy a specific predicate.*)\nNotation \"\\bigcap_ ( i | P ) F\" :=\n (\\big[@setI _/setT]_(i | P%B) F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by all elements of a given finite type.*)\nNotation \"\\bigcap_ i F\" :=\n (\\big[@setI _/setT]_i F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by elements of a given finite type that satisfy a specific predicate.*)\nNotation \"\\bigcap_ ( i : t | P ) F\" :=\n (\\big[@setI _/setT]_(i : t | P%B) F%SET) (only parsing): set_scope.\n(*This notation represents the intersection of a family of sets, indexed by all elements of a given finite type.*)\nNotation \"\\bigcap_ ( i : t ) F\" :=\n (\\big[@setI _/setT]_(i : t) F%SET) (only parsing) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by natural numbers less than a given bound that also satisfy a specific predicate.*)\nNotation \"\\bigcap_ ( i < n | P ) F\" :=\n (\\big[@setI _/setT]_(i < n | P%B) F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by natural numbers less than a given bound.*)\nNotation \"\\bigcap_ ( i < n ) F\" :=\n (\\big[@setI _/setT]_(i < n) F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by elements of a given finite set that also satisfy a specific predicate.*)\nNotation \"\\bigcap_ ( i 'in' A | P ) F\" :=\n (\\big[@setI _/setT]_(i in A | P%B) F%SET) : set_scope.\n(*This notation represents the intersection of a family of sets, indexed by the elements of a given finite set.*)\nNotation \"\\bigcap_ ( i 'in' A ) F\" :=\n (\\big[@setI _/setT]_(i in A) F%SET) : set_scope.\n\nSection BigSetOps.\n\nVariables T I : finType.\nImplicit Types (U : {pred T}) (P : pred I) (A B : {set I}) (F : I -> {set T}).\n\n(*This lemma states that if a given index satisfies the indexing predicate for a big union of sets, then the set corresponding to that index is a subset of the total union.*)\nLemma bigcup_sup j P F : P j -> F j \\subset \\bigcup_(i | P i) F i.\n\n(*This lemma states that if a given set is a subset of one of the sets in a family being unioned, and the index for that set satisfies the governing predicate, then the given set is also a subset of the total union.*)\nLemma bigcup_max j U P F :\n P j -> U \\subset F j -> U \\subset \\bigcup_(i | P i) F i.\n\n(*This lemma provides an equivalence property for membership in a big union of sets, stating that an element belongs to the union if and only if there exists an index satisfying the governing predicate such that the element is a member of the set corresponding to that index.*)\nLemma bigcupP x P F :\n reflect (exists2 i, P i & x \\in F i) (x \\in \\bigcup_(i | P i) F i).\n\n(*This lemma provides an equivalence property for a big union of sets being a subset of another set, stating that the union is a subset of the given set if and only if every set in the indexed family that meets the predicate is a subset of that given set.*)\nLemma bigcupsP U P F :\n reflect (forall i, P i -> F i \\subset U) (\\bigcup_(i | P i) F i \\subset U).\n\n(*This lemma provides an equivalence property for a big union of sets being equal to the empty set, stating that the union is empty if and only if every set in the indexed family that meets the predicate is itself empty.*)\nLemma bigcup0P P F :\n reflect (forall i, P i -> F i = set0) (\\bigcup_(i | P i) F i == set0).\n\n(*This lemma provides an equivalence property for the disjointness of a set and a big union, stating that the set is disjoint from the union if and only if it is disjoint from every set in the indexed family that satisfies the governing predicate.*)\nLemma bigcup_disjointP U P F :\n reflect (forall i : I, P i -> [disjoint U & F i])\n [disjoint U & \\bigcup_(i | P i) F i].\n\n(*This lemma states that if a given set is disjoint from every set in an indexed family that meets a certain predicate, then it is also disjoint from the big union of those sets.*)\nLemma bigcup_disjoint U P F :\n (forall i, P i -> [disjoint U & F i]) -> [disjoint U & \\bigcup_(i | P i) F i].\n\n(*This lemma states that the big union of a family of sets over the union of two index sets is equal to the union of the two big unions calculated over each index set individually.*)\nLemma bigcup_setU A B F :\n \\bigcup_(i in A :|: B) F i =\n (\\bigcup_(i in A) F i) :|: (\\bigcup_ (i in B) F i).\n\n(*This lemma states that the big union of a family of sets indexed by the elements of a finite sequence is equal to the big union of the same family of sets indexed by the elements of the finite set corresponding to that sequence.*)\nLemma bigcup_seq r F : \\bigcup_(i <- r) F i = \\bigcup_(i in r) F i.\n\n(*This lemma states that if a given index satisfies the indexing predicate for a big intersection of sets, then the total intersection is a subset of the set corresponding to that index.*)\nLemma bigcap_inf j P F : P j -> \\bigcap_(i | P i) F i \\subset F j.\n\n(*This lemma states that if a set from an indexed family is a subset of a given set, and its index satisfies the governing predicate, then the big intersection of the family is also a subset of that given set.*)\nLemma bigcap_min j U P F :\n P j -> F j \\subset U -> \\bigcap_(i | P i) F i \\subset U.\n\n(*This lemma provides an equivalence property for a set being a subset of a big intersection, stating that the set is a subset of the intersection if and only if it is a subset of every set in the indexed family that satisfies the governing predicate.*)\nLemma bigcapsP U P F :\n reflect (forall i, P i -> U \\subset F i) (U \\subset \\bigcap_(i | P i) F i).\n\n(*This lemma provides an equivalence property for membership in a big intersection of sets, stating that an element belongs to the intersection if and only if it is a member of every set in the indexed family that satisfies the governing predicate.*)\nLemma bigcapP x P F :\n reflect (forall i, P i -> x \\in F i) (x \\in \\bigcap_(i | P i) F i).\n\n(*This lemma states that the complement of the union of a family of sets, indexed over a filtered finite sequence, is equal to the intersection of the complements of those sets.*)\nLemma setC_bigcup J r (P : pred J) (F : J -> {set T}) :\n ~: (\\bigcup_(j <- r | P j) F j) = \\bigcap_(j <- r | P j) ~: F j.\n\n(*This lemma states that the complement of the intersection of a family of sets, indexed over a filtered finite sequence, is equal to the union of the complements of those sets.*)\nLemma setC_bigcap J r (P : pred J) (F : J -> {set T}) :\n ~: (\\bigcap_(j <- r | P j) F j) = \\bigcup_(j <- r | P j) ~: F j.\n\n(*This lemma states that the intersection of a family of sets indexed over the union of two index sets is equal to the intersection of the results of intersecting the family over each index set separately.*)\nLemma bigcap_setU A B F :\n (\\bigcap_(i in A :|: B) F i) =\n (\\bigcap_(i in A) F i) :&: (\\bigcap_(i in B) F i).\n\n(*This lemma states that intersecting a family of sets over the indices in a finite sequence yields the same result as intersecting the family over the set of elements in that sequence.*)\nLemma bigcap_seq r F : \\bigcap_(i <- r) F i = \\bigcap_(i in r) F i.\n\nEnd BigSetOps.\n\nArguments bigcup_sup [T I] j [P F].\nArguments bigcup_max [T I] j [U P F].\nArguments bigcupP {T I x P F}.\nArguments bigcupsP {T I U P F}.\nArguments bigcup_disjointP {T I U P F}.\nArguments bigcap_inf [T I] j [P F].\nArguments bigcap_min [T I] j [U P F].\nArguments bigcapP {T I x P F}.\nArguments bigcapsP {T I U P F}.\n\nSection ImsetCurry.\n\nVariables (aT1 aT2 rT : finType) (f : aT1 -> aT2 -> rT).\n\nSection Curry.\n\nVariables (A1 : {set aT1}) (A2 : {set aT2}).\nVariables (D1 : {pred aT1}) (D2 : {pred aT2}).\n\n(*This lemma states that the image of a pair of sets under a curried two-argument function is equal to the image of the Cartesian product of those sets under the uncurried version of the function.*)\nLemma curry_imset2X : f @2: (A1, A2) = uncurry f @: (setX A1 A2).\n\n(*This lemma states that the image of a pair of sets under a curried two-argument function can be computed as a union of images, formed by applying the function to each element of the first set and the entire second set.*)\nLemma curry_imset2l : f @2: (D1, D2) = \\bigcup_(x1 in D1) f x1 @: D2.\n\n(*This lemma states that the image of a pair of sets under a curried two-argument function can be computed as a union of images, formed by applying the transposed function to each element of the second set and the entire first set.*)\nLemma curry_imset2r : f @2: (D1, D2) = \\bigcup_(x2 in D2) f^~ x2 @: D1.\n\nEnd Curry.\n\n(*This lemma demonstrates that the image of a pair of sets under a two-argument function distributes over a union in its first argument.*)\nLemma imset2Ul (A B : {set aT1}) (C : {set aT2}) :\n f @2: (A :|: B, C) = f @2: (A, C) :|: f @2: (B, C).\n\n(*This lemma demonstrates that the image of a pair of sets under a two-argument function distributes over a union in its second argument.*)\nLemma imset2Ur (A : {set aT1}) (B C : {set aT2}) :\n f @2: (A, B :|: C) = f @2: (A, B) :|: f @2: (A, C).\n\nEnd ImsetCurry.\n\nSection Partitions.\n\nVariables T I : finType.\nImplicit Types (x y z : T) (A B D X : {set T}) (P Q : {set {set T}}).\nImplicit Types (J : pred I) (F : I -> {set T}).\n\n(*This definition defines the cover of a set of sets as the union of all the member sets.*)\nDefinition cover P := \\bigcup_(B in P) B.\n(*This definition defines the partition block containing a given element with respect to a given set of sets. It returns a set from the collection that contains the element, or the empty set if no such set exists.*)\nDefinition pblock P x := odflt set0 (pick [pred B in P | x \\in B]).\n(*This definition defines a boolean property for a set of sets which is true if the sum of the cardinalities of the member sets equals the cardinality of their union, which is equivalent to the sets being pairwise disjoint.*)\nDefinition trivIset P := \\sum_(B in P) #|B| == #|cover P|.\n(*This definition defines a boolean property that is true if a given collection of sets forms a partition of a given domain set. This requires that the union of the collection equals the domain, the sets in the collection are pairwise disjoint, and the collection does not contain the empty set.*)\nDefinition partition P D := [&& cover P == D, trivIset P & set0 \\notin P].\n\n(*This definition defines a boolean property that is true if a set is a transversal for a given partition of a domain. This requires that the collection of sets is a partition of the domain, the potential transversal set is a subset of the domain, and its intersection with each block of the partition has a cardinality of exactly one.*)\nDefinition is_transversal X P D :=\n [&& partition P D, X \\subset D & [forall B in P, #|X :&: B| == 1]].\n(*This definition constructs a set that is a transversal of a partition of a domain. For each element in the domain, it identifies the partition block containing that element and selects a canonical representative from that block, collecting these representatives into a new set.*)\nDefinition transversal P D := [set odflt x [pick y in pblock P x] | x in D].\n(*This definition defines a representative element for the intersection of two sets. It selects a canonical element from the intersection, returning a specified default element if the intersection is empty.*)\nDefinition transversal_repr x0 X B := odflt x0 [pick x in X :&: B].\n\n(*This lemma states that the cardinality of the union of two sets is less than or equal to the sum of their individual cardinalities. It also states that equality holds if and only if the two sets are disjoint.*)\nLemma leq_card_setU A B : #|A :|: B| <= #|A| + #|B| ?= iff [disjoint A & B].\n\n(*This lemma states that the cardinality of the union of a collection of sets is less than or equal to the sum of the cardinalities of the individual sets in the collection. Equality holds if and only if the sets in the collection are pairwise disjoint.*)\nLemma leq_card_cover P : #|cover P| <= \\sum_(A in P) #|A| ?= iff trivIset P.\n\n(*This lemma states that the image of the union of a collection of sets under a function is equal to the union of the images of each individual set in that collection.*)\nLemma imset_cover (T' : finType) P (f : T -> T') :\n [set f x | x in cover P] = \\bigcup_(i in P) [set f x | x in i].\n\n(*This lemma states that the cover of a collection containing a single set is that set itself.*)\nLemma cover1 A : cover [set A] = A.\n\n(*This lemma states that any collection containing just a single set satisfies the property of having pairwise disjoint members.*)\nLemma trivIset1 A : trivIset [set A].\n\n(*This lemma states that for a collection of sets, the property of having a union whose cardinality equals the sum of the individual cardinalities is equivalent to the property that any two distinct sets in the collection are disjoint.*)\nLemma trivIsetP P :\n reflect {in P &, forall A B, A != B -> [disjoint A & B]} (trivIset P).\n\n(*This lemma states that if a collection of sets consists of pairwise disjoint sets, then any sub-collection also consists of pairwise disjoint sets.*)\nLemma trivIsetS P Q : P \\subset Q -> trivIset Q -> trivIset P.\n\n(*This lemma states that if a collection of sets is pairwise disjoint, then the collection formed by removing some sets from it remains pairwise disjoint.*)\nLemma trivIsetD P Q : trivIset P -> trivIset (P :\\: Q).\n\n(*This lemma states that the union of two collections of pairwise disjoint sets is also a collection of pairwise disjoint sets, provided that the union of the sets in the first collection is disjoint from the union of the sets in the second collection.*)\nLemma trivIsetU P Q :\n trivIset Q -> trivIset P -> [disjoint cover Q & cover P] -> trivIset (Q :|: P).\n\n(*This lemma states that for a collection of pairwise disjoint sets, the union of the sets remaining after removing one member set is equal to the set difference between the original union and the removed set.*)\nLemma coverD1 P B : trivIset P -> B \\in P -> cover (P :\\ B) = cover P :\\: B.\n\n(*This lemma states that if a collection of sets is pairwise disjoint, then the collection formed by intersecting each of its member sets with a given set is also pairwise disjoint.*)\nLemma trivIsetI P D : trivIset P -> trivIset (P ::&: D).\n\n(*This lemma states that the union of a collection of sets, where each set has been intersected with a given set, is a subset of the intersection between the original union and the given set.*)\nLemma cover_setI P D : cover (P ::&: D) \\subset cover P :&: D.\n\n(*This lemma states that an element is a member of its own partition block if and only if it is a member of the union of all sets in the given collection.*)\nLemma mem_pblock P x : (x \\in pblock P x) = (x \\in cover P).\n\n(*This lemma states that if an element is in the union of a collection of sets, then the partition block containing that element is itself a member of the collection.*)\nLemma pblock_mem P x : x \\in cover P -> pblock P x \\in P.\n\n(*This lemma states that for a collection of pairwise disjoint sets, if a given set is part of this collection and contains a certain element, then the block corresponding to that element is the given set.*)\nLemma def_pblock P B x : trivIset P -> B \\in P -> x \\in B -> pblock P x = B.\n\n(*This lemma states that for a collection of pairwise disjoint sets, if a first element is contained in the block defined by a second element, then the block of the first element is identical to the block of the second element.*)\nLemma same_pblock P x y :\n trivIset P -> x \\in pblock P y -> pblock P x = pblock P y.\n\n(*This lemma states that for a collection of pairwise disjoint sets and an element within their union, the block associated with that element is equal to the block of a second element if and only if the second element is a member of the first element's block.*)\nLemma eq_pblock P x y :\n trivIset P -> x \\in cover P ->\n (pblock P x == pblock P y) = (y \\in pblock P x).\n\n(*This lemma states that if a given set is disjoint from every set in a collection of pairwise disjoint, non-empty sets, then the new collection formed by adding the given set preserves the property of being pairwise disjoint, and the given set was not already present in the original collection.*)\nLemma trivIsetU1 A P :\n {in P, forall B, [disjoint A & B]} -> trivIset P -> set0 \\notin P ->\n trivIset (A |: P) /\\ A \\notin P.\n\n(*This lemma states that the union of all sets in a collection formed by the image of a function over an index set is equal to the indexed union of the sets generated by applying the function to each element of the index set.*)\nLemma cover_imset J F : cover (F @: J) = \\bigcup_(i in J) F i.\n\n(*This lemma states that if a function from an index set to a collection of sets maps distinct indices to disjoint sets, and none of the resulting sets are empty, then the collection of resulting sets is pairwise disjoint and the function itself is injective.*)\nLemma trivIimset J F (P := F @: J) :\n {in J &, forall i j, j != i -> [disjoint F i & F j]} -> set0 \\notin P ->\n trivIset P /\\ {in J &, injective F}.\n\n(*This lemma states that if a collection of sets forms a partition of a given set, then the union of all sets in that collection is equal to the given set.*)\nLemma cover_partition P D : partition P D -> cover P = D.\n\n(*This lemma states that if a collection of sets forms a partition, then the empty set cannot be a member of that collection.*)\nLemma partition0 P D : partition P D -> set0 \\in P = false.\n\n(*This lemma states that for any partition of a set, every block within that partition is a non-empty set.*)\nLemma partition_neq0 P D B : partition P D -> B \\in P -> B != set0.\n\n(*This lemma states that if a collection of sets forms a partition of a given set, then its constituent sets are pairwise disjoint.*)\nLemma partition_trivIset P D : partition P D -> trivIset P.\n\n(*This lemma states that if a collection of sets forms a partition of a given set, then every set in that collection is a subset of the given set.*)\nLemma partitionS P D B : partition P D -> B \\in P -> B \\subset D.\n\n(*This lemma states that if a collection of sets forms a partition of a given set, then removing one set from the collection results in a new collection that is a partition of the original set minus the removed set.*)\nLemma partitionD1 P D B :\n partition P D -> B \\in P -> partition (P :\\ B) (D :\\: B).\n\n(*This lemma states that given a partition of a set, if a non-empty set is disjoint from the partitioned set, then adding this new set to the collection of partitioning sets creates a valid partition of the union of the original set and the new set.*)\nLemma partitionU1 P D B :\n partition P D -> B != set0 -> [disjoint B & D] -> partition (B |: P) (B :|: D).\n\n(*This lemma states that a collection of sets forms a partition of the empty set if and only if the collection itself is empty.*)\nLemma partition_set0 P : partition P set0 = (P == set0).\n\n(*This lemma states that for a partition of a finite set, the cardinality of the set is equal to the sum of the cardinalities of all the sets in the partition.*)\nLemma card_partition P D : partition P D -> #|D| = \\sum_(A in P) #|A|.\n\n(*This lemma states that if a collection of sets forms a partition of a finite set, and every set in the collection has the same given cardinality, then the cardinality of the partitioned set is the product of the number of sets in the collection and their common cardinality.*)\nLemma card_uniform_partition n P D :\n {in P, forall A, #|A| = n} -> partition P D -> #|D| = #|P| * n.\n\n(*This lemma states a version of the pigeonhole principle: for a partition of a set, if a subset of this set has a cardinality greater than or equal to the number of blocks in the partition, and each block intersects the subset in at most one element, then every block must have a non-empty intersection with the subset.*)\nLemma partition_pigeonhole P D A :\n partition P D -> #|P| <= #|A| -> A \\subset D -> {in P, forall B, #|A :&: B| <= 1} ->\n {in P, forall B, A :&: B != set0}.\n\nSection BigOps.\n\nVariables (R : Type) (idx : R) (op : Monoid.com_law idx).\n(*This definition introduces a notation for a nested computation over a collection of sets. The computation first applies a commutative monoid operation to the results of a function on elements within each set that satisfy a predicate, and then applies the same operation to combine the results from each set.*)\nLet rhs_cond P K E := \\big[op/idx]_(A in P) \\big[op/idx]_(x in A | K x) E x.\n(*This definition introduces a notation for a nested computation over a collection of sets. The computation first applies a commutative monoid operation to the results of a function on all elements within each set, and then applies the same operation to combine the results from each set.*)\nLet rhs P E := \\big[op/idx]_(A in P) \\big[op/idx]_(x in A) E x.\n\n(*This lemma states that for a collection of pairwise disjoint sets, an aggregation over all elements in the union of these sets that satisfy a predicate is equal to a nested aggregation performed first over the elements of each set satisfying the predicate, and then over the sets themselves.*)\nLemma big_trivIset_cond P (K : pred T) (E : T -> R) :\n trivIset P -> \\big[op/idx]_(x in cover P | K x) E x = rhs_cond P K E.\n\n(*This lemma states that for a collection of pairwise disjoint sets, an aggregation over all elements in the union of these sets is equal to a nested aggregation performed first over the elements of each set, and then over the sets themselves.*)\nLemma big_trivIset P (E : T -> R) :\n trivIset P -> \\big[op/idx]_(x in cover P) E x = rhs P E.\n\n(*This lemma states that if a collection of sets forms a partition of a given set, an aggregation over the elements of the given set that satisfy a predicate is equal to a nested aggregation performed first over elements within each partitioning block that satisfy the predicate, and then over all the blocks.*)\nLemma set_partition_big_cond P D (K : pred T) (E : T -> R) :\n partition P D -> \\big[op/idx]_(x in D | K x) E x = rhs_cond P K E.\n\n(*This lemma states that if a collection of sets forms a partition of a given set, an aggregation over all elements of the given set is equal to a nested aggregation performed first over the elements within each partitioning block, and then over all the blocks.*)\nLemma set_partition_big P D (E : T -> R) :\n partition P D -> \\big[op/idx]_(x in D) E x = rhs P E.\n\n(*This lemma states that for an indexed family of pairwise disjoint sets, an aggregation over the union of all sets in the family is equivalent to a nested aggregation, where an inner aggregation is first performed over each set, and an outer aggregation is then performed over the results for each index.*)\nLemma partition_disjoint_bigcup (F : I -> {set T}) E :\n (forall i j, i != j -> [disjoint F i & F j]) ->\n \\big[op/idx]_(x in \\bigcup_i F i) E x =\n \\big[op/idx]_i \\big[op/idx]_(x in F i) E x.\n\nEnd BigOps.\n\nSection Equivalence.\n\nVariables (R : rel T) (D : {set T}).\n\n(*This definition specifies a function that, for a given element, returns the set of all elements in a domain that are related to it by a given binary relation, effectively defining its equivalence class.*)\nLet Px x := [set y in D | R x y].\n(*This definition constructs the set of all sets of related elements, where each set is formed by taking an element from a given domain and collecting all other elements from that domain that are related to it by a specified binary relation.*)\nDefinition equivalence_partition := [set Px x | x in D].\n(*This notation introduces a local shorthand for the collection of equivalence classes generated by a relation on a given domain.*)\nLocal Notation P := equivalence_partition.\nHypothesis eqiR : {in D & &, equivalence_rel R}.\n\n(*This definition provides a proof that any element in the domain of an equivalence relation is a member of its own equivalence class, which is a consequence of the relation's reflexivity.*)\nLet Pxx x : x \\in D -> x \\in Px x.\n\n(*This definition provides a proof that for any element in the domain of an equivalence relation, its corresponding equivalence class is a member of the collection of all equivalence classes.*)\nLet PPx x : x \\in D -> Px x \\in P := fun Dx => imset_f _ Dx.\n\n(*This lemma states that the collection of all equivalence classes induced by an equivalence relation on a given domain forms a partition of that domain.*)\nLemma equivalence_partitionP : partition P D.\n\n(*This lemma states that for a partition generated from an equivalence relation, an element `y` belongs to the partition block of an element `x` if and only if `x` and `y` are equivalent under that relation.*)\nLemma pblock_equivalence_partition :\n {in D &, forall x y, (y \\in pblock P x) = R x y}.\n\nEnd Equivalence.\n\n(*This lemma states that for any given partition of a set, the relation of two elements belonging to the same partition block forms an equivalence relation on that set.*)\nLemma pblock_equivalence P D :\n partition P D -> {in D & &, equivalence_rel (fun x y => y \\in pblock P x)}.\n\n(*This lemma states that if one starts with a partition, defines an equivalence relation based on its blocks, and then generates a new partition from this relation, the resulting partition is identical to the original one.*)\nLemma equivalence_partition_pblock P D :\n partition P D -> equivalence_partition (fun x y => y \\in pblock P x) D = P.\n\nSection Preim.\n\nVariables (rT : eqType) (f : T -> rT).\n\n(*This definition constructs a partition of a set where each block consists of all elements that are mapped to the same value by a given function.*)\nDefinition preim_partition := equivalence_partition (fun x y => f x == f y).\n\n(*This lemma asserts that the collection of preimages generated by a function over a given domain forms a valid partition of that domain.*)\nLemma preim_partitionP D : partition (preim_partition D) D.\n\nEnd Preim.\n\n(*This lemma states that for a given partition of a set, the preimage partition induced by the function that maps each element to its block is identical to the original partition.*)\nLemma preim_partition_pblock P D :\n partition P D -> preim_partition (pblock P) D = P.\n\n(*This lemma states that the canonical construction of a transversal for a given partition of a set indeed produces a valid transversal, which is a set containing exactly one element from each block of the partition.*)\nLemma transversalP P D : partition P D -> is_transversal (transversal P D) P D.\n\nSection Transversals.\n\nVariables (X : {set T}) (P : {set {set T}}) (D : {set T}).\nHypothesis trPX : is_transversal X P D.\n\n(*This lemma states that a transversal of a partition on a set is a subset of that set.*)\nLemma transversal_sub : X \\subset D. \n\n(*This declaration represents a proof that a given partition consists of non-empty sets, which is a precondition for operations involving transversals.*)\nLet tiP : trivIset P. \n\n(*This declaration represents a proof that a transversal set is a subset of the union of all blocks in the corresponding partition.*)\nLet sXP : {subset X <= cover P}.\n\n(*This declaration represents the fundamental property of a transversal, stating that its intersection with any block of the partition contains exactly one element.*)\nLet trX : {in P, forall B, #|X :&: B| == 1}.\n\n(*This lemma states that the intersection of a transversal set and a specific block from a partition is a singleton set containing that block's chosen representative element.*)\nLemma setI_transversal_pblock x0 B :\n B \\in P -> X :&: B = [set transversal_repr x0 X B].\n\n(*This lemma asserts that the representative element chosen from a partition block is a member of that same block.*)\nLemma repr_mem_pblock x0 B : B \\in P -> transversal_repr x0 X B \\in B.\n\n(*This lemma asserts that the representative element of any partition block is a member of the transversal set.*)\nLemma repr_mem_transversal x0 B : B \\in P -> transversal_repr x0 X B \\in X.\n\n(*This lemma establishes a cancellation law, stating that finding the representative element of a partition block and then finding the block containing that representative returns the original block.*)\nLemma transversal_reprK x0 : {in P, cancel (transversal_repr x0 X) (pblock P)}.\n\n(*This lemma provides a cancellation law, stating that finding the partition block of an element from a transversal and then finding the representative of that block returns the original element.*)\nLemma pblockK x0 : {in X, cancel (pblock P) (transversal_repr x0 X)}.\n\n(*This lemma states that the function mapping an element to its partition block is injective when restricted to a transversal of the partition.*)\nLemma pblock_inj : {in X &, injective (pblock P)}.\n\n(*This lemma states that the image of a transversal set under the function that maps elements to their partition blocks is the set of all blocks in the partition.*)\nLemma pblock_transversal : pblock P @: X = P.\n\n(*This lemma states that the cardinality of a transversal set is equal to the number of blocks in the corresponding partition.*)\nLemma card_transversal : #|X| = #|P|.\n\n(*This lemma states that the image of the set of all partition blocks under the representative selection function is the transversal set itself.*)\nLemma im_transversal_repr x0 : transversal_repr x0 X @: P = X.\n\nEnd Transversals.\n\nEnd Partitions.\n\nArguments trivIsetP {T P}.\nArguments big_trivIset_cond [T R idx op] P [K E].\nArguments set_partition_big_cond [T R idx op] P [D K E].\nArguments big_trivIset [T R idx op] P [E].\nArguments set_partition_big [T R idx op] P [D E].\n\nPrenex Implicits cover trivIset partition pblock.\n\n(*This lemma describes the formation of a coarser partition from a finer one. It states that if a set of sets `Q` partitions a partition `P` of a domain `D`, then the set of unions of the blocks in each part of `Q` forms a valid partition of `D`.*)\nLemma partition_partition (T : finType) (D : {set T}) P Q :\n partition P D -> partition Q P ->\n partition (cover @: Q) D /\\ {in Q &, injective cover}.\n\n(*This lemma provides conditions for an indexed family of sets to form a partition, stating that a family of non-empty, pairwise disjoint sets forms a partition of their union.*)\nLemma indexed_partition (I T : finType) (J : {pred I}) (B : I -> {set T}) :\n let P := [set B i | i in J] in\n {in J &, forall i j : I, j != i -> [disjoint B i & B j]} ->\n (forall i : I, J i -> B i != set0) -> partition P (cover P) /\\ {in J &, injective B}.\n\nSection PartitionImage.\nVariables (T : finType) (P : {set {set T}}) (D : {set T}).\nVariables (T' : finType) (f : T -> T') (inj_f : injective f).\n(*This definition denotes the set of sets obtained by applying a function to each set in a given collection of sets.*)\nLet fP := [set f @: (B : {set T}) | B in P].\n\n(*This lemma states that the image of a collection of sets under an injective function contains the empty set if and only if the original collection of sets contained the empty set.*)\nLemma imset_trivIset : trivIset fP = trivIset P.\n\n(*This lemma states that the empty set is a member of the image of a collection of sets if and only if it is a member of the original collection.*)\nLemma imset0mem : (set0 \\in fP) = (set0 \\in P).\n\n(*This lemma states that the property of being a partition is preserved under an injective function; that is, a collection of sets forms a partition of a domain if and only if their images under the function form a partition of the image of the domain.*)\nLemma imset_partition : partition fP (f @: D) = partition P D.\n\nEnd PartitionImage.\n\nSection MaxSetMinSet.\n\nVariable T : finType.\n(*This notation serves as a shorthand for the type of sets whose elements are of a given finite type.*)\nNotation sT := {set T}.\nImplicit Types A B C : sT.\nImplicit Type P : pred sT.\n\n(*This definition specifies a property for a set, which holds if the set satisfies a given predicate, but no proper subset of it does, effectively identifying it as a minimal set satisfying the predicate with respect to the subset relation.*)\nDefinition minset P A := [forall (B : sT | B \\subset A), (B == A) == P B].\n\n(*This lemma states that if two predicates on sets are extensionally equal, then the property of a given set being minimal for the first predicate is equivalent to it being minimal for the second predicate.*)\nLemma minset_eq P1 P2 A : P1 =1 P2 -> minset P1 A = minset P2 A.\n\n(*This lemma establishes the definition of a minimal set. It states that a set is minimal with respect to a given predicate if and only if it satisfies the predicate and no proper subset of it also satisfies the predicate.*)\nLemma minsetP P A :\n reflect ((P A) /\\ (forall B, P B -> B \\subset A -> B = A)) (minset P A).\n\nArguments minsetP {P A}.\n\n(*This lemma states that if a given set is minimal with respect to a predicate, then that set must satisfy the predicate.*)\nLemma minsetp P A : minset P A -> P A.\n\n(*This lemma states that if a given set is minimal with respect to a predicate, then any other set satisfying the same predicate and contained within the given set must be equal to it.*)\nLemma minsetinf P A B : minset P A -> P B -> B \\subset A -> B = A.\n\n(*This lemma asserts that if there exists at least one set satisfying a given predicate, then there must exist a minimal set satisfying that predicate.*)\nLemma ex_minset P : (exists A, P A) -> {A | minset P A}.\n\n(*This lemma asserts that if a given set satisfies a predicate, then there exists a minimal set for that predicate which is a subset of the given set.*)\nLemma minset_exists P C : P C -> {A | minset P A & A \\subset C}.\n\n(*This fact provides a unique key used internally to define the concept of a maximal set in terms of a minimal set, ensuring the definition remains abstract.*)\nFact maxset_key : unit. \n(*This definition specifies a maximal set for a given predicate. A set is maximal for a predicate if its complement is a minimal set for a related predicate based on the complement.*)\nDefinition maxset P A :=\n minset (fun B => locked_with maxset_key P (~: B)) (~: A).\n\n(*This lemma states that if two predicates on sets are extensionally equal, then the property of a given set being maximal for the first predicate is equivalent to it being maximal for the second predicate.*)\nLemma maxset_eq P1 P2 A : P1 =1 P2 -> maxset P1 A = maxset P2 A.\n\n(*This lemma shows the explicit definition of a maximal set. It states that a set is maximal for a predicate if and only if its complement is a minimal set for the predicate applied to complements of sets.*)\nLemma maxminset P A : maxset P A = minset [pred B | P (~: B)] (~: A).\n\n(*This lemma shows the explicit definition of a minimal set in terms of a maximal set. It states that a set is minimal for a predicate if and only if its complement is a maximal set for the predicate applied to complements of sets.*)\nLemma minmaxset P A : minset P A = maxset [pred B | P (~: B)] (~: A).\n\n(*This lemma establishes the definition of a maximal set. It states that a set is maximal with respect to a given predicate if and only if it satisfies the predicate and is not a proper subset of any other set that also satisfies the predicate.*)\nLemma maxsetP P A :\n reflect ((P A) /\\ (forall B, P B -> A \\subset B -> B = A)) (maxset P A).\n\n(*This lemma states that if a given set is maximal with respect to a predicate, then that set must satisfy the predicate.*)\nLemma maxsetp P A : maxset P A -> P A.\n\n(*This lemma states that if a given set is maximal with respect to a predicate, then any other set satisfying the same predicate and containing the given set must be equal to it.*)\nLemma maxsetsup P A B : maxset P A -> P B -> A \\subset B -> B = A.\n\n(*This lemma asserts that if there exists at least one set satisfying a given predicate, then there must exist a maximal set satisfying that predicate.*)\nLemma ex_maxset P : (exists A, P A) -> {A | maxset P A}.\n\n(*This lemma asserts that if a given set satisfies a predicate, then there exists a maximal set for that predicate which contains the given set.*)\nLemma maxset_exists P C : P C -> {A : sT | maxset P A & C \\subset A}.\n\nEnd MaxSetMinSet.\n\nArguments setCK {T}.\nArguments minsetP {T P A}.\nArguments maxsetP {T P A}.\nPrenex Implicits minset maxset.\n\nSection SetFixpoint.\n\nSection Least.\nVariables (T : finType) (F : {set T} -> {set T}).\nHypothesis (F_mono : {homo F : X Y / X \\subset Y}).\n\n(*This definition assigns the name `n` to the number of elements in the base finite type.*)\nLet n := #|T|.\n(*This definition describes the function that, for a given natural number, computes the result of repeatedly applying a monotonic set function that many times, starting from the empty set.*)\nLet iterF i := iter i F set0.\n\n(*This lemma states that the set resulting from a given number of applications of a monotonic function is a subset of the set resulting from one additional application.*)\nLemma subset_iterS i : iterF i \\subset iterF i.+1.\n\n(*This lemma states that the function generating iterative applications of a monotonic set function is itself monotonic; applying the function more times results in a superset.*)\nLemma subset_iter : {homo iterF : i j / i <= j >-> i \\subset j}.\n\n(*This definition specifies the least fixed point of a monotonic set function over a finite type, computed by iterating the function a number of times equal to the cardinality of the type, starting from the empty set.*)\nDefinition fixset := iterF n.\n\n(*This lemma states that applying the monotonic set function to its computed least fixed point yields the fixed point itself, confirming it is indeed a fixed point.*)\nLemma fixsetK : F fixset = fixset.\n\nHint Resolve fixsetK : core.\n\n(*This lemma states that the computed fixed point of a monotonic set function is the minimal such fixed point with respect to the subset relation.*)\nLemma minset_fix : minset [pred X | F X == X] fixset.\n\n(*This lemma states that repeatedly applying a monotonic function to its own least fixed point, any number of times, will always result in the same fixed point.*)\nLemma fixsetKn k : iter k F fixset = fixset.\n\n(*This lemma states that any set obtained by iterating a monotonic function from the empty set is a subset of the function's least fixed point.*)\nLemma iter_sub_fix k : iterF k \\subset fixset.\n\n(*This lemma shows that if an element belongs to the least fixed point of a monotonic set function, then there must exist a finite number of iterations after which the element first appears in the iteratively constructed set.*)\nLemma fix_order_proof x : x \\in fixset -> exists n, x \\in iterF n.\n\n(*This definition computes the order of an element with respect to a fixed point construction. The order is the smallest number of iterations of a monotonic set function required for the element to be included in the resulting set; it is zero if the element is not in the fixed point.*)\nDefinition fix_order (x : T) :=\n if (x \\in fixset) =P true isn't ReflectT x_fix then 0\n else (ex_minn (fix_order_proof x_fix)).\n\n(*This lemma states that the order of any element with respect to a fixed point construction is less than or equal to the total number of elements in the underlying finite type.*)\nLemma fix_order_le_max (x : T) : fix_order x <= n.\n\n(*This lemma provides an equivalence property for the order of an element. It states that an element is a member of the set generated by a number of iterations equal to its order if and only if that element is a member of the final fixed point.*)\nLemma in_iter_fix_orderE (x : T) :\n (x \\in iterF (fix_order x)) = (x \\in fixset).\n\n(*This lemma states that the order of an element is greater than zero if and only if the element is a member of the least fixed point.*)\nLemma fix_order_gt0 (x : T) : (fix_order x > 0) = (x \\in fixset).\n\n(*This lemma states that the fixed-point order of an element is equal to zero if and only if that element is not a member of the least fixed point.*)\nLemma fix_order_eq0 (x : T) : (fix_order x == 0) = (x \\notin fixset).\n\n(*This lemma provides an equivalence for an element's membership in the k-th iteration set of a monotonic function. It states that an element belongs to this set if and only if its fixed-point order is a positive number that is less than or equal to the iteration count k.*)\nLemma in_iter_fixE (x : T) k : (x \\in iterF k) = (0 < fix_order x <= k).\n\n(*This lemma states that if an element is a member of the least fixed point and its fixed-point order is less than or equal to a given natural number, then the element is also a member of the iteration set corresponding to that number.*)\nLemma in_iter (x : T) k : x \\in fixset -> fix_order x <= k -> x \\in iterF k.\n\n(*This lemma states that if a given natural number is strictly less than the fixed-point order of an element, then that element is not a member of the iteration set corresponding to that number.*)\nLemma notin_iter (x : T) k : k < fix_order x -> x \\notin iterF k.\n\n(*This lemma states that if an element belongs to the k-th iteration set of a monotonic function, then its fixed-point order is less than or equal to k.*)\nLemma fix_order_small x k : x \\in iterF k -> fix_order x <= k.\n\n(*This lemma states that for an element that is a member of the least fixed point but not of the k-th iteration set, its fixed-point order must be strictly greater than k.*)\nLemma fix_order_big x k : x \\in fixset -> x \\notin iterF k -> fix_order x > k.\n\n(*This lemma establishes a relationship between the fixed-point orders of two elements. It states that if a second element is a member of the iteration set corresponding to the fixed-point order of a first element, then the fixed-point order of the second element is less than or equal to the fixed-point order of the first element.*)\nLemma le_fix_order (x y : T) : y \\in iterF (fix_order x) ->\n fix_order y <= fix_order x.\n\nEnd Least.\n\nSection Greatest.\nVariables (T : finType) (F : {set T} -> {set T}).\nHypothesis (F_mono : {homo F : X Y / X \\subset Y}).\n\n(*This definition introduces the dual of a monotonic set function. The dual function, applied to a given set, returns the complement of the result of applying the original function to the complement of the given set.*)\nDefinition funsetC X := ~: (F (~: X)).\n(*This lemma states that the dual of a monotonic set function is itself monotonic with respect to subset inclusion.*)\nLemma funsetC_mono : {homo funsetC : X Y / X \\subset Y}.\n\nHint Resolve funsetC_mono : core.\n\n(*This definition specifies the greatest fixed point of a monotonic set function. It is defined as the complement of the least fixed point of the corresponding dual function.*)\nDefinition cofixset := ~: fixset funsetC.\n\n(*This lemma states that applying a monotonic set function to its greatest fixed point yields the greatest fixed point itself.*)\nLemma cofixsetK : F cofixset = cofixset.\n\n(*This lemma states that the greatest fixed point of a monotonic set function is the maximal element in the collection of all sets that are fixed points of that function.*)\nLemma maxset_cofix : maxset [pred X | F X == X] cofixset.\n\nEnd Greatest.\n\nEnd SetFixpoint.\n\nSection FProd.\n\nVariables (I : finType) (T_ : I -> finType).\n\n(*This lemma states that the total number of elements in a dependent product space, formed from a family of finite types, is equal to the product of the cardinalities of each type in the family.*)\nLemma card_fprod : #|fprod T_| = \\prod_(i : I) #|T_ i|.\n\n(*This definition provides a dependent function that, from a proof that a dependent product space is inhabited, returns an element from each of its component types.*)\nDefinition fprod_pick : 0 < #|fprod T_| -> forall i : I, T_ i.\n\n(*This definition specifies a function that, given a finite function mapping indices to corresponding tagged values from a family of types, extracts the untagged value associated with a specific index.*)\nDefinition ftagged (T_gt0 : 0 < #|fprod T_|)\n (f : {ffun I -> {i : I & T_ i}}) (i : I) :=\n @untag I T_ (T_ i) (fprod_pick T_gt0 i) i id (f i).\n\n(*This lemma shows that applying the `ftagged` function to a dependent function, once converted to a finite function representation, retrieves the original value of the dependent function at any given index.*)\nLemma ftaggedE t T_gt0 i : ftagged T_gt0 (fprod_fun t) i = t i.\n\nEnd FProd.\n\nSection BigTag.\nVariables (R : Type) (idx : R) (op : Monoid.com_law idx).\nVariables (I : finType) (T_ : I -> finType).\n\n(*This lemma allows changing the domain of a big operator. It states that an operation iterating over a subset of a type is equivalent to an operation iterating over a corresponding 'tagged' version of that type, provided the predicate and the function body are adjusted accordingly.*)\nLemma big_tag_cond (Q_ : forall i, {pred T_ i})\n (P_ : forall i : I, T_ i -> R) (i : I) :\n \\big[op/idx]_(j in Q_ i) P_ i j =\n \\big[op/idx]_(j in tagged_with T_ i | untag true (Q_ i) j)\n untag idx (P_ i) j.\n\n(*This lemma allows changing the domain of a big operator. It states that an operation iterating over a whole type is equivalent to an operation iterating over a corresponding 'tagged' version of that type, provided the function body is adjusted accordingly.*)\nLemma big_tag (P_ : forall i : I, T_ i -> R) (i : I) :\n \\big[op/idx]_(j : T_ i) P_ i j =\n \\big[op/idx]_(j in tagged_with T_ i) untag idx (P_ i) j.\n\nEnd BigTag.\n\nArguments big_tag_cond [R idx op I T_] _ _ _.\nArguments big_tag [R idx op I T_] _ _.\n\nSection BigFProd.\n Variables (R : Type) (zero one : R) (times : R -> R -> R).\n Variables (plus : Monoid.add_law zero times).\n Variables (I : finType) (T_ : I -> finType).\n Variables (P_ : forall i : I, {ffun T_ i -> R}).\n(*This definition introduces a local alias for the type of dependent functions over a family of finite types, also known as the dependent product type.*)\n Let T := fprod T_.\n\n(*This lemma provides a Fubini-like identity for computing a sum-of-products, which is restricted by a predicate, over a dependent product space.*)\n Lemma big_fprod_dep (Q : {pred {ffun I -> {i : I & (T_ i)}}}) :\n \\big[plus/zero]_(t : T | Q (fprod_fun t)) \\big[times/one]_(i : I) P_ i (t i) =\n \\big[plus/zero]_(g in family (tagged_with T_) | Q g)\n \\big[times/one]_(i : I) (untag zero (P_ i) (g i)).\n \n\n(*This lemma provides an identity for swapping a summation over a dependent product space with a product over its index type. It asserts that the sum of products is equal to the product of sums, effectively a form of Fubini's theorem for dependent types.*)\n Lemma big_fprod :\n \\big[plus/zero]_(t : T) \\big[times/one]_(i in I) P_ i (t i) =\n \\big[plus/zero]_(g in family (tagged_with T_))\n \\big[times/one]_(i : I) (untag zero (P_ i) (g i)).", - "boot.all_boot": "Require Export ssreflect.\nRequire Export ssrbool.\nRequire Export ssrfun.\nRequire Export eqtype.\nRequire Export ssrnat.\nRequire Export seq.\nRequire Export choice.\nRequire Export monoid.\nRequire Export nmodule.\nRequire Export path.\nRequire Export div.\nRequire Export fintype.\nRequire Export fingraph.\nRequire Export tuple.\nRequire Export finfun.\nRequire Export bigop.\nRequire Export prime.\nRequire Export finset.\nRequire Export binomial.\nRequire Export generic_quotient.", - "boot.eqtype": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope eq_scope.\nDeclare Scope fun_delta_scope.\n\n(*This definition specifies the property of a binary relation that it reflects propositional equality. A relation has this property if, for any two elements, the boolean result of applying the relation to them is true if and only if the elements are propositionally equal.*)\nDefinition eq_axiom T (e : rel T) := forall x y, reflect (x = y) (e x y).\n\n(*This record defines a mixin for types that have a decidable equality. It bundles a type with a boolean-valued binary relation and a proof that this relation accurately reflects the propositional equality of the type.*)\nHB.mixin Record hasDecEq T := { eq_op : rel T; eqP : eq_axiom eq_op }.\n\n#[mathcomp(axiom=\"eq_axiom\"), short(type=\"eqType\")]\n(*This structure defines the interface for types equipped with a decidable equality relation, encapsulating the underlying type and its decidable equality properties.*)\nHB.structure Definition Equality := { T of hasDecEq T }.\n\n(*This lemma states that the boolean equality test on a type is defined by the specific equality relation provided by its decidable equality structure.*)\nLemma eqE (T : eqType) x : eq_op x = hasDecEq.eq_op (Equality.class T) x.\n\nArguments eqP {T x y} : rename.\n\nDelimit Scope eq_scope with EQ.\nOpen Scope eq_scope.\n\n(*This notation provides a syntax for the boolean-valued comparison of two elements for equality.*)\nNotation \"x == y\" := (eq_op x y) (no associativity) : bool_scope.\n(*This notation provides a syntax for the boolean-valued comparison of two elements for equality, with an explicit annotation specifying their common type.*)\nNotation \"x == y :> T\" := ((x : T) == (y : T)) : bool_scope.\n(*This notation provides a syntax for the boolean-valued comparison of two elements for inequality, which evaluates to true if the elements are not equal.*)\nNotation \"x != y\" := (~~ (x == y)) (no associativity) : bool_scope.\n(*This notation provides a syntax for the boolean-valued comparison of two elements for inequality, with an explicit annotation specifying their common type.*)\nNotation \"x != y :> T\" := (~~ (x == y :> T)) : bool_scope.\n(*This notation provides a syntax to access the reflection property that connects the boolean equality test between two elements to their propositional equality.*)\nNotation \"x =P y\" := (eqP : reflect (x = y) (x == y))\n (at level 70, no associativity) : eq_scope.\n(*This notation provides a syntax to access the reflection property that connects the boolean equality test between two elements of an explicitly specified type to their propositional equality.*)\nNotation \"x =P y :> T\" := (eqP : reflect (x = y :> T) (x == y :> T))\n (no associativity) : eq_scope.\n\n(*This notation provides a pattern to specifically match the left-hand side of a boolean equality comparison, for use in term rewriting.*)\nNotation eqbLHS := (X in (X == _))%pattern.\n(*This notation provides a pattern to specifically match the right-hand side of a boolean equality comparison, for use in term rewriting.*)\nNotation eqbRHS := (X in (_ == X))%pattern.\n\n(*This lemma states that any element is equal to itself, according to the boolean equality test.*)\nLemma eq_refl (T : eqType) (x : T) : x == x. \n(*This notation provides a short alias for the lemma stating the reflexivity of boolean equality.*)\nNotation eqxx := eq_refl.\n\n(*This lemma states that the boolean result of comparing two elements for equality is the same regardless of their order.*)\nLemma eq_sym (T : eqType) (x y : T) : (x == y) = (y == x).\n\n#[global] Hint Resolve eq_refl eq_sym : core.\n\n(*This variant type represents the fact that for any two elements, exactly one of two cases holds: either they are propositionally equal, or they are propositionally not equal. The specific case is determined by the boolean outcomes of their equality tests.*)\nVariant eq_xor_neq (T : eqType) (x y : T) : bool -> bool -> Set :=\n(**)\n | EqNotNeq of x = y : eq_xor_neq x y true true\n(**)\n | NeqNotEq of x != y : eq_xor_neq x y false false.\n\n(*This lemma provides a proof that for any two elements on a type with decidable equality, they are either propositionally equal or propositionally not equal, and this corresponds to the result of their boolean equality test.*)\nLemma eqVneq (T : eqType) (x y : T) : eq_xor_neq x y (y == x) (x == y).\n\nArguments eqVneq {T} x y, {T x y}.\n\nSection Contrapositives.\n\nVariables (T1 T2 : eqType).\nImplicit Types (A : pred T1) (b : bool) (P : Prop) (x : T1) (z : T2).\n\n(*This lemma states that if the inequality of two elements implies that a given boolean value is false, then the fact that this boolean is true implies that the two elements must be equal.*)\nLemma contraTeq b x y : (x != y -> ~~ b) -> b -> x = y.\n\n(*This lemma states that if the inequality of two elements implies a certain boolean value, then the fact that this boolean is false implies that the two elements must be equal.*)\nLemma contraNeq b x y : (x != y -> b) -> ~~ b -> x = y.\n\n(*This lemma states that if the inequality of two elements implies a certain boolean condition, then the confirmation that this boolean is false implies that the two elements must be equal.*)\nLemma contraFeq b x y : (x != y -> b) -> b = false -> x = y.\n\n(*This lemma states that if the inequality of two elements implies the negation of a given proposition, then the truth of that proposition implies that the two elements must be equal.*)\nLemma contraPeq P x y : (x != y -> ~ P) -> P -> x = y.\n\n(*This lemma states that if the inequality of two elements implies a given proposition, then the falsity of that proposition implies that the two elements must be equal.*)\nLemma contra_not_eq P x y : (x != y -> P) -> ~ P -> x = y.\n\n(*This lemma states that if the equality of two elements implies a given proposition, then the falsity of that proposition implies that the two elements must be not equal.*)\nLemma contra_not_neq P x y : (x = y -> P) -> ~ P -> x != y.\n\n(*This lemma states that if the equality of two elements implies that a given boolean value is false, then the fact that this boolean is true implies that the two elements must be not equal.*)\nLemma contraTneq b x y : (x = y -> ~~ b) -> b -> x != y.\n\n(*This lemma states that if the equality of two elements implies a certain boolean value, then the fact that this boolean is false implies that the two elements must be not equal.*)\nLemma contraNneq b x y : (x = y -> b) -> ~~ b -> x != y.\n\n(*This lemma states that if the equality of two elements implies a certain boolean value, then the confirmation that this boolean is false implies that the two elements must be not equal.*)\nLemma contraFneq b x y : (x = y -> b) -> b = false -> x != y.\n\n(*This lemma states that if the equality of two elements implies the negation of a given proposition, then the truth of that proposition implies that the two elements must be not equal.*)\nLemma contraPneq P x y : (x = y -> ~ P) -> P -> x != y.\n\n(*This lemma states that if a given boolean value implies the inequality of two elements, then the equality of those elements implies that the given boolean value must be false.*)\nLemma contra_eqN b x y : (b -> x != y) -> x = y -> ~~ b.\n\n(*This lemma states that if a boolean condition implies that two elements are not equal, then the equality of those elements implies that the boolean condition must be false.*)\nLemma contra_eqF b x y : (b -> x != y) -> x = y -> b = false.\n\n(*This lemma states that if the falsity of a given boolean value implies the inequality of two elements, then the equality of those elements implies that the given boolean value must be true.*)\nLemma contra_eqT b x y : (~~ b -> x != y) -> x = y -> b.\n\n(*This lemma states that if a proposition implies that two values are equal, then the fact that these values are not equal implies the double negation of the proposition.*)\nLemma contra_neqN b x y : (b -> x = y) -> x != y -> ~~ b.\n\n(*This lemma states that if a boolean condition implies that two values are equal, then the fact that these values are not equal implies that the boolean condition is false.*)\nLemma contra_neqF b x y : (b -> x = y) -> x != y -> b = false.\n\n(*This lemma states that if the double negation of a proposition implies that two values are equal, then the fact that these values are not equal implies that the proposition itself is true.*)\nLemma contra_neqT b x y : (~~ b -> x = y) -> x != y -> b.\n\n(*This lemma states that if a proposition implies that two values are not equal, then the fact that these values are equal implies the negation of the proposition.*)\nLemma contra_eq_not P x y : (P -> x != y) -> x = y -> ~ P.\n\n(*This lemma states that if a proposition implies that two values are equal, then the fact that these values are not equal implies the negation of the proposition.*)\nLemma contra_neq_not P x y : (P -> x = y) -> x != y -> ~ P.\n\n(*This lemma states that if the inequality of a first pair of values implies the inequality of a second pair of values, then the equality of the second pair implies the equality of the first pair.*)\nLemma contra_eq z1 z2 x1 x2 : (x1 != x2 -> z1 != z2) -> z1 = z2 -> x1 = x2.\n\n(*This lemma states that if the equality of a first pair of values implies the equality of a second pair of values, then the inequality of the second pair implies the inequality of the first pair.*)\nLemma contra_neq z1 z2 x1 x2 : (x1 = x2 -> z1 = z2) -> z1 != z2 -> x1 != x2.\n\n(*This lemma states that if the inequality of a first pair of values implies the equality of a second pair of values, then the inequality of the second pair implies the equality of the first pair.*)\nLemma contra_neq_eq z1 z2 x1 x2 : (x1 != x2 -> z1 = z2) -> z1 != z2 -> x1 = x2.\n\n(*This lemma states that if the equality of a first pair of values implies the inequality of a second pair of values, then the equality of the second pair implies the inequality of the first pair.*)\nLemma contra_eq_neq z1 z2 x1 x2 : (z1 = z2 -> x1 != x2) -> x1 = x2 -> z1 != z2.\n\n(*This lemma asserts that a value is not a member of a given collection if and only if every element in the collection is not equal to that value.*)\nLemma memPn A x : reflect {in A, forall y, y != x} (x \\notin A).\n\n(*This lemma asserts that a value is not a member of a given collection if and only if that value is not equal to any element in the collection.*)\nLemma memPnC A x : reflect {in A, forall y, x != y} (x \\notin A).\n\n(*This lemma states that if two values are not equal, then a conditional expression testing for their equality evaluates to its 'else' branch value.*)\nLemma ifN_eq R x y vT vF : x != y -> (if x == y then vT else vF) = vF :> R.\n\n(*This lemma states that if two values are not equal, then a conditional expression testing for their equality with the operands swapped evaluates to its 'else' branch value.*)\nLemma ifN_eqC R x y vT vF : x != y -> (if y == x then vT else vF) = vF :> R.\n\nEnd Contrapositives.\n\nArguments memPn {T1 A x}.\nArguments memPnC {T1 A x}.\n\n(*This theorem asserts that for any two values of a type with decidable equality, any two proofs of their equality are themselves equal.*)\nTheorem eq_irrelevance (T : eqType) x y : forall e1 e2 : x = y :> T, e1 = e2.\n\n(*This corollary states that for any value on a type with decidable equality, any proof that the value is equal to itself is equal to the canonical proof of reflexivity.*)\nCorollary eq_axiomK (T : eqType) (x : T) : all_equal_to (erefl x).\n\nModule Type EqTypePredSig.\nParameter sort : eqType -> predArgType.\nEnd EqTypePredSig.\nModule MakeEqTypePred (eqmod : EqTypePredSig).\nCoercion eqmod.sort : eqType >-> predArgType.\nEnd MakeEqTypePred.\nModule Export EqTypePred := MakeEqTypePred eqtype.Equality.\n\n(*This lemma asserts that the constant function returning true for any two inputs of the unique unit type serves as a valid equality-testing axiom for that type.*)\nLemma unit_eqP : Equality.axiom (fun _ _ : unit => true).\n\nHB.instance Definition _ := hasDecEq.Build unit unit_eqP.\n\n(*This definition introduces the boolean equality function, which returns true if two input booleans are the same and false otherwise.*)\nDefinition eqb b := addb (~~ b).\n\n(*This lemma states that the boolean equality function satisfies the axiom of equality, meaning it returns true if and only if its two boolean arguments are equal.*)\nLemma eqbP : Equality.axiom eqb.\n\nHB.instance Definition _ := hasDecEq.Build bool eqbP.\n\n(*This lemma states that the boolean equality function is equivalent to the generic equality operator when applied to booleans.*)\nLemma eqbE : eqb = eq_op. \n\n(*This lemma states that for any given boolean value, any two proofs that this boolean is true are themselves equal.*)\nLemma bool_irrelevance (b : bool) (p1 p2 : b) : p1 = p2.\n\n(*This lemma states that the negation of the exclusive OR of two booleans is equivalent to testing them for equality.*)\nLemma negb_add b1 b2 : ~~ (b1 (+) b2) = (b1 == b2).\n\n(*This lemma states that two booleans are not equal if and only if their exclusive OR is true.*)\nLemma negb_eqb b1 b2 : (b1 != b2) = b1 (+) b2.\n\n(*This lemma states that comparing a boolean value for equality with true yields the boolean value itself.*)\nLemma eqb_id b : (b == true) = b.\n\n(*This lemma states that comparing a boolean value for equality with false is equivalent to negating that boolean value.*)\nLemma eqbF_neg b : (b == false) = ~~ b.\n\n(*This lemma states that the negation of a first boolean being equal to a second boolean is equivalent to the first boolean being equal to the negation of the second boolean.*)\nLemma eqb_negLR b1 b2 : (~~ b1 == b2) = (b1 == ~~ b2).\n\n(*This notation defines a predicate that checks if its argument is equal to a single, specific value.*)\nNotation xpred1 := (fun a1 x => x == a1).\n(*This notation defines a predicate that checks if its argument is equal to either of two specific values.*)\nNotation xpred2 := (fun a1 a2 x => (x == a1) || (x == a2)).\n(*This notation defines a predicate that checks if its argument is equal to one of three specific values.*)\nNotation xpred3 := (fun a1 a2 a3 x => [|| x == a1, x == a2 | x == a3]).\n(*This notation defines a predicate that checks if its argument is equal to one of four specific values.*)\nNotation xpred4 :=\n (fun a1 a2 a3 a4 x => [|| x == a1, x == a2, x == a3 | x == a4]).\n(*This notation defines a new predicate by taking an existing predicate and extending it to also be true for an additional specific value.*)\nNotation xpredU1 := (fun a1 (p : pred _) x => (x == a1) || p x).\n(*This notation defines a function that, given an element, returns a predicate testing whether another element is not equal to the first one.*)\nNotation xpredC1 := (fun a1 x => x != a1).\n(*This notation defines a function that combines a given predicate with an inequality check. It takes a predicate and an element, and produces a new predicate that is true for any input that is not equal to the given element and also satisfies the original predicate.*)\nNotation xpredD1 := (fun (p : pred _) a1 x => (x != a1) && p x).\n\nSection EqPred.\n\nVariable T : eqType.\n\n(*This definition creates a predicate that is true for any element that is equal to a given element.*)\nDefinition pred1 (a1 : T) := SimplPred (xpred1 a1).\n(*This definition creates a predicate that is true for any element that is equal to either of two given elements.*)\nDefinition pred2 (a1 a2 : T) := SimplPred (xpred2 a1 a2).\n(*This definition creates a predicate that is true for any element that is equal to any of three given elements.*)\nDefinition pred3 (a1 a2 a3 : T) := SimplPred (xpred3 a1 a2 a3).\n(*This definition creates a predicate that is true for any element that is equal to any of four given elements.*)\nDefinition pred4 (a1 a2 a3 a4 : T) := SimplPred (xpred4 a1 a2 a3 a4).\n(*This definition creates a new predicate from an existing predicate and a given element. The new predicate is true for any element that either is equal to the given element or satisfies the original predicate.*)\nDefinition predU1 (a1 : T) p := SimplPred (xpredU1 a1 p).\n(*This definition creates a predicate that is true for any element that is not equal to a given element.*)\nDefinition predC1 (a1 : T) := SimplPred (xpredC1 a1).\n(*This definition creates a new predicate from an existing predicate and a given element. The new predicate is true for any element that both is not equal to the given element and satisfies the original predicate.*)\nDefinition predD1 p (a1 : T) := SimplPred (xpredD1 p a1).\n\n(*This lemma states that the predicate constructor for a single element is extensionally equivalent to the boolean equality relation. That is, the predicate checking for equality with a given value behaves the same as the curried equality relation.*)\nLemma pred1E : pred1 =2 eq_op. \n\nVariables (T2 : eqType) (x y : T) (z u : T2) (b : bool).\n\n(*This lemma states that the boolean expression composed of a decidable equality check between two elements disjoined with another boolean value correctly reflects the logical disjunction of the corresponding properties.*)\nLemma predU1P : reflect (x = y \\/ b) ((x == y) || b).\n\n(*This lemma states that the boolean disjunction of two separate decidable equality checks correctly reflects the logical disjunction of the corresponding equality propositions.*)\nLemma pred2P : reflect (x = y \\/ z = u) ((x == y) || (z == u)).\n\n(*This lemma states that the boolean expression composed of a decidable inequality check between two elements conjoined with another boolean value correctly reflects the logical conjunction of the corresponding properties.*)\nLemma predD1P : reflect (x <> y /\\ b) ((x != y) && b).\n\n(*This lemma states that if two elements are propositionally equal, then the boolean disjunction of their decidable equality check with any other boolean value evaluates to true.*)\nLemma predU1l : x = y -> (x == y) || b.\n\n(*This lemma states that if a given boolean value is true, then its boolean disjunction with any decidable equality check also evaluates to true.*)\nLemma predU1r : b -> (x == y) || b.\n\nEnd EqPred.\n\nArguments predU1P {T x y b}.\nArguments pred2P {T T2 x y z u}.\nArguments predD1P {T x y b}.\nPrenex Implicits pred1 pred2 pred3 pred4 predU1 predC1 predD1.\n\n(*This notation provides a syntax for creating a predicate that is true for any element that is either equal to a specified element or satisfies a given predicate.*)\nNotation \"[ 'predU1' x & A ]\" := (predU1 x [in A])\n (format \"[ 'predU1' x & A ]\") : function_scope.\n(*This notation provides a syntax for creating a predicate that is true for any element that both satisfies a given predicate and is not equal to a specified element.*)\nNotation \"[ 'predD1' A & x ]\" := (predD1 [in A] x)\n (format \"[ 'predD1' A & x ]\") : function_scope.\n\nSection EqFun.\n\nSection Exo.\n\nVariables (aT rT : eqType) (D : pred aT) (f : aT -> rT) (g : rT -> aT).\n\n(*This lemma states that for any injective function between types with decidable equality, the boolean equality of the images of two elements is equivalent to the boolean equality of the elements themselves.*)\nLemma inj_eq : injective f -> forall x y, (f x == f y) = (x == y).\n\n(*This lemma states that if a function has a left inverse, then the boolean equality of the images of two elements under that function is equivalent to the boolean equality of the elements themselves.*)\nLemma can_eq : cancel f g -> forall x y, (f x == f y) = (x == y).\n\n(*This lemma states that for any bijective function between types with decidable equality, the boolean equality of the images of two elements is equivalent to the boolean equality of the elements themselves.*)\nLemma bij_eq : bijective f -> forall x y, (f x == f y) = (x == y).\n\n(*This lemma states that if two functions are inverses of each other, then checking if the image of an element under the first function equals a second element is equivalent to checking if the first element equals the image of the second element under the inverse function.*)\nLemma can2_eq : cancel f g -> cancel g f -> forall x y, (f x == y) = (x == g y).\n\n(*This lemma states that if a function is injective on a specific subset of its domain, then for any two elements within that subset, the boolean equality of their images is equivalent to the boolean equality of the elements themselves.*)\nLemma inj_in_eq :\n {in D &, injective f} -> {in D &, forall x y, (f x == f y) = (x == y)}.\n\n(*This lemma states that if a function has a left inverse on a specific subset of its domain, then for any two elements within that subset, the boolean equality of their images under that function is equivalent to the boolean equality of the elements themselves.*)\nLemma can_in_eq :\n {in D, cancel f g} -> {in D &, forall x y, (f x == f y) = (x == y)}.\n\nEnd Exo.\n\nSection Endo.\n\nVariable T : eqType.\n\n(*This definition constructs a binary relation from a given function, where the relation holds between two elements if and only if applying the function to the first element results in a value that is equal to the second element.*)\nDefinition frel f := [rel x y : T | f x == y].\n\n(*This lemma states that for an involutive function, which is its own inverse, checking if the image of a first element equals a second element is equivalent to checking if the first element equals the image of the second element.*)\nLemma inv_eq f : involutive f -> forall x y : T, (f x == y) = (x == f y).\n\n(*This lemma states that if two functions are extensionally equal, meaning they produce the same output for every input, then the binary relations generated from them are also extensionally equal.*)\nLemma eq_frel f f' : f =1 f' -> frel f =2 frel f'.\n\nEnd Endo.\n\nVariable aT : Type.\n\n(*This definition specifies a property called \"invariant,\" which holds for a binary relation and a function. The function is considered an invariant of the relation if any two elements that are related by the relation are mapped by the function to equal values.*)\nDefinition invariant (rT : eqType) f (k : aT -> rT) :=\n [pred x | k (f x) == k x].\n\nVariables (rT1 rT2 : eqType) (f : aT -> aT) (h : rT1 -> rT2) (k : aT -> rT1).\n\n(*This lemma states that if the application of a first function is invariant under a transformation of its input, then the composition of a second function with the first function is also invariant under the same transformation.*)\nLemma invariant_comp : subpred (invariant f k) (invariant f (h \\o k)).\n\n(*This lemma states that if a function is injective, then the invariance property of its composition with a second function is equivalent to the invariance property of the second function alone.*)\nLemma invariant_inj : injective h -> invariant f (h \\o k) =1 invariant f k.\n\nEnd EqFun.\n\nPrenex Implicits frel.\n\nNotation coerced_frel f := (rel_of_simpl (frel f)) (only parsing).\n\nSection FunWith.\n\nVariables (aT : eqType) (rT : Type).\n\n(*This definition creates a total function from a partial function and a default value. The resulting function evaluates the partial function at a given input; if the partial function yields a value, that value is returned, otherwise the default value is returned.*)\nVariant fun_delta : Type := FunDelta of aT & rT.\n\n(*This definition constructs a new function from an existing one by specifying a single point-wise update. The resulting function maps a given input to a new specified output, while behaving identically to the original function for all other inputs.*)\nDefinition fwith x y (f : aT -> rT) := [fun z => if z == x then y else f z].\n\n(*This definition applies a functional change, represented by an input-output pair, to a given function. The result is a function that incorporates this new mapping while retaining the behavior of the original function everywhere else.*)\nDefinition app_fdelta df f z :=\n let: FunDelta x y := df in if z == x then y else f z.\n\nEnd FunWith.\n\nPrenex Implicits fwith.\n\n(*This notation creates a representation of a single-point functional update, consisting of an input value and its corresponding new output value.*)\nNotation \"x |-> y\" := (FunDelta x y)\n (at level 190, no associativity,\n format \"'[hv' x '/ ' |-> y ']'\") : fun_delta_scope.\n\nDelimit Scope fun_delta_scope with FUN_DELTA.\nArguments app_fdelta {aT rT%_type} df%_FUN_DELTA f z.\n\n(*This notation provides a syntax for defining a typed function by specifying a base function body and then applying a series of one or more point-wise updates.*)\nNotation \"[ 'fun' z : T => F 'with' d1 , .. , dn ]\" :=\n (SimplFunDelta (fun z : T =>\n app_fdelta d1%FUN_DELTA .. (app_fdelta dn%FUN_DELTA (fun _ => F)) ..))\n (z name, only parsing) : function_scope.\n\n(*This notation provides a syntax for defining a function whose argument type is inferred, by specifying a base function body and then applying a series of one or more point-wise updates.*)\nNotation \"[ 'fun' z => F 'with' d1 , .. , dn ]\" :=\n (SimplFunDelta (fun z =>\n app_fdelta d1%FUN_DELTA .. (app_fdelta dn%FUN_DELTA (fun _ => F)) ..))\n (z name, format\n \"'[hv' [ '[' 'fun' z => '/ ' F ']' '/' 'with' '[' d1 , '/' .. , '/' dn ']' ] ']'\"\n ) : function_scope.\n\n(*This notation provides a syntax for creating a new function by applying a series of one or more point-wise updates to an existing function.*)\nNotation \"[ 'eta' f 'with' d1 , .. , dn ]\" :=\n (SimplFunDelta (fun _ =>\n app_fdelta d1%FUN_DELTA .. (app_fdelta dn%FUN_DELTA f) ..))\n (format\n \"'[hv' [ '[' 'eta' '/ ' f ']' '/' 'with' '[' d1 , '/' .. , '/' dn ']' ] ']'\"\n ) : function_scope.\n\nSection DFunWith.\nVariables (I : eqType) (T : I -> Type) (f : forall i, T i).\n\n(*This definition constructs a new dependent function from an existing one by updating its value at a single specified index. The new function returns the updated value at that index and the original function's values at all other indices.*)\nDefinition dfwith i (x : T i) (j : I) : T j :=\n if (i =P j) is ReflectT ij then ecast j (T j) ij x else f j.\n\n(*This lemma asserts that evaluating a dependent function that has been updated at a specific index will return the new value when queried at that same index.*)\nLemma dfwith_in i x : dfwith x i = x.\n\n(*This lemma asserts that evaluating a dependent function that has been updated at a specific index will return the original function's value when queried at any other index.*)\nLemma dfwith_out i (x : T i) j : i != j -> dfwith x j = f j.\n\n(*This inductive type defines the specification for a dependent function update. It consists of two cases: one asserting that evaluation at the update index yields the new value, and another asserting that evaluation at any other index yields the original function's value.*)\nVariant dfwith_spec i (x : T i) : forall j, T j -> Type:=\n(**)\n | DFunWithIn : dfwith_spec x x\n(**)\n | DFunWithOut j : i != j -> dfwith_spec x (f j).\n\n(*This lemma proves that the dependent function update operation conforms to its specification, correctly returning either the new value or the original value based on the evaluation index.*)\nLemma dfwithP i (x : T i) (j : I) : dfwith_spec x (dfwith x j).\n\nEnd DFunWith.\nArguments dfwith {I T} f [i] x.\n\nSection ComparableType.\n\nVariable T : Type.\n\n(*This definition specifies the property of a type for which equality is decidable, meaning there is a computable procedure to determine whether any two elements are equal.*)\nDefinition comparable := forall x y : T, decidable (x = y).\n\nHypothesis compare_T : comparable.\n\n(*This definition creates a boolean-valued function that returns true if two elements of a type with decidable equality are equal, and false otherwise.*)\nDefinition compareb x y : bool := compare_T x y.\n\n(*This lemma establishes the correctness of the boolean equality comparison function, stating that it returns true if and only if its two arguments are propositionally equal.*)\nLemma compareP : Equality.axiom compareb.\n\n(*This definition constructs a structure that formally endows a type with decidable equality by bundling it with the proof of correctness for its boolean comparison function.*)\nDefinition comparableMixin := hasDecEq.Build T compareP.\n\nEnd ComparableType.\n\n(*This definition shows how to construct a proof of decidable equality for any type that already possesses a boolean equality operator, thereby demonstrating that such types are comparable.*)\nDefinition eq_comparable (T : eqType) : comparable T :=\n fun x y => decP (x =P y).\n\n#[key=\"sub_sort\"]\n(*This mixin record specifies the structural requirements for a type to be considered a subtype of another type defined by a predicate. It formally captures the relationship between the subset and the superset.*)\nHB.mixin Record isSub (T : Type) (P : pred T) (sub_sort : Type) := {\n val_subdef : sub_sort -> T;\n Sub : forall x, P x -> sub_sort;\n Sub_rect : forall K (_ : forall x Px, K (@Sub x Px)) u, K u;\n SubK_subproof : forall x Px, val_subdef (@Sub x Px) = x\n}.\n\n#[short(type=\"subType\")]\n(*This structure defines a subtype of a given type as the collection of elements that satisfy a specific predicate, packaging the subtype's carrier with its structural properties.*)\nHB.structure Definition SubType (T : Type) (P : pred T) := { S of isSub T P S }.\n\n(*This notation refers to the embedding function that retrieves the value of a subtype element within its parent type.*)\nNotation val := (isSub.val_subdef (SubType.on _)).\nNotation \"\\val\" := (isSub.val_subdef (SubType.on _)) (only parsing).\n(*This notation provides an alternative syntax for the embedding function that maps an element of a subtype to its corresponding value in the parent type.*)\nNotation \"\\val\" := (isSub.val_subdef _) (only printing).\n\n#[short(type=\"subEqType\")]\n(*This structure defines a subtype that is also equipped with decidable equality, combining the properties of a subtype with those of a type with a computable equality test.*)\nHB.structure Definition SubEquality T (P : pred T) :=\n { sT of Equality sT & isSub T P sT}.\n\nSection SubType.\n\nVariables (T : Type) (P : pred T).\n\n(*This lemma states that any element is equal to itself, a property that holds even when conditioned on an arbitrary predicate.*)\nLemma vrefl : forall x, P x -> x = x. \n(*This definition provides an alias for the reflexivity of equality lemma, named to serve as a recursor in specific proof contexts.*)\nDefinition vrefl_rect := vrefl.\n\nSection Theory.\n\nVariable sT : subType P.\n\n(*This definition describes the projection function that extracts the underlying value from an element of a subtype, mapping it back to its original, larger type.*)\nLocal Notation val := (isSub.val_subdef (SubType.on sT)).\n(*This constructor builds an element of a subtype from an element of a larger type, provided with a proof that the element satisfies the subtype's defining predicate.*)\nLocal Notation Sub := (@Sub _ _ sT).\n\n(*This lemma states that applying the subtype constructor to an element and then immediately projecting it back with the value function returns the original element.*)\nLemma SubK x Px : val (@Sub x Px) = x. \n\n(*This lemma states that for any element of a subtype, the corresponding value in the underlying base type satisfies the characteristic predicate of that subtype.*)\nVariant Sub_spec : sT -> Type := subSpec x Px : Sub_spec (Sub x Px).\n\n(*This lemma states that any element of a subtype can be deconstructed into its underlying value in the larger type and a proof that this value satisfies the subtype's defining predicate.*)\nLemma SubP u : Sub_spec u.\n\n(*This definition provides a function that attempts to lift an element from a larger type into a subtype. It returns an optional value, which is the subtype element if the given element satisfies the defining predicate, and none otherwise.*)\nDefinition insub x := if idP is ReflectT Px then Some (Sub x Px) else None.\n\n(*This definition provides a function that lifts an element from a larger type into a subtype, returning a provided default subtype element if the given element does not satisfy the defining predicate.*)\nDefinition insubd u0 x := odflt u0 (insub x).\n\n(*This inductive type specifies the behavior of the lifting function. It has two cases: one for when the lifting succeeds, providing the resulting subtype element and a proof of correctness, and another for when it fails, providing a proof that the defining predicate does not hold.*)\nVariant insub_spec x : option sT -> Type :=\n(**)\n | InsubSome u of P x & val u = x : insub_spec x (Some u)\n(*This lemma states that if an element of a base type does not satisfy the predicate defining a subtype, then the partial injection of that element into the subtype evaluates to the 'None' optional value.*)\n | InsubNone of ~~ P x : insub_spec x None.\n\n(*This lemma asserts that the lifting function 'insub' conforms to its specification 'insub_spec', meaning its output for any given element correctly reflects whether that element satisfies the subtype predicate.*)\nLemma insubP x : insub_spec x (insub x).\n\n(*This lemma states that if an element is known to satisfy the subtype's predicate, the lifting function 'insub' will successfully convert it into an optional value containing the corresponding subtype element.*)\nLemma insubT x Px : insub x = Some (Sub x Px).\n\n(*This lemma states that if the subtype's defining predicate evaluates to false for a given element, the lifting function 'insub' will return none for that element.*)\nLemma insubF x : P x = false -> insub x = None.\n\n(*This lemma states that if the subtype's defining predicate does not hold for a given element, the lifting function 'insub' will return none.*)\nLemma insubN x : ~~ P x -> insub x = None.\n\n(*This lemma states that the boolean predicate checking if the lifting function 'insub' returns a successful result for an element is equivalent to the subtype's own defining predicate.*)\nLemma isSome_insub : ([eta insub] : pred T) =1 P.\n\n(*This lemma states a cancellation property: projecting a subtype element to its underlying value and then immediately lifting it back with 'insub' yields an optional value containing the original subtype element.*)\nLemma insubK : ocancel insub val.\n\n(*This lemma asserts that for any element of a subtype, its underlying value in the larger type is guaranteed to satisfy the subtype's defining predicate.*)\nLemma valP u : P (val u).\n\n(*This lemma states a cancellation property: if lifting an element into a subtype is successful, then projecting the resulting subtype element back to its underlying value returns the original element.*)\nLemma valK : pcancel val insub.\n\n(*This lemma asserts that the projection function from a subtype to its larger, underlying type is injective, meaning two different subtype elements must correspond to two different underlying values.*)\nLemma val_inj : injective val.\n\n(*This lemma states a conditional cancellation property for the defaulted lifting function. Applying the projection after the defaulted lifting function returns the original element, provided that the element satisfies the subtype predicate.*)\nLemma valKd u0 : cancel val (insubd u0).\n\n(*This lemma describes the result of composing the projection function with the defaulted lifting function. The composition returns the original element if it satisfies the subtype predicate; otherwise, it returns the underlying value of the default subtype element.*)\nLemma val_insubd u0 x : val (insubd u0 x) = if P x then x else val u0.\n\n(*This lemma states a cancellation property for the defaulted lifting function within the context of the subtype. For any element already in the subtype, projecting it to its underlying value and then lifting it back with the defaulted lifting function returns the original subtype element.*)\nLemma insubdK u0 : {in P, cancel (insubd u0) val}.\n\n(*This definition provides an auxiliary function used to build an alternative an implementation of the lifting function 'insub', constructing an optional subtype value based on an element, a boolean, and a proof that the subtype predicate on the element equals that boolean.*)\nLet insub_eq_aux x isPx : P x = isPx -> option sT :=\n if isPx as b return _ = b -> _ then fun Px => Some (Sub x Px) else fun=> None.\n(*This definition provides an alternative implementation of the 'insub' lifting function, defined in a way that is more directly based on logical proofs rather than conditional branching.*)\nDefinition insub_eq x := insub_eq_aux (erefl (P x)).\n\n(*This lemma states that the alternative, proof-based implementation of the lifting function, 'insub_eq', is functionally equivalent to the standard implementation, 'insub'.*)\nLemma insub_eqE : insub_eq =1 insub.\n\nEnd Theory.\n\nEnd SubType.\n\nArguments Sub {T P sT} x Px : rename.\nArguments vrefl {T P} x Px.\nArguments vrefl_rect {T P} x Px.\nArguments insub {T P sT} x.\nArguments insubd {T P sT} u0 x.\nArguments insubT [T] P [sT x].\nArguments val_inj {T P sT} [u1 u2] eq_u12 : rename.\nArguments valK {T P sT} u : rename.\nArguments valKd {T P sT} u0 u : rename.\nArguments insubK {T P} sT x.\nArguments insubdK {T P sT} u0 [x] Px.\n\n(*This notation defines a default recursion principle for a newly-declared subtype. It allows defining functions over the subtype by specifying how to handle its deconstructed components, namely the underlying value and the proof of predicate satisfaction.*)\nLocal Notation inlined_sub_rect :=\n (fun K K_S u => let (x, Px) as u return K u := u in K_S x Px).\n\n(*This notation defines a default recursion principle for a newly-declared type that is a simple wrapper around an existing type. It allows defining functions over the new type by specifying how to handle the underlying value from the original type.*)\nLocal Notation inlined_new_rect :=\n (fun K K_S u => let (x) as u return K u := u in K_S x).\n\nReserved Notation \"[ 'isSub' 'for' v ]\" (format \"[ 'isSub' 'for' v ]\").\n\nNotation \"[ 'isSub' 'for' v ]\" :=\n (@isSub.phant_Build _ _ _ v _ inlined_sub_rect vrefl_rect)\n (only parsing) : form_scope.\n\n(*This notation provides a command to declare that a type is a subtype of a specific, explicitly named supertype, using a given predicate to define membership. This is a parsing-only variant for when the supertype cannot be inferred.*)\nNotation \"[ 'isSub' 'of' T 'for' v ]\" :=\n (@isSub.phant_Build _ _ T v _ inlined_sub_rect vrefl_rect)\n (only parsing) : form_scope.\n\n(*This notation provides a command to declare that a type is a subtype defined by a given predicate, allowing the user to supply a custom recursion principle for the new subtype instead of the default one.*)\nNotation \"[ 'isSub' 'for' v 'by' rec ]\" :=\n (@isSub.phant_Build _ _ _ v _ rec vrefl)\n (format \"[ 'isSub' 'for' v 'by' rec ]\") : form_scope.\n\n(*This notation provides a command to declare that a type is a subtype defined by a given predicate. It sets up the necessary structure and proofs, using a default recursion principle, and is used for both parsing user declarations and for displaying subtype goals.*)\nNotation \"[ 'isSub' 'for' v ]\" := (@isSub.phant_Build _ _ _ v _ _ _)\n (only printing, format \"[ 'isSub' 'for' v ]\") : form_scope.\n\nReserved Notation \"[ 'isNew' 'for' v ]\" (format \"[ 'isNew' 'for' v ]\").\n\n(*This definition provides a builder for establishing that a new type is structurally equivalent to an existing type, by packaging it as a subtype where the defining predicate is always true. This is used to create type wrappers or clones that inherit structure.*)\nDefinition NewMixin T U v c Urec sk :=\n let Urec' P IH := Urec P (fun x : T => IH x isT : P _) in\n @isSub.phant_Build _ _ U v (fun x _ => c x) Urec' sk.\n\nNotation \"[ 'isNew' 'for' v ]\" :=\n (@NewMixin _ _ v _ inlined_new_rect vrefl_rect) (only parsing) : form_scope.\n\n(*This notation provides a command to declare that a type is a simple wrapper or clone of an existing type. It uses the underlying subtype machinery to establish an isomorphism, where the provided constructor 'v' maps from the base type to the new type.*)\nNotation \"[ 'isNew' 'for' v ]\" := (@NewMixin _ _ v _ _ _)\n (only printing, format \"[ 'isNew' 'for' v ]\") : form_scope.\n\n(*This notation provides a command to declare that a type is a simple wrapper or clone of a specific, explicitly named base type 'T'. The constructor 'v' maps elements from the base type to the new type.*)\nNotation \"[ 'isNew' 'of' T 'for' v ]\" :=\n (@NewMixin _ T v _ inlined_new_rect vrefl_rect) (only parsing) : form_scope.\n\n(*This definition constructs an element of a subtype by packaging a given element of the base type with a trivial proof of membership.*)\nDefinition innew T nT x := @Sub T predT nT x (erefl true).\nArguments innew {T nT}.\n\n(*This lemma states that projecting an element of a subtype created with `innew` back to the base type yields the original element.*)\nLemma innew_val T nT : cancel val (@innew T nT).\n\nHB.instance Definition _ T (P : pred T) := [isSub of sig P for sval].\n\n(*A notation for defining a subtype consisting of all elements that are members of a given set or satisfy a given predicate.*)\nNotation \"{ x 'in' A }\" := {x | x \\in A}\n (x at level 99, format \"{ x 'in' A }\") : type_scope.\n(*A notation for defining a subtype consisting of all elements that are members of a given set or satisfy a given predicate, and also satisfy an additional boolean condition.*)\nNotation \"{ x 'in' A | P }\" := {x | (x \\in A) && P}\n (x at level 99, format \"{ x 'in' A | P }\") : type_scope.\n\n(*A notation for the type of an optional value, which, if present, consists of an element of a given type packaged with a proof that it satisfies a specific boolean property.*)\nNotation \"{ ? x : T | P }\" := (option {x : T | is_true P})\n (x at level 99, only parsing) : type_scope.\n(*A notation for the type of an optional value, which, if present, consists of an element of an inferred type packaged with a proof that it satisfies a specific boolean property.*)\nNotation \"{ ? x | P }\" := {? x : _ | P}\n (x at level 99, format \"{ ? x | P }\") : type_scope.\n(*A notation for the type of an optional value, which, if present, consists of an element packaged with a proof of its membership in a given set or satisfaction of a given predicate.*)\nNotation \"{ ? x 'in' A }\" := {? x | x \\in A}\n (x at level 99, format \"{ ? x 'in' A }\") : type_scope.\n(*A notation for the type of an optional value, which, if present, consists of an element packaged with proofs of its membership in a given set and its satisfaction of an additional boolean property.*)\nNotation \"{ ? x 'in' A | P }\" := {? x | (x \\in A) && P}\n (x at level 99, format \"{ ? x 'in' A | P }\") : type_scope.\n\n(*This definition constructs an element of a dependent subtype by taking an element of a base type and a proof that it satisfies the subtype's predicate.*)\nDefinition insigd T (A : mem_pred T) x (Ax : in_mem x A) :=\n insubd (exist [eta A] x Ax).\n\nSection TransferType.\n\nVariables (T T' : Type) (f : T -> T').\n\n(*This definition provides a type alias for the domain of a given injective function, used as a mechanism to attach transported algebraic structures to that type.*)\nDefinition inj_type of injective f : Type := T.\n(*This definition provides a type alias for the codomain of an injective function that has a known left inverse. This alias is used to manage type identities when transferring algebraic structures.*)\nDefinition pcan_type g of pcancel f g : Type := T.\n(*This definition provides a type alias for the domain of an injective function that has a known right inverse. This alias helps in the construction of new algebraic structures on the domain type.*)\nDefinition can_type g of cancel f g : Type := T.\n\nEnd TransferType.\n\nSection TransferEqType.\n\nVariables (T : Type) (eT : eqType) (f : T -> eT).\n\n(*This lemma states that for any injective function mapping a type into a type with equality, a valid equality relation on the source type can be defined by checking for the equality of the function's outputs.*)\nLemma inj_eqAxiom : injective f -> Equality.axiom (fun x y => f x == f y).\n\nHB.instance Definition _ f_inj := hasDecEq.Build (inj_type f_inj)\n (inj_eqAxiom f_inj).\n\nHB.instance Definition _ g (fK : pcancel f g) := Equality.copy (pcan_type fK)\n (inj_type (pcan_inj fK)).\n\n(*This definition provides a deprecated method for constructing a decidable equality structure on a type by inheriting it from a target type through an injective function.*)\nDefinition deprecated_InjEqMixin f_inj := hasDecEq.Build T (inj_eqAxiom f_inj).\n(*This definition provides a deprecated method for constructing a decidable equality structure on a type by leveraging a function that possesses a left inverse, which guarantees its injectivity.*)\nDefinition deprecated_PcanEqMixin g (fK : pcancel f g) :=\n deprecated_InjEqMixin (pcan_inj fK).\n(*This definition provides a deprecated method for constructing a decidable equality structure on a type by leveraging a function that possesses a right inverse, which guarantees its injectivity.*)\nDefinition deprecated_CanEqMixin g (fK : cancel f g) :=\n deprecated_InjEqMixin (can_inj fK).\n\nEnd TransferEqType.\n\n(*This definition extracts the carrier type from a given subtype structure, effectively treating the subtype structure as the type it represents.*)\nDefinition sub_type T (P : pred T) (sT : subType P) : Type := sT.\nHB.instance Definition _ T (P : pred T) (sT : subType P) :=\n SubType.on (sub_type sT).\n\nSection SubEqType.\n\nVariables (T : eqType) (P : pred T) (sT : subType P).\n\n(*A local notation for an expression that asserts that a relation defined by comparing the outputs of a function applied to two inputs is a valid equality relation.*)\nLocal Notation ev_ax := (fun T v => @Equality.axiom T (fun x y => v x == v y)).\n(*This lemma states that equality between two elements of a subtype holds if and only if the equality holds for their corresponding values in the parent type.*)\nLemma val_eqP : ev_ax sT val. \n\n(*This lemma states that the boolean indicating whether two subtype elements are equal is the same as the boolean indicating whether their underlying values in the base type are equal.*)\nLemma val_eqE (T : eqType) (P : pred T) (sT : subEqType P)\n (u v : sT) : (val u == val v) = (u == v).\n\nArguments val_eqP {T P sT x y}.\n\n(*A notation to explicitly instantiate the equality structure for a type by copying it from that type's canonical subtype implementation.*)\nNotation \"[ 'Equality' 'of' T 'by' <: ]\" := (Equality.copy T%type (sub_type T%type))\n (format \"[ 'Equality' 'of' T 'by' <: ]\") : form_scope.\n\nHB.instance Definition _ := Equality.copy void (pcan_type (of_voidK unit)).\n(*This definition establishes the equality relation for pairs, where two pairs are equal if and only if their corresponding components are equal.*)\nDefinition pair_eq : rel (T1 * T2) := fun u v => (u.1 == v.1) && (u.2 == v.2).\n\n(*This lemma asserts that the component-wise equality relation for pairs satisfies the axioms of an equality relation.*)\nLemma pair_eqP : Equality.axiom pair_eq.\n\n(*This lemma states that the explicitly defined component-wise equality for pairs is equivalent to the canonical equality operation on the product type.*)\nLemma pair_eqE : pair_eq = eq_op :> rel _. \n\n(*This lemma provides a boolean equivalence stating that two pairs are equal if and only if their first components are equal and their second components are equal.*)\nLemma xpair_eqE (x1 y1 : T1) (x2 y2 : T2) :\n ((x1, x2) == (y1, y2)) = ((x1 == y1) && (x2 == y2)).\n\n(*This lemma states that the equality of two pairs implies the equality of their first components.*)\nLemma pair_eq1 (u v : T1 * T2) : u == v -> u.1 == v.1.\n\n(*This lemma states that the equality of two pairs implies the equality of their second components.*)\nLemma pair_eq2 (u v : T1 * T2) : u == v -> u.2 == v.2.\n\nEnd ProdEqType.\n\nArguments pair_eq {T1 T2} u v /.\nArguments pair_eqP {T1 T2}.\n\n(*This definition creates a predicate on a product type from two predicates on its component types. The new predicate is satisfied by a pair if each component satisfies its respective predicate.*)\nDefinition predX T1 T2 (p1 : pred T1) (p2 : pred T2) :=\n [pred z | p1 z.1 & p2 z.2].\n\n(*A notation for creating a predicate on a product type, which holds for a pair if its first component belongs to the first given set and its second component belongs to the second given set.*)\nNotation \"[ 'predX' A1 & A2 ]\" := (predX [in A1] [in A2])\n (format \"[ 'predX' A1 & A2 ]\") : function_scope.\n\nSection OptionEqType.\n\nVariable T : eqType.\n\n(*This definition specifies the boolean equality for optional values. Two optional values are equal if both are 'none', or if both are 'some' and their wrapped values are equal.*)\nDefinition opt_eq (u v : option T) : bool :=\n oapp (fun x => oapp (eq_op x) false v) (~~ v) u.\n\n(*This lemma states that the defined equality on option types is a valid decidable equality, meaning it is reflexive, symmetric, transitive, and respects substitutivity.*)\nLemma opt_eqP : Equality.axiom opt_eq.\n\n(*This definition specifies a function that, given two dependently typed values, returns the underlying value of the second input, typecast to match the type of the first input, if and only if their tags are equal; otherwise, it returns the underlying value of the first input.*)\nDefinition tagged_as u v :=\n if tag u =P tag v is ReflectT eq_uv then\n eq_rect_r T_ (tagged v) eq_uv\n else tagged u.\n\n(*This lemma states that when the `tagged_as` function is applied to a first dependently typed value and a second value created by tagging a raw value with the same type index, the result is the original raw value.*)\nLemma tagged_asE u x : tagged_as u (Tagged T_ x) = x.\n\nEnd TaggedAs.\n\nSection EqTagged.\n\nVariables (I : eqType) (T_ : I -> Type).\n(*A local notation that serves as an alias for a dependent pair type, where each value consists of an index from an equality type and an element from a type family indexed by that index.*)\nLocal Notation T := {i : I & T_ i}.\n\n(*This definition provides a safe way to extract the underlying value from a dependently typed pair by casting it to a specific type, given a proof that the pair's tag matches the index of the target type.*)\nDefinition etagged i u (p : tag u = i) := ecast i (T_ i) p (tagged u).\n\nImplicit Types (i j : I) (u v : T).\n\n(*This lemma states that the constructor for creating tagged values is injective; if two tagged values constructed from elements of the same underlying type are equal, then the original elements themselves must be equal.*)\nLemma eq_from_Tagged i (t s : T_ i) : Tagged T_ t = Tagged T_ s -> t = s.\n\n(*This lemma states that re-tagging a value immediately after extracting it from a dependent pair using the `etagged` function restores the original dependent pair.*)\nLemma etaggedK i u (p : tag u = i) : Tagged T_ (etagged p) = u.\n\n(*This definition creates a predicate that checks if a dependently typed value has a specific tag, effectively filtering for all values associated with a given index.*)\nDefinition tagged_with i : pred {i : I & T_ i} := [pred j | tag j == i].\n\n(*This definition specifies a function that takes a dependently typed value known to have a specific tag and safely extracts its underlying data, returning it as a value of the corresponding non-dependent type.*)\nDefinition untag_with i (x : {x in tagged_with i}) : T_ i :=\n etagged (eqP (valP x)).\n(*This definition specifies a function that takes a raw value of a specific type and wraps it into a dependently typed pair with the corresponding tag, asserting that the resulting pair belongs to the subset of values with that tag.*)\nDefinition tag_with i (t : T_ i) : {x in tagged_with i} :=\n exist _ (Tagged T_ t) (eq_refl i).\n\n(*This lemma states that the `untag_with` function is a left inverse to the `tag_with` function; applying `untag_with` after `tag_with` recovers the original value.*)\nLemma untag_withK i : cancel (@untag_with i) (@tag_with i).\n\n#[local] Hint Resolve untag_withK : core.\n\n(*This lemma states that the `tag_with` function is a left inverse to the `untag_with` function; applying `tag_with` after `untag_with` restores the original dependently typed value within its subtype.*)\nLemma tag_withK i : cancel (@tag_with i) (@untag_with i).\n\n#[local] Hint Resolve tag_withK : core.\n\n(*This lemma states that for any given index, the `tag_with` function is a bijection between the raw type and the subtype of dependent pairs with that index's tag.*)\nLemma tag_with_bij i : bijective (@tag_with i).\n\n(*This lemma states that for any given index, the `untag_with` function is a bijection between the subtype of dependent pairs with that index's tag and the raw type.*)\nLemma untag_with_bij i : bijective (@untag_with i).\n\n(*This definition provides a way to conditionally process a dependently typed value: if the value's tag matches a given index, a specified function is applied to its unwrapped content; otherwise, a default value is returned.*)\nDefinition untag (R : Type) (idx : R) (i : I) (F : T_ i -> R) u :=\n if tag u =P i is ReflectT e then F (etagged e) else idx.\n\n(*This lemma states that if a dependently typed value has a tag matching a given index, the `untag` operation simplifies to applying the provided function to the safely extracted underlying value.*)\nLemma untagE (R : Type) (idx : R) (i : I) (F : T_ i -> R) u (e : tag u = i):\n untag idx F u = F (etagged e).\n\n(*This lemma states that if a dependently typed value has a tag that does not match a given index, the `untag` operation returns the provided default value.*)\nLemma untag_dflt (R : Type) (idx : R) (i : I) (F : T_ i -> R) u : tag u != i ->\n untag idx F u = idx.\n\n(*This lemma states that if the function provided to the `untag` operation is a constant function that returns the default value, then the `untag` operation will always yield that same default value, regardless of the input.*)\nLemma untag_cst (R : Type) (idx : R) (i : I) u :\n untag idx (fun _ : T_ i => idx) u = idx.\n\nEnd EqTagged.\n\nArguments etagged {I T_ i u}.\nArguments untag {I T_ R} idx [i].\nArguments tagged_with {I}.\nArguments tag_with {I T_}.\nArguments untag_with {I T_}.\n\nSection TagEqType.\n\nVariables (I : eqType) (T_ : I -> eqType).\nImplicit Types u v : {i : I & T_ i}.\n\n(*This definition specifies decidable equality for dependently typed pairs. Two such pairs are considered equal if their tags are equal and their underlying values are equal, where the equality check on values is performed after safely aligning their types.*)\nDefinition tag_eq u v := (tag u == tag v) && (tagged u == tagged_as u v).\n\n(*This lemma states that the defined equality for dependently typed pairs satisfies the properties of a valid decidable equality relation, such as reflexivity, symmetry, and transitivity.*)\nLemma tag_eqP : Equality.axiom tag_eq.\n\n(*This lemma states that the specialized equality definition for dependently typed pairs is equivalent to the canonical equality operator for that type.*)\nLemma tag_eqE : tag_eq = eq_op. \n\n(*This lemma states that if two dependently typed pairs are equal, then their respective tags must also be equal.*)\nLemma eq_tag u v : u == v -> tag u = tag v.\n\n(*This lemma states that checking for equality between a dependently typed value and a newly constructed tagged value is equivalent to checking for equality between their respective underlying values.*)\nLemma eq_Tagged u x :(u == Tagged _ x) = (tagged u == x).\n\nEnd TagEqType.\n\nArguments tag_eq {I T_} !u !v.\nArguments tag_eqP {I T_ x y}.\n\nSection SumEqType.\n\nVariables T1 T2 : eqType.\nImplicit Types u v : T1 + T2.\n\n(*This definition specifies decidable equality for disjoint sum types. Two values are equal if they belong to the same side of the sum (both left or both right) and their underlying values are equal; otherwise, they are not equal.*)\nDefinition sum_eq u v :=\n match u, v with\n | inl x, inl y | inr x, inr y => x == y\n | _, _ => false\n end.\n\n(*This lemma states that the defined equality for disjoint sum types is a valid decidable equality relation, satisfying reflexivity, symmetry, and transitivity.*)\nLemma sum_eqP : Equality.axiom sum_eq.\n\n(*This lemma states that the specialized equality definition for disjoint sum types is equivalent to the canonical equality operator for that type.*)\nLemma sum_eqE : sum_eq = eq_op. \n\nEnd SumEqType.\n\nArguments sum_eq {T1 T2} !u !v.\nArguments sum_eqP {T1 T2 x y}.\n\nSection MonoHomoTheory.\n\nVariables (aT rT : eqType) (f : aT -> rT).\nVariables (aR aR' : rel aT) (rR rR' : rel rT).\n\nHypothesis aR_refl : reflexive aR.\nHypothesis rR_refl : reflexive rR.\nHypothesis aR'E : forall x y, aR' x y = (x != y) && (aR x y).\nHypothesis rR'E : forall x y, rR' x y = (x != y) && (rR x y).\n\n(*This local definition establishes that a reflexive relation between two elements holds if and only if the elements are equal or a corresponding irreflexive relation holds between them.*)\nLet aRE x y : aR x y = (x == y) || (aR' x y).\n\n(*This local definition establishes that a second reflexive relation on a different type holds between two elements if and only if the elements are equal or a corresponding irreflexive relation holds between them.*)\nLet rRE x y : rR x y = (x == y) || (rR' x y).\n\nSection InDom.\nVariable D : pred aT.\n\nSection DifferentDom.\nVariable D' : pred aT.\n\n(*This lemma asserts a property derived from the premise that a function is a homomorphism between two irreflexive relations, specifically when its inputs are restricted to two distinct subsets of the domain.*)\nLemma homoW_in : {in D & D', {homo f : x y / aR' x y >-> rR' x y}} ->\n {in D & D', {homo f : x y / aR x y >-> rR x y}}.\n\n(*This lemma states that for a function between two ordered types, an injective and non-decreasing function on specified subsets of its domain and codomain is also strictly increasing on those subsets.*)\nLemma inj_homo_in : {in D & D', injective f} ->\n {in D & D', {homo f : x y / aR x y >-> rR x y}} ->\n {in D & D', {homo f : x y / aR' x y >-> rR' x y}}.\n\nEnd DifferentDom.\n\nHypothesis aR_anti : antisymmetric aR.\nHypothesis rR_anti : antisymmetric rR.\n\n(*This lemma extracts the injectivity property from the structure of an injective order-preserving map, also known as a monomorphism, defined on subsets of two ordered types.*)\nLemma mono_inj_in : {in D &, {mono f : x y / aR x y >-> rR x y}} ->\n {in D &, injective f}.\n\n(*This lemma states that for a function between two types with antisymmetric order relations, an injective, non-decreasing map on a given subset is also an injective, strictly increasing map on that same subset.*)\nLemma anti_mono_in : {in D &, {mono f : x y / aR x y >-> rR x y}} ->\n {in D &, {mono f : x y / aR' x y >-> rR' x y}}.\n\n(*This lemma states that for a function whose domain is a totally ordered type, if the function is strictly increasing on a given subset, then it is an injective and non-decreasing map on that subset.*)\nLemma total_homo_mono_in : total aR ->\n {in D &, {homo f : x y / aR' x y >-> rR' x y}} ->\n {in D &, {mono f : x y / aR x y >-> rR x y}}.\n\nEnd InDom.\n\n(*This definition establishes an alias, `D`, for the type of predicates on a given base type. A predicate is a function that characterizes a subset of the base type.*)\nLet D := @predT aT.\n\n(*This lemma states that a strictly increasing function between two ordered types is also non-decreasing.*)\nLemma homoW : {homo f : x y / aR' x y >-> rR' x y} ->\n {homo f : x y / aR x y >-> rR x y}.\n\n(*This lemma states that an injective and non-decreasing function between two ordered types is also strictly increasing.*)\nLemma inj_homo : injective f ->\n {homo f : x y / aR x y >-> rR x y} ->\n {homo f : x y / aR' x y >-> rR' x y}.\n\nHypothesis aR_anti : antisymmetric aR.\nHypothesis rR_anti : antisymmetric rR.\n\n(*This lemma extracts the injectivity property from the structure of an injective order-preserving map, also known as a monomorphism.*)\nLemma mono_inj : {mono f : x y / aR x y >-> rR x y} -> injective f.\n\n(*This lemma states that for a function between two types with antisymmetric order relations, an injective, non-decreasing map is also an injective, strictly increasing map.*)\nLemma anti_mono : {mono f : x y / aR x y >-> rR x y} ->\n {mono f : x y / aR' x y >-> rR' x y}.\n\n(*This lemma states that for a function on a totally ordered domain, a strictly increasing function is also an injective and non-decreasing map.*)\nLemma total_homo_mono : total aR ->\n {homo f : x y / aR' x y >-> rR' x y} ->\n {mono f : x y / aR x y >-> rR x y}.", - "boot.ssrbool": "From mathcomp Require Import ssreflect ssrfun.\nFrom Corelib Require Export ssrbool.\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\n(*This lemma states that a function is injective on a subset of its domain defined by a predicate, provided that the function has a right inverse, and both the function and its right inverse map elements between the specified subset and a corresponding subset in the codomain.*)\nLemma homo_mono1 [aT rT : Type] [f : aT -> rT] [g : rT -> aT]\n [aP : pred aT] [rP : pred rT] :\n cancel g f ->\n {homo f : x / aP x >-> rP x} ->\n {homo g : x / rP x >-> aP x} -> {mono g : x / rP x >-> aP x}.\n\n(*This lemma states that a conditional expression dependent on the logical conjunction of two booleans is equivalent to a nested conditional expression that checks the first boolean, and only if it is true, proceeds to check the second.*)\nLemma if_and b1 b2 T (x y : T) :\n (if b1 && b2 then x else y) = (if b1 then if b2 then x else y else y).\n\n(*This lemma states that a conditional expression dependent on the logical disjunction of two booleans is equivalent to a nested conditional expression that checks the first boolean, and if it is false, proceeds to check the second.*)\nLemma if_or b1 b2 T (x y : T) :\n (if b1 || b2 then x else y) = (if b1 then x else if b2 then x else y).\n\n(*This lemma states that a conditional expression dependent on the boolean implication between two booleans is equivalent to a nested conditional. If the first boolean is true, the result depends on a conditional over the second boolean, but if the first boolean is false, the result is the 'then' value of the original expression.*)\nLemma if_implyb b1 b2 T (x y : T) :\n (if b1 ==> b2 then x else y) = (if b1 then if b2 then x else y else x).\n\n(*This lemma states an alternative equivalence for a conditional expression dependent on boolean implication. It is equivalent to a nested conditional that first checks the second boolean; if true, it returns the 'then' value, and if false, the outcome is determined by a conditional on the first boolean.*)\nLemma if_implybC b1 b2 T (x y : T) :\n (if b1 ==> b2 then x else y) = (if b2 then x else if b1 then y else x).\n\n(*This lemma states that a conditional expression dependent on the exclusive OR of two booleans is equivalent to a nested conditional structure where the first boolean determines whether the 'then' and 'else' values are returned normally or in a swapped order based on the second boolean.*)\nLemma if_add b1 b2 T (x y : T) :\n (if b1 (+) b2 then x else y) = (if b1 then if b2 then y else x else if b2 then x else y).\n\n(*This lemma states that for any function and any transitive binary relation on that function's codomain, the relational preimage induced by the function is also transitive. The relational preimage is a new relation on the function's domain that holds between two elements if and only if their images under the function are related by the original relation.*)\nLemma relpre_trans {T' T : Type} {leT : rel T} {f : T' -> T} :\n transitive leT -> transitive (relpre f leT).", - "boot.bigop": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.\nFrom mathcomp Require Import div fintype tuple finfun.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope big_scope.\n\nReserved Notation \"\\big [ op / idx ]_ i F\"\n (at level 36, F at level 36, op, idx at level 10, i at level 0,\n right associativity,\n format \"'[' \\big [ op / idx ]_ i '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i <- r | P ) F\"\n (F at level 36, i, r at level 50,\n format \"'[' \\big [ op / idx ]_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i <- r ) F\"\n (F at level 36,\n format \"'[' \\big [ op / idx ]_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( m <= i < n | P ) F\"\n (F at level 36, m, i, n at level 50,\n format \"'[' \\big [ op / idx ]_ ( m <= i < n | P ) F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( m <= i < n ) F\"\n (at level 36, F at level 36,\n format \"'[' \\big [ op / idx ]_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i | P ) F\"\n (F at level 36,\n format \"'[' \\big [ op / idx ]_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i : t | P ) F\"\n (F at level 36,\n format \"'[' \\big [ op / idx ]_ ( i : t | P ) '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i : t ) F\"\n (F at level 36,\n format \"'[' \\big [ op / idx ]_ ( i : t ) '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i < n | P ) F\"\n (F at level 36, n at level 50,\n format \"'[' \\big [ op / idx ]_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i < n ) F\"\n (F at level 36,\n format \"'[' \\big [ op / idx ]_ ( i < n ) F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i 'in' A | P ) F\"\n (F at level 36, A at level 50,\n format \"'[' \\big [ op / idx ]_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\big [ op / idx ]_ ( i 'in' A ) F\"\n (F at level 36,\n format \"'[' \\big [ op / idx ]_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\sum_ i F\"\n (at level 41, F at level 41, i at level 0,\n right associativity,\n format \"'[' \\sum_ i '/ ' F ']'\").\nReserved Notation \"\\sum_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\sum_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\sum_ ( i <- r ) F\"\n (F at level 41,\n format \"'[' \\sum_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\sum_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\sum_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\sum_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\sum_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\sum_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\sum_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\sum_ ( i : t | P ) F\"\n (F at level 41). \nReserved Notation \"\\sum_ ( i : t ) F\"\n (F at level 41). \nReserved Notation \"\\sum_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\sum_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\sum_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\sum_ ( i < n ) '/ ' F ']'\").\nReserved Notation \"\\sum_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\sum_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\sum_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\sum_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\max_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\max_ i '/ ' F ']'\").\nReserved Notation \"\\max_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\max_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i <- r ) F\"\n (F at level 41,\n format \"'[' \\max_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\max_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\max_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\max_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i : t | P ) F\"\n (F at level 41). \nReserved Notation \"\\max_ ( i : t ) F\"\n (F at level 41). \nReserved Notation \"\\max_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\max_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\max_ ( i < n ) F ']'\").\nReserved Notation \"\\max_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\max_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\max_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\prod_ i F\"\n (at level 36, F at level 36, i at level 0,\n format \"'[' \\prod_ i '/ ' F ']'\").\nReserved Notation \"\\prod_ ( i <- r | P ) F\"\n (F at level 36, i, r at level 50,\n format \"'[' \\prod_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\prod_ ( i <- r ) F\"\n (F at level 36,\n format \"'[' \\prod_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\prod_ ( m <= i < n | P ) F\"\n (F at level 36, i, n at level 50,\n format \"'[' \\prod_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\prod_ ( m <= i < n ) F\"\n (F at level 36,\n format \"'[' \\prod_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\prod_ ( i | P ) F\"\n (F at level 36,\n format \"'[' \\prod_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\prod_ ( i : t | P ) F\"\n (F at level 36). \nReserved Notation \"\\prod_ ( i : t ) F\"\n (F at level 36). \nReserved Notation \"\\prod_ ( i < n | P ) F\"\n (F at level 36, n at level 50,\n format \"'[' \\prod_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\prod_ ( i < n ) F\"\n (F at level 36,\n format \"'[' \\prod_ ( i < n ) '/ ' F ']'\").\nReserved Notation \"\\prod_ ( i 'in' A | P ) F\"\n (F at level 36, A at level 50,\n format \"'[' \\prod_ ( i 'in' A | P ) F ']'\").\nReserved Notation \"\\prod_ ( i 'in' A ) F\"\n (F at level 36,\n format \"'[' \\prod_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\bigcup_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\bigcup_ i '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\bigcup_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i <- r ) F\"\n (F at level 41,\n format \"'[' \\bigcup_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\bigcup_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\bigcup_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\bigcup_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i : t | P ) F\"\n (F at level 41,\n format \"'[' \\bigcup_ ( i : t | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i : t ) F\"\n (F at level 41,\n format \"'[' \\bigcup_ ( i : t ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\bigcup_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\bigcup_ ( i < n ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\bigcup_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcup_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\bigcup_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\bigcap_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\bigcap_ i '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\bigcap_ ( i <- r | P ) F ']'\").\nReserved Notation \"\\bigcap_ ( i <- r ) F\"\n (F at level 41,\n format \"'[' \\bigcap_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\bigcap_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\bigcap_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\bigcap_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( i : t | P ) F\"\n (F at level 41,\n format \"'[' \\bigcap_ ( i : t | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( i : t ) F\"\n (F at level 41,\n format \"'[' \\bigcap_ ( i : t ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\bigcap_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\bigcap_ ( i < n ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\bigcap_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\bigcap_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\bigcap_ ( i 'in' A ) '/ ' F ']'\").\n\nModule SemiGroup.\n\n(*A mixin that specifies the property for a binary operation on a type to be associative, meaning that the grouping of operands does not affect the outcome of repeated applications of the operation.*)\nHB.mixin Record isLaw T (op : T -> T -> T) := {\n opA : associative op;\n}.\n\n#[export]\n(*This structure defines a semigroup, which is a type equipped with a single binary operation that is associative.*)\nHB.structure Definition Law T := {op of isLaw T op}.\n(*This notation provides a shorthand for the property that a binary operation is associative.*)\nNotation law := Law.type.\n\n(*A mixin that specifies the property for a binary operation on a type to be commutative, meaning that the order of the two operands does not affect the result.*)\nHB.mixin Record isCommutativeLaw T (op : T -> T -> T) := {\n opC : commutative op;\n}.\n\n#[export]\n(*This structure defines a commutative semigroup, which is a type equipped with a single binary operation that is both associative and commutative.*)\nHB.structure Definition ComLaw T := {op of Law T op & isCommutativeLaw T op}.\n(*This notation provides a shorthand for the property that a binary operation is commutative.*)\nNotation com_law := ComLaw.type.\n\n(*A factory that constructs a commutative semigroup structure from proofs that a given binary operation on a type is both associative and commutative.*)\nHB.factory Record isComLaw T (op : T -> T -> T) := {\n opA : associative op;\n opC : commutative op;\n}.\n\nHB.builders Context T op of isComLaw T op.\n\nHB.instance Definition _ := isLaw.Build T op opA.\n(*This lemma states that the binary operation in a semigroup is associative, meaning that rearranging parentheses in a sequence of operations does not change the final result.*)\nLemma mulmA : associative mul. \nEnd Plain.\n\nSection Commutative.\nVariable mul : com_law T.\n(*This lemma states that the binary operation in a commutative semigroup is commutative, meaning that swapping the order of two operands does not change the result.*)\nLemma mulmC : commutative mul. \n(*This lemma states that the binary operation of a commutative semigroup is left-commutative, meaning that for any three elements, operating with the first on the product of the second and third is equivalent to operating with the second on the product of the first and third.*)\nLemma mulmCA : left_commutative mul.\n\n(*This lemma states that the binary operation of a commutative semigroup is right-commutative, meaning that for any three elements, operating on the product of the first two with the third is equivalent to operating on the product of the first and third with the second.*)\nLemma mulmAC : right_commutative mul.\n\n(*This lemma states that the binary operation in a commutative semigroup satisfies the interchange property, meaning that the product of two products can be reordered as the product of the products of their corresponding components.*)\nLemma mulmACA : interchange mul mul.\n\nEnd Commutative.\n\nEnd Theory.\n\nEnd Theory.\n\nInclude Theory.\n\nEnd SemiGroup.\nExport SemiGroup.Exports.\n\nModule Monoid.\n\nExport SemiGroup.\n\n(*A mixin that specifies the properties for an element to be a two-sided identity for a binary operation, meaning that applying the operation with this element on either the left or the right does not change the other operand.*)\nHB.mixin Record isMonoidLaw T (idm : T) (op : T -> T -> T) := {\n op1m : left_id idm op;\n opm1 : right_id idm op;\n}.\n\n#[export]\n(*This structure defines a monoid law, which is an associative binary operation on a type that has a two-sided identity element.*)\nHB.structure Definition Law T idm :=\n {op of SemiGroup.Law T op & isMonoidLaw T idm op}.\n(*A notation for the type of monoid laws, representing an associative binary operation with a two-sided identity element.*)\nNotation law := Law.type.\n\n(*A record that packages the properties for a binary operation to form a monoid, requiring associativity and the existence of a left and right identity element.*)\nHB.factory Record isLaw T (idm : T) (op : T -> T -> T) := {\n opA : associative op;\n op1m : left_id idm op;\n opm1 : right_id idm op;\n}.\n\nHB.builders Context T idm op of isLaw T idm op.\n\nHB.instance Definition _ := SemiGroup.isLaw.Build T op opA.\nHB.instance Definition _ := isMonoidLaw.Build T idm op op1m opm1.\n\nHB.end.\n\n#[export]\n(*This structure defines a commutative monoid law, which is an associative and commutative binary operation on a type that has a two-sided identity element.*)\nHB.structure Definition ComLaw T idm :=\n {op of Law T idm op & isCommutativeLaw T op}.\n(*A notation for the type of commutative monoid laws, representing an associative and commutative binary operation with a two-sided identity element.*)\nNotation com_law := ComLaw.type.\n\n(*A record that packages the properties for a binary operation to form a commutative monoid, requiring associativity, commutativity, and the existence of a left identity element.*)\nHB.factory Record isComLaw T (idm : T) (op : T -> T -> T) := {\n opA : associative op;\n opC : commutative op;\n op1m : left_id idm op;\n}.\n\nHB.builders Context T idm op of isComLaw T idm op.\n\n(*This lemma states that for a commutative binary operation, if an element serves as a left identity, then it also serves as a right identity.*)\nLemma opm1 : right_id idm op. \n\nHB.instance Definition _ := isLaw.Build T idm op opA op1m opm1.\n(*A record that captures properties of a multiplicative operation in a structure with a zero element, specifically requiring that the zero element acts as a left and right annihilator.*)\nHB.mixin Record isMulLaw T (zero : T) (mul : T -> T -> T) := {\n mul_zerol : left_zero zero mul;\n mul_zeror : right_zero zero mul;\n}.\n\n#[export]\n(*This structure defines a multiplicative law where a given element acts as a two-sided annihilator for the binary operation.*)\nHB.structure Definition MulLaw T zero := {mul of isMulLaw T zero mul}.\n(*A notation for the type of multiplicative laws where a specific element is a two-sided annihilator.*)\nNotation mul_law := MulLaw.type.\n\n(*A record that captures the interaction between two binary operations, requiring that the first operation distributes over the second operation from both the left and the right.*)\nHB.mixin Record isAddLaw T (mul : T -> T -> T) (op : T -> T -> T) := {\n mul_op_Dl : left_distributive mul op;\n mul_op_Dr : right_distributive mul op;\n}.\n\n#[export]\n(*This structure defines an additive law, which is a commutative monoid operation that interacts with a given multiplicative operation through distributivity.*)\nHB.structure Definition AddLaw T zero mul :=\n {add of ComLaw T zero add & isAddLaw T mul add}.\n(*A notation for the type of additive laws, representing a commutative monoid operation over which a separate multiplication distributes.*)\nNotation add_law := AddLaw.type.\n\nModule Import Exports. HB.reexport. End Exports.\n\nSection CommutativeAxioms.\n\nVariable (T : Type) (zero one : T) (mul add : T -> T -> T).\nHypothesis mulC : commutative mul.\n\n(*This lemma states that for a commutative multiplicative operation, if an element is a left identity, it is also a right identity.*)\nLemma mulC_id : left_id one mul -> right_id one mul.\n\n(*This lemma states that for a commutative multiplicative operation, if an element is a left annihilator, it is also a right annihilator.*)\nLemma mulC_zero : left_zero zero mul -> right_zero zero mul.\n\n(*This lemma states that if a multiplicative operation is commutative, then its left distributivity over an additive operation implies its right distributivity over the same additive operation.*)\nLemma mulC_dist : left_distributive mul add -> right_distributive mul add.\n\nEnd CommutativeAxioms.\n\nModule Theory.\n\nExport SemiGroup.Theory.\n\nSection Theory.\nVariables (T : Type) (idm : T).\n\nSection Plain.\nVariable mul : law idm.\n(*This lemma states that the identity element of a monoid structure is a left identity for its binary operation.*)\nLemma mul1m : left_id idm mul. \n(*This lemma states that the identity element of a monoid structure is a right identity for its binary operation.*)\nLemma mulm1 : right_id idm mul. \n(*This lemma states that iterating a monoid's binary operation with a given element for a specified number of times, starting from the identity, is equivalent to repeatedly applying the function that multiplies by that element to the identity element the same number of times.*)\nLemma iteropE n x : iterop n mul x idm = iter n (mul x) idm.\n\nEnd Plain.\n\nSection Mul.\nVariable mul : mul_law idm.\n(*This lemma states that the designated zero element of a multiplicative law is a left annihilator for its binary operation.*)\nLemma mul0m : left_zero idm mul. \n(*This lemma states that the designated zero element of a multiplicative law is a right annihilator for its binary operation.*)\nLemma mulm0 : right_zero idm mul. \nEnd Mul.\n\nSection Add.\nVariables (mul : T -> T -> T) (add : add_law idm mul).\n(*This lemma states that the binary operation of an additive law is associative.*)\nLemma addmA : associative add. \n(*This lemma states that the binary operation of an additive law is commutative.*)\nLemma addmC : commutative add. \n(*This lemma states that the binary operation of an additive law is left-commutative, meaning that applying the operation to an element and the result of the operation on two other elements is the same as swapping the first two elements.*)\nLemma addmCA : left_commutative add. \n(*This lemma states that the binary operation of an additive law is right-commutative, meaning that applying the operation to the result of an operation and a third element is the same as swapping the second and third elements.*)\nLemma addmAC : right_commutative add. \n(*This lemma states that the identity element of an additive law is a left identity for its binary operation.*)\nLemma add0m : left_id idm add. \n(*This lemma states that the identity element of an additive law is a right identity for its binary operation.*)\nLemma addm0 : right_id idm add. \n(*This lemma states that the multiplicative operation corresponding to an additive law is left-distributive over the additive operation.*)\nLemma mulmDl : left_distributive mul add. \n(*This lemma states that the multiplicative operation corresponding to an additive law is right-distributive over the additive operation.*)\nLemma mulmDr : right_distributive mul add. \nEnd Add.\n\n(*This definition groups together a collection of fundamental simplification lemmas about a multiplicative operation, including its interaction with identity and zero elements and its associativity.*)\nDefinition simpm := (mulm1, mulm0, mul1m, mul0m, mulmA).\n\nEnd Theory.\n\nEnd Theory.\nInclude SemiGroup.Theory.\nInclude Theory.\n\nEnd Monoid.\nExport Monoid.Exports.\n\nSection PervasiveMonoids.\n\nImport Monoid.\n\nHB.instance Definition _ := isComLaw.Build bool true andb andbA andbC andTb.\n\nHB.instance Definition _ := isMulLaw.Build bool false andb andFb andbF.\nHB.instance Definition _ := isComLaw.Build bool false orb orbA orbC orFb.\nHB.instance Definition _ := isMulLaw.Build bool true orb orTb orbT.\nHB.instance Definition _ := isComLaw.Build bool false addb addbA addbC addFb.\nHB.instance Definition _ := isAddLaw.Build bool andb orb andb_orl andb_orr.\nHB.instance Definition _ := isAddLaw.Build bool orb andb orb_andl orb_andr.\nHB.instance Definition _ := isAddLaw.Build bool andb addb andb_addl andb_addr.\n\nHB.instance Definition _ := isComLaw.Build nat 0 addn addnA addnC add0n.\nHB.instance Definition _ := isComLaw.Build nat 1 muln mulnA mulnC mul1n.\nHB.instance Definition _ := isMulLaw.Build nat 0 muln mul0n muln0.\nHB.instance Definition _ := isAddLaw.Build nat muln addn mulnDl mulnDr.\n\nHB.instance Definition _ := isComLaw.Build nat 0 maxn maxnA maxnC max0n.\nHB.instance Definition _ := isAddLaw.Build nat muln maxn maxnMl maxnMr.\n\nHB.instance Definition _ := isComLaw.Build nat 0 gcdn gcdnA gcdnC gcd0n.\nHB.instance Definition _ := isAddLaw.Build nat muln gcdn muln_gcdl muln_gcdr.\n\nHB.instance Definition _ := isComLaw.Build nat 1 lcmn lcmnA lcmnC lcm1n.\nHB.instance Definition _ := isAddLaw.Build nat muln lcmn muln_lcml muln_lcmr.\n\n(*This variant type encapsulates the components for a single term within an iterated operation, including the index, the binary operation, a conditional boolean flag, and the value of the term.*)\nVariant bigbody R I := BigBody of I & (R -> R -> R) & bool & R.\n\n(*This definition specifies a function that performs a single step in a cumulative computation. It takes a structure representing a term and an accumulated value. If the term's conditional flag is true, it combines the term's value with the accumulator using the specified binary operation; otherwise, it returns the accumulator unchanged.*)\nDefinition applybig {R I} (body : bigbody R I) x :=\n let: BigBody _ op b v := body in if b then op v x else x.\n\n(*This definition specifies a function that computes the result of an iterated operation over a sequence of indices. It takes an initial value, a sequence of indices, and a function generating term data for each index, and folds the operation over the sequence from right to left to produce a final value.*)\nDefinition reducebig R I idx r (body : I -> bigbody R I) :=\n foldr (applybig \\o body) idx r.\n\n(*This definition introduces a locked, canonical name for the general-purpose function that computes the result of an iterated operation, providing a stable identifier for the reduction mechanism.*)\nHB.lock Definition bigop := reducebig.\nCanonical bigop_unlock := Unlockable bigop.unlock.\n\n(*This definition creates a finite sequence of natural numbers representing the integer range starting from a given number up to, but not including, another given number.*)\nDefinition index_iota m n := iota m (n - m).\n\n(*This lemma states that a natural number is a member of the sequence generated for a range if and only if that number is greater than or equal to the lower bound and strictly less than the upper bound of the range.*)\nLemma mem_index_iota m n i : i \\in index_iota m n = (m <= i < n).\n\n(*This definition establishes an opaque key used to prevent the unfolding of the definition for the canonical enumeration of a finite type, ensuring its implementation remains abstract in proofs.*)\nFact index_enum_key : unit. \n(*This definition provides a canonical, locked enumeration of all elements of a given finite type, represented as a finite sequence.*)\nDefinition index_enum (T : finType) :=\n locked_with index_enum_key (Finite.enum T).\n\n(*This lemma states that filtering the canonical enumeration of a finite type with a boolean predicate yields the same sequence as directly enumerating only the elements that satisfy that predicate.*)\nLemma deprecated_filter_index_enum T P : filter P (index_enum T) = enum P.\n\n(*This lemma states that any element belonging to a given finite type is guaranteed to be present in the canonical sequence that enumerates all elements of that type.*)\nLemma mem_index_enum T i : i \\in index_enum T.\n\n#[global] Hint Resolve mem_index_enum : core.\n\n(*This lemma states that the canonical sequence enumerating all elements of a finite type contains no duplicate elements.*)\nLemma index_enum_uniq T : uniq (index_enum T).\n\n(*This notation represents a generic iterated operation over a given sequence of indices. It computes the result of repeatedly applying a binary operation to terms, where terms are included only if their corresponding index satisfies a boolean condition. The operation starts from a specified initial value.*)\nNotation \"\\big [ op / idx ]_ ( i <- r | P ) F\" :=\n (bigop idx r (fun i => BigBody i op P%B F)) : big_scope.\n(*This notation represents a generic iterated operation over a given sequence of indices. It computes the result of repeatedly applying a binary operation to terms corresponding to all indices in the sequence, starting from a specified initial value.*)\nNotation \"\\big [ op / idx ]_ ( i <- r ) F\" :=\n (bigop idx r (fun i => BigBody i op true F)) : big_scope.\n(*This notation represents a generic iterated operation over a range of natural numbers. It computes the result of repeatedly applying a binary operation to terms for indices within the range, but only includes terms whose index satisfies a boolean condition. The operation starts from a specified initial value.*)\nNotation \"\\big [ op / idx ]_ ( m <= i < n | P ) F\" :=\n (bigop idx (index_iota m n) (fun i : nat => BigBody i op P%B F))\n : big_scope.\n(*This notation represents a generic iterated operation over a range of natural numbers. It computes the result of repeatedly applying a binary operation to terms for all indices from a given start (inclusive) to an end (exclusive), starting from a specified initial value.*)\nNotation \"\\big [ op / idx ]_ ( m <= i < n ) F\" :=\n (bigop idx (index_iota m n) (fun i : nat => BigBody i op true F))\n : big_scope.\n(*This notation represents a generic iterated operation over all elements of a finite type. It computes the result of repeatedly applying a binary operation to terms corresponding to elements that satisfy a boolean condition, starting from a specified initial value.*)\nNotation \"\\big [ op / idx ]_ ( i | P ) F\" :=\n (bigop idx (index_enum _) (fun i => BigBody i op P%B F)) : big_scope.\n(*This notation represents a generic iterated operation over all elements of a finite type. It computes the result of repeatedly applying a binary operation to terms for all elements of the type, starting from a specified initial value.*)\nNotation \"\\big [ op / idx ]_ i F\" :=\n (bigop idx (index_enum _) (fun i => BigBody i op true F)) : big_scope.\n(*This notation serves as a parsing-only syntax for a generic iterated operation, allowing an explicit type annotation for the index variable. It computes the cumulative result over elements of the specified finite type that satisfy a boolean condition, using a given binary operation and initial value.*)\nNotation \"\\big [ op / idx ]_ ( i : t | P ) F\" :=\n (bigop idx (index_enum _) (fun i : t => BigBody i op P%B F))\n (only parsing) : big_scope.\n(*This notation serves as a parsing-only syntax for a generic iterated operation, allowing an explicit type annotation for the index variable. It computes the cumulative result over all elements of the specified finite type, using a given binary operation and initial value.*)\nNotation \"\\big [ op / idx ]_ ( i : t ) F\" :=\n (bigop idx (index_enum _) (fun i : t => BigBody i op true F))\n (only parsing) : big_scope.\n(*This notation represents a generic iterated operation over the natural numbers strictly less than a given bound. It computes the cumulative result of applying a binary operation to terms whose index satisfies a boolean condition, starting from a specified initial value.*)\nNotation \"\\big [ op / idx ]_ ( i < n | P ) F\" :=\n (\\big[op/idx]_(i : ordinal n | P%B) F) : big_scope.\n(*This notation represents a generic iterated operation over the natural numbers strictly less than a given bound. It computes the cumulative result of applying a binary operation to terms for all such indices, starting from a specified initial value.*)\nNotation \"\\big [ op / idx ]_ ( i < n ) F\" :=\n (\\big[op/idx]_(i : ordinal n) F) : big_scope.\n(*This notation represents a generic iterated operation over the elements of a given finite set. It computes the cumulative result by applying a binary operation to a starting value and all terms for which the index is in the set and also satisfies an additional boolean condition.*)\nNotation \"\\big [ op / idx ]_ ( i 'in' A | P ) F\" :=\n (\\big[op/idx]_(i | (i \\in A) && P) F) : big_scope.\n(*This notation represents a generic iterated operation over the elements of a given finite set. It computes the cumulative result by applying a binary operation to a starting value and all terms whose index is in the set.*)\nNotation \"\\big [ op / idx ]_ ( i 'in' A ) F\" :=\n (\\big[op/idx]_(i | i \\in A) F) : big_scope.\n\n(*This notation is a pattern used in rewrite tactics to match the function that generates the term's value within a big operator expression.*)\nNotation BIG_F := (F in \\big[_/_]_(i <- _ | _) F i)%pattern.\n(*This notation is a pattern used in rewrite tactics to match the boolean predicate function that filters indices within a big operator expression.*)\nNotation BIG_P := (P in \\big[_/_]_(i <- _ | P i) _)%pattern.\n\n(*This notation provides a local, parsing-only alias for natural number addition, intended for use within the definition of summation notations.*)\nLocal Notation \"+%N\" := addn (only parsing).\n(*This notation represents the sum of a sequence of natural numbers, starting from zero. It computes the total sum of terms generated from indices in a given list, but only includes terms for which the index satisfies a specified boolean condition.*)\nNotation \"\\sum_ ( i <- r | P ) F\" :=\n (\\big[+%N/0%N]_(i <- r | P%B) F%N) : nat_scope.\n(*This notation represents the sum of a sequence of natural numbers, starting from zero. It computes the total sum of terms generated from all indices in a given list.*)\nNotation \"\\sum_ ( i <- r ) F\" :=\n (\\big[+%N/0%N]_(i <- r) F%N) : nat_scope.\n(*This notation represents the sum of natural numbers over a given range, starting from zero. It computes the total value by summing terms for indices from a lower bound (inclusive) to an upper bound (exclusive), but only includes terms whose index satisfies a specified boolean condition.*)\nNotation \"\\sum_ ( m <= i < n | P ) F\" :=\n (\\big[+%N/0%N]_(m <= i < n | P%B) F%N) : nat_scope.\n(*This notation represents the sum of natural numbers over a given range, starting from zero. It computes the total value by summing terms corresponding to all indices from a lower bound (inclusive) to an upper bound (exclusive).*)\nNotation \"\\sum_ ( m <= i < n ) F\" :=\n (\\big[+%N/0%N]_(m <= i < n) F%N) : nat_scope.\n(*A notation for the sum of a natural number expression over all indices that satisfy a given boolean predicate.*)\nNotation \"\\sum_ ( i | P ) F\" :=\n (\\big[+%N/0%N]_(i | P%B) F%N) : nat_scope.\n(*A notation for the sum of a natural number expression over all indices in an inferred domain.*)\nNotation \"\\sum_ i F\" :=\n (\\big[+%N/0%N]_i F%N) : nat_scope.\n(*A parsing-only notation for the sum of a natural number expression over all indices of a given type that satisfy a boolean predicate.*)\nNotation \"\\sum_ ( i : t | P ) F\" :=\n (\\big[+%N/0%N]_(i : t | P%B) F%N) (only parsing) : nat_scope.\n(*A parsing-only notation for the sum of a natural number expression over all indices of a given type.*)\nNotation \"\\sum_ ( i : t ) F\" :=\n (\\big[+%N/0%N]_(i : t) F%N) (only parsing) : nat_scope.\n(*A notation for the sum of a natural number expression over all indices less than a given natural number that also satisfy a boolean predicate.*)\nNotation \"\\sum_ ( i < n | P ) F\" :=\n (\\big[+%N/0%N]_(i < n | P%B) F%N) : nat_scope.\n(*A notation for the sum of a natural number expression over all indices less than a given natural number.*)\nNotation \"\\sum_ ( i < n ) F\" :=\n (\\big[+%N/0%N]_(i < n) F%N) : nat_scope.\n(*A notation for the sum of a natural number expression over all indices belonging to a given finite set that also satisfy a boolean predicate.*)\nNotation \"\\sum_ ( i 'in' A | P ) F\" :=\n (\\big[+%N/0%N]_(i in A | P%B) F%N) : nat_scope.\n(*A notation for the sum of a natural number expression over all indices belonging to a given finite set.*)\nNotation \"\\sum_ ( i 'in' A ) F\" :=\n (\\big[+%N/0%N]_(i in A) F%N) : nat_scope.\n\n(*A local parsing-only notation for the multiplication of two natural numbers.*)\nLocal Notation \"*%N\" := muln (only parsing).\n(*A notation for the product of a natural number expression over all indices in a given finite sequence that also satisfy a boolean predicate.*)\nNotation \"\\prod_ ( i <- r | P ) F\" :=\n (\\big[*%N/1%N]_(i <- r | P%B) F%N) : nat_scope.\n(*A notation for the product of a natural number expression over all indices in a given finite sequence.*)\nNotation \"\\prod_ ( i <- r ) F\" :=\n (\\big[*%N/1%N]_(i <- r) F%N) : nat_scope.\n(*A notation for the product of a natural number expression over all indices in a given half-open range of natural numbers that also satisfy a boolean predicate.*)\nNotation \"\\prod_ ( m <= i < n | P ) F\" :=\n (\\big[*%N/1%N]_(m <= i < n | P%B) F%N) : nat_scope.\n(*A notation for the product of a natural number expression over all indices in a given half-open range of natural numbers.*)\nNotation \"\\prod_ ( m <= i < n ) F\" :=\n (\\big[*%N/1%N]_(m <= i < n) F%N) : nat_scope.\n(*A notation for the product of a natural number expression over all indices that satisfy a given boolean predicate.*)\nNotation \"\\prod_ ( i | P ) F\" :=\n (\\big[*%N/1%N]_(i | P%B) F%N) : nat_scope.\n(*A notation for the product of a natural number expression over all indices in an inferred domain.*)\nNotation \"\\prod_ i F\" :=\n (\\big[*%N/1%N]_i F%N) : nat_scope.\n(*A parsing-only notation for the product of a natural number expression over all indices of a given type that satisfy a boolean predicate.*)\nNotation \"\\prod_ ( i : t | P ) F\" :=\n (\\big[*%N/1%N]_(i : t | P%B) F%N) (only parsing) : nat_scope.\n(*A parsing-only notation for the product of a natural number expression over all indices of a given type.*)\nNotation \"\\prod_ ( i : t ) F\" :=\n (\\big[*%N/1%N]_(i : t) F%N) (only parsing) : nat_scope.\n(*A notation for the product of a natural number expression over all indices less than a given natural number that also satisfy a boolean predicate.*)\nNotation \"\\prod_ ( i < n | P ) F\" :=\n (\\big[*%N/1%N]_(i < n | P%B) F%N) : nat_scope.\n(*A notation for the product of a natural number expression over all indices less than a given natural number.*)\nNotation \"\\prod_ ( i < n ) F\" :=\n (\\big[*%N/1%N]_(i < n) F%N) : nat_scope.\n(*A notation for the product of a natural number expression over all indices belonging to a given finite set that also satisfy a boolean predicate.*)\nNotation \"\\prod_ ( i 'in' A | P ) F\" :=\n (\\big[*%N/1%N]_(i in A | P%B) F%N) : nat_scope.\n(*A notation for the product of a natural number expression over all indices belonging to a given finite set.*)\nNotation \"\\prod_ ( i 'in' A ) F\" :=\n (\\big[*%N/1%N]_(i in A) F%N) : nat_scope.\n\n(*A notation for the maximum value of a natural number expression over all indices in a given finite sequence that also satisfy a boolean predicate.*)\nNotation \"\\max_ ( i <- r | P ) F\" :=\n (\\big[maxn/0%N]_(i <- r | P%B) F%N) : nat_scope.\n(*A notation for the maximum value of a natural number expression over all indices in a given finite sequence.*)\nNotation \"\\max_ ( i <- r ) F\" :=\n (\\big[maxn/0%N]_(i <- r) F%N) : nat_scope.\n(*A notation for the maximum value of a natural number expression over all indices that satisfy a given boolean predicate.*)\nNotation \"\\max_ ( i | P ) F\" :=\n (\\big[maxn/0%N]_(i | P%B) F%N) : nat_scope.\n(*A notation for the maximum value of a natural number expression over all indices in an inferred domain.*)\nNotation \"\\max_ i F\" :=\n (\\big[maxn/0%N]_i F%N) : nat_scope.\n(*A parsing-only notation for the maximum value of a natural number expression over all indices of a given type that also satisfy a boolean predicate.*)\nNotation \"\\max_ ( i : I | P ) F\" :=\n (\\big[maxn/0%N]_(i : I | P%B) F%N) (only parsing) : nat_scope.\n(*A parsing-only notation for the maximum value of a natural number expression over all indices of a given type.*)\nNotation \"\\max_ ( i : I ) F\" :=\n (\\big[maxn/0%N]_(i : I) F%N) (only parsing) : nat_scope.\n(*A notation for the maximum value of a natural number expression over all indices in a given half-open range of natural numbers that also satisfy a boolean predicate.*)\nNotation \"\\max_ ( m <= i < n | P ) F\" :=\n (\\big[maxn/0%N]_(m <= i < n | P%B) F%N) : nat_scope.\n(*A notation for the maximum value of a natural number expression over all indices in a given half-open range of natural numbers.*)\nNotation \"\\max_ ( m <= i < n ) F\" :=\n (\\big[maxn/0%N]_(m <= i < n) F%N) : nat_scope.\n(*A notation for the maximum value of a natural number expression over all indices less than a given natural number that also satisfy a boolean predicate.*)\nNotation \"\\max_ ( i < n | P ) F\" :=\n (\\big[maxn/0%N]_(i < n | P%B) F%N) : nat_scope.\n(*This notation represents the maximum value of a function over the range of natural numbers less than a given bound. The function takes a natural number as input and returns a natural number. If the range is empty, the result is zero.*)\nNotation \"\\max_ ( i < n ) F\" :=\n (\\big[maxn/0%N]_(i < n) F%N) : nat_scope.\n(*This notation represents the maximum value of a function over all elements in a given finite set that also satisfy a given boolean predicate. The function takes an element from the set as input and returns a natural number. If no elements satisfy the predicate, the result is zero.*)\nNotation \"\\max_ ( i 'in' A | P ) F\" :=\n (\\big[maxn/0%N]_(i in A | P%B) F%N) : nat_scope.\n(*This notation represents the maximum value of a function over all elements in a given finite set. The function takes an element from the set as input and returns a natural number. If the set is empty, the result is zero.*)\nNotation \"\\max_ ( i 'in' A ) F\" :=\n (\\big[maxn/0%N]_(i in A) F%N) : nat_scope.\n\n(*This lemma states that if a pair of properties, represented by two dependent types, both hold for the result of a big operator computation, then the second property in the pair also holds for that result.*)\nLemma big_load R (K K' : R -> Type) idx op I r (P : pred I) F :\n K (\\big[op/idx]_(i <- r | P i) F i) * K' (\\big[op/idx]_(i <- r | P i) F i)\n -> K' (\\big[op/idx]_(i <- r | P i) F i).\n\nArguments big_load [R] K [K'] idx op [I].\n\nSection Elim3.\n\nVariables (R1 R2 R3 : Type) (K : R1 -> R2 -> R3 -> Type).\nVariables (id1 : R1) (op1 : R1 -> R1 -> R1).\nVariables (id2 : R2) (op2 : R2 -> R2 -> R2).\nVariables (id3 : R3) (op3 : R3 -> R3 -> R3).\n\nHypothesis Kid : K id1 id2 id3.\n\n(*This lemma provides a recursion principle for a property involving three parallel big operator computations. It states that if a ternary predicate holds for the initial identity elements, and if for each element in the iteration sequence, the predicate is preserved when combining the current function values with the accumulated results, then the predicate will hold for the final triple of accumulated results.*)\nLemma big_rec3 I r (P : pred I) F1 F2 F3\n (K_F : forall i y1 y2 y3, P i -> K y1 y2 y3 ->\n K (op1 (F1 i) y1) (op2 (F2 i) y2) (op3 (F3 i) y3)) :\n K (\\big[op1/id1]_(i <- r | P i) F1 i)\n (\\big[op2/id2]_(i <- r | P i) F2 i)\n (\\big[op3/id3]_(i <- r | P i) F3 i).\n\nHypothesis Kop : forall x1 x2 x3 y1 y2 y3,\n K x1 x2 x3 -> K y1 y2 y3-> K (op1 x1 y1) (op2 x2 y2) (op3 x3 y3).\n(*This lemma provides an induction principle for a property involving three parallel big operator computations. It states that if a ternary predicate is closed under the three respective binary operators and holds for the values of the three functions at each valid index in the iteration sequence, then the predicate will also hold for the final triple of accumulated results.*)\nLemma big_ind3 I r (P : pred I) F1 F2 F3\n (K_F : forall i, P i -> K (F1 i) (F2 i) (F3 i)) :\n K (\\big[op1/id1]_(i <- r | P i) F1 i)\n (\\big[op2/id2]_(i <- r | P i) F2 i)\n (\\big[op3/id3]_(i <- r | P i) F3 i).\n\nEnd Elim3.\n\nArguments big_rec3 [R1 R2 R3] K [id1 op1 id2 op2 id3 op3] _ [I r P F1 F2 F3].\nArguments big_ind3 [R1 R2 R3] K [id1 op1 id2 op2 id3 op3] _ _ [I r P F1 F2 F3].\n\nSection Elim2.\n\nVariables (R1 R2 : Type) (K : R1 -> R2 -> Type) (f : R2 -> R1).\nVariables (id1 : R1) (op1 : R1 -> R1 -> R1).\nVariables (id2 : R2) (op2 : R2 -> R2 -> R2).\n\nHypothesis Kid : K id1 id2.\n\n(*This lemma provides a recursion principle for a property involving two parallel big operator computations. It states that if a binary predicate holds for the initial identity elements, and if for each element in the iteration sequence, the predicate is preserved when combining the current function values with the accumulated results, then the predicate will hold for the final pair of accumulated results.*)\nLemma big_rec2 I r (P : pred I) F1 F2\n (K_F : forall i y1 y2, P i -> K y1 y2 ->\n K (op1 (F1 i) y1) (op2 (F2 i) y2)) :\n K (\\big[op1/id1]_(i <- r | P i) F1 i) (\\big[op2/id2]_(i <- r | P i) F2 i).\n\nHypothesis Kop : forall x1 x2 y1 y2,\n K x1 x2 -> K y1 y2 -> K (op1 x1 y1) (op2 x2 y2).\n(*This lemma provides an induction principle for a property involving two parallel big operator computations. It states that if a binary predicate is closed under the two respective binary operators and holds for the values of the two functions at each valid index in the iteration sequence, then the predicate will also hold for the final pair of accumulated results.*)\nLemma big_ind2 I r (P : pred I) F1 F2 (K_F : forall i, P i -> K (F1 i) (F2 i)) :\n K (\\big[op1/id1]_(i <- r | P i) F1 i) (\\big[op2/id2]_(i <- r | P i) F2 i).\n\nHypotheses (f_op : {morph f : x y / op2 x y >-> op1 x y}) (f_id : f id2 = id1).\n(*This lemma states that a function that is a structure-preserving morphism between two algebraic structures commutes with the big operator. Applying the function to the result of a big operation over a sequence is equivalent to performing the big operation in the target structure over the sequence of function values.*)\nLemma big_morph I r (P : pred I) F :\n f (\\big[op2/id2]_(i <- r | P i) F i) = \\big[op1/id1]_(i <- r | P i) f (F i).\n\nEnd Elim2.\n\nArguments big_rec2 [R1 R2] K [id1 op1 id2 op2] _ [I r P F1 F2].\nArguments big_ind2 [R1 R2] K [id1 op1 id2 op2] _ _ [I r P F1 F2].\nArguments big_morph [R1 R2] f [id1 op1 id2 op2] _ _ [I].\n\nSection Elim1.\n\nVariables (R : Type) (K : R -> Type) (f : R -> R).\nVariables (idx : R) (op op' : R -> R -> R).\n\nHypothesis Kid : K idx.\n\n(*This lemma provides a recursion principle for a property of a single big operator computation. It states that if a unary predicate holds for the initial identity element, and if for each element in the iteration sequence, the predicate is preserved when combining the current function value with the accumulated result, then the predicate will hold for the final accumulated result.*)\nLemma big_rec I r (P : pred I) F\n (Kop : forall i x, P i -> K x -> K (op (F i) x)) :\n K (\\big[op/idx]_(i <- r | P i) F i).\n\nHypothesis Kop : forall x y, K x -> K y -> K (op x y).\n(*This lemma provides an induction principle for a property of a single big operator computation. It states that if a unary predicate is closed under the binary operator and holds for the value of the function at each valid index in the iteration sequence, then the predicate will also hold for the final accumulated result.*)\nLemma big_ind I r (P : pred I) F (K_F : forall i, P i -> K (F i)) :\n K (\\big[op/idx]_(i <- r | P i) F i).\n\nHypothesis Kop' : forall x y, K x -> K y -> op x y = op' x y.\n(*This lemma states that if two binary operators produce identical results for all pairs of inputs satisfying a given predicate, then the corresponding big operators will also produce identical results when applied to a sequence of function values, provided that each of these values satisfies the predicate.*)\nLemma eq_big_op I r (P : pred I) F (K_F : forall i, P i -> K (F i)) :\n \\big[op/idx]_(i <- r | P i) F i = \\big[op'/idx]_(i <- r | P i) F i.\n\nHypotheses (fM : {morph f : x y / op x y}) (f_id : f idx = idx).\n(*This lemma states that an endomorphism, which is a structure-preserving function from a type to itself, commutes with the big operator. Applying the endomorphism to the result of a big operation is equivalent to performing the big operation over the sequence of function values after applying the endomorphism to each of them.*)\nLemma big_endo I r (P : pred I) F :\n f (\\big[op/idx]_(i <- r | P i) F i) = \\big[op/idx]_(i <- r | P i) f (F i).\n\nEnd Elim1.\n\nArguments big_rec [R] K [idx op] _ [I r P F].\nArguments big_ind [R] K [idx op] _ _ [I r P F].\nArguments eq_big_op [R] K [idx op] op' _ _ _ [I].\nArguments big_endo [R] f [idx op] _ _ [I].\n\n(*This lemma states that a function which is a morphism between two algebraic structures, restricted to a specific subset of its domain, commutes with the big operator, provided that all inputs to the operator and all intermediate results remain within that subset.*)\nLemma big_morph_in (R1 R2 : Type) (Q : {pred R2}) (f : R2 -> R1)\n (id1 : R1) (op1 : R1 -> R1 -> R1)\n (id2 : R2) (op2 : R2 -> R2 -> R2) :\n {in Q &, forall x y, op2 x y \\in Q} ->\n id2 \\in Q ->\n {in Q &, {morph f : x y / op2 x y >-> op1 x y}} ->\n f id2 = id1 ->\n forall [I : Type] (r : seq I) (P : pred I) (F : I -> R2),\n (forall i, P i -> F i \\in Q) ->\n f (\\big[op2/id2]_(i <- r | P i) F i) = \\big[op1/id1]_(i <- r | P i) f (F i).\n\nArguments big_morph_in [R1 R2] Q f [id1 op1 id2 op2].\n\nSection oAC.\n\nVariables (T : Type) (op : T -> T -> T).\n\n(*This definition constructs a binary operator on an option type from a given associative and commutative binary operator on the underlying type. This new operator will serve as the operation for a commutative monoid structure on the option type.*)\nDefinition oAC of associative op & commutative op :=\n fun x => oapp (fun y => Some (oapp (op^~ y) y x)) x.\nArguments oAC : simpl never.\n\nHypothesis (opA : associative op) (opC : commutative op).\n\n(*This notation is a local alias for a binary operator on an option type, constructed from a given associative and commutative binary operator on the underlying type, designed to form a commutative monoid.*)\nLocal Notation oop := (oAC opA opC).\n\n(*This lemma states that the monoid operator on an option type, when applied to two arguments that are both 'Some' values, yields a 'Some' value containing the result of applying the underlying base operator to the unwrapped values.*)\nLemma oACE x y : oop (Some x) (Some y) = some (op x y). \n\n(*This lemma states that the constructed binary operator for an option type is associative.*)\nLemma oopA_subdef : associative oop.\n\n(*This lemma states that the 'None' value is the left identity for the constructed binary operator on an option type.*)\nLemma oopx1_subdef : left_id None oop. \n(*This lemma states that the 'None' value is the right identity for the constructed binary operator on an option type.*)\nLemma oop1x_subdef : right_id None oop. \n\n(*This lemma states that the constructed binary operator for an option type is commutative.*)\nLemma oopC_subdef : commutative oop.\n\n(*This lemma relates a big operator computation over a base type with an associative and commutative operator to a corresponding big operator computation over the associated option type, which has a canonical monoid structure. It states that wrapping the result of the base computation in 'Some' is equivalent to a specific combination of operations within the option monoid.*)\nLemma some_big_AC_mk_monoid [I : Type] r P (F : I -> T) :\n Some (\\big[op/x]_(i <- r | P i) F i) =\n oop (\\big[oop/None]_(i <- r | P i) Some (F i)) (Some x).\n\n(*This lemma provides a way to compute the result of a big operation with an associative and commutative operator by lifting the computation to the canonical monoid on the corresponding option type and then providing a default value if the result is 'None'.*)\nLemma big_AC_mk_monoid [I : Type] r P (F : I -> T) :\n \\big[op/x]_(i <- r | P i) F i =\n odflt x (oop (\\big[oop/None]_(i <- r | P i) Some (F i)) (Some x)).\n\nEnd oAC.\nArguments oAC : simpl never.\n\nSection Extensionality.\n\nVariables (R : Type) (idx : R) (op : R -> R -> R).\n\nSection SeqExtension.\n\nVariable I : Type.\n\n(*This lemma states that a right fold over a finite sequence using a given binary operator and initial value is equivalent to performing a big operator computation with the same operator and identity over the elements of that sequence.*)\nLemma foldrE r : foldr op idx r = \\big[op/idx]_(x <- r) x.\n\n(*This lemma states that performing a big operator computation over a sequence that has been filtered by a predicate is equivalent to performing the same big operator computation over the original sequence with the predicate incorporated into the operator's range.*)\nLemma big_filter r (P : pred I) F :\n \\big[op/idx]_(i <- filter P r) F i = \\big[op/idx]_(i <- r | P i) F i.\n\n(*This lemma states that performing a big operator computation over a pre-filtered sequence with an additional predicate is equivalent to performing the computation over the original sequence with a single predicate that is the logical conjunction of the filtering predicate and the additional predicate.*)\nLemma big_filter_cond r (P1 P2 : pred I) F :\n \\big[op/idx]_(i <- filter P1 r | P2 i) F i\n = \\big[op/idx]_(i <- r | P1 i && P2 i) F i.\n\n(*This lemma states that if two predicates are equivalent over the domain of iteration, then the results of the corresponding big operator computations using these two predicates will be identical.*)\nLemma eq_bigl r (P1 P2 : pred I) F :\n P1 =1 P2 ->\n \\big[op/idx]_(i <- r | P1 i) F i = \\big[op/idx]_(i <- r | P2 i) F i.\n\n(*This lemma states that swapping the order of two predicates joined by a logical conjunction within the range of a big operator does not change the final result of the computation.*)\nLemma big_andbC r (P Q : pred I) F :\n \\big[op/idx]_(i <- r | P i && Q i) F i\n = \\big[op/idx]_(i <- r | Q i && P i) F i.\n\n(*This lemma states that if two functions yield identical values for all indices satisfying a given predicate, a big operator computation over these two functions with that predicate will produce identical results.*)\nLemma eq_bigr r (P : pred I) F1 F2 : (forall i, P i -> F1 i = F2 i) ->\n \\big[op/idx]_(i <- r | P i) F1 i = \\big[op/idx]_(i <- r | P i) F2 i.\n\n(*This lemma states that two big operator computations are equal if their predicates are equivalent over the iteration domain and their functions produce identical values for all indices that satisfy the second predicate.*)\nLemma eq_big r (P1 P2 : pred I) F1 F2 :\n P1 =1 P2 -> (forall i, P1 i -> F1 i = F2 i) ->\n \\big[op/idx]_(i <- r | P1 i) F1 i = \\big[op/idx]_(i <- r | P2 i) F2 i.\n\n(*This lemma states that the result of a big operation over a sequence is identical if the sequence, the filtering predicate, and the function being applied are replaced by respectively equal counterparts.*)\nLemma congr_big r1 r2 (P1 P2 : pred I) F1 F2 :\n r1 = r2 -> P1 =1 P2 -> (forall i, P1 i -> F1 i = F2 i) ->\n \\big[op/idx]_(i <- r1 | P1 i) F1 i = \\big[op/idx]_(i <- r2 | P2 i) F2 i.\n\n(*This lemma states that applying a big operation over an empty sequence results in the identity element of the operation.*)\nLemma big_nil (P : pred I) F : \\big[op/idx]_(i <- [::] | P i) F i = idx.\n\n(*This lemma provides a recursive formula for the big operation over a non-empty sequence, where the result is obtained by combining the function's value at the head element with the operation's result on the tail, but only if the head element satisfies the predicate; otherwise, the result is simply that of the operation on the tail.*)\nLemma big_cons i r (P : pred I) F :\n let x := \\big[op/idx]_(j <- r | P j) F j in\n \\big[op/idx]_(j <- i :: r | P j) F j = if P i then op (F i) x else x.\n\n(*This lemma describes how to compute a big operation on a sequence with an element appended at the end. It states that this is equivalent to computing the operation on the original sequence with a new identity element, which is formed by combining the function's value at the appended element with the original identity, provided the appended element satisfies the predicate.*)\nLemma big_rcons_op i r (P : pred I) F :\n let idx' := if P i then op (F i) idx else idx in\n \\big[op/idx]_(j <- rcons r i | P j) F j = \\big[op/idx']_(j <- r | P j) F j.\n\n(*This lemma states that a big operation over a sequence created by mapping a function is equivalent to performing the big operation on the original sequence, with both the predicate and the operated-on function composed with the mapping function.*)\nLemma big_map J (h : J -> I) r (P : pred I) F :\n \\big[op/idx]_(i <- map h r | P i) F i\n = \\big[op/idx]_(j <- r | P (h j)) F (h j).\n\n(*This lemma states that computing a big operation over the elements of a sequence is equivalent to computing the same operation over the range of its valid indices, applying the function and predicate to the element at each index.*)\nLemma big_nth x0 r (P : pred I) F :\n \\big[op/idx]_(i <- r | P i) F i\n = \\big[op/idx]_(0 <= i < size r | P (nth x0 r i)) (F (nth x0 r i)).\n\n(*This lemma asserts that if a predicate holds for no element in a sequence, the big operation over that sequence with that predicate evaluates to the operation's identity element.*)\nLemma big_hasC r (P : pred I) F :\n ~~ has P r -> \\big[op/idx]_(i <- r | P i) F i = idx.\n\n(*This lemma states that performing a big operation over any sequence with a predicate that is always false results in the identity element of the operation.*)\nLemma big_pred0_eq (r : seq I) F : \\big[op/idx]_(i <- r | false) F i = idx.\n\n(*This lemma states that if a predicate is equivalent to one that is always false, the big operation over any sequence with that predicate results in the identity element of the operation.*)\nLemma big_pred0 r (P : pred I) F :\n P =1 xpred0 -> \\big[op/idx]_(i <- r | P i) F i = idx.\n\n(*This lemma provides a method for computing a big operation over the concatenation of two sequences, by first calculating the operation over the second sequence and then using that result as the initial value for the calculation over the first sequence.*)\nLemma big_cat_nested r1 r2 (P : pred I) F :\n let x := \\big[op/idx]_(i <- r2 | P i) F i in\n \\big[op/idx]_(i <- r1 ++ r2 | P i) F i = \\big[op/x]_(i <- r1 | P i) F i.\n\n(*This lemma states that if a predicate is false for every element in a second sequence, the big operation over the concatenation of a first sequence and the second sequence is equal to the big operation over just the first sequence.*)\nLemma big_catl r1 r2 (P : pred I) F :\n ~~ has P r2 ->\n \\big[op/idx]_(i <- r1 ++ r2 | P i) F i = \\big[op/idx]_(i <- r1 | P i) F i.\n\n(*This lemma states that if a predicate is false for every element in a first sequence, the big operation over the concatenation of that first sequence and a second one is equal to the big operation over just the second sequence.*)\nLemma big_catr r1 r2 (P : pred I) F :\n ~~ has P r1 ->\n \\big[op/idx]_(i <- r1 ++ r2 | P i) F i = \\big[op/idx]_(i <- r2 | P i) F i.\n\nEnd SeqExtension.\n\n(*This lemma shows that applying a big operation to the elements of a mapped sequence, where the accumulated value is the element itself, is equivalent to accumulating the results of the mapping function over the original sequence, filtered by the correspondingly mapped predicate.*)\nLemma big_map_id J (h : J -> R) r (P : pred R) :\n \\big[op/idx]_(i <- map h r | P i) i\n = \\big[op/idx]_(j <- r | P (h j)) h j.\n\n(*This lemma states that for a big operation over a finite collection of elements, using a predicate that is always true is equivalent to performing the operation without a predicate.*)\nLemma big_condT (J : finType) (A : {pred J}) F :\n \\big[op/idx]_(i in A | true) F i = \\big[op/idx]_(i in A) F i.\n\n(*This lemma states that for a big operation over a sequence, strengthening the predicate with an additional condition that the element must be a member of the sequence does not alter the result.*)\nLemma big_seq_cond (I : eqType) r (P : pred I) F :\n \\big[op/idx]_(i <- r | P i) F i\n = \\big[op/idx]_(i <- r | (i \\in r) && P i) F i.\n\n(*This lemma clarifies that a big operation over a sequence without an explicit predicate is implicitly equivalent to one with a predicate that verifies membership of each element in the sequence.*)\nLemma big_seq (I : eqType) (r : seq I) F :\n \\big[op/idx]_(i <- r) F i = \\big[op/idx]_(i <- r | i \\in r) F i.\n\n(*This lemma states that if two functions yield equal values for every element in a sequence, the results of applying a big operation over that sequence with either of these functions will be identical.*)\nLemma eq_big_seq (I : eqType) (r : seq I) F1 F2 :\n {in r, F1 =1 F2} -> \\big[op/idx]_(i <- r) F1 i = \\big[op/idx]_(i <- r) F2 i.\n\n(*This lemma states that for a big operation over a range of natural numbers, strengthening the predicate with an additional condition that the iterated number must be within that range does not alter the final result.*)\nLemma big_nat_cond m n (P : pred nat) F :\n \\big[op/idx]_(m <= i < n | P i) F i\n = \\big[op/idx]_(m <= i < n | (m <= i < n) && P i) F i.\n\n(*This lemma clarifies that a big operation over a range of natural numbers without an explicit predicate is implicitly equivalent to one with a predicate that verifies the iterated number falls within that range.*)\nLemma big_nat m n F :\n \\big[op/idx]_(m <= i < n) F i = \\big[op/idx]_(m <= i < n | m <= i < n) F i.\n\n(*This lemma provides a congruence rule for big operations over ranges of natural numbers, asserting that the result remains the same if the range boundaries, the predicate, and the function are replaced by equal counterparts.*)\nLemma congr_big_nat m1 n1 m2 n2 P1 P2 F1 F2 :\n m1 = m2 -> n1 = n2 ->\n (forall i, m1 <= i < n2 -> P1 i = P2 i) ->\n (forall i, P1 i && (m1 <= i < n2) -> F1 i = F2 i) ->\n \\big[op/idx]_(m1 <= i < n1 | P1 i) F1 i\n = \\big[op/idx]_(m2 <= i < n2 | P2 i) F2 i.\n\n(*This lemma states that if two functions produce equal outputs for all natural numbers within a specified range, then the big operations performed with these functions over that range will yield the same result.*)\nLemma eq_big_nat m n F1 F2 :\n (forall i, m <= i < n -> F1 i = F2 i) ->\n \\big[op/idx]_(m <= i < n) F1 i = \\big[op/idx]_(m <= i < n) F2 i.\n\n(*This lemma asserts that if the starting bound of a numerical range is greater than or equal to its ending bound, the big operation over this empty range evaluates to the identity element.*)\nLemma big_geq m n (P : pred nat) F :\n m >= n -> \\big[op/idx]_(m <= i < n | P i) F i = idx.\n\n(*This lemma provides a recursive formula for computing a big operation over a non-empty range of natural numbers. The result is found by combining the function's value at the starting number with the operation's result on the rest of the range, only if the starting number satisfies the predicate; otherwise, the result is simply the operation's result on the rest of the range.*)\nLemma big_ltn_cond m n (P : pred nat) F :\n m < n -> let x := \\big[op/idx]_(m.+1 <= i < n | P i) F i in\n \\big[op/idx]_(m <= i < n | P i) F i = if P m then op (F m) x else x.\n\n(*This lemma provides a recursive formula for computing a big operation over a non-empty range of natural numbers without an explicit predicate, by combining the function's value at the starting number with the result of the operation on the rest of the range.*)\nLemma big_ltn m n F :\n m < n ->\n \\big[op/idx]_(m <= i < n) F i = op (F m) (\\big[op/idx]_(m.+1 <= i < n) F i).\n\n(*This lemma provides a change of variable rule for big operations over a range of natural numbers. It equates an operation over a shifted range to an operation over an un-shifted range of the same length, where the index variable within the predicate and function is adjusted by the shift amount.*)\nLemma big_addn m n a (P : pred nat) F :\n \\big[op/idx]_(m + a <= i < n | P i) F i =\n \\big[op/idx]_(m <= i < n - a | P (i + a)) F (i + a).\n\n(*This lemma is a special case of index shifting for big operations, showing that an operation over a range starting from a number plus one is equivalent to an operation over a range starting from the original number but ending one step earlier, with the index shifted by one in the predicate and function.*)\nLemma big_add1 m n (P : pred nat) F :\n \\big[op/idx]_(m.+1 <= i < n | P i) F i =\n \\big[op/idx]_(m <= i < n.-1 | P (i.+1)) F (i.+1).\n\n(*This lemma provides an alternative recursive decomposition for a big operation over a range of natural numbers, expressing the operation over a range ending at a number plus one as the combination of the function's value at the start of the range and the result of a similar operation over a smaller range applied to a shifted function.*)\nLemma big_nat_recl n m F : m <= n ->\n \\big[op/idx]_(m <= i < n.+1) F i =\n op (F m) (\\big[op/idx]_(m <= i < n) F i.+1).\n\n(*This lemma establishes an equivalence between a big operation over the range of natural numbers from zero up to a given bound and the corresponding big operation over the finite type of ordinals less than that same bound.*)\nLemma big_mkord n (P : pred nat) F :\n \\big[op/idx]_(0 <= i < n | P i) F i = \\big[op/idx]_(i < n | P i) F i.\n\n(*This lemma shows that a big operation over the finite type of ordinals less than a number plus one is equivalent to a big operation over the range of natural numbers from zero up to that number plus one, using a function to convert the natural number index to an ordinal.*)\nLemma big_mknat n (P : pred 'I_n.+1) F :\n \\big[op/idx]_(i < n.+1 | P i) F i\n = \\big[op/idx]_(0 <= i < n.+1 | P (inord i)) F (inord i).\n\n(*This lemma states that a big operation over a given range of natural numbers is equivalent to performing the operation over a wider range, provided the predicate is strengthened with a condition that restricts the index to the original, smaller range.*)\nLemma big_nat_widen m n1 n2 (P : pred nat) F :\n n1 <= n2 ->\n \\big[op/idx]_(m <= i < n1 | P i) F i\n = \\big[op/idx]_(m <= i < n2 | P i && (i < n1)) F i.\n\n(*This lemma states that a cumulative operation over a range of natural numbers from a starting value up to, but not including, a bound `n1`, where elements satisfy a given predicate, is equivalent to performing the same operation over a wider range up to `n2` (where `n1` is less than or equal to `n2`), but with an additional condition that the iterated number must also be less than `n1`.*)\nLemma big_ord_widen_cond n1 n2 (P : pred nat) (F : nat -> R) :\n n1 <= n2 ->\n \\big[op/idx]_(i < n1 | P i) F i\n = \\big[op/idx]_(i < n2 | P i && (i < n1)) F i.\n\n(*This lemma states that a cumulative operation over a range of natural numbers up to, but not including, a value `n1` is equivalent to performing the same operation over a wider range up to `n2` (where `n1` is less than or equal to `n2`), with an added condition that the iterated number must also be less than `n1`.*)\nLemma big_ord_widen n1 n2 (F : nat -> R) :\n n1 <= n2 ->\n \\big[op/idx]_(i < n1) F i = \\big[op/idx]_(i < n2 | i < n1) F i.\n\n(*This lemma states that a cumulative operation over a range of natural numbers less than `n1` plus one, where each number satisfies a given predicate, is equivalent to performing the operation over a wider range up to `n2` (where `n1` is less than `n2`), with an additional condition that the iterated number must be less than or equal to `n1`.*)\nLemma big_ord_widen_leq n1 n2 (P : pred 'I_(n1.+1)) F :\n n1 < n2 ->\n \\big[op/idx]_(i < n1.+1 | P i) F i\n = \\big[op/idx]_(i < n2 | P (inord i) && (i <= n1)) F (inord i).\n\n(*This lemma states that a cumulative operation over an empty range of natural numbers, specifically for indices less than zero, evaluates to the identity element of the operation.*)\nLemma big_ord0 P F : \\big[op/idx]_(i < 0 | P i) F i = idx.\n\n(*This lemma states that a cumulative operation over the elements of a sequence, formed by filtering a tuple with a boolean mask, is equivalent to a cumulative operation over the indices of the tuple, where the operation's body is applied only if the mask is true at that index and the element at that index satisfies a given predicate.*)\nLemma big_mask_tuple I n m (t : n.-tuple I) (P : pred I) F :\n \\big[op/idx]_(i <- mask m t | P i) F i\n = \\big[op/idx]_(i < n | nth false m i && P (tnth t i)) F (tnth t i).\n\n(*This lemma states that a cumulative operation over a sequence filtered by a boolean mask is equivalent to an operation over the indices of the original sequence, where the body of the operation is evaluated only for indices where the mask is true and a given predicate holds for the corresponding element.*)\nLemma big_mask I r m (P : pred I) (F : I -> R) (r_ := tnth (in_tuple r)) :\n \\big[op/idx]_(i <- mask m r | P i) F i\n = \\big[op/idx]_(i < size r | nth false m i && P (r_ i)) F (r_ i).\n\n(*This lemma states that a cumulative operation over the elements of a sequence that satisfy a given predicate is equivalent to an operation over the indices of that sequence, where the body of the operation is applied to the element at each index, provided that element satisfies the predicate.*)\nLemma big_tnth I r (P : pred I) F (r_ := tnth (in_tuple r)) :\n \\big[op/idx]_(i <- r | P i) F i\n = \\big[op/idx]_(i < size r | P (r_ i)) (F (r_ i)).\n\n(*This lemma states that for a sequence with unique elements, a cumulative operation over its indices is equivalent to an operation over its elements, where the body function is composed with a function that maps each element back to its unique index.*)\nLemma big_index_uniq (I : eqType) (r : seq I) (E : 'I_(size r) -> R) :\n uniq r ->\n \\big[op/idx]_i E i = \\big[op/idx]_(x <- r) oapp E idx (insub (index x r)).\n\n(*This lemma states that a cumulative operation over the elements of a tuple that satisfy a given predicate is equivalent to an operation over the indices of the tuple, where the body is applied to the element at each index if that element satisfies the predicate.*)\nLemma big_tuple I n (t : n.-tuple I) (P : pred I) F :\n \\big[op/idx]_(i <- t | P i) F i\n = \\big[op/idx]_(i < n | P (tnth t i)) F (tnth t i).\n\n(*This lemma states that a cumulative operation over a range of natural numbers up to `n2`, with an added condition that the number is also less than `n1` (where `n1` is less than or equal to `n2`), is equivalent to an operation over the narrower range up to `n1`, where the body function is applied to the index appropriately mapped from the smaller range to the larger one.*)\nLemma big_ord_narrow_cond n1 n2 (P : pred 'I_n2) F (le_n12 : n1 <= n2) :\n let w := widen_ord le_n12 in\n \\big[op/idx]_(i < n2 | P i && (i < n1)) F i\n = \\big[op/idx]_(i < n1 | P (w i)) F (w i).\n\n(*This lemma states that a cumulative operation over a range of natural numbers up to `n2` plus one, with a condition that the number is less than or equal to `n1`, is equivalent to an operation over the narrower range up to `n1` plus one. The body of the operation is applied to the index mapped from the smaller range to the larger one, provided `n1` is less than or equal to `n2`.*)\nLemma big_ord_narrow_cond_leq n1 n2 (P : pred _) F (le_n12 : n1 <= n2) :\n let w := @widen_ord n1.+1 n2.+1 le_n12 in\n \\big[op/idx]_(i < n2.+1 | P i && (i <= n1)) F i\n = \\big[op/idx]_(i < n1.+1 | P (w i)) F (w i).\n\n(*This lemma states that a cumulative operation over a wide range of natural numbers up to `n2`, restricted by the condition that the number must be less than `n1` (where `n1` is less than or equal to `n2`), is equivalent to an operation over the narrower range up to `n1`. The body of the operation is applied to the index mapped from the smaller range.*)\nLemma big_ord_narrow n1 n2 F (le_n12 : n1 <= n2) :\n let w := widen_ord le_n12 in\n \\big[op/idx]_(i < n2 | i < n1) F i = \\big[op/idx]_(i < n1) F (w i).\n\n(*This lemma states that a cumulative operation over a range of natural numbers up to `n2` plus one, with the condition that the number is less than or equal to `n1`, is equivalent to an operation over the range up to `n1` plus one. This holds when `n1` is less than or equal to `n2`, and the function body takes a mapped index.*)\nLemma big_ord_narrow_leq n1 n2 F (le_n12 : n1 <= n2) :\n let w := @widen_ord n1.+1 n2.+1 le_n12 in\n \\big[op/idx]_(i < n2.+1 | i <= n1) F i = \\big[op/idx]_(i < n1.+1) F (w i).\n\n(*This lemma provides a recursive definition for a cumulative operation over a range of natural numbers up to `n` plus one. It expresses the operation as the combination of the result for the first element and the result of the cumulative operation over the remaining `n` elements, with indices appropriately lifted.*)\nLemma big_ord_recl n F :\n \\big[op/idx]_(i < n.+1) F i =\n op (F ord0) (\\big[op/idx]_(i < n) F (@lift n.+1 ord0 i)).\n\n(*This lemma states that a cumulative operation over a sequence consisting of `n` repetitions of an element, with an additional predicate, evaluates to `n` iterations of the operation applied to the function of that element if the predicate holds for it, and to the identity element otherwise.*)\nLemma big_nseq_cond I n a (P : pred I) F :\n \\big[op/idx]_(i <- nseq n a | P i) F i\n = if P a then iter n (op (F a)) idx else idx.\n\n(*This lemma states that a cumulative operation over a sequence consisting of `n` repetitions of an element is equivalent to iterating the operation on the function of that element `n` times, starting from the identity element.*)\nLemma big_nseq I n a (F : I -> R):\n \\big[op/idx]_(i <- nseq n a) F i = iter n (op (F a)) idx.\n\nEnd Extensionality.\n\n(*This is an inductive specification for a finite sequence that serves as a valid enumeration for a subset of a finite type defined by a predicate. It asserts that the sequence is a permutation of the canonical enumeration of the subset, contains exactly the elements satisfying the predicate, has no duplicates, and that cumulative operations over the sequence are equivalent to operations over the subset.*)\nVariant big_enum_spec (I : finType) (P : pred I) : seq I -> Type :=\n BigEnumSpec e of\n forall R idx op (F : I -> R),\n \\big[op/idx]_(i <- e) F i = \\big[op/idx]_(i | P i) F i\n & uniq e /\\ (forall i, i \\in e = P i)\n & (let cP := [pred i | P i] in perm_eq e (enum cP) /\\ size e = #|cP|)\n : big_enum_spec P e.\n\n(*This lemma demonstrates that a valid enumeration for the purpose of a cumulative operation over a subset of a finite type can be constructed by filtering the canonical enumeration of the entire type with the defining predicate of the subset.*)\nLemma big_enumP I P : big_enum_spec P (filter P (index_enum I)).\n\nSection BigConst.\n\nVariables (R : Type) (idx : R) (op : R -> R -> R).\n\n(*This lemma states that a cumulative operation over a sequence with a constant function body is equivalent to iterating the binary operation with the constant value a number of times equal to how many elements in the sequence satisfy a given predicate.*)\nLemma big_const_seq I r (P : pred I) x :\n \\big[op/idx]_(i <- r | P i) x = iter (count P r) (op x) idx.\n\n(*This lemma states that a cumulative operation over a finite set with a constant function body is equivalent to iterating the binary operation with the constant value a number of times equal to the cardinality of the set.*)\nLemma big_const (I : finType) (A : {pred I}) x :\n \\big[op/idx]_(i in A) x = iter #|A| (op x) idx.\n\n(*This lemma states that a cumulative operation over a range of natural numbers from `m` to `n` with a constant function body is equivalent to iterating the binary operation with the constant value a number of times equal to the difference between `n` and `m`.*)\nLemma big_const_nat m n x :\n \\big[op/idx]_(m <= i < n) x = iter (n - m) (op x) idx.\n\n(*This lemma states that a cumulative operation over a range of `n` ordinals with a constant function body is equivalent to iterating the binary operation with the constant value `n` times.*)\nLemma big_const_ord n x :\n \\big[op/idx]_(i < n) x = iter n (op x) idx.\n\nEnd BigConst.\n\nSection Plain.\n\nVariable R : Type.\nVariable op : R -> R -> R.\nVariable x : R.\n\n(*This lemma states that a cumulative operation over a sequence containing a single element results in applying the binary operation to the function of that element and the initial value.*)\nLemma big_seq1_id I (i : I) (F : I -> R) :\n \\big[op/x]_(j <- [:: i]) F j = op (F i) x.\n\n(*This lemma states that a cumulative operation over a range of natural numbers containing a single element, from `n` up to `n` plus one, results in applying the binary operation to the function of `n` and the initial value.*)\nLemma big_nat1_id n F : \\big[op/x]_(n <= i < n.+1) F i = op (F n) x.\n\n(*This lemma states that a cumulative operation over a domain restricted by a predicate checking for equality with a specific element results in applying the binary operation to the function of that element and the initial value.*)\nLemma big_pred1_eq_id (I : finType) (i : I) F :\n \\big[op/x]_(j | j == i) F j = op (F i) x.\n\n(*This lemma states that if a predicate is equivalent to one that is true only for a single specific element, then the cumulative operation over that predicate simplifies to applying the binary operation to the function of that specific element and the initial value.*)\nLemma big_pred1_id (I : finType) i (P : pred I) F :\n P =1 pred1 i -> \\big[op/x]_(j | P j) F j = op (F i) x.\n\nEnd Plain.\n\nSection SemiGroupProperties.\n\nVariable R : Type.\n\n(*This proposition asserts that the binary operation is associative, meaning that the order of evaluation does not matter when combining three elements.*)\n#[local] Notation opA := SemiGroup.opA.\n(*This proposition asserts that the binary operation is commutative, meaning that swapping the order of the two operands does not change the result.*)\n#[local] Notation opC := SemiGroup.opC.\n\nSection Id.\n\nVariable op : SemiGroup.law R.\n\nVariable x : R.\nHypothesis opxx : op x x = x.\n\n(*This lemma states that for an operation that is idempotent with respect to a value `x` (meaning applying the operation to `x` and `x` yields `x`), a cumulative operation with a constant function body that always returns `x` will also result in `x`.*)\nLemma big_const_idem I (r : seq I) P : \\big[op/x]_(i <- r | P i) x = x.\n\n(*This lemma states that if a function evaluates to a specific value for all inputs that satisfy a given predicate, then the big operator that combines these function values over a sequence, filtered by the same predicate, will also result in that same value, assuming the operation is idempotent.*)\nLemma big1_idem I r (P : pred I) F :\n (forall i, P i -> F i = x) -> \\big[op/x]_(i <- r | P i) F i = x.\n\n(*This lemma states that applying a binary operation to the result of a big operator computation and its neutral element yields the result of the big operator itself.*)\nLemma big_id_idem I (r : seq I) P F :\n op (\\big[op/x]_(i <- r | P i) F i) x = \\big[op/x]_(i <- r | P i) F i.\n\nEnd Id.\n\nSection Abelian.\n\nVariable op : SemiGroup.com_law R.\n\n(*This definition establishes that a commutative and associative binary operation is also left-commutative, meaning that the order of the first two operands in a nested application can be swapped.*)\nLet opCA : left_commutative op.\n\nVariable x : R.\n\n(*This lemma states that for a commutative binary operation, the result of a big operator over a sequence containing a specific element can be computed by conditionally combining the function's value at that element with the result of the big operator over the sequence with that element removed. The combination happens if the element satisfies the filtering predicate; otherwise, the result is simply the computation over the rest of the sequence.*)\nLemma big_rem_AC (I : eqType) (r : seq I) z (P : pred I) F : z \\in r ->\n \\big[op/x]_(y <- r | P y) F y\n = if P z then op (F z) (\\big[op/x]_(y <- rem z r | P y) F y)\n else \\big[op/x]_(y <- rem z r | P y) F y.\n\n(*This lemma states that for an idempotent binary operation, the result of a big operator over a sequence is identical to the result of the same big operator over that sequence with all duplicate elements removed.*)\nLemma big_undup (I : eqType) (r : seq I) (P : pred I) F :\n idempotent_op op ->\n \\big[op/x]_(i <- undup r | P i) F i = \\big[op/x]_(i <- r | P i) F i.\n\n(*This lemma states that for a commutative binary operation, the result of a big operator is unchanged if the sequence of iteration is replaced by any of its permutations.*)\nLemma perm_big (I : eqType) r1 r2 (P : pred I) F :\n perm_eq r1 r2 ->\n \\big[op/x]_(i <- r1 | P i) F i = \\big[op/x]_(i <- r2 | P i) F i.\n\n(*This lemma states that for a commutative binary operation, computing a big operator over an enumeration of a finite set, with a given predicate, is equivalent to computing the big operator over the elements of the set itself, filtered by the same predicate.*)\nLemma big_enum_cond (I : finType) (A : {pred I}) (P : pred I) F :\n \\big[op/x]_(i <- enum A | P i) F i = \\big[op/x]_(i in A | P i) F i.\n\n(*This lemma states that for a commutative binary operation, computing a big operator over an enumeration of a finite set is equivalent to computing the big operator over the elements of the set itself.*)\nLemma big_enum (I : finType) (A : {pred I}) F :\n \\big[op/x]_(i <- enum A) F i = \\big[op/x]_(i in A) F i.\n\n(*This lemma states that for a commutative binary operation, if a sequence contains no duplicate elements, computing a big operator by iterating over the sequence is equivalent to computing it by iterating over the set of elements in that sequence.*)\nLemma big_uniq (I : finType) (r : seq I) F :\n uniq r -> \\big[op/x]_(i <- r) F i = \\big[op/x]_(i in r) F i.\n\n(*This lemma states that for a commutative binary operation over a finite type, if a specific element satisfies a given predicate, the big operator can be computed by combining the function's value at that element with the result of the big operator over all other elements that also satisfy the predicate.*)\nLemma bigD1 (I : finType) j (P : pred I) F :\n P j -> \\big[op/x]_(i | P i) F i\n = op (F j) (\\big[op/x]_(i | P i && (i != j)) F i).\n\nArguments bigD1 [I] j [P F].\n\n(*This lemma states that for a commutative binary operation, if a specific element is present in a sequence with no duplicates, the big operator over that sequence can be computed by combining the function's value at that element with the result of the big operator over the same sequence, but excluding that element.*)\nLemma bigD1_seq (I : eqType) (r : seq I) j F :\n j \\in r -> uniq r ->\n \\big[op/x]_(i <- r) F i = op (F j) (\\big[op/x]_(i <- r | i != j) F i).\n\n(*This lemma provides a change of variables formula for a big operator with a commutative operation, stating that computing over the image of a finite set under some function, with a given predicate on the image, is equivalent to computing over the domain set, with the predicate and function composed accordingly.*)\nLemma big_image_cond I (J : finType) (h : J -> I) (A : pred J) (P : pred I) F :\n \\big[op/x]_(i <- [seq h j | j in A] | P i) F i\n = \\big[op/x]_(j in A | P (h j)) F (h j).\n\n(*This lemma provides a change of variables formula for a big operator with a commutative operation, stating that computing over the image of a finite set under some function is equivalent to computing over the domain set with the function composed into the expression.*)\nLemma big_image I (J : finType) (h : J -> I) (A : pred J) F :\n \\big[op/x]_(i <- [seq h j | j in A]) F i = \\big[op/x]_(j in A) F (h j).\n\n(*This lemma states that if an element belongs to a finite set, the cardinality of that set is equal to one plus the cardinality of the set containing all other elements.*)\nLemma cardD1x (I : finType) (A : pred I) j :\n A j -> #|SimplPred A| = 1 + #|[pred i | A i & i != j]|.\n\nArguments cardD1x [I A].\n\n(*This lemma provides a reindexing rule for a big operator with a commutative operation, showing its equivalence when changing the index from one finite type to another, provided there is a function and a partial inverse that maps elements back to their original index within a specified domain.*)\nLemma reindex_omap (I J : finType) (h : J -> I) h' (P : pred I) F :\n (forall i, P i -> omap h (h' i) = some i) ->\n \\big[op/x]_(i | P i) F i =\n \\big[op/x]_(j | P (h j) && (h' (h j) == some j)) F (h j).\n\nArguments reindex_omap [I J] h h' [P F].\n\n(*This lemma provides a reindexing rule for a big operator with a commutative operation, showing its equivalence when the index is changed from one finite type to another, under the condition that there exists a function and a right-inverse function for it on a given subdomain.*)\nLemma reindex_onto (I J : finType) (h : J -> I) h' (P : pred I) F :\n (forall i, P i -> h (h' i) = i) ->\n \\big[op/x]_(i | P i) F i =\n \\big[op/x]_(j | P (h j) && (h' (h j) == j)) F (h j).\n\nArguments reindex_onto [I J] h h' [P F].\n\n(*This lemma provides a reindexing rule for a big operator with a commutative operation, stating that if a function is a bijection on the subset of elements satisfying a predicate, then the computation over the original indices is equivalent to the computation over the new indices, with the function and predicate composed appropriately.*)\nLemma reindex (I J : finType) (h : J -> I) (P : pred I) F :\n {on [pred i | P i], bijective h} ->\n \\big[op/x]_(i | P i) F i = \\big[op/x]_(j | P (h j)) F (h j).\n\nArguments reindex [I J] h [P F].\n\n(*This lemma provides a reindexing rule for a big operator with a commutative operation, stating that if an injective function maps a finite type to itself, the computation over the original indices is equivalent to the computation over the re-indexed values, with the predicate composed with the function.*)\nLemma reindex_inj (I : finType) (h : I -> I) (P : pred I) F :\n injective h -> \\big[op/x]_(i | P i) F i = \\big[op/x]_(j | P (h j)) F (h j).\n\nArguments reindex_inj [I h P F].\n\n(*This lemma states that for a commutative binary operation on a range of ordinals, if a specific ordinal satisfies a given predicate, the big operator can be computed by combining the function's value at that ordinal with the result of the big operator over the remaining ordinals, which are appropriately lifted to skip the selected one.*)\nLemma bigD1_ord n j (P : pred 'I_n) F :\n P j -> \\big[op/x]_(i < n | P i) F i\n = op (F j) (\\big[op/x]_(i < n.-1 | P (lift j i)) F (lift j i)).\n\n(*This lemma states that for a commutative binary operation, computing a big operator over the elements of a finite set with a given predicate is equivalent to computing it over the range of indices from zero up to the cardinality of the set, where each index is mapped to the corresponding element in the set's canonical enumeration.*)\nLemma big_enum_val_cond (I : finType) (A : pred I) (P : pred I) F :\n \\big[op/x]_(x in A | P x) F x =\n \\big[op/x]_(i < #|A| | P (enum_val i)) F (enum_val i).\n\nArguments big_enum_val_cond [I A] P F.\n\n(*This lemma states that for a commutative binary operation, computing a big operator over a range of indices up to the cardinality of a finite set is equivalent to computing it over the elements of the set itself, where the index in the original expression is replaced by the rank of the corresponding element in the set's canonical enumeration.*)\nLemma big_enum_rank_cond (I : finType) (A : pred I) z (zA : z \\in A) P F\n (h := enum_rank_in zA) :\n \\big[op/x]_(i < #|A| | P i) F i = \\big[op/x]_(s in A | P (h s)) F (h s).\n\nArguments big_enum_rank_cond [I A z] zA P F.\n\n(*This lemma states that for a commutative binary operation, the result of a big operator over a range of natural numbers is unchanged if the order of iteration is reversed.*)\nLemma big_nat_rev m n P F :\n \\big[op/x]_(m <= i < n | P i) F i\n = \\big[op/x]_(m <= i < n | P (m + n - i.+1)) F (m + n - i.+1).\n\n(*This lemma states that for a commutative binary operation, computing a big operator over a range of natural numbers is equivalent to computing it over a corresponding range starting from zero, with the index transformed to reflect a reversed order of iteration.*)\nLemma big_rev_mkord m n P F :\n \\big[op/x]_(m <= k < n | P k) F k\n = \\big[op/x]_(k < n - m | P (n - k.+1)) F (n - k.+1).\n\nSection Id.\n\nHypothesis opxx : op x x = x.\n\n(*This lemma states that computing a big operator over a filtered sequence is equivalent to computing it over the unfiltered sequence using a function that returns the original value if the predicate is true, and the neutral element of the operation otherwise.*)\nLemma big_mkcond_idem I r (P : pred I) F :\n \\big[op/x]_(i <- r | P i) F i = \\big[op/x]_(i <- r) (if P i then F i else x).\n\n(*This lemma states that a big operator filtered by the conjunction of two predicates is equivalent to a big operator filtered only by the first predicate, where the function argument is replaced by a conditional expression that returns the original function's value if the second predicate holds, and the neutral element otherwise.*)\nLemma big_mkcondr_idem I r (P Q : pred I) F :\n \\big[op/x]_(i <- r | P i && Q i) F i =\n \\big[op/x]_(i <- r | P i) (if Q i then F i else x).\n\n(*This lemma states that a big operator filtered by the conjunction of two predicates is equivalent to a big operator filtered only by the second predicate, where the function argument is replaced by a conditional expression that returns the original function's value if the first predicate holds, and the neutral element otherwise.*)\nLemma big_mkcondl_idem I r (P Q : pred I) F :\n \\big[op/x]_(i <- r | P i && Q i) F i =\n \\big[op/x]_(i <- r | Q i) (if P i then F i else x).\n\n(*This lemma states that if a function evaluates to the neutral element for all inputs that do not satisfy a given predicate, then computing a big operator over a sequence filtered by that predicate is equivalent to computing it over the entire unfiltered sequence.*)\nLemma big_rmcond_idem I (r : seq I) (P : pred I) F :\n (forall i, ~~ P i -> F i = x) ->\n \\big[op/x]_(i <- r | P i) F i = \\big[op/x]_(i <- r) F i.\n\n(*This lemma states that if a function evaluates to the neutral element for all elements in a sequence that do not satisfy a given predicate, then computing a big operator over that sequence filtered by the predicate is equivalent to computing it over the entire sequence without the filter.*)\nLemma big_rmcond_in_idem (I : eqType) (r : seq I) (P : pred I) F :\n (forall i, i \\in r -> ~~ P i -> F i = x) ->\n \\big[op/x]_(i <- r | P i) F i = \\big[op/x]_(i <- r) F i.\n\n(*This lemma states that for an associative binary operation, the result of a big operator over the concatenation of two sequences is equal to the operation applied to the results of the big operator computed over each sequence individually.*)\nLemma big_cat_idem I r1 r2 (P : pred I) F :\n \\big[op/x]_(i <- r1 ++ r2 | P i) F i =\n op (\\big[op/x]_(i <- r1 | P i) F i) (\\big[op/x]_(i <- r2 | P i) F i).\n\n(*This lemma sets up a property for a big operator that iterates over dependent pairs of elements, where the type of the second element in each pair depends on the value of the first. The setup involves a function that maps these dependent pairs to a common type.*)\nLemma big_allpairs_dep_idem I1 (I2 : I1 -> Type) J (h : forall i1, I2 i1 -> J)\n (r1 : seq I1) (r2 : forall i1, seq (I2 i1)) (F : J -> R) :\n \\big[op/x]_(i <- [seq h i1 i2 | i1 <- r1, i2 <- r2 i1]) F i =\n \\big[op/x]_(i1 <- r1) \\big[op/x]_(i2 <- r2 i1) F (h i1 i2).\n\n(*This lemma states that for an idempotent, associative, and commutative binary operation, an iterated application of this operation over a sequence of all pairs formed from two input sequences is equivalent to a nested application. The nested form consists of an outer iteration over the first sequence, where each step combines the result of an inner iterated operation over the second sequence.*)\nLemma big_allpairs_idem I1 I2 (r1 : seq I1) (r2 : seq I2) F :\n \\big[op/x]_(i <- [seq (i1, i2) | i1 <- r1, i2 <- r2]) F i =\n \\big[op/x]_(i1 <- r1) \\big[op/x]_(i2 <- r2) F (i1, i2).\n\n(*This lemma states that an iterated binary operation over a range of natural numbers from a start to an end value can be split at an intermediate natural number. The result is equivalent to applying the operation to the intermediate results of the operation on the two contiguous sub-ranges.*)\nLemma big_cat_nat_idem n m p (P : pred nat) F : m <= n -> n <= p ->\n \\big[op/x]_(m <= i < p | P i) F i =\n op (\\big[op/x]_(m <= i < n | P i) F i) (\\big[op/x]_(n <= i < p | P i) F i).\n\n(*This lemma states that for an idempotent, associative, and commutative binary operation, an iterated application of this operation to terms that are themselves formed by the same operation is equivalent to applying the operation to the results of two separate iterated operations, one for each of the component functions.*)\nLemma big_split_idem I r (P : pred I) F1 F2 :\n \\big[op/x]_(i <- r | P i) op (F1 i) (F2 i) =\n op (\\big[op/x]_(i <- r | P i) F1 i) (\\big[op/x]_(i <- r | P i) F2 i).\n\n(*This lemma states that for an associative, commutative, and idempotent binary operation, an iterated application over a sequence of terms, where each term is formed by applying the operation to a function's output and a fixed value, yields the same result as the iterated operation applied directly to the function's outputs.*)\nLemma big_id_idem_AC I (r : seq I) P F :\n \\big[op/x]_(i <- r | P i) op (F i) x = \\big[op/x]_(i <- r | P i) F i.\n\n(*This lemma states that for an idempotent, associative, and commutative binary operation, an iterated application of the operation over a filtered sequence can be computed by partitioning the sequence based on an additional predicate. The final result is obtained by applying the operation to the results of iterating over the two disjoint subsequences.*)\nLemma bigID_idem I r (a P : pred I) F :\n \\big[op/x]_(i <- r | P i) F i =\n op (\\big[op/x]_(i <- r | P i && a i) F i)\n (\\big[op/x]_(i <- r | P i && ~~ a i) F i).\n\nArguments bigID_idem [I r].\n\n(*This lemma asserts that for an idempotent, associative, and commutative binary operation, the iterated operation over the union of two disjoint sets of indices is equal to the operation applied to the results of iterating over each set individually.*)\nLemma bigU_idem (I : finType) (A B : pred I) F :\n [disjoint A & B] ->\n \\big[op/x]_(i in [predU A & B]) F i =\n op (\\big[op/x]_(i in A) F i) (\\big[op/x]_(i in B) F i).\n\n(*This lemma states that for an idempotent, associative, and commutative binary operation, an iterated operation over a filtered sequence can be re-expressed as a nested iteration. The outer iteration runs over a finite type, and for each element of that type, the inner iteration runs over the elements of the original sequence that map to it under a given projection function.*)\nLemma partition_big_idem I (s : seq I)\n (J : finType) (P : pred I) (p : I -> J) (Q : pred J) F :\n (forall i, P i -> Q (p i)) ->\n \\big[op/x]_(i <- s | P i) F i =\n \\big[op/x]_(j : J | Q j) \\big[op/x]_(i <- s | (P i) && (p i == j)) F i.\n\nArguments partition_big_idem [I s J P] p Q [F].\n\n(*This lemma shows how to flatten a nested iterated operation over dependent types. It states that for an idempotent, associative, and commutative operation, a nested iteration\u2014where the inner loop's range depends on the outer loop's index\u2014is equivalent to a single iteration over the dependent sum type (sigma type) that combines both indices.*)\nLemma sig_big_dep_idem (I : finType) (J : I -> finType)\n (P : pred I) (Q : forall {i}, pred (J i)) (F : forall {i}, J i -> R) :\n \\big[op/x]_(i | P i) \\big[op/x]_(j : J i | Q j) F j =\n \\big[op/x]_(p : {i : I & J i} | P (tag p) && Q (tagged p)) F (tagged p).\n\n(*This lemma states that for an idempotent, associative, and commutative operation, a nested iteration over two finite types, where the inner iteration's predicate depends on the outer loop's index, is equivalent to a single iteration over their Cartesian product. The predicate for the single iteration combines the predicates from both original loops.*)\nLemma pair_big_dep_idem (I J : finType) (P : pred I) (Q : I -> pred J) F :\n \\big[op/x]_(i | P i) \\big[op/x]_(j | Q i j) F i j =\n \\big[op/x]_(p | P p.1 && Q p.1 p.2) F p.1 p.2.\n\n(*This lemma states that for an idempotent, associative, and commutative operation, a nested iteration over two independent filtered ranges of finite types is equivalent to a single iteration over their Cartesian product, where the new predicate is the conjunction of the original predicates applied to the components of the pair.*)\nLemma pair_big_idem (I J : finType) (P : pred I) (Q : pred J) F :\n \\big[op/x]_(i | P i) \\big[op/x]_(j | Q j) F i j =\n \\big[op/x]_(p | P p.1 && Q p.2) F p.1 p.2.\n\n(*This lemma demonstrates a Fubini-style property, stating that for an idempotent, associative, and commutative operation, a nested iteration over two finite types is equivalent to a single iteration over their Cartesian product type.*)\nLemma pair_bigA_idem (I J : finType) (F : I -> J -> R) :\n \\big[op/x]_i \\big[op/x]_j F i j = \\big[op/x]_p F p.1 p.2.\n\n(*This lemma provides a Fubini-style rule for exchanging the order of nested iterations for an idempotent, associative, and commutative operation. It states that an iteration over a sequence followed by a dependent inner iteration can be swapped into an outer iteration over the second sequence's type, with a new inner iteration whose predicate combines the original conditions.*)\nLemma exchange_big_dep_idem I J rI rJ (P : pred I) (Q : I -> pred J)\n (xQ : pred J) F :\n (forall i j, P i -> Q i j -> xQ j) ->\n \\big[op/x]_(i <- rI | P i) \\big[op/x]_(j <- rJ | Q i j) F i j =\n \\big[op/x]_(j <- rJ | xQ j) \\big[op/x]_(i <- rI | P i && Q i j) F i j.\n\nArguments exchange_big_dep_idem [I J rI rJ P Q] xQ [F].\n\n(*This lemma states the Fubini-style theorem for exchanging the order of independent nested iterations. For an idempotent, associative, and commutative operation, the result is the same regardless of which of the two independent filtered sequences is iterated over first.*)\nLemma exchange_big_idem I J rI rJ (P : pred I) (Q : pred J) F :\n \\big[op/x]_(i <- rI | P i) \\big[op/x]_(j <- rJ | Q j) F i j =\n \\big[op/x]_(j <- rJ | Q j) \\big[op/x]_(i <- rI | P i) F i j.\n\n(*This lemma specializes the Fubini-style exchange rule for nested iterations over ranges of natural numbers. It allows swapping the order of a dependent nested iteration, where both loops are over natural number intervals, for an idempotent, associative, and commutative operation.*)\nLemma exchange_big_dep_nat_idem m1 n1 m2 n2 (P : pred nat) (Q : rel nat)\n (xQ : pred nat) F :\n (forall i j, m1 <= i < n1 -> m2 <= j < n2 -> P i -> Q i j -> xQ j) ->\n \\big[op/x]_(m1 <= i < n1 | P i) \\big[op/x]_(m2 <= j < n2 | Q i j) F i j =\n \\big[op/x]_(m2 <= j < n2 | xQ j)\n \\big[op/x]_(m1 <= i < n1 | P i && Q i j) F i j.\n\nArguments exchange_big_dep_nat_idem [m1 n1 m2 n2 P Q] xQ [F].\n\n(*This lemma states the Fubini-style theorem for exchanging the order of independent nested iterations over ranges of natural numbers for an idempotent, associative, and commutative operation.*)\nLemma exchange_big_nat_idem m1 n1 m2 n2 (P Q : pred nat) F :\n \\big[op/x]_(m1 <= i < n1 | P i) \\big[op/x]_(m2 <= j < n2 | Q j) F i j =\n \\big[op/x]_(m2 <= j < n2 | Q j) \\big[op/x]_(m1 <= i < n1 | P i) F i j.\n\nEnd Id.\n\nEnd Abelian.\n\nEnd SemiGroupProperties.\nArguments big_undup [R op x I].\nArguments perm_big [R op x I r1 r2].\nArguments bigD1 [R op x I] j [P F].\nArguments reindex_omap [R op x I J] h h' [P F].\nArguments reindex_onto [R op x I J] h h' [P F].\nArguments reindex [R op x I J] h [P F].\nArguments reindex_inj [R op x I h P F].\nArguments big_enum_val_cond [R op x I A] P F.\nArguments big_enum_rank_cond [R op x I A z] zA P F.\n\nSection MonoidProperties.\n\nImport Monoid.Theory.\n\nVariable R : Type.\n\nVariable idx : R.\n(*This notation defines '1' as a local alias for the identity element of the monoid.*)\nLocal Notation \"1\" := idx.\n\nSection Plain.\n\nVariable op : Monoid.law 1.\n\n(*This notation defines '*%M' as a local alias for the binary operation of the monoid.*)\nLocal Notation \"*%M\" := op.\n(**)\nLocal Notation \"x * y\" := (op x y).\n\n(*This lemma states that folding a sequence from the left with a given initial value and a monoid operation is equivalent to performing an iterated monoid operation over the sequence with the initial value prepended, using the monoid's identity as the default value.*)\nLemma foldlE x r : foldl *%M x r = \\big[*%M/1]_(y <- x :: r) y.\n\n(*This lemma states that folding a sequence from the left using the monoid's identity element as the initial value is equivalent to computing the iterated monoid product of the sequence's elements.*)\nLemma foldl_idx r : foldl *%M 1 r = \\big[*%M/1]_(x <- r) x.\n\n(*This lemma asserts that for a non-empty filtered sequence, the value of an iterated monoid operation is independent of the chosen default value, provided the alternative default is a right identity for the monoid operation. The result will be the same as when using the canonical monoid identity.*)\nLemma eq_big_idx_seq idx' I r (P : pred I) F :\n right_id idx' *%M -> has P r ->\n \\big[*%M/idx']_(i <- r | P i) F i = \\big[*%M/1]_(i <- r | P i) F i.\n\n(*This lemma states that for an iteration over a non-empty set of indices from a finite type, the result of the iterated monoid operation is the same whether using the canonical identity or any other right identity as the default value.*)\nLemma eq_big_idx idx' (I : finType) i0 (P : pred I) F :\n P i0 -> right_id idx' *%M ->\n \\big[*%M/idx']_(i | P i) F i = \\big[*%M/1]_(i | P i) F i.\n\n(*This lemma shows how changing the default value of an iterated monoid operation affects the result. It states that computing an iterated product with an arbitrary default value is equivalent to computing it with the monoid's identity as the default and then multiplying the result on the right by the arbitrary default value.*)\nLemma big_change_idx I x r (P : pred I) F :\n \\big[*%M/x]_(j <- r | P j) F j = (\\big[*%M/1]_(j <- r | P j) F j) * x.\n\n(*This lemma states that the iterated monoid product over any sequence where every term is the monoid's identity element is equal to the identity element.*)\nLemma big1_eq I r (P : pred I) : \\big[*%M/1]_(i <- r | P i) 1 = 1.\n\n(*This lemma states that if a function evaluates to the monoid's identity element for all indices in a filtered sequence, then the iterated monoid product of the function's values over that sequence is also the identity element.*)\nLemma big1 I r (P : pred I) F :\n (forall i, P i -> F i = 1) -> \\big[*%M/1]_(i <- r | P i) F i = 1.\n\n(*This lemma asserts that the iterated monoid product of a function over a filtered sequence equals the monoid's identity element, provided that the function is guaranteed to return the identity element for all items in the sequence that satisfy the filter.*)\nLemma big1_seq (I : eqType) r (P : pred I) F :\n (forall i, P i && (i \\in r) -> F i = 1) ->\n \\big[*%M/1]_(i <- r | P i) F i = 1.\n\n(*This lemma states that the iterated monoid product over a singleton sequence is simply the value of the function applied to the single element of the sequence.*)\nLemma big_seq1 I (i : I) F : \\big[*%M/1]_(j <- [:: i]) F j = F i.\n\n(*This lemma provides a recursive formula for computing an iterated monoid product over a sequence. It states that the product over a sequence with an element appended to the end is equal to the product over the original sequence, multiplied on the right by the value associated with the new element if it satisfies the predicate, or by the monoid identity otherwise.*)\nLemma big_rcons I i r (P : pred I) F :\n \\big[*%M/1]_(j <- rcons r i | P j) F j =\n (\\big[*%M/1]_(j <- r | P j) F j) * (if P i then F i else idx).\n\n(*This lemma provides an alternative way to compute a filtered iterated monoid product. It states that iterating over a sequence with a predicate is equivalent to iterating over the entire sequence without a predicate, but applying the function to a term only if it satisfies the predicate, and using the monoid's identity element otherwise.*)\nLemma big_mkcond I r (P : pred I) F :\n \\big[*%M/1]_(i <- r | P i) F i =\n \\big[*%M/1]_(i <- r) (if P i then F i else 1).\n\n(*This lemma simplifies an iterated monoid product where the iterated term is conditional. It states that iterating over a sequence filtered by a predicate, with a body that conditionally uses a function's value or the monoid identity based on a second predicate, is equivalent to iterating over a sequence filtered by the conjunction of both predicates.*)\nLemma big_mkcondr I r (P Q : pred I) F :\n \\big[*%M/1]_(i <- r | P i && Q i) F i =\n \\big[*%M/1]_(i <- r | P i) (if Q i then F i else 1).\n\n(*This lemma states that a cumulative operation over a sequence, filtered by the conjunction of two predicates, is equivalent to performing the operation with only the second predicate, where the accumulated function's value is replaced by the monoid's identity if the first predicate is false.*)\nLemma big_mkcondl I r (P Q : pred I) F :\n \\big[*%M/1]_(i <- r | P i && Q i) F i =\n \\big[*%M/1]_(i <- r | Q i) (if P i then F i else 1).\n\n(*This lemma states that if a function evaluates to the monoid's identity for all elements that do not satisfy a predicate, then a cumulative operation over a sequence with that predicate yields the same result as the operation without the predicate.*)\nLemma big_rmcond I (r : seq I) (P : pred I) F :\n (forall i, ~~ P i -> F i = 1) ->\n \\big[*%M/1]_(i <- r | P i) F i = \\big[*%M/1]_(i <- r) F i.\n\n(*This lemma states that if a function evaluates to the monoid's identity for all elements within a sequence that fail to satisfy a predicate, the cumulative operation over that sequence with the predicate is equivalent to the operation without the predicate.*)\nLemma big_rmcond_in (I : eqType) (r : seq I) (P : pred I) F :\n (forall i, i \\in r -> ~~ P i -> F i = 1) ->\n \\big[*%M/1]_(i <- r | P i) F i = \\big[*%M/1]_(i <- r) F i.\n\n(*This lemma states that a cumulative operation over the concatenation of two sequences is equal to the monoid product of the cumulative operations on each individual sequence.*)\nLemma big_cat I r1 r2 (P : pred I) F :\n \\big[*%M/1]_(i <- r1 ++ r2 | P i) F i =\n \\big[*%M/1]_(i <- r1 | P i) F i * \\big[*%M/1]_(i <- r2 | P i) F i.\n\n(*This lemma states that a cumulative operation over a sequence formed from dependent pairs is equivalent to a nested cumulative operation, where the outer operation iterates over the first sequence and the inner one iterates over the corresponding dependent sequences.*)\nLemma big_allpairs_dep I1 (I2 : I1 -> Type) J (h : forall i1, I2 i1 -> J)\n (r1 : seq I1) (r2 : forall i1, seq (I2 i1)) (F : J -> R) :\n \\big[*%M/1]_(i <- [seq h i1 i2 | i1 <- r1, i2 <- r2 i1]) F i =\n \\big[*%M/1]_(i1 <- r1) \\big[*%M/1]_(i2 <- r2 i1) F (h i1 i2).\n\n(*This lemma states that a cumulative operation over a sequence of all pairs from two independent sequences is equivalent to a nested operation, with the outer one iterating over the first sequence and the inner one over the second.*)\nLemma big_allpairs I1 I2 (r1 : seq I1) (r2 : seq I2) F :\n \\big[*%M/1]_(i <- [seq (i1, i2) | i1 <- r1, i2 <- r2]) F i =\n \\big[*%M/1]_(i1 <- r1) \\big[op/idx]_(i2 <- r2) F (i1, i2).\n\n(*This lemma states that a cumulative operation over a reversed sequence is equivalent to performing the operation over the original sequence using a swapped binary operator.*)\nLemma rev_big_rev I (r : seq I) P F :\n \\big[*%M/1]_(i <- rev r | P i) F i =\n \\big[(fun x y => y * x)/1]_(i <- r | P i) F i.\n\n(*This lemma states that if a predicate over a finite type holds for a specific element, and for any other element satisfying the predicate the given function evaluates to the identity, then the cumulative operation over the whole type filtered by the predicate simplifies to the function's value at that specific element.*)\nLemma big_only1 (I : finType) (i : I) (P : pred I) (F : I -> R) : P i ->\n (forall j, j != i -> P j -> F j = idx) ->\n \\big[op/idx]_(j | P j) F j = F i.\n\n(*This lemma states that a cumulative operation over a finite type, restricted by a predicate checking for equality with a specific element, yields the value of the function at that element.*)\nLemma big_pred1_eq (I : finType) (i : I) F : \\big[*%M/1]_(j | j == i) F j = F i.\n\n(*This lemma states that if a predicate is equivalent to one that is true only for a single specific element of a finite type, the cumulative operation over that predicate simplifies to the function's value at that element.*)\nLemma big_pred1 (I : finType) i (P : pred I) F :\n P =1 pred1 i -> \\big[*%M/1]_(j | P j) F j = F i.\n\n(*This lemma states that a cumulative operation over the range of ordinals strictly less than one results in the value of the function at ordinal zero.*)\nLemma big_ord1 F : \\big[op/idx]_(i < 1) F i = F ord0.\n\n(*This lemma states that a cumulative operation over the range of ordinals strictly less than one with a predicate yields the function's value at ordinal zero if the predicate holds for ordinal zero, and the identity element otherwise.*)\nLemma big_ord1_cond P F :\n \\big[op/idx]_(i < 1 | P i) F i = if P ord0 then F ord0 else idx.\n\n(*This lemma states that a cumulative operation over a range of ordinals, filtered by a predicate checking for equality with a given natural number, results in the function's value at that number if it falls within the range, and the identity element otherwise.*)\nLemma big_ord1_eq (F : nat -> R) i n :\n \\big[op/idx]_(j < n | j == i :> nat) F j = if i < n then F i else idx.\n\n(*This lemma states that a cumulative operation over a range of ordinals, filtered by both a general predicate and an equality check with a natural number, yields the function's value at that number if it is in range and satisfies the predicate, and the identity element otherwise.*)\nLemma big_ord1_cond_eq (F : nat -> R) (P : pred nat) i n :\n \\big[op/idx]_(j < n | P j && (j == i :> nat)) F j =\n if (i < n) && P i then F i else idx.\n\n(*This lemma states that a cumulative operation over a range of natural numbers can be split at an intermediate point, with the total result being the monoid product of the operations on the two sub-ranges.*)\nLemma big_cat_nat n m p (P : pred nat) F : m <= n -> n <= p ->\n \\big[*%M/1]_(m <= i < p | P i) F i =\n (\\big[*%M/1]_(m <= i < n | P i) F i) * (\\big[*%M/1]_(n <= i < p | P i) F i).\n\n(*This lemma states that the lower bound of a summation range over natural numbers can be extended downwards, provided the original lower bound is added as a condition to the predicate.*)\nLemma big_nat_widenl (m1 m2 n : nat) (P : pred nat) F :\n m2 <= m1 ->\n \\big[op/idx]_(m1 <= i < n | P i) F i =\n \\big[op/idx]_(m2 <= i < n | P i && (m1 <= i)) F i.\n\n(*This lemma states that a cumulative operation over a range of natural numbers is equivalent to an operation over a range of ordinals with a correspondingly modified predicate that enforces the original lower bound.*)\nLemma big_geq_mkord (m n : nat) (P : pred nat) F :\n \\big[op/idx]_(m <= i < n | P i) F i =\n \\big[op/idx]_(i < n | P i && (m <= i)) F i.\n\n(*This lemma states that a cumulative operation over a range of natural numbers, filtered by a predicate checking for equality with a given number, evaluates to the function's value at that number if it is in the range, and the identity element otherwise.*)\nLemma big_nat1_eq (F : nat -> R) i m n :\n \\big[op/idx]_(m <= j < n | j == i) F j = if m <= i < n then F i else idx.\n\n(*This lemma states that a cumulative operation over a range of natural numbers, filtered by both a general predicate and an equality condition, evaluates to the function's value at the tested number if it is in range and satisfies the predicate, and the identity otherwise.*)\nLemma big_nat1_cond_eq (F : nat -> R) (P : pred nat) i m n :\n \\big[op/idx]_(m <= j < n | P j && (j == i)) F j =\n if (m <= i < n) && P i then F i else idx.\n\n(*This lemma states that a cumulative operation over a singleton range of natural numbers yields the value of the function at that number.*)\nLemma big_nat1 n F : \\big[*%M/1]_(n <= i < n.+1) F i = F n.\n\n(*This lemma provides a recurrence relation for cumulative operations over natural number ranges, showing that the operation up to a number's successor is the product of the operation up to the number and the function's value at that number.*)\nLemma big_nat_recr n m F : m <= n ->\n \\big[*%M/1]_(m <= i < n.+1) F i = (\\big[*%M/1]_(m <= i < n) F i) * F n.\n\n(*This lemma states that a cumulative operation over a range of natural numbers of size `n` times `k` can be computed as a nested operation, with the outer loop running `n` times and the inner loop covering consecutive blocks of size `k`.*)\nLemma big_nat_mul n k F :\n \\big[*%M/1]_(0 <= i < n * k) F i =\n \\big[*%M/1]_(0 <= i < n) \\big[*%M/1]_(i * k <= j < i.+1 * k) F j.\n\n(*This lemma provides a recurrence formula for a cumulative operation over ordinals, expressing the operation up to a successor ordinal in terms of the operation up to the predecessor and the function's value at the maximal ordinal.*)\nLemma big_ord_recr n F :\n \\big[*%M/1]_(i < n.+1) F i =\n (\\big[*%M/1]_(i < n) F (widen_ord (leqnSn n) i)) * F ord_max.\n\n(*This lemma states that a cumulative operation over a finite sum type is the monoid product of the operations performed separately on the elements from each constituent type.*)\nLemma big_sumType (I1 I2 : finType) (P : pred (I1 + I2)) F :\n \\big[*%M/1]_(i | P i) F i =\n (\\big[*%M/1]_(i | P (inl _ i)) F (inl _ i))\n * (\\big[*%M/1]_(i | P (inr _ i)) F (inr _ i)).\n\n(*This lemma states that a cumulative operation over an ordinal type corresponding to a sum of two numbers can be split into the monoid product of operations over the two corresponding smaller ordinal types.*)\nLemma big_split_ord m n (P : pred 'I_(m + n)) F :\n \\big[*%M/1]_(i | P i) F i =\n (\\big[*%M/1]_(i | P (lshift n i)) F (lshift n i))\n * (\\big[*%M/1]_(i | P (rshift m i)) F (rshift m i)).\n\n(*This lemma states that a cumulative operation over a flattened sequence of sequences is equivalent to a nested operation, where the outer loop iterates through the sequences and the inner loop iterates through the elements of each sequence.*)\nLemma big_flatten I rr (P : pred I) F :\n \\big[*%M/1]_(i <- flatten rr | P i) F i\n = \\big[*%M/1]_(r <- rr) \\big[*%M/1]_(i <- r | P i) F i.\n\n(*This lemma shows that a cumulative operation over a sequence obtained by partially mapping a function is equivalent to an operation over the original sequence where the identity element is used for elements that map to none.*)\nLemma big_pmap J I (h : J -> option I) (r : seq J) F :\n \\big[op/idx]_(i <- pmap h r) F i = \\big[op/idx]_(j <- r) oapp F idx (h j).\n\n(*This lemma states that if a function has a telescoping property, a cumulative operation over a sequence of its consecutive applications simplifies to a single application of the function over the entire range, or the identity if the range is empty.*)\nLemma telescope_big (f : nat -> nat -> R) (n m : nat) :\n (forall k, n < k < m -> op (f n k) (f k k.+1) = f n k.+1) ->\n \\big[op/idx]_(n <= i < m) f i i.+1 = if n < m then f n m else idx.\n\nEnd Plain.\n\nSection Abelian.\n\nVariable op : Monoid.com_law 1.\n\n(*This notation defines a generic cumulative operator for a commutative monoid.*)\nLocal Notation \"'*%M'\" := op.\n(*This notation defines an infix binary operator for the underlying commutative monoid operation.*)\nLocal Notation \"x * y\" := (op x y).\n\n(*This lemma states that the iterated product of a function over a sequence containing a specific element is equal to the product of the function's value at that element (if it satisfies a predicate) and the iterated product over the sequence with that element removed.*)\nLemma big_rem (I : eqType) r x (P : pred I) F :\n x \\in r ->\n \\big[*%M/1]_(y <- r | P y) F y\n = (if P x then F x else 1) * \\big[*%M/1]_(y <- rem x r | P y) F y.\n\n(*This lemma states that for a commutative operation, the iterated product of a function over a finite sequence is equal to the iterated product over the reversed sequence.*)\nLemma big_rev I (r : seq I) P F :\n \\big[*%M/1]_(i <- rev r | P i) F i = \\big[*%M/1]_(i <- r | P i) F i.\n\n(*This lemma states that if two finite sequences are composed of the same set of elements and the underlying operation is idempotent, then the iterated product of a function over both sequences yields the same result.*)\nLemma eq_big_idem (I : eqType) (r1 r2 : seq I) (P : pred I) F :\n idempotent_op *%M -> r1 =i r2 ->\n \\big[*%M/1]_(i <- r1 | P i) F i = \\big[*%M/1]_(i <- r2 | P i) F i.\n\n(*This lemma states that the iterated product of a function over a finite sequence is equivalent to first removing duplicate elements, then for each unique element, applying the function and repeating the operation a number of times equal to its multiplicity, and finally computing the iterated product of these results.*)\nLemma big_undup_iterop_count (I : eqType) (r : seq I) (P : pred I) F :\n \\big[*%M/1]_(i <- undup r | P i) iterop (count_mem i r) *%M (F i) 1\n = \\big[*%M/1]_(i <- r | P i) F i.\n\n(*This lemma states that the iterated product of a pointwise product of two functions over a sequence is equal to the product of their individual iterated products over the same sequence.*)\nLemma big_split I r (P : pred I) F1 F2 :\n \\big[*%M/1]_(i <- r | P i) (F1 i * F2 i) =\n \\big[*%M/1]_(i <- r | P i) F1 i * \\big[*%M/1]_(i <- r | P i) F2 i.\n\n(*This lemma states that an iterated product over a sequence can be split into the product of two separate iterated products based on a predicate: one over the elements that satisfy the predicate, and one over the elements that do not.*)\nLemma bigID I r (a P : pred I) F :\n \\big[*%M/1]_(i <- r | P i) F i =\n \\big[*%M/1]_(i <- r | P i && a i) F i *\n \\big[*%M/1]_(i <- r | P i && ~~ a i) F i.\n\nArguments bigID [I r].\n\n(*This lemma states that the iterated product of a conditional function over a sequence is equal to the product of two iterated products: one of the 'then' branch function over elements satisfying the condition, and one of the 'else' branch function over elements not satisfying the condition.*)\nLemma big_if I r (P Q : pred I) F G :\n \\big[*%M/1]_(i <- r | P i) (if Q i then F i else G i) =\n \\big[*%M/1]_(i <- r | P i && Q i) F i *\n \\big[*%M/1]_(i <- r | P i && ~~ Q i) G i.\n\n(*This lemma states that for two disjoint sets of elements, the iterated product of a function over their union is equal to the product of the iterated products over each individual set.*)\nLemma bigU (I : finType) (A B : pred I) F :\n [disjoint A & B] ->\n \\big[*%M/1]_(i in [predU A & B]) F i =\n (\\big[*%M/1]_(i in A) F i) * (\\big[*%M/1]_(i in B) F i).\n\n(*This lemma states that an iterated product over a sequence can be re-grouped according to a partition function. The total product equals the iterated product over the codomain of the partition, where each term is the inner iterated product over the elements of the sequence that map to a specific value in the partition.*)\nLemma partition_big I (s : seq I)\n (J : finType) (P : pred I) (p : I -> J) (Q : pred J) F :\n (forall i, P i -> Q (p i)) ->\n \\big[*%M/1]_(i <- s | P i) F i =\n \\big[*%M/1]_(j : J | Q j) \\big[*%M/1]_(i <- s | (P i) && (p i == j)) F i.\n\nArguments partition_big [I s J P] p Q [F].\n\n(*This lemma states that an iterated operation over the elements of a finite set is equivalent to an iterated operation over the natural numbers up to the cardinality of the set, where each element is accessed via its index in a canonical enumeration.*)\nLemma big_enum_val (I : finType) (A : pred I) F :\n \\big[op/idx]_(x in A) F x = \\big[op/idx]_(i < #|A|) F (enum_val i).\n\nArguments big_enum_val [I A] F.\n\n(*This lemma states that an iterated operation of a function over the indices of a finite set is equal to the iterated operation of the same function composed with the canonical rank mapping over the elements of the set itself.*)\nLemma big_enum_rank (I : finType) (A : pred I) x (xA : x \\in A) F\n (h := enum_rank_in xA) :\n \\big[op/idx]_(i < #|A|) F i = \\big[op/idx]_(s in A) F (h s).\n\nArguments big_enum_rank [I A x] xA F.\n\n(*This lemma states that an iterated product over a finite type, restricted to a subset and a predicate, is equivalent to an iterated product over the corresponding subtype where the predicate and function are applied to the projected value.*)\nLemma big_sub_cond (I : finType) (A P : {pred I}) (F : I -> R) :\n \\big[*%M/1]_(i in A | P i) F i =\n \\big[*%M/1]_(x : {x in A} | P (val x)) F (val x).\n\n(*This lemma states that an iterated product over a finite type, restricted to a subset, is equivalent to an iterated product over the corresponding subtype, applying the function to the projected value from that subtype.*)\nLemma big_sub (I : finType) (A : {pred I}) (F : I -> R) :\n \\big[*%M/1]_(i in A) F i = \\big[*%M/1]_(x : {x in A}) F (val x).\n\n(*This lemma states that a nested iterated operation, where the inner iteration's domain depends on the outer iteration's variable, can be flattened into a single iterated operation over the corresponding dependent pair type.*)\nLemma sig_big_dep (I : finType) (J : I -> finType)\n (P : pred I) (Q : forall {i}, pred (J i)) (F : forall {i}, J i -> R) :\n \\big[op/idx]_(i | P i) \\big[op/idx]_(j : J i | Q j) F j =\n \\big[op/idx]_(p : {i : I & J i} | P (tag p) && Q (tagged p)) F (tagged p).\n\n(*This lemma states that a nested iterated product, where the predicate of the inner loop depends on the variable of the outer loop, is equivalent to a single iterated product over pairs, with a combined predicate on the components of the pair.*)\nLemma pair_big_dep (I J : finType) (P : pred I) (Q : I -> pred J) F :\n \\big[*%M/1]_(i | P i) \\big[*%M/1]_(j | Q i j) F i j =\n \\big[*%M/1]_(p | P p.1 && Q p.1 p.2) F p.1 p.2.\n\n(*This lemma states that a nested iterated product over two independent domains is equivalent to a single iterated product over the Cartesian product of the domains.*)\nLemma pair_big (I J : finType) (P : pred I) (Q : pred J) F :\n \\big[*%M/1]_(i | P i) \\big[*%M/1]_(j | Q j) F i j =\n \\big[*%M/1]_(p | P p.1 && Q p.2) F p.1 p.2.\n\n(*This lemma states that a nested iterated product of a two-argument function over all elements of two finite types is equivalent to a single iterated product over all pairs in their Cartesian product.*)\nLemma pair_bigA (I J : finType) (F : I -> J -> R) :\n \\big[*%M/1]_i \\big[*%M/1]_j F i j = \\big[*%M/1]_p F p.1 p.2.\n\n(*This lemma provides a rule for exchanging the order of nested iterated products over sequences, especially when the inner loop's predicate depends on the outer loop's variable, by appropriately adjusting the predicates.*)\nLemma exchange_big_dep I J rI rJ (P : pred I) (Q : I -> pred J)\n (xQ : pred J) F :\n (forall i j, P i -> Q i j -> xQ j) ->\n \\big[*%M/1]_(i <- rI | P i) \\big[*%M/1]_(j <- rJ | Q i j) F i j =\n \\big[*%M/1]_(j <- rJ | xQ j) \\big[*%M/1]_(i <- rI | P i && Q i j) F i j.\n\nArguments exchange_big_dep [I J rI rJ P Q] xQ [F].\n\n(*This lemma states that for nested iterated products over sequences with independent predicates, the order of the iterations can be freely exchanged.*)\nLemma exchange_big I J rI rJ (P : pred I) (Q : pred J) F :\n \\big[*%M/1]_(i <- rI | P i) \\big[*%M/1]_(j <- rJ | Q j) F i j =\n \\big[*%M/1]_(j <- rJ | Q j) \\big[*%M/1]_(i <- rI | P i) F i j.\n\n(*This lemma provides a rule for exchanging the order of nested iterated products over ranges of natural numbers, especially when the inner loop's predicate depends on the outer loop's variable.*)\nLemma exchange_big_dep_nat m1 n1 m2 n2 (P : pred nat) (Q : rel nat)\n (xQ : pred nat) F :\n (forall i j, m1 <= i < n1 -> m2 <= j < n2 -> P i -> Q i j -> xQ j) ->\n \\big[*%M/1]_(m1 <= i < n1 | P i) \\big[*%M/1]_(m2 <= j < n2 | Q i j) F i j =\n \\big[*%M/1]_(m2 <= j < n2 | xQ j)\n \\big[*%M/1]_(m1 <= i < n1 | P i && Q i j) F i j.\n\nArguments exchange_big_dep_nat [m1 n1 m2 n2 P Q] xQ [F].\n\n(*This lemma states that for nested iterated products over independent ranges of natural numbers, the order of the iterations can be freely exchanged.*)\nLemma exchange_big_nat m1 n1 m2 n2 (P Q : pred nat) F :\n \\big[*%M/1]_(m1 <= i < n1 | P i) \\big[*%M/1]_(m2 <= j < n2 | Q j) F i j =\n \\big[*%M/1]_(m2 <= j < n2 | Q j) \\big[*%M/1]_(m1 <= i < n1 | P i) F i j.\n\nEnd Abelian.\n\nEnd MonoidProperties.\n\nArguments big_filter [R idx op I].\nArguments big_filter_cond [R idx op I].\nArguments congr_big [R idx op I r1] r2 [P1] P2 [F1] F2.\nArguments eq_big [R idx op I r P1] P2 [F1] F2.\nArguments eq_bigl [R idx op I r P1] P2.\nArguments eq_bigr [R idx op I r P F1] F2.\nArguments eq_big_idx [R idx op idx' I] i0 [P F].\nArguments big_seq_cond [R idx op I r].\nArguments eq_big_seq [R idx op I r F1] F2.\nArguments congr_big_nat [R idx op m1 n1] m2 n2 [P1] P2 [F1] F2.\nArguments big_map [R idx op I J] h [r].\nArguments big_nth [R idx op I] x0 [r].\nArguments big_catl [R idx op I r1 r2 P F].\nArguments big_catr [R idx op I r1 r2 P F].\nArguments big_geq [R idx op m n P F].\nArguments big_ltn_cond [R idx op m n P F].\nArguments big_ltn [R idx op m n F].\nArguments big_addn [R idx op].\nArguments big_mkord [R idx op n].\nArguments big_nat_widen [R idx op].\nArguments big_nat_widenl [R idx op].\nArguments big_geq_mkord [R idx op].\nArguments big_ord_widen_cond [R idx op n1].\nArguments big_ord_widen [R idx op n1].\nArguments big_ord_widen_leq [R idx op n1].\nArguments big_ord_narrow_cond [R idx op n1 n2 P F].\nArguments big_ord_narrow_cond_leq [R idx op n1 n2 P F].\nArguments big_ord_narrow [R idx op n1 n2 F].\nArguments big_ord_narrow_leq [R idx op n1 n2 F].\nArguments big_mkcond [R idx op I r].\nArguments big1_eq [R idx op I].\nArguments big1_seq [R idx op I].\nArguments big1 [R idx op I].\nArguments big_only1 {R idx op I} i [P F].\nArguments big_pred1 [R idx op I] i [P F].\nArguments perm_big [R op x I r1] r2 [P F].\nArguments big_uniq [R op x I] r [F].\nArguments big_rem [R idx op I r] x [P F].\nArguments bigID [R idx op I r].\nArguments bigU [R idx op I].\nArguments bigD1 [R op x I] j [P F].\nArguments bigD1_seq [R op x I r] j [F].\nArguments bigD1_ord [R op x n] j [P F].\nArguments partition_big [R idx op I s J P] p Q [F].\nArguments reindex_omap [R op x I J] h h' [P F].\nArguments reindex_onto [R op x I J] h h' [P F].\nArguments reindex [R op x I J] h [P F].\nArguments reindex_inj [R op x I h P F].\nArguments big_enum_val_cond [R op x I A] P F.\nArguments big_enum_rank_cond [R op x I A z] zA P F.\nArguments big_enum_val [R idx op I A] F.\nArguments big_enum_rank [R idx op I A x] xA F.\nArguments big_sub_cond [R idx op I].\nArguments big_sub [R idx op I].\nArguments sig_big_dep [R idx op I J].\nArguments pair_big_dep [R idx op I J].\nArguments pair_big [R idx op I J].\nArguments big_allpairs_dep {R idx op I1 I2 J h r1 r2 F}.\nArguments big_allpairs {R idx op I1 I2 r1 r2 F}.\nArguments exchange_big_dep [R idx op I J rI rJ P Q] xQ [F].\nArguments exchange_big_dep_nat [R idx op m1 n1 m2 n2 P Q] xQ [F].\nArguments big_ord_recl [R idx op].\nArguments big_ord_recr [R idx op].\nArguments big_nat_recl [R idx op].\nArguments big_nat_recr [R idx op].\nArguments big_cat_nat_idem [R op x] opxx [n m p P F].\nArguments big_cat_nat [R idx op n m p P F].\nArguments big_pmap [R idx op J I] h [r].\nArguments telescope_big [R idx op] f [n m].\n\nSection IncreasingSemiGroup.\n\nVariables (R : Type) (op : SemiGroup.com_law R).\nVariable le : rel R.\nHypothesis le_refl : reflexive le.\nHypothesis op_incr : forall x y, le x (op x y).\nContext [x : R].\n\n(*This notation refers to the associativity property of the commutative semigroup operation.*)\nLocal Notation opA := SemiGroup.opA.\n(*This notation refers to the commutativity property of the commutative semigroup operation.*)\nLocal Notation opC := SemiGroup.opC.\n\n(*This lemma states that if one predicate implies another, the iterated product of a function over a sequence with the first predicate is less than or equal to the iterated product with the second predicate, provided that the operation is increasing.*)\nLemma sub_le_big I [s] (P P' : {pred I}) (F : I -> R) :\n (forall i, P i -> P' i) ->\n le (\\big[op/x]_(i <- s | P i) F i) (\\big[op/x]_(i <- s | P' i) F i).\n\n(*This lemma states that if one finite sequence is a sub-multiset of another, then the iterated product of a function over the first sequence is less than or equal to the iterated product over the second, given that the underlying operation is increasing.*)\nLemma sub_le_big_seq (I : eqType) s s' P (F : I -> R) :\n (forall i, count_mem i s <= count_mem i s')%N ->\n le (\\big[op/x]_(i <- s | P i) F i) (\\big[op/x]_(i <- s' | P i) F i).\n\n(*This lemma states that if the multiset of elements from a sequence satisfying a predicate is a sub-multiset of elements from a second sequence satisfying a second predicate, then the corresponding first iterated product is less than or equal to the second, given that the underlying operation is increasing.*)\nLemma sub_le_big_seq_cond (I : eqType) s s' P P' (F : I -> R) :\n (forall i, count_mem i (filter P s) <= count_mem i (filter P' s'))%N ->\n le (\\big[op/x]_(i <- s | P i) F i) (\\big[op/x]_(i <- s' | P' i) F i).\n\n(*This lemma states that for two finite sequences without duplicate elements, if the first sequence is a subset of the second, then the iterated product of a function over the first is less than or equal to the iterated product over the second, given an increasing operation.*)\nLemma uniq_sub_le_big (I : eqType) s s' P (F : I -> R) : uniq s -> uniq s' ->\n {subset s <= s'} ->\n le (\\big[op/x]_(i <- s | P i) F i) (\\big[op/x]_(i <- s' | P i) F i).\n\n(*This lemma states that if the set of elements from a sequence satisfying a predicate is a subset of the elements from another sequence satisfying a second predicate, and both filtered sequences have no duplicates, then the first iterated product is less than or equal to the second, given an increasing operation.*)\nLemma uniq_sub_le_big_cond (I : eqType) s s' P P' (F : I -> R) :\n uniq (filter P s) -> uniq (filter P' s') ->\n {subset [seq i <- s | P i] <= [seq i <- s' | P' i]} ->\n le (\\big[op/x]_(i <- s | P i) F i) (\\big[op/x]_(i <- s' | P' i) F i).\n\nSection Id.\n\nHypothesis opK : idempotent_op op.\n\n(*This lemma states that if the set of elements in one finite sequence is a subset of the elements in another, and the underlying operation is both idempotent and increasing, then the iterated product of a function over the first sequence is less than or equal to the iterated product over the second.*)\nLemma idem_sub_le_big (I : eqType) s s' P (F : I -> R) :\n {subset s <= s'} ->\n le (\\big[op/x]_(i <- s | P i) F i) (\\big[op/x]_(i <- s' | P i) F i).\n\n(*This lemma states that if the set of elements from a sequence satisfying a predicate is a subset of the elements from a second sequence satisfying a second predicate, and the operation is both idempotent and increasing, then the corresponding first iterated product is less than or equal to the second.*)\nLemma idem_sub_le_big_cond (I : eqType) s s' P P' (F : I -> R) :\n {subset [seq i <- s | P i] <= [seq i <- s' | P' i]} ->\n le (\\big[op/x]_(i <- s | P i) F i) (\\big[op/x]_(i <- s' | P' i) F i).\n\nEnd Id.\n\n(*This lemma states that for a big operation over a sequence, if the predicate filtering the elements is weakened such that it holds for more elements, then the resulting value of the big operation is greater than or equal to the original value, assuming an increasing semigroup operator.*)\nLemma sub_in_le_big [I : eqType] (s : seq I) (P P' : {pred I}) (F : I -> R) :\n {in s, forall i, P i -> P' i} ->\n le (\\big[op/x]_(i <- s | P i) F i) (\\big[op/x]_(i <- s | P' i) F i).\n\n(*This lemma states that for an increasing semigroup operator, the value of a big operation over the natural numbers up to a certain limit is less than or equal to the value of the same operation performed up to a greater or equal limit.*)\nLemma le_big_ord n m [P : {pred nat}] [F : nat -> R] : (n <= m)%N ->\n le (\\big[op/x]_(i < n | P i) F i) (\\big[op/x]_(i < m | P i) F i).\n\n(*This lemma states that for an increasing semigroup operator over a finite type, the value of a big operation over a given set of elements is less than or equal to the value of the same operation performed over a superset of those elements.*)\nLemma subset_le_big [I : finType] [A A' P : {pred I}] (F : I -> R) :\n A \\subset A' ->\n le (\\big[op/x]_(i in A | P i) F i) (\\big[op/x]_(i in A' | P i) F i).\n\n(*This lemma states that the result of a big operation over a range of natural numbers is less than or equal to the result of a second big operation if the second operation's range contains the first one and its predicate is weaker on that first range, assuming an increasing semigroup operator.*)\nLemma le_big_nat_cond n m n' m' (P P' : {pred nat}) (F : nat -> R) :\n (n' <= n)%N -> (m <= m')%N -> (forall i, (n <= i < m)%N -> P i -> P' i) ->\n le (\\big[op/x]_(n <= i < m | P i) F i) (\\big[op/x]_(n' <= i < m' | P' i) F i).\n\n(*This lemma states that for an increasing semigroup operator, the value of a big operation over a range of natural numbers is less than or equal to the value of the same operation performed over a larger range that contains the original one.*)\nLemma le_big_nat n m n' m' [P] [F : nat -> R] : (n' <= n)%N -> (m <= m')%N ->\n le (\\big[op/x]_(n <= i < m | P i) F i) (\\big[op/x]_(n' <= i < m' | P i) F i).\n\n(*This lemma states that for an increasing semigroup operator, a big operation over natural numbers up to a limit is less than or equal to a similar operation up to a larger limit, provided the predicate for the first operation implies the predicate for the second on the smaller range.*)\nLemma le_big_ord_cond n m (P P' : {pred nat}) (F : nat -> R) :\n (n <= m)%N -> (forall i : 'I_n, P i -> P' i) ->\n le (\\big[op/x]_(i < n | P i) F i) (\\big[op/x]_(i < m | P' i) F i).\n\nEnd IncreasingSemiGroup.\n\nSection EqSupport.\n\nVariables (R : eqType) (idx : R).\n\nSection MonoidSupport.\n\nVariables (op : Monoid.law idx) (I : Type).\n\n(*This lemma states that two big monoid operations over a sequence yield the same result if their respective predicates are equivalent on the support of the function being aggregated, where the support consists of elements not mapped to the monoid's identity element.*)\nLemma eq_bigl_supp (r : seq I) (P1 : pred I) (P2 : pred I) (F : I -> R) :\n {in [pred x | F x != idx], P1 =1 P2} ->\n \\big[op/idx]_(i <- r | P1 i) F i = \\big[op/idx]_(i <- r | P2 i) F i.\n\nEnd MonoidSupport.\n\nSection ComoidSupport.\n\nVariables (op : Monoid.com_law idx) (I : eqType).\n\n(*This lemma states that for a commutative monoid operation, two big operations over potentially different sequences result in the same value if the subsequences formed by elements that satisfy a given predicate and are not mapped to the identity element are permutations of each other.*)\nLemma perm_big_supp_cond [r s : seq I] [P : pred I] (F : I -> R) :\n perm_eq\n [seq i <- r | P i && (F i != idx)]\n [seq i <- s | P i && (F i != idx)] ->\n \\big[op/idx]_(i <- r | P i) F i = \\big[op/idx]_(i <- s | P i) F i.\n\n(*This lemma states that for a commutative monoid operation, two big operations over different sequences yield the same result, provided that the subsequences formed by elements not mapped to the identity element are permutations of each other.*)\nLemma perm_big_supp [r s : seq I] [P : pred I] (F : I -> R) :\n perm_eq [seq i <- r | F i != idx] [seq i <- s | F i != idx] ->\n \\big[op/idx]_(i <- r | P i) F i = \\big[op/idx]_(i <- s | P i) F i.\n\nEnd ComoidSupport.\n\nEnd EqSupport.\n\nArguments eq_bigl_supp [R idx op I r P1].\nArguments perm_big_supp_cond [R idx op I r s P].\nArguments perm_big_supp [R idx op I r s P].\n\nSection Distributivity.\n\nImport Monoid.Theory.\n\nVariable R : Type.\nVariables zero one : R.\n(*A local notation for the identity element of an additive monoid operation, typically representing zero.*)\nLocal Notation \"0\" := zero.\n(*A local notation for the identity element of a multiplicative monoid operation, typically representing one.*)\nLocal Notation \"1\" := one.\nVariable times : Monoid.mul_law 0.\n(*A local notation for a multiplicative monoid operation.*)\nLocal Notation \"*%M\" := times.\n(*A local infix notation for applying a multiplicative monoid operation to two elements.*)\nLocal Notation \"x * y\" := (times x y).\nVariable plus : Monoid.add_law 0 *%M.\n(*A local notation for an additive monoid operation over which a corresponding multiplication distributes.*)\nLocal Notation \"+%M\" := plus.\n(*A local infix notation for applying an additive monoid operation to two elements.*)\nLocal Notation \"x + y\" := (plus x y).\n\n(*This lemma asserts the left distributivity of multiplication over a big sum, stating that multiplying the result of the big sum by an element is equivalent to performing the big sum on the results of multiplying each term by that element.*)\nLemma big_distrl I r a (P : pred I) F :\n \\big[+%M/0]_(i <- r | P i) F i * a = \\big[+%M/0]_(i <- r | P i) (F i * a).\n\n(*This lemma asserts the right distributivity of multiplication over a big sum, stating that an element multiplied by the result of the big sum is equivalent to performing the big sum on the results of multiplying that element by each term.*)\nLemma big_distrr I r a (P : pred I) F :\n a * \\big[+%M/0]_(i <- r | P i) F i = \\big[+%M/0]_(i <- r | P i) (a * F i).\n\n(*This lemma states that the product of two big sums is equal to the big sum of the big sum of the products of the terms, effectively distributing the terms of the first sum over the second.*)\nLemma big_distrlr I J rI rJ (pI : pred I) (pJ : pred J) F G :\n (\\big[+%M/0]_(i <- rI | pI i) F i) * (\\big[+%M/0]_(j <- rJ | pJ j) G j)\n = \\big[+%M/0]_(i <- rI | pI i) \\big[+%M/0]_(j <- rJ | pJ j) (F i * G j).\n\n(*This lemma establishes a general distributive law, showing that a big product of big sums, where the inner sum's range depends on the outer product's index, is equal to a big sum over a family of choice functions, where each term in the sum is a big product.*)\nLemma big_distr_big_dep (I J : finType) j0 (P : pred I) (Q : I -> pred J) F :\n \\big[*%M/1]_(i | P i) \\big[+%M/0]_(j | Q i j) F i j =\n \\big[+%M/0]_(f in pfamily j0 P Q) \\big[*%M/1]_(i | P i) F i (f i).\n\n(*This lemma establishes a distributive law showing that a big product of big sums is equal to a big sum over a set of partial functions, where each term in the sum is a big product.*)\nLemma big_distr_big (I J : finType) j0 (P : pred I) (Q : pred J) F :\n \\big[*%M/1]_(i | P i) \\big[+%M/0]_(j | Q j) F i j =\n \\big[+%M/0]_(f in pffun_on j0 P Q) \\big[*%M/1]_(i | P i) F i (f i).\n\n(*This lemma states that a big product over an entire finite type of big sums, where the inner sum's range depends on the outer product's index, is equal to a big sum over a family of valid choice functions, where each term of the sum is a big product.*)\nLemma bigA_distr_big_dep (I J : finType) (Q : I -> pred J) F :\n \\big[*%M/1]_i \\big[+%M/0]_(j | Q i j) F i j\n = \\big[+%M/0]_(f in family Q) \\big[*%M/1]_i F i (f i).\n\n(*This lemma states that a big product over an entire finite type of big sums is equal to a big sum over a set of functions whose images are contained in the sum's domain, where each term of the sum is a big product.*)\nLemma bigA_distr_big (I J : finType) (Q : pred J) (F : I -> J -> R) :\n \\big[*%M/1]_i \\big[+%M/0]_(j | Q j) F i j\n = \\big[+%M/0]_(f in ffun_on Q) \\big[*%M/1]_i F i (f i).\n\n(*This lemma states that a big product of big sums, where both operations iterate over entire finite types, is equal to a big sum over all functions between the two index types, with each term being a big product determined by one such function.*)\nLemma bigA_distr_bigA (I J : finType) F :\n \\big[*%M/1]_(i : I) \\big[+%M/0]_(j : J) F i j\n = \\big[+%M/0]_(f : {ffun I -> J}) \\big[*%M/1]_i F i (f i).\n\nEnd Distributivity.\n\nArguments big_distrl [R zero times plus I r].\nArguments big_distrr [R zero times plus I r].\nArguments big_distr_big_dep [R zero one times plus I J].\nArguments big_distr_big [R zero one times plus I J].\nArguments bigA_distr_big_dep [R zero one times plus I J].\nArguments bigA_distr_big [R zero one times plus I J].\nArguments bigA_distr_bigA [R zero one times plus I J].\n\nSection BigBool.\n\nSection Seq.\n\nVariables (I : Type) (r : seq I) (P B : pred I).\n\n(*This lemma states that performing a big operation with boolean OR over a sequence for a given boolean predicate is equivalent to checking if at least one element in the sequence satisfies the predicate.*)\nLemma big_has : \\big[orb/false]_(i <- r) B i = has B r.\n\n(*This lemma states that performing a big operation with boolean AND over a sequence for a given boolean predicate is equivalent to checking if all elements in the sequence satisfy the predicate.*)\nLemma big_all : \\big[andb/true]_(i <- r) B i = all B r.\n\n(*This lemma states that the big disjunction (OR) of a boolean-valued function over the elements of a sequence that satisfy a given predicate is equivalent to checking whether there exists at least one element in the sequence that satisfies both the predicate and for which the function evaluates to true.*)\nLemma big_has_cond : \\big[orb/false]_(i <- r | P i) B i = has (predI P B) r.\n\n(*This lemma states that the big conjunction (AND) of a boolean-valued function over the elements of a sequence that satisfy a given predicate is equivalent to checking if for every element in the sequence, the predicate's truth implies that the function also evaluates to true.*)\nLemma big_all_cond :\n \\big[andb/true]_(i <- r | P i) B i = all [pred i | P i ==> B i] r.\n\n(*This lemma states that a big operation with a commutative law over the boolean type, applied to a function from booleans to some type, is equivalent to applying the binary operation to the function's value at true and its value at false.*)\nLemma big_bool R (idx : R) (op : Monoid.com_law idx) (F : bool -> R):\n \\big[op/idx]_(i : bool) F i = op (F true) (F false).\n\nEnd Seq.\n\nSection FinType.\n\nVariables (I : finType) (P B : pred I).\n\n(*This lemma states that for a finite type, the big disjunction (OR) of a boolean-valued function over the elements that satisfy a given predicate is equivalent to the proposition that there exists an element satisfying both the predicate and for which the function is true.*)\nLemma big_orE : \\big[orb/false]_(i | P i) B i = [exists (i | P i), B i].\n\n(*This lemma states that for a finite type, the big conjunction (AND) of a boolean-valued function over the elements that satisfy a given predicate is equivalent to the proposition that for all elements satisfying the predicate, the function also evaluates to true.*)\nLemma big_andE : \\big[andb/true]_(i | P i) B i = [forall (i | P i), B i].\n\nEnd FinType.\n\nEnd BigBool.\n\nSection NatConst.\n\nVariables (I : finType) (A : pred I).\n\n(*This lemma states that the sum of a constant natural number over all elements in a given finite set is equal to the product of the set's cardinality and the constant number.*)\nLemma sum_nat_const n : \\sum_(i in A) n = #|A| * n.\n\n(*This lemma states that the sum of the natural number one over all elements in a given finite set is equal to the cardinality of that set.*)\nLemma sum1_card : \\sum_(i in A) 1 = #|A|.\n\n(*This lemma states that the sum of the natural number one over all elements in a finite sequence that satisfy a given predicate is equal to the number of elements in the sequence for which the predicate holds.*)\nLemma sum1_count J (r : seq J) (a : pred J) : \\sum_(j <- r | a j) 1 = count a r.\n\n(*This lemma states that the sum of the natural number one over all elements in a finite sequence is equal to the length of the sequence.*)\nLemma sum1_size J (r : seq J) : \\sum_(j <- r) 1 = size r.\n\n(*This lemma states that the product of a constant natural number over all elements in a given finite set is equal to the constant number raised to the power of the set's cardinality.*)\nLemma prod_nat_const n : \\prod_(i in A) n = n ^ #|A|.\n\n(*This lemma states that the sum of a constant natural number over a range of natural numbers from a lower bound (inclusive) to an upper bound (exclusive) is equal to the product of the range's length and the constant number.*)\nLemma sum_nat_const_nat n1 n2 n : \\sum_(n1 <= i < n2) n = (n2 - n1) * n.\n\n(*This lemma states that the product of a constant natural number over a range of natural numbers from a lower bound (inclusive) to an upper bound (exclusive) is equal to the constant number raised to the power of the range's length.*)\nLemma prod_nat_const_nat n1 n2 n : \\prod_(n1 <= i < n2) n = n ^ (n2 - n1).\n\nEnd NatConst.\n\n(*This lemma presents a telescoping sum property, stating that for a non-decreasing function from natural numbers to natural numbers, the sum of the differences between the function's values at successive integers over a given range is equal to the difference between the function's values at the endpoints of the range.*)\nLemma telescope_sumn_in n m f : n <= m ->\n (forall i, n <= i < m -> f i <= f i.+1) ->\n \\sum_(n <= k < m) (f k.+1 - f k) = f m - f n.\n\n(*This lemma provides a telescoping sum property, asserting that for any non-decreasing function from natural numbers to natural numbers, the sum of differences between the function's values at consecutive integers over a range is equal to the difference between the function's values at the range's upper and lower bounds.*)\nLemma telescope_sumn n m f : {homo f : x y / x <= y} ->\n \\sum_(n <= k < m) (f k.+1 - f k) = f m - f n.\n\n(*This lemma states that the sum of all natural numbers in a given finite sequence is equivalent to using the big sum operator with the identity function over that same sequence.*)\nLemma sumnE r : sumn r = \\sum_(i <- r) i. \n\n(*This lemma states that the total number of finite sequences of elements from a given finite type, with a length up to and including a specified natural number, is equal to the sum of the cardinality of the type raised to each power from zero up to that specified length.*)\nLemma card_bseq n (T : finType) : #|{bseq n of T}| = \\sum_(i < n.+1) #|T| ^ i.\n\n(*This lemma asserts that if, for every element satisfying a given predicate, the less-than-or-equal relationship between the values of two natural-number-valued functions is equivalent to a second condition on that element, then the less-than-or-equal relationship between the sums of these functions over all such elements is equivalent to the universal satisfaction of the second condition for all those elements.*)\nLemma leqif_sum (I : finType) (P C : pred I) (E1 E2 : I -> nat) :\n (forall i, P i -> E1 i <= E2 i ?= iff C i) ->\n \\sum_(i | P i) E1 i <= \\sum_(i | P i) E2 i ?= iff [forall (i | P i), C i].\n\n(*This lemma states that if a first function from a type to the natural numbers is pointwise less than or equal to a second function for all elements in a sequence that satisfy a given predicate, then the sum of the first function's values over those elements is less than or equal to the sum of the second function's values.*)\nLemma leq_sum I r (P : pred I) (E1 E2 : I -> nat) :\n (forall i, P i -> E1 i <= E2 i) ->\n \\sum_(i <- r | P i) E1 i <= \\sum_(i <- r | P i) E2 i.\n\n(*This lemma states that if a first natural-number-valued function is pointwise less than or equal to a second one for all elements in a sequence satisfying a given predicate, then the sum of the pointwise differences is equal to the difference of their respective sums over those elements.*)\nLemma sumnB I r (P : pred I) (E1 E2 : I -> nat) :\n (forall i, P i -> E1 i <= E2 i) ->\n \\sum_(i <- r | P i) (E2 i - E1 i) =\n \\sum_(i <- r | P i) E2 i - \\sum_(i <- r | P i) E1 i.\n\n(*This lemma states that for a function from a finite type to the natural numbers, the sum of its values over all elements satisfying a given predicate is equal to zero if and only if the function evaluates to zero for all of those elements.*)\nLemma sum_nat_eq0 (I : finType) (P : pred I) (E : I -> nat) :\n (\\sum_(i | P i) E i == 0)%N = [forall (i | P i), E i == 0%N].\n\n(*This lemma states that the sum of a natural-number-valued function over the elements of a sequence that satisfy a given predicate is equal to zero if and only if for all elements in the original sequence, the predicate's truth implies the function's value is zero.*)\nLemma sum_nat_seq_eq0 I r (P : pred I) F :\n (\\sum_(i <- r | P i) F i == 0)%N = all (fun i => P i ==> (F i == 0%N)) r.\n\n(*This lemma states that the sum of a natural-number-valued function over the elements of a sequence that satisfy a given predicate is not equal to zero if and only if there exists at least one element in the sequence that satisfies the predicate and for which the function's value is non-zero.*)\nLemma sum_nat_seq_neq0 I r (P : pred I) F :\n (\\sum_(i <- r | P i) F i != 0)%N = has (fun i => P i && (F i != 0)%N) r.\n\n(*This lemma provides a reflection, stating that the sum of a natural-number-valued function over elements of a finite type satisfying a predicate is equal to one if and only if there exists exactly one element that satisfies the predicate and for which the function evaluates to one, while the function evaluates to zero for all other elements satisfying the predicate.*)\nLemma sum_nat_eq1 (I : finType) (P : pred I) (F : I -> nat) :\n reflect\n (exists i : I, [/\\ P i, F i = 1 & forall j, j != i -> P j -> F j = 0]%N)\n (\\sum_(i | P i) F i == 1)%N.\n\n(*This lemma states that if the sum of a natural-number-valued function over the elements of a sequence that satisfy a predicate is equal to one, then there must exist exactly one element in the sequence that satisfies the predicate and for which the function's value is one, while for all other distinct elements in the sequence satisfying the predicate, the function's value is zero.*)\nLemma sum_nat_seq_eq1 (I : eqType) r (P : pred I) (F : I -> nat) :\n (\\sum_(i <- r | P i) F i = 1)%N ->\n exists i, [/\\ i \\in r, P i, F i = 1\n & forall j, j != i -> j \\in r -> P j -> F j = 0]%N.\n\n(*This lemma states that the product of a natural-number-valued function over the elements of a sequence that satisfy a given predicate is equal to zero if and only if there exists at least one element in the sequence that both satisfies the predicate and for which the function evaluates to zero.*)\nLemma prod_nat_seq_eq0 I r (P : pred I) F :\n (\\prod_(i <- r | P i) F i == 0)%N = has (fun i => P i && (F i == 0%N)) r.\n\n(*This lemma states that the product of a natural-number-valued function over the elements of a sequence that satisfy a given predicate is not equal to zero if and only if for every element in the sequence, if it satisfies the predicate, then its value under the function is non-zero.*)\nLemma prod_nat_seq_neq0 I r (P : pred I) F :\n (\\prod_(i <- r | P i) F i != 0)%N = all (fun i => P i ==> (F i != 0%N)) r.\n\n(*This lemma states that the product of a natural-number-valued function over the elements of a sequence that satisfy a given predicate is equal to one if and only if for every element in the sequence that satisfies the predicate, its value under the function is one.*)\nLemma prod_nat_seq_eq1 I r (P : pred I) F :\n (\\prod_(i <- r | P i) F i == 1)%N = all (fun i => P i ==> (F i == 1%N)) r.\n\n(*This lemma states that the product of a natural-number-valued function over the elements of a sequence that satisfy a given predicate is not equal to one if and only if there exists at least one element in the sequence that both satisfies the predicate and for which the function's value is not one.*)\nLemma prod_nat_seq_neq1 I r (P : pred I) F :\n (\\prod_(i <- r | P i) F i != 1)%N = has (fun i => P i && (F i != 1%N)) r.\n\n(*This lemma states that if a first function from a type to the natural numbers is pointwise less than or equal to a second function for all elements in a sequence that satisfy a given predicate, then the product of the first function's values over those elements is less than or equal to the product of the second function's values.*)\nLemma leq_prod I r (P : pred I) (E1 E2 : I -> nat) :\n (forall i, P i -> E1 i <= E2 i) ->\n \\prod_(i <- r | P i) E1 i <= \\prod_(i <- r | P i) E2 i.\n\nArguments leq_prod [I r P E1 E2].\n\n(*This lemma states that if a natural-number-valued function evaluates to a value greater than zero for all elements in a sequence that satisfy a given predicate, then the product of the function's values over those elements is also greater than zero.*)\nLemma prodn_cond_gt0 I r (P : pred I) F :\n (forall i, P i -> 0 < F i) -> 0 < \\prod_(i <- r | P i) F i.\n\nArguments prodn_cond_gt0 [I r P F].\n\n(*This lemma states that if a function always maps to a natural number greater than zero, then the product of its values over a finite sequence of indices satisfying a predicate will also be greater than zero.*)\nLemma prodn_gt0 I r (P : pred I) F :\n (forall i, 0 < F i) -> 0 < \\prod_(i <- r | P i) F i.\n\nArguments prodn_gt0 [I r P F].\n\n(*This lemma states that if the product of a function's values over a finite sequence of indices satisfying a predicate is greater than zero, then for any index that is both in the sequence and satisfies the predicate, the function's value at that index must be greater than zero.*)\nLemma gt0_prodn_seq (I : eqType) r (P : pred I) F :\n 0 < \\prod_(i <- r | P i) F i -> forall i, i \\in r -> P i -> 0 < F i.\n\nArguments gt0_prodn_seq [I r P F].\n\n(*This lemma states that if the product of a function's values, taken over all elements of a finite type that satisfy a given predicate, is greater than zero, then the function's value for any element satisfying the predicate must also be greater than zero.*)\nLemma gt0_prodn (I : finType) (P : pred I) F :\n 0 < \\prod_(i | P i) F i -> forall i, P i -> 0 < F i.\n\nArguments gt0_prodn [I P F].\n\n(*This lemma states that, for a function evaluated over a sequence of indices satisfying a predicate, the function's value at any particular index within that sequence which satisfies the predicate is less than or equal to the maximum value of the function over the entire filtered sequence.*)\nLemma leq_bigmax_seq (I : eqType) r (P : pred I) F i0 :\n i0 \\in r -> P i0 -> F i0 <= \\max_(i <- r | P i) F i.\n\nArguments leq_bigmax_seq [I r P F].\n\n(*This lemma states that for a function evaluated over the elements of a finite type that satisfy a predicate, the function's value at any particular element satisfying that predicate is less than or equal to the maximum value of the function over all such elements.*)\nLemma leq_bigmax_cond (I : finType) (P : pred I) F i0 :\n P i0 -> F i0 <= \\max_(i | P i) F i.\n\nArguments leq_bigmax_cond [I P F].\n\n(*This lemma states that for a function evaluated over all elements of a finite type, its value at any particular element is less than or equal to the maximum value of the function over the entire type.*)\nLemma leq_bigmax (I : finType) F (i0 : I) : F i0 <= \\max_i F i.\n\nArguments leq_bigmax [I F].\n\n(*This lemma provides a reflection, establishing the logical equivalence between the statement that the maximum of a function's values over a filtered subset of a finite type is less than or equal to a given bound, and the statement that every value of the function over that same subset is less than or equal to that bound.*)\nLemma bigmax_leqP (I : finType) (P : pred I) m F :\n reflect (forall i, P i -> F i <= m) (\\max_(i | P i) F i <= m).\n\n(*This lemma provides a reflection, establishing the logical equivalence between the statement that the maximum of a function's values over a filtered subsequence of indices is less than or equal to a given bound, and the statement that every value of the function for an index in that filtered subsequence is less than or equal to that bound.*)\nLemma bigmax_leqP_seq (I : eqType) r (P : pred I) m F :\n reflect (forall i, i \\in r -> P i -> F i <= m) (\\max_(i <- r | P i) F i <= m).\n\n(*This lemma states that if a given value is a lower bound for a function at a specific index satisfying a predicate, then that value is also a lower bound for the maximum of the function over all indices satisfying the predicate.*)\nLemma bigmax_sup (I : finType) i0 (P : pred I) m F :\n P i0 -> m <= F i0 -> m <= \\max_(i | P i) F i.\n\nArguments bigmax_sup [I] i0 [P m F].\n\n(*This lemma states that if a given value is a lower bound for a function at a specific index that is present in a sequence and satisfies a predicate, then that value is also a lower bound for the maximum of the function over all indices in the sequence that satisfy the predicate.*)\nLemma bigmax_sup_seq (I : eqType) r i0 (P : pred I) m F :\n i0 \\in r -> P i0 -> m <= F i0 -> m <= \\max_(i <- r | P i) F i.\n\nArguments bigmax_sup_seq [I r] i0 [P m F].\n\n(*This lemma states that the maximum value of a function over a subset of a finite type, defined by a predicate, is equal to the function's value at the index that yields this maximum. The index is found by searching over elements that satisfy the predicate and come after a given starting index in the type's canonical order.*)\nLemma bigmax_eq_arg (I : finType) i0 (P : pred I) F :\n P i0 -> \\max_(i | P i) F i = F [arg max_(i > i0 | P i) F i].\n\nArguments bigmax_eq_arg [I] i0 [P F].\n\n(*This lemma states that for any non-empty subset of a finite type, there exists an element within that subset at which a given function attains its maximum value over that subset.*)\nLemma eq_bigmax_cond (I : finType) (A : pred I) F :\n #|A| > 0 -> {i0 | i0 \\in A & \\max_(i in A) F i = F i0}.\n\n(*This lemma states that for any non-empty finite type, there exists an element within that type at which a given function attains its maximum value over the entire type.*)\nLemma eq_bigmax (I : finType) F : #|I| > 0 -> {i0 : I | \\max_i F i = F i0}.\n\n(*This lemma states that for natural numbers, a base raised to the power of a sum is equal to the product of the base raised to each term in the sum. The sum and product are taken over the values of a function for a filtered sequence of indices.*)\nLemma expn_sum m I r (P : pred I) F :\n (m ^ (\\sum_(i <- r | P i) F i) = \\prod_(i <- r | P i) m ^ F i)%N.\n\n(*This lemma provides a reflection to show a logical equivalence for natural numbers: a given number is divisible by the least common multiple of a set of numbers if and only if it is a multiple of every number in that set. The set of numbers is given by a function over a filtered subset of a finite type, and the least common multiple of an empty set is taken to be one.*)\nLemma dvdn_biglcmP (I : finType) (P : pred I) F m :\n reflect (forall i, P i -> F i %| m) (\\big[lcmn/1%N]_(i | P i) F i %| m).\n\n(*This lemma states that if a natural number divides a specific value in a set of natural numbers, then it also divides the least common multiple of the entire set. The set is generated by a function's values over a filtered subset of a finite type.*)\nLemma biglcmn_sup (I : finType) i0 (P : pred I) F m :\n P i0 -> m %| F i0 -> m %| \\big[lcmn/1%N]_(i | P i) F i.\n\nArguments biglcmn_sup [I] i0 [P F m].\n\n(*This lemma provides a reflection to show a logical equivalence for natural numbers: a given number is a common divisor of a set of numbers if and only if it divides the greatest common divisor of that set. The set of numbers is given by a function over a filtered subset of a finite type, and the greatest common divisor of an empty set is taken to be zero.*)\nLemma dvdn_biggcdP (I : finType) (P : pred I) F m :\n reflect (forall i, P i -> m %| F i) (m %| \\big[gcdn/0]_(i | P i) F i).\n\n(*This lemma states that if one number in a set divides a given natural number, then the greatest common divisor of the entire set also divides that natural number.*)\nLemma biggcdn_inf (I : finType) i0 (P : pred I) F m :\n P i0 -> F i0 %| m -> \\big[gcdn/0]_(i | P i) F i %| m.", - "boot.prime": "From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path.\nFrom mathcomp Require Import choice fintype div bigop.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nReserved Notation \"pi ^'\" (format \"pi ^'\").\nReserved Notation \"pi .-nat\" (format \"pi .-nat\").\n\nModule Import PrimeDecompAux.\n\n(*This function recursively computes the quotient and remainder of a natural number upon division by two. It operates by repeatedly incrementing a quotient accumulator while decrementing the dividend by two until the dividend is less than two.*)\nFixpoint edivn2 q r := if r is r'.+2 then edivn2 q.+1 r' else (q, r).\n\n(*This lemma states that applying the `edivn2` function, with an initial quotient of zero, to a given natural number correctly computes its Euclidean division by two.*)\nLemma edivn2P n : edivn_spec n 2 (edivn2 0 n).\n\n(*This recursive function determines the prime factorization of a positive number with respect to the prime two. It returns a pair containing the exponent of two and the remaining odd factor.*)\nFixpoint elogn2 e q r {struct q} :=\n match q, r with\n | 0, _ | _, 0 => (e, q)\n | q'.+1, 1 => elogn2 e.+1 q' q'\n | q'.+1, r'.+2 => elogn2 e q' r'\n end.\nArguments elogn2 : simpl nomatch.\n\n(*This specification describes the property of a pair of natural numbers, an exponent and a factor, in relation to a given positive number. It asserts that the given number equals two raised to the power of the exponent, multiplied by an odd number derived from the factor.*)\nVariant elogn2_spec n : nat * nat -> Type :=\n Elogn2Spec e m of n = 2 ^ e * m.*2.+1 : elogn2_spec n (e, m).\n\n(*This lemma states that the `elogn2` function correctly computes the exponent of two and the remaining odd factor for any positive natural number, satisfying its corresponding specification.*)\nLemma elogn2P n : elogn2_spec n.+1 (elogn2 0 n n).\n\n(*This function conditionally returns one of two provided values of the same type. It returns the first value if a given natural number is non-zero, and the second value if the number is zero.*)\nDefinition ifnz T n (x y : T) := if n is 0 then y else x.\n\n(*This specification describes the behavior of a conditional function through two cases based on a natural number. One case asserts that the function returns the first of two values if the number is positive, and the other case asserts that it returns the second value if the number is zero.*)\nVariant ifnz_spec T n (x y : T) : T -> Type :=\n(*A constructor for a dependent type that certifies a natural number is positive. It packages a proof that the number is greater than zero.*)\n | IfnzPos of n > 0 : ifnz_spec n x y x\n(*A constructor for a dependent type that certifies a natural number is zero. It packages a proof that the number is equal to zero.*)\n | IfnzZero of n = 0 : ifnz_spec n x y y.\n\n(*This lemma states that the `ifnz` function behaves according to its specification, choosing between two values based on whether a given natural number is zero or non-zero.*)\nLemma ifnzP T n (x y : T) : ifnz_spec n x y (ifnz n x y).\n\n(*This function expands a sorted list of divisors with a new prime factor. It takes a pair representing a prime and its exponent, and an existing list of divisors, and returns a new sorted list containing all divisors formed by including the new prime factor.*)\nDefinition add_divisors f divs :=\n let: (p, e) := f in\n let add1 divs' := merge leq (map (NatTrec.mul p) divs') divs in\n iter e add1 divs.\n\nImport NatTrec.\n\n(*This function computes a single multiplicative term used in calculating Euler's totient function. It takes a pair representing a prime factor and its exponent, along with an accumulator, and multiplies the accumulator by the prime minus one and the prime raised to its exponent minus one.*)\nDefinition add_totient_factor f m := let: (p, e) := f in p.-1 * p ^ e.-1 * m.\n\n(*This function prepends a pair, representing a prime factor and its exponent, to a list of such pairs, but only if the exponent is non-zero. If the exponent is zero, it returns the original list unchanged.*)\nDefinition cons_pfactor (p e : nat) pd := ifnz e ((p, e) :: pd) pd.\n\n(*This notation offers a concise syntax for conditionally adding a prime factor and its exponent to the front of a list of prime factors, with the addition occurring only if the exponent is a positive number.*)\nNotation \"p ^? e :: pd\" := (cons_pfactor p e pd)\n (at level 30, e at level 30, pd at level 60) : nat_scope.\n\nEnd PrimeDecompAux.\n\n(*This function transforms a pair of natural numbers, representing a numeric factor and an exponent. It converts the first element into a dedicated numeric type while leaving the exponent as a natural number.*)\nDefinition NumFactor (f : nat * nat) := ([Num of f.1], f.2).\n\n(*This function computes the value resulting from raising a natural number base to a natural number exponent.*)\nDefinition pfactor p e := p ^ e.\n\nSection prime_decomp.\n\nImport NatTrec.\n\n(*This function is a recursive helper that implements the core logic of a prime factorization algorithm. It takes a set of numerical state parameters to efficiently discover the prime factors and their exponents for a given number, returning them as a list of pairs.*)\nLocal Fixpoint prime_decomp_rec m k a b c e :=\n let p := k.*2.+1 in\n if a is a'.+1 then\n if b - (ifnz e 1 k - c) is b'.+1 then\n [rec m, k, a', b', ifnz c c.-1 (ifnz e p.-2 1), e] else\n if (b == 0) && (c == 0) then\n let b' := k + a' in [rec b'.*2.+3, k, a', b', k.-1, e.+1] else\n let bc' := ifnz e (ifnz b (k, 0) (edivn2 0 c)) (b, c) in\n p ^? e :: ifnz a' [rec m, k.+1, a'.-1, bc'.1 + a', bc'.2, 0] [:: (m, 1)]\n else if (b == 0) && (c == 0) then [:: (p, e.+2)] else p ^? e :: [:: (m, 1)]\nwhere \"[ 'rec' m , k , a , b , c , e ]\" := (prime_decomp_rec m k a b c e).\n\n(*This function computes the prime factorization of a given natural number. It returns a list of pairs, where each pair contains a prime factor and its corresponding multiplicity.*)\nDefinition prime_decomp n :=\n let: (e2, m2) := elogn2 0 n.-1 n.-1 in\n if m2 < 2 then 2 ^? e2 :: 3 ^? m2 :: [::] else\n let: (a, bc) := edivn m2.-2 3 in\n let: (b, c) := edivn (2 - bc) 2 in\n 2 ^? e2 :: [rec m2.*2.+1, 1, a, b, c, 0].\n\nEnd prime_decomp.\n\n(*This function extracts the list of distinct prime factors from the prime decomposition of a given natural number.*)\nDefinition primes n := unzip1 (prime_decomp n).\n\n(*This function determines if a natural number is prime. It returns true if the number's prime decomposition consists of a single entry: the number itself with an exponent of one.*)\nDefinition prime p := if prime_decomp p is [:: (_ , 1)] then true else false.\n\n(*This definition establishes a type for decidable predicates on natural numbers.*)\nDefinition nat_pred := simpl_pred nat.\n\n(*This definition establishes a type alias for natural numbers that are intended as arguments for prime-related functions, with coercions that allow it to represent both a plain number and the cardinality of a finite set.*)\nDefinition pi_arg := nat.\nCoercion pi_arg_of_nat (n : nat) : pi_arg := n.\nCoercion pi_arg_of_fin_pred T pT (A : @fin_pred_sort T pT) : pi_arg := #|A|.\nArguments pi_arg_of_nat n /.\nArguments pi_arg_of_fin_pred {T pT} A /.\n(*This function creates a predicate from a natural number. The resulting predicate holds true for any number that is a prime factor of the original number.*)\nDefinition pi_of (n : pi_arg) : nat_pred := [pred p in primes n].\n\n(*This notation represents the predicate that determines if a number is a prime factor of the given natural number `n`.*)\nNotation \"\\pi ( n )\" := (pi_of n) (format \"\\pi ( n )\") : nat_scope.\n(*This notation represents the predicate that determines if a number is a prime factor of the cardinality of a given finite set `A`.*)\nNotation \"\\p 'i' ( A )\" := \\pi(#|A|) (format \"\\p 'i' ( A )\") : nat_scope.\n\n(*This function finds the smallest prime factor of a given natural number, returning one if the number has no prime factors.*)\nDefinition pdiv n := head 1 (primes n).\n\n(*This function finds the largest prime factor of a given natural number, returning one if the number has no prime factors.*)\nDefinition max_pdiv n := last 1 (primes n).\n\n(*This function generates a sorted list of all positive divisors of a given natural number by iteratively combining its prime factors.*)\nDefinition divisors n := foldr add_divisors [:: 1] (prime_decomp n).\n\n(*This function calculates Euler's totient for a given natural number, which is the count of positive integers up to that number that are relatively prime to it.*)\nDefinition totient n := foldr add_totient_factor (n > 0) (prime_decomp n).\n\n(*This lemma asserts the correctness of the prime decomposition function, ensuring that the original number can be reconstructed by multiplying the prime powers from the resulting list and that all factors in the list are prime.*)\nLemma prime_decomp_correct :\n let pd_val pd := \\prod_(f <- pd) pfactor f.1 f.2 in\n let lb_dvd q m := ~~ has [pred d | d %| m] (index_iota 2 q) in\n let pf_ok f := lb_dvd f.1 f.1 && (0 < f.2) in\n let pd_ord q pd := path ltn q (unzip1 pd) in\n let pd_ok q n pd := [/\\ n = pd_val pd, all pf_ok pd & pd_ord q pd] in\n forall n, n > 0 -> pd_ok 1 n (prime_decomp n).\n\n(*This lemma states that a natural number is not prime if and only if it is less than two or it has a divisor strictly between one and itself.*)\nLemma primePn n :\n reflect (n < 2 \\/ exists2 d, 1 < d < n & d %| n) (~~ prime n).\n\n(*This lemma states that if a natural number greater than or equal to two is not prime, then there exists a natural number that is a divisor of it and is strictly between one and the number itself.*)\nLemma primeNsig n : ~~ prime n -> 2 <= n -> { d : nat | 1 < d < n & d %| n }.\n\n(*This lemma states that a natural number is prime if and only if it is greater than one and all of its divisors are either one or the number itself.*)\nLemma primeP p :\n reflect (p > 1 /\\ forall d, d %| p -> xpred2 1 p d) (prime p).\n\n(*This lemma states that for a prime number, any divisor that is not one must be equal to the prime number itself.*)\nLemma prime_nt_dvdP d p : prime p -> d != 1 -> reflect (d = p) (d %| p).\n\nArguments primeP {p}.\nArguments primePn {n}.\n\n(*This lemma states that any prime number is strictly greater than one.*)\nLemma prime_gt1 p : prime p -> 1 < p.\n\n(*This lemma states that any prime number is strictly greater than zero.*)\nLemma prime_gt0 p : prime p -> 0 < p.\n\n#[global] Hint Resolve prime_gt1 prime_gt0 : core.\n\n(*This lemma states that any natural number greater than zero is equal to the product of the prime factors from its prime decomposition, each raised to its corresponding exponent.*)\nLemma prod_prime_decomp n :\n n > 0 -> n = \\prod_(f <- prime_decomp n) f.1 ^ f.2.\n\n(*This lemma states that any prime number is either equal to two or is an odd number.*)\nLemma even_prime p : prime p -> p = 2 \\/ odd p.\n\n(*This lemma states that a prime number is not odd if and only if it is equal to two.*)\nLemma prime_oddPn p : prime p -> reflect (p = 2) (~~ odd p).\n\n(*This lemma states that any odd prime number is strictly greater than two.*)\nLemma odd_prime_gt2 p : odd p -> prime p -> p > 2.\n\n(*This lemma states that if a pair, consisting of a base and an exponent, is an element of the prime decomposition of a natural number, then the base is a prime number, the exponent is greater than zero, and the base raised to the power of the exponent divides the original number.*)\nLemma mem_prime_decomp n p e :\n (p, e) \\in prime_decomp n -> [/\\ prime p, e > 0 & p ^ e %| n].\n\n(*This lemma states that a prime number is coprime with another natural number if and only if the prime does not divide the other number.*)\nLemma prime_coprime p m : prime p -> coprime p m = ~~ (p %| m).\n\n(*This lemma states that for any two prime numbers, the first divides the second if and only if they are equal.*)\nLemma dvdn_prime2 p q : prime p -> prime q -> (p %| q) = (p == q).\n\n(*This lemma states that a prime number never divides one.*)\nLemma Euclid_dvd1 p : prime p -> (p %| 1) = false.\n\n(*This lemma, known as Euclid's lemma, states that a prime number divides the product of two natural numbers if and only if it divides at least one of those numbers.*)\nLemma Euclid_dvdM m n p : prime p -> (p %| m * n) = (p %| m) || (p %| n).\n\n(*This lemma generalizes Euclid's lemma, stating that a prime number divides a finite product of natural numbers if and only if it divides at least one of the factors in the product.*)\nLemma Euclid_dvd_prod (I : Type) (r : seq I) (P : pred I) (f : I -> nat) p :\n prime p ->\n p %| \\prod_(i <- r | P i) f i = \\big[orb/false]_(i <- r | P i) (p %| f i).\n\n(*This lemma states that a prime number divides a natural number raised to a positive power if and only if the prime divides the base number and the exponent is greater than zero.*)\nLemma Euclid_dvdX m n p : prime p -> (p %| m ^ n) = (p %| m) && (n > 0).\n\n(*This lemma states that a natural number is a member of the sequence of prime factors of another natural number if and only if it is prime, the second number is greater than zero, and it divides the second number.*)\nLemma mem_primes p n : (p \\in primes n) = [&& prime p, n > 0 & p %| n].\n\n(*This lemma states that the sequence of prime factors of any natural number is sorted in strictly ascending order.*)\nLemma sorted_primes n : sorted ltn (primes n).\n\n(*This lemma states that every element in the sequence of prime factors of a natural number is a prime number.*)\nLemma all_prime_primes n : all prime (primes n).\n\n(*This lemma states that the sequences of prime factors of two natural numbers are equivalent as multisets if and only if they are identical as sequences.*)\nLemma eq_primes m n : (primes m =i primes n) <-> (primes m = primes n).\n\n(*This lemma states that the sequence of prime factors of any natural number contains no duplicate elements.*)\nLemma primes_uniq n : uniq (primes n).\n\n(*This lemma states that the smallest prime divisor of a natural number is a member of its set of prime divisors if and only if the number is greater than one.*)\nLemma pi_pdiv n : (pdiv n \\in \\pi(n)) = (n > 1).\n\n(*This lemma states that for any natural number greater than one, its smallest prime divisor is a prime number.*)\nLemma pdiv_prime n : 1 < n -> prime (pdiv n).\n\n(*This lemma states that the smallest prime divisor of a natural number divides that number.*)\nLemma pdiv_dvd n : pdiv n %| n.\n\n(*This lemma states that the largest prime divisor of a natural number is a member of its set of prime divisors if and only if the number is greater than one.*)\nLemma pi_max_pdiv n : (max_pdiv n \\in \\pi(n)) = (n > 1).\n\n(*This lemma states that for any natural number greater than one, its largest prime divisor is a prime number.*)\nLemma max_pdiv_prime n : n > 1 -> prime (max_pdiv n).\n\n(*This lemma states that the largest prime divisor of a natural number divides that number.*)\nLemma max_pdiv_dvd n : max_pdiv n %| n.\n\n(*This lemma states that for any positive natural number, its smallest prime divisor is less than or equal to the number itself.*)\nLemma pdiv_leq n : 0 < n -> pdiv n <= n.\n\n(*This lemma states that for any positive natural number, its largest prime divisor is less than or equal to the number itself.*)\nLemma max_pdiv_leq n : 0 < n -> max_pdiv n <= n.\n\n(*This lemma states that the smallest prime divisor of any natural number is a positive number.*)\nLemma pdiv_gt0 n : 0 < pdiv n.\n\n(*This lemma states that the largest prime divisor of any natural number is a positive number.*)\nLemma max_pdiv_gt0 n : 0 < max_pdiv n.\n\n#[global] Hint Resolve pdiv_gt0 max_pdiv_gt0 : core.\n\n(*This lemma states that for any natural number, its smallest prime divisor is less than or equal to any of its divisors that are greater than one.*)\nLemma pdiv_min_dvd m d : 1 < d -> d %| m -> pdiv m <= d.\n\n(*This lemma states that any prime factor of a natural number is less than or equal to the largest prime divisor of that number.*)\nLemma max_pdiv_max n p : p \\in \\pi(n) -> p <= max_pdiv n.\n\n(*This lemma states that if a positive natural number is strictly less than the square of its smallest prime divisor, then that number is prime.*)\nLemma ltn_pdiv2_prime n : 0 < n -> n < pdiv n ^ 2 -> prime n.\n\n(*This lemma establishes that a natural number is not prime if and only if either the number is less than two, or there exists a prime number whose square is less than or equal to the number and which divides the number.*)\nLemma primePns n :\n reflect (n < 2 \\/ exists p, [/\\ prime p, p ^ 2 <= n & p %| n]) (~~ prime n).\n\nArguments primePns {n}.\n\n(*This lemma states that for any natural number greater than one, there exists a prime number that divides it.*)\nLemma pdivP n : n > 1 -> {p | prime p & p %| n}.\n\n \n(*This lemma states that the list of prime factors of a natural number is empty if and only if the number is less than two.*)\nLemma primes_eq0 n : (primes n == [::]) = (n < 2).\n\n(*This lemma states that for any two positive natural numbers, a prime number is a factor of their product if and only if it is a factor of at least one of the numbers.*)\nLemma primesM m n p : m > 0 -> n > 0 ->\n (p \\in primes (m * n)) = (p \\in primes m) || (p \\in primes n).\n\n(*This lemma states that for any positive exponent, the list of prime factors of a natural number raised to that exponent is the same as the list of prime factors of the original number.*)\nLemma primesX m n : n > 0 -> primes (m ^ n) = primes m.\n\n(*This lemma states that if a natural number is prime, its list of prime factors is a singleton list containing that number.*)\nLemma primes_prime p : prime p -> primes p = [:: p].\n\n(*This lemma states that two positive natural numbers are coprime if and only if their lists of prime factors have no elements in common.*)\nLemma coprime_has_primes m n :\n 0 < m -> 0 < n -> coprime m n = ~~ has [in primes m] (primes n).\n\n(*This lemma states that for any prime number, its smallest prime divisor is the number itself.*)\nLemma pdiv_id p : prime p -> pdiv p = p.\n\n(*This lemma states that for any prime number raised to a positive power, its smallest prime divisor is the prime base itself.*)\nLemma pdiv_pfactor p k : prime p -> pdiv (p ^ k.+1) = p.\n\n(*This lemma asserts the existence of a prime number strictly greater than any given natural number.*)\nLemma prime_above m : {p | m < p & prime p}.\n\n(*This fixpoint defines a recursive helper function that counts the number of times a natural number divides another, using a recursion limit to ensure termination.*)\nFixpoint logn_rec d m r :=\n match r, edivn m d with\n | r'.+1, (_.+1 as m', 0) => (logn_rec d m' r').+1\n | _, _ => 0\n end.\n\n(*This definition computes the p-adic valuation of a natural number, which is the exponent of a given prime in the prime factorization of the number. It returns zero if the first argument is not a prime number.*)\nDefinition logn p m := if prime p then logn_rec p m m else 0.\n\n(*This lemma provides a recursive characterization of the p-adic valuation of a natural number. It states that if a prime divides a positive number, the valuation is one plus the valuation of the quotient; otherwise, the valuation is zero.*)\nLemma lognE p m :\n logn p m = if [&& prime p, 0 < m & p %| m] then (logn p (m %/ p)).+1 else 0.\n\n(*This lemma states that the p-adic valuation of a natural number with respect to a prime is positive if and only if that prime is a factor of the number.*)\nLemma logn_gt0 p n : (0 < logn p n) = (p \\in primes n).\n\n(*This lemma states that if a natural number is strictly smaller than a prime number, then its p-adic valuation with respect to that prime is zero.*)\nLemma ltn_log0 p n : n < p -> logn p n = 0.\n\n(*This lemma states that for any prime, the p-adic valuation of zero is zero.*)\nLemma logn0 p : logn p 0 = 0.\n\n(*This lemma states that for any prime, the p-adic valuation of one is zero.*)\nLemma logn1 p : logn p 1 = 0.\n\n(*This lemma states that for any prime and any natural number, the prime raised to the power of its p-adic valuation in the number is a positive value.*)\nLemma pfactor_gt0 p n : 0 < p ^ logn p n.\n\n#[global] Hint Resolve pfactor_gt0 : core.\n\n(*This lemma states that for a given prime and a positive natural number, the prime raised to a certain power divides the number if and only if that power is less than or equal to the prime's p-adic valuation in the number.*)\nLemma pfactor_dvdn p n m : prime p -> m > 0 -> (p ^ n %| m) = (n <= logn p m).\n\n(*This lemma states that for any prime and any natural number, the prime raised to the power of its p-adic valuation in the number divides that number.*)\nLemma pfactor_dvdnn p n : p ^ logn p n %| n.\n\n(*This lemma states that for two primes, the p-adic valuation of one with respect to the other is equal to one if the primes are the same, and zero otherwise.*)\nLemma logn_prime p q : prime q -> logn p q = (p == q).\n\n(*This lemma states that for a prime and a positive natural number, the prime is coprime to the result of dividing the number by its p-part, which is the prime raised to its p-adic valuation.*)\nLemma pfactor_coprime p n :\n prime p -> n > 0 -> {m | coprime p m & n = m * p ^ logn p n}.\n\n(*This lemma states that for a given prime natural number, the p-adic valuation of that prime raised to some power is equal to that power.*)\nLemma pfactorK p n : prime p -> logn p (p ^ n) = n.\n\n(*This lemma asserts that for a given prime natural number, the p-adic valuation of that prime raised to some power, using a prime divisor of that result as the base, is equal to the exponent.*)\nLemma pfactorKpdiv p n : prime p -> logn (pdiv (p ^ n)) (p ^ n) = n.\n\n(*This lemma states that for any prime natural number, if a first natural number divides a second positive natural number, then the p-adic valuation of the divisor is less than or equal to the p-adic valuation of the dividend.*)\nLemma dvdn_leq_log p m n : 0 < n -> m %| n -> logn p m <= logn p n.\n\n(*This lemma states that for any prime natural number and any positive natural number, the p-adic valuation of the positive number is strictly less than the number itself.*)\nLemma ltn_logl p n : 0 < n -> logn p n < n.\n\n(*This lemma states that if a natural number is coprime to a prime natural number, then the p-adic valuation of the product of that number and another natural number is equal to the p-adic valuation of the second number alone.*)\nLemma logn_Gauss p m n : coprime p m -> logn p (m * n) = logn p n.\n\n(*This lemma states that if a natural number is coprime to a prime natural number, its p-adic valuation with respect to that prime is zero.*)\nLemma logn_coprime p m : coprime p m -> logn p m = 0.\n\n(*This lemma states that for any prime natural number, the p-adic valuation of the product of two positive natural numbers is equal to the sum of their individual p-adic valuations.*)\nLemma lognM p m n : 0 < m -> 0 < n -> logn p (m * n) = logn p m + logn p n.\n\n(*This lemma states that for any prime natural number, the p-adic valuation of a natural number raised to a power is equal to the product of the exponent and the p-adic valuation of the base number.*)\nLemma lognX p m n : logn p (m ^ n) = n * logn p m.\n\n(*This lemma states that for a prime natural number, if a first natural number divides a second one, the p-adic valuation of their quotient is the difference between the p-adic valuation of the dividend and the p-adic valuation of the divisor.*)\nLemma logn_div p m n : m %| n -> logn p (n %/ m) = logn p n - logn p m.\n\n(*This lemma provides a characterization of the divisors of a prime power. It states that for a prime natural number, a number is a divisor of that prime raised to a power if and only if the divisor itself can be expressed as that same prime raised to a smaller or equal power.*)\nLemma dvdn_pfactor p d n : prime p ->\n reflect (exists2 m, m <= n & d = p ^ m) (d %| p ^ n).\n\n(*This lemma describes the structure of the prime decomposition of a natural number. It states that the prime decomposition is a sequence of pairs, where each pair consists of a prime factor of the number and its corresponding p-adic valuation.*)\nLemma prime_decompE n : prime_decomp n = [seq (p, logn p n) | p <- primes n].\n\n(*This lemma provides a way to compute the integer quotient of two natural numbers by counting. It states that the quotient of a first number divided by a second is equal to the total count of natural numbers between one and the first number, inclusive, that are divisible by the second number.*)\nLemma divn_count_dvd d n : n %/ d = \\sum_(1 <= i < n.+1) (d %| i).\n\n(*This lemma presents a formula for the p-adic valuation of a natural number. It asserts that for a given prime, the p-adic valuation of another number is the sum, over all positive powers of the prime, of a value indicating whether that power divides the number.*)\nLemma logn_count_dvd p n : prime p -> logn p n = \\sum_(1 <= k < n) (p ^ k %| n).\n\n(*This definition introduces a function that computes the truncated integer logarithm of a natural number with respect to a given base. It calculates the largest integer exponent such that the base raised to that exponent is less than or equal to the number. The result is zero if the base is one or less.*)\nDefinition trunc_log p n :=\n let fix loop n k :=\n if k is k'.+1 then if p <= n then (loop (n %/ p) k').+1 else 0 else 0\n in if p <= 1 then 0 else loop n n.\n\n(*This lemma states that the truncated integer logarithm of zero, for any base, is zero.*)\nLemma trunc_log0 p : trunc_log p 0 = 0.\n\n(*This lemma states that the truncated integer logarithm of one, for any base greater than one, is zero.*)\nLemma trunc_log1 p : trunc_log p 1 = 0.\n\n(*This lemma establishes the fundamental bounding property of the truncated integer logarithm. It states that for a base greater than one and a positive number, if k is the truncated logarithm, then the number is greater than or equal to the base raised to the power of k, and strictly less than the base raised to the power of k plus one.*)\nLemma trunc_log_bounds p n :\n 1 < p -> 0 < n -> let k := trunc_log p n in p ^ k <= n < p ^ k.+1.\n\n(*This lemma provides the lower bound for the truncated integer logarithm. It asserts that for a base greater than one and a positive number, the base raised to the power of its truncated logarithm is less than or equal to the number itself.*)\nLemma trunc_logP p n : 1 < p -> 0 < n -> p ^ trunc_log p n <= n.\n\n(*This lemma provides the strict upper bound for the truncated integer logarithm. It asserts that for a base greater than one, a number is strictly less than the base raised to the power of its truncated logarithm plus one.*)\nLemma trunc_log_ltn p n : 1 < p -> n < p ^ (trunc_log p n).+1.\n\n(*This lemma shows that the truncated integer logarithm is the maximal exponent satisfying a power inequality. It states that for a base greater than one, if the base raised to some power is less than or equal to a given number, then that power must be less than or equal to the truncated integer logarithm of that number.*)\nLemma trunc_log_max p k j : 1 < p -> p ^ j <= k -> j <= trunc_log p k.\n\n(*This lemma characterizes when the truncated integer logarithm evaluates to zero. It states that the truncated logarithm of a number with respect to a base is zero if and only if either the base is less than or equal to one, or the number is strictly less than the base.*)\nLemma trunc_log_eq0 p n : (trunc_log p n == 0) = (p <= 1) || (n <= p.-1).\n\n(*This lemma characterizes when the truncated integer logarithm is positive. It states that the truncated logarithm of a number with respect to a base is greater than zero if and only if the base is greater than one and the number is greater than or equal to the base.*)\nLemma trunc_log_gt0 p n : (0 < trunc_log p n) = (1 < p) && (p.-1 < n).\n\n(*This lemma states that the truncated integer logarithm with a base of zero is always zero, regardless of the other number.*)\nLemma trunc_log0n n : trunc_log 0 n = 0.\n\n(*This lemma states that the truncated integer logarithm with a base of one is always zero, regardless of the other number.*)\nLemma trunc_log1n n : trunc_log 1 n = 0.\n\n(*This lemma states that the truncated integer logarithm function is monotonic. For a fixed base, if a first natural number is less than or equal to a second natural number, then the truncated logarithm of the first number is less than or equal to the truncated logarithm of the second.*)\nLemma leq_trunc_log p m n : m <= n -> trunc_log p m <= trunc_log p n.\n\n(*This lemma provides a condition for determining the value of a truncated integer logarithm. It states that for a base greater than one, if a number is between a power of the base and the next successive power, then its truncated logarithm with respect to that base is equal to the exponent of the lower-bounding power.*)\nLemma trunc_log_eq p n k : 1 < p -> p ^ n <= k < p ^ n.+1 -> trunc_log p k = n.\n\n(*This lemma states that for any base greater than one, the truncated integer logarithm of the base itself is one.*)\nLemma trunc_lognn p : 1 < p -> trunc_log p p = 1.\n\n(*This lemma shows that the truncated integer logarithm acts as an inverse to exponentiation. It states that for a base greater than one, the truncated logarithm of the base raised to some power is equal to that power.*)\nLemma trunc_expnK p n : 1 < p -> trunc_log p (p ^ n) = n.\n\n(*This lemma provides a rule for the truncated integer logarithm of a product involving the base. It states that for a base greater than one and a positive number, the truncated logarithm of the product of the base and the number is equal to one plus the truncated logarithm of the number.*)\nLemma trunc_logMp p n : 1 < p -> 0 < n ->\n trunc_log p (p * n) = (trunc_log p n).+1.\n\n(*This lemma specifies the behavior of the truncated integer logarithm with base two when its argument is doubled. It states that for any positive number, the truncated logarithm of twice that number is one greater than the truncated logarithm of the original number.*)\nLemma trunc_log2_double n : 0 < n -> trunc_log 2 n.*2 = (trunc_log 2 n).+1.\n\n(*This lemma states that for any natural number greater than one, its truncated base-2 logarithm is equal to one plus the truncated base-2 logarithm of its integer division by two.*)\nLemma trunc_log2S n : 1 < n -> trunc_log 2 n = (trunc_log 2 n./2).+1.\n\n(*This definition introduces the 'upper logarithm' function, which for a given base and a natural number, computes the smallest integer exponent such that the base raised to this exponent is greater than or equal to the number. If the base is less than or equal to one, the result is zero.*)\nDefinition up_log p n :=\n if (p <= 1) then 0 else\n let v := trunc_log p n in if n <= p ^ v then v else v.+1.\n\n(*This lemma states that the upper logarithm of zero for any base is always zero.*)\nLemma up_log0 p : up_log p 0 = 0.\n\n(*This lemma states that the upper logarithm of one for any base is always zero.*)\nLemma up_log1 p : up_log p 1 = 0.\n\n(*This lemma establishes that the upper logarithm of a natural number to a given base is equal to zero if and only if either the base is less than or equal to one or the number itself is less than or equal to one.*)\nLemma up_log_eq0 p n : (up_log p n == 0) = (p <= 1) || (n <= 1).\n\n(*This lemma asserts that the upper logarithm of a natural number to a given base is greater than zero if and only if both the base and the number are strictly greater than one.*)\nLemma up_log_gt0 p n : (0 < up_log p n) = (1 < p) && (1 < n).\n\n(*This lemma states that for a base and a natural number both greater than one, the number is strictly bounded below by the base raised to the power of its upper logarithm minus one, and bounded above by the base raised to the power of its upper logarithm.*)\nLemma up_log_bounds p n :\n 1 < p -> 1 < n -> let k := up_log p n in p ^ k.-1 < n <= p ^ k.\n\n(*This lemma states that for any base greater than one, a given natural number is always less than or equal to the base raised to the power of the number's upper logarithm with respect to that base.*)\nLemma up_logP p n : 1 < p -> n <= p ^ up_log p n.\n\n(*This lemma states that for a base and a natural number both greater than one, the number is strictly greater than the base raised to the power of its upper logarithm minus one.*)\nLemma up_log_gtn p n : 1 < p -> 1 < n -> p ^ (up_log p n).-1 < n.\n\n(*This lemma shows that for a base greater than one, if a first natural number is less than or equal to the base raised to the power of a second natural number, then the upper logarithm of the first number is less than or equal to the second number.*)\nLemma up_log_min p k j : 1 < p -> k <= p ^ j -> up_log p k <= j.\n\n(*This lemma states that the upper logarithm function is non-decreasing with respect to its second argument; that is, if a first natural number is less than or equal to a second natural number, then the upper logarithm of the first number is less than or equal to the upper logarithm of the second number for the same base.*)\nLemma leq_up_log p m n : m <= n -> up_log p m <= up_log p n.\n\n(*This lemma states that for a base greater than one, if a natural number is strictly greater than the base raised to some power and less than or equal to the base raised to that power plus one, then its upper logarithm with that base is equal to that power plus one.*)\nLemma up_log_eq p n k : 1 < p -> p ^ n < k <= p ^ n.+1 -> up_log p k = n.+1.\n\n(*This lemma states that for any base greater than one, the upper logarithm of the base itself is one.*)\nLemma up_lognn p : 1 < p -> up_log p p = 1.\n\n(*This lemma states that for a base greater than one, the upper logarithm of the base raised to some power is equal to that power, showing that upper logarithm is a left inverse to exponentiation.*)\nLemma up_expnK p n : 1 < p -> up_log p (p ^ n) = n.\n\n(*This lemma states that for a base greater than one and a positive natural number, the upper logarithm of the product of the base and the number is equal to one plus the upper logarithm of the number.*)\nLemma up_logMp p n : 1 < p -> 0 < n -> up_log p (p * n) = (up_log p n).+1.\n\n(*This lemma states that for any positive natural number, the upper logarithm with base two of twice that number is equal to one plus the upper logarithm with base two of the number.*)\nLemma up_log2_double n : 0 < n -> up_log 2 n.*2 = (up_log 2 n).+1.\n\n(*This lemma states that for any positive natural number, the upper logarithm with base two of that number plus one is equal to one plus the upper logarithm with base two of the sum of one and the integer division of the original number by two.*)\nLemma up_log2S n : 0 < n -> up_log 2 n.+1 = (up_log 2 (n./2.+1)).+1.\n\n(*This lemma relates the upper logarithm and the truncated logarithm, stating that for a base and a number both greater than one, the upper logarithm of the number is equal to one plus the truncated logarithm of the number minus one.*)\nLemma up_log_trunc_log p n :\n 1 < p -> 1 < n -> up_log p n = (trunc_log p n.-1).+1.\n\n(*This lemma relates the truncated logarithm and the upper logarithm, stating that for a base greater than one and a positive number, the truncated logarithm of the number is equal to the upper logarithm of the number plus one, all decremented by one.*)\nLemma trunc_log_up_log p n :\n 1 < p -> 0 < n -> trunc_log p n = (up_log p n.+1).-1.\n\nCanonical nat_pred_pred := Eval hnf in [predType of nat_pred].\n\nCoercion nat_pred_of_nat (p : nat) : nat_pred := pred1 p.\n\nSection NatPreds.\n\nVariables (n : nat) (pi : nat_pred).\n\n(*This definition introduces the negation of a predicate on natural numbers, which is a new predicate that evaluates to true for any natural number for which the original predicate evaluates to false, and vice versa.*)\nDefinition negn : nat_pred := [predC pi].\n\n(*This definition specifies a predicate on natural numbers that is true if and only if the number is positive and all of its prime factors satisfy a given second predicate.*)\nDefinition pnat : pred nat := fun m => (m > 0) && all [in pi] (primes m).\n\n(*This definition computes the part of a natural number composed exclusively of prime factors that satisfy a given predicate. It is calculated as the product, for each prime number satisfying the predicate, of that prime raised to the power of its exponent in the prime factorization of the original number.*)\nDefinition partn := \\prod_(0 <= p < n.+1 | p \\in pi) p ^ logn p n.\n\nEnd NatPreds.\n\n(*A notation for the complement of a predicate on natural numbers. It yields a new predicate which is true when the original is false, and false when the original is true.*)\nNotation \"pi ^'\" := (negn pi) : nat_scope.\n\n(*A notation for a predicate on natural numbers which is true for a positive natural number if all of its prime factors satisfy the given input predicate.*)\nNotation \"pi .-nat\" := (pnat pi) : nat_scope.\n\n(*A notation representing the component of a natural number whose prime factors all satisfy a given predicate. It is the largest divisor of the number with this property.*)\nNotation \"n `_ pi\" := (partn n pi) : nat_scope.\n\nSection PnatTheory.\n\nImplicit Types (n p : nat) (pi rho : nat_pred).\n\n(*This lemma states that taking the complement of a predicate on natural numbers twice results in a predicate that is pointwise equal to the original predicate.*)\nLemma negnK pi : pi^'^' =i pi.\n\n(*This lemma asserts that if two predicates on natural numbers are pointwise equal, then their respective complements are also pointwise equal.*)\nLemma eq_negn pi1 pi2 : pi1 =i pi2 -> pi1^' =i pi2^'.\n\n(*This lemma states that for any two predicates on natural numbers, pointwise equality is equivalent to propositional equality, an instance of function extensionality.*)\nLemma eq_piP m n : \\pi(m) =i \\pi(n) <-> \\pi(m) = \\pi(n).\n\n(*This lemma asserts that the component of any natural number whose prime factors satisfy a given predicate is always strictly greater than zero.*)\nLemma part_gt0 pi n : 0 < n`_pi.\n\nHint Resolve part_gt0 : core.\n\n(*This lemma states that if a first predicate on natural numbers implies a second predicate, then for any given natural number, the component formed from prime factors satisfying the first predicate divides the component formed from prime factors satisfying the second predicate.*)\nLemma sub_in_partn pi1 pi2 n :\n {in \\pi(n), {subset pi1 <= pi2}} -> n`_pi1 %| n`_pi2.\n\n(*This lemma states that if two sets of prime numbers are identical when restricted to the prime factors of a given natural number, then their corresponding parts of that natural number are equal.*)\nLemma eq_in_partn pi1 pi2 n : {in \\pi(n), pi1 =i pi2} -> n`_pi1 = n`_pi2.\n\n(*This lemma states that if two sets of prime numbers are identical, then their corresponding parts of any given natural number are equal.*)\nLemma eq_partn pi1 pi2 n : pi1 =i pi2 -> n`_pi1 = n`_pi2.\n\n(*This lemma states that the part of a natural number corresponding to the complement of the complement of a set of primes is equal to the part corresponding to the original set of primes.*)\nLemma partnNK pi n : n`_pi^'^' = n`_pi.\n\n(*This lemma provides a way to compute the pi-part of a natural number `n` by stating that if `n` is less than or equal to another natural number `m`, its pi-part is the product of each prime `p` in the set `pi` raised to its exponent in the factorization of `n`, provided `p` is less than `m` plus one.*)\nLemma widen_partn m pi n :\n n <= m -> n`_pi = \\prod_(0 <= p < m.+1 | p \\in pi) p ^ logn p n.\n\n(*This lemma asserts that for two positive natural numbers, if the exponent of every prime from a given set of primes is the same in the prime factorization of both numbers, then the parts of these two numbers corresponding to that set of primes are equal.*)\nLemma eq_partn_from_log m n (pi : nat_pred) : 0 < m -> 0 < n ->\n {in pi, logn^~ m =1 logn^~ n} -> m`_pi = n`_pi.\n\n(*This lemma states that the part of the number zero corresponding to any set of primes is one.*)\nLemma partn0 pi : 0`_pi = 1.\n\n(*This lemma states that the part of the number one corresponding to any set of primes is one.*)\nLemma partn1 pi : 1`_pi = 1.\n\n(*This lemma states that for any two positive natural numbers, the part of their product corresponding to a given set of primes is equal to the product of their individual parts corresponding to the same set of primes.*)\nLemma partnM pi m n : m > 0 -> n > 0 -> (m * n)`_pi = m`_pi * n`_pi.\n\n(*This lemma shows that the part of a natural number raised to a power, corresponding to a given set of primes, is equal to the part of the base number raised to that same power.*)\nLemma partnX pi m n : (m ^ n)`_pi = m`_pi ^ n.\n\n(*This lemma establishes that if a natural number divides a positive natural number, then the part of the first number corresponding to a given set of primes divides the part of the second number corresponding to the same set of primes.*)\nLemma partn_dvd pi m n : n > 0 -> m %| n -> m`_pi %| n`_pi.\n\n(*This lemma defines the p-part of a natural number, for a given prime `p`, as `p` raised to the power of its exponent in the prime factorization of that number.*)\nLemma p_part p n : n`_p = p ^ logn p n.\n\n(*This lemma states that the p-part of a natural number is equal to one if and only if the prime `p` is not a factor of that number.*)\nLemma p_part_eq1 p n : (n`_p == 1) = (p \\notin \\pi(n)).\n\n(*This lemma states that the p-part of a natural number is greater than one if and only if the prime `p` is a factor of that number.*)\nLemma p_part_gt1 p n : (n`_p > 1) = (p \\in \\pi(n)).\n\n(*This lemma asserts that the set of prime factors of the pi-part of a natural number is equivalent to the set of prime factors of the original number that are also members of the set pi.*)\nLemma primes_part pi n : primes n`_pi = filter [in pi] (primes n).\n\n(*This lemma states that if a natural number `n` is less than another natural number `m`, filtering the sequence of integers from zero up to `m` minus one to keep only the prime factors of `n` results in the list of prime factors of `n`.*)\nLemma filter_pi_of n m : n < m -> filter \\pi(n) (index_iota 0 m) = primes n.\n\n(*This lemma states that for any positive natural number, its part corresponding to the set of its own prime factors is the number itself.*)\nLemma partn_pi n : n > 0 -> n`_\\pi(n) = n.\n\n(*This lemma states that for any positive natural number, its part corresponding to the set of all primes is the number itself.*)\nLemma partnT n : n > 0 -> n`_predT = n.\n\n(*This lemma asserts that two positive natural numbers are equal if and only if the exponent of every prime in their respective prime factorizations is the same.*)\nLemma eqn_from_log m n : 0 < m -> 0 < n -> logn^~ m =1 logn^~ n -> m = n.\n\n(*This lemma states that for any positive natural number, the product of its part corresponding to a set of primes and its part corresponding to the complement of that set of primes equals the original number.*)\nLemma partnC pi n : n > 0 -> n`_pi * n`_pi^' = n.\n\n(*This lemma states that the part of a natural number corresponding to any set of primes is a divisor of the original number.*)\nLemma dvdn_part pi n : n`_pi %| n.\n\n(*This lemma states that the exponent of a prime `p` in the factorization of the p-part of a natural number `m` is the same as the exponent of `p` in the factorization of `m` itself.*)\nLemma logn_part p m : logn p m`_p = logn p m.\n\n(*This lemma shows that for any two positive natural numbers, the part of their least common multiple corresponding to a given set of primes is equal to the least common multiple of their individual parts corresponding to the same set of primes.*)\nLemma partn_lcm pi m n : m > 0 -> n > 0 -> (lcmn m n)`_pi = lcmn m`_pi n`_pi.\n\n(*This lemma shows that for any two positive natural numbers, the part of their greatest common divisor corresponding to a given set of primes is equal to the greatest common divisor of their individual parts corresponding to the same set of primes.*)\nLemma partn_gcd pi m n : m > 0 -> n > 0 -> (gcdn m n)`_pi = gcdn m`_pi n`_pi.\n\n(*This lemma generalizes the distributivity of the part operation over the least common multiple, stating that for a family of positive natural numbers indexed over a finite set, the part of their least common multiple with respect to a set of primes is equal to the least common multiple of their individual parts.*)\nLemma partn_biglcm (I : finType) (P : pred I) F pi :\n (forall i, P i -> F i > 0) ->\n (\\big[lcmn/1%N]_(i | P i) F i)`_pi = \\big[lcmn/1%N]_(i | P i) (F i)`_pi.\n\n(*This lemma generalizes the distributivity of the part operation over the greatest common divisor, stating that for a non-empty family of positive natural numbers indexed over a finite set, the part of their greatest common divisor with respect to a set of primes is equal to the greatest common divisor of their individual parts.*)\nLemma partn_biggcd (I : finType) (P : pred I) F pi :\n #|SimplPred P| > 0 -> (forall i, P i -> F i > 0) ->\n (\\big[gcdn/0]_(i | P i) F i)`_pi = \\big[gcdn/0]_(i | P i) (F i)`_pi.\n\n(*This lemma states that for any two positive natural numbers, the exponent of a prime in the prime factorization of their greatest common divisor is the minimum of the exponents of that prime in their individual factorizations.*)\nLemma logn_gcd p m n : 0 < m -> 0 < n ->\n logn p (gcdn m n) = minn (logn p m) (logn p n).\n\n(*This lemma states that for any two positive natural numbers, the exponent of a prime in the prime factorization of their least common multiple is the maximum of the exponents of that prime in their individual factorizations.*)\nLemma logn_lcm p m n : 0 < m -> 0 < n ->\n logn p (lcmn m n) = maxn (logn p m) (logn p n).\n\n(*This lemma asserts that if a natural number is a pi-number, meaning all its prime factors are in the set pi, and the set pi is a subset of another set of primes rho within the context of the number's prime factors, then the number is also a rho-number.*)\nLemma sub_in_pnat pi rho n :\n {in \\pi(n), {subset pi <= rho}} -> pi.-nat n -> rho.-nat n.\n\n(*This lemma states that if two sets of primes, pi and rho, are identical when restricted to the prime factors of a given natural number, then the property of that number being a pi-number is equivalent to it being a rho-number.*)\nLemma eq_in_pnat pi rho n : {in \\pi(n), pi =i rho} -> pi.-nat n = rho.-nat n.\n\n(*This lemma states that if two sets of prime numbers are identical, then for any given natural number, the property of being a number whose prime factors are all in the first set is equivalent to the property of being a number whose prime factors are all in the second set.*)\nLemma eq_pnat pi rho n : pi =i rho -> pi.-nat n = rho.-nat n.\n\n(*This lemma states that for any set of prime numbers, the property that all prime factors of a given natural number belong to the double complement of the set is equivalent to the property that they belong to the original set.*)\nLemma pnatNK pi n : pi^'^'.-nat n = pi.-nat n.\n\n(*This lemma states that for any two sets of prime numbers, the property that all prime factors of a given natural number belong to the intersection of the two sets is equivalent to the conjunction of the properties that all prime factors belong to each of the two sets individually.*)\nLemma pnatI pi rho n : [predI pi & rho].-nat n = pi.-nat n && rho.-nat n.\n\n(*This lemma states that for a given set of prime numbers, all prime factors of the product of two natural numbers belong to the set if and only if all prime factors of each of the two numbers also belong to the set.*)\nLemma pnatM pi m n : pi.-nat (m * n) = pi.-nat m && pi.-nat n.\n\n(*This lemma states that for a given set of prime numbers, all prime factors of a natural number raised to a power belong to the set if and only if either all prime factors of the base belong to the set or the exponent is zero.*)\nLemma pnatX pi m n : pi.-nat (m ^ n) = pi.-nat m || (n == 0).\n\n(*This lemma states that for any set of prime numbers and any natural number, all prime factors of the part of the natural number corresponding to the set belong to that set.*)\nLemma part_pnat pi n : pi.-nat n`_pi.\n\n(*This lemma states that for a given set of prime numbers, the property that all prime factors of a prime number belong to the set is equivalent to the membership of that prime number in the set.*)\nLemma pnatE pi p : prime p -> pi.-nat p = (p \\in pi).\n\n(*This lemma states that for any prime number, all of its prime factors belong to the singleton set containing just that prime number.*)\nLemma pnat_id p : prime p -> p.-nat p.\n\n(*This lemma states that for any two positive natural numbers, their coprimality is equivalent to the property that all prime factors of the second number belong to the set of primes that are not factors of the first number.*)\nLemma coprime_pi' m n : m > 0 -> n > 0 -> coprime m n = \\pi(m)^'.-nat n.\n\n(*This lemma states that for any positive natural number, all of its prime factors belong to the set of its own prime factors.*)\nLemma pnat_pi n : n > 0 -> \\pi(n).-nat n.\n\n(*This lemma states that if a first natural number divides a second positive natural number, then the set of prime factors of the first number is a subset of the set of prime factors of the second number.*)\nLemma pi_of_dvd m n : m %| n -> n > 0 -> {subset \\pi(m) <= \\pi(n)}.\n\n(*This lemma states that for any two positive natural numbers, the set of prime factors of their product is equal to the union of their individual sets of prime factors.*)\nLemma pi_ofM m n : m > 0 -> n > 0 -> \\pi(m * n) =i [predU \\pi(m) & \\pi(n)].\n\n(*This lemma states that for any positive natural number and any set of prime numbers, the set of prime factors of the part of the natural number corresponding to the set is equal to the intersection of the set of all prime factors of the number and the given set of primes.*)\nLemma pi_of_part pi n : n > 0 -> \\pi(n`_pi) =i [predI \\pi(n) & pi].\n\n(*This lemma states that for any positive exponent, the set of prime factors of a natural number raised to that exponent is identical to the set of prime factors of the base number.*)\nLemma pi_of_exp p n : n > 0 -> \\pi(p ^ n) = \\pi(p).\n\n(*This lemma states that for any prime number, its set of prime factors is equal to the singleton set containing only that prime number itself.*)\nLemma pi_of_prime p : prime p -> \\pi(p) =i (p : nat_pred).\n\n(*This lemma states that for a positive natural number and a prime number, the property that all prime factors of the natural number are different from the given prime is equivalent to the given prime not being a member of the set of prime factors of the natural number.*)\nLemma p'natEpi p n : n > 0 -> p^'.-nat n = (p \\notin \\pi(n)).\n\n(*This lemma states that for a prime number and any natural number, the property that all prime factors of the natural number are different from the given prime is equivalent to the boolean property that the given prime does not divide the natural number.*)\nLemma p'natE p n : prime p -> p^'.-nat n = ~~ (p %| n).\n\n(*This lemma states that if all prime factors of a natural number belong to a given set of primes, then any prime factor of that natural number must also be an element of that set.*)\nLemma pnatPpi pi n p : pi.-nat n -> p \\in \\pi(n) -> p \\in pi.\n\n(*This lemma states that if a first natural number divides a second one, and all prime factors of the second number belong to a given set of primes, then all prime factors of the first number also belong to that set.*)\nLemma pnat_dvd m n pi : m %| n -> pi.-nat n -> pi.-nat m.\n\n(*This lemma states that if a natural number divides another and all prime factors of the dividend belong to a given set of primes, then all prime factors of the quotient also belong to that set.*)\nLemma pnat_div m n pi : m %| n -> pi.-nat n -> pi.-nat (n %/ m).\n\n(*This lemma states that if all prime factors of a first natural number belong to a given set of primes, and all prime factors of a second natural number belong to the complement of that set, then the two natural numbers are coprime.*)\nLemma pnat_coprime pi m n : pi.-nat m -> pi^'.-nat n -> coprime m n.\n\n(*This lemma states that if all prime factors of a first natural number belong to the complement of a given set of primes, and all prime factors of a second natural number belong to that set, then the two natural numbers are coprime.*)\nLemma p'nat_coprime pi m n : pi^'.-nat m -> pi.-nat n -> coprime m n.\n\n(*This lemma states that if all prime factors of a first natural number belong to a given set of primes, and all prime factors of a second natural number belong to a second set of primes which is a subset of the complement of the first set, then the two natural numbers are coprime.*)\nLemma sub_pnat_coprime pi rho m n :\n {subset rho <= pi^'} -> pi.-nat m -> rho.-nat n -> coprime m n.\n\n(*This lemma states that for any two natural numbers and any set of prime numbers, the part of the first number corresponding to the set is coprime with the part of the second number corresponding to the complement of the set.*)\nLemma coprime_partC pi m n : coprime m`_pi n`_pi^'.\n\n(*This lemma states that if all prime factors of a natural number belong to a given set of primes, and also all of its prime factors belong to the complement of that set, then the natural number must be one.*)\nLemma pnat_1 pi n : pi.-nat n -> pi^'.-nat n -> n = 1.\n\n(*This lemma states that if all prime factors of a natural number belong to a given set of primes, then the part of that number corresponding to the set is equal to the number itself.*)\nLemma part_pnat_id pi n : pi.-nat n -> n`_pi = n.\n\n(*This lemma states that if all prime factors of a natural number belong to the complement of a given set of primes, then the part of that number corresponding to the set is equal to one.*)\nLemma part_p'nat pi n : pi^'.-nat n -> n`_pi = 1.\n\n(*This lemma states that for any positive natural number and any set of prime numbers, the boolean property that the part of the number corresponding to the set is equal to one is equivalent to the property that all prime factors of the number belong to the complement of the set.*)\nLemma partn_eq1 pi n : n > 0 -> (n`_pi == 1) = pi^'.-nat n.\n\n(*This lemma states that for any positive natural number and any set of primes, the boolean property that all prime factors of the number belong to the set is logically equivalent to the proposition that every prime number that divides the number is an element of the set.*)\nLemma pnatP pi n :\n n > 0 -> reflect (forall p, prime p -> p %| n -> p \\in pi) (pi.-nat n).\n\n(*This lemma states that if a natural number is a power of a single prime number, and that prime is an element of a given set of primes, then all prime factors of the natural number belong to that given set.*)\nLemma pi_pnat pi p n : p.-nat n -> p \\in pi -> pi.-nat n.\n\n(*This lemma states that if the only prime factor of a natural number is a given prime number, then there exists a natural number exponent such that the original number is equal to the prime raised to that exponent.*)\nLemma p_natP p n : p.-nat n -> {k | n = p ^ k}.\n\n(*This lemma states that if no prime from a given list of primes divides a natural number, then any particular prime from that same list does not divide that number.*)\nLemma pi'_p'nat pi p n : pi^'.-nat n -> p \\in pi -> p^'.-nat n.\n\n(*This lemma states that if a given set of primes is the exact set of prime factors of a natural number, then any prime not in that set does not divide the number.*)\nLemma pi_p'nat p pi n : pi.-nat n -> p \\in pi^' -> p^'.-nat n.\n\n(*This lemma states that if a set of primes is a subset of another, then the part of a number corresponding to the larger set, when applied to the part corresponding to the smaller set, yields the part corresponding to the smaller set.*)\nLemma partn_part pi rho n : {subset pi <= rho} -> n`_rho`_pi = n`_pi.\n\n(*This lemma states that the part of a natural number corresponding to the intersection of two sets of primes is equal to the part associated with the second set of the part associated with the first set.*)\nLemma partnI pi rho n : n`_[predI pi & rho] = n`_pi`_rho.\n\n(*This lemma states that a natural number is odd if and only if it is not divisible by the prime number two.*)\nLemma odd_2'nat n : odd n = 2^'.-nat n.\n\nEnd PnatTheory.\n#[global] Hint Resolve part_gt0 : core.\n\n(*This lemma states that for any positive natural number, the list of its divisors contains unique elements, is sorted in non-decreasing order, and a number is in this list if and only if it divides the given number.*)\nLemma divisors_correct n : n > 0 ->\n [/\\ uniq (divisors n), sorted leq (divisors n)\n & forall d, (d \\in divisors n) = (d %| n)].\n\n(*This lemma states that the list of divisors of a natural number is sorted in non-decreasing order.*)\nLemma sorted_divisors n : sorted leq (divisors n).\n\n(*This lemma states that the list of divisors of a natural number contains no duplicate elements.*)\nLemma divisors_uniq n : uniq (divisors n).\n\n(*This lemma states that the list of divisors of a natural number is sorted in strictly increasing order.*)\nLemma sorted_divisors_ltn n : sorted ltn (divisors n).\n\n(*This lemma states that for any positive natural number, another number divides it if and only if that number is present in its list of divisors.*)\nLemma dvdn_divisors d m : 0 < m -> (d %| m) = (d \\in divisors m).\n\n(*This lemma states that for any positive natural number, the number one is present in its list of divisors.*)\nLemma divisor1 n : 1 \\in divisors n.\n\n(*This lemma states that any positive natural number is present in its own list of divisors.*)\nLemma divisors_id n : 0 < n -> n \\in divisors n.\n\n(*This lemma states that if a natural number divides every term of a sum produced by a function over a filtered sequence, then it also divides the total sum.*)\nLemma dvdn_sum d I r (K : pred I) F :\n (forall i, K i -> d %| F i) -> d %| \\sum_(i <- r | K i) F i.\n\n(*This lemma establishes that a positive natural number `n` divides another number `m` if and only if for every prime factor `p` of `n`, the p-primary part of `n` also divides `m`.*)\nLemma dvdn_partP n m : 0 < n ->\n reflect (forall p, p \\in \\pi(n) -> n`_p %| m) (n %| m).\n\n(*This lemma establishes that for a positive natural number `n`, two other numbers are congruent modulo `n` if and only if they are congruent modulo the p-primary part of `n` for every prime factor `p` of `n`.*)\nLemma modn_partP n a b : 0 < n ->\n reflect (forall p : nat, p \\in \\pi(n) -> a = b %[mod n`_p]) (a == b %[mod n]).\n\n(*This lemma provides Euler's product formula, stating that for a positive natural number, its totient is the product, over its distinct prime factors, of the quantity obtained by multiplying the prime minus one with the prime raised to the power of its p-adic valuation minus one.*)\nLemma totientE n :\n n > 0 -> totient n = \\prod_(p <- primes n) (p.-1 * p ^ (logn p n).-1).\n\n(*This lemma states that the value of Euler's totient function for a natural number is positive if and only if the number itself is positive.*)\nLemma totient_gt0 n : (0 < totient n) = (0 < n).\n\n(*This lemma provides the formula for Euler's totient function of a prime power, stating that for a prime number `p` and a positive exponent `e`, the totient of `p` to the power of `e` is equal to `p` minus one multiplied by `p` to the power of `e` minus one.*)\nLemma totient_pfactor p e :\n prime p -> e > 0 -> totient (p ^ e) = p.-1 * p ^ e.-1.\n\n(*This lemma states that for any prime number, its totient is equal to the prime number minus one.*)\nLemma totient_prime p : prime p -> totient p = p.-1.\n\n(*This lemma states that Euler's totient function is multiplicative, meaning for any two coprime natural numbers, the totient of their product is the product of their individual totients.*)\nLemma totient_coprime m n :\n coprime m n -> totient (m * n) = totient m * totient n.\n\n(*This lemma states that the totient of a natural number `n` is equal to the total count of natural numbers less than `n` that are coprime to `n`.*)\nLemma totient_count_coprime n : totient n = \\sum_(0 <= d < n) coprime n d.\n\n(*This lemma states that for any given natural number, the value of Euler's totient function is greater than one if and only if the number itself is greater than two.*)\nLemma totient_gt1 n : (totient n > 1) = (n > 2).", - "boot.path": "From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nSection Paths.\n\nVariables (n0 : nat) (T : Type).\n\nSection Path.\n\nVariables (x0_cycle : T) (e : rel T).\n\n(*This fixpoint recursively defines whether a sequence of elements forms a valid path starting from an initial element, with respect to a binary relation. A path is valid if the relation holds between the initial element and the first element of the sequence, and recursively for all subsequent adjacent pairs in the sequence. An empty sequence always forms a valid path.*)\nFixpoint path x (p : seq T) :=\n if p is y :: p' then e x y && path y p' else true.\n\n(*This lemma states that a path over the concatenation of two sequences is valid if and only if the path is valid over the first sequence, and the path over the second sequence is also valid starting from the last element of the first sequence.*)\nLemma cat_path x p1 p2 : path x (p1 ++ p2) = path x p1 && path (last x p1) p2.\n\n(*This lemma states that a path over a sequence with an element appended at the end is valid if and only if the path is valid for the original sequence and the defining relation holds between the last element of the original sequence and the newly appended element.*)\nLemma rcons_path x p y : path x (rcons p y) = path x p && e (last x p) y.\n\n(*This lemma states that if a path is valid over a given sequence with respect to a binary relation, then the path is also valid over any prefix of that sequence.*)\nLemma take_path x p i : path x p -> path x (take i p).\n\n(*This lemma provides an alternative characterization of a valid path. It states that a path is valid if and only if the governing relation holds for every pair of consecutive elements in the full path sequence, which includes the starting element followed by the given sequence.*)\nLemma pathP x p x0 :\n reflect (forall i, i < size p -> e (nth x0 (x :: p) i) (nth x0 p i))\n (path x p).\n\n(*This definition specifies a cycle for a sequence of elements. A sequence forms a cycle if it is empty, or if there is a valid path starting from its first element, traversing the rest of the sequence, and ending by satisfying the relation with the first element again.*)\nDefinition cycle p := if p is x :: p' then path x (rcons p' x) else true.\n\n(*This lemma states that a sequence forms a cycle if and only if there is a valid path over the sequence that starts from the last element of that same sequence.*)\nLemma cycle_path p : cycle p = path (last x0_cycle p) p.\n\n(*This lemma states that the cyclic property of a sequence formed by concatenating two smaller sequences is commutative; the result is the same regardless of the order of concatenation.*)\nLemma cycle_catC p q : cycle (p ++ q) = cycle (q ++ p).\n\n(*This lemma states that the cyclic property of a sequence is invariant under left rotation; rotating a sequence does not change whether it forms a cycle.*)\nLemma rot_cycle p : cycle (rot n0 p) = cycle p.\n\n(*This lemma states that the cyclic property of a sequence is invariant under right rotation; rotating a sequence to the right does not change whether it forms a cycle.*)\nLemma rotr_cycle p : cycle (rotr n0 p) = cycle p.\n\n(*This definition specifies that a sequence is sorted with respect to a given relation if the relation holds for every pair of adjacent elements in the sequence. By convention, empty and singleton sequences are considered sorted.*)\nDefinition sorted s := if s is x :: s' then path x s' else true.\n\n(*This lemma provides an alternative characterization of a sorted sequence, stating that a sequence is sorted if and only if for every valid index, the given relation holds between the element at that index and the element at the next index.*)\nLemma sortedP s x :\n reflect (forall i, i.+1 < size s -> e (nth x s i) (nth x s i.+1)) (sorted s).\n\n(*This lemma states that if a path starting from an initial element is valid over a given sequence, then that sequence itself is sorted with respect to the same relation.*)\nLemma path_sorted x s : path x s -> sorted s.\n\n(*This lemma states that if a given relation holds between an initial element and all elements of a sequence, then the property of the sequence being a valid path from that initial element is equivalent to the property of the sequence being sorted.*)\nLemma path_min_sorted x s : all (e x) s -> path x s = sorted s.\n\n(*This lemma states that if a binary relation holds for every pair of elements in a sequence where the first element of the pair appears before the second, then the sequence is sorted with respect to that relation.*)\nLemma pairwise_sorted s : pairwise e s -> sorted s.\n\n(*This lemma provides a condition for a sequence formed by concatenating a first sequence, a single element, and a second sequence to be sorted. It states this is true if and only if the sequence formed by appending the single element to the first sequence is sorted, and there is a valid path from that single element over the second sequence.*)\nLemma sorted_cat_cons s1 x s2 :\n sorted (s1 ++ x :: s2) = sorted (rcons s1 x) && path x s2.\n\nEnd Path.\n\nSection PathEq.\n\nVariables (e e' : rel T).\n\n(*This lemma relates a path over a reversed sequence to a path over the original sequence. It states that a path defined by a relation over the reverse of a sequence's initial segment, starting from the last element of the original sequence, is equivalent to a path defined by the converse relation over the original sequence, starting from its first element.*)\nLemma rev_path x p :\n path e (last x p) (rev (belast x p)) = path (fun z => e^~ z) x p.\n\n(*This lemma states that checking the cyclic property for a reversed sequence with a given relation is equivalent to checking the cyclic property for the original sequence with the converse of that relation.*)\nLemma rev_cycle p : cycle e (rev p) = cycle (fun z => e^~ z) p.\n\n(*This lemma states that a reversed sequence is sorted with respect to a given relation if and only if the original sequence is sorted with respect to the converse of that relation.*)\nLemma rev_sorted p : sorted e (rev p) = sorted (fun z => e^~ z) p.\n\n(*This lemma states that a path is valid with respect to the intersection of two binary relations if and only if it is valid with respect to each of the two relations individually.*)\nLemma path_relI x s :\n path [rel x y | e x y && e' x y] x s = path e x s && path e' x s.\n\n(*This lemma states that a sequence forms a cycle with respect to the intersection of two binary relations if and only if it forms a cycle with respect to each of the two relations individually.*)\nLemma cycle_relI s :\n cycle [rel x y | e x y && e' x y] s = cycle e s && cycle e' s.\n\n(*This lemma states that a sequence is sorted with respect to the intersection of two binary relations if and only if it is sorted with respect to each of the two relations individually.*)\nLemma sorted_relI s :\n sorted [rel x y | e x y && e' x y] s = sorted e s && sorted e' s.\n\nEnd PathEq.\n\nSection SubPath_in.\n\nVariable (P : {pred T}) (e e' : rel T).\nHypothesis (ee' : {in P &, subrel e e'}).\n\n(*This lemma states that if a path is valid with respect to a first binary relation, and all elements in the path sequence satisfy a given predicate, and the first relation is a subrelation of a second relation for all elements satisfying that predicate, then the path is also valid with respect to the second relation.*)\nLemma sub_in_path x s : all P (x :: s) -> path e x s -> path e' x s.\n\n(*This lemma states that if a sequence forms a cycle with respect to a first binary relation, and all elements in the sequence satisfy a given predicate, and the first relation is a subrelation of a second relation for all elements satisfying that predicate, then the sequence also forms a cycle with respect to the second relation.*)\nLemma sub_in_cycle s : all P s -> cycle e s -> cycle e' s.\n\n(*This lemma states that if a sequence is sorted with respect to a first binary relation, and all elements in the sequence satisfy a given predicate, and the first relation is a subrelation of a second relation for all elements satisfying that predicate, then the sequence is also sorted with respect to the second relation.*)\nLemma sub_in_sorted s : all P s -> sorted e s -> sorted e' s.\n\nEnd SubPath_in.\n\nSection EqPath_in.\n\nVariable (P : {pred T}) (e e' : rel T).\nHypothesis (ee' : {in P &, e =2 e'}).\n\n(*This definition is a proof term which shows that a first binary relation is a subrelation of a second binary relation on a given domain, derived from the hypothesis that the two relations are equivalent on that domain.*)\nLet e_e' : {in P &, subrel e e'}. \n(*This definition is a proof term which shows that a second binary relation is a subrelation of a first binary relation on a given domain, derived from the hypothesis that the two relations are equivalent on that domain.*)\nLet e'_e : {in P &, subrel e' e}. \n\n(*This lemma states that if all elements in a path sequence satisfy a given predicate, and two binary relations are equivalent for all elements satisfying that predicate, then the validity of the path is the same for both relations.*)\nLemma eq_in_path x s : all P (x :: s) -> path e x s = path e' x s.\n\n(*This lemma states that if all elements in a sequence satisfy a given predicate, and two binary relations are equivalent for all elements satisfying that predicate, then the property of the sequence forming a cycle is the same for both relations.*)\nLemma eq_in_cycle s : all P s -> cycle e s = cycle e' s.\n\n(*This lemma states that if all elements in a sequence satisfy a given predicate, and two binary relations are equivalent for all elements satisfying that predicate, then the property of the sequence being sorted is the same for both relations.*)\nLemma eq_in_sorted s : all P s -> sorted e s = sorted e' s.\n\nEnd EqPath_in.\n\nSection SubPath.\n\nVariables e e' : rel T.\n\n(*This lemma states that if a first binary relation is a subrelation of a second binary relation, then any sequence that forms a path with respect to the first relation also forms a path with respect to the second relation.*)\nLemma sub_path : subrel e e' -> forall x p, path e x p -> path e' x p.\n\n(*This lemma states that if a first binary relation is a subrelation of a second binary relation, then any sequence that forms a cycle with respect to the first relation is also a cycle with respect to the second relation.*)\nLemma sub_cycle : subrel e e' -> subpred (cycle e) (cycle e').\n\n(*This lemma states that if a first binary relation is a subrelation of a second binary relation, then any sequence sorted with respect to the first relation is also sorted with respect to the second relation.*)\nLemma sub_sorted : subrel e e' -> subpred (sorted e) (sorted e').\n\n(*This lemma states that if two binary relations are equivalent, then the property of forming a path with respect to the first relation is equivalent to the property of forming a path with respect to the second relation.*)\nLemma eq_path : e =2 e' -> path e =2 path e'.\n\n(*This lemma states that if two binary relations are equivalent, then a sequence forms a cycle with respect to the first relation if and only if it forms a cycle with respect to the second relation.*)\nLemma eq_cycle : e =2 e' -> cycle e =1 cycle e'.\n\n(*This lemma states that if two binary relations are equivalent, then a sequence is sorted with respect to the first relation if and only if it is sorted with respect to the second relation.*)\nLemma eq_sorted : e =2 e' -> sorted e =1 sorted e'.\n\nEnd SubPath.\n\nSection Transitive_in.\n\nVariables (P : {pred T}) (leT : rel T).\n\n(*This lemma states that if a binary relation is transitive on a subset of elements, and a sequence starting with a given element forms a path with respect to this relation where all elements belong to the subset, then the starting element is related to every other element in the sequence.*)\nLemma order_path_min_in x s :\n {in P & &, transitive leT} -> all P (x :: s) -> path leT x s -> all (leT x) s.\n\nHypothesis leT_tr : {in P & &, transitive leT}.\n\n(*This lemma states that for a transitive binary relation on a subset of elements, a sequence starting with a given element, where all elements are in the subset, forms a path if and only if the starting element is related to all subsequent elements and the rest of the sequence is sorted.*)\nLemma path_sorted_inE x s :\n all P (x :: s) -> path leT x s = all (leT x) s && sorted leT s.\n\n(*This lemma states that for a transitive binary relation on a subset of elements, a sequence whose elements all belong to that subset is sorted if and only if every element in the sequence is related to all subsequent elements.*)\nLemma sorted_pairwise_in s : all P s -> sorted leT s = pairwise leT s.\n\n(*This lemma states that for a transitive binary relation on a subset of elements, a sequence starting with a given element, where all elements are in the subset, forms a path if and only if every element in the full sequence is related to all of its subsequent elements.*)\nLemma path_pairwise_in x s :\n all P (x :: s) -> path leT x s = pairwise leT (x :: s).\n\n(*This lemma states that for a transitive binary relation, if the concatenation of two sequences is sorted, then both of the original sequences are also sorted.*)\nLemma cat_sorted2 s s' : sorted leT (s ++ s') -> sorted leT s * sorted leT s'.\n\n(*This lemma states that for a transitive binary relation on a subset of elements, if a sequence whose elements all belong to that subset is sorted, then any subsequence formed by applying a boolean mask will also be sorted.*)\nLemma sorted_mask_in m s : all P s -> sorted leT s -> sorted leT (mask m s).\n\n(*This lemma states that for a transitive binary relation on a subset of elements, if a sequence whose elements all belong to that subset is sorted, then filtering this sequence with a predicate will produce a new sequence that is also sorted.*)\nLemma sorted_filter_in a s : all P s -> sorted leT s -> sorted leT (filter a s).\n\n(*This lemma states that for a transitive binary relation on a subset of elements, if a sequence starting with a given element forms a path and all its elements are in the subset, then the sequence formed by the same starting element followed by a masked version of the tail is also a path.*)\nLemma path_mask_in x m s :\n all P (x :: s) -> path leT x s -> path leT x (mask m s).\n\n(*This lemma states that for a transitive binary relation on a subset of elements, if a sequence starting with a given element forms a path and all its elements are in the subset, then the sequence formed by the same starting element followed by a filtered version of the tail is also a path.*)\nLemma path_filter_in x a s :\n all P (x :: s) -> path leT x s -> path leT x (filter a s).\n\n(*This lemma states that for a transitive binary relation on a subset of elements, if a sequence whose elements all belong to that subset is sorted, then for any two indices where the first index is strictly less than the second, the element at the first index is related to the element at the second index.*)\nLemma sorted_ltn_nth_in x0 s : all P s -> sorted leT s ->\n {in [pred n | n < size s] &, {homo nth x0 s : i j / i < j >-> leT i j}}.\n\nHypothesis leT_refl : {in P, reflexive leT}.\n\n(*This lemma states that for a reflexive and transitive binary relation on a subset of elements, if a sequence whose elements all belong to that subset is sorted, then for any two indices where the first index is less than or equal to the second, the element at the first index is related to the element at the second index.*)\nLemma sorted_leq_nth_in x0 s : all P s -> sorted leT s ->\n {in [pred n | n < size s] &, {homo nth x0 s : i j / i <= j >-> leT i j}}.\n\nEnd Transitive_in.\n\nSection Transitive.\n\nVariable (leT : rel T).\n\n(*This lemma states that if a binary relation is transitive and a sequence starting with a given element forms a path, then the starting element is related to every other element in the sequence.*)\nLemma order_path_min x s : transitive leT -> path leT x s -> all (leT x) s.\n\nHypothesis leT_tr : transitive leT.\n\n(*This lemma states that for a transitive binary relation, if a first element is related to a second element, and a sequence starting with the second element forms a path, then the sequence starting with the first element and followed by the same tail also forms a path.*)\nLemma path_le x x' s : leT x x' -> path leT x' s -> path leT x s.\n\n(*This definition asserts that the given binary relation is transitive across all elements of the type.*)\nLet leT_tr' : {in predT & &, transitive leT}. \n\n(*This lemma states that for a transitive binary relation, a sequence starting with a given element forms a path if and only if the starting element is related to all subsequent elements and the rest of the sequence is sorted.*)\nLemma path_sortedE x s : path leT x s = all (leT x) s && sorted leT s.\n\n(*This lemma states that for a transitive binary relation, a sequence is sorted if and only if every element in the sequence is related to all of its subsequent elements.*)\nLemma sorted_pairwise s : sorted leT s = pairwise leT s.\n\n(*This lemma states that for a transitive binary relation, a sequence starting with a given element forms a path if and only if every element in the full sequence, including the start element, is related to all of its subsequent elements.*)\nLemma path_pairwise x s : path leT x s = pairwise leT (x :: s).\n\n(*This lemma states that for a transitive binary relation, if a sequence is sorted, then any subsequence formed by applying a boolean mask will also be sorted.*)\nLemma sorted_mask m s : sorted leT s -> sorted leT (mask m s).\n\n(*This lemma states that for a transitive binary relation, if a sequence is sorted, then filtering this sequence with a predicate will produce a new sequence that is also sorted.*)\nLemma sorted_filter a s : sorted leT s -> sorted leT (filter a s).\n\n(*This lemma states that for a transitive binary relation, if a sequence starting with a given element forms a path, then the sequence formed by the same starting element followed by a masked version of the tail is also a path.*)\nLemma path_mask x m s : path leT x s -> path leT x (mask m s).\n\n(*This lemma states that for a transitive binary relation, if a sequence starting with a given element forms a path, then the sequence formed by the same starting element followed by a filtered version of the tail is also a path.*)\nLemma path_filter x a s : path leT x s -> path leT x (filter a s).\n\n(*This lemma states that for a transitive binary relation, if a sequence is sorted, then for any two indices where the first index is strictly less than the second, the element at the first index is related to the element at the second index.*)\nLemma sorted_ltn_nth x0 s : sorted leT s ->\n {in [pred n | n < size s] &, {homo nth x0 s : i j / i < j >-> leT i j}}.\n\nHypothesis leT_refl : reflexive leT.\n\n(*This lemma states that for a reflexive and transitive binary relation, if a sequence is sorted, then for any two indices where the first index is less than or equal to the second, the element at the first index is related to the element at the second index.*)\nLemma sorted_leq_nth x0 s : sorted leT s ->\n {in [pred n | n < size s] &, {homo nth x0 s : i j / i <= j >-> leT i j}}.\n\n(*This lemma states that for a reflexive and transitive binary relation, if a sequence is sorted, then any prefix of that sequence is also sorted.*)\nLemma take_sorted n s : sorted leT s -> sorted leT (take n s).\n\n(*This lemma states that if a finite sequence is sorted with respect to a given relation, then any sequence obtained by removing a specified number of elements from the beginning of the original sequence is also sorted with respect to the same relation.*)\nLemma drop_sorted n s : sorted leT s -> sorted leT (drop n s).\n\nEnd Transitive.\n\nEnd Paths.\n\nArguments pathP {T e x p}.\nArguments sortedP {T e s}.\nArguments path_sorted {T e x s}.\nArguments path_min_sorted {T e x s}.\nArguments order_path_min_in {T P leT x s}.\nArguments path_sorted_inE {T P leT} leT_tr {x s}.\nArguments sorted_pairwise_in {T P leT} leT_tr {s}.\nArguments path_pairwise_in {T P leT} leT_tr {x s}.\nArguments sorted_mask_in {T P leT} leT_tr {m s}.\nArguments sorted_filter_in {T P leT} leT_tr {a s}.\nArguments path_mask_in {T P leT} leT_tr {x m s}.\nArguments path_filter_in {T P leT} leT_tr {x a s}.\nArguments sorted_ltn_nth_in {T P leT} leT_tr x0 {s}.\nArguments sorted_leq_nth_in {T P leT} leT_tr leT_refl x0 {s}.\nArguments order_path_min {T leT x s}.\nArguments path_sortedE {T leT} leT_tr x s.\nArguments sorted_pairwise {T leT} leT_tr s.\nArguments path_pairwise {T leT} leT_tr x s.\nArguments sorted_mask {T leT} leT_tr m {s}.\nArguments sorted_filter {T leT} leT_tr a {s}.\nArguments path_mask {T leT} leT_tr {x} m {s}.\nArguments path_filter {T leT} leT_tr {x} a {s}.\nArguments sorted_ltn_nth {T leT} leT_tr x0 {s}.\nArguments sorted_leq_nth {T leT} leT_tr leT_refl x0 {s}.\n\nSection HomoPath.\n\nVariables (T T' : Type) (P : {pred T}) (f : T -> T') (e : rel T) (e' : rel T').\n\n(*This lemma states that applying a function to an initial element and a finite sequence results in a path under a target relation if and only if the original element and sequence form a path under a source relation that holds whenever the target relation holds on the function's outputs.*)\nLemma path_map x s : path e' (f x) (map f s) = path (relpre f e') x s.\n\n(*This lemma states that applying a function to a finite sequence results in a cycle under a target relation if and only if the original sequence forms a cycle under a source relation that holds whenever the target relation holds on the function's outputs.*)\nLemma cycle_map s : cycle e' (map f s) = cycle (relpre f e') s.\n\n(*This lemma states that applying a function to a finite sequence results in a sorted sequence under a target relation if and only if the original sequence is sorted under a source relation that holds whenever the target relation holds on the function's outputs.*)\nLemma sorted_map s : sorted e' (map f s) = sorted (relpre f e') s.\n\n(*This lemma states that if a function preserves a relation for all elements within a given subset, and an element and a finite sequence all belong to that subset and form a path with respect to this relation, then the sequence of their images under the function also forms a path with respect to the target relation.*)\nLemma homo_path_in x s : {in P &, {homo f : x y / e x y >-> e' x y}} ->\n all P (x :: s) -> path e x s -> path e' (f x) (map f s).\n\n(*This lemma states that if a function preserves a relation for all elements within a given subset, and a finite sequence of elements from that subset forms a cycle with respect to this relation, then the sequence of their images under the function also forms a cycle with respect to the target relation.*)\nLemma homo_cycle_in s : {in P &, {homo f : x y / e x y >-> e' x y}} ->\n all P s -> cycle e s -> cycle e' (map f s).\n\n(*This lemma states that if a function preserves a relation for all elements within a given subset, and a finite sequence of elements from that subset is sorted with respect to this relation, then the sequence of their images under the function is also sorted with respect to the target relation.*)\nLemma homo_sorted_in s : {in P &, {homo f : x y / e x y >-> e' x y}} ->\n all P s -> sorted e s -> sorted e' (map f s).\n\n(*This lemma states that if a function reflects a relation for all elements within a given subset, and an element and a finite sequence all belong to that subset, then the sequence of their images forms a path with respect to the target relation if and only if the original element and sequence form a path with respect to the source relation.*)\nLemma mono_path_in x s : {in P &, {mono f : x y / e x y >-> e' x y}} ->\n all P (x :: s) -> path e' (f x) (map f s) = path e x s.\n\n(*This lemma states that if a function reflects a relation for all elements within a given subset, and a finite sequence of elements is from that subset, then the sequence of their images forms a cycle with respect to the target relation if and only if the original sequence forms a cycle with respect to the source relation.*)\nLemma mono_cycle_in s : {in P &, {mono f : x y / e x y >-> e' x y}} ->\n all P s -> cycle e' (map f s) = cycle e s.\n\n(*This lemma states that if a function reflects a relation for all elements within a given subset, and a finite sequence of elements is from that subset, then the sequence of their images is sorted with respect to the target relation if and only if the original sequence is sorted with respect to the source relation.*)\nLemma mono_sorted_in s : {in P &, {mono f : x y / e x y >-> e' x y}} ->\n all P s -> sorted e' (map f s) = sorted e s.\n\n(*This lemma states that if a function preserves a relation everywhere, and an element and a finite sequence form a path with respect to this relation, then the sequence of their images under the function also forms a path with respect to the target relation.*)\nLemma homo_path x s : {homo f : x y / e x y >-> e' x y} ->\n path e x s -> path e' (f x) (map f s).\n\n(*This lemma states that if a function from one type to another preserves a given relation, then mapping this function over a finite sequence preserves the property of being a cycle.*)\nLemma homo_cycle : {homo f : x y / e x y >-> e' x y} ->\n {homo map f : s / cycle e s >-> cycle e' s}.\n\n(*This lemma states that if a function from one type to another preserves a given relation, then mapping this function over a finite sequence preserves the property of being sorted.*)\nLemma homo_sorted : {homo f : x y / e x y >-> e' x y} ->\n {homo map f : s / sorted e s >-> sorted e' s}.\n\n(*This lemma states that if a function reflects a relation everywhere, then the image of an element and a finite sequence forms a path with respect to the target relation if and only if the original element and sequence form a path with respect to the source relation.*)\nLemma mono_path x s : {mono f : x y / e x y >-> e' x y} ->\n path e' (f x) (map f s) = path e x s.\n\n(*This lemma states that if a function from one type to another reflects a given relation, then applying that function to each element of a finite sequence preserves and reflects the property of being a cycle.*)\nLemma mono_cycle : {mono f : x y / e x y >-> e' x y} ->\n {mono map f : s / cycle e s >-> cycle e' s}.\n\n(*This lemma states that if a function from one type to another reflects a given relation, then applying that function to each element of a finite sequence preserves and reflects the property of being sorted.*)\nLemma mono_sorted : {mono f : x y / e x y >-> e' x y} ->\n {mono map f : s / sorted e s >-> sorted e' s}.\n\nEnd HomoPath.\n\nArguments path_map {T T' f e'}.\nArguments cycle_map {T T' f e'}.\nArguments sorted_map {T T' f e'}.\nArguments homo_path_in {T T' P f e e' x s}.\nArguments homo_cycle_in {T T' P f e e' s}.\nArguments homo_sorted_in {T T' P f e e' s}.\nArguments mono_path_in {T T' P f e e' x s}.\nArguments mono_cycle_in {T T' P f e e' s}.\nArguments mono_sorted_in {T T' P f e e' s}.\nArguments homo_path {T T' f e e' x s}.\nArguments homo_cycle {T T' f e e'}.\nArguments homo_sorted {T T' f e e'}.\nArguments mono_path {T T' f e e' x s}.\nArguments mono_cycle {T T' f e e'}.\nArguments mono_sorted {T T' f e e'}.\n\nSection CycleAll2Rel.\n\n(*This lemma states that for a transitive relation, a finite sequence forms a cycle if and only if every element in the sequence is related to every other element in the sequence.*)\nLemma cycle_all2rel (T : Type) (leT : rel T) :\n transitive leT -> forall s, cycle leT s = all2rel leT s.\n\n(*This lemma states that if a relation is transitive on a given subset of elements, then for any finite sequence composed entirely of elements from that subset, forming a cycle is equivalent to every element in the sequence being related to every other element in the sequence.*)\nLemma cycle_all2rel_in (T : Type) (P : {pred T}) (leT : rel T) :\n {in P & &, transitive leT} ->\n forall s, all P s -> cycle leT s = all2rel leT s.\n\nEnd CycleAll2Rel.\n\nSection PreInSuffix.\n\nVariables (T : eqType) (e : rel T).\nImplicit Type s : seq T.\n\n(*A notation for the predicate checking if an element and a following finite sequence form a chain where each element is related to the subsequent one by a specified binary relation.*)\nLocal Notation path := (path e).\n(*A notation for the predicate that checks if a finite sequence is sorted, meaning that every adjacent pair of elements in the sequence satisfies a specified binary relation.*)\nLocal Notation sorted := (sorted e).\n\n(*This lemma states that if a first finite sequence is a prefix of a second one, and a given element followed by the second sequence forms a path, then the same element followed by the first sequence also forms a path.*)\nLemma prefix_path x s1 s2 : prefix s1 s2 -> path x s2 -> path x s1.\n\n(*This lemma states that if a first finite sequence is a prefix of a second one, and the second sequence is sorted with respect to some relation, then the first sequence is also sorted with respect to the same relation.*)\nLemma prefix_sorted s1 s2 : prefix s1 s2 -> sorted s2 -> sorted s1.\n\n(*This lemma states that if a first finite sequence is a contiguous subsegment of a second one, and the second sequence is sorted with respect to some relation, then the first sequence is also sorted with respect to the same relation.*)\nLemma infix_sorted s1 s2 : infix s1 s2 -> sorted s2 -> sorted s1.\n\n(*This lemma states that if a first finite sequence is a suffix of a second one, and the second sequence is sorted with respect to some relation, then the first sequence is also sorted with respect to the same relation.*)\nLemma suffix_sorted s1 s2 : suffix s1 s2 -> sorted s2 -> sorted s1.\n\nEnd PreInSuffix.\n\nSection EqSorted.\n\nVariables (T : eqType) (leT : rel T).\nImplicit Type s : seq T.\n\n(*This predicate asserts that a given binary relation holds between a specified start element and the first element of a finite sequence, and also between every pair of consecutive elements within that sequence.*)\nLocal Notation path := (path leT).\n(*This predicate asserts that a finite sequence is sorted with respect to a given binary relation, which means the relation holds for every pair of adjacent elements in the order they appear in the sequence.*)\nLocal Notation sorted := (sorted leT).\n\n(*This lemma states that if a binary relation is transitive over a set of elements containing a specific element and a sequence, and if one sequence is a subsequence of the other, then a path through the larger sequence implies a path through the subsequence. A path from an element through a sequence means the relation holds between the element and the first item of the sequence, and between all consecutive items in the sequence.*)\nLemma subseq_path_in x s1 s2 :\n {in x :: s2 & &, transitive leT} -> subseq s1 s2 -> path x s2 -> path x s1.\n\n(*This lemma states that if a binary relation is transitive on the elements of a sequence, and a second sequence is a subsequence of the first, then if the first sequence is sorted, the second sequence is also sorted.*)\nLemma subseq_sorted_in s1 s2 :\n {in s2 & &, transitive leT} -> subseq s1 s2 -> sorted s2 -> sorted s1.\n\n(*This lemma states that for any sorted finite sequence under a transitive binary relation, the relation holds between any two elements if the first element appears at an earlier position in the sequence than the second.*)\nLemma sorted_ltn_index_in s : {in s & &, transitive leT} -> sorted s ->\n {in s &, forall x y, index x s < index y s -> leT x y}.\n\n(*This lemma states that for any sorted finite sequence under a transitive and reflexive binary relation, the relation holds between any two elements if the first element appears at the same or an earlier position in the sequence than the second.*)\nLemma sorted_leq_index_in s :\n {in s & &, transitive leT} -> {in s, reflexive leT} -> sorted s ->\n {in s &, forall x y, index x s <= index y s -> leT x y}.\n\nHypothesis leT_tr : transitive leT.\n\n(*This lemma states that for a transitive binary relation, if a finite sequence is a subsequence of another, and a path exists from an element through the larger sequence, then a path also exists from that same element through the subsequence. A path from an element through a sequence means the relation holds between the element and the first item of the sequence, and between all consecutive items in the sequence.*)\nLemma subseq_path x s1 s2 : subseq s1 s2 -> path x s2 -> path x s1.\n\n(*This lemma states that for a transitive binary relation, any subsequence of a sorted finite sequence is also sorted.*)\nLemma subseq_sorted s1 s2 : subseq s1 s2 -> sorted s2 -> sorted s1.\n\n(*This lemma states that for an irreflexive binary relation, any finite sequence that is sorted with respect to this relation must consist of unique elements.*)\nLemma sorted_uniq : irreflexive leT -> forall s, sorted s -> uniq s.\n\n(*This lemma states that for an antisymmetric binary relation, if two sorted finite sequences are permutations of each other, then they must be equal.*)\nLemma sorted_eq : antisymmetric leT ->\n forall s1 s2, sorted s1 -> sorted s2 -> perm_eq s1 s2 -> s1 = s2.\n\n(*This lemma states that for an irreflexive binary relation, if two sorted finite sequences contain the same multiset of elements, then they must be equal.*)\nLemma irr_sorted_eq : irreflexive leT ->\n forall s1 s2, sorted s1 -> sorted s2 -> s1 =i s2 -> s1 = s2.\n\n(*This lemma states that for any sorted finite sequence under a transitive binary relation, if an element appears at an earlier position in the sequence than another, then the relation holds between them.*)\nLemma sorted_ltn_index s :\n sorted s -> {in s &, forall x y, index x s < index y s -> leT x y}.\n\n(*This lemma states that for a transitive binary relation, if a path exists from an element through a finite sequence, then a path also exists from that element through the sequence that results from removing all duplicate elements.*)\nLemma undup_path x s : path x s -> path x (undup s).\n\n(*This lemma states that for a transitive binary relation, if a finite sequence is sorted, then the sequence that results from removing all of its duplicate elements is also sorted.*)\nLemma undup_sorted s : sorted s -> sorted (undup s).\n\nHypothesis leT_refl : reflexive leT.\n\n(*This lemma states that for any sorted finite sequence under a transitive and reflexive binary relation, if an element appears at the same or an earlier position in the sequence than another, then the relation holds between them.*)\nLemma sorted_leq_index s :\n sorted s -> {in s &, forall x y, index x s <= index y s -> leT x y}.\n\nEnd EqSorted.\n\nArguments sorted_ltn_index_in {T leT s} leT_tr s_sorted.\nArguments sorted_leq_index_in {T leT s} leT_tr leT_refl s_sorted.\nArguments sorted_ltn_index {T leT} leT_tr {s}.\nArguments sorted_leq_index {T leT} leT_tr leT_refl {s}.\n\nSection EqSorted_in.\n\nVariables (T : eqType) (leT : rel T).\nImplicit Type s : seq T.\n\n(*This lemma states that if a binary relation is both transitive and irreflexive on the elements of a sorted finite sequence, then all elements in that sequence must be unique.*)\nLemma sorted_uniq_in s :\n {in s & &, transitive leT} -> {in s, irreflexive leT} ->\n sorted leT s -> uniq s.\n\n(*This lemma states that if a binary relation is transitive and antisymmetric over the elements of a sorted finite sequence, and a second sorted sequence is a permutation of the first, then the two sequences are equal.*)\nLemma sorted_eq_in s1 s2 :\n {in s1 & &, transitive leT} -> {in s1 &, antisymmetric leT} ->\n sorted leT s1 -> sorted leT s2 -> perm_eq s1 s2 -> s1 = s2.\n\n(*This lemma states that if a binary relation is transitive and irreflexive over the elements of a sorted finite sequence, and a second sorted sequence contains the same multiset of elements as the first, then the two sequences are equal.*)\nLemma irr_sorted_eq_in s1 s2 :\n {in s1 & &, transitive leT} -> {in s1, irreflexive leT} ->\n sorted leT s1 -> sorted leT s2 -> s1 =i s2 -> s1 = s2.\n\nEnd EqSorted_in.\n\nSection EqPath.\n\nVariables (n0 : nat) (T : eqType) (e : rel T).\nImplicit Type p : seq T.\n\n(*This inductive type provides evidence that a finite sequence can be deconstructed with respect to a pivot element into a prefix and a suffix, such that the sequence is equal to the prefix with the pivot appended, followed by the suffix.*)\nVariant split x : seq T -> seq T -> seq T -> Type :=\n Split p1 p2 : split x (rcons p1 x ++ p2) p1 p2.\n\n(*This lemma shows that for any finite sequence containing a given element, a 'split' structure can be constructed where the prefix is the part of the sequence before the element's first occurrence and the suffix is the part after.*)\nLemma splitP p x (i := index x p) :\n x \\in p -> split x p (take i p) (drop i.+1 p).\n\n(*This inductive type provides evidence that a finite sequence can be partitioned into two sub-sequences, where the first part is non-empty and its last element is a given element. A second element is provided to serve as a default value for the 'last' operation if the first part were empty.*)\nVariant splitl x1 x : seq T -> Type :=\n Splitl p1 p2 of last x1 p1 = x : splitl x1 x (p1 ++ p2).\n\n(*This lemma states that if an element is present in a non-empty finite sequence, then the tail of that sequence can be split in a way that is witnessed by the 'splitl' type, using the head of the original sequence and the target element as parameters.*)\nLemma splitPl x1 p x : x \\in x1 :: p -> splitl x1 x p.\n\n(*This inductive type provides evidence that a finite sequence can be deconstructed into a prefix sequence, a single pivot element, and a suffix sequence.*)\nVariant splitr x : seq T -> Type :=\n Splitr p1 p2 : splitr x (p1 ++ x :: p2).\n\n(*This lemma states that if an element is present in a finite sequence, a 'splitr' structure can be constructed, which partitions the sequence around the first occurrence of that element.*)\nLemma splitPr p x : x \\in p -> splitr x p.\n\n(*This recursive helper function finds the successor of an element within a sequence. It searches for a given element and, if the target element matches it, returns the next element in the traversal. If it reaches the end, it wraps around, returning the head of the original sequence passed as a default. If the target is not found, it returns the target itself.*)\nFixpoint next_at x y0 y p :=\n match p with\n | [::] => if x == y then y0 else x\n | y' :: p' => if x == y then y' else next_at x y0 y' p'\n end.\n\n(*This function computes the successor of an element within a finite sequence. If the element is in the sequence, it returns the element that immediately follows it. If the element is the last one, it returns the first element, treating the sequence as a cycle. If the element is not in the sequence or the sequence is empty, it returns the element itself.*)\nDefinition next p x := if p is y :: p' then next_at x y y p' else x.\n\n(*This recursive helper function finds the predecessor of an element within a sequence. It takes a target element, the head of the original sequence, the current 'previous' element, and the rest of the sequence. If the head of the remaining sequence matches the target, it returns the 'previous' element. If the target is the head of the original sequence, it returns the last element. If the target is not found, it returns the target itself.*)\nFixpoint prev_at x y0 y p :=\n match p with\n | [::] => if x == y0 then y else x\n | y' :: p' => if x == y' then y else prev_at x y0 y' p'\n end.\n\n(*This function computes the predecessor of an element within a finite sequence. If the element is in the sequence, it returns the element that immediately precedes it. If the element is the first one, it returns the last element, treating the sequence as a cycle. If the element is not in the sequence or the sequence is empty, it returns the element itself.*)\nDefinition prev p x := if p is y :: p' then prev_at x y y p' else x.\n\n(*This lemma provides an equivalent definition for the 'next' function using indices. It states that for an element in a sequence, its successor is the element at the position immediately following its own index. This operation wraps around, so the successor of the last element is the first. If the element is not in the sequence, it is returned as is.*)\nLemma next_nth p x :\n next p x = if x \\in p then\n if p is y :: p' then nth y p' (index x p) else x\n else x.\n\n(*This lemma provides an equivalent definition for the 'prev' function using indices. It states that for an element in a sequence, its predecessor is the element at the position immediately preceding its own index. This operation wraps around, so the predecessor of the first element is the last. If the element is not in the sequence, it is returned as is.*)\nLemma prev_nth p x :\n prev p x = if x \\in p then\n if p is y :: p' then nth y p (index x p') else x\n else x.\n\n(*This lemma states that the successor of a given element within a finite sequence is a member of that sequence if and only if the given element is also a member of the sequence.*)\nLemma mem_next p x : (next p x \\in p) = (x \\in p).\n\n(*This lemma states that the predecessor of a given element within a finite sequence is a member of that sequence if and only if the given element is also a member of the sequence.*)\nLemma mem_prev p x : (prev p x \\in p) = (x \\in p).\n\n(*This definition provides a boolean check that evaluates to true if a given finite sequence forms a cycle under a specified relation and contains no duplicate elements.*)\nDefinition ucycleb p := cycle e p && uniq p.\n(*This definition describes the property that a given finite sequence forms a cycle under a specified relation and contains no duplicate elements.*)\nDefinition ucycle p : Prop := cycle e p && uniq p.\n\n(*This lemma states that if a finite sequence has the unique cycle property, then it is also a cycle under the specified relation.*)\nLemma ucycle_cycle p : ucycle p -> cycle e p.\n\n(*This lemma states that if a finite sequence has the unique cycle property, then it contains no duplicate elements.*)\nLemma ucycle_uniq p : ucycle p -> uniq p.\n\n(*This lemma states that for any element in a finite sequence that forms a cycle, this element is related to its successor in the sequence by the cycle's defining relation.*)\nLemma next_cycle p x : cycle e p -> x \\in p -> e x (next p x).\n\n(*This lemma states that for any element in a finite sequence that forms a cycle, its predecessor in the sequence is related to this element by the cycle's defining relation.*)\nLemma prev_cycle p x : cycle e p -> x \\in p -> e (prev p x) x.\n\n(*This lemma states that the property of being a unique cycle is invariant under rotation of the finite sequence.*)\nLemma rot_ucycle p : ucycle (rot n0 p) = ucycle p.\n\n(*This lemma states that the property of being a unique cycle is invariant under reverse rotation of the finite sequence.*)\nLemma rotr_ucycle p : ucycle (rotr n0 p) = ucycle p.\n\n(*This definition describes a relation between two elements within a finite sequence, which is true if the second element appears at or after the first occurrence of the first element in the sequence.*)\nDefinition mem2 p x y := y \\in drop (index x p) p.\n\n(*This lemma states that if a second element appears at or after a first element in a finite sequence, then the first element must be a member of that sequence.*)\nLemma mem2l p x y : mem2 p x y -> x \\in p.\n\n(*This lemma states that the relation of a second element appearing at or after a first element in a finite sequence is false if the first element is not a member of the sequence.*)\nLemma mem2lf {p x y} : x \\notin p -> mem2 p x y = false.\n\n(*This lemma states that if a second element appears at or after a first element in a finite sequence, then the second element must also be a member of that sequence.*)\nLemma mem2r p x y : mem2 p x y -> y \\in p.\n\n(*This lemma states that the relation of a second element appearing at or after a first element in a finite sequence is false if the second element is not a member of the sequence.*)\nLemma mem2rf {p x y} : y \\notin p -> mem2 p x y = false.\n\n(*This lemma states that for two concatenated finite sequences, the property that a second element appears at or after a first element holds if this property holds within the first sequence, or it holds within the second sequence, or if the first element is in the first sequence and the second element is in the second sequence.*)\nLemma mem2_cat p1 p2 x y :\n mem2 (p1 ++ p2) x y = mem2 p1 x y || mem2 p2 x y || (x \\in p1) && (y \\in p2).\n\n(*This lemma states that if an element appears at or after another in the concatenation of two finite sequences, this ordering is preserved when a third sequence is inserted between them.*)\nLemma mem2_splice p1 p3 x y p2 :\n mem2 (p1 ++ p3) x y -> mem2 (p1 ++ p2 ++ p3) x y.\n\n(*This lemma states that if an element appears at or after another in the concatenation of two finite sequences, this ordering is preserved when a single new element is prepended to the second sequence.*)\nLemma mem2_splice1 p1 p3 x y z :\n mem2 (p1 ++ p3) x y -> mem2 (p1 ++ z :: p3) x y.\n\n(*This lemma provides a recursive characterization for the ordered membership relation on a non-empty finite sequence. If the first element of the relation is the head of the sequence, the relation holds if the second element is any member of the sequence. Otherwise, the relation on the full sequence is equivalent to the relation on its tail.*)\nLemma mem2_cons x p y z :\n mem2 (x :: p) y z = (if x == y then z \\in x :: p else mem2 p y z).\n\n(*This lemma states that for a singleton finite sequence, the ordered membership relation holds only if both specified elements are equal to the unique element in the sequence.*)\nLemma mem2_seq1 x y z : mem2 [:: x] y z = (y == x) && (z == x).\n\n(*This lemma states that the last element of a finite sequence appears at or after any other given element in that sequence if and only if the given element is a member of the sequence.*)\nLemma mem2_last y0 p x : mem2 p x (last y0 p) = (x \\in p).\n\n(*This lemma states that if the first element of an ordered membership relation is not in the first of two concatenated finite sequences, then the relation on the concatenated sequence is equivalent to the relation on the second sequence alone.*)\nLemma mem2l_cat {p1 p2 x} : x \\notin p1 -> mem2 (p1 ++ p2) x =1 mem2 p2 x.\n\n(*This lemma states that if the second element of an ordered membership relation is not in the second of two concatenated finite sequences, then the relation on the concatenated sequence is equivalent to the relation on the first sequence alone.*)\nLemma mem2r_cat {p1 p2 x y} : y \\notin p2 -> mem2 (p1 ++ p2) x y = mem2 p1 x y.\n\n(*This lemma states that if neither of the two elements in an ordered membership relation are present in a middle sequence that is spliced between two other finite sequences, then the relation on the fully spliced sequence is equivalent to the relation on the sequence formed by concatenating only the outer two sequences.*)\nLemma mem2lr_splice {p1 p2 p3 x y} :\n x \\notin p2 -> y \\notin p2 -> mem2 (p1 ++ p2 ++ p3) x y = mem2 (p1 ++ p3) x y.\n\n(*This lemma provides an alternative characterization of the ordered membership relation, stating it is equivalent to the property that the two elements appear as an ordered subsequence within the given finite sequence. If the elements are identical, this is equivalent to simple membership.*)\nLemma mem2E s x y :\n mem2 s x y = subseq (if x == y then [:: x] else [:: x; y]) s.\n\n(*This is an inductive type that provides evidence for a finite sequence being decomposable into a prefix and a suffix, where the suffix begins with a given first element and also contains a given second element.*)\nVariant split2r x y : seq T -> Type :=\n Split2r p1 p2 of y \\in x :: p2 : split2r x y (p1 ++ x :: p2).\n\n(*This lemma states that if an element appears at or after another in a finite sequence, then there exists a constructive proof that the sequence can be split around the first element such that the second element is in the resulting suffix.*)\nLemma splitP2r p x y : mem2 p x y -> split2r x y p.\n\n(*This function takes an element and a finite sequence that represents a path, and returns a new sequence corresponding to a simple path, which has no repeated elements, by removing any cycles found in the original path.*)\nFixpoint shorten x p :=\n if p is y :: p' then\n if x \\in p then shorten x p' else y :: shorten y p'\n else [::].\n\n(*This inductive type specifies the properties of the output of a path-shortening operation. It certifies that a given resulting sequence is a simple path with no repeated elements, starts from a specified element, is composed entirely of elements from the original sequence, and terminates at a particular final element.*)\nVariant shorten_spec x p : T -> seq T -> Type :=\n ShortenSpec p' of path e x p' & uniq (x :: p') & {subset p' <= p} :\n shorten_spec x p (last x p') p'.\n\n(*This lemma states that if a given finite sequence is a path starting from a specific element, applying the `shorten` function to it produces a new sequence that is a simple path. This new path starts with the same element, ends with the same element as the original path, and is certified to satisfy the properties defined by `shorten_spec`.*)\nLemma shortenP x p : path e x p -> shorten_spec x p (last x p) (shorten x p).\n\nEnd EqPath.\n\nSection SortSeq.\n\nVariables (T : Type) (leT : rel T).\n\n(*This function takes two sequences, assumed to be sorted with respect to a given relation, and merges them into a single sorted sequence containing all elements from both inputs.*)\nFixpoint merge s1 :=\n if s1 is x1 :: s1' then\n let fix merge_s1 s2 :=\n if s2 is x2 :: s2' then\n if leT x1 x2 then x1 :: merge s1' s2 else x2 :: merge_s1 s2'\n else s1 in\n merge_s1\n else id.\n\nArguments merge !s1 !s2 : rename.\n\n(*This function is a helper for a bottom-up merge sort. It takes a sorted sequence and a list of sorted sequences, known as runs, and repeatedly merges the input sequence with the runs at the head of the list until an empty slot is found, effectively pushing the new, larger run onto the list of runs.*)\nFixpoint merge_sort_push s1 ss :=\n match ss with\n | [::] :: ss' | [::] as ss' => s1 :: ss'\n | s2 :: ss' => [::] :: merge_sort_push (merge s2 s1) ss'\n end.\n\n(*This function is a helper for a bottom-up merge sort. It takes a sequence and a list of sorted sequences, known as runs, and merges them all into a single final sorted sequence by repeatedly merging the input sequence with the head of the list of runs.*)\nFixpoint merge_sort_pop s1 ss :=\n if ss is s2 :: ss' then merge_sort_pop (merge s2 s1) ss' else s1.\n\n(*This function is the recursive core of a bottom-up merge sort algorithm. It processes an input sequence by creating small sorted runs of size two, and then uses a push-and-merge strategy on a list of runs to progressively build larger sorted runs until the entire input is processed, finally merging all runs into a single sorted sequence.*)\nFixpoint merge_sort_rec ss s :=\n if s is [:: x1, x2 & s'] then\n let s1 := if leT x1 x2 then [:: x1; x2] else [:: x2; x1] in\n merge_sort_rec (merge_sort_push s1 ss) s'\n else merge_sort_pop s ss.\n\n(*This definition provides a bottom-up merge sort algorithm that sorts a given sequence of elements according to a specified relation.*)\nDefinition sort := merge_sort_rec [::].\n\n(*This function provides an alternative implementation of a bottom-up merge sort which processes the input sequence one element at a time, treating each element as a sorted run of size one and successively merging them into larger runs.*)\nFixpoint sort_rec1 ss s :=\n if s is x :: s then sort_rec1 (merge_sort_push [:: x] ss) s else\n merge_sort_pop [::] ss.\n\n(*This lemma states that the standard merge sort function is equivalent to an alternative implementation that processes the input sequence one element at a time.*)\nLemma sortE s : sort s = sort_rec1 [::] s.\n\n(*This lemma states that the number of elements satisfying a given predicate in a sequence resulting from a merge operation is equal to the total count of such elements in the original two sequences combined.*)\nLemma count_merge (p : pred T) s1 s2 :\n count p (merge s1 s2) = count p (s1 ++ s2).\n\n(*This lemma states that the length of a sequence resulting from a merge operation is equal to the sum of the lengths of the two input sequences.*)\nLemma size_merge s1 s2 : size (merge s1 s2) = size (s1 ++ s2).\n\n(*This lemma states that if two input sequences are sorted and every element in the first sequence is less than or equal to every element in the second sequence according to a given relation, then merging them is equivalent to concatenating them in order.*)\nLemma allrel_merge s1 s2 : allrel leT s1 s2 -> merge s1 s2 = s1 ++ s2.\n\n(*This lemma states that sorting a sequence does not change the number of elements that satisfy a given predicate.*)\nLemma count_sort (p : pred T) s : count p (sort s) = count p s.\n\n(*This lemma states that if a sequence is already sorted with respect to a given relation, applying the sort function to it will return the original sequence unchanged.*)\nLemma pairwise_sort s : pairwise leT s -> sort s = s.\n\n(*This remark formalizes a property of the merge sort's push operation, stating that if it acts on a sequence of size two, it preserves the invariant that the list of sorted runs is 'graded', meaning the size of each run is bounded by a power of two.*)\nRemark size_merge_sort_push s1 :\n let graded ss := forall i, size (nth [::] ss i) \\in pred2 0 (2 ^ (i + 1)) in\n size s1 = 2 -> {homo merge_sort_push s1 : ss / graded ss}.\n\nSection Stability.\n\nVariable leT' : rel T.\nHypothesis (leT_total : total leT) (leT'_tr : transitive leT').\n\n(*This definition creates a new lexicographic relation from two existing relations. An element is less than or equal to another if it is so under the first relation, and, in the case where they are equivalent under the first relation, the second relation is used as a tie-breaker.*)\nLet leT_lex := [rel x y | leT x y && (leT y x ==> leT' x y)].\n\n(*This lemma establishes a stability property for the merge operation. It states that if two sequences are sorted paths starting with the same element with respect to a lexicographic relation, and the secondary tie-breaking relation holds between all elements of the first sequence and all elements of the second, then the merged sequence will also be a sorted path with respect to the same lexicographic relation.*)\nLemma merge_stable_path x s1 s2 :\n allrel leT' s1 s2 -> path leT_lex x s1 -> path leT_lex x s2 ->\n path leT_lex x (merge s1 s2).\n\n(*This lemma proves that the merge operation is stable. It shows that if two sequences are sorted with respect to a lexicographic tie-breaking relation, and the merge is performed using only the primary relation, the resulting merged sequence remains sorted with respect to the original lexicographic relation.*)\nLemma merge_stable_sorted s1 s2 :\n allrel leT' s1 s2 -> sorted leT_lex s1 -> sorted leT_lex s2 ->\n sorted leT_lex (merge s1 s2).\n\nEnd Stability.\n\nHypothesis leT_total : total leT.\n\n(*This definition shows that a total relation is extensionally equal to a lexicographic relation where the tie-breaking condition is always true.*)\nLet leElex : leT =2 [rel x y | leT x y && (leT y x ==> true)].\n\n(*This lemma states that if two sequences are sorted paths starting with the same element, then the sequence resulting from merging them is also a sorted path starting with that element, assuming the relation is total.*)\nLemma merge_path x s1 s2 :\n path leT x s1 -> path leT x s2 -> path leT x (merge s1 s2).\n\n(*This lemma states that for a total relation, merging two sorted sequences results in a new sequence that is also sorted.*)\nLemma merge_sorted s1 s2 :\n sorted leT s1 -> sorted leT s2 -> sorted leT (merge s1 s2).\n\nHypothesis leT_tr : transitive leT.\n\n(*This lemma states that if the concatenation of two sequences is already sorted with respect to a transitive relation, then merging these two sequences is equivalent to simply concatenating them.*)\nLemma sorted_merge s t : sorted leT (s ++ t) -> merge s t = s ++ t.\n\n(*This lemma states that applying the sort function to a sequence that is already sorted with respect to a transitive relation returns the original sequence unchanged.*)\nLemma sorted_sort s : sorted leT s -> sort s = s.\n\n(*This lemma states that the merge operation is associative, provided the underlying relation is total and transitive.*)\nLemma mergeA : associative merge.\n\nEnd SortSeq.\n\nArguments merge {T} relT !s1 !s2 : rename.\nArguments size_merge {T} leT s1 s2.\nArguments allrel_merge {T leT s1 s2}.\nArguments pairwise_sort {T leT s}.\nArguments merge_path {T leT} leT_total {x s1 s2}.\nArguments merge_sorted {T leT} leT_total {s1 s2}.\nArguments sorted_merge {T leT} leT_tr {s t}.\nArguments sorted_sort {T leT} leT_tr {s}.\nArguments mergeA {T leT} leT_total leT_tr.\n\nSection SortMap.\nVariables (T T' : Type) (f : T' -> T).\n\nSection Monotonicity.\n\nVariables (leT' : rel T') (leT : rel T).\nHypothesis f_mono : {mono f : x y / leT' x y >-> leT x y}.\n\n(*This lemma asserts that for a monotonic function, mapping the function over the result of a merge operation is equivalent to first mapping the function over each input sequence and then merging the results.*)\nLemma map_merge : {morph map f : s1 s2 / merge leT' s1 s2 >-> merge leT s1 s2}.\n\n(*This lemma asserts that for a monotonic function, mapping the function over a sorted sequence is equivalent to first mapping the function over the original sequence and then sorting the result.*)\nLemma map_sort : {morph map f : s1 / sort leT' s1 >-> sort leT s1}.\n\nEnd Monotonicity.\n\nVariable leT : rel T.\n\n(*This lemma states that merging two sequences that have been transformed by a function is equivalent to first merging the original sequences using the pullback of the relation by that function, and then applying the function to the result.*)\nLemma merge_map s1 s2 :\n merge leT (map f s1) (map f s2) = map f (merge (relpre f leT) s1 s2).\n\n(*This lemma states that sorting a sequence that has been transformed by a function is equivalent to applying the function to the sequence that has been sorted using the pullback of the relation by that function.*)\nLemma sort_map s : sort leT (map f s) = map f (sort (relpre f leT) s).\n\nEnd SortMap.\n\nArguments map_merge {T T' f leT' leT}.\nArguments map_sort {T T' f leT' leT}.\nArguments merge_map {T T' f leT}.\nArguments sort_map {T T' f leT}.\n\n(*This lemma states that if a sequence is already sorted and all its elements satisfy a certain predicate, and the sorting relation is transitive for all elements satisfying that predicate, then applying the sort function to the sequence returns the original sequence unchanged.*)\nLemma sorted_sort_in T (P : {pred T}) (leT : rel T) :\n {in P & &, transitive leT} ->\n forall s : seq T, all P s -> sorted leT s -> sort leT s = s.\n\nArguments sorted_sort_in {T P leT} leT_tr {s}.\n\nSection EqSortSeq.\n\nVariables (T : eqType) (leT : rel T).\n\n(*This lemma states that the sequence resulting from a merge operation is a permutation of the sequence created by concatenating the two original input sequences.*)\nLemma perm_merge s1 s2 : perm_eql (merge leT s1 s2) (s1 ++ s2).\n\n(*This lemma states that the multiset of elements in a sequence resulting from a merge operation is identical to the multiset of elements in the concatenation of the two original input sequences.*)\nLemma mem_merge s1 s2 : merge leT s1 s2 =i s1 ++ s2.\n\n(*This lemma states that the sequence of unique elements obtained from a merged sequence is identical to the sequence of unique elements obtained from the concatenation of the two original input sequences.*)\nLemma merge_uniq s1 s2 : uniq (merge leT s1 s2) = uniq (s1 ++ s2).\n\n(*This lemma states that sorting a finite sequence with a given relation results in a sequence that is a permutation of the original one.*)\nLemma perm_sort s : perm_eql (sort leT s) s.\n\n(*This lemma states that the multiset of elements in a sorted finite sequence is identical to the multiset of elements in the original sequence.*)\nLemma mem_sort s : sort leT s =i s. \n\n(*This lemma states that the sequence of unique elements obtained from a sorted finite sequence is identical to the sequence of unique elements obtained from the original sequence.*)\nLemma sort_uniq s : uniq (sort leT s) = uniq s.\n\n(*This lemma states that if two pairs of finite sequences have respectively equal counts of elements satisfying a given predicate, then the count of elements satisfying that predicate in the merged sequence of the first pair is equal to the count in the merged sequence of the second pair.*)\nLemma eq_count_merge (p : pred T) s1 s1' s2 s2' :\n count p s1 = count p s1' -> count p s2 = count p s2' ->\n count p (merge leT s1 s2) = count p (merge leT s1' s2').\n\nEnd EqSortSeq.\n\n(*This lemma states that for any finite sequence, there exists a permutation of its indices such that mapping the original sequence over these permuted indices produces the sorted version of that sequence.*)\nLemma perm_iota_sort (T : Type) (leT : rel T) x0 s :\n {i_s : seq nat | perm_eq i_s (iota 0 (size s)) &\n sort leT s = map (nth x0 s) i_s}.\n\n(*This lemma states that a predicate holds for all elements of a merged finite sequence if and only if it holds for all elements of both input sequences.*)\nLemma all_merge (T : Type) (P : {pred T}) (leT : rel T) s1 s2 :\n all P (merge leT s1 s2) = all P s1 && all P s2.\n\n(*This lemma states that a predicate holds for all elements of a sorted finite sequence if and only if it holds for all elements of the original sequence.*)\nLemma all_sort (T : Type) (P : {pred T}) (leT : rel T) s :\n all P (sort leT s) = all P s.\n\n(*This lemma states that the length of a sorted finite sequence is equal to the length of the original sequence.*)\nLemma size_sort (T : Type) (leT : rel T) s : size (sort leT s) = size s.\n\n(*This lemma states that a finite sequence of natural numbers is sorted in strictly increasing order if and only if it contains no duplicate elements and is sorted in non-decreasing order.*)\nLemma ltn_sorted_uniq_leq s : sorted ltn s = uniq s && sorted leq s.\n\n(*This lemma states that a finite sequence of natural numbers is sorted in strictly decreasing order if and only if it contains no duplicate elements and is sorted in non-increasing order.*)\nLemma gtn_sorted_uniq_geq s : sorted gtn s = uniq s && sorted geq s.\n\n(*This lemma states that the finite sequence of natural numbers generated by iota, starting from a given number for a given length, is sorted in non-decreasing order.*)\nLemma iota_sorted i n : sorted leq (iota i n).\n\n(*This lemma states that the finite sequence of natural numbers generated by iota, starting from a given number for a given length, is sorted in strictly increasing order.*)\nLemma iota_ltn_sorted i n : sorted ltn (iota i n).\n\nSection Stability_iota.\n\nVariables (leN : rel nat) (leN_total : total leN).\n\n(*This definition creates a strict lexicographical order relation on natural numbers. An element is considered smaller than another if it is smaller under a given total preorder, or if they are equivalent under the preorder, it is smaller under the standard strict less-than relation.*)\nLet lt_lex := [rel n m | leN n m && (leN m n ==> (n < m))].\n\n(*This definition specifies a recursive invariant for a sequence of sequences of natural numbers, which holds if, for each sequence in the list, it is sorted according to a strict lexicographical order, and all its elements are strictly greater than every element in all subsequent sequences.*)\nLet Fixpoint push_invariant (ss : seq (seq nat)) :=\n if ss is s :: ss' then\n [&& sorted lt_lex s, allrel gtn s (flatten ss') & push_invariant ss']\n else\n true.\n\n(*This declaration states that if a given invariant holds for a sequence of sequences of natural numbers after prepending a new sequence, then the same invariant also holds for the result of applying the merge-sort push operation.*)\nLet push_stable s1 ss :\n push_invariant (s1 :: ss) -> push_invariant (merge_sort_push leN s1 ss).\n\n(*This declaration states that if a given invariant holds for a sequence of sequences of natural numbers after prepending a new sequence, then the result of applying the merge-sort pop operation is a single sequence sorted according to a strict lexicographical order.*)\nLet pop_stable s1 ss :\n push_invariant (s1 :: ss) -> sorted lt_lex (merge_sort_pop leN s1 ss).\n\n(*This lemma states that sorting the sequence of natural numbers from zero up to a given bound using a total relation results in a sequence that is sorted with respect to the corresponding derived strict lexicographical order.*)\nLemma sort_iota_stable n : sorted lt_lex (sort leN (iota 0 n)).\n\nEnd Stability_iota.\n\n(*This lemma states that if a finite sequence has a property where a secondary relation holds for every pair of its elements in their original order, then sorting this sequence with a primary total relation results in a sequence that is sorted according to a composite relation; this composite relation uses the primary relation for comparison and the secondary relation to break ties.*)\nLemma sort_pairwise_stable T (leT leT' : rel T) :\n total leT -> forall s : seq T, pairwise leT' s ->\n sorted [rel x y | leT x y && (leT y x ==> leT' x y)] (sort leT s).\n\n(*This lemma states that if a finite sequence is already sorted with respect to a secondary transitive relation, then sorting it with a primary total relation produces a sequence that is sorted with respect to a composite relation, which uses the primary relation for comparison and the secondary relation to break ties.*)\nLemma sort_stable T (leT leT' : rel T) :\n total leT -> transitive leT' -> forall s : seq T, sorted leT' s ->\n sorted [rel x y | leT x y && (leT y x ==> leT' x y)] (sort leT s).\n\n(*This lemma states that for a finite sequence whose elements all satisfy a certain predicate, if the sequence is sorted with respect to a secondary relation that is transitive on those elements, then sorting it with a primary relation that is total on those elements yields a sequence sorted by the corresponding composite, tie-breaking relation.*)\nLemma sort_stable_in T (P : {pred T}) (leT leT' : rel T) :\n {in P &, total leT} -> {in P & &, transitive leT'} ->\n forall s : seq T, all P s -> sorted leT' s ->\n sorted [rel x y | leT x y && (leT y x ==> leT' x y)] (sort leT s).\n\n(*This lemma states that for any total and transitive relation, filtering a sorted finite sequence with a given predicate yields the same result as first filtering the original sequence with the same predicate and then sorting the outcome.*)\nLemma filter_sort T (leT : rel T) :\n total leT -> transitive leT ->\n forall p s, filter p (sort leT s) = sort leT (filter p s).\n\n(*This lemma states that for a finite sequence whose elements all satisfy a given property, and for a relation that is total and transitive on those elements, filtering the sorted sequence is equivalent to sorting the filtered sequence.*)\nLemma filter_sort_in T (P : {pred T}) (leT : rel T) :\n {in P &, total leT} -> {in P & &, transitive leT} ->\n forall p s, all P s -> filter p (sort leT s) = sort leT (filter p s).\n\nSection Stability_mask.\n\nVariables (T : Type) (leT : rel T).\nVariables (leT_total : total leT) (leT_tr : transitive leT).\n\n(*This lemma states that for any finite sequence and a given boolean mask, there exists another boolean mask such that applying it to the sorted version of the sequence yields the same result as sorting the subsequence obtained by applying the original mask to the original sequence.*)\nLemma mask_sort s m :\n {m_s : bitseq | mask m_s (sort leT s) = sort leT (mask m s)}.\n\n(*This lemma states that if a subsequence of a finite sequence, selected by a boolean mask, is already sorted, then there exists another boolean mask that can extract that very same subsequence from the sorted version of the original sequence.*)\nLemma sorted_mask_sort s m :\n sorted leT (mask m s) -> {m_s | mask m_s (sort leT s) = mask m s}.\n\nEnd Stability_mask.\n\nSection Stability_mask_in.\n\nVariables (T : Type) (P : {pred T}) (leT : rel T).\nHypothesis leT_total : {in P &, total leT}.\nHypothesis leT_tr : {in P & &, transitive leT}.\n\n(*This definition creates a relation on a subtype by lifting a relation from the ambient type; two elements of the subtype are related if their corresponding elements in the ambient type are related.*)\nLet le_sT := relpre (val : sig P -> _) leT.\n(*This declaration states that if a relation is total on all elements of a type that satisfy a given predicate, then the corresponding lifted relation on the subtype of elements satisfying that predicate is also total.*)\nLet le_sT_total : total le_sT := in2_sig leT_total.\n(*This declaration states that if a relation is transitive on all elements of a type that satisfy a given predicate, then the corresponding lifted relation on the subtype of elements satisfying that predicate is also transitive.*)\nLet le_sT_tr : transitive le_sT := in3_sig leT_tr.\n\n(*This lemma states that for a finite sequence whose elements all satisfy a given predicate, and for any boolean mask, there exists another mask such that applying it to the sorted sequence gives the same result as sorting the subsequence obtained by applying the original mask.*)\nLemma mask_sort_in s m :\n all P s -> {m_s : bitseq | mask m_s (sort leT s) = sort leT (mask m s)}.\n\n(*This lemma states that for a finite sequence whose elements all satisfy a given predicate, if a subsequence selected by a boolean mask is already sorted, then there exists another mask that extracts that exact same subsequence from the sorted version of the original sequence.*)\nLemma sorted_mask_sort_in s m :\n all P s -> sorted leT (mask m s) -> {m_s | mask m_s (sort leT s) = mask m s}.\n\nEnd Stability_mask_in.\n\nSection Stability_subseq.\n\nVariables (T : eqType) (leT : rel T).\nVariables (leT_total : total leT) (leT_tr : transitive leT).\n\n(*This lemma states that the sort operation is a homomorphism with respect to the subsequence relation, meaning that if one finite sequence is a subsequence of another, then the sorted version of the first sequence is a subsequence of the sorted version of the second.*)\nLemma subseq_sort : {homo sort leT : t s / subseq t s}.\n\n(*This lemma states that if a sorted sequence is a subsequence of another sequence, then it is also a subsequence of the sorted version of that other sequence.*)\nLemma sorted_subseq_sort t s :\n subseq t s -> sorted leT t -> subseq t (sort leT s).\n\n(*This lemma states that if two elements are present in a sequence and one is less than or equal to the other according to a given relation, then both elements will also be present in the sequence after it has been sorted using that relation.*)\nLemma mem2_sort s x y : leT x y -> mem2 s x y -> mem2 (sort leT s) x y.\n\nEnd Stability_subseq.\n\nSection Stability_subseq_in.\n\nVariables (T : eqType) (leT : rel T).\n\n(*This lemma states that if a relation is total and transitive for all elements in a given sequence, and another sequence is a subsequence of it, then the sorted version of the latter sequence is a subsequence of the sorted version of the former.*)\nLemma subseq_sort_in t s :\n {in s &, total leT} -> {in s & &, transitive leT} ->\n subseq t s -> subseq (sort leT t) (sort leT s).\n\n(*This lemma states that if a relation is total and transitive for all elements in a sequence, and a sorted sequence is a subsequence of it, then the sorted subsequence remains a subsequence of the sorted version of the original sequence.*)\nLemma sorted_subseq_sort_in t s :\n {in s &, total leT} -> {in s & &, transitive leT} ->\n subseq t s -> sorted leT t -> subseq t (sort leT s).\n\n(*This lemma states that if a relation is total and transitive for all elements in a sequence, and two elements present in that sequence are ordered by the relation, then both elements will also be present in the sorted version of the sequence.*)\nLemma mem2_sort_in s :\n {in s &, total leT} -> {in s & &, transitive leT} ->\n forall x y, leT x y -> mem2 s x y -> mem2 (sort leT s) x y.\n\nEnd Stability_subseq_in.\n\n(*This lemma states that for any sequence, sorting it with a total relation yields a sequence that is sorted with respect to that same relation.*)\nLemma sort_sorted T (leT : rel T) :\n total leT -> forall s, sorted leT (sort leT s).\n\n(*This lemma states that if a relation is total over a subset of elements defined by a predicate, then sorting a sequence containing only elements from that subset will result in a sorted sequence.*)\nLemma sort_sorted_in T (P : {pred T}) (leT : rel T) :\n {in P &, total leT} -> forall s : seq T, all P s -> sorted leT (sort leT s).\n\nArguments sort_sorted {T leT} leT_total s.\nArguments sort_sorted_in {T P leT} leT_total {s}.\n\n(*This lemma states that for any two sequences and a total order relation, the sorted versions of the sequences are identical if and only if the two original sequences are permutations of each other.*)\nLemma perm_sortP (T : eqType) (leT : rel T) :\n total leT -> transitive leT -> antisymmetric leT ->\n forall s1 s2, reflect (sort leT s1 = sort leT s2) (perm_eq s1 s2).\n\n(*This lemma states that for any two sequences, if a relation is a total order for all elements in the first sequence, then the sorted versions of the sequences are identical if and only if the two original sequences are permutations of each other.*)\nLemma perm_sort_inP (T : eqType) (leT : rel T) (s1 s2 : seq T) :\n {in s1 &, total leT} -> {in s1 & &, transitive leT} ->\n {in s1 &, antisymmetric leT} ->\n reflect (sort leT s1 = sort leT s2) (perm_eq s1 s2).\n\n(*This lemma states that mapping a function over a sorted sequence is equivalent to sorting the sequence after mapping the function over it, provided the function is monotonic with respect to the source and target relations, and the relations meet certain totality, transitivity, and antisymmetry conditions.*)\nLemma homo_sort_map (T : Type) (T' : eqType) (f : T -> T') leT leT' :\n antisymmetric (relpre f leT') -> transitive (relpre f leT') -> total leT ->\n {homo f : x y / leT x y >-> leT' x y} ->\n forall s : seq T, sort leT' (map f s) = map f (sort leT s).\n\n(*This lemma states that for any sequence whose elements satisfy a given predicate, mapping a function over the sorted sequence yields the same result as sorting the sequence after mapping the function over it. This holds if the function is monotonic and the relations satisfy certain properties on the subset of elements defined by the predicate.*)\nLemma homo_sort_map_in\n (T : Type) (T' : eqType) (P : {pred T}) (f : T -> T') leT leT' :\n {in P &, antisymmetric (relpre f leT')} ->\n {in P & &, transitive (relpre f leT')} -> {in P &, total leT} ->\n {in P &, {homo f : x y / leT x y >-> leT' x y}} ->\n forall s : seq T, all P s ->\n sort leT' [seq f x | x <- s] = [seq f x | x <- sort leT s].\n\nNotation fpath f := (path (coerced_frel f)).\nNotation fcycle f := (cycle (coerced_frel f)).\nNotation ufcycle f := (ucycle (coerced_frel f)).\n\nPrenex Implicits path next prev cycle ucycle mem2.\n\nSection Trajectory.\n\nVariables (T : Type) (f : T -> T).\n\n(*This fixpoint defines the trajectory of an element under a function as the sequence of the first n iterates of the function starting from that element.*)\nFixpoint traject x n := if n is n'.+1 then x :: traject (f x) n' else [::].\n\n(*This lemma states that the trajectory of length n plus one starting from an element is equal to that element consed with the trajectory of length n starting from the next element in the sequence generated by the function.*)\nLemma trajectS x n : traject x n.+1 = x :: traject (f x) n.\n\n(*This lemma provides an alternative construction for a trajectory, stating that the trajectory of length n plus one is the trajectory of length n with the n-th iterate of the function appended to the end.*)\nLemma trajectSr x n : traject x n.+1 = rcons (traject x n) (iter n f x).\n\n(*This lemma states that the last element of a trajectory of length n starting from the successor of an element x under a function f is the n-th iterate of f applied to x. If the trajectory is empty, a default value is returned.*)\nLemma last_traject x n : last x (traject (f x) n) = iter n f x.\n\n(*This lemma expresses the construction of a trajectory as an iteration, where the sequence is built up by successively appending each iterate of a function from the zeroth to the n-th minus one.*)\nLemma traject_iteri x n :\n traject x n = iteri n (fun i => rcons^~ (iter i f x)) [::].\n\n(*This lemma states that the size of a trajectory generated over n steps is equal to the natural number n.*)\nLemma size_traject x n : size (traject x n) = n.\n\n(*This lemma states that for a valid index i, the element at that index in an n-step trajectory starting from an element x is the i-th iterate of the function f applied to x.*)\nLemma nth_traject i n : i < n -> forall x, nth x (traject x n) i = iter i f x.\n\n(*This lemma states that a trajectory of length m plus n can be decomposed into the concatenation of a trajectory of length m and a trajectory of length n starting from the m-th iterate of the function.*)\nLemma trajectD m n x :\n traject x (m + n) = traject x m ++ traject (iter m f x) n.\n\n(*This lemma states that taking the first k elements of a trajectory of length n, where k is less than or equal to n, results in a trajectory of length k.*)\nLemma take_traject n k x : k <= n -> take k (traject x n) = traject x k.\n\nEnd Trajectory.\n\nSection EqTrajectory.\n\nVariables (T : eqType) (f : T -> T).\n\n(*This lemma states that if two functions are pointwise equal, then their induced path relations are also pointwise equal.*)\nLemma eq_fpath f' : f =1 f' -> fpath f =2 fpath f'.\n\n(*This lemma states that if two functions are pointwise equal, then their induced cycle predicates are also pointwise equal.*)\nLemma eq_fcycle f' : f =1 f' -> fcycle f =1 fcycle f'.\n\n(*This lemma states that if a sequence is a path originating from an element x under a function f, then this sequence is equal to the trajectory of f starting from the successor of x, with a length equal to the size of the path.*)\nLemma fpathE x p : fpath f x p -> p = traject f (f x) (size p).\n\n(*This lemma provides a characterization of a path: a sequence is a path originating from an element x under a function f if and only if it is a trajectory of f of some length n starting from the successor of x.*)\nLemma fpathP x p : reflect (exists n, p = traject f (f x) n) (fpath f x p).\n\n(*This lemma states that for any natural number n, the trajectory of length n starting from the successor of an element x under a function f constitutes a valid path originating from x.*)\nLemma fpath_traject x n : fpath f x (traject f (f x) n).\n\n(*This definition specifies a condition, called looping, which holds if the n-th iterate of a function starting from an element is found within the trajectory of the first n iterates.*)\nDefinition looping x n := iter n f x \\in traject f x n.\n\n(*This lemma states that the looping condition at step n is equivalent to the property that any iterate of the function will be a member of the initial trajectory of length n.*)\nLemma loopingP x n :\n reflect (forall m, iter m f x \\in traject f x n) (looping x n).\n\n(*This lemma provides a characterization for membership in a trajectory: an element belongs to a trajectory of length n if and only if it is equal to some iterate i of the function, where i is less than n.*)\nLemma trajectP x n y :\n reflect (exists2 i, i < n & y = iter i f x) (y \\in traject f x n).\n\n(*This lemma states that a trajectory of length n plus one has unique elements if and only if the n-th step looping condition is false.*)\nLemma looping_uniq x n : uniq (traject f x n.+1) = ~~ looping x n.\n\nEnd EqTrajectory.\n\nArguments fpathP {T f x p}.\nArguments loopingP {T f x n}.\nArguments trajectP {T f x n y}.\nPrenex Implicits traject.\n\nSection Fcycle.\nVariables (T : eqType) (f : T -> T) (p : seq T) (f_p : fcycle f p).\n\n(*This lemma states that for any element in a sequence that forms a cycle under a given function, the next element in the sequence is equal to the result of applying the function to that element.*)\nLemma nextE (x : T) (p_x : x \\in p) : next p x = f x.\n\n(*This lemma states that for a sequence that forms a cycle under a function, applying the function to any element in the sequence yields another element that is also in the sequence.*)\nLemma mem_fcycle : {homo f : x / x \\in p}.\n\n(*This lemma states that for a sequence that forms a cycle under a function, the function is injective when its domain is restricted to the elements of that sequence.*)\nLemma inj_cycle : {in p &, injective f}.\n\nEnd Fcycle.\n\nSection UniqCycle.\n\nVariables (n0 : nat) (T : eqType) (e : rel T) (p : seq T).\n\nHypothesis Up : uniq p.\n\n(*This lemma states that for any element in a sequence with unique elements, applying the 'previous' operation followed by the 'next' operation returns the original element.*)\nLemma prev_next : cancel (next p) (prev p).\n\n(*This lemma states that for any element in a sequence with unique elements, applying the 'next' operation followed by the 'previous' operation returns the original element.*)\nLemma next_prev : cancel (prev p) (next p).\n\n(*This lemma states that a sequence with unique elements forms a cycle under its 'next' operation, which determines the successor of each element within the sequence.*)\nLemma cycle_next : fcycle (next p) p.\n\n(*This lemma states that a sequence with unique elements forms a cycle under the relation where an element is related to another if the first is the predecessor of the second within the sequence.*)\nLemma cycle_prev : cycle (fun x y => x == prev p y) p.\n\n(*This lemma states that if a given binary relation holds between every element in a sequence with unique elements and its successor, then the sequence forms a cycle under that relation.*)\nLemma cycle_from_next : (forall x, x \\in p -> e x (next p x)) -> cycle e p.\n\n(*This lemma states that if a given binary relation holds between the predecessor of every element in a sequence with unique elements and the element itself, then the sequence forms a cycle under that relation.*)\nLemma cycle_from_prev : (forall x, x \\in p -> e (prev p x) x) -> cycle e p.\n\n(*This lemma states that the 'next' operation, which finds the successor of an element in a cyclic sequence with unique elements, is invariant under left rotation of the sequence.*)\nLemma next_rot : next (rot n0 p) =1 next p.\n\n(*This lemma states that the 'previous' operation, which finds the predecessor of an element in a cyclic sequence with unique elements, is invariant under left rotation of the sequence.*)\nLemma prev_rot : prev (rot n0 p) =1 prev p.\n\nEnd UniqCycle.\n\nSection UniqRotrCycle.\n\nVariables (n0 : nat) (T : eqType) (p : seq T).\n\nHypothesis Up : uniq p.\n\n(*This lemma states that the 'next' operation, which determines the successor of an element in a cyclic sequence with unique elements, remains unchanged when the sequence is rotated to the right.*)\nLemma next_rotr : next (rotr n0 p) =1 next p. \n\n(*This lemma states that the 'previous' operation, which determines the predecessor of an element in a cyclic sequence with unique elements, remains unchanged when the sequence is rotated to the right.*)\nLemma prev_rotr : prev (rotr n0 p) =1 prev p. \n\nEnd UniqRotrCycle.\n\nSection UniqCycleRev.\n\nVariable T : eqType.\nImplicit Type p : seq T.\n\n(*This lemma states that for a sequence with unique elements, the 'previous' operation on the reversed sequence is equivalent to the 'next' operation on the original sequence.*)\nLemma prev_rev p : uniq p -> prev (rev p) =1 next p.\n\n(*This lemma states that for a sequence with unique elements, the 'next' operation on the reversed sequence is equivalent to the 'previous' operation on the original sequence.*)\nLemma next_rev p : uniq p -> next (rev p) =1 prev p.\n\nEnd UniqCycleRev.\n\nSection MapPath.\n\nVariables (T T' : Type) (h : T' -> T) (e : rel T) (e' : rel T').\n\n(*This definition specifies a condition on two relations, a function, and a predicate, stating that for any pair of elements, if the image of the first element under the function does not satisfy the predicate, then the first relation applied to their images is equivalent to the second relation applied to the original elements.*)\nDefinition rel_base (b : pred T) :=\n forall x' y', ~~ b (h x') -> e (h x') (h y') = e' x' y'.\n\n(*This lemma states that if the `rel_base` condition holds and a path contains no elements whose images under a function satisfy a given predicate, then the property of forming a path is preserved when the function is applied to all elements of the path.*)\nLemma map_path b x' p' (Bb : rel_base b) :\n ~~ has (preim h b) (belast x' p') ->\n path e (h x') (map h p') = path e' x' p'.\n\nEnd MapPath.\n\nSection MapEqPath.\n\nVariables (T T' : eqType) (h : T' -> T) (e : rel T) (e' : rel T').\n\nHypothesis Ih : injective h.\n\n(*This lemma states that for an injective function, checking if the images of two elements are both present in a mapped sequence is equivalent to checking if the original two elements are both present in the original sequence.*)\nLemma mem2_map x' y' p' : mem2 (map h p') (h x') (h y') = mem2 p' x' y'.\n\n(*This lemma states that for an injective function and a sequence with unique elements, finding the successor of a mapped element in the mapped sequence is equivalent to mapping the successor of the original element from the original sequence.*)\nLemma next_map p : uniq p -> forall x, next (map h p) (h x) = h (next p x).\n\n(*This lemma states that for an injective function and a sequence with unique elements, finding the predecessor of a mapped element in the mapped sequence is equivalent to mapping the predecessor of the original element from the original sequence.*)\nLemma prev_map p : uniq p -> forall x, prev (map h p) (h x) = h (prev p x).\n\nEnd MapEqPath.\n\n(*This definition asserts that a function commutes with two other functions, meaning that applying the first function to the result of the second is equivalent to applying the third function and then the first.*)\nDefinition fun_base (T T' : eqType) (h : T' -> T) f f' :=\n rel_base h (frel f) (frel f').\n\nSection CycleArc.\n\nVariable T : eqType.\nImplicit Type p : seq T.\n\n(*This definition computes the path segment, or arc, within a cyclic sequence between two specified elements by rotating the sequence to start with the first element and taking all elements up to the position of the second.*)\nDefinition arc p x y := let px := rot (index x p) p in take (index y px) px.\n\n(*This lemma states that for a cyclic sequence with unique elements, the arc between any two elements remains the same even if the underlying sequence is rotated.*)\nLemma arc_rot i p : uniq p -> {in p, arc (rot i p) =2 arc p}.\n\n(*This lemma states that for a unique-element sequence constructed by concatenating an element 'x', a sequence 'p1', an element 'y', and a sequence 'p2', the arc from 'x' to 'y' is precisely the sequence formed by 'x' followed by 'p1'.*)\nLemma left_arc x y p1 p2 (p := x :: p1 ++ y :: p2) :\n uniq p -> arc p x y = x :: p1.\n\n(*This lemma states that for a unique-element sequence constructed by concatenating an element 'x', a sequence 'p1', an element 'y', and a sequence 'p2', the arc from 'y' back to 'x' is precisely the sequence formed by 'y' followed by 'p2'.*)\nLemma right_arc x y p1 p2 (p := x :: p1 ++ y :: p2) :\n uniq p -> arc p y x = y :: p2.\n\n(*This is an inductive specification asserting that a cyclic sequence containing two given elements can be decomposed into two complementary arcs, one from the first element to the second and the other from the second back to the first, and that the appropriately rotated sequence is equivalent to the concatenation of these two arcs.*)\nVariant rot_to_arc_spec p x y :=\n RotToArcSpec i p1 p2 of x :: p1 = arc p x y\n & y :: p2 = arc p y x\n & rot i p = x :: p1 ++ y :: p2 :\n rot_to_arc_spec p x y.\n\n(*This lemma asserts that for any cyclic sequence with unique elements containing two specified elements, there exists a decomposition of the sequence into two arcs connecting these elements that satisfies the `rot_to_arc_spec`.*)\nLemma rot_to_arc p x y :\n uniq p -> x \\in p -> y \\in p -> x != y -> rot_to_arc_spec p x y.\n\nEnd CycleArc.", - "boot.tuple": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat.\nFrom mathcomp Require Import seq choice fintype path.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nSection TupleDef.\n\nVariables (n : nat) (T : Type).\n\n(*A structure that defines a tuple of a fixed length with elements of a given type. It is represented by a sequence of elements along with a proof that the length of the sequence is exactly equal to the fixed length.*)\nStructure tuple_of : Type := Tuple {tval :> seq T; _ : size tval == n}.\n\n(*This definition specifies the size of a tuple, returning the fixed natural number that corresponds to its length.*)\nDefinition tsize of tuple_of := n.\n\n(*This lemma states that the size of the underlying sequence of a tuple of a given length is equal to that length.*)\nLemma size_tuple t : size t = n.\n\n(*This lemma postulates the existence of a function that provides a default value of the element type for any given valid index of a tuple.*)\nLemma tnth_default t : 'I_n -> T.\n\n(*This definition provides access to the element of a tuple at a given ordinal index.*)\nDefinition tnth t i := nth (tnth_default t i) t i.\n\n(*This lemma states that accessing the element of a tuple at a given index is equivalent to accessing the element of its underlying sequence at the same index, when provided with a specific default value.*)\nLemma tnth_nth x t i : tnth t i = nth x t i.\n\n(*This lemma establishes an equivalence between two ways of accessing an element in a tuple: it states that retrieving an element at a given index with a default value yields a specific value if and only if a safe retrieval at the same index returns an optional value containing that specific value.*)\nLemma tnth_onth x t i : tnth t i = x <-> onth t i = Some x.\n\n(*This lemma states that mapping the element-access function over the complete sequence of valid indices for a tuple rebuilds the sequence that underlies that tuple.*)\nLemma map_tnth_enum t : map (tnth t) (enum 'I_n) = t.\n\n(*This lemma provides an extensionality principle for tuples, stating that if two tuples yield equal elements for every valid index, then the two tuples are themselves equal.*)\nLemma eq_from_tnth t1 t2 : tnth t1 =1 tnth t2 -> t1 = t2.\n\n(*This definition provides a generic constructor for creating a tuple from its underlying sequence, requiring a separate proof that the sequence's length matches the tuple's expected length.*)\nDefinition tuple t mkT : tuple_of :=\n mkT (let: Tuple _ tP := t return size t == n in tP).\n\n(*This lemma states that constructing a tuple from the underlying sequence and size proof of an existing tuple results in the original tuple.*)\nLemma tupleE t : tuple (fun sP => @Tuple t sP) = t.\n\nEnd TupleDef.\n\n(*This notation represents the type of tuples of a fixed length, specified by a natural number.*)\nNotation \"n .-tuple\" := (tuple_of n)\n (at level 2, format \"n .-tuple\") : type_scope.\n\n(*This notation is used for parsing the type of tuples of a specified length and element type.*)\nNotation \"{ 'tuple' n 'of' T }\" := (n.-tuple T : predArgType)\n (only parsing) : type_scope.\n\n(*This notation constructs a tuple from a given sequence, where the fixed length of the tuple is inferred from the context and proven equal to the sequence's length.*)\nNotation \"[ 'tuple' 'of' s ]\" := (tuple (fun sP => @Tuple _ _ s sP))\n (format \"[ 'tuple' 'of' s ]\") : form_scope.\n\n(*This notation provides a convenient way to access the element of a tuple at a given natural number index, which is internally converted to a corresponding ordinal index.*)\nNotation \"[ 'tnth' t i ]\" := (tnth t (@Ordinal (tsize t) i (erefl true)))\n (t, i at level 8, format \"[ 'tnth' t i ]\") : form_scope.\n\nCanonical nil_tuple T := Tuple (isT : @size T [::] == 0).\nCanonical cons_tuple n T x (t : n.-tuple T) :=\n Tuple (valP t : size (x :: t) == n.+1).\n\n(*This notation constructs a tuple directly from an explicit, semicolon-separated list of its elements.*)\nNotation \"[ 'tuple' x1 ; .. ; xn ]\" := [tuple of x1 :: .. [:: xn] ..]\n (format \"[ 'tuple' '[' x1 ; '/' .. ; '/' xn ']' ]\") : form_scope.\n\n(*This notation represents the empty tuple, which is a tuple of length zero.*)\nNotation \"[ 'tuple' ]\" := [tuple of [::]] (format \"[ 'tuple' ]\") : form_scope.\n\nSection CastTuple.\n\nVariable T : Type.\n\n(*This definition converts a sequence into a tuple, where the fixed length of the new tuple is defined to be the length of the input sequence.*)\nDefinition in_tuple (s : seq T) := Tuple (eqxx (size s)).\n\n(*This definition casts a tuple with a specific length to a tuple with a different length, provided there is a proof that the two lengths are equal.*)\nDefinition tcast m n (eq_mn : m = n) t :=\n let: erefl in _ = n := eq_mn return n.-tuple T in t.\n\n(*This lemma states that accessing an element at a given index in a length-casted tuple is equivalent to accessing the element in the original tuple at an index that has been correspondingly cast to the original length's index type.*)\nLemma tcastE m n (eq_mn : m = n) t i :\n tnth (tcast eq_mn t) i = tnth t (cast_ord (esym eq_mn) i).\n\n(*This lemma states that casting a tuple to the same length, using a proof that the length is equal to itself, results in the original tuple.*)\nLemma tcast_id n (eq_nn : n = n) t : tcast eq_nn t = t.\n\n(*This lemma states that casting a tuple's length from one value to another is cancelled out by casting it back, effectively yielding an identity transformation.*)\nLemma tcastK m n (eq_mn : m = n) : cancel (tcast eq_mn) (tcast (esym eq_mn)).\n\n(*This lemma states that a tuple length cast is cancelled out by its inverse cast, effectively yielding an identity transformation.*)\nLemma tcastKV m n (eq_mn : m = n) : cancel (tcast (esym eq_mn)) (tcast eq_mn).\n\n(*This lemma establishes the transitivity of the tuple casting operation, showing that casting a tuple's length from an initial length to a final length is equivalent to composing two intermediate casts through a middle length.*)\nLemma tcast_trans m n p (eq_mn : m = n) (eq_np : n = p) t:\n tcast (etrans eq_mn eq_np) t = tcast eq_np (tcast eq_mn t).\n\n(*This lemma states that converting a tuple's underlying sequence back into a tuple is equivalent to casting the original tuple using a proof that its fixed length is equal to the dynamic size of its underlying sequence.*)\nLemma tvalK n (t : n.-tuple T) : in_tuple t = tcast (esym (size_tuple t)) t.\n\n(*This lemma states that casting a tuple's type-level length does not change its underlying sequence representation.*)\nLemma val_tcast m n (eq_mn : m = n) (t : m.-tuple T) :\n tcast eq_mn t = t :> seq T.\n\n(*This lemma states that the underlying sequence of a tuple created from a given sequence is identical to the original sequence.*)\nLemma in_tupleE s : in_tuple s = s :> seq T. \n\nEnd CastTuple.\n\nSection SeqTuple.\n\nVariables (n m : nat) (T U rT : Type).\nImplicit Type t : n.-tuple T.\n\n(*This lemma states that appending an element to the right of the underlying sequence of a tuple of length `n` results in a new sequence whose length is `n` plus one.*)\nLemma rcons_tupleP t x : size (rcons t x) == n.+1.\n\nCanonical rcons_tuple t x := Tuple (rcons_tupleP t x).\n\n(*This lemma states that a sequence created by repeating a given element `n` times has a length equal to `n`.*)\nLemma nseq_tupleP x : @size T (nseq n x) == n.\n\nCanonical nseq_tuple x := Tuple (nseq_tupleP x).\n\n(*This lemma states that the sequence of `n` consecutive natural numbers starting from a given number `m` has a length equal to `n`.*)\nLemma iota_tupleP : size (iota m n) == n.\n\nCanonical iota_tuple := Tuple iota_tupleP.\n\n(*This lemma states that removing the first element from a finite sequence of a given size results in a new finite sequence whose size is one less than the original.*)\nLemma behead_tupleP t : size (behead t) == n.-1.\n\nCanonical behead_tuple t := Tuple (behead_tupleP t).\n\n(*This lemma states that creating a new finite sequence by removing the first element of a given finite sequence and appending a new element to the end results in a finite sequence of the same original size.*)\nLemma belast_tupleP x t : size (belast x t) == n.\n\nCanonical belast_tuple x t := Tuple (belast_tupleP x t).\n\n(*This lemma states that the size of a finite sequence created by concatenating two finite sequences is the sum of their individual sizes.*)\nLemma cat_tupleP t (u : m.-tuple T) : size (t ++ u) == n + m.\n\nCanonical cat_tuple t u := Tuple (cat_tupleP t u).\n\n(*This lemma states that the size of the finite sequence formed by taking a specified number of initial elements from another finite sequence is the minimum of the specified number and the original sequence's size.*)\nLemma take_tupleP t : size (take m t) == minn m n.\n\nCanonical take_tuple t := Tuple (take_tupleP t).\n\n(*This lemma states that the size of the finite sequence resulting from removing a specified number of initial elements from another finite sequence is the difference between the original size and the number of elements removed.*)\nLemma drop_tupleP t : size (drop m t) == n - m.\n\nCanonical drop_tuple t := Tuple (drop_tupleP t).\n\n(*This lemma states that reversing the order of elements in a finite sequence does not change its size.*)\nLemma rev_tupleP t : size (rev t) == n.\n\nCanonical rev_tuple t := Tuple (rev_tupleP t).\n\n(*This lemma states that cyclically shifting the elements of a finite sequence to the left by any number of positions results in a finite sequence of the same size.*)\nLemma rot_tupleP t : size (rot m t) == n.\n\nCanonical rot_tuple t := Tuple (rot_tupleP t).\n\n(*This lemma states that cyclically shifting the elements of a finite sequence to the right by any number of positions results in a finite sequence of the same size.*)\nLemma rotr_tupleP t : size (rotr m t) == n.\n\nCanonical rotr_tuple t := Tuple (rotr_tupleP t).\n\n(*This lemma states that applying a function to every element of a finite sequence produces a new finite sequence of the same size as the original.*)\nLemma map_tupleP f t : @size rT (map f t) == n.\n\nCanonical map_tuple f t := Tuple (map_tupleP f t).\n\n(*This lemma states that performing a left scan operation on a finite sequence with a given binary function and an initial value yields a new finite sequence of the same size.*)\nLemma scanl_tupleP f x t : @size rT (scanl f x t) == n.\n\nCanonical scanl_tuple f x t := Tuple (scanl_tupleP f x t).\n\n(*This lemma states that applying a binary function to each consecutive pair of elements in a finite sequence, using an initial value for the first pairing, produces a new finite sequence of the same size.*)\nLemma pairmap_tupleP f x t : @size rT (pairmap f x t) == n.\n\nCanonical pairmap_tuple f x t := Tuple (pairmap_tupleP f x t).\n\n(*This lemma states that combining two finite sequences of the same size into a single finite sequence of pairs results in a new finite sequence that also has the same size.*)\nLemma zip_tupleP t (u : n.-tuple U) : size (zip t u) == n.\n\nCanonical zip_tuple t u := Tuple (zip_tupleP t u).\n\n(*This lemma states that the size of the finite sequence generated by applying a binary function to every possible pair of elements from two input finite sequences is equal to the product of the sizes of the input sequences.*)\nLemma allpairs_tupleP f t (u : m.-tuple U) : @size rT (allpairs f t u) == n * m.\n\nCanonical allpairs_tuple f t u := Tuple (allpairs_tupleP f t u).\n\n(*This lemma states that sorting the elements of a finite sequence according to some specified order does not change the size of the sequence.*)\nLemma sort_tupleP r t : size (sort r t) == n.\n\nCanonical sort_tuple r t := Tuple (sort_tupleP r t).\n\n(*This definition specifies the head of a non-empty finite sequence as its first element.*)\nDefinition thead (u : n.+1.-tuple T) := tnth u ord0.\n\n(*This lemma states that the element at the first position of a finite sequence constructed by prepending an element to another sequence is that prepended element.*)\nLemma tnth0 x t : tnth [tuple of x :: t] ord0 = x.\n\n(*This lemma states that the element at a position greater than zero in a finite sequence constructed by prepending an element is the same as the element at the preceding position in the original sequence.*)\nLemma tnthS x t i : tnth [tuple of x :: t] (lift ord0 i) = tnth t i.\n\n(*This lemma states that the head of a finite sequence constructed by prepending an element is that same element.*)\nLemma theadE x t : thead [tuple of x :: t] = x.\n\n(*This lemma states that the property of all elements being equal to each other holds vacuously for an empty finite sequence.*)\nLemma tuple0 : all_equal_to ([tuple] : 0.-tuple T).\n\n(**)\nVariant tuple1_spec : n.+1.-tuple T -> Type :=\n Tuple1spec x t : tuple1_spec [tuple of x :: t].\n\n(*This lemma asserts that any non-empty finite sequence can be deconstructed into its first element and the remaining sub-sequence.*)\nLemma tupleP u : tuple1_spec u.\n\n(*This lemma states that accessing the element at a specific position in a finite sequence that has been transformed by a function is equivalent to first accessing the element at that position in the original sequence and then applying the function to it.*)\nLemma tnth_map f t i : tnth [tuple of map f t] i = f (tnth t i) :> rT.\n\n(*This lemma states that any element of a finite sequence constructed by repeating a single value a certain number of times is equal to that value.*)\nLemma tnth_nseq x i : tnth [tuple of nseq n x] i = x.\n\nEnd SeqTuple.\n\n(*This lemma states that accessing the element at a given position in the tail of a non-empty finite sequence is equivalent to accessing the element at the next position in the original sequence.*)\nLemma tnth_behead n T (t : n.+1.-tuple T) i :\n tnth [tuple of behead t] i = tnth t (inord i.+1).\n\n(*This lemma states that any non-empty finite sequence is equal to the sequence reconstructed by prepending its first element to its tail.*)\nLemma tuple_eta n T (t : n.+1.-tuple T) : t = [tuple of thead t :: behead t].\n\nSection tnth_shift.\nContext {T : Type} {n1 n2} (t1 : n1.-tuple T) (t2 : n2.-tuple T).\n\n(*This lemma states that accessing an element in the first part of a concatenated finite sequence, using an index adjusted for the concatenation, is equivalent to accessing that element in the original first sequence with its original index.*)\nLemma tnth_lshift i : tnth [tuple of t1 ++ t2] (lshift n2 i) = tnth t1 i.\n\n(*This lemma states that accessing an element in the second part of a concatenated finite sequence, using an index adjusted for the concatenation, is equivalent to accessing that element in the original second sequence with its original index.*)\nLemma tnth_rshift j : tnth [tuple of t1 ++ t2] (rshift n1 j) = tnth t2 j.\n\nEnd tnth_shift.\n\nSection TupleQuantifiers.\n\nVariables (n : nat) (T : Type).\nImplicit Types (a : pred T) (t : n.-tuple T).\n\n(*This lemma states that a boolean quantification over the indices of a finite sequence to check if a predicate holds for every element is equivalent to using the 'all' function, which directly checks the predicate against all elements of the sequence.*)\nLemma forallb_tnth a t : [forall i, a (tnth t i)] = all a t.\n\n(*This lemma states that a boolean quantification over the indices of a finite sequence to check if a predicate holds for at least one element is equivalent to using the 'has' function, which directly checks for the existence of such an element in the sequence.*)\nLemma existsb_tnth a t : [exists i, a (tnth t i)] = has a t.\n\n(*This lemma states that the proposition that a predicate holds for every element in a finite sequence is logically equivalent to the boolean function 'all' evaluating to true for that predicate and sequence.*)\nLemma all_tnthP a t : reflect (forall i, a (tnth t i)) (all a t).\n\n(*This lemma states that the proposition that a predicate holds for at least one element in a finite sequence is logically equivalent to the boolean function 'has' evaluating to true for that predicate and sequence.*)\nLemma has_tnthP a t : reflect (exists i, a (tnth t i)) (has a t).\n\nEnd TupleQuantifiers.\n\nArguments all_tnthP {n T a t}.\nArguments has_tnthP {n T a t}.\n\nSection EqTuple.\n\nVariables (n : nat) (T : eqType).\n\n(*This lemma states that two tuples of the same length are equal if and only if their elements at every corresponding index are equal.*)\nLemma eqEtuple (t1 t2 : n.-tuple T) :\n (t1 == t2) = [forall i, tnth t1 i == tnth t2 i].\n\n(*This lemma states that the set of elements contained in a tuple is identical to the set of elements in the underlying finite sequence that represents the tuple.*)\nLemma memtE (t : n.-tuple T) : mem t = mem (tval t).\n\n(*This lemma states that for any given valid index, the element at that index within a tuple is a member of that tuple.*)\nLemma mem_tnth i (t : n.-tuple T) : tnth t i \\in t.\n\n(*This lemma states that for any given tuple, an element retrieved from its underlying sequence at an index less than the tuple's length is guaranteed to be a member of that tuple.*)\nLemma memt_nth x0 (t : n.-tuple T) i : i < n -> nth x0 t i \\in t.\n\n(*This lemma provides a property stating that an element is a member of a tuple if and only if there exists an index at which the tuple's value is that element.*)\nLemma tnthP (t : n.-tuple T) x : reflect (exists i, x = tnth t i) (x \\in t).\n\n(*This lemma states that if an element is present in a finite sequence, then there exists a valid index such that the element can be retrieved from that index in the tuple representation of the sequence.*)\nLemma seq_tnthP (s : seq T) x : x \\in s -> {i | x = tnth (in_tuple s) i}.\n\n(*This lemma provides a property stating that a tuple consists of unique elements if and only if the function that maps each index to its corresponding element is injective.*)\nLemma tuple_uniqP (t : n.-tuple T) : reflect (injective (tnth t)) (uniq t).\n\nEnd EqTuple.\n\nHB.instance Definition _ n (T : choiceType) :=\n [Choice of n.-tuple T by <:].\nHB.instance Definition _ n (T : countType) :=\n [Countable of n.-tuple T by <:].\n\nModule Type FinTupleSig.\nSection FinTupleSig.\nVariables (n : nat) (T : finType).\nParameter enum : seq (n.-tuple T).\nAxiom enumP : Finite.axiom enum.\nAxiom size_enum : size enum = #|T| ^ n.\nEnd FinTupleSig.\nEnd FinTupleSig.\n\nModule FinTuple : FinTupleSig.\nSection FinTuple.\nVariables (n : nat) (T : finType).\n\n(*This definition constructs a finite sequence that enumerates all possible tuples of a given length, where each element of the tuple is drawn from a given finite type.*)\nDefinition enum : seq (n.-tuple T) :=\n let extend e := flatten (codom (fun x => map (cons x) e)) in\n pmap insub (iter n extend [::[::]]).\n\n(*This axiom asserts that the defined enumeration of all possible tuples of a given length over a finite type is a valid finite set enumeration, meaning it contains all such tuples without duplicates.*)\nLemma enumP : Finite.axiom enum.\n\n(*This axiom states that the total number of unique tuples of a given length over a finite type equals the cardinality of the type raised to the power of the tuple's length.*)\nLemma size_enum : size enum = #|T| ^ n.\n\nEnd FinTuple.\nEnd FinTuple.\n\nSection UseFinTuple.\n\nVariables (n : nat) (T : finType).\n\n(*This lemma states that the cardinality of the type of all tuples of a given length, whose elements are from a given finite type, is equal to the cardinality of the element type raised to the power of the tuple's length.*)\nLemma card_tuple : #|{:n.-tuple T}| = #|T| ^ n.\n\n(*This lemma asserts that the length of the canonical enumeration of the elements satisfying a given predicate over a finite type is equal to the cardinality of the set of those elements.*)\nLemma enum_tupleP (A : {pred T}) : size (enum A) == #|A|.\n\nCanonical enum_tuple A := Tuple (enum_tupleP A).\n\n(*This definition creates a canonical tuple of a given length, where the elements are the finite ordinals from zero up to the length minus one, arranged in increasing order.*)\nDefinition ord_tuple : n.-tuple 'I_n := Tuple (introT eqP (size_enum_ord n)).\n(*This lemma states that the underlying finite sequence of the canonical ordinal tuple of a given length is the enumeration of all finite ordinals less than that length, in ascending order.*)\nLemma val_ord_tuple : val ord_tuple = enum 'I_n. \n\n(*This lemma states that any tuple can be reconstructed by applying its own indexing function to the canonical ordinal tuple of the same length.*)\nLemma tuple_map_ord U (t : n.-tuple U) : t = [tuple of map (tnth t) ord_tuple].\n\n(*This lemma states that the element at any given index in the canonical ordinal tuple is the ordinal corresponding to that index.*)\nLemma tnth_ord_tuple i : tnth ord_tuple i = i.\n\nSection ImageTuple.\n\nVariables (T' : Type) (f : T -> T') (A : {pred T}).\n\nCanonical image_tuple : #|A|.-tuple T' := [tuple of image f A].\nCanonical codom_tuple : #|T|.-tuple T' := [tuple of codom f].\n\nEnd ImageTuple.\n\nSection MkTuple.\n\nVariables (T' : Type) (f : 'I_n -> T').\n\n(*This definition provides a generic way to construct a tuple by applying a given function to each index from zero up to the tuple's length minus one.*)\nDefinition mktuple := map_tuple f ord_tuple.\n\n(*This lemma states that the element at a given index of a tuple constructed from a function is equal to the value of that function applied to the index.*)\nLemma tnth_mktuple i : tnth mktuple i = f i.\n\n(*This lemma states that retrieving an element with a default value at a given valid index from the underlying sequence of a tuple constructed from a function yields the value of that function at that index.*)\nLemma nth_mktuple x0 (i : 'I_n) : nth x0 mktuple i = f i.\n\nEnd MkTuple.\n\n(*This lemma states that if two functions from indices to values are extensionally equal, then the tuples constructed from these two functions are also equal.*)\nLemma eq_mktuple T' (f1 f2 : 'I_n -> T') :\n f1 =1 f2 -> mktuple f1 = mktuple f2.\n\nEnd UseFinTuple.\n\n(*This notation provides a convenient syntax for constructing a tuple of a given length, where the expression on the left of the bar specifies the value of the elements as a function of the index, which ranges from zero to the length minus one.*)\nNotation \"[ 'tuple' F | i < n ]\" := (mktuple (fun i : 'I_n => F))\n (i at level 0,\n format \"[ '[hv' 'tuple' F '/' | i < n ] ']'\") : form_scope.\n\nArguments eq_mktuple {n T'} [f1] f2 eq_f12.\n\nSection BseqDef.\n\nVariables (n : nat) (T : Type).\n\n(*This structure defines a type for bounded finite sequences, which are sequences equipped with a proof that their length does not exceed a specified maximum.*)\nStructure bseq_of : Type := Bseq {bseqval :> seq T; _ : size bseqval <= n}.\n\n(*This lemma states that the length of any bounded finite sequence is less than or equal to its specified maximum length.*)\nLemma size_bseq bs : size bs <= n.\n\n(*This definition is a constructor function used to build or modify a bounded finite sequence by providing a mechanism to handle its underlying length-bound proof.*)\nDefinition bseq bs mkB : bseq_of :=\n mkB (let: Bseq _ bsP := bs return size bs <= n in bsP).\n\n(*This lemma states that re-wrapping an existing bounded finite sequence using its own length-bound proof results in the original bounded finite sequence.*)\nLemma bseqE bs : bseq (fun sP => @Bseq bs sP) = bs.\n\nEnd BseqDef.\n\nCanonical nil_bseq n T := Bseq (isT : @size T [::] <= n).\nCanonical cons_bseq n T x (t : bseq_of n T) :=\n Bseq (valP t : size (x :: t) <= n.+1).\n\n(*This notation provides a concise syntax for the type of bounded finite sequences, where the natural number on the left specifies the maximum allowed length.*)\nNotation \"n .-bseq\" := (bseq_of n)\n (at level 2, format \"n .-bseq\") : type_scope.\n\n(*This notation provides a descriptive parsing-only syntax for specifying the type of bounded finite sequences of a given maximum length with elements of a specific type.*)\nNotation \"{ 'bseq' n 'of' T }\" := (n.-bseq T : predArgType)\n (only parsing) : type_scope.\n\n(*This notation provides a syntax for creating a bounded finite sequence from a given standard finite sequence, where the adherence to the length bound must be provable from the context.*)\nNotation \"[ 'bseq' 'of' s ]\" := (bseq (fun sP => @Bseq _ _ s sP))\n (format \"[ 'bseq' 'of' s ]\") : form_scope.\n\n(*A notation for creating a bounded sequence by listing its elements.*)\nNotation \"[ 'bseq' x1 ; .. ; xn ]\" := [bseq of x1 :: .. [:: xn] ..]\n (format \"[ 'bseq' '[' x1 ; '/' .. ; '/' xn ']' ]\") : form_scope.\n\n(*This notation represents an empty bounded sequence.*)\nNotation \"[ 'bseq' ]\" := [bseq of [::]] (format \"[ 'bseq' ]\") : form_scope.\n\nCoercion bseq_of_tuple n T (t : n.-tuple T) : n.-bseq T :=\n Bseq (eq_leq (size_tuple t)).\n\n(*This definition creates a bounded sequence of a specified maximum length from a given sequence, truncating the input sequence if it is longer than the maximum allowed length.*)\nDefinition insub_bseq n T (s : seq T) : n.-bseq T := insubd [bseq] s.\n\n(*This lemma states that the length of a bounded sequence created by truncating an input sequence is less than or equal to the length of that original input sequence.*)\nLemma size_insub_bseq n T (s : seq T) : size (insub_bseq n s) <= size s.\n\nSection CastBseq.\n\nVariable T : Type.\n\n(*This definition converts a given sequence into a bounded sequence where the maximum length is exactly the length of the input sequence.*)\nDefinition in_bseq (s : seq T) : (size s).-bseq T := Bseq (leqnn (size s)).\n\n(*This definition changes the type-level maximum length of a bounded sequence from a first natural number to a second, given a proof that the two numbers are equal.*)\nDefinition cast_bseq m n (eq_mn : m = n) bs :=\n let: erefl in _ = n := eq_mn return n.-bseq T in bs.\n\n(*This definition changes the type-level maximum length of a bounded sequence from a first natural number to a second, given a proof that the first is less than or equal to the second.*)\nDefinition widen_bseq m n (lemn : m <= n) (bs : m.-bseq T) : n.-bseq T :=\n @Bseq n T bs (leq_trans (size_bseq bs) lemn).\n\n(*This lemma states that casting a bounded sequence to have a new maximum length that is provably equal to its original maximum length results in the original sequence unchanged.*)\nLemma cast_bseq_id n (eq_nn : n = n) bs : cast_bseq eq_nn bs = bs.\n\n(*This lemma states that casting a bounded sequence to a new, equal maximum length and then casting it back to the original maximum length restores the original sequence.*)\nLemma cast_bseqK m n (eq_mn : m = n) :\n cancel (cast_bseq eq_mn) (cast_bseq (esym eq_mn)).\n\n(*This lemma states that casting a bounded sequence to a new, equal maximum length and then casting it back to the original maximum length restores the original sequence.*)\nLemma cast_bseqKV m n (eq_mn : m = n) :\n cancel (cast_bseq (esym eq_mn)) (cast_bseq eq_mn).\n\n(*This lemma states that casting a bounded sequence's maximum length from a value 'm' to 'p' is equivalent to first casting it from 'm' to 'n' and then from 'n' to 'p', given proofs that all three lengths are equal.*)\nLemma cast_bseq_trans m n p (eq_mn : m = n) (eq_np : n = p) bs :\n cast_bseq (etrans eq_mn eq_np) bs = cast_bseq eq_np (cast_bseq eq_mn bs).\n\n(*This lemma states that casting a bounded sequence to a new maximum length does not change its actual underlying length.*)\nLemma size_cast_bseq m n (eq_mn : m = n) (bs : m.-bseq T) :\n size (cast_bseq eq_mn bs) = size bs.\n\n(*This lemma states that widening a bounded sequence's maximum length using a reflexive proof of inequality, where the new bound is the same as the old one, leaves the sequence unchanged.*)\nLemma widen_bseq_id n (lenn : n <= n) (bs : n.-bseq T) :\n widen_bseq lenn bs = bs.\n\n(*This lemma states that casting a bounded sequence's maximum length using a proof of equality is equivalent to widening its maximum length using a proof of less-than-or-equal-to derived from that same equality.*)\nLemma cast_bseqEwiden m n (eq_mn : m = n) (bs : m.-bseq T) :\n cast_bseq eq_mn bs = widen_bseq (eq_leq eq_mn) bs.\n\n(*This lemma states that widening a bounded sequence from a first maximum length to a second, and then widening it back to the first, restores the original sequence, provided that the two lengths are proven equal through mutual inequality.*)\nLemma widen_bseqK m n (lemn : m <= n) (lenm : n <= m) :\n cancel (@widen_bseq m n lemn) (widen_bseq lenm).\n\n(*This lemma states that widening a bounded sequence from a first maximum length directly to a third is equivalent to first widening it to a second maximum length and then from the second to the third, given the corresponding less-than-or-equal-to relationships between the lengths.*)\nLemma widen_bseq_trans m n p (lemn : m <= n) (lenp : n <= p) (bs : m.-bseq T) :\n widen_bseq (leq_trans lemn lenp) bs = widen_bseq lenp (widen_bseq lemn bs).\n\n(*This lemma states that widening the maximum length of a bounded sequence does not change its actual underlying length.*)\nLemma size_widen_bseq m n (lemn : m <= n) (bs : m.-bseq T) :\n size (widen_bseq lemn bs) = size bs.\n\n(*This lemma states that converting a sequence to a bounded sequence and then coercing it back to a standard sequence results in the original sequence.*)\nLemma in_bseqE s : in_bseq s = s :> seq T. \n\n(*This lemma states that taking a bounded sequence, converting its underlying sequence into a new bounded sequence whose maximum length is its actual length, and then widening this new sequence back to the original maximum length, yields the original bounded sequence.*)\nLemma widen_bseq_in_bseq n (bs : n.-bseq T) :\n widen_bseq (size_bseq bs) (in_bseq bs) = bs.\n\nEnd CastBseq.\n\nSection SeqBseq.\n\nVariables (n m : nat) (T U rT : Type).\nImplicit Type s : n.-bseq T.\n\n(*This lemma states that appending an element to a bounded sequence with a maximum length 'n' results in a new sequence whose length is less than or equal to 'n' plus one.*)\nLemma rcons_bseqP s x : size (rcons s x) <= n.+1.\n\nCanonical rcons_bseq s x := Bseq (rcons_bseqP s x).\n\n(*This lemma states that removing the first element from a bounded sequence with a maximum length 'n' results in a new sequence whose length is less than or equal to 'n' minus one.*)\nLemma behead_bseqP s : size (behead s) <= n.-1.\n\nCanonical behead_bseq s := Bseq (behead_bseqP s).\n\n(*This lemma states that removing the last element from a bounded sequence with a given maximum length results in a new sequence whose length is less than or equal to that same maximum length.*)\nLemma belast_bseqP x s : size (belast x s) <= n.\n\nCanonical belast_bseq x s := Bseq (belast_bseqP x s).\n\n(*This lemma states that concatenating a first bounded sequence with maximum length 'n' and a second bounded sequence with maximum length 'm' results in a new sequence whose length is less than or equal to the sum of 'n' and 'm'.*)\nLemma cat_bseqP s (s' : m.-bseq T) : size (s ++ s') <= n + m.\n\nCanonical cat_bseq s (s' : m.-bseq T) := Bseq (cat_bseqP s s').\n\n(*This lemma states that taking a specified number of initial elements from a bounded sequence with a given maximum length results in a new sequence whose length is less than or equal to that same maximum length.*)\nLemma take_bseqP s : size (take m s) <= n.\n\nCanonical take_bseq s := Bseq (take_bseqP s).\n\n(*This lemma states that removing a specified number of initial elements from a bounded sequence with maximum length 'n' results in a new sequence whose length is less than or equal to 'n' minus the number of removed elements.*)\nLemma drop_bseqP s : size (drop m s) <= n - m.\n\nCanonical drop_bseq s := Bseq (drop_bseqP s).\n\n(*This lemma states that reversing a bounded sequence with a given maximum length results in a new sequence whose length is less than or equal to that same maximum length.*)\nLemma rev_bseqP s : size (rev s) <= n.\n\nCanonical rev_bseq s := Bseq (rev_bseqP s).\n\n(*This lemma states that rotating a bounded sequence by a specified number of positions results in a new sequence whose length is less than or equal to the original maximum length.*)\nLemma rot_bseqP s : size (rot m s) <= n.\n\nCanonical rot_bseq s := Bseq (rot_bseqP s).\n\n(*This lemma states that rotating a bounded sequence to the right by a specified number of positions results in a new sequence whose length is less than or equal to the original maximum length.*)\nLemma rotr_bseqP s : size (rotr m s) <= n.\n\nCanonical rotr_bseq s := Bseq (rotr_bseqP s).\n\n(*This lemma states that applying a function to each element of a bounded sequence with a given maximum length results in a new sequence whose length is less than or equal to that same maximum length.*)\nLemma map_bseqP f s : @size rT (map f s) <= n.\n\nCanonical map_bseq f s := Bseq (map_bseqP f s).\n\n(*This lemma states that performing a left scan operation on a bounded sequence with a maximum length 'n' results in a new sequence whose length is less than or equal to 'n' plus one.*)\nLemma scanl_bseqP f x s : @size rT (scanl f x s) <= n.\n\nCanonical scanl_bseq f x s := Bseq (scanl_bseqP f x s).\n\n(*This lemma states that the length of the sequence resulting from applying the `pairmap` operation with an initial element to a bounded sequence of maximum length `n` is also at most `n`.*)\nLemma pairmap_bseqP f x s : @size rT (pairmap f x s) <= n.\n\nCanonical pairmap_bseq f x s := Bseq (pairmap_bseqP f x s).\n\n(*This lemma states that the size of the sequence obtained by applying a given two-argument function to every pair of elements from two bounded sequences, of maximum lengths `n` and `m` respectively, is at most the product of `n` and `m`.*)\nLemma allpairs_bseqP f s (s' : m.-bseq U) : @size rT (allpairs f s s') <= n * m.\n\nCanonical allpairs_bseq f s (s' : m.-bseq U) := Bseq (allpairs_bseqP f s s').\n\n(*This lemma states that sorting a bounded sequence of maximum length `n` results in another sequence whose length is also at most `n`.*)\nLemma sort_bseqP r s : size (sort r s) <= n.\n\nCanonical sort_bseq r s := Bseq (sort_bseqP r s).\n\n(*This lemma states that all bounded sequences with a maximum length of zero are equal to each other, as they must all be the empty sequence.*)\nLemma bseq0 : all_equal_to ([bseq] : 0.-bseq T).\n\nEnd SeqBseq.\n\n(*This instance provides a decidable equality for bounded sequences of a given maximum length, provided that the element type has decidable equality.*)\nHB.instance Definition bseq_hasDecEq n (T : eqType) :=\n [Equality of n.-bseq T by <:].\n\nCanonical bseq_predType n (T : eqType) :=\n Eval hnf in PredType (fun t : n.-bseq T => mem_seq t).\n\n(*This lemma states that the set of elements contained in a bounded sequence is identical to the set of elements in the underlying plain sequence from which it is constructed.*)\nLemma membsE n (T : eqType) (bs : n.-bseq T) : mem bs = mem (bseqval bs).\n\n(*This instance provides a choice structure for bounded sequences of a given maximum length, provided that the element type itself has a choice structure.*)\nHB.instance Definition bseq_hasChoice n (T : choiceType) :=\n [Choice of n.-bseq T by <:].\n\n(*This instance provides a countable structure for bounded sequences of a given maximum length, provided that the element type is also countable.*)\nHB.instance Definition bseq_isCountable n (T : countType) :=\n [Countable of n.-bseq T by <:].\n\n(*This definition provides a function that converts a bounded sequence of maximum length `n` into a dependent pair, consisting of the sequence's actual length `k` as an ordinal up to `n`, and the sequence itself represented as a tuple of that specific length `k`.*)\nDefinition bseq_tagged_tuple n T (s : n.-bseq T) : {k : 'I_n.+1 & k.-tuple T} :=\n Tagged _ (in_tuple s : (Ordinal (size_bseq s : size s < n.+1)).-tuple _).\nArguments bseq_tagged_tuple {n T}.\n\n(*This definition provides a function that converts a dependent pair, consisting of a length `k` and a tuple of that length, into a bounded sequence whose maximum allowed length is `n`, provided that `k` is less than or equal to `n`.*)\nDefinition tagged_tuple_bseq n T (t : {k : 'I_n.+1 & k.-tuple T}) : n.-bseq T :=\n widen_bseq (leq_ord (tag t)) (tagged t).\nArguments tagged_tuple_bseq {n T}.\n\n(*This lemma states that converting a tagged tuple to a bounded sequence and then converting it back to a tagged tuple results in the original tagged tuple.*)\nLemma bseq_tagged_tupleK {n T} :\n cancel (@bseq_tagged_tuple n T) tagged_tuple_bseq.\n\n(*This lemma states that converting a bounded sequence to a tagged tuple and then converting it back to a bounded sequence results in the original bounded sequence.*)\nLemma tagged_tuple_bseqK {n T} :\n cancel (@tagged_tuple_bseq n T) bseq_tagged_tuple.\n\n(*This lemma states that the function for converting a bounded sequence into a tagged tuple is a bijection, meaning it is both one-to-one and onto.*)\nLemma bseq_tagged_tuple_bij {n T} : bijective (@bseq_tagged_tuple n T).\n\n(*This lemma states that the function for converting a tagged tuple into a bounded sequence is a bijection, meaning it is both one-to-one and onto.*)\nLemma tagged_tuple_bseq_bij {n T} : bijective (@tagged_tuple_bseq n T).\n\n#[global] Hint Resolve bseq_tagged_tuple_bij tagged_tuple_bseq_bij : core.\n\n#[non_forgetful_inheritance]", - "boot.binomial": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path.\nFrom mathcomp Require Import div fintype tuple finfun bigop prime finset.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\n(*This lemma states that the factorial of a natural number is equal to the product of all natural numbers from one up to that number.*)\nLemma fact_prod n : n`! = \\prod_(1 <= i < n.+1) i.\n\n(*This lemma states that if a first natural number is less than or equal to a second natural number, then the factorial of the second number is equal to the factorial of the first number multiplied by the product of all integers from the successor of the first number up to the second number.*)\nLemma fact_split n m : m <= n -> n`! = m`! * \\prod_(m.+1 <= k < n.+1) k.\n\n(*This lemma states that for a prime number, the exponent of that prime in the prime factorization of a given natural number's factorial is equal to the sum of the integer quotients resulting from dividing the given number by successive powers of the prime.*)\nLemma logn_fact p n : prime p -> logn p n`! = \\sum_(1 <= k < n.+1) n %/ p ^ k.\n\n(*This theorem states that a natural number greater than one is a prime number if and only if it divides the sum of one and the factorial of its predecessor.*)\nTheorem Wilson p : p > 1 -> prime p = (p %| ((p.-1)`!).+1).\n\n(*This fixpoint defines a recursive function that computes the falling factorial of a natural number given a second natural number as the number of terms, by multiplying the first number with the recursive result on its predecessor and the predecessor of the second number.*)\nFixpoint ffact_rec n m := if m is m'.+1 then n * ffact_rec n.-1 m' else 1.\n\n(*This definition assigns the name falling_factorial to the recursive function that computes the falling factorial.*)\nDefinition falling_factorial := ffact_rec.\nArguments falling_factorial : simpl never.\n\n(*This notation introduces an expression for the falling factorial of a first natural number with a second natural number of terms.*)\nNotation \"n ^_ m\" := (falling_factorial n m)\n (at level 30, right associativity) : nat_scope.\n\n(*This lemma states that the named falling factorial function is equivalent to its underlying recursive implementation.*)\nLemma ffactE : falling_factorial = ffact_rec. \n\n(*This lemma states that the falling factorial of any natural number with zero terms is equal to one.*)\nLemma ffactn0 n : n ^_ 0 = 1. \n\n(*This lemma states that the falling factorial of zero is equal to one if the number of terms is zero, and zero otherwise.*)\nLemma ffact0n m : 0 ^_ m = (m == 0). \n\n(*This lemma provides a recursive formula for the falling factorial, stating that the falling factorial of a natural number with a successor number of terms is equal to the first number multiplied by the falling factorial of its predecessor with the original number of terms.*)\nLemma ffactnS n m : n ^_ m.+1 = n * n.-1 ^_ m. \n\n(*This lemma states that the falling factorial of a successor of a natural number with a successor number of terms is equal to the successor number multiplied by the falling factorial of the original number with the original number of terms.*)\nLemma ffactSS n m : n.+1 ^_ m.+1 = n.+1 * n ^_ m. \n\n(*This lemma states that the falling factorial of any natural number with one term is equal to the number itself.*)\nLemma ffactn1 n : n ^_ 1 = n. \n\n(*This lemma provides an alternative recursive formula for the falling factorial, stating that the falling factorial of a natural number with a successor number of terms is equal to the falling factorial of that number with the original number of terms, multiplied by the difference between the first number and the original number of terms.*)\nLemma ffactnSr n m : n ^_ m.+1 = n ^_ m * (n - m).\n\n(*This lemma states that the falling factorial of a first natural number with a second natural number of terms is equivalent to the product of terms of the form 'first number minus a counter', where the counter ranges from zero up to, but not including, the second number.*)\nLemma ffact_prod n m : n ^_ m = \\prod_(i < m) (n - i).\n\n(*This lemma states that the falling factorial of a first natural number with a second natural number of terms is positive if and only if the second number is less than or equal to the first number.*)\nLemma ffact_gt0 n m : (0 < n ^_ m) = (m <= n).\n\n(*This lemma states that if a first natural number is strictly less than a second natural number, the falling factorial of the first number with the second number of terms is equal to zero.*)\nLemma ffact_small n m : n < m -> n ^_ m = 0.\n\n(*This lemma states that the falling factorial of a natural number with the same number of terms is equal to the factorial of that number.*)\nLemma ffactnn n : n ^_ n = n`!.\n\n(*This lemma states that if a second natural number is less than or equal to a first natural number, then the product of the falling factorial of the first number with the second number of terms and the factorial of their difference is equal to the factorial of the first number.*)\nLemma ffact_fact n m : m <= n -> n ^_ m * (n - m)`! = n`!.\n\n(*This lemma states that if a second natural number is less than or equal to a first natural number, the falling factorial of the first number with the second number of terms is equal to the quotient of the factorial of the first number and the factorial of their difference.*)\nLemma ffact_factd n m : m <= n -> n ^_ m = n`! %/ (n - m)`!.\n\n(*This fixpoint provides a recursive definition for the binomial coefficient of two natural numbers, using Pascal's identity for the recursive step. The base cases define the value as one when the second argument is zero, and zero when the first argument is zero but the second is a successor.*)\nFixpoint binomial n m :=\n match n, m with\n | n'.+1, m'.+1 => binomial n' m + binomial n' m'\n | _, 0 => 1\n | 0, _.+1 => 0\n end.\nArguments binomial : simpl never.\n\n(*This notation introduces a standard representation for the binomial coefficient, denoting the number of ways to choose a subset of a given size from a larger set.*)\nNotation \"''C' ( n , m )\" := (binomial n m)\n (format \"''C' ( n , m )\") : nat_scope.\n\n(*This lemma states the definitional equality for the binomial coefficient, unfolding its recursive definition based on Pascal's identity and base cases.*)\nLemma binE n m : binomial n m =\n match n, m with\n | n'.+1, m'.+1 => binomial n' m + binomial n' m'\n | _, 0 => 1\n | 0, _.+1 => 0\n end.\n\n(*This lemma states that the binomial coefficient for choosing zero elements from a set of any size is one.*)\nLemma bin0 n : 'C(n, 0) = 1. \n\n(*This lemma states that the binomial coefficient for choosing a number of elements from an empty set is one if the number of elements to choose is zero, and zero otherwise.*)\nLemma bin0n m : 'C(0, m) = (m == 0). \n\n(*This lemma states Pascal's identity for binomial coefficients, which expresses a coefficient as the sum of two other coefficients with smaller arguments.*)\nLemma binS n m : 'C(n.+1, m.+1) = 'C(n, m.+1) + 'C(n, m). \n\n(*This lemma states that the binomial coefficient for choosing one element from a set of a given size is equal to the size of the set.*)\nLemma bin1 n : 'C(n, 1) = n.\n\n(*This lemma states that a binomial coefficient is positive if and only if the number of elements to choose is less than or equal to the total number of elements available.*)\nLemma bin_gt0 n m : (0 < 'C(n, m)) = (m <= n).\n\n(*This lemma states that the binomial coefficient is non-decreasing in its first argument; that is, if a first natural number is less than or equal to a second natural number, the value of choosing a fixed number of elements from the first is less than or equal to the value of choosing the same number of elements from the second.*)\nLemma leq_bin2l n1 n2 m : n1 <= n2 -> 'C(n1, m) <= 'C(n2, m).\n\n(*This lemma states that if the total number of elements is strictly less than the number of elements to choose, the binomial coefficient is zero.*)\nLemma bin_small n m : n < m -> 'C(n, m) = 0.\n\n(*This lemma states that for any natural number, the binomial coefficient of that number choose itself is equal to one.*)\nLemma binn n : 'C(n, n) = 1.\n\n(*This lemma states that for two natural numbers, the first number multiplied by the binomial coefficient of the predecessor of the first number choose the second number is equal to the successor of the second number multiplied by the binomial coefficient of the first number choose the successor of the second number.*)\nLemma mul_bin_diag n m : n * 'C(n.-1, m) = m.+1 * 'C(n, m.+1).\n\n(*This lemma states that for two natural numbers where the second is less than or equal to the first, the product of the binomial coefficient of the first choose the second, the factorial of the second, and the factorial of their difference is equal to the factorial of the first number.*)\nLemma bin_fact n m : m <= n -> 'C(n, m) * (m`! * (n - m)`!) = n`!.\n\n(*This lemma states that for two natural numbers where the first is positive, the binomial coefficient of the first choose the second is equal to the factorial of the first number divided by the product of the factorial of the second number and the factorial of their difference.*)\nLemma bin_factd n m : 0 < n -> 'C(n, m) = n`! %/ (m`! * (n - m)`!).\n\n(*This lemma states that for two natural numbers, the product of the binomial coefficient of the first choose the second and the factorial of the second is equal to the falling factorial of the first number of a length given by the second number.*)\nLemma bin_ffact n m : 'C(n, m) * m`! = n ^_ m.\n\n(*This lemma states that for two natural numbers, the binomial coefficient of the first choose the second is equal to the falling factorial of the first number of a length given by the second, divided by the factorial of the second number.*)\nLemma bin_ffactd n m : 'C(n, m) = n ^_ m %/ m`!.\n\n(*This lemma states that for two natural numbers where the second is less than or equal to the first, the binomial coefficient of the first number choose the difference between the numbers is equal to the binomial coefficient of the first number choose the second number.*)\nLemma bin_sub n m : m <= n -> 'C(n, n - m) = 'C(n, m).\n\n(*This lemma states that for two natural numbers, the first number multiplied by the binomial coefficient of its predecessor choose the second number is equal to the difference of the two numbers multiplied by the binomial coefficient of the first choose the second.*)\nLemma mul_bin_down n m : n * 'C(n.-1, m) = (n - m) * 'C(n, m).\n\n(*This lemma states that for two natural numbers, the product of the successor of the second number and the binomial coefficient of the first number choose the successor of the second is equal to the product of the difference between the two numbers and the binomial coefficient of the first number choose the second.*)\nLemma mul_bin_left n m : m.+1 * 'C(n, m.+1) = (n - m) * 'C(n, m).\n\n(*This lemma states that for any natural number, the binomial coefficient of its successor choose the number itself is equal to its successor.*)\nLemma binSn n : 'C(n.+1, n) = n.+1.\n\n(*This lemma provides a formula for the binomial coefficient of a natural number choose two, stating it is equal to half the product of the number and its predecessor.*)\nLemma bin2 n : 'C(n, 2) = (n * n.-1)./2.\n\n(*This lemma states that for an odd natural number, the binomial coefficient of that number choose two is equal to the number multiplied by half of its predecessor.*)\nLemma bin2odd n : odd n -> 'C(n, 2) = n * n.-1./2.\n\n(*This lemma states that for a prime number and a natural number strictly between zero and the prime, the prime number divides the binomial coefficient of the prime choose the natural number.*)\nLemma prime_dvd_bin k p : prime p -> 0 < k < p -> p %| 'C(p, k).\n\n(*This lemma states that the sum of all natural numbers strictly less than a given natural number is equal to the binomial coefficient of the given number choose two.*)\nLemma bin2_sum n : \\sum_(0 <= i < n) i = 'C(n, 2).\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use bin2_sum instead.\")]\n(*A deprecated notation for the sum of natural numbers strictly less than a given number, which is equivalent to the binomial coefficient of the given number choose two. The use of 'bin2_sum' is now preferred.*)\nNotation triangular_sum := bin2_sum (only parsing).\n\n(*This theorem, known as the Binomial Theorem, states that the power of a sum of two ring elements is equal to a sum over a range from zero to the exponent. Each term in the sum is the product of a binomial coefficient of the exponent choose the summation index, the first element raised to the power of the exponent minus the index, and the second element raised to the power of the index.*)\nTheorem expnDn a b n :\n (a + b) ^ n = \\sum_(i < n.+1) 'C(n, i) * (a ^ (n - i) * b ^ i).\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use expnDn instead.\")]\n(*A deprecated definition for the Binomial Theorem, which provides an expansion for the power of a sum of two ring elements. The use of 'expnDn' is now preferred.*)\nDefinition Pascal := expnDn.\n\n(*This lemma, known as Vandermonde's Identity, states that for three natural numbers, the binomial coefficient of their sum choose the third number is equal to a sum over a range from zero to the third number. Each term in the sum is the product of two binomial coefficients: the first is the first number choose the summation index, and the second is the second number choose the difference between the third number and the index.*)\nLemma Vandermonde k l i :\n \\sum_(j < i.+1) 'C(k, j) * 'C(l, i - j) = 'C(k + l , i).\n\n(*This lemma provides a factorization for the difference of two identical powers, stating that the difference between two ring elements each raised to a given power is equal to the product of their difference and a summation. The sum is composed of terms where the first element has a decreasing exponent and the second has an increasing exponent.*)\nLemma subn_exp m n k :\n m ^ k - n ^ k = (m - n) * (\\sum_(i < k) m ^ (k.-1 -i) * n ^ i).\n\n(*This lemma states that for two natural numbers, the predecessor of the first number raised to the power of the second is equal to the product of the predecessor of the first number and the sum of the powers of the first number, for all exponents from zero up to the second number minus one.*)\nLemma predn_exp m k : (m ^ k).-1 = m.-1 * (\\sum_(i < k) m ^ i).\n\n(*This lemma states that for two natural numbers, the predecessor of the first number divides the predecessor of the first number raised to the power of the second number.*)\nLemma dvdn_pred_predX n e : (n.-1 %| (n ^ e).-1)%N.\n\n(*This lemma states that the remainder of a finite sum of natural numbers when divided by a divisor is equal to the remainder of the sum of the remainders of each individual term, when also divided by the same divisor.*)\nLemma modn_summ I r (P : pred I) F d :\n \\sum_(i <- r | P i) F i %% d = \\sum_(i <- r | P i) F i %[mod d].\n\n(*This lemma states that for a prime number and any natural number, the successor of the natural number raised to the power of the prime is congruent, modulo the prime, to the successor of the natural number already raised to the power of the prime.*)\nLemma prime_modn_expSn p n : prime p -> n.+1 ^ p = (n ^ p).+1 %[mod p].\n\n(*This lemma, known as Fermat's Little Theorem, states that for any prime number and any natural number, the natural number raised to the power of the prime is congruent to the natural number itself, modulo the prime.*)\nLemma fermat_little a p : prime p -> a ^ p = a %[mod p].\n\nSection Combinations.\n\nImplicit Types T D : finType.\n\n(*This lemma states that the number of fixed-length tuples containing unique elements all satisfying a given predicate is equal to the falling factorial of the number of elements satisfying the predicate, with a length equal to the tuple length.*)\nLemma card_uniq_tuples T n (A : pred T) :\n #|[set t : n.-tuple T | all A t & uniq t]| = #|A| ^_ n.\n\n(*This lemma states that the number of injective finite functions from a finite domain type to a specified subset of a finite codomain type is equal to the falling factorial of the cardinality of the subset, with a length equal to the cardinality of the domain.*)\nLemma card_inj_ffuns_on D T (R : pred T) :\n #|[set f : {ffun D -> T} in ffun_on R | injectiveb f]| = #|R| ^_ #|D|.\n\n(*This lemma states that the number of injective finite functions from a finite domain type to a finite codomain type is equal to the falling factorial of the cardinality of the codomain, with a length equal to the cardinality of the domain.*)\nLemma card_inj_ffuns D T :\n #|[set f : {ffun D -> T} | injectiveb f]| = #|T| ^_ #|D|.\n\n(*This lemma states that the number of subsets of a given finite set that have a specific cardinality is equal to the binomial coefficient of the cardinality of the given set choose the specified cardinality.*)\nLemma cards_draws T (B : {set T}) k :\n #|[set A : {set T} | A \\subset B & #|A| == k]| = 'C(#|B|, k).\n\n(*This lemma states that the number of subsets of a given finite type that have a specific cardinality is equal to the binomial coefficient of the cardinality of the type choose the specified cardinality.*)\nLemma card_draws T k : #|[set A : {set T} | #|A| == k]| = 'C(#|T|, k).\n\n(*This lemma states that the number of strictly increasing tuples of a given length, whose elements are natural numbers all less than a second given natural number, is equal to the binomial coefficient of the second number choose the first number.*)\nLemma card_ltn_sorted_tuples m n :\n #|[set t : m.-tuple 'I_n | sorted ltn (map val t)]| = 'C(n, m).\n\n(*This lemma states that for any two natural numbers m and n, the number of finite sequences of length m whose elements are natural numbers from 0 up to n and which are sorted in non-decreasing order is equal to the binomial coefficient of 'm plus n' choose 'm'.*)\nLemma card_sorted_tuples m n :\n #|[set t : m.-tuple 'I_n.+1 | sorted leq (map val t)]| = 'C(m + n, m).\n\n(*This lemma states that for any two natural numbers m and n, the number of finite sequences of length m containing natural numbers from 0 up to n whose sum is at most n is equal to the binomial coefficient of 'm plus n' choose 'm'.*)\nLemma card_partial_ord_partitions m n :\n #|[set t : m.-tuple 'I_n.+1 | \\sum_(i <- t) i <= n]| = 'C(m + n, m).\n\n(*This lemma states that for any two natural numbers m and n, the number of finite sequences of length m of natural numbers that sum up to exactly n is equal to the binomial coefficient of 'n plus m minus 1' choose 'm minus 1'.*)\nLemma card_ord_partitions m n :\n #|[set t : m.+1.-tuple 'I_n.+1 | \\sum_(i <- t) i == n]| = 'C(m + n, m).", - "boot.ssreflect": "From Corelib Require Export ssreflect.\nGlobal Set SsrOldRewriteGoalsOrder.\nGlobal Set Asymmetric Patterns.\nGlobal Set Bullet Behavior \"None\".\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use `Arguments def : simpl never` instead (should work fine since Coq 8.18).\")]", - "boot.ssrnat": "From Corelib Require Import PosDef.\nFrom HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype.\n#[export] Set Warnings \"-overwriting-delimiting-key\".\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope coq_nat_scope.\n\n#[global] Remove Hints plus_n_O plus_n_Sm mult_n_O mult_n_Sm : core.\n\nDelimit Scope coq_nat_scope with coq_nat.\n\n(*This notation represents the sum of two natural numbers.*)\nNotation \"m + n\" := (plus m n) : coq_nat_scope.\n(*This notation represents the difference between two natural numbers, where the result is zero if the first number is less than or equal to the second.*)\nNotation \"m - n\" := (minus m n) : coq_nat_scope.\n(*This notation represents the product of two natural numbers.*)\nNotation \"m * n\" := (mult m n) : coq_nat_scope.\n(*This notation represents the proposition that a first natural number is less than or equal to a second natural number.*)\nNotation \"m <= n\" := (le m n) : coq_nat_scope.\n(*This notation represents the proposition that a first natural number is strictly less than a second natural number.*)\nNotation \"m < n\" := (lt m n) : coq_nat_scope.\n(*This notation represents the proposition that a first natural number is greater than or equal to a second natural number.*)\nNotation \"m >= n\" := (ge m n) : coq_nat_scope.\n(*This notation represents the proposition that a first natural number is strictly greater than a second natural number.*)\nNotation \"m > n\" := (gt m n) : coq_nat_scope.\n\nDelimit Scope N_scope with num.\n#[warning=\"-hiding-delimiting-key\"]\nDelimit Scope nat_scope with N.\n\n(*This definition provides an alias for the successor function on natural numbers, which maps a given natural number to the next one in sequence.*)\nNotation succn := Datatypes.S.\n(*This definition provides an alias for the predecessor function on natural numbers, which maps a non-zero natural number to the preceding one and maps zero to itself.*)\nNotation predn := Peano.pred.\n\n(*This notation represents the successor of a natural number, which is the number immediately following it.*)\nNotation \"n .+1\" := (succn n) (at level 2, left associativity,\n format \"n .+1\") : nat_scope.\n(*This notation represents the result of adding two to a natural number.*)\nNotation \"n .+2\" := n.+1.+1 (at level 2, left associativity,\n format \"n .+2\") : nat_scope.\n(*This notation represents the result of adding three to a natural number.*)\nNotation \"n .+3\" := n.+2.+1 (at level 2, left associativity,\n format \"n .+3\") : nat_scope.\n(*This notation represents the result of adding four to a natural number.*)\nNotation \"n .+4\" := n.+2.+2 (at level 2, left associativity,\n format \"n .+4\") : nat_scope.\n\n(*This notation represents the predecessor of a natural number, where the predecessor of zero is defined to be zero.*)\nNotation \"n .-1\" := (predn n) (at level 2, left associativity,\n format \"n .-1\") : nat_scope.\n(*This notation represents the result of subtracting two from a natural number; if the initial number is less than two, the result is zero.*)\nNotation \"n .-2\" := n.-1.-1 (at level 2, left associativity,\n format \"n .-2\") : nat_scope.\n\n(*This lemma states that applying the predecessor function to the successor of any natural number yields the original number.*)\nLemma succnK : cancel succn predn. \n(*This lemma states that the successor function is injective, which means that if two natural numbers have the same successor, they must be equal.*)\nLemma succn_inj : injective succn. \n\nReserved Notation \"n .*2\" (left associativity, format \"n .*2\").\nReserved Notation \"n ./2\" (left associativity, format \"n ./2\").\n\n(*This function defines a boolean test for equality between two natural numbers, returning true if they are identical and false otherwise.*)\nFixpoint eqn m n {struct m} :=\n match m, n with\n | 0, 0 => true\n | m'.+1, n'.+1 => eqn m' n'\n | _, _ => false\n end.\n\n(*This lemma states that the boolean equality function for natural numbers reflects propositional equality, which means the function returns true if and only if the two input numbers are equal.*)\nLemma eqnP : Equality.axiom eqn.\n\nHB.instance Definition _ := hasDecEq.Build nat eqnP.\n\nArguments eqn !m !n.\nArguments eqnP {x y}.\n\n(*This lemma states that the specific boolean equality function for natural numbers is definitionally identical to the generic equality operator provided for types with decidable equality.*)\nLemma eqnE : eqn = eq_op. \n\n(*This lemma states that the successors of two natural numbers are equal if and only if the original two natural numbers are equal.*)\nLemma eqSS m n : (m.+1 == n.+1) = (m == n). \n\n(*This lemma establishes proof irrelevance for natural number equality by stating that any two proofs that a pair of natural numbers are equal are themselves equal.*)\nLemma nat_irrelevance (x y : nat) (E E' : x = y) : E = E'.\n\n(*This definition is an alias for the addition function on natural numbers, which is prevented from automatically expanding in proofs.*)\nDefinition addn := plus.\nArguments addn : simpl never.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use addn instead.\")]\n(*This definition is a deprecated alias for the standard addition function on natural numbers and its use is discouraged.*)\nDefinition addn_rec := addn.\n(*A notation for the sum of two natural numbers.*)\nNotation \"m + n\" := (addn m n) : nat_scope.\n\n(*This lemma states that the function for natural number addition is equivalent to the function named 'plus'.*)\nLemma addnE : addn = plus. \n\n(*This lemma states that the function named 'plus' is equivalent to the function for natural number addition.*)\nLemma plusE : plus = addn. \n\n(*This lemma states that zero is the left identity for natural number addition, meaning that for any natural number, summing zero and that number results in the number itself.*)\nLemma add0n : left_id 0 addn. \n(*This lemma states that adding the successor of a natural number to another natural number is equal to the successor of their sum.*)\nLemma addSn m n : m.+1 + n = (m + n).+1. \n(*This lemma states that adding one to a natural number results in the successor of that number.*)\nLemma add1n n : 1 + n = n.+1. \n\n(*This lemma states that zero is the right identity for natural number addition, meaning that for any natural number, summing that number and zero results in the number itself.*)\nLemma addn0 : right_id 0 addn. \n\n(*This lemma states that adding a natural number to the successor of another natural number is equal to the successor of their sum.*)\nLemma addnS m n : m + n.+1 = (m + n).+1. \n\n(*This lemma states that adding the successor of a first natural number to a second natural number is equal to adding the first number to the successor of the second.*)\nLemma addSnnS m n : m.+1 + n = m + n.+1. \n\n(*This lemma states that the addition of natural numbers is left-commutative, which means that the sum of three numbers remains unchanged if the first two numbers are swapped.*)\nLemma addnCA : left_commutative addn.\n\n(*This lemma states that the addition of natural numbers is commutative, meaning that the order of the two numbers being added does not affect the result.*)\nLemma addnC : commutative addn.\n\n(*This lemma states that adding a natural number to one results in the successor of that number.*)\nLemma addn1 n : n + 1 = n.+1. \n\n(*This lemma states that the addition of natural numbers is associative, meaning that when adding three numbers, the grouping of the additions does not affect the final sum.*)\nLemma addnA : associative addn.\n\n(*This lemma states that the addition of natural numbers is right-commutative. This property asserts that summing a first and second number, and then adding a third, gives the same result as summing the first and third number, and then adding the second.*)\nLemma addnAC : right_commutative addn.\n\n(*This lemma states a commutative and associative property for the sum of three natural numbers, showing that the sum of a first, second, and third number is equal to the sum of the third, second, and first number.*)\nLemma addnCAC m n p : m + n + p = p + n + m.\n\n(*This lemma states a cyclic associativity and commutativity property for the sum of three natural numbers, showing that the sum of a first, second, and third number is equal to the sum of the second number with the sum of the third and first numbers.*)\nLemma addnACl m n p: m + n + p = n + (p + m).\n\n(*This lemma states that addition of natural numbers has the interchange property with itself, meaning that the sum of two sums can be regrouped by summing the first terms and the second terms separately.*)\nLemma addnACA : interchange addn addn.\n\n(*This lemma states that the sum of two natural numbers is equal to zero if and only if both numbers are themselves equal to zero.*)\nLemma addn_eq0 m n : (m + n == 0) = (m == 0) && (n == 0).\n\n(*This lemma states that the sum of two natural numbers is equal to one if and only if one number is one and the other is zero, or vice-versa.*)\nLemma addn_eq1 m n :\n (m + n == 1) = ((m == 1) && (n == 0)) || ((m == 0) && (n == 1)).\n\n(*This lemma states the left cancellation property for equality in natural number addition, asserting that adding the same natural number to two others results in an equality if and only if the original two numbers were equal.*)\nLemma eqn_add2l p m n : (p + m == p + n) = (m == n).\n\n(*This lemma states the right cancellation property for equality in natural number addition, asserting that two natural numbers summed with the same third number results in an equality if and only if the original two numbers were equal.*)\nLemma eqn_add2r p m n : (m + p == n + p) = (m == n).\n\n(*This lemma states that natural number addition is right-injective. This means that if two natural numbers, when used as the left-hand operand in an addition, consistently produce the same sum for any given right-hand operand, then those two numbers must be equal.*)\nLemma addnI : right_injective addn.\n\n(*This lemma states that natural number addition is left-injective. This means that if two natural numbers, when used as the right-hand operand in an addition, consistently produce the same sum for any given left-hand operand, then those two numbers must be equal.*)\nLemma addIn : left_injective addn.\n\n(*This lemma states that adding two to a natural number is equivalent to applying the successor function twice to that number.*)\nLemma addn2 m : m + 2 = m.+2. \n(*This lemma states that adding a natural number to two is equivalent to applying the successor function twice to that number.*)\nLemma add2n m : 2 + m = m.+2. \n(*This lemma states that adding three to a natural number is equivalent to applying the successor function three times to that number.*)\nLemma addn3 m : m + 3 = m.+3. \n(*This lemma states that adding a natural number to three is equivalent to applying the successor function three times to that number.*)\nLemma add3n m : 3 + m = m.+3. \n(*This lemma states that adding four to a natural number is equivalent to applying the successor function four times to that number.*)\nLemma addn4 m : m + 4 = m.+4. \n(*This lemma states that adding a natural number to four is equivalent to applying the successor function four times to that number.*)\nLemma add4n m : 4 + m = m.+4. \n\n(*This definition establishes 'subn' as an alias for the 'minus' function, which represents natural number subtraction.*)\nDefinition subn := minus.\nArguments subn : simpl never.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use subn instead.\")]\n(*This definition provides a deprecated alias for the natural number subtraction function `subn`.*)\nDefinition subn_rec := subn.\n(*This notation represents the truncated subtraction of one natural number from another, yielding zero if the second number is greater than or equal to the first.*)\nNotation \"m - n\" := (subn m n) : nat_scope.\n\n(*This lemma states that the natural number subtraction function `subn` is equivalent to the `minus` function from the standard library.*)\nLemma subnE : subn = minus. \n(*This lemma states that the `minus` function from the standard library is equivalent to the natural number subtraction function `subn`.*)\nLemma minusE : minus = subn. \n\n(*This lemma states that zero is a left-zero for natural number subtraction, meaning that subtracting any natural number from zero results in zero.*)\nLemma sub0n : left_zero 0 subn. \n(*This lemma states that zero is a right identity for natural number subtraction, meaning that subtracting zero from any natural number leaves it unchanged.*)\nLemma subn0 : right_id 0 subn. \n(*This lemma states that subtracting any natural number from itself results in zero.*)\nLemma subnn : self_inverse 0 subn. \n\n(*This lemma states that subtracting the successor of a natural number from the successor of another natural number is equivalent to subtracting the original numbers.*)\nLemma subSS n m : m.+1 - n.+1 = m - n. \n(*This lemma states that subtracting one from a natural number is equivalent to taking its predecessor.*)\nLemma subn1 n : n - 1 = n.-1. \n(*This lemma states that subtracting two from a natural number is equivalent to taking its double predecessor.*)\nLemma subn2 n : (n - 2)%N = n.-2. \n\n(*This lemma states that in a natural number subtraction, a common term added to both the minuend and the subtrahend can be cancelled.*)\nLemma subnDl p m n : (p + m) - (p + n) = m - n.\n\n(*This lemma states that in a natural number subtraction, a common term added to both operands can be cancelled.*)\nLemma subnDr p m n : (m + p) - (n + p) = m - n.\n\n(*This lemma asserts that for any given natural number, the operation of subtracting that number is the left inverse of the operation of adding it.*)\nLemma addnK n : cancel (addn^~ n) (subn^~ n).\n\n(*This lemma asserts that for any given natural number, the operation of subtracting that number is the right inverse of the operation of adding it.*)\nLemma addKn n : cancel (addn n) (subn^~ n).\n\n(*This lemma states that subtracting a natural number from its successor always results in one.*)\nLemma subSnn n : n.+1 - n = 1.\n\n(*This lemma states that subtracting a sum from a natural number is equivalent to subtracting the terms of the sum sequentially.*)\nLemma subnDA m n p : n - (m + p) = (n - m) - p.\n\n(*This lemma states that natural number subtraction is right-commutative, meaning that subtracting two numbers in sequence from a third is equivalent to subtracting them in the reverse order.*)\nLemma subnAC : right_commutative subn.\n\n(*This lemma states that subtracting the successor of a natural number from another is equivalent to taking the predecessor of the result of subtracting the original number.*)\nLemma subnS m n : m - n.+1 = (m - n).-1.\n\n(*This lemma states that taking the predecessor of the result of subtracting a natural number from a successor is equivalent to subtracting the original number from the value before the successor.*)\nLemma subSKn m n : (m.+1 - n).-1 = m - n.\n\n(*This definition introduces the 'less than or equal to' relation on natural numbers, where a first number is considered less than or equal to a second if their truncated difference is zero.*)\nDefinition leq m n := m - n == 0.\n\n(*This notation represents the 'less than or equal to' comparison between two natural numbers.*)\nNotation \"m <= n\" := (leq m n) : nat_scope.\n(*This notation represents the 'strictly less than' comparison between two natural numbers, defined as the successor of the first number being less than or equal to the second.*)\nNotation \"m < n\" := (m.+1 <= n) : nat_scope.\n(*This notation represents the 'greater than or equal to' comparison between two natural numbers, defined as the second number being less than or equal to the first.*)\nNotation \"m >= n\" := (n <= m) (only parsing) : nat_scope.\n(*This notation represents the 'strictly greater than' comparison between two natural numbers, defined as the second number being strictly less than the first.*)\nNotation \"m > n\" := (n < m) (only parsing) : nat_scope.\n\n(*This definition creates a formal relational object representing the 'greater than or equal to' comparison for natural numbers.*)\nDefinition geq := [rel m n | m >= n].\n(*This definition creates a formal relational object representing the 'strictly less than' comparison for natural numbers.*)\nDefinition ltn := [rel m n | m < n].\n(*This definition creates a formal relational object representing the 'strictly greater than' comparison for natural numbers.*)\nDefinition gtn := [rel m n | m > n].\n\n(*This notation provides syntax for a chained comparison, asserting that a first natural number is less than or equal to a second, and the second is less than or equal to a third.*)\nNotation \"m <= n <= p\" := ((m <= n) && (n <= p)) : nat_scope.\n(*This notation provides syntax for a chained comparison, asserting that a first natural number is strictly less than a second, and the second is less than or equal to a third.*)\nNotation \"m < n <= p\" := ((m < n) && (n <= p)) : nat_scope.\n(*This notation provides syntax for a chained comparison, asserting that a first natural number is less than or equal to a second, and the second is strictly less than a third.*)\nNotation \"m <= n < p\" := ((m <= n) && (n < p)) : nat_scope.\n(*A notation for expressing a chained comparison between three natural numbers, asserting that the first is strictly less than the second and the second is strictly less than the third.*)\nNotation \"m < n < p\" := ((m < n) && (n < p)) : nat_scope.\n\n(*This lemma states that a first natural number is strictly less than the successor of a second natural number if and only if the first natural number is less than or equal to the second.*)\nLemma ltnS m n : (m < n.+1) = (m <= n). \n(*This lemma states that for any given natural number, zero is less than or equal to it.*)\nLemma leq0n n : 0 <= n. \n(*This lemma states that zero is strictly less than the successor of any given natural number.*)\nLemma ltn0Sn n : 0 < n.+1. \n(*This lemma states that the proposition that a natural number is strictly less than zero is always false.*)\nLemma ltn0 n : n < 0 = false. \n(*This lemma states that the 'less than or equal to' relation on natural numbers is reflexive, meaning any natural number is less than or equal to itself.*)\nLemma leqnn n : n <= n. \n#[global] Hint Resolve leqnn : core.\n(*This lemma states that any natural number is strictly less than its successor.*)\nLemma ltnSn n : n < n.+1. \n(*This lemma states that if two natural numbers are equal, then the first is less than or equal to the second.*)\nLemma eq_leq m n : m = n -> m <= n. \n(*This lemma states that any natural number is less than or equal to its successor.*)\nLemma leqnSn n : n <= n.+1. \n#[global] Hint Resolve leqnSn : core.\n(*This lemma states that the predecessor of a natural number is always less than or equal to that number.*)\nLemma leq_pred n : n.-1 <= n. \n(*This lemma states that any natural number is less than or equal to the successor of its predecessor.*)\nLemma leqSpred n : n <= n.-1.+1. \n\n(*This lemma states that the predecessor of a natural number is strictly less than the number itself if and only if that number is strictly greater than zero.*)\nLemma ltn_predL n : (n.-1 < n) = (0 < n).\n\n(*This lemma states that a first natural number is strictly less than the predecessor of a second natural number if and only if the successor of the first number is strictly less than the second number.*)\nLemma ltn_predRL m n : (m < n.-1) = (m.+1 < n).\n\n(*This lemma states that if a first natural number is strictly less than a second, then the successor of the predecessor of the second natural number is equal to the second number itself.*)\nLemma ltn_predK m n : m < n -> n.-1.+1 = n.\n\n(*This lemma states that if a natural number is strictly greater than zero, then the successor of its predecessor is equal to the number itself.*)\nLemma prednK n : 0 < n -> n.-1.+1 = n.\n\n(*This lemma states that the proposition that a first natural number is less than or equal to a second is logically equivalent to the double negation of the proposition that the second number is strictly less than the first.*)\nLemma leqNgt m n : (m <= n) = ~~ (n < m).\n\n(*This lemma asserts the law of trichotomy for natural numbers, stating that for any two natural numbers, either the first is less than or equal to the second, or the second is strictly less than the first.*)\nLemma leqVgt m n : (m <= n) || (n < m). \n\n(*This lemma states that the proposition that a first natural number is strictly less than a second is logically equivalent to the double negation of the proposition that the second number is less than or equal to the first.*)\nLemma ltnNge m n : (m < n) = ~~ (n <= m).\n\n(*This lemma states that the 'strictly less than' relation on natural numbers is irreflexive, meaning the proposition that a natural number is strictly less than itself is always false.*)\nLemma ltnn n : n < n = false.\n\n(*This lemma states that a given natural number is less than or equal to zero if and only if that number is equal to zero.*)\nLemma leqn0 n : (n <= 0) = (n == 0). \n(*This lemma states that zero is strictly less than a given natural number if and only if that number is not equal to zero.*)\nLemma lt0n n : (0 < n) = (n != 0). \n(*This lemma states that if zero is strictly less than a given natural number, then that number is not equal to zero.*)\nLemma lt0n_neq0 n : 0 < n -> n != 0. \n(*This lemma states that the proposition that a natural number is equal to zero is logically equivalent to the double negation of the proposition that the number is strictly greater than zero.*)\nLemma eqn0Ngt n : (n == 0) = ~~ (n > 0). \n(*This lemma states that if a natural number is not equal to zero, then zero is strictly less than that number.*)\nLemma neq0_lt0n n : (n == 0) = false -> 0 < n. \n#[global] Hint Resolve lt0n_neq0 neq0_lt0n : core.\n\n(*This lemma states that two natural numbers are equal if and only if the first is less than or equal to the second and the second is also less than or equal to the first.*)\nLemma eqn_leq m n : (m == n) = (m <= n <= m).\n\n(*This lemma asserts that the 'less than or equal to' relation on natural numbers is antisymmetric.*)\nLemma anti_leq : antisymmetric leq.\n\n(*This lemma states that two natural numbers are not equal if and only if either the first is strictly less than the second or the second is strictly less than the first.*)\nLemma neq_ltn m n : (m != n) = (m < n) || (n < m).\n\n(*This lemma states that if a first natural number is strictly less than a second, then the proposition that the second is equal to the first is false.*)\nLemma gtn_eqF m n : m < n -> n == m = false.\n\n(*This lemma states that if a first natural number is strictly less than a second, then the proposition that the first is equal to the second is false.*)\nLemma ltn_eqF m n : m < n -> m == n = false.\n\n(*This lemma states that if a first natural number is strictly less than a second, then the proposition that the first is greater than or equal to the second is false.*)\nLemma ltn_geF m n : m < n -> m >= n = false.\n\n(*This lemma states that if a natural number is less than or equal to another natural number, then it cannot be strictly greater than that same number.*)\nLemma leq_gtF m n : m <= n -> m > n = false.\n\n(*This lemma states that a natural number is less than or equal to another natural number if and only if the first number is either equal to the second number or is strictly less than the second number.*)\nLemma leq_eqVlt m n : (m <= n) = (m == n) || (m < n).\n\n(*This lemma states that a natural number is strictly less than another natural number if and only if the first number is not equal to the second and is less than or equal to the second.*)\nLemma ltn_neqAle m n : (m < n) = (m != n) && (m <= n).\n\n(*This lemma states the transitivity property of the less-than-or-equal-to relation for natural numbers: if a first natural number is less than or equal to a second, and the second is less than or equal to a third, then the first is less than or equal to the third.*)\nLemma leq_trans n m p : m <= n -> n <= p -> m <= p.\n\n(*This lemma states a transitivity property for natural numbers: if a first natural number is less than or equal to a second, and the second is strictly less than a third, then the first is strictly less than the third.*)\nLemma leq_ltn_trans n m p : m <= n -> n < p -> m < p.\n\n(*This lemma states that if a natural number is strictly less than another natural number, it is also less than or equal to that number.*)\nLemma ltnW m n : m < n -> m <= n.\n\n#[global] Hint Resolve ltnW : core.\n\n(*This lemma states that if a natural number is less than or equal to another natural number, then the first number is also less than or equal to the successor of the second number.*)\nLemma leqW m n : m <= n -> m <= n.+1.\n\n(*This lemma states the transitivity property of the strictly-less-than relation for natural numbers: if a first natural number is strictly less than a second, and the second is strictly less than a third, then the first is strictly less than a third.*)\nLemma ltn_trans n m p : m < n -> n < p -> m < p.\n\n(*This lemma states that the order on natural numbers is total, meaning that for any two natural numbers, either the first is less than or equal to the second, or the first is greater than or equal to the second.*)\nLemma leq_total m n : (m <= n) || (m >= n).\n\n(*This lemma states that for any given natural number, there exists another natural number that is strictly greater than it, demonstrating that the set of natural numbers is unbounded above.*)\nLemma ubnP m : {n | m < n}. \n(*This lemma states that if a natural number is strictly less than the successor of another natural number, then the first number must be less than or equal to the second number.*)\nLemma ltnSE m n : m < n.+1 -> m <= n. \n(*This variant defines a type that holds a proof, for a given natural number, that it is less than or equal to another natural number.*)\nVariant ubn_leq_spec m : nat -> Type := UbnLeq n of m <= n : ubn_leq_spec m n.\n(*This variant defines a type that holds a proof, for a given natural number, that it is greater than or equal to another natural number.*)\nVariant ubn_geq_spec m : nat -> Type := UbnGeq n of m >= n : ubn_geq_spec m n.\n(*This variant defines a type that holds a proof, for a given natural number, that it is equal to another natural number.*)\nVariant ubn_eq_spec m : nat -> Type := UbnEq n of m == n : ubn_eq_spec m n.\n(*This lemma provides a proof that any natural number is less than or equal to itself, packaged within the ubn_leq_spec type.*)\nLemma ubnPleq m : ubn_leq_spec m m. \n(*This lemma provides a proof that any natural number is greater than or equal to itself, packaged within the ubn_geq_spec type.*)\nLemma ubnPgeq m : ubn_geq_spec m m. \n(*This lemma provides a proof that any natural number is equal to itself, packaged within the ubn_eq_spec type.*)\nLemma ubnPeq m : ubn_eq_spec m m. \n(*This lemma provides the principle of strong induction on natural numbers: to prove that a property holds for all natural numbers, it is sufficient to show that for any given natural number, the property holds for it under the assumption that it holds for all smaller natural numbers.*)\nLemma ltn_ind P : (forall n, (forall m, m < n -> P m) -> P n) -> forall n, P n.\n\n(*This lemma establishes a reflection between the boolean evaluation of whether a natural number is less than or equal to another and the corresponding logical proposition, allowing one to be used in place of the other in proofs.*)\nLemma leP m n : reflect (m <= n)%coq_nat (m <= n).\n\nArguments leP {m n}.\n\n(*This lemma states that any two proofs of the proposition that one natural number is less than or equal to another are equal, demonstrating the principle of proof irrelevance for this relation.*)\nLemma le_irrelevance m n le_mn1 le_mn2 : le_mn1 = le_mn2 :> (m <= n)%coq_nat.\n\n(*This lemma establishes a reflection between the boolean evaluation of whether a natural number is strictly less than another and the corresponding logical proposition.*)\nLemma ltP m n : reflect (m < n)%coq_nat (m < n).\n\nArguments ltP {m n}.\n\n(*This lemma states that any two proofs of the proposition that one natural number is strictly less than another are equal, asserting proof irrelevance for this relation.*)\nLemma lt_irrelevance m n lt_mn1 lt_mn2 : lt_mn1 = lt_mn2 :> (m < n)%coq_nat.\n\n(*This lemma states that for natural numbers, adding the same number to both sides of a less-than-or-equal-to inequality does not change its truth value, so the term can be cancelled from the left.*)\nLemma leq_add2l p m n : (p + m <= p + n) = (m <= n).\n\n(*This lemma states that for natural numbers, adding the same number to both sides of a strictly-less-than inequality does not change its truth value, allowing cancellation from the left.*)\nLemma ltn_add2l p m n : (p + m < p + n) = (m < n).\n\n(*This lemma states that for natural numbers, adding the same number to both sides of a less-than-or-equal-to inequality does not change its truth value, so the term can be cancelled from the right.*)\nLemma leq_add2r p m n : (m + p <= n + p) = (m <= n).\n\n(*This lemma states that for natural numbers, adding the same number to both sides of a strictly-less-than inequality does not change its truth value, allowing cancellation from the right.*)\nLemma ltn_add2r p m n : (m + p < n + p) = (m < n).\n\n(*This lemma states that if a first pair of natural numbers and a second pair of natural numbers are each related by the less-than-or-equal-to comparison, then the sum of the smaller numbers is less than or equal to the sum of the larger numbers.*)\nLemma leq_add m1 m2 n1 n2 : m1 <= n1 -> m2 <= n2 -> m1 + m2 <= n1 + n2.\n\n(*This lemma states that for any two natural numbers, the second number is less than or equal to the sum of the first and the second.*)\nLemma leq_addl m n : n <= m + n. \n\n(*This lemma states that for any two natural numbers, the second number is less than or equal to the sum of the second and the first.*)\nLemma leq_addr m n : n <= n + m. \n\n(*This lemma states that if a first natural number is strictly less than a second, then the first number is also strictly less than the sum of the second number and any third natural number.*)\nLemma ltn_addl m n p : m < n -> m < p + n.\n\n(*This lemma states that if a first natural number is less than a second natural number, then the first number is also less than the sum of the second number and a third natural number.*)\nLemma ltn_addr m n p : m < n -> m < n + p.\n\n(*This lemma states that the sum of two natural numbers is greater than zero if and only if at least one of the two numbers is itself greater than zero.*)\nLemma addn_gt0 m n : (0 < m + n) = (0 < m) || (0 < n).\n\n(*This lemma states that the difference of a second natural number minus a first natural number is greater than zero if and only if the first number is strictly less than the second.*)\nLemma subn_gt0 m n : (0 < n - m) = (m < n).\n\n(*This lemma states that the difference of a first natural number minus a second natural number is zero if and only if the first number is less than or equal to the second.*)\nLemma subn_eq0 m n : (m - n == 0) = (m <= n).\n\n(*This lemma states that the difference of a first natural number minus a second is less than or equal to a third natural number if and only if the first number is less than or equal to the sum of the second and third numbers.*)\nLemma leq_subLR m n p : (m - n <= p) = (m <= n + p).\n\n(*This lemma states that the result of subtracting a first natural number from a second natural number is always less than or equal to the second number.*)\nLemma leq_subr m n : n - m <= n.\n\n(*This lemma states that a natural number is never strictly less than the result of subtracting another natural number from it.*)\nLemma ltn_subrR m n : (n < n - m) = false.\n\n(*This lemma states that a natural number is less than or equal to the result of subtracting a second natural number from it if and only if either the second number is zero or the first number is zero.*)\nLemma leq_subrR m n : (n <= n - m) = (m == 0) || (n == 0).\n\n(*This lemma states that the difference of a second natural number minus a first is strictly less than the second number if and only if both numbers are greater than zero.*)\nLemma ltn_subrL m n : (n - m < n) = (0 < m) && (0 < n).\n\n(*This lemma states that if a first natural number is less than or equal to a second, then the sum of the first number and the difference of the second minus the first is equal to the second number.*)\nLemma subnKC m n : m <= n -> m + (n - m) = n.\n\n(*This lemma states an identity for natural numbers, asserting that the sum of a first number and the difference of a second minus the first is equal to the sum of the difference of the first minus the second and the second number; this value is the maximum of the two numbers.*)\nLemma addnBn m n : m + (n - m) = m - n + n.\n\n(*This lemma states that if a first natural number is less than or equal to a second, then the sum of the difference of the second minus the first and choreographed first number is equal to the second number.*)\nLemma subnK m n : m <= n -> (n - m) + m = n.\n\n(*This lemma provides an associativity rule for addition and subtraction of natural numbers, stating that if a third natural number is less than or equal to a second, then adding a first number to the difference of the second and third is equal to subtracting the third from the sum of choreographed first and second.*)\nLemma addnBA m n p : p <= n -> m + (n - p) = m + n - p.\n\n(*This lemma states a rule for reordering subtraction and addition of natural numbers: if a second natural number is less than or equal to a first, then adding a third number to the difference of the first and second is equal to subtracting the second from the sum of the choreographed first and third.*)\nLemma addnBAC m n p : n <= m -> m - n + p = m + p - n.\n\n(*This lemma states a symmetry property for natural numbers: if a third natural number is less than or equal to both a first and a second number, then adding choreographed first number to the difference of the second minus the third is equal to adding the second number to the difference of the first minus the third.*)\nLemma addnBCA m n p : p <= m -> p <= n -> m + (n - p) = n + (m - p).\n\n(*This lemma states a reordering property for natural numbers: if a third natural number is less than or equal to both a first and a second number, then adding choreographed first number to the difference of the second minus choreographed third is equal to adding choreographed second number to the result of subtracting the third from the first.*)\nLemma addnABC m n p : p <= m -> p <= n -> m + (n - p) = m - p + n.\n\n(*This lemma states a rule for distributing subtraction over subtraction for natural numbers. If a third number is less than or equal to a second, then subtracting the difference of the second minus the third from a first number is equivalent to subtracting the second number from the sum of choreographed first and third numbers.*)\nLemma subnBA m n p : p <= n -> m - (n - p) = m + p - n.\n\n(*This lemma provides an associativity-like property for subtraction of natural numbers. If a third number is less than or equal to a second, and the second is less than or equal to a first, then subtracting choreographed difference of the second minus choreographed third from choreographed first is equal to adding the third to the difference of the first minus choreographed second.*)\nLemma subnA m n p : p <= n -> n <= m -> m - (n - p) = m - n + p.\n\n(*This lemma states a cancellation property for natural number subtraction. If a first number is less than or equal to a second, then subtracting from choreographed second number the difference of choreographed second minus the first yields choreographed first number.*)\nLemma subKn m n : m <= n -> n - (n - m) = m.\n\n(*This lemma relates subtraction and choreographed successor operation for natural numbers. It states that if a first number is less than or equal to a second, then subtracting choreographed first number from the successor of choreographed second is equal to choreographed successor of the difference of the second minus the first.*)\nLemma subSn m n : m <= n -> n.+1 - m = (n - m).+1.\n\n(*This lemma describes an interaction between subtraction and choreographed successor operation for natural numbers. It states that if a first number is strictly less than a second, then the successor of the result of subtracting choreographed successor of choreographed first from the second is equal to the difference of choreographed second minus choreographed first.*)\nLemma subnSK m n : m < n -> (n - m.+1).+1 = n - m. \n\n(*This lemma states a reordering property for addition and subtraction of natural numbers. If a third number is less than or equal to a second, then adding a first number to choreographed difference of choreographed second minus choreographed third is equal to subtracting choreographed third from the sum of choreographed second and first numbers.*)\nLemma addnCBA m n p : p <= n -> m + (n - p) = n + m - p.\n\n(*This lemma states that for three natural numbers, if a second number is less than or equal to a third, then adding a first number to the difference of the second minus choreographed third results in choreographed first number, because the difference is zero.*)\nLemma addnBr_leq n p m : n <= p -> m + (n - p) = m.\n\n(*This lemma states that for three natural numbers, if a first number is less than or equal to a second, then adding a third number to the difference of choreographed first minus choreographed second results in choreographed third number, because the difference is zero.*)\nLemma addnBl_leq m n p : m <= n -> m - n + p = p.\n\n(*This lemma states a rule for reordering subtractions of natural numbers, showing that subtracting a sum of a second and a third number from a first number is equivalent to first subtracting choreographed third number from choreographed first, and then subtracting choreographed second number from the result.*)\nLemma subnDAC m n p : m - (n + p) = m - p - n.\n\n(*This lemma states a reordering property for expressions with natural numbers. If a third number is less than or equal to a second, then subtracting choreographed difference of choregraphed second minus the third from a first number is equivalent to subtracting choreographed second from choreographed sum of choreographed third and choreographed first.*)\nLemma subnCBA m n p : p <= n ->\tm - (n - p) = p + m - n.\n\n(*This lemma states that for three natural numbers, if a second number is less than or equal to a third, then subtracting choreographed difference of choreographed second minus choreographed third from a first number results in choreographed first number, as choreographed difference is zero.*)\nLemma subnBr_leq n p m : n <= p -> m - (n - p) = m.\n\n(*This lemma states that for three natural numbers, if a first number is less than or equal to a second, then subtracting a third number from choreographed difference of choreographed first minus choreographed second results in zero, as choreographed initial difference is zero.*)\nLemma subnBl_leq m n p : m <= n -> (m - n) - p = 0.\n\n(*This lemma provides an identity for subtraction of natural numbers. If a third number is less than or equal to a second, and choreographed second is less than or equal to a first, then subtracting choreographed difference of choreographed second minus choreographed third from choreographed first is equivalent to adding choreographed third to choreographed difference of choreographed first minus choreographed second.*)\nLemma subnBAC m n p : p <= n -> n <= m -> m - (n - p) = p + (m - n).\n\n(*This lemma states a commutativity-like property for expressions involving addition and subtraction. If a third natural number is less than or equal to a second, then subtracting choreographed third from choreographed sum of a first and choreographed second is equivalent to adding choreographed first to choreographed difference of choreographed second minus choreographed third.*)\nLemma subDnAC m n p : p <= n -> m + n - p = n - p + m.\n\n(*This lemma states that for three natural numbers, if the third is less than or equal to the first, then subtracting the third from the sum of the first and second is equivalent to adding the second number to the result of subtracting the third from the first.*)\nLemma subDnCA m n p : p <= m -> m + n - p = n + (m - p).\n\n(*This lemma states that for three natural numbers, if the first is less than or equal to the third, then subtracting the third from the sum of the first and second is equivalent to subtracting the difference of the third and first from the second number.*)\nLemma subDnCAC m n p : m <= p -> m + n - p = n - (p - m).\n\n(*This lemma states that for two natural numbers, the result of adding the second number to the difference of the first and second is equal to the result of adding the first number to the difference of the second and first.*)\nLemma addnBC m n : m - n + n = n - m + m.\n\n(*This lemma states that for two natural numbers, adding the second number to the difference of the first and second is equivalent to adding the difference of the second and first to the first number.*)\nLemma addnCB m n : m - n + n = m + (n - m).\n\n(*This lemma states that for three natural numbers, if the second number is less than or equal to the first, then adding the third number to the difference of the first and second is equivalent to adding that same difference to the third number.*)\nLemma addBnAC m n p : n <= m -> m - n + p = p + m - n.\n\n(*This lemma states that for three natural numbers, if the second number is less than or equal to both the first and third numbers, then adding the third number to the difference of the first and second is equivalent to adding the first number to the difference of the third and second.*)\nLemma addBnCAC m n p : n <= m -> n <= p -> m - n + p = p - n + m.\n\n(*This lemma states that for three natural numbers, if the second is less than or equal to the first, and the third is less than or equal to the second, then adding the third to the difference of the first and second is equivalent to subtracting from the first number the difference of the second and third.*)\nLemma addBnA m n p : n <= m -> p <= n -> m - n + p = m - (n - p).\n\n(*This lemma states that for three natural numbers, sequentially subtracting the second and then the third from the first is equivalent to subtracting the sum of the second and third from the first number.*)\nLemma subBnAC m n p : m - n - p = m - (p + n).\n\n(*This lemma states that for two natural numbers, the predecessor of their difference is equal to the difference between the predecessor of the first number and the second number.*)\nLemma predn_sub m n : (m - n).-1 = (m.-1 - n).\n\n(*This lemma states that for three natural numbers, if the first is less than or equal to the second, then subtracting the third number from the first results in a value less than or equal to the result of subtracting the third number from the second.*)\nLemma leq_sub2r p m n : m <= n -> m - p <= n - p.\n\n(*This lemma states that for three natural numbers, if a second number is less than or equal to a third number, then subtracting the third number from a first number results in a value less than or equal to the result of subtracting the second number from that first number.*)\nLemma leq_sub2l p m n : m <= n -> p - n <= p - m.\n\n(*This lemma states that for four natural numbers, if a first number is less than or equal to a second, and a fourth number is less than or equal to a third, then the result of subtracting the third from the first is less than or equal to the result of subtracting the fourth from the second.*)\nLemma leq_sub m1 m2 n1 n2 : m1 <= m2 -> n2 <= n1 -> m1 - n1 <= m2 - n2.\n\n(*This lemma states that for three natural numbers, if a first number is strictly less than a second, and a third number is also strictly less than that second number, then subtracting the third from the first yields a result strictly less than subtracting the third from the second.*)\nLemma ltn_sub2r p m n : p < n -> m < n -> m - p < n - p.\n\n(*This lemma states that for three natural numbers, if the first is strictly less than the third and also strictly less than the second, then the difference of the third and second is strictly less than the difference of the third and first.*)\nLemma ltn_sub2l p m n : m < p -> m < n -> p - n < p - m.\n\n(*This lemma states an equivalence for three natural numbers: that a second number is strictly less than the difference of a third and a first is equivalent to the sum of the first and second numbers being strictly less than the third.*)\nLemma ltn_subRL m n p : (n < p - m) = (m + n < p).\n\n(*This lemma states an equivalence for three natural numbers, where the second number is positive: that the second number is less than or equal to the difference of the third and first is equivalent to the sum of the first and second numbers being less than or equal to the third.*)\nLemma leq_psubRL m n p : 0 < n -> (n <= p - m) = (m + n <= p).\n\n(*This lemma states an equivalence for three natural numbers, where the third number is positive: that the difference of the first and second is strictly less than the third is equivalent to the first number being strictly less than the sum of the second and third.*)\nLemma ltn_psubLR m n p : 0 < p -> (m - n < p) = (m < n + p).\n\n(*This lemma states an equivalence for three natural numbers, provided the first is less than or equal to the third: that the second number is less than or equal to the difference of the third and first is equivalent to the sum of the first and second numbers being less than or equal to the third.*)\nLemma leq_subRL m n p : m <= p -> (n <= p - m) = (m + n <= p).\n\n(*This lemma states an equivalence for three natural numbers, provided the second is less than or equal to the first: that the difference of the first and second is strictly less than the third is equivalent to the first number being strictly less than the sum of the second and third.*)\nLemma ltn_subLR m n p : n <= m -> (m - n < p) = (m < n + p).\n\n(*This lemma states an equivalence for three natural numbers: that the difference of the first and second is less than or equal to the third is equivalent to the difference of the first and third being less than or equal to the second.*)\nLemma leq_subCl m n p : (m - n <= p) = (m - p <= n).\n\n(*This lemma states an equivalence for three natural numbers: that the third is strictly less than the difference of the first and second is equivalent to the second being strictly less than the difference of the first and third.*)\nLemma ltn_subCr m n p : (p < m - n) = (n < m - p).\n\n(*This lemma states an equivalence for three natural numbers, provided the second and third are positive: that the third is less than or equal to the difference of the first and second is equivalent to the second being less than or equal to the difference of the first and third.*)\nLemma leq_psubCr m n p : 0 < p -> 0 < n -> (p <= m - n) = (n <= m - p).\n\n(*This lemma states an equivalence for three natural numbers, provided the second and third are positive: that the difference of the first and second is strictly less than the third is equivalent to the difference of the first and third being strictly less than the second.*)\nLemma ltn_psubCl m n p : 0 < p -> 0 < n -> (m - n < p) = (m - p < n).\n\n(*This lemma states an equivalence for three natural numbers, provided both the second and third are less than or equal to the first: that the third is less than or equal to the difference of the first and second is equivalent to the second being less than or equal to the difference of the first and third.*)\nLemma leq_subCr m n p : n <= m -> p <= m -> (p <= m - n) = (n <= m - p).\n\n(*This lemma states an equivalence for three natural numbers, provided both the second and third are less than or equal to the first: that the difference of the first and second is strictly less than the third is equivalent to the difference of the first and third being strictly less than the second.*)\nLemma ltn_subCl m n p : n <= m -> p <= m -> (m - n < p) = (m - p < n).\n\n(*This lemma states an equivalence for three natural numbers, provided a first is less than or equal to a third: the inequality stating that the difference of a second and the first is less than or equal to the difference of the third and the first is equivalent to the second number being less than or equal to the third.*)\nLemma leq_sub2rE p m n : p <= n -> (m - p <= n - p) = (m <= n).\n\n(*This lemma states an equivalence for three natural numbers, provided the second is less than or equal to the first: that subtracting the third from the first yields a result less than or equal to subtracting the second from the first is equivalent to the second number being less than or equal to the third.*)\nLemma leq_sub2lE m n p : n <= m -> (m - p <= m - n) = (n <= p).\n\n(*This lemma states an equivalence for three natural numbers, provided a first is less than or equal to a second: that the difference of the second and first is strictly less than the difference of a third and the first is equivalent to the second number being strictly less than the third.*)\nLemma ltn_sub2rE p m n : p <= m -> (m - p < n - p) = (m < n).\n\n(*This lemma states an equivalence for three natural numbers, provided the third is less than or equal to the first: that subtracting the third from the first yields a result strictly less than subtracting the second from the first is equivalent to the second number being strictly less than the third.*)\nLemma ltn_sub2lE m n p : p <= m -> (m - p < m - n) = (n < p).\n\n(*This lemma states an equivalence for three natural numbers, provided the third is less than or equal to both the first and the second: that the difference of the first and third is equal to the difference of the second and third is equivalent to the first number being equal to the second.*)\nLemma eqn_sub2rE p m n : p <= m -> p <= n -> (m - p == n - p) = (m == n).\n\n(*This lemma states that for three natural numbers, if subtracting the second and third from the first is a valid operation, then the results of these subtractions are equal if and only if the second and third numbers are equal to each other.*)\nLemma eqn_sub2lE m n p : p <= m -> n <= m -> (m - p == m - n) = (p == n).\n\n(*This definition specifies a function that returns the greater of two given natural numbers.*)\nDefinition maxn m n := if m < n then n else m.\n\n(*This definition specifies a function that returns the smaller of two given natural numbers.*)\nDefinition minn m n := if m < n then m else n.\n\n(*This lemma states that for any natural number, the maximum of zero and that number is the number itself.*)\nLemma max0n : left_id 0 maxn. \n(*This lemma states that for any natural number, the maximum of that number and zero is the number itself.*)\nLemma maxn0 : right_id 0 maxn. \n\n(*This lemma states that the maximum operation on natural numbers is commutative, meaning the order of the two inputs does not affect the result.*)\nLemma maxnC : commutative maxn.\n\n(*This lemma provides an alternative formula for the maximum of two natural numbers: it is equal to the first number plus the difference between the second and the first, where the difference is zero if the second is smaller than the first.*)\nLemma maxnE m n : maxn m n = m + (n - m).\n\n(*This lemma states that the maximum operation on natural numbers is right-commutative. This means that taking the maximum of a number with the maximum of two other numbers is equivalent to taking the maximum of the second number with the maximum of the first and third numbers.*)\nLemma maxnAC : right_commutative maxn.\n\n(*This lemma states that the maximum operation on natural numbers is associative, which means that when finding the maximum of three numbers, the grouping of the operations does not change the outcome.*)\nLemma maxnA : associative maxn.\n\n(*This lemma states that the maximum operation on natural numbers is left-commutative. This means that taking the maximum of the maximum of two numbers with a third number is equivalent to taking the maximum of the maximum of the third and second numbers with the first number.*)\nLemma maxnCA : left_commutative maxn.\n\n(*This lemma states that the maximum operation on natural numbers self-interchanges. This means that the maximum of the maximums of two pairs of numbers is equal to the maximum of the maximums of reshuffled pairs.*)\nLemma maxnACA : interchange maxn maxn.\n\n(*This lemma states that the maximum of two natural numbers is equal to the first number if and only if the first number is greater than or equal to the second number.*)\nLemma maxn_idPl {m n} : reflect (maxn m n = m) (m >= n).\n\n(*This lemma states that the maximum of two natural numbers is equal to the second number if and only if the first number is less than or equal to the second number.*)\nLemma maxn_idPr {m n} : reflect (maxn m n = n) (m <= n).\n\n(*This lemma states that the maximum operation on natural numbers is idempotent, which means that the maximum of a number with itself is the number itself.*)\nLemma maxnn : idempotent_op maxn.\n\n(*This lemma states that a natural number is less than or equal to the maximum of two other natural numbers if and only if it is less than or equal to at least one of those two numbers.*)\nLemma leq_max m n1 n2 : (m <= maxn n1 n2) = (m <= n1) || (m <= n2).\n\n(*This lemma states that any given natural number is always less than or equal to its maximum with any other natural number.*)\nLemma leq_maxl m n : m <= maxn m n. \n(*This lemma states that any given natural number is always less than or equal to the maximum of another natural number and itself.*)\nLemma leq_maxr m n : n <= maxn m n. \n\n(*This lemma states that a natural number is strictly greater than the maximum of two other natural numbers if and only if it is strictly greater than both of those numbers.*)\nLemma gtn_max m n1 n2 : (m > maxn n1 n2) = (m > n1) && (m > n2).\n\n(*This lemma states that a natural number is greater than or equal to the maximum of two other natural numbers if and only if it is greater than or equal to both of those numbers.*)\nLemma geq_max m n1 n2 : (m >= maxn n1 n2) = (m >= n1) && (m >= n2).\n\n(*This lemma states that the maximum of the successors of two natural numbers is equal to the successor of their maximum.*)\nLemma maxnSS m n : maxn m.+1 n.+1 = (maxn m n).+1.\n\n(*This lemma states that addition of natural numbers is left-distributive over the maximum operation. This means that adding a number to the maximum of two other numbers gives the same result as taking the maximum of the sums of the first number with each of the other two.*)\nLemma addn_maxl : left_distributive addn maxn.\n\n(*This lemma states that addition of natural numbers is right-distributive over the maximum operation. This means that the maximum of two sums with a common term is equal to the sum of the maximum of the other two terms and the common term.*)\nLemma addn_maxr : right_distributive addn maxn.\n\n(*This lemma states a distributive-like property for subtraction over the maximum operation on natural numbers. Specifically, subtracting the maximum of two numbers from a third number yields the same result as taking the minimum of the differences obtained by subtracting each of the two numbers from the third.*)\nLemma subn_maxl : left_distributive subn maxn.\n\n(*This lemma states that zero is a left absorbing element for the minimum operation on natural numbers, meaning the minimum of zero and any natural number is always zero.*)\nLemma min0n : left_zero 0 minn. \n(*This lemma states that zero is a right absorbing element for the minimum operation on natural numbers, meaning the minimum of any natural number and zero is always zero.*)\nLemma minn0 : right_zero 0 minn. \n\n(*This lemma states that the minimum operation on natural numbers is commutative, meaning the order of the two inputs does not affect the result.*)\nLemma minnC : commutative minn.\n\n(*This lemma states that for any two natural numbers, the sum of their minimum and their maximum is equal to their sum.*)\nLemma addn_min_max m n : minn m n + maxn m n = m + n.\n\n(*This lemma provides an alternative formula for the minimum of two natural numbers: it is equal to the first number minus the result of subtracting the second number from the first, where the subtraction is truncated at zero.*)\nLemma minnE m n : minn m n = m - (m - n).\n\n(*This lemma states that the minimum operation on natural numbers is right-commutative. This means that taking the minimum of a number with the minimum of two other numbers is equivalent to taking the minimum of the second number with the minimum of the first and third numbers.*)\nLemma minnAC : right_commutative minn.\n\n(*This lemma states that the minimum operation on natural numbers is associative, which means that when finding the minimum of three numbers, the grouping of the operations does not change the outcome.*)\nLemma minnA : associative minn.\n\n(*This lemma states that the minimum operation on natural numbers is left-commutative, meaning that the minimum of a first natural number and the minimum of a second and a third is equal to the minimum of the second number and the minimum of the first and third.*)\nLemma minnCA : left_commutative minn.\n\n(*This lemma states that the minimum operation on natural numbers has the interchange property, meaning that the minimum of the minimum of a first pair of natural numbers and the minimum of a second pair of natural numbers is equal to the minimum of the minimums of the cross-paired numbers.*)\nLemma minnACA : interchange minn minn.\n\n(*This lemma states that the minimum of two natural numbers is equal to the first number if and only if the first number is less than or equal to the second.*)\nLemma minn_idPl {m n} : reflect (minn m n = m) (m <= n).\n\n(*This lemma states that the minimum of two natural numbers is equal to the second number if and only if the first number is greater than or equal to the second.*)\nLemma minn_idPr {m n} : reflect (minn m n = n) (m >= n).\n\n(*This lemma states that the minimum operation on natural numbers is idempotent, meaning that the minimum of a natural number with itself is the number itself.*)\nLemma minnn : idempotent_op minn.\n\n(*This lemma states that a natural number is less than or equal to the minimum of two other natural numbers if and only if it is less than or equal to both of these numbers.*)\nLemma leq_min m n1 n2 : (m <= minn n1 n2) = (m <= n1) && (m <= n2).\n\n(*This lemma states that a natural number is strictly greater than the minimum of two other natural numbers if and only if it is either strictly greater than the first number or strictly greater than the second number.*)\nLemma gtn_min m n1 n2 : (m > minn n1 n2) = (m > n1) || (m > n2).\n\n(*This lemma states that a natural number is greater than or equal to the minimum of two other natural numbers if and only if it is greater than or equal to the first number or greater than or equal to the second number.*)\nLemma geq_min m n1 n2 : (m >= minn n1 n2) = (m >= n1) || (m >= n2).\n\n(*This lemma states that a natural number is strictly less than the minimum of two other natural numbers if and only if it is strictly less than both of these numbers.*)\nLemma ltn_min m n1 n2 : (m < minn n1 n2) = (m < n1) && (m < n2).\n\n(*This lemma states that the minimum of two natural numbers is always less than or equal to the first number.*)\nLemma geq_minl m n : minn m n <= m. \n(*This lemma states that the minimum of two natural numbers is always less than or equal to the second number.*)\nLemma geq_minr m n : minn m n <= n. \n\n(*This lemma states that addition of natural numbers distributes over the minimum operation from the right, meaning that the sum of the minimum of two numbers and a third number is equal to the minimum of the sum of the first and third numbers and the sum of the second and third numbers.*)\nLemma addn_minr : right_distributive addn minn.\n\n(*This lemma states that addition of natural numbers is left-distributive over the minimum operation, meaning that the sum of a natural number and the minimum of two others is equal to the minimum of the sums of the first number with each of the other two.*)\nLemma addn_minl : left_distributive addn minn.\n\n(*This lemma states that natural number subtraction is left-distributive over the minimum operation. Specifically, subtracting the minimum of a second and third natural number from a first natural number yields the same result as taking the minimum of two differences: the first minus the second, and the first minus the third.*)\nLemma subn_minl : left_distributive subn minn.\n\n(*This lemma states that the minimum of the successors of two natural numbers is equal to the successor of their minimum.*)\nLemma minnSS m n : minn m.+1 n.+1 = (minn m n).+1.\n\n(*This lemma states an absorption property between minimum and maximum, asserting that the minimum of the maximum of two natural numbers and the first number is equal to the first number itself.*)\nLemma maxnK m n : minn (maxn m n) m = m.\n\n(*This lemma states an absorption property between minimum and maximum, asserting that the minimum of the second of two natural numbers and their maximum is equal to the second number itself.*)\nLemma maxKn m n : minn n (maxn m n) = n.\n\n(*This lemma states an absorption property between maximum and minimum, asserting that the maximum of the minimum of two natural numbers and the first number is equal to the first number itself.*)\nLemma minnK m n : maxn (minn m n) m = m.\n\n(*This lemma states an absorption property between maximum and minimum, asserting that the maximum of the second of two natural numbers and their minimum is equal to the second number itself.*)\nLemma minKn m n : maxn n (minn m n) = n.\n\n(*This lemma states that the maximum operation on natural numbers is left-distributive over the minimum operation, meaning that the maximum of a natural number and the minimum of two others is equal to the minimum of two values: the maximum of the first and second numbers, and the maximum of the first and third numbers.*)\nLemma maxn_minl : left_distributive maxn minn.\n\n(*This lemma states that the maximum operation on natural numbers is right-distributive over the minimum operation, meaning that taking the maximum of the minimum of a first and second number with a third number is equivalent to taking the minimum of two values: the maximum of the first and third numbers, and the maximum of the second and third numbers.*)\nLemma maxn_minr : right_distributive maxn minn.\n\n(*This lemma states that the minimum operation on natural numbers is left-distributive over the maximum operation, meaning that the minimum of a natural number and the maximum of two others is equal to the maximum of two values: the minimum of the first and second numbers, and the minimum of the first and third numbers.*)\nLemma minn_maxl : left_distributive minn maxn.\n\n(*This lemma states that the minimum operation on natural numbers is right-distributive over the maximum operation, meaning that taking the minimum of the maximum of a first and second number with a third number is equivalent to taking the maximum of two values: the minimum of the first and third numbers, and the minimum of the second and third numbers.*)\nLemma minn_maxr : right_distributive minn maxn.\n\n(*This inductive type represents the law of trichotomy for the less-than-or-equal relation on natural numbers, which states that for any two natural numbers, exactly one of two cases holds: either the first is less than or equal to the second, or the first is strictly greater than the second.*)\nVariant leq_xor_gtn m n : nat -> nat -> nat -> nat -> bool -> bool -> Set :=\n(**)\n | LeqNotGtn of m <= n : leq_xor_gtn m n m m n n true false\n(**)\n | GtnNotLeq of n < m : leq_xor_gtn m n n n m m false true.\n\n(*This lemma provides a constructive proof of the law of trichotomy for the less-than-or-equal relation on natural numbers, demonstrating that for any two given natural numbers, one can decide whether the first is less than or equal to the second or strictly greater than the second.*)\nLemma leqP m n : leq_xor_gtn m n (minn n m) (minn m n) (maxn n m) (maxn m n)\n (m <= n) (n < m).\n\n(*This inductive type represents the law of trichotomy for the strictly-less-than relation on natural numbers, which states that for any two natural numbers, exactly one of two cases holds: either the first is strictly less than the second, or the first is greater than or equal to the second.*)\nVariant ltn_xor_geq m n : nat -> nat -> nat -> nat -> bool -> bool -> Set :=\n(**)\n | LtnNotGeq of m < n : ltn_xor_geq m n m m n n false true\n(**)\n | GeqNotLtn of n <= m : ltn_xor_geq m n n n m m true false.\n\n(*This lemma provides a constructive proof of the law of trichotomy for the strictly-less-than relation on natural numbers, demonstrating that for any two given natural numbers, one can decide whether the first is strictly less than the second or greater than or equal to the second.*)\nLemma ltnP m n : ltn_xor_geq m n (minn n m) (minn m n) (maxn n m) (maxn m n)\n (n <= m) (m < n).\n\n(*This inductive type represents the property that any natural number is either equal to zero or strictly greater than zero, providing evidence for which case holds.*)\nVariant eqn0_xor_gt0 n : bool -> bool -> Set :=\n(**)\n | Eq0NotPos of n = 0 : eqn0_xor_gt0 n true false\n(**)\n | PosNotEq0 of n > 0 : eqn0_xor_gt0 n false true.\n\n(*This lemma provides a constructive proof that any given natural number is either equal to zero or strictly positive, by constructing a term of the inductive type that represents this choice.*)\nLemma posnP n : eqn0_xor_gt0 n (n == 0) (0 < n).\n\n(*This inductive type represents the result of a three-way comparison between two natural numbers, indicating whether the first number is strictly less than, equal to, or strictly greater than the second number.*)\nVariant compare_nat m n : nat -> nat -> nat -> nat ->\n bool -> bool -> bool -> bool -> bool -> bool -> Set :=\n | CompareNatLt of m < n :\n compare_nat m n m m n n false false false true false true\n | CompareNatGt of m > n :\n compare_nat m n n n m m false false true false true false\n | CompareNatEq of m = n :\n compare_nat m n m m m m true true true true false false.\n\n(*This lemma asserts that the `compare_nat` constructor, which encapsulates the full comparison state of two natural numbers, can be constructed using various standard comparison functions and predicates. These include the minimum, maximum, equality, less-than-or-equal, and less-than relations between the two numbers.*)\nLemma ltngtP m n :\n compare_nat m n (minn n m) (minn m n) (maxn n m) (maxn m n)\n (n == m) (m == n) (n <= m) (m <= n) (n < m) (m < n).\n\n(*This lemma states that a conditional expression testing if the subtraction of a second natural number from one more than a first natural number results in a positive value is equivalent to a conditional expression testing if the second number is less than or equal to the first. In the case where the condition is met, a function is applied to the result of the subtraction.*)\nLemma subn_if_gt T m n F (E : T) :\n (if m.+1 - n is m'.+1 then F m' else E) = (if n <= m then F (m - n) else E).\n\n(*This notation defines a pattern for use in rewrite rules that matches the term on the left-hand side of a less-than-or-equal-to comparison between natural numbers.*)\nNotation leqLHS := (X in (X <= _)%N)%pattern.\n(*This notation defines a pattern for use in rewrite rules that matches the term on the right-hand side of a less-than-or-equal-to comparison between natural numbers.*)\nNotation leqRHS := (X in (_ <= X)%N)%pattern.\n(*This notation defines a pattern for use in rewrite rules that matches the term on the left-hand side of a strict less-than comparison between natural numbers.*)\nNotation ltnLHS := (X in (X < _)%N)%pattern.\n(*This notation defines a pattern for use in rewrite rules that matches the term on the right-hand side of a strict less-than comparison between natural numbers.*)\nNotation ltnRHS := (X in (_ < X)%N)%pattern.\n\nSection ExMinn.\n\nVariable P : pred nat.\nHypothesis exP : exists n, P n.\n\n(*This inductive proposition formalizes the concept of accessibility for natural numbers with respect to a given predicate. It asserts that for a given natural number, the predicate holds either for that number itself or for some larger natural number.*)\nInductive acc_nat i : Prop := AccNat0 of P i | AccNatS of acc_nat i.+1.\n\n(*This lemma asserts the existence and provides a proof of a minimal natural number that satisfies a given predicate, under the assumption that at least one number satisfies the predicate.*)\nLemma find_ex_minn : {m | P m & forall n, P n -> n >= m}.\n\n(*This definition provides the smallest natural number that satisfies a given predicate, assuming such a number is proven to exist.*)\nDefinition ex_minn := s2val find_ex_minn.\n\n(*This lemma states that for any monotonic boolean predicate on natural numbers, if the predicate holds for some number, then the predicate is true for a given number if and only if that number is greater than or equal to the minimal number for which the predicate holds.*)\nInductive ex_minn_spec : nat -> Type :=\n ExMinnSpec m of P m & (forall n, P n -> n >= m) : ex_minn_spec m.\n\n(*This lemma states that the natural number defined by `ex_minn` indeed satisfies the given predicate and is less than or equal to any other natural number that also satisfies the predicate.*)\nLemma ex_minnP : ex_minn_spec ex_minn.\n\nEnd ExMinn.\n\nSection ExMaxn.\n\nVariables (P : pred nat) (m : nat).\nHypotheses (exP : exists i, P i) (ubP : forall i, P i -> i <= m).\n\n(*This lemma provides an auxiliary proof which asserts that if a predicate on natural numbers has an upper bound and is satisfied by at least one number, then there exists a natural number whose difference from the upper bound results in a value that satisfies the predicate.*)\nLemma ex_maxn_subproof : exists i, P (m - i).\n\n(*This definition provides the largest natural number that satisfies a given predicate, under the assumptions that such a number exists and is bounded by a given upper limit.*)\nDefinition ex_maxn := m - ex_minn ex_maxn_subproof.\n\n(**)\nVariant ex_maxn_spec : nat -> Type :=\n ExMaxnSpec i of P i & (forall j, P j -> j <= i) : ex_maxn_spec i.\n\n(*This lemma states that the natural number defined by `ex_maxn` indeed satisfies the given predicate and is greater than or equal to any other natural number that also satisfies the predicate.*)\nLemma ex_maxnP : ex_maxn_spec ex_maxn.\n\nEnd ExMaxn.\n\n(*This lemma states that if two predicates on natural numbers are extensionally equal, meaning they hold for the same set of numbers, then their respective minimal satisfying elements are also equal.*)\nLemma eq_ex_minn P Q exP exQ : P =1 Q -> @ex_minn P exP = @ex_minn Q exQ.\n\n(*This lemma states that if two predicates on natural numbers are extensionally equal, meaning they hold for the same set of numbers, then their respective maximal satisfying elements are also equal, even if their specified upper bounds differ.*)\nLemma eq_ex_maxn (P Q : pred nat) m n exP ubP exQ ubQ :\n P =1 Q -> @ex_maxn P m exP ubP = @ex_maxn Q n exQ ubQ.\n\nSection Iteration.\n\nVariable T : Type.\nImplicit Types m n : nat.\nImplicit Types x y : T.\nImplicit Types S : {pred T}.\n\n(*This definition computes the result of applying a given function to an initial value for a specified number of times.*)\nDefinition iter n f x :=\n let fix loop m := if m is i.+1 then f (loop i) else x in loop n.\n\n(*This definition computes the result of repeatedly applying an indexed function to an initial value. At each step, the function receives the current iteration index, starting from one less than the total number of iterations and counting down to zero.*)\nDefinition iteri n f x :=\n let fix loop m := if m is i.+1 then f i (loop i) else x in loop n.\n\n(*This definition computes the result of repeatedly applying a binary operator. An initial value serves as both the fixed first argument to the operator and the starting value for the iteration.*)\nDefinition iterop n op x :=\n let f i y := if i is 0 then x else op x y in iteri n f.\n\n(*This lemma states that iterating a function `n` plus one times on a value is equivalent to iterating the function `n` times on the result of a single application of the function to that value.*)\nLemma iterSr n f x : iter n.+1 f x = iter n f (f x).\n\n(*This lemma provides the standard recursive property of iteration, stating that applying a function `n` plus one times is equivalent to applying the function once to the result of iterating it `n` times.*)\nLemma iterS n f x : iter n.+1 f x = f (iter n f x). \n\n(*This lemma expresses an additive property of iteration, stating that iterating a function a number of times equal to the sum of two natural numbers is equivalent to composing the iterations of the function for each of those numbers.*)\nLemma iterD n m f x : iter (n + m) f x = iter n f (iter m f x).\n\n(*This lemma provides the recursive property of indexed iteration, stating that iterating an indexed function `n` plus one times is equivalent to applying the function with index `n` to the result of iterating it `n` times.*)\nLemma iteriS n f x : iteri n.+1 f x = f n (iteri n f x).\n\n(*This lemma states that iterating a binary operator `n` plus one times using `iterop` is equivalent to iterating `n` times the unary function that is formed by fixing the first argument of the binary operator.*)\nLemma iteropS idx n op x : iterop n.+1 op x idx = iter n (op x) x.\n\n(*This lemma states that if two functions are extensionally equal, then the functions resulting from iterating them for any given number of times are also extensionally equal.*)\nLemma eq_iter f f' : f =1 f' -> forall n, iter n f =1 iter n f'.\n\n(*This lemma states that if a value is a fixed point of a function, meaning the function maps the value to itself, then iterating that function any number of times on that value will always result in the same value.*)\nLemma iter_fix n f x : f x = x -> iter n f x = x.\n\n(*This lemma states that if two indexed functions are extensionally equal, then the functions resulting from their indexed iteration for any given number of times are also extensionally equal.*)\nLemma eq_iteri f f' : f =2 f' -> forall n, iteri n f =1 iteri n f'.\n\n(*This lemma states that if two binary operators are extensionally equal, then the functions obtained by applying `iterop` with these operators for a fixed number of iterations will also be extensionally equal.*)\nLemma eq_iterop n op op' : op =2 op' -> iterop n op =2 iterop n op'.\n\n(*This lemma states that if a function consistently maps elements of a given set to other elements within the same set, then iterating that function any number of times also produces a function with this same set-preserving property.*)\nLemma iter_in f S i : {homo f : x / x \\in S} -> {homo iter i f : x / x \\in S}.\n\nEnd Iteration.\n\n(*This lemma states that iterating the successor function on natural numbers `n` times, starting from an initial number `m`, is equivalent to computing the sum of `m` and `n`.*)\nLemma iter_succn m n : iter n succn m = m + n.\n\n(*This lemma states that iterating the successor function a given number of times, starting from zero, results in that same number.*)\nLemma iter_succn_0 n : iter n succn 0 = n.\n\n(*This lemma states that iterating the predecessor function on a first natural number a second number of times results in the truncated difference between the first and second numbers.*)\nLemma iter_predn m n : iter n predn m = m - n.\n\n(*This definition introduces `muln` as the standard multiplication operation for natural numbers.*)\nDefinition muln := mult.\nArguments muln : simpl never.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use muln instead.\")]\n(*This definition provides a deprecated alias for the natural number multiplication operation.*)\nDefinition muln_rec := muln.\n(*This notation defines the infix asterisk symbol as the standard multiplication operation between two natural numbers.*)\nNotation \"m * n\" := (muln m n) : nat_scope.\n\n(*This lemma states that the function `mult` is equivalent to the function `muln` for natural number multiplication.*)\nLemma multE : mult = muln. \n(*This lemma states that the function `muln` is equivalent to the function `mult` for natural number multiplication.*)\nLemma mulnE : muln = mult. \n\n(*This lemma states that zero is a left zero for multiplication, meaning that multiplying zero by any natural number results in zero.*)\nLemma mul0n : left_zero 0 muln. \n(*This lemma states that zero is a right zero for multiplication, meaning that multiplying any natural number by zero results in zero.*)\nLemma muln0 : right_zero 0 muln. \n(*This lemma states that one is the left identity for multiplication, meaning that multiplying one by any natural number results in that same number.*)\nLemma mul1n : left_id 1 muln. \n(*This lemma provides a recursive property of multiplication, stating that the product of the successor of a first natural number and a second natural number is equal to the sum of the second number and the product of the first and second numbers.*)\nLemma mulSn m n : m.+1 * n = n + m * n. \n(*This lemma provides a recursive property of multiplication, stating that the product of the successor of a first natural number and a second natural number is equal to the sum of their product and the second number.*)\nLemma mulSnr m n : m.+1 * n = m * n + n. \n\n(*This lemma provides a recursive property of multiplication, stating that the product of a first natural number and the successor of a second natural number is equal to the sum of the first number and the product of the first and second numbers.*)\nLemma mulnS m n : m * n.+1 = m + m * n.\n\n(*This lemma provides a recursive property of multiplication, stating that the product of a first natural number and the successor of a second natural number is equal to the sum of their product and the first number.*)\nLemma mulnSr m n : m * n.+1 = m * n + m.\n\n(*This lemma states that iterating the function 'add a first natural number' a second number of times, starting from a third natural number, results in the sum of the third number and the product of the first two numbers.*)\nLemma iter_addn m n p : iter n (addn m) p = m * n + p.\n\n(*This lemma states that iterating the function 'add a first natural number' a second number of times, starting from zero, results in the product of the two numbers.*)\nLemma iter_addn_0 m n : iter n (addn m) 0 = m * n.\n\n(*This lemma states that one is the right identity for multiplication, meaning that multiplying any natural number by one results in that same number.*)\nLemma muln1 : right_id 1 muln.\n\n(*This lemma states that multiplication of natural numbers is a commutative operation.*)\nLemma mulnC : commutative muln.\n\n(*This lemma states that multiplication of natural numbers is left-distributive over addition.*)\nLemma mulnDl : left_distributive muln addn.\n\n(*This lemma states that multiplication of natural numbers is right-distributive over addition.*)\nLemma mulnDr : right_distributive muln addn.\n\n(*This lemma states that multiplication of natural numbers is left-distributive over truncated subtraction.*)\nLemma mulnBl : left_distributive muln subn.\n\n(*This lemma states that multiplication of natural numbers is right-distributive over truncated subtraction.*)\nLemma mulnBr : right_distributive muln subn.\n\n(*This lemma states that multiplication of natural numbers is an associative operation.*)\nLemma mulnA : associative muln.\n\n(*This lemma states that multiplication of natural numbers is left-commutative, meaning that in a product of three numbers grouped to the right, the first and second numbers can be swapped.*)\nLemma mulnCA : left_commutative muln.\n\n(*This lemma states that multiplication of natural numbers is right-commutative, meaning that in a product of three numbers grouped to the left, the second and third numbers can be swapped.*)\nLemma mulnAC : right_commutative muln.\n\n(*This lemma states that the multiplication operation interchanges with itself, meaning the product of two products can be re-grouped by taking the products of the first factors and the second factors respectively.*)\nLemma mulnACA : interchange muln muln.\n\n(*This lemma states that the product of two natural numbers is equal to zero if and only if at least one of the numbers is equal to zero.*)\nLemma muln_eq0 m n : (m * n == 0) = (m == 0) || (n == 0).\n\n(*This lemma states that the product of two natural numbers is equal to one if and only if both numbers are equal to one.*)\nLemma muln_eq1 m n : (m * n == 1) = (m == 1) && (n == 1).\n\n(*This lemma states that the product of two natural numbers is greater than zero if and only if both numbers are greater than zero.*)\nLemma muln_gt0 m n : (0 < m * n) = (0 < m) && (0 < n).\n\n(*This lemma states that for any two natural numbers, a first number is less than or equal to the product of a second number and the first number, provided the second number is greater than zero.*)\nLemma leq_pmull m n : n > 0 -> m <= n * m.\n\n(*This lemma states that multiplying a natural number by a positive natural number results in a value greater than or equal to the original number.*)\nLemma leq_pmulr m n : n > 0 -> m <= m * n.\n\n(*This lemma states that the product of a common factor and a first natural number is less than or equal to the product of the same common factor and a second natural number if and only if the common factor is zero or the first number is less than or equal to the second.*)\nLemma leq_mul2l m n1 n2 : (m * n1 <= m * n2) = (m == 0) || (n1 <= n2).\n\n(*This lemma states that the product of a first natural number and a common factor is less than or equal to the product of a second natural number and the same common factor if and only if the common factor is zero or the first number is less than or equal to the second.*)\nLemma leq_mul2r m n1 n2 : (n1 * m <= n2 * m) = (m == 0) || (n1 <= n2).\n\n(*This lemma states that for four natural numbers, if a first number is less than or equal to a second, and a third number is less than or equal to a fourth, then the product of the first and third numbers is less than or equal to the product of the second and fourth numbers.*)\nLemma leq_mul m1 m2 n1 n2 : m1 <= n1 -> m2 <= n2 -> m1 * m2 <= n1 * n2.\n\n(*This lemma provides a cancellation rule for multiplication, stating that the product of a common factor and a first natural number equals the product of the same common factor and a second natural number if and only if the common factor is zero or the first and second numbers are equal.*)\nLemma eqn_mul2l m n1 n2 : (m * n1 == m * n2) = (m == 0) || (n1 == n2).\n\n(*This lemma provides a right cancellation rule for multiplication, stating that the product of a first natural number and a common factor equals the product of a second natural number and the same common factor if and only if the common factor is zero or the first and second numbers are equal.*)\nLemma eqn_mul2r m n1 n2 : (n1 * m == n2 * m) = (m == 0) || (n1 == n2).\n\n(*This lemma simplifies an inequality involving multiplication by a positive factor, stating that if a common factor is positive, the product of this factor and a first natural number is less than or equal to the product of the same factor and a second natural number if and only if the first number is less than or equal to the second.*)\nLemma leq_pmul2l m n1 n2 : 0 < m -> (m * n1 <= m * n2) = (n1 <= n2).\n\nArguments leq_pmul2l [m n1 n2].\n\n(*This lemma simplifies an inequality involving multiplication by a positive factor on the right, stating that if a common factor is positive, the product of a first natural number and this factor is less than or equal to the product of a second natural number and the same factor if and only if the first number is less than or equal to the second.*)\nLemma leq_pmul2r m n1 n2 : 0 < m -> (n1 * m <= n2 * m) = (n1 <= n2).\n\nArguments leq_pmul2r [m n1 n2].\n\n(*This lemma provides a cancellation rule for multiplication by a positive factor, stating that if a common factor is positive, the product of this factor and a first natural number equals the product of the same factor and a second natural number if and only if the first and second numbers are equal.*)\nLemma eqn_pmul2l m n1 n2 : 0 < m -> (m * n1 == m * n2) = (n1 == n2).\n\nArguments eqn_pmul2l [m n1 n2].\n\n(*This lemma provides a right cancellation rule for multiplication by a positive factor, stating that if a common factor is positive, the product of a first natural number and this factor equals the product of a second natural number and the same factor if and only if the first and second numbers are equal.*)\nLemma eqn_pmul2r m n1 n2 : 0 < m -> (n1 * m == n2 * m) = (n1 == n2).\n\nArguments eqn_pmul2r [m n1 n2].\n\n(*This lemma concerns strict inequality with a common left multiplier, stating that the product of a common factor and a first natural number is strictly less than the product of the same factor and a second natural number if and only if the common factor is positive and the first number is strictly less than the second.*)\nLemma ltn_mul2l m n1 n2 : (m * n1 < m * n2) = (0 < m) && (n1 < n2).\n\n(*This lemma concerns strict inequality with a common right multiplier, stating that the product of a first natural number and a common factor is strictly less than the product of a second natural number and the same factor if and only if the common factor is positive and the first number is strictly less than the second.*)\nLemma ltn_mul2r m n1 n2 : (n1 * m < n2 * m) = (0 < m) && (n1 < n2).\n\n(*This lemma simplifies a strict inequality involving multiplication by a positive factor, stating that if a common factor is positive, the product of this factor and a first natural number is strictly less than the product of the same factor and a second natural number if and only if the first number is strictly less than the second.*)\nLemma ltn_pmul2l m n1 n2 : 0 < m -> (m * n1 < m * n2) = (n1 < n2).\n\nArguments ltn_pmul2l [m n1 n2].\n\n(*This lemma simplifies a strict inequality involving multiplication by a positive factor on the right, stating that if a common factor is positive, the product of a first natural number and this factor is strictly less than the product of a second natural number and the same factor if and only if the first number is strictly less than the second.*)\nLemma ltn_pmul2r m n1 n2 : 0 < m -> (n1 * m < n2 * m) = (n1 < n2).\n\nArguments ltn_pmul2r [m n1 n2].\n\n(*This lemma states that multiplying a positive natural number on the left by another natural number strictly greater than one results in a value strictly greater than the original positive number.*)\nLemma ltn_Pmull m n : 1 < n -> 0 < m -> m < n * m.\n\n(*This lemma states that multiplying a positive natural number on the right by another natural number strictly greater than one results in a value strictly greater than the original positive number.*)\nLemma ltn_Pmulr m n : 1 < n -> 0 < m -> m < m * n.\n\n(*This lemma states that for four natural numbers, if a first number is strictly less than a second, a third number is less than or equal to a fourth, and the fourth number is positive, then the product of the first and third numbers is strictly less than the product of the second and fourth numbers.*)\nLemma ltn_mull m1 m2 n1 n2 : 0 < n2 -> m1 < n1 -> m2 <= n2 -> m1 * m2 < n1 * n2.\n\n(*This lemma states that for four natural numbers, if a first number is less than or equal to a second, a third number is strictly less than a fourth, and the second number is positive, then the product of the first and third numbers is strictly less than the product of the second and fourth numbers.*)\nLemma ltn_mulr m1 m2 n1 n2 : 0 < n1 -> m1 <= n1 -> m2 < n2 -> m1 * m2 < n1 * n2.\n\n(*This lemma states that for four natural numbers, if a first number is strictly less than a second number and a third number is strictly less than a fourth number, then the product of the first and third numbers is strictly less than the product of the second and fourth numbers.*)\nLemma ltn_mul m1 m2 n1 n2 : m1 < n1 -> m2 < n2 -> m1 * m2 < n1 * n2.\n\n(*This lemma states that multiplication of natural numbers is right distributive over the maximum operation.*)\nLemma maxnMr : right_distributive muln maxn.\n\n(*This lemma states that multiplication of natural numbers is left distributive over the maximum operation.*)\nLemma maxnMl : left_distributive muln maxn.\n\n(*This lemma states that multiplication of natural numbers is right distributive over the minimum operation.*)\nLemma minnMr : right_distributive muln minn.\n\n(*This lemma states that multiplication of natural numbers is left distributive over the minimum operation.*)\nLemma minnMl : left_distributive muln minn.\n\n(*This lemma states that iterating a function a number of times equal to a product of two natural numbers is equivalent to iterating the function by the second number, and then iterating the resulting function by the first number.*)\nLemma iterM (T : Type) (n m : nat) (f : T -> T) :\n iter (n * m) f =1 iter n (iter m f).\n\n(*This definition defines exponentiation of natural numbers, where a base raised to a power is computed by repeatedly multiplying the base by itself a number of times given by the exponent, with one as the initial value.*)\nDefinition expn m n := iterop n muln m 1.\nArguments expn : simpl never.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use expn instead.\")]\n(*This definition provides a deprecated alias for the exponentiation function `expn`.*)\nDefinition expn_rec := expn.\n(*This notation provides the caret symbol for the exponentiation of a natural number base by a natural number exponent.*)\nNotation \"m ^ n\" := (expn m n) : nat_scope.\n\n(*This lemma provides a rule for rewriting an exponentiation expression into its underlying definition as an iterated multiplication.*)\nLemma expnE n m : expn m n = iterop n muln m 1. \n\n(*This lemma states that any natural number raised to the power of zero is equal to one.*)\nLemma expn0 m : m ^ 0 = 1. \n(*This lemma states that any natural number raised to the power of one is equal to itself.*)\nLemma expn1 m : m ^ 1 = m. \n(*This lemma states that raising a natural number to the power of the successor of another natural number is equivalent to multiplying the base by itself raised to the power of the original number.*)\nLemma expnS m n : m ^ n.+1 = m * m ^ n. \n(*This lemma states that a natural number raised to the power of the successor of another natural number is equal to the product of the number raised to the original exponent and the base number itself.*)\nLemma expnSr m n : m ^ n.+1 = m ^ n * m. \n\n(*This lemma states that repeatedly applying multiplication by a first natural number for a second natural number of times, starting with a third natural number, yields the same result as multiplying the third number by the first number raised to the power of the second.*)\nLemma iter_muln m n p : iter n (muln m) p = m ^ n * p.\n\n(*This lemma states that iterating multiplication by a given natural number a specified number of times, starting from one, is equivalent to raising the given number to the power of the specified number of iterations.*)\nLemma iter_muln_1 m n : iter n (muln m) 1 = m ^ n.\n\n(*This lemma states that for any natural number greater than zero, raising zero to the power of that number results in zero.*)\nLemma exp0n n : 0 < n -> 0 ^ n = 0. \n\n(*This lemma states that one raised to the power of any natural number is equal to one.*)\nLemma exp1n n : 1 ^ n = 1.\n\n(*This lemma states that raising a natural number to the power of a sum of two other natural numbers is equivalent to the product of the base raised to each of the two exponents separately.*)\nLemma expnD m n1 n2 : m ^ (n1 + n2) = m ^ n1 * m ^ n2.\n\n(*This lemma states that raising a product of two natural numbers to a given power is equivalent to the product of each number raised to that same power.*)\nLemma expnMn m1 m2 n : (m1 * m2) ^ n = m1 ^ n * m2 ^ n.\n\n(*This lemma states that raising a natural number to the power of a product of two exponents is equivalent to successively raising the base to the first exponent and then raising the result to the second exponent.*)\nLemma expnM m n1 n2 : m ^ (n1 * n2) = (m ^ n1) ^ n2.\n\n(*This lemma states that the order of exponents can be interchanged when raising a natural number to a power and then raising the result to another power.*)\nLemma expnAC m n1 n2 : (m ^ n1) ^ n2 = (m ^ n2) ^ n1.\n\n(*This lemma states that a natural number raised to a power is greater than zero if and only if the base is greater than zero or the exponent is equal to zero.*)\nLemma expn_gt0 m n : (0 < m ^ n) = (0 < m) || (n == 0).\n\n(*This lemma states that a natural number raised to a power is equal to zero if and only if the base is zero and the exponent is greater than zero.*)\nLemma expn_eq0 m e : (m ^ e == 0) = (m == 0) && (e > 0).\n\n(*This lemma states that if a natural number base is greater than one, then any natural number exponent is strictly less than the result of raising the base to that exponent.*)\nLemma ltn_expl m n : 1 < m -> n < m ^ n.\n\n(*This lemma states that for a natural number base greater than one, the comparison of two powers of that base is equivalent to the comparison of their exponents; specifically, one power is less than or equal to another if and only if its exponent is less than or equal to the other's exponent.*)\nLemma leq_exp2l m n1 n2 : 1 < m -> (m ^ n1 <= m ^ n2) = (n1 <= n2).\n\n(*This lemma states that for a natural number base greater than one, a strict inequality between two powers of that base holds if and only if a corresponding strict inequality holds for their exponents.*)\nLemma ltn_exp2l m n1 n2 : 1 < m -> (m ^ n1 < m ^ n2) = (n1 < n2).\n\n(*This lemma states that for a natural number base greater than one, two powers of that base are equal if and only if their exponents are equal.*)\nLemma eqn_exp2l m n1 n2 : 1 < m -> (m ^ n1 == m ^ n2) = (n1 == n2).\n\n(*This lemma states that for any natural number base greater than one, the exponentiation function with that fixed base is injective, meaning different exponents yield different results.*)\nLemma expnI m : 1 < m -> injective (expn m).\n\n(*This lemma states that for any natural number base greater than zero, the exponentiation function with that base is non-decreasing; specifically, if a first exponent is less than or equal to a second exponent, then the base raised to the first exponent is less than or equal to the base raised to the second.*)\nLemma leq_pexp2l m n1 n2 : 0 < m -> n1 <= n2 -> m ^ n1 <= m ^ n2.\n\n(*This lemma states that for a natural number base greater than zero, if the base raised to a first exponent is strictly less than the base raised to a second exponent, then the first exponent must be strictly less than the second.*)\nLemma ltn_pexp2l m n1 n2 : 0 < m -> m ^ n1 < m ^ n2 -> n1 < n2.\n\n(*This lemma states that for any positive natural number exponent, a strict inequality between two natural number bases holds if and only if the same strict inequality holds for the bases raised to that exponent.*)\nLemma ltn_exp2r m n e : e > 0 -> (m ^ e < n ^ e) = (m < n).\n\n(*This lemma states that for any positive natural number exponent, a non-strict inequality between two natural number bases holds if and only if the same non-strict inequality holds for the bases raised to that exponent.*)\nLemma leq_exp2r m n e : e > 0 -> (m ^ e <= n ^ e) = (m <= n).\n\n(*This lemma states that for any positive natural number exponent, two natural numbers are equal if and only if their results are equal when raised to that exponent.*)\nLemma eqn_exp2r m n e : e > 0 -> (m ^ e == n ^ e) = (m == n).\n\n(*This lemma states that for any positive natural number exponent, the function that raises a natural number to that fixed exponent is injective.*)\nLemma expIn e : e > 0 -> injective (expn^~ e).\n\n(*This lemma states that for any function, iterating it a number of times equal to a base raised to an exponent is equivalent to nesting iterations, where the inner iteration is performed a number of times equal to the base, and this process is repeated a number of times equal to the exponent.*)\nLemma iterX (T : Type) (n m : nat) (f : T -> T) :\n iter (n ^ m) f =1 iter m (iter n) f.\n\n(*This definition computes the factorial of a natural number, which is defined recursively as the product of all positive natural numbers up to that number, with the factorial of zero being one.*)\nFixpoint factorial n := if n is n'.+1 then n * factorial n' else 1.\nArguments factorial : simpl never.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use factorial instead.\")]\n(*This definition provides a deprecated alias for the factorial function.*)\nDefinition fact_rec := factorial.\n\n(*This notation provides the standard postfix syntax for the factorial of a natural number.*)\nNotation \"n `!\" := (factorial n) (at level 2, format \"n `!\") : nat_scope.\n\n(*This lemma states the definitional equation for factorial, expressing its value for a given natural number in terms of its value for the predecessor if the number is positive, and as one if the number is zero.*)\nLemma factE n : factorial n = if n is n'.+1 then n * factorial n' else 1.\n\n(*This lemma states that the factorial of zero is equal to one.*)\nLemma fact0 : 0`! = 1. \n\n(*This lemma states that the factorial of the successor of a natural number is equal to the product of the successor and the factorial of the original number.*)\nLemma factS n : (n.+1)`! = n.+1 * n`!. \n\n(*This lemma states that the factorial of any natural number is strictly greater than zero.*)\nLemma fact_gt0 n : n`! > 0.\n\n(*This lemma states that any natural number is less than or equal to its factorial.*)\nLemma fact_geq n : n <= n`!.\n\n(*This lemma states that for any two natural numbers, if the first number is strictly greater than zero and strictly less than the second number, then the factorial of the first number is strictly less than the factorial of the second number.*)\nLemma ltn_fact m n : 0 < m -> m < n -> m`! < n`!.\n\nCoercion nat_of_bool (b : bool) := if b then 1 else 0.\n\n(*This lemma states that any boolean value, when interpreted as a natural number, is less than or equal to one.*)\nLemma leq_b1 (b : bool) : b <= 1. \n\n(*This lemma states that for any boolean value, the sum of the natural number representation of its negation and the natural number representation of itself is equal to one.*)\nLemma addn_negb (b : bool) : ~~ b + b = 1. \n\n(*This lemma states that for any boolean value, the boolean result of testing its natural number representation for equality with zero is equivalent to the logical negation of the original boolean value.*)\nLemma eqb0 (b : bool) : (b == 0 :> nat) = ~~ b. \n\n(*This lemma states that for any boolean value, the boolean result of testing its natural number representation for equality with one is equivalent to the original boolean value itself.*)\nLemma eqb1 (b : bool) : (b == 1 :> nat) = b. \n\n(*This lemma states that for any boolean value, the boolean result of testing if its natural number representation is strictly greater than zero is equivalent to the original boolean value.*)\nLemma lt0b (b : bool) : (b > 0) = b. \n\n(*This lemma states that for any boolean value, subtracting its natural number representation from one results in the natural number representation of its logical negation.*)\nLemma sub1b (b : bool) : 1 - b = ~~ b. \n\n(*This lemma states that the product of two boolean values, when interpreted as natural numbers, is equal to the natural number representation of their logical conjunction.*)\nLemma mulnb (b1 b2 : bool) : b1 * b2 = b1 && b2.\n\n(*This lemma states that multiplying the natural number representation of a boolean value by a natural number results in that natural number if the boolean is true, and zero if the boolean is false.*)\nLemma mulnbl (b : bool) n : b * n = (if b then n else 0).\n\n(*This lemma states that multiplying a natural number by the natural number representation of a boolean value results in that natural number if the boolean is true, and zero if the boolean is false.*)\nLemma mulnbr (b : bool) n : n * b = (if b then n else 0).\n\n(*This definition provides a recursive function that determines whether a given natural number is odd, returning true if it is odd and false if it is even.*)\nFixpoint odd n := if n is n'.+1 then ~~ odd n' else false.\n\n(*This lemma states that the boolean result of testing the successor of a natural number for oddness is the logical negation of the boolean result of testing the original number for oddness.*)\nLemma oddS n : odd n.+1 = ~~ odd n. \n\n(*This lemma states that applying the 'odd' predicate to the natural number representation of a boolean value yields that same boolean value.*)\nLemma oddb (b : bool) : odd b = b. \n\n(*This lemma states that the boolean result of testing the sum of two natural numbers for oddness is equivalent to the exclusive disjunction of the boolean results of testing each number for oddness individually.*)\nLemma oddD m n : odd (m + n) = odd m (+) odd n.\n\n(*This lemma states that for two natural numbers where the second is less than or equal to the first, the boolean result of testing their difference for oddness is equivalent to the exclusive disjunction of the boolean results of testing each number for oddness individually.*)\nLemma oddB m n : n <= m -> odd (m - n) = odd m (+) odd n.\n\n(*This lemma states that if a natural number is even, and a second natural number is less than or equal to the first, then the oddness of the difference between the first and second numbers is the same as the oddness of the second number.*)\nLemma oddN i m : odd m = false -> i <= m -> odd (m - i) = odd i.\n\n(*This lemma states that the boolean result of testing the product of two natural numbers for oddness is equivalent to the logical conjunction of the boolean results of testing each number for oddness individually.*)\nLemma oddM m n : odd (m * n) = odd m && odd n.\n\n(*This lemma states that the result of raising a natural number to a power is odd if and only if the exponent is zero or the base number is odd.*)\nLemma oddX m n : odd (m ^ n) = (n == 0) || odd m.\n\n(*This definition provides a recursive function that computes the double of a given natural number.*)\nFixpoint double n := if n is n'.+1 then (double n').+2 else 0.\nArguments double : simpl never.\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use double instead.\")]\n(*This definition provides a deprecated alias for the function that computes the double of a natural number.*)\nDefinition double_rec := double.\n(**)\nNotation \"n .*2\" := (double n) : nat_scope.\n\n(*This lemma provides the definitional equation for the 'double' function, stating that the double of a natural number is zero if the number is zero, and is otherwise computed by adding two to the double of its predecessor.*)\nLemma doubleE n : double n = if n is n'.+1 then (double n').+2 else 0.\n\n(*This lemma states that doubling the natural number zero results in zero.*)\nLemma double0 : 0.*2 = 0. \n\n(*This lemma states that the double of the successor of a natural number is equal to the double of the original number plus two.*)\nLemma doubleS n : n.+1.*2 = n.*2.+2. \n\n(*This lemma states that the double of the predecessor of a natural number is equal to the double of that number minus two.*)\nLemma double_pred n : n.-1.*2 = n.*2.-2. \n\n(*This lemma states that adding a natural number to itself is equivalent to doubling that number.*)\nLemma addnn n : n + n = n.*2.\n\n(*This lemma states that multiplying a natural number by two is equivalent to doubling that number.*)\nLemma mul2n m : 2 * m = m.*2.\n\n(*This lemma states that multiplying two by a natural number is equivalent to doubling that number.*)\nLemma muln2 m : m * 2 = m.*2.\n\n(*This lemma states that for any two natural numbers, doubling their sum is equivalent to adding the result of doubling each number individually.*)\nLemma doubleD m n : (m + n).*2 = m.*2 + n.*2.\n\n(*This lemma states that for any two natural numbers, doubling their difference is equivalent to subtracting the double of the second number from the double of the first number.*)\nLemma doubleB m n : (m - n).*2 = m.*2 - n.*2.\n\n(*This lemma states that for two natural numbers, the double of the first is less than or equal to the double of the second if and only if the first number is less than or equal to the second number.*)\nLemma leq_double m n : (m.*2 <= n.*2) = (m <= n).\n\n(*This lemma states that for two natural numbers, the double of the first is strictly less than the double of the second if and only if the first number is strictly less than the second number.*)\nLemma ltn_double m n : (m.*2 < n.*2) = (m < n).\n\n(*This lemma states that for two natural numbers, the successor of the double of the first number is strictly less than the double of the second number if and only if the first number is strictly less than the second number.*)\nLemma ltn_Sdouble m n : (m.*2.+1 < n.*2) = (m < n).\n\n(*This lemma states that for two natural numbers, the double of the first number is less than or equal to the successor of the double of the second number if and only if the first number is less than or equal to the second number.*)\nLemma leq_Sdouble m n : (m.*2 <= n.*2.+1) = (m <= n).\n\n(*This lemma states that the double of any natural number is not an odd number.*)\nLemma odd_double n : odd n.*2 = false.\n\n(*This lemma states that for any natural number, its double is greater than zero if and only if the number itself is greater than zero.*)\nLemma double_gt0 n : (0 < n.*2) = (0 < n).\n\n(*This lemma states that for any natural number, its double is equal to zero if and only if the number itself is equal to zero.*)\nLemma double_eq0 n : (n.*2 == 0) = (n == 0).\n\n(*This lemma states that for two natural numbers, doubling their product is equivalent to the product of the double of the first number and the second number.*)\nLemma doubleMl m n : (m * n).*2 = m.*2 * n.\n\n(*This lemma states that for two natural numbers, doubling their product is equivalent to the product of the first number and the double of the second number.*)\nLemma doubleMr m n : (m * n).*2 = m * n.*2.\n\n(*This definition specifies a function that computes the integer part of half of a given natural number, effectively performing integer division by two.*)\nFixpoint half (n : nat) : nat := if n is n'.+1 then uphalf n' else n\nwith uphalf (n : nat) : nat := if n is n'.+1 then n'./2.+1 else n\nwhere \"n ./2\" := (half n) : nat_scope.\n\n(*This lemma states that the ceiling of half a natural number is equivalent to the integer half of its successor.*)\nLemma uphalfE n : uphalf n = n.+1./2.\n\n(*This lemma states that computing the integer half of the double of a natural number yields the original number.*)\nLemma doubleK : cancel double half.\n\n(*This definition provides an alternative name for the lemma stating that applying the integer half function to the double of a natural number yields the original number.*)\nDefinition half_double := doubleK.\n(*This definition establishes that the function for doubling a natural number is injective, meaning that if the doubles of two natural numbers are equal, then the original numbers must also be equal.*)\nDefinition double_inj := can_inj doubleK.\n\n(*This lemma states that computing the ceiling of half of the double of a natural number results in the original number.*)\nLemma uphalf_double n : uphalf n.*2 = n.\n\n(*This lemma states that the ceiling of half a natural number is equal to the sum of its integer half and a value indicating if the number is odd.*)\nLemma uphalf_half n : uphalf n = odd n + n./2.\n\n(*This lemma states that any natural number can be reconstructed by adding a value indicating its oddness to the double of its integer half.*)\nLemma odd_double_half n : odd n + n./2.*2 = n.\n\n(*This lemma states that doubling the integer half of a natural number is equal to that number minus a value indicating whether it is odd.*)\nLemma halfK n : n./2.*2 = n - odd n.\n\n(*This lemma states that doubling the ceiling of half a natural number is equal to that number plus a value indicating whether it is odd.*)\nLemma uphalfK n : (uphalf n).*2 = odd n + n.\n\n(*This lemma states that for any odd natural number, doubling its integer half results in its predecessor.*)\nLemma odd_halfK n : odd n -> n./2.*2 = n.-1.\n\n(*This lemma states that for any even natural number, doubling its integer half results in the original number.*)\nLemma even_halfK n : ~~ odd n -> n./2.*2 = n.\n\n(*This lemma states that for any odd natural number, doubling the ceiling of its half results in its successor.*)\nLemma odd_uphalfK n : odd n -> (uphalf n).*2 = n.+1.\n\n(*This lemma states that for any even natural number, doubling the ceiling of its half results in the original number.*)\nLemma even_uphalfK n : ~~ odd n -> (uphalf n).*2 = n.\n\n(*This lemma states that for any natural number and any boolean value, computing the integer half of the sum of the double of the number and the boolean's integer equivalent results in the original number.*)\nLemma half_bit_double n (b : bool) : (b + n.*2)./2 = n.\n\n(*This lemma states that the integer half of the sum of two natural numbers is equal to the sum of their individual integer halves, plus one if both numbers are odd, and plus zero otherwise.*)\nLemma halfD m n : (m + n)./2 = (odd m && odd n) + (m./2 + n./2).\n\n(*This lemma states that if a first natural number is less than or equal to a second natural number, then the integer half of the first is also less than or equal to the integer half of the second.*)\nLemma half_leq m n : m <= n -> m./2 <= n./2.\n\n(*This lemma states that for two natural numbers, the first is less than or equal to the integer half of the second if and only if the double of the first is less than or equal to the second.*)\nLemma geq_half_double m n : (m <= n./2) = (m.*2 <= n).\n\n(*This lemma states that for two natural numbers, the integer half of the first is strictly less than the second if and only if the first is strictly less than the double of the second.*)\nLemma ltn_half_double m n : (m./2 < n) = (m < n.*2).\n\n(*This lemma states that for two natural numbers, the integer division of the first by two is less than or equal to the second if and only if the first number is less than or equal to the result of doubling the second number and adding one.*)\nLemma leq_half_double m n : (m./2 <= n) = (m <= n.*2.+1).\n\n(*This lemma states that a first natural number is strictly less than the integer division of a second natural number by two if and only if the result of doubling the first number and adding one is strictly less than the second number.*)\nLemma gtn_half_double m n : (n < m./2) = (n.*2.+1 < m).\n\n(*This lemma states that the integer division of a natural number by two is strictly greater than zero if and only if the natural number itself is strictly greater than one.*)\nLemma half_gt0 n : (0 < n./2) = (1 < n).\n\n(*This lemma states that the ceiling division by two function is non-decreasing; if a first natural number is less than or equal to a second natural number, then the ceiling division of the first by two is less than or equal to the ceiling division of the second by two.*)\nLemma uphalf_leq m n : m <= n -> uphalf m <= uphalf n.\n\n(*This lemma states that the ceiling division of a first natural number by two is less than or equal to a second natural number if and only if the first number is less than or equal to the second number doubled.*)\nLemma leq_uphalf_double m n : (uphalf m <= n) = (m <= n.*2).\n\n(*This lemma states that a first natural number is less than or equal to the ceiling division of a second natural number by two if and only if doubling the first number results in a value less than or equal to the second number plus one.*)\nLemma geq_uphalf_double m n : (m <= uphalf n) = (m.*2 <= n.+1).\n\n(*This lemma states that a first natural number is strictly less than the ceiling division of a second natural number by two if and only if doubling the first number results in a value strictly less than the second number.*)\nLemma gtn_uphalf_double m n : (n < uphalf m) = (n.*2 < m).\n\n(*This lemma states that the ceiling division of a first natural number by two is strictly less than a second natural number if and only if the first number plus one is strictly less than the second number doubled.*)\nLemma ltn_uphalf_double m n : (uphalf m < n) = (m.+1 < n.*2).\n\n(*This lemma states that the ceiling division of a natural number by two is strictly greater than zero if and only if the natural number itself is strictly greater than zero.*)\nLemma uphalf_gt0 n : (0 < uphalf n) = (0 < n).\n\n(*This lemma states that if a natural number is odd, then another natural number is less than or equal to it if and only if the largest even number less than or equal to the other number is also less than or equal to the odd number.*)\nLemma odd_geq m n : odd n -> (m <= n) = (m./2.*2 <= n).\n\n(*This lemma states that if a first natural number is odd, it is strictly less than a second natural number if and only if it is also strictly less than the largest even number that is less than or equal to the second number.*)\nLemma odd_ltn m n : odd n -> (n < m) = (n < m./2.*2).\n\n(*This lemma states that any odd natural number is strictly greater than zero.*)\nLemma odd_gt0 n : odd n -> n > 0. \n\n(*This lemma states that any odd natural number that is strictly greater than one is also strictly greater than two.*)\nLemma odd_gt2 n : odd n -> n > 1 -> n > 2.\n\n(*This lemma states that multiplying a natural number by itself is equivalent to raising that number to the power of two.*)\nLemma mulnn m : m * m = m ^ 2.\n\n(*This lemma states that the square of the sum of two natural numbers is equal to the sum of their squares plus twice their product.*)\nLemma sqrnD m n : (m + n) ^ 2 = m ^ 2 + n ^ 2 + 2 * (m * n).\n\n(*This lemma states that for two natural numbers where the second is less than or equal to the first, the square of their difference is equal to the sum of their squares minus twice their product.*)\nLemma sqrnB m n : n <= m -> (m - n) ^ 2 = m ^ 2 + n ^ 2 - 2 * (m * n).\n\n(*This lemma states that for two natural numbers where the second is less than or equal to the first, subtracting four times their product from the square of their sum yields the square of their difference.*)\nLemma sqrnD_sub m n : n <= m -> (m + n) ^ 2 - 4 * (m * n) = (m - n) ^ 2.\n\n(*This lemma states that the difference between the squares of two natural numbers is equal to the product of their difference and their sum.*)\nLemma subn_sqr m n : m ^ 2 - n ^ 2 = (m - n) * (m + n).\n\n(*This lemma states that for two natural numbers, the square of the first is strictly less than the square of the second if and only if the first number is strictly less than the second.*)\nLemma ltn_sqr m n : (m ^ 2 < n ^ 2) = (m < n).\n\n(*This lemma states that for two natural numbers, the square of the first is less than or equal to the square of the second if and only if the first number is less than or equal to the second.*)\nLemma leq_sqr m n : (m ^ 2 <= n ^ 2) = (m <= n).\n\n(*This lemma states that the square of a natural number is strictly greater than zero if and only if the number itself is strictly greater than zero.*)\nLemma sqrn_gt0 n : (0 < n ^ 2) = (0 < n).\n\n(*This lemma states that the squares of two natural numbers are equal if and only if the numbers themselves are equal.*)\nLemma eqn_sqr m n : (m ^ 2 == n ^ 2) = (m == n).\n\n(*This lemma asserts that the function that squares a natural number is injective, meaning that distinct natural numbers have distinct squares.*)\nLemma sqrn_inj : injective (expn ^~ 2).\n\n(*This definition introduces a structure that combines a proof that a first natural number is less than or equal to a second, with a proof that a given boolean value is true if and only if the two numbers are equal.*)\nDefinition leqif m n C := ((m <= n) * ((m == n) = C))%type.\n\n(*This notation provides a syntax for expressing that a first natural number is less than or equal to a second, and that a given boolean value reflects whether the two numbers are equal.*)\nNotation \"m <= n ?= 'iff' C\" := (leqif m n C) : nat_scope.\n\nCoercion leq_of_leqif m n C (H : m <= n ?= iff C) := H.1 : m <= n.\n\n(*This lemma provides a reflection property, stating that a `leqif` relation holds if and only if a corresponding boolean expression is true. The expression evaluates to whether the two numbers are equal if the given boolean is true, or to whether the first number is strictly less than the second if the given boolean is false.*)\nLemma leqifP m n C : reflect (m <= n ?= iff C) (if C then m == n else m < n).\n\n(*This lemma establishes a reflexivity property, stating that for any natural number, the relation expressing that the number is less than or equal to itself with a boolean condition holds if and only if the boolean condition is true.*)\nLemma leqif_refl m C : reflect (m <= m ?= iff C) C.\n\n(*This lemma establishes a transitivity property, stating that if a `leqif` relation holds between a first and second number with a first boolean, and between the second and a third number with a second boolean, then the relation holds between the first and third numbers with a boolean that is the logical conjunction of the first and second booleans.*)\nLemma leqif_trans m1 m2 m3 C12 C23 :\n m1 <= m2 ?= iff C12 -> m2 <= m3 ?= iff C23 -> m1 <= m3 ?= iff C12 && C23.\n\n(*This lemma states that for any strictly monotonic function on natural numbers, applying the function to the two number arguments of a `leqif` relation results in an equivalent `leqif` relation with the same boolean condition.*)\nLemma mono_leqif f : {mono f : m n / m <= n} ->\n forall m n C, (f m <= f n ?= iff C) = (m <= n ?= iff C).\n\n(*This lemma states that if a first natural number is less than or equal to a second, then the `leqif` relation holds between them with the boolean condition given by whether the first number is greater than or equal to the second.*)\nLemma leqif_geq m n : m <= n -> m <= n ?= iff (m >= n).\n\n(*This lemma asserts that for any two natural numbers where the first is less than or equal to the second, the boolean value of a less-than-or-equal-to comparison between them is equivalent to the boolean value of an equality test between them.*)\nLemma leqif_eq m n : m <= n -> m <= n ?= iff (m == n).\n\n(*This lemma states that if the boolean result of comparing a natural number `a` to be less than or equal to `b` is some boolean `C`, then the result of comparing `b` to be less than or equal to `a` is also `C`.*)\nLemma geq_leqif a b C : a <= b ?= iff C -> (b <= a) = C.\n\n(*This lemma claims that for two natural numbers, if the boolean result of a less-than-or-equal-to comparison is a certain boolean `C`, then the boolean result of a strict less-than comparison is the logical negation of `C`.*)\nLemma ltn_leqif a b C : a <= b ?= iff C -> (a < b) = ~~ C.\n\n(*This lemma states that for two natural numbers, if the boolean result of a less-than-or-equal-to comparison is the logical negation of a boolean `C`, then the boolean result of a strict less-than comparison is equal to `C`.*)\nLemma ltnNleqif x y C : x <= y ?= iff ~~ C -> (x < y) = C.\n\n(*This lemma asserts that if the boolean result of comparing a natural number `x` to be less than or equal to `y` is a boolean `C`, then the boolean result of testing their equality is also `C`.*)\nLemma eq_leqif x y C : x <= y ?= iff C -> (x == y) = C.\n\n(*This lemma states that if a natural number is less than or equal to another, then they must be equal.*)\nLemma eqTleqif x y C : x <= y ?= iff C -> C -> x = y.\n\n(*This lemma states that for natural numbers, if the boolean result of a first less-than-or-equal-to comparison is `C1` and the result of a second is `C2`, then the result of comparing the sum of the first numbers with the sum of the second numbers is the logical conjunction of `C1` and `C2`.*)\nLemma leqif_add m1 n1 C1 m2 n2 C2 :\n m1 <= n1 ?= iff C1 -> m2 <= n2 ?= iff C2 ->\n m1 + m2 <= n1 + n2 ?= iff C1 && C2.\n\n(*This lemma relates the comparison of a product of natural numbers to the comparisons of its factors. It states that if two less-than-or-equal-to comparisons yield booleans `C1` and `C2` respectively, the comparison of the products is true if and only if either the product on the right side of the inequality is zero, or both `C1` and `C2` are true.*)\nLemma leqif_mul m1 n1 C1 m2 n2 C2 :\n m1 <= n1 ?= iff C1 -> m2 <= n2 ?= iff C2 ->\n m1 * m2 <= n1 * n2 ?= iff (n1 * n2 == 0) || (C1 && C2).\n\n(*This lemma asserts that for any two natural numbers, the boolean indicating that twice their product is less than or equal to the sum of their squares is equivalent to the boolean indicating that they are equal.*)\nLemma nat_Cauchy m n : 2 * (m * n) <= m ^ 2 + n ^ 2 ?= iff (m == n).\n\n(*This lemma asserts that for any two natural numbers, the boolean indicating that four times their product is less than or equal to the square of their sum is equivalent to the boolean indicating that they are equal.*)\nLemma nat_AGM2 m n : 4 * (m * n) <= (m + n) ^ 2 ?= iff (m == n).\n\nSection ContraLeq.\nImplicit Types (b : bool) (m n : nat) (P : Prop).\n\n(*This lemma states that for two natural numbers and a boolean, if the falsity of the boolean is implied by the second number being strictly less than the first, then the truth of the boolean implies that the first number is less than or equal to the second.*)\nLemma contraTleq b m n : (n < m -> ~~ b) -> (b -> m <= n).\n\n(*This lemma is a contraposition argument. It states that for two natural numbers and a boolean, if the falsity of the boolean is implied by the second number being less than or equal to the first, then the truth of the boolean implies that the first number is strictly less than the second.*)\nLemma contraTltn b m n : (n <= m -> ~~ b) -> (b -> m < n).\n\n(*This lemma states by contraposition that for two natural numbers and a proposition, if the negation of the proposition is implied by the second number being strictly less than the first, then the proposition implies that the first number is less than or equal to the second.*)\nLemma contraPleq P m n : (n < m -> ~ P) -> (P -> m <= n).\n\n(*This lemma is a contraposition argument. It states that for two natural numbers and a proposition, if the negation of the proposition is implied by the second number being less than or equal to the first, then the proposition implies that the first number is strictly less than the second.*)\nLemma contraPltn P m n : (n <= m -> ~ P) -> (P -> m < n).\n\n(*This lemma states via contraposition that for two natural numbers and a boolean, if the boolean is implied by the second number being strictly less than the first, then the negation of the boolean implies that the first number is less than or equal to the second.*)\nLemma contraNleq b m n : (n < m -> b) -> (~~ b -> m <= n).\n\n(*This lemma states via contraposition that for two natural numbers and a boolean, if the boolean is implied by the second number being less than or equal to the first, then the negation of the boolean implies that the first number is strictly less than the second.*)\nLemma contraNltn b m n : (n <= m -> b) -> (~~ b -> m < n).\n\n(*This lemma states via contraposition that for two natural numbers and a proposition, if the proposition is implied by the second number being strictly less than the first, then the negation of the proposition implies that the first number is less than or equal to the second.*)\nLemma contra_not_leq P m n : (n < m -> P) -> (~ P -> m <= n).\n\n(*This lemma states via contraposition that for two natural numbers and a proposition, if the proposition is implied by the second number being less than or equal to the first, then the negation of the proposition implies that the first number is strictly less than the second.*)\nLemma contra_not_ltn P m n : (n <= m -> P) -> (~ P -> m < n).\n\n(*This lemma states that for two natural numbers and a boolean, if the boolean is implied by the second number being strictly less than the first, then the boolean being false implies that the first number is less than or equal to the second.*)\nLemma contraFleq b m n : (n < m -> b) -> (b = false -> m <= n).\n\n(*This lemma states that for two natural numbers and a boolean, if the boolean is implied by the second number being less than or equal to the first, then the boolean being false implies that the first number is strictly less than the second.*)\nLemma contraFltn b m n : (n <= m -> b) -> (b = false -> m < n).\n\n(*This lemma, an application of contraposition, states that for a boolean and two natural numbers, if the negation of the boolean implies the first number is strictly less than the second, then the second number being less than or equal to the first implies the boolean is true.*)\nLemma contra_leqT b m n : (~~ b -> m < n) -> (n <= m -> b).\n\n(*This lemma states by contraposition that for a boolean and two natural numbers, if the negation of the boolean implies the first number is less than or equal to the second, then the second number being strictly less than the first implies the boolean is true.*)\nLemma contra_ltnT b m n : (~~ b -> m <= n) -> (n < m -> b).\n\n(*This lemma states by contraposition that for a boolean and two natural numbers, if the boolean implies the first number is strictly less than the second, then the second number being less than or equal to the first implies the boolean is false.*)\nLemma contra_leqN b m n : (b -> m < n) -> (n <= m -> ~~ b).\n\n(*This lemma states by contraposition that for a boolean and two natural numbers, if the boolean implies the first number is less than or equal to the second, then the second number being strictly less than the first implies the boolean is false.*)\nLemma contra_ltnN b m n : (b -> m <= n) -> (n < m -> ~~ b).\n\n(*This lemma states by contraposition that for a proposition and two natural numbers, if the proposition implies the first number is strictly less than the second, then the second number being less than or equal to the first implies the negation of the proposition.*)\nLemma contra_leq_not P m n : (P -> m < n) -> (n <= m -> ~ P).\n\n(*This lemma states by contraposition that for a proposition and two natural numbers, if the proposition implies the first number is less than or equal to the second, then the second number being strictly less than the first implies the negation of the proposition.*)\nLemma contra_ltn_not P m n : (P -> m <= n) -> (n < m -> ~ P).\n\n(*This lemma states that for a boolean and two natural numbers, if the boolean being true implies the first number is strictly less than the second, then the second number being less than or equal to the first implies the boolean is false.*)\nLemma contra_leqF b m n : (b -> m < n) -> (n <= m -> b = false).\n\n(*This lemma states that for a boolean and two natural numbers, if the boolean being true implies the first number is less than or equal to the second, then the second number being strictly less than the first implies the boolean is false.*)\nLemma contra_ltnF b m n : (b -> m <= n) -> (n < m -> b = false).\n\n(*This lemma states by contraposition that for four natural numbers, if it holds that the fourth being strictly less than the third implies the second is strictly less than the first, then it also holds that the first being less than or equal to the second implies the third is less than or equal to the fourth.*)\nLemma contra_leq m n p q : (q < p -> n < m) -> (m <= n -> p <= q).\n\n(*This lemma states by contraposition that for four natural numbers, if it holds that the fourth being less than or equal to the third implies the second is strictly less than the first, then it also holds that the first being less than or equal to the second implies the third is strictly less than the fourth.*)\nLemma contra_leq_ltn m n p q : (q <= p -> n < m) -> (m <= n -> p < q).\n\n(*This lemma states that for any four natural numbers, if the proposition 'if the fourth number is strictly less than the third, then the second number is less than or equal to the first' holds, then it implies that 'if the first number is strictly less than the second, then the third number is less than or equal to the fourth'.*)\nLemma contra_ltn_leq m n p q : (q < p -> n <= m) -> (m < n -> p <= q).\n\n(*This lemma states that for any four natural numbers, if the proposition 'if the fourth number is less than or equal to the third, then the second number is less than or equal to the first' holds, then it implies that 'if the first number is strictly less than the second, then the third number is strictly less than the fourth'.*)\nLemma contra_ltn m n p q : (q <= p -> n <= m) -> (m < n -> p < q).\n\nEnd ContraLeq.\n\nSection Monotonicity.\nVariable T : Type.\n\n(*This lemma establishes that a function from a convex subset of natural numbers to a generic type with a transitive relation is order-preserving with respect to strict inequality. If the function preserves the relation between any element in the subset and its successor, provided the successor is also in the subset, then it preserves the relation for any two elements in the subset where the first is strictly less than the second.*)\nLemma homo_ltn_in (D : {pred nat}) (f : nat -> T) (r : T -> T -> Prop) :\n (forall y x z, r x y -> r y z -> r x z) ->\n {in D &, forall i j k, i < k < j -> k \\in D} ->\n {in D, forall i, i.+1 \\in D -> r (f i) (f i.+1)} ->\n {in D &, {homo f : i j / i < j >-> r i j}}.\n\n(*This lemma provides a general induction principle for functions from natural numbers. It states that if a function to a type equipped with a transitive relation preserves that relation for every natural number and its successor, then the function preserves the relation for any pair of natural numbers where the first is strictly less than the second.*)\nLemma homo_ltn (f : nat -> T) (r : T -> T -> Prop) :\n (forall y x z, r x y -> r y z -> r x z) ->\n (forall i, r (f i) (f i.+1)) -> {homo f : i j / i < j >-> r i j}.\n\n(*This lemma establishes that a function from a convex subset of natural numbers to a generic type with a reflexive and transitive relation is order-preserving. If the function preserves the relation between any element in the subset and its successor, provided the successor is also in the subset, then it preserves the relation for any two elements in the subset where the first is less than or equal to the second.*)\nLemma homo_leq_in (D : {pred nat}) (f : nat -> T) (r : T -> T -> Prop) :\n (forall x, r x x) -> (forall y x z, r x y -> r y z -> r x z) ->\n {in D &, forall i j k, i < k < j -> k \\in D} ->\n {in D, forall i, i.+1 \\in D -> r (f i) (f i.+1)} ->\n {in D &, {homo f : i j / i <= j >-> r i j}}.\n\n(*This lemma provides a general induction principle for functions from natural numbers. It states that if a function to a type equipped with a reflexive and transitive relation preserves that relation for every natural number and its successor, then the function preserves the relation for any pair of natural numbers where the first is less than or equal to the second.*)\nLemma homo_leq (f : nat -> T) (r : T -> T -> Prop) :\n (forall x, r x x) -> (forall y x z, r x y -> r y z -> r x z) ->\n (forall i, r (f i) (f i.+1)) -> {homo f : i j / i <= j >-> r i j}.\n\nSection NatToNat.\nVariable (f : nat -> nat).\n\n(*This lemma states that for any two natural numbers, the first being strictly less than the second is equivalent to the first being not equal to the second and also less than or equal to the second.*)\nLet ltn_neqAle := ltn_neqAle.\n(*This lemma states that for any two natural numbers, the first being strictly greater than the second is equivalent to the first being not equal to the second and also greater than or equal to the second.*)\nLet gtn_neqAge x y : (y < x) = (x != y) && (y <= x).\n\n(*This lemma states the antisymmetry property of the less-than-or-equal-to relation on natural numbers: if a first natural number is less than or equal to a second, and the second is also less than or equal to the first, then they must be equal.*)\nLet anti_leq := anti_leq.\n(*This lemma states the antisymmetry property of the greater-than-or-equal-to relation on natural numbers: if a first natural number is greater than or equal to a second, and the second is also greater than or equal to the first, then they must be equal.*)\nLet anti_geq : antisymmetric geq.\n\n(*This lemma states that the less-than-or-equal-to relation on natural numbers is total, meaning that for any pair of natural numbers, either the first is less than or equal to the second, or the second is less than or equal to the first.*)\nLet leq_total := leq_total.\n\n(*This lemma states that if a function from natural numbers to natural numbers is strictly increasing, meaning it maps strictly smaller inputs to strictly smaller outputs, then it is also non-decreasing, meaning it maps smaller or equal inputs to smaller or equal outputs.*)\nLemma ltnW_homo : {homo f : m n / m < n} -> {homo f : m n / m <= n}.\n\n(*This lemma asserts that an injective, non-decreasing function from natural numbers to natural numbers must be strictly increasing. That is, if a function never maps distinct inputs to the same output and maps smaller or equal inputs to smaller or equal outputs, then it must map strictly smaller inputs to strictly smaller outputs.*)\nLemma inj_homo_ltn : injective f -> {homo f : m n / m <= n} ->\n {homo f : m n / m < n}.\n\n(*This lemma states that if a function from natural numbers to natural numbers is strictly decreasing, meaning it maps strictly smaller inputs to strictly larger outputs, then it is also non-increasing, meaning it maps smaller or equal inputs to larger or equal outputs.*)\nLemma ltnW_nhomo : {homo f : m n /~ m < n} -> {homo f : m n /~ m <= n}.\n\n(*This lemma asserts that an injective, non-increasing function from natural numbers to natural numbers must be strictly decreasing. That is, if a function never maps distinct inputs to the same output and maps smaller or equal inputs to larger or equal outputs, then it must map strictly smaller inputs to strictly larger outputs.*)\nLemma inj_nhomo_ltn : injective f -> {homo f : m n /~ m <= n} ->\n {homo f : m n /~ m < n}.\n\n(*This lemma states that a function from natural numbers to natural numbers that reflects the less-than-or-equal-to relation is injective. Specifically, if the condition that the function's value at a first number is less than or equal to its value at a second number is equivalent to the first number being less than or equal to the second, then the function cannot map distinct inputs to the same output.*)\nLemma incn_inj : {mono f : m n / m <= n} -> injective f.\n\n(*This lemma states that a function from natural numbers to natural numbers that reverses the less-than-or-equal-to relation is injective. Specifically, if the condition that the function's value at a first number is less than or equal to its value at a second number is equivalent to the second number being less than or equal to the first, then the function cannot map distinct inputs to the same output.*)\nLemma decn_inj : {mono f : m n /~ m <= n} -> injective f.\n\n(*This lemma states that if a function from natural numbers to natural numbers reflects the less-than-or-equal-to relation, it also reflects the strict less-than relation. In other words, if the property of being less than or equal is preserved and reflected by the function, then the property of being strictly less than is also preserved and reflected.*)\nLemma leqW_mono : {mono f : m n / m <= n} -> {mono f : m n / m < n}.\n\n(*This lemma asserts that a function from one natural number to another that is a strict anti-morphism with respect to the less-than-or-equal-to relation is also a strict anti-morphism with respect to the strict less-than relation.*)\nLemma leqW_nmono : {mono f : m n /~ m <= n} -> {mono f : m n /~ m < n}.\n\n(*This lemma states that a function from one natural number to another which is a homomorphism for the strict less-than relation is also a strict morphism for the less-than-or-equal-to relation.*)\nLemma leq_mono : {homo f : m n / m < n} -> {mono f : m n / m <= n}.\n\n(*This lemma states that a function from a natural number to another which is an anti-homomorphism for the strict less-than relation is also a strict anti-morphism for the less-than-or-equal-to relation.*)\nLemma leq_nmono : {homo f : m n /~ m < n} -> {mono f : m n /~ m <= n}.\n\nVariables (D D' : {pred nat}).\n\n(*This lemma states that for functions between subsets of natural numbers, being a homomorphism for the strict less-than relation implies also being a homomorphism for the less-than-or-equal-to relation.*)\nLemma ltnW_homo_in : {in D & D', {homo f : m n / m < n}} ->\n {in D & D', {homo f : m n / m <= n}}.\n\n(*This lemma states that for functions between subsets of natural numbers, being an anti-homomorphism for the strict less-than relation implies also being an anti-homomorphism for the less-than-or-equal-to relation.*)\nLemma ltnW_nhomo_in : {in D & D', {homo f : m n /~ m < n}} ->\n {in D & D', {homo f : m n /~ m <= n}}.\n\n(*This lemma states that an injective function between subsets of natural numbers that is a homomorphism for the less-than-or-equal-to relation is also a homomorphism for the strict less-than relation.*)\nLemma inj_homo_ltn_in : {in D & D', injective f} ->\n {in D & D', {homo f : m n / m <= n}} ->\n {in D & D', {homo f : m n / m < n}}.\n\n(*This lemma states that an injective function between subsets of natural numbers that is an anti-homomorphism for the less-than-or-equal-to relation is also an anti-homomorphism for the strict less-than relation.*)\nLemma inj_nhomo_ltn_in : {in D & D', injective f} ->\n {in D & D', {homo f : m n /~ m <= n}} ->\n {in D & D', {homo f : m n /~ m < n}}.\n\n(*This lemma asserts that a strictly increasing function between subsets of natural numbers is necessarily injective.*)\nLemma incn_inj_in : {in D &, {mono f : m n / m <= n}} ->\n {in D &, injective f}.\n\n(*This lemma asserts that a strictly decreasing function between subsets of natural numbers is necessarily injective.*)\nLemma decn_inj_in : {in D &, {mono f : m n /~ m <= n}} ->\n {in D &, injective f}.\n\n(*This lemma states that for functions between subsets of natural numbers, being a strict morphism for the less-than-or-equal-to relation implies also being a strict morphism for the strict less-than relation.*)\nLemma leqW_mono_in : {in D &, {mono f : m n / m <= n}} ->\n {in D &, {mono f : m n / m < n}}.\n\n(*This lemma states that for functions between subsets of natural numbers, being a strict anti-morphism for the less-than-or-equal-to relation implies also being a strict anti-morphism for the strict less-than relation.*)\nLemma leqW_nmono_in : {in D &, {mono f : m n /~ m <= n}} ->\n {in D &, {mono f : m n /~ m < n}}.\n\n(*This lemma states that for functions between subsets of natural numbers, being a homomorphism for the strict less-than relation implies also being a strict morphism for the less-than-or-equal-to relation.*)\nLemma leq_mono_in : {in D &, {homo f : m n / m < n}} ->\n {in D &, {mono f : m n / m <= n}}.\n\n(*This lemma states that for functions between subsets of natural numbers, being an anti-homomorphism for the strict less-than relation implies also being a strict anti-morphism for the less-than-or-equal-to relation.*)\nLemma leq_nmono_in : {in D &, {homo f : m n /~ m < n}} ->\n {in D &, {mono f : m n /~ m <= n}}.\n\nEnd NatToNat.\nEnd Monotonicity.\n\n(*This lemma states that the factorial function is non-decreasing when its input is a positive natural number.*)\nLemma leq_pfact : {in [pred n | 0 < n] &, {mono factorial : m n / m <= n}}.\n\n(*This lemma states that the factorial function is a non-decreasing homomorphism over the natural numbers with respect to the less-than-or-equal-to relation.*)\nLemma leq_fact : {homo factorial : m n / m <= n}.\n\n(*This lemma asserts that the factorial function is strictly increasing for positive natural number inputs.*)\nLemma ltn_pfact : {in [pred n | 0 < n] &, {mono factorial : m n / m < n}}.\n\nModule NatTrec.\n\n(*This fixpoint defines a tail-recursive function for the addition of two natural numbers.*)\nFixpoint add m n := if m is m'.+1 then m' + n.+1 else n\nwhere \"n + m\" := (add n m) : nat_scope.\n\n(*This fixpoint defines a tail-recursive helper function that computes the result of multiplying two natural numbers and then adding a third natural number.*)\nFixpoint add_mul m n s := if m is m'.+1 then add_mul m' n (n + s) else s.\n\n(*This definition implements tail-recursive multiplication of two natural numbers.*)\nDefinition mul m n := if m is m'.+1 then add_mul m' n n else 0.\n\n(*This notation provides the standard infix symbol for the multiplication of two natural numbers.*)\nNotation \"n * m\" := (mul n m) : nat_scope.\n\n(*This fixpoint defines a tail-recursive helper function that computes the result of raising a natural number to the power of another, and then multiplying by a third natural number.*)\nFixpoint mul_exp m n p := if n is n'.+1 then mul_exp m n' (m * p) else p.\n\n(*This definition implements tail-recursive exponentiation, computing a natural number raised to the power of another.*)\nDefinition exp m n := if n is n'.+1 then mul_exp m n' m else 1.\n\n(*This notation provides the standard infix symbol for raising a natural number to the power of another natural number.*)\nNotation \"n ^ m\" := (exp n m) : nat_scope.\n\n(*This notation is an alias for the `odd` predicate.*)\nLocal Notation oddn := odd.\n(*This fixpoint defines a tail-recursive boolean function that determines if a given natural number is odd.*)\nFixpoint odd n := if n is n'.+2 then odd n' else eqn n 1.\n\n(*This notation is an alias for the `double` function.*)\nLocal Notation doublen := double.\n(*This definition provides a tail-recursive function that computes twice the value of a given natural number.*)\nDefinition double n := if n is n'.+1 then n' + n.+1 else 0.\n(*This notation defines a postfix operator that computes twice the value of a given natural number.*)\nNotation \"n .*2\" := (double n) : nat_scope.\n\n(*This lemma states that the high-level binary function for addition on natural numbers produces the same results as its corresponding primitive implementation.*)\nLemma addE : add =2 addn.\n\n(*This lemma states that the high-level unary function for doubling a natural number produces the same results as its corresponding primitive implementation.*)\nLemma doubleE : double =1 doublen.\n\n(*This lemma states that the fused operation of multiplying two natural numbers and then adding a third produces the same result as composing the primitive multiplication and primitive addition functions.*)\nLemma add_mulE n m s : add_mul n m s = addn (muln n m) s.\n\n(*This lemma states that the high-level binary function for multiplication on natural numbers produces the same results as its corresponding primitive implementation.*)\nLemma mulE : mul =2 muln.\n\n(*This lemma states that the fused operation of raising one natural number to the power of a second and then multiplying by a third produces the same result as composing the primitive exponentiation and primitive multiplication functions.*)\nLemma mul_expE m n p : mul_exp m n p = muln (expn m n) p.\n\n(*This lemma states that the high-level binary function for exponentiation on natural numbers produces the same results as its corresponding primitive implementation.*)\nLemma expE : exp =2 expn.\n\n(*This lemma states that the high-level unary predicate for checking if a natural number is odd produces the same results as its corresponding primitive implementation.*)\nLemma oddE : odd =1 oddn.\n\n(*This definition creates a tuple containing proofs that various arithmetic operations on natural numbers are equivalent to their respective primitive implementations.*)\nDefinition trecE := (addE, (doubleE, oddE), (mulE, add_mulE, (expE, mul_expE))).\n\nEnd NatTrec.\n\n(*This notation provides a shorthand for the tuple of proofs which establish the equivalence between high-level arithmetic functions and their primitive counterparts.*)\nNotation natTrecE := NatTrec.trecE.\n\n(*This definition provides a boolean-valued equality test for numbers in binary representation, returning true if the two input numbers are identical and false otherwise.*)\nDefinition N_eqb n m :=\n match n, m with\n | N0, N0 => true\n | Npos p, Npos q => Pos.eqb p q\n | _, _ => false\n end.\n\n(*This lemma states that the boolean equality test for numbers in binary representation returns true if and only if the two numbers are actually equal.*)\nLemma eq_binP : Equality.axiom N_eqb.\n\nHB.instance Definition _ := hasDecEq.Build N eq_binP.\n\nArguments N_eqb !n !m.\n\nSection NumberInterpretation.\n\nSection Trec.\n\nImport NatTrec.\n\n(*This definition provides a recursive function to convert a number from its positive binary representation to its standard natural number representation.*)\nFixpoint nat_of_pos p0 :=\n match p0 with\n | xO p => (nat_of_pos p).*2\n | xI p => (nat_of_pos p).*2.+1\n | xH => 1\n end.\n\nEnd Trec.\n\nLocal Coercion nat_of_pos : positive >-> nat.\n\nCoercion nat_of_bin b := if b is Npos p then p : nat else 0.\n\n(*This definition provides a recursive helper function to convert a natural number into its positive binary representation, using an accumulator-style implementation.*)\nFixpoint pos_of_nat n0 m0 :=\n match n0, m0 with\n | n.+1, m.+2 => pos_of_nat n m\n | n.+1, 1 => xO (pos_of_nat n n)\n | n.+1, 0 => xI (pos_of_nat n n)\n | 0, _ => xH\n end.\n\n(*This definition provides a function to convert a standard natural number into its binary representation, handling the zero case explicitly and using a helper for positive numbers.*)\nDefinition bin_of_nat n0 := if n0 is n.+1 then Npos (pos_of_nat n n) else N0.\n\n(*This lemma states that converting a number from its binary representation to a standard natural number and then converting it back to its binary representation results in the original binary number.*)\nLemma bin_of_natK : cancel bin_of_nat nat_of_bin.\n\n(*This lemma states that converting a standard natural number to its binary representation and then converting it back to a standard natural number results in the original natural number.*)\nLemma nat_of_binK : cancel nat_of_bin bin_of_nat.\n\n(*This lemma states that computing the successor of a number in positive binary representation and then converting the result to a standard natural number is equivalent to first converting the number to a standard natural number and then computing its successor.*)\nLemma nat_of_succ_pos p : Pos.succ p = p.+1 :> nat.\n\n(*This lemma states that adding two numbers in positive binary representation and then converting the result to a standard natural number is equivalent to first converting each number to a standard natural number and then adding them.*)\nLemma nat_of_add_pos p q : Pos.add p q = p + q :> nat.\n\n(*This lemma states that multiplying two numbers in positive binary representation and then converting the result to a standard natural number is equivalent to first converting each number to a standard natural number and then multiplying them.*)\nLemma nat_of_mul_pos p q : Pos.mul p q = p * q :> nat.\n\nEnd NumberInterpretation.\n\n(*This definition introduces a record type that represents a number, internally storing it in a binary format.*)\nRecord number : Type := Num {bin_of_number :> N}.\n\n(*This definition provides a proof object that establishes a new numeric record type as a distinct subtype of the binary number representation.*)\nDefinition number_subType := Eval hnf in [isNew for bin_of_number].\nHB.instance Definition _ := number_subType.\n(*This notation provides a syntax to construct an element of the custom number type from a standard natural number by first converting it to an internal binary representation.*)\nNotation \"[ 'Num' 'of' e ]\" := (Num (bin_of_nat e))\n (format \"[ 'Num' 'of' e ]\") : nat_scope.\n\nFixpoint pop_succn e := if e is e'.+1 then fun n => pop_succn e' n.+1 else id.\n\n(*This definition introduces a recursive function used inside a tactic to analyze a natural number expression, effectively counting the number of explicit successor operations applied to a base number.*)\nLtac pop_succn e := eval lazy beta iota delta [pop_succn] in (pop_succn e 1).\n\n(*This tactic provides a procedure to automatically rewrite expressions in the proof goal, converting chains of successor operations on natural numbers into an equivalent addition expression.*)\nLtac succn_to_add :=\n match goal with\n | |- context G [?e.+1] =>\n let x := fresh \"NatLit0\" in\n match pop_succn e with\n | ?n.+1 => pose x := n.+1; let G' := context G [x] in change G'\n | _ ?e' ?n => pose x := n; let G' := context G [x + e'] in change G'\n end; succn_to_add; rewrite {}/x\n | _ => idtac\n end.\n\n(*This tactic provides a procedure for normalizing arithmetic expressions involving natural numbers by converting successor chains to sums and then applying standard simplification rules for addition.*)\nLtac nat_norm :=\n succn_to_add; rewrite ?add0n ?addn0 -?addnA ?(addSn, addnS, add0n, addn0).\n\n(*A tactic that applies congruence reasoning to goals involving natural numbers. It aims to prove that two applications of the same function are equal by generating subgoals to prove that their respective arguments are equal.*)\nLtac nat_congr := first\n [ apply: (congr1 succn _)\n | apply: (congr1 predn _)\n | apply: (congr1 (addn _) _)\n | apply: (congr1 (subn _) _)\n | apply: (congr1 (addn^~ _) _)\n | match goal with |- (?X1 + ?X2 = ?X3) =>\n symmetry;\n rewrite -1?(addnC X1) -?(addnCA X1);\n apply: (congr1 (addn X1) _);\n symmetry", - "boot.choice": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nModule CodeSeq.\n\n(*This definition specifies a function that encodes a finite sequence of natural numbers into a single natural number. The encoding is achieved by iteratively combining each number from the sequence with an accumulator, starting from zero, using powers of two.*)\nDefinition code := foldr (fun n m => 2 ^ n * m.*2.+1) 0.\n\n(*This definition specifies a recursive helper function that reconstructs a sequence of natural numbers from three natural number inputs representing the current value, a quotient, and a remainder during the decoding process.*)\nFixpoint decode_rec (v q r : nat) {struct q} :=\n match q, r with\n | 0, _ => [:: v]\n | q'.+1, 0 => v :: [rec 0, q', q']\n | q'.+1, 1 => [rec v.+1, q', q']\n | q'.+1, r'.+2 => [rec v, q', r']\n end where \"[ 'rec' v , q , r ]\" := (decode_rec v q r).\nArguments decode_rec : simpl nomatch.\n\n(*This definition specifies a function that decodes a single natural number back into the finite sequence of natural numbers it represents. It handles the zero case separately and otherwise initiates a recursive decoding process.*)\nDefinition decode n := if n is 0 then [::] else [rec 0, n.-1, n.-1].\n\n(*This lemma states that applying the decoding function to the result of encoding a sequence of natural numbers yields the original sequence.*)\nLemma decodeK : cancel decode code.\n\n(*This lemma states that applying the encoding function to the result of decoding a natural number yields the original natural number.*)\nLemma codeK : cancel code decode.\n\n(*This lemma states that for any given finite sequence of natural numbers, every number within that sequence is strictly less than the single natural number that results from encoding the sequence.*)\nLemma ltn_code s : all (fun j => j < code s) s.\n\n(*This lemma states that for any given natural number, all numbers in the sequence resulting from decoding it are strictly smaller than the original natural number.*)\nLemma gtn_decode n : all (ltn^~ n) (decode n).\n\nEnd CodeSeq.\n\nSection OtherEncodings.\n\nVariables T T1 T2 : Type.\n\n(*This definition specifies a function that converts an optional value into a finite sequence. If the input is an actual value, the function returns a sequence containing only that value; if the input is none, it returns an empty sequence.*)\nDefinition seq_of_opt := @oapp T _ (nseq 1) [::].\n(*This lemma states that converting the optional head of a sequence of length at most one back into a sequence results in the original sequence.*)\nLemma seq_of_optK : cancel seq_of_opt ohead. \n\n(*This definition specifies a function that converts a standard pair of two values into a dependent pair where the type of the second component is formally indexed by the value of the first component.*)\nDefinition tag_of_pair (p : T1 * T2) := @Tagged T1 p.1 (fun _ => T2) p.2.\n(*This definition specifies a function that converts a dependent pair, where the type of the second component is indexed by the first, back into a standard pair of two values.*)\nDefinition pair_of_tag (u : {i : T1 & T2}) := (tag u, tagged u).\n(*This lemma states that converting a dependent pair to a standard pair and then back to a dependent pair yields the original dependent pair.*)\nLemma tag_of_pairK : cancel tag_of_pair pair_of_tag. \n(*This lemma states that converting a standard pair to a dependent pair and then back to a standard pair yields the original standard pair.*)\nLemma pair_of_tagK : cancel pair_of_tag tag_of_pair. \n\n(*This definition specifies a function that converts a value from a sum type into a pair of optional values. If the input is from the left side of the sum, it returns a pair with the value in the first component and none in the second; if from the right, it returns none in the first component and the value in the second.*)\nDefinition opair_of_sum (s : T1 + T2) :=\n match s with inl x => (Some x, None) | inr y => (None, Some y) end.\n(*This definition specifies a function that converts a pair of optional values into an optional sum type value. If the first component of the pair contains a value and the second is none, it returns the value injected into the left of the sum; if the second contains a value and the first is none, it returns the value injected into the right; otherwise, it returns none.*)\nDefinition sum_of_opair p :=\n oapp (some \\o @inr T1 T2) (omap (@inl _ T2) p.1) p.2.\n(*This lemma states that converting a sum type value to a pair of optional values and then converting it back to a sum type results in the original sum type value, wrapped in an option.*)\nLemma opair_of_sumK : pcancel opair_of_sum sum_of_opair. \n\n(*This lemma asserts a cancellation property between a function from the unit type to the boolean value true, and a function from any boolean to the unit value.*)\nLemma bool_of_unitK : cancel (fun _ => true) (fun _ => tt).\n\nEnd OtherEncodings.\n\nPrenex Implicits seq_of_opt tag_of_pair pair_of_tag opair_of_sum sum_of_opair.\nPrenex Implicits seq_of_optK tag_of_pairK pair_of_tagK opair_of_sumK.\n\nModule GenTree.\n\nSection Def.\n\nVariable T : Type.\n\nUnset Elimination Schemes.\n(*This definition introduces an inductive type for a generic tree structure. A tree is either a leaf, containing a single value of a given type, or an internal node, which holds a natural number and a finite sequence of subtrees.*)\nInductive tree := Leaf of T | Node of nat & seq tree.\n\n(*This definition specifies a custom recursion principle for the generic tree type. It allows defining a function that computes a result for any given tree by specifying how to handle leaf nodes and how to combine the results from all subtrees of an internal node.*)\nDefinition tree_rect K IH_leaf IH_node :=\n fix loop t : K t := match t with\n | Leaf x => IH_leaf x\n | Node n f0 =>\n let fix iter_pair f : foldr (fun t => prod (K t)) unit f :=\n if f is t :: f' then (loop t, iter_pair f') else tt in\n IH_node n f0 (iter_pair f0)\n end.\n(*This definition provides a dependent recursion principle for the generic tree type, which is an alias of the standard recursion principle, for cases where the return type of the recursive function depends on the input tree.*)\nDefinition tree_rec (K : tree -> Set) := @tree_rect K.\n(*This definition specifies a custom induction principle for the generic tree type. It allows proving a property for all trees by providing a proof for leaf nodes and a proof for internal nodes, assuming the property holds for all of its subtrees.*)\nDefinition tree_ind K IH_leaf IH_node :=\n fix loop t : K t : Prop := match t with\n | Leaf x => IH_leaf x\n | Node n f0 =>\n let fix iter_conj f : foldr (fun t => and (K t)) True f :=\n if f is t :: f' then conj (loop t) (iter_conj f') else Logic.I\n in IH_node n f0 (iter_conj f0)\n end.\n\n(*This definition specifies a function that encodes a generic tree into a linear sequence of values. Leaf values are injected directly into the sequence, while internal nodes are represented by their numeric label and a special marker, with the encodings of their children appearing recursively.*)\nFixpoint encode t : seq (nat + T) :=\n match t with\n | Leaf x => [:: inr _ x]\n | Node n f => inl _ n.+1 :: rcons (flatten (map encode f)) (inl _ 0)\n end.\n\n(*This definition specifies a single step in the process of decoding a tree from a sequence. It takes one element from the encoded sequence and an accumulator state, and updates the state by either creating a leaf, completing a list of sibling subtrees, or constructing an internal node from a completed list of its children.*)\nDefinition decode_step c fs :=\n match c with\n | inr x => (Leaf x :: fs.1, fs.2)\n | inl 0 => ([::], fs.1 :: fs.2)\n | inl n.+1 => (Node n fs.1 :: head [::] fs.2, behead fs.2)\n end.\n\n(*This function reconstructs a generic tree from its encoded representation as a sequence. It acts as a partial inverse to the `encode` function, returning the corresponding tree if the input sequence is a valid encoding, or no value otherwise.*)\nDefinition decode c := ohead (foldr decode_step ([::], [::]) c).1.\n\n(*This lemma establishes a partial cancellation property between an encode function and a decode function, stating that applying the decode function after the encode function returns the original element.*)\nLemma codeK : pcancel encode decode.\n\nEnd Def.\n\nEnd GenTree.\nArguments GenTree.codeK : clear implicits.\n\nHB.instance Definition _ (T : eqType) := Equality.copy (GenTree.tree T)\n (pcan_type (GenTree.codeK T)).\n\n(*This record specifies the properties required for a type to support a choice operator. It bundles a search function with proofs of its correctness, completeness, and extensionality.*)\nHB.mixin Record hasChoice T := Mixin {\n find_subdef : pred T -> nat -> option T;\n choice_correct_subdef {P n x} : find_subdef P n = Some x -> P x;\n choice_complete_subdef {P : pred T} :\n (exists x, P x) -> exists n, find_subdef P n;\n choice_extensional_subdef {P Q : pred T} :\n P =1 Q -> find_subdef P =1 find_subdef Q\n}.\n\n#[short(type=\"choiceType\")]\n(*This structure represents a type equipped with both a constructive choice mechanism and a decidable equality. Types satisfying this structure are referred to as choice types.*)\nHB.structure Definition Choice := { T of hasChoice T & hasDecEq T}.\n\nModule Export ChoiceNamespace.\n Module Choice.\n\n Module InternalTheory.\n\n(*This notation refers to a function that, given a predicate and a natural number, attempts to find an element that satisfies the predicate, returning an optional value.*)\n Notation find := find_subdef.\n\n(*This notation refers to the property asserting that if the `find` function successfully returns an element for a given predicate, then that element indeed satisfies the predicate.*)\n Notation correct := choice_correct_subdef.\n Arguments correct {_ _ _ _}.\n\n(*This notation refers to the property asserting that if at least one element exists that satisfies a given predicate, then there must exist a natural number for which the `find` function will successfully return an element.*)\n Notation complete := choice_complete_subdef.\n Arguments complete {_ _}.\n\n(*This notation refers to the property that the `find` function is extensional, meaning it behaves identically for any two predicates that are satisfied by the exact same collection of elements.*)\n Notation extensional := choice_extensional_subdef.\n Arguments extensional {_ _ _}.\n\n Section InternalTheory.\n\n Variable T : Choice.type.\n Implicit Types P Q : pred T.\n\n(*This lemma provides the constructive proof for selecting a witness for a given predicate on a choice type. It establishes the existence of an element that is found by the `find` function at the smallest natural number index for which the search is successful.*)\n Fact xchoose_subproof P exP :\n {x | find P (ex_minn (@choice_complete_subdef _ P exP)) = Some x}.\n \n\n End InternalTheory.\n End InternalTheory.\n End Choice.\nEnd ChoiceNamespace.\n\nSection ChoiceTheory.\n\nImplicit Type T : choiceType.\nImport Choice.InternalTheory CodeSeq.\n(*This is a local notation for the `decode` function, used within the theory of choice types to map elements from a canonical representation back to their original type.*)\nLocal Notation dc := decode.\n\nSection OneType.\n\nVariable T : choiceType.\nImplicit Types P Q : pred T.\n\n(*This definition provides a dependent choice function. Given a predicate and a proof that there exists an element satisfying it, this function returns a specific element that is guaranteed to satisfy the predicate.*)\nDefinition xchoose P exP := sval (@xchoose_subproof T P exP).\n\n(*This lemma states that the element returned by the `xchoose` function for a given predicate is guaranteed to satisfy that predicate.*)\nLemma xchooseP P exP : P (@xchoose P exP).\n\n(*This lemma states that the `xchoose` function is extensional. If two predicates are extensionally equal, meaning they hold for the same set of elements, then applying `xchoose` to each of them yields the same element.*)\nLemma eq_xchoose P Q exP exQ : P =1 Q -> @xchoose P exP = @xchoose Q exQ.\n\n(*This lemma provides a witness for an existential proposition. It converts a proof that there exists an element satisfying a predicate into a dependent pair containing such an element and a proof of the property.*)\nLemma sigW P : (exists x, P x) -> {x | P x}.\n\n(*This lemma provides a witness for a compound existential proposition. It converts a proof that there exists an element satisfying two predicates simultaneously into a dependent pair containing such an element and a proof of this fact.*)\nLemma sig2W P Q : (exists2 x, P x & Q x) -> {x | P x & Q x}.\n\n(*This lemma provides a witness for an existential proposition involving an equality. It converts a proof that there exists an element for which two functions yield the same value into a dependent pair containing such an element and a proof of the equality.*)\nLemma sig_eqW (vT : eqType) (lhs rhs : T -> vT) :\n (exists x, lhs x = rhs x) -> {x | lhs x = rhs x}.\n\n(*This lemma provides a witness for a compound existential proposition involving a predicate and an equality. It converts a proof that there exists an element that satisfies a predicate and for which two functions yield the same value into a dependent pair containing such an element and a proof of these properties.*)\nLemma sig2_eqW (vT : eqType) (P : pred T) (lhs rhs : T -> vT) :\n (exists2 x, P x & lhs x = rhs x) -> {x | P x & lhs x = rhs x}.\n\n(*This definition provides a non-dependent choice function. Given a predicate and a default value, it returns an element satisfying the predicate if one is known to exist; otherwise, it returns the default value.*)\nDefinition choose P x0 :=\n if insub x0 : {? x | P x} is Some (exist x Px) then\n xchoose (ex_intro [eta P] x Px)\n else x0.\n\n(*This lemma states that if a given predicate holds for the default argument of the `choose` function, then the predicate will also hold for the element returned by `choose`.*)\nLemma chooseP P x0 : P x0 -> P (choose P x0).\n\n(*This lemma states that the element returned by the `choose` function depends only on the predicate, not on the provided default value, provided the predicate is satisfiable. If the predicate holds for two different default values, the `choose` function will return the same element in both cases.*)\nLemma choose_id P x0 y0 : P x0 -> P y0 -> choose P x0 = choose P y0.\n\n(*This lemma states that the `choose` function is extensional. If two predicates are extensionally equal, then the corresponding `choose` functions will behave identically when given the same default value.*)\nLemma eq_choose P Q : P =1 Q -> choose P =1 choose Q.\n\nSection CanChoice.\n\nVariables (sT : Type) (f : sT -> T).\n\n(*This lemma states that a type can be given a choice structure if it admits a function to a known choice type that has a left inverse. This allows transferring the choice property from one type to another.*)\nLemma PCanHasChoice f' : pcancel f f' -> hasChoice sT.\n\n(*This definition provides a way to construct a proof of `hasChoice` for a type, given a function to a choice type and a proof that this function has a left inverse.*)\nDefinition CanHasChoice f' (fK : cancel f f') :=\n PCanHasChoice (can_pcan fK).\n\nHB.instance Definition _ f' (fK : pcancel f f') : hasChoice (pcan_type fK) :=\n PCanHasChoice fK.\n(*This fact asserts that the type of finite sequences whose elements are of a choice type is itself a choice type.*)\nFact seq_hasChoice : hasChoice (seq T).\n\n(*This fact asserts that a dependent pair type (a sigma-type) is a choice type, provided that the index type and all types in the family are choice types.*)\nFact tagged_hasChoice : hasChoice {i : I & T_ i}.\n\n(*This fact asserts that the type of natural numbers has a choice structure.*)\nFact nat_hasChoice : hasChoice nat.\n\nHB.instance Definition _ := nat_hasChoice.\n\nHB.instance Definition _ := Choice.copy bool (can_type oddb).\nHB.instance Definition _ := Choice.on bitseq.\n\nHB.instance Definition _ := Choice.copy unit (can_type bool_of_unitK).\n\nHB.instance Definition _ := Choice.copy void (pcan_type (of_voidK unit)).\n\nHB.instance Definition _ T :=\n Choice.copy (option T) (can_type (@seq_of_optK (Choice.sort T))).\n\nHB.instance Definition _ (T1 T2 : choiceType) :=\n Choice.copy (T1 * T2)%type (can_type (@tag_of_pairK T1 T2)).\n\nHB.instance Definition _ (T1 T2 : choiceType) :=\n Choice.copy (T1 + T2)%type (pcan_type (@opair_of_sumK T1 T2)).\n\n(*This structure defines a choice type that is also a subtype of another type. It bundles a choice type with a proof that it is a subtype of a given type with respect to a predicate.*)\nHB.structure Definition SubChoice T (P : pred T) :=\n { sT of Choice sT & isSub T P sT }.\n\nPrenex Implicits xchoose choose.\n(*This notation provides a convenient syntax for creating a choice type from a subtype of an existing choice type. It equips the set of elements of a type that satisfy a given predicate with the induced choice structure.*)\nNotation \"[ 'Choice' 'of' T 'by' <: ]\" := (Choice.copy T%type (sub_type T%type))\n (format \"[ 'Choice' 'of' T 'by' <: ]\") : form_scope.\n\nHB.instance Definition _ (T : choiceType) (P : pred T) :=\n [Choice of {x | P x} by <:].\n\n(*This record is a mixin that combines the properties of being a choice type and being a countable type. It is used to define structures on types that have both a choice operator and a mapping to natural numbers.*)\nHB.mixin Record Choice_isCountable (T : Type) : Type := {\n pickle : T -> nat;\n unpickle : nat -> option T;\n pickleK : pcancel pickle unpickle\n}.\nArguments Choice_isCountable.axioms_ T%_type_scope.\n\n#[short(type=\"countType\")]\n(*This structure describes a countable type, which is a type whose elements can be injectively mapped to natural numbers and optionally recovered from them.*)\nHB.structure Definition Countable := { T of Choice T & Choice_isCountable T }.\n\n(*This record provides the necessary components to establish that a type is countable, namely a function mapping elements to natural numbers, a partial inverse function from natural numbers back to elements, and a proof that this pair forms a partial cancellation.*)\nHB.factory Record isCountable (T : Type) : Type := {\n pickle : T -> nat;\n unpickle : nat -> option T;\n pickleK : pcancel pickle unpickle\n}.\nHB.builders Context T of isCountable T.\n HB.instance Definition _ := Equality.copy T (pcan_type pickleK).\n HB.instance Definition _ := PCanHasChoice pickleK.\n(*This definition provides a refined inverse for the 'pickle' function. Given a natural number, it first attempts to 'unpickle' it into an element, and then verifies that 'pickling' this element yields the original natural number. It returns the element only if this check succeeds, otherwise it returns nothing.*)\nDefinition pickle_inv n :=\n obind (fun x : T => if pickle x == n then Some x else None) (unpickle n).\n\n(*This lemma states that the 'pickle_inv' function acts as a one-sided inverse to the 'pickle' function, meaning that composing 'pickle' with 'pickle_inv' successfully recovers the original element.*)\nLemma pickle_invK : ocancel pickle_inv pickle.\n\n(*This lemma states that the 'pickle' function is a partial left inverse to the 'pickle_inv' function. Specifically, if 'pickle_inv' successfully maps a natural number to an element, then applying 'pickle' to that element will recover the original natural number.*)\nLemma pickleK_inv : pcancel pickle pickle_inv.\n\n(*This lemma states that if a pair of functions between two types forms a partial cancellation, then composing these functions with the 'pickle' and 'unpickle' functions of a countable type preserves the partial cancellation property for the resulting composite functions.*)\nLemma pcan_pickleK sT f f' :\n @pcancel T sT f f' -> pcancel (pickle \\o f) (pcomp f' unpickle).\n\n(*This definition constructs a proof that a given type is countable, provided there exists a pair of functions forming a partial cancellation between this type and an already established countable type.*)\nDefinition PCanIsCountable sT (f : sT -> T) f' (fK : pcancel f f') :=\n isCountable.Build sT (pcan_pickleK fK).\n\n(*This definition constructs a proof that a given type is countable, provided there exists a pair of functions forming a full cancellation, or bijection, between this type and an already established countable type.*)\nDefinition CanIsCountable sT f f' (fK : cancel f f') :=\n @PCanIsCountable sT _ _ (can_pcan fK).\n\nHB.instance Definition _ sT (f : sT -> T) f' (fK : pcancel f f') :\n isCountable (pcan_type fK) := PCanIsCountable fK.\nHB.instance Definition _ sT (f : sT -> T) f' (fK : cancel f f') :\n isCountable (can_type fK) := CanIsCountable fK.\n\n#[hnf] HB.instance Definition _ (P : pred T) (sT : subType P) :=\n Countable.copy (sub_type sT) (pcan_type valK).\n\n(*This definition provides a 'pickle' function for sequences of elements from a countable type. It operates by first applying the individual element 'pickle' function to each element in the sequence, and then encoding the resulting sequence of natural numbers into a single natural number.*)\nDefinition pickle_seq s := CodeSeq.code (map (@pickle T) s).\n(*This definition provides an 'unpickle' function for sequences. It takes a single natural number, decodes it into a sequence of natural numbers, and then 'unpickles' each of these numbers to form a sequence of elements. The result is a new sequence, wrapped in a success value.*)\nDefinition unpickle_seq n := Some (pmap (@unpickle T) (CodeSeq.decode n)).\n(*This lemma states that the 'pickle_seq' and 'unpickle_seq' functions form a partial cancellation pair. This means that if 'unpickle_seq' successfully decodes a natural number into a sequence of elements, then applying 'pickle_seq' to that sequence will recover the original natural number.*)\nLemma pickle_seqK : pcancel pickle_seq unpickle_seq.\n\n(*This notation provides a convenient way to declare that a type is countable by inheriting the countable structure from its supertype. It is used for subtypes of already-known countable types.*)\nNotation \"[ 'Countable' 'of' T 'by' <: ]\" :=\n (Countable.copy T%type (sub_type T%type))\n (format \"[ 'Countable' 'of' T 'by' <: ]\") : form_scope.\n\nArguments pickle_inv {T} n.\nArguments pickleK {T} x : rename.\nArguments pickleK_inv {T} x.\nArguments pickle_invK {T} n : rename.\n\n#[short(type=\"subCountType\")]\n(*This structure represents a countable subtype, which is a type that is both countable and also a subtype of another given type satisfying a specific predicate.*)\nHB.structure Definition SubCountable T (P : pred T) :=\n { sT of Countable sT & isSub T P sT}.\n\nSection TagCountType.\n\nVariables (I : countType) (T_ : I -> countType).\n\n(*This definition provides a 'pickle' function for a dependent pair, where the first element is a tag from a countable index type and the second element's type depends on the tag. It works by pickling both the tag and the element, forming a two-element sequence of natural numbers, and then encoding this sequence into a single natural number.*)\nDefinition pickle_tagged (u : {i : I & T_ i}) :=\n CodeSeq.code [:: pickle (tag u); pickle (tagged u)].\n(*This definition provides an 'unpickle' function for a dependent pair. It takes a single natural number, decodes it into a sequence of natural numbers, and if this sequence contains exactly two numbers, it attempts to unpickle the first as a tag and the second as an element. If both steps succeed, it reconstructs and returns the dependent pair; otherwise, it returns nothing.*)\nDefinition unpickle_tagged s :=\n if CodeSeq.decode s is [:: ni; nx] then\n obind (fun i => omap (@Tagged I i T_) (unpickle nx)) (unpickle ni)\n else None.\n(*This lemma states that the 'pickle_tagged' and 'unpickle_tagged' functions form a partial cancellation pair for dependent pairs. This ensures that if 'unpickle_tagged' successfully reconstructs a dependent pair from a natural number, then applying 'pickle_tagged' to that pair will yield the original natural number.*)\nLemma pickle_taggedK : pcancel pickle_tagged unpickle_tagged.\n\n(*This lemma provides the proof of partial cancellation needed to establish that the type of natural numbers is countable. It uses the identity function as the 'pickle' map and the 'Some' constructor as the 'unpickle' map.*)\nLemma nat_pickleK : pcancel id (@Some nat). \nHB.instance Definition _ := Choice_isCountable.Build nat nat_pickleK.\n\nHB.instance Definition _ := Countable.copy bool (can_type oddb).\nHB.instance Definition _ := Countable.on bitseq.\n\nHB.instance Definition _ := Countable.copy unit (can_type bool_of_unitK).\n\nHB.instance Definition _ := Countable.copy void\n (pcan_type (of_voidK unit)).\n\nHB.instance Definition _ T := Countable.copy (option T)\n (can_type (@seq_of_optK T)).\n\nHB.instance Definition _ T (P : pred T) := [Countable of {x | P x} by <:].\n\nHB.instance Definition _ T1 T2 :=\n Countable.copy (T1 * T2)%type (can_type (@tag_of_pairK T1 T2)).\n\nHB.instance Definition _ (T1 T2 : countType) :=\n Countable.copy (T1 + T2)%type (pcan_type (@opair_of_sumK T1 T2)).", - "boot.generic_quotient": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat choice.\nFrom mathcomp Require Import seq fintype.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope quotient_scope.\n\nReserved Notation \"\\pi_ Q\" (at level 0, format \"\\pi_ Q\").\nReserved Notation \"\\pi\" (format \"\\pi\").\nReserved Notation \"{pi_ Q a }\" (Q at next level, format \"{pi_ Q a }\").\nReserved Notation \"{pi a }\" (format \"{pi a }\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"x == y %[mod_eq e ]\"\n (no associativity, format \"'[hv ' x '/' == y '/' %[mod_eq e ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"x = y %[mod_eq e ]\"\n (no associativity, format \"'[hv ' x '/' = y '/' %[mod_eq e ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"x != y %[mod_eq e ]\"\n (no associativity, format \"'[hv ' x '/' != y '/' %[mod_eq e ] ']'\").\n#[warning=\"-postfix-notation-not-level-1\"]\nReserved Notation \"x <> y %[mod_eq e ]\"\n (no associativity, format \"'[hv ' x '/' <> y '/' %[mod_eq e ] ']'\").\nReserved Notation \"{eq_quot e }\" (e at level 0, format \"{eq_quot e }\").\n\nDelimit Scope quotient_scope with qT.\nLocal Open Scope quotient_scope.\n\n(*This record defines the properties of a quotient type. It consists of a representative function from the quotient type to a base type, a projection function from the base type to the quotient type, and a proof asserting that applying the projection and then the representative function is equivalent to the identity function on the base type.*)\nHB.mixin Record isQuotient T (qT : Type) := {\n repr_of : qT -> T;\n quot_pi_subdef : T -> qT;\n repr_ofK_subproof : cancel repr_of quot_pi_subdef\n}.\n\n#[short(type=\"quotType\")]\n(*This definition creates a bundled structure that combines a carrier type with the proof that it satisfies the properties of being a quotient of another specified type.*)\nHB.structure Definition Quotient T := { qT of isQuotient T qT }.\nArguments repr_of [T qT] : rename.\n\nSection QuotientDef.\n\nVariable T : Type.\nVariable qT : quotType T.\n(*This definition provides the canonical projection function, which takes an element of a base type and returns its corresponding element in the associated quotient type.*)\nDefinition pi_subdef := @quot_pi_subdef _ qT.\n(*This notation serves as a shorthand for the canonical projection function that maps an element from a base type to its corresponding element in the quotient type.*)\nLocal Notation \"\\pi\" := pi_subdef.\n\n(*This lemma states that applying the projection function to an element of the base type, and then applying the representative function to the result, yields the original element.*)\nLemma repr_ofK : cancel (@repr_of _ _) \\pi.\n\nEnd QuotientDef.\nArguments repr_ofK {T qT}.\n\n(*A globally available, opaque definition of the canonical projection function that maps an element from a base type to its corresponding representation in a quotient type.*)\nHB.lock Definition pi := pi_subdef.\n(*A globally available, opaque definition, aliasing the canonical projection function, that maps an element from a base type to its corresponding representation in a quotient type.*)\nHB.lock Definition mpi := pi_subdef.\n(*A globally available, opaque definition of the representative function, which maps an element from a quotient type to a corresponding element in the base type.*)\nHB.lock Definition repr := repr_of.\n\nArguments pi.body [T]%_type qT%_type.\n(*A notation for applying the projection function associated with a specific quotient type structure, mapping an element from the base type to the specified quotient type.*)\nNotation \"\\pi_ Q\" := (@pi _ Q) : quotient_scope.\n(*A notation for the canonical projection function that maps an element from a base type to its corresponding equivalence class in a quotient type.*)\nNotation \"\\pi\" := (@pi _ _) (only parsing) : quotient_scope.\n(*This notation expresses that the projections of two elements from a base type into a given quotient type are decidably equal.*)\nNotation \"x == y %[mod Q ]\" := (\\pi_Q x == \\pi_Q y) : quotient_scope.\n(*This notation expresses that the projections of two elements from a base type into a given quotient type are propositionally equal.*)\nNotation \"x = y %[mod Q ]\" := (\\pi_Q x = \\pi_Q y) : quotient_scope.\n(*This notation expresses that the projections of two elements from a base type into a given quotient type are decidably not equal.*)\nNotation \"x != y %[mod Q ]\" := (\\pi_Q x != \\pi_Q y) : quotient_scope.\n(*This notation expresses that the projections of two elements from a base type into a given quotient type are propositionally not equal.*)\nNotation \"x <> y %[mod Q ]\" := (\\pi_Q x <> \\pi_Q y) : quotient_scope.\n\n(*A notation for the projection function from a type to its quotient type, which is definitionally equivalent to the standard projection function.*)\nLocal Notation \"\\mpi\" := (@mpi _ _).\nCanonical mpi_unlock := Unlockable mpi.unlock.\nCanonical pi_unlock := Unlockable pi.unlock.\nCanonical repr_unlock := Unlockable repr.unlock.\n\nArguments repr {T qT} x.\n\nSection QuotTypeTheory.\n\nVariable T : Type.\nVariable qT : quotType T.\n\n(*This lemma states that for any element in a base type, the canonical representative of its projection into the quotient type is an element that belongs to the same equivalence class as the original element.*)\nLemma reprK : cancel repr \\pi_qT.\n\n(*This inductive type represents the property that two elements of a base type belong to the same equivalence class in the corresponding quotient type. An instance of this type serves as a proof of their equivalence.*)\nVariant pi_spec (x : T) : T -> Type :=\n PiSpec y of x = y %[mod qT] : pi_spec x y.\n\n(*This lemma states that for any element in a base type, its canonical representative, obtained by projecting it to the quotient type and then taking a representative, is in the same equivalence class as the original element.*)\nLemma piP (x : T) : pi_spec x (repr (\\pi_qT x)).\n\n(*This lemma states that the function denoted by `\\mpi` is definitionally identical to the canonical projection function.*)\nLemma mpiE : \\mpi =1 \\pi_qT.\n\n(*This lemma provides an elimination principle for quotient types, stating that a property holds for all elements of a quotient type if it holds for the projection of every element from the base type.*)\nLemma quotW P : (forall y : T, P (\\pi_qT y)) -> forall x : qT, P x.\n\n(*This lemma provides a specialized elimination principle for quotient types, stating that a property holds for all elements of a quotient type if it holds for the projections of all canonical representatives from the base type.*)\nLemma quotP P : (forall y : T, repr (\\pi_qT y) = y -> P (\\pi_qT y))\n -> forall x : qT, P x.\n\nEnd QuotTypeTheory.\n\nArguments reprK {T qT} x.\n\n(*This structure bundles a value with a proof that this value is equal to a given, fixed value. It is used to carry a value that is known to satisfy a specific equality.*)\nStructure equal_to T (x : T) := EqualTo {\n(*This definition provides the boolean equality test for a quotient type. It returns true if two given elements of the quotient type represent the same equivalence class, and false otherwise.*)\n equal_val : T;\n _ : x = equal_val\n}.\n(*This lemma states that the value contained within an `equal_to` structure is indeed equal to the element it is associated with, as guaranteed by the structure's definition.*)\nLemma equal_toE (T : Type) (x : T) (m : equal_to x) : equal_val m = x.\n\n(*This notation provides an alias for the lemma `equal_toE`, which extracts the value from an `equal_to` structure.*)\nNotation piE := (@equal_toE _ _).\n\nCanonical equal_to_pi T (qT : quotType T) (x : T) :=\n @EqualTo _ (\\pi_qT x) (\\pi x) (erefl _).\n\nArguments EqualTo {T x equal_val}.\n\nSection Morphism.\n\nVariables T U : Type.\nVariable (qT : quotType T).\nVariable (qU : quotType U).\n\nVariable (f : T -> T) (g : T -> T -> T) (p : T -> U) (r : T -> T -> U).\nVariable (fq : qT -> qT) (gq : qT -> qT -> qT) (pq : qT -> U) (rq : qT -> qT -> U).\nVariable (h : T -> U) (hq : qT -> qU).\nHypothesis pi_f : {morph \\pi : x / f x >-> fq x}.\nHypothesis pi_g : {morph \\pi : x y / g x y >-> gq x y}.\nHypothesis pi_p : {mono \\pi : x / p x >-> pq x}.\nHypothesis pi_r : {mono \\pi : x y / r x y >-> rq x y}.\nHypothesis pi_h : forall (x : T), \\pi_qU (h x) = hq (\\pi_qT x).\nVariables (a b : T) (x : equal_to (\\pi_qT a)) (y : equal_to (\\pi_qT b)).\n\n(*This lemma asserts the compatibility of a unary function on a base type with its corresponding function on the quotient type. It states that projecting the result of the base function is equivalent to applying the quotient function to the projection of the input.*)\nLemma pi_morph1 : \\pi (f a) = fq (equal_val x). \n(*This lemma asserts the compatibility of a binary function on a base type with its corresponding function on the quotient type. It states that projecting the result of the base function is equivalent to applying the quotient function to the projections of the two inputs.*)\nLemma pi_morph2 : \\pi (g a b) = gq (equal_val x) (equal_val y). \n(*This lemma states that a unary function from a base type to another type respects the quotient structure, meaning its value at a given element is identical to the value of a corresponding quotient function applied to the element's projection.*)\nLemma pi_mono1 : p a = pq (equal_val x). \n(*This lemma states that a binary function from a base type to another type respects the quotient structure, meaning its value at two given elements is identical to the value of a corresponding quotient function applied to the elements' projections.*)\nLemma pi_mono2 : r a b = rq (equal_val x) (equal_val y). \n(*This lemma asserts that a function between two different base types is a morphism with respect to their quotient structures. It states that projecting the function's output into the target quotient type is equivalent to applying the corresponding quotient function to the projection of the input from the source quotient type.*)\nLemma pi_morph11 : \\pi (h a) = hq (equal_val x). \n\nEnd Morphism.\n\nArguments pi_morph1 {T qT f fq}.\nArguments pi_morph2 {T qT g gq}.\nArguments pi_mono1 {T U qT p pq}.\nArguments pi_mono2 {T U qT r rq}.\nArguments pi_morph11 {T U qT qU h hq}.\n\n(*This notation defines the type of all values that are proven to be equal to the projection of a given element into a specified quotient type.*)\nNotation \"{pi_ Q a }\" := (equal_to (\\pi_Q a)) : quotient_scope.\n(*This notation represents the type of all values that are proven to be equal to the projection of a given element into its contextually inferred quotient type.*)\nNotation \"{pi a }\" := (equal_to (\\pi a)) : quotient_scope.\n\nNotation PiMorph pi_x := (EqualTo pi_x).\nNotation PiMorph1 pi_f :=\n (fun a (x : {pi a}) => EqualTo (pi_morph1 pi_f a x)).\nNotation PiMorph2 pi_g :=\n (fun a b (x : {pi a}) (y : {pi b}) => EqualTo (pi_morph2 pi_g a b x y)).\nNotation PiMono1 pi_p :=\n (fun a (x : {pi a}) => EqualTo (pi_mono1 pi_p a x)).\nNotation PiMono2 pi_r :=\n (fun a b (x : {pi a}) (y : {pi b}) => EqualTo (pi_mono2 pi_r a b x y)).\nNotation PiMorph11 pi_f :=\n (fun a (x : {pi a}) => EqualTo (pi_morph11 pi_f a x)).\n\nNotation lift_op1 Q f := (locked (fun x : Q => \\pi_Q (f (repr x)) : Q)).\nNotation lift_op2 Q g :=\n (locked (fun x y : Q => \\pi_Q (g (repr x) (repr y)) : Q)).\nNotation lift_fun1 Q f := (locked (fun x : Q => f (repr x))).\nNotation lift_fun2 Q g := (locked (fun x y : Q => g (repr x) (repr y))).\nNotation lift_op11 Q Q' f := (locked (fun x : Q => \\pi_Q' (f (repr x)) : Q')).\n\nNotation lift_cst Q x := (locked (\\pi_Q x : Q)).\nNotation PiConst a := (@EqualTo _ _ a (lock _)).\n\nNotation lift_embed qT e := (locked (fun x => \\pi_qT (e x) : qT)).\n\n(*This lemma states that any function is definitionally equal to its eta-expanded form enclosed within a `locked` wrapper, providing a principle for proving function equalities while controlling definitional expansion.*)\nLemma eq_lock T T' e : e =1 (@locked (T -> T') (fun x : T => e x)).\n\nPrenex Implicits eq_lock.\n\nNotation PiEmbed e :=\n (fun x => @EqualTo _ _ (e x) (eq_lock (fun _ => \\pi _) _)).\n\n(*This record defines a mixin for quotient types that are equipped with a decidable equality. It specifies that the equivalence relation on the base type must imply decidable equality for the corresponding projections in the quotient type.*)\nHB.mixin Record isEqQuotient T (eq_quot_op : rel T) (Q : Type) of\n isQuotient T Q & hasDecEq Q := {\n pi_eq_quot : {mono \\pi_Q : x y / eq_quot_op x y >-> x == y}\n}.\n\n#[short(type=\"eqQuotType\")]\n(*This structure defines a quotient type that has a decidable equality which is consistent with the equivalence relation on the base type.*)\nHB.structure Definition EqQuotient T eq_quot_op :=\n {Q of isEqQuotient T eq_quot_op Q & Quotient T Q & hasDecEq Q}.\n\nCanonical pi_eq_quot_mono T eq_quot_op eqT :=\n PiMono2 (@pi_eq_quot T eq_quot_op eqT).\n\n(*This definition provides a function that extracts the underlying carrier type from a quotient type structure, allowing the structure to be used where a plain type is expected.*)\nDefinition quot_type_of T (qT : quotType T) : Type := qT.\nArguments quot_type_of T%_type qT%_type : clear implicits.\nNotation quot_type Q := (quot_type_of _ Q).\nHB.instance Definition _ T (qT : quotType T) := Quotient.on (quot_type qT).\n\nModule QuotSubType.\nSection QuotSubType.\nVariable (T : eqType) (qT : quotType T).\n\n(*This definition introduces a constructor for elements of a quotient type. It takes an element from the base type, along with a proof that this element is a canonical representative, and yields its projection into the quotient type.*)\nDefinition Sub x (px : repr (\\pi_qT x) == x) := \\pi_qT x.\n\n(*This lemma states that if a quotient element is constructed using the `Sub` function from a canonical representative, then applying the representation function to this quotient element recovers the original canonical representative.*)\nLemma qreprK x Px : repr (@Sub x Px) = x.\n\n(*This lemma asserts that the canonical representative of any element in a quotient type is itself a fixed point of the process of projection followed by representation. This confirms that the representation function consistently picks a canonical element.*)\nLemma sortPx (x : qT) : repr (\\pi_qT (repr x)) == repr x.\n\n(*This lemma states that any element of a quotient type is equal to the result of applying the `Sub` constructor to its canonical representative, effectively showing that every element can be expressed via its canonical form.*)\nLemma sort_Sub (x : qT) : x = Sub (sortPx x).\n\n(*This lemma states that a property holding for all representatives of a subtype also holds for any element of the corresponding quotient type.*)\nLemma reprP K (PK : forall x Px, K (@Sub x Px)) u : K u.\n\n#[export]\nHB.instance Definition _ := isSub.Build _ _ (quot_type qT) reprP qreprK.\n#[export]\n(*This notation defines a subtype structure on a quotient type, where the quotient type is constructed from a given base type and a predicate, and the subtype structure itself is defined by that same predicate.*)\nNotation \"[ 'Sub' Q 'of' T 'by' %/ ]\" :=\n (SubType.copy Q%type (quot_type_of T Q%type))\n (format \"[ 'Sub' Q 'of' T 'by' %/ ]\") : form_scope.\n\n(*This notation defines a subtype structure on an inferred quotient type, where the quotient type is derived from a given subtype, and the new structure is a copy of the original subtype's structure.*)\nNotation \"[ 'Sub' Q 'by' %/ ]\" :=\n (SubType.copy Q%type (quot_type Q))\n (format \"[ 'Sub' Q 'by' %/ ]\") : form_scope.\n\n(*This notation endows a type with an equality structure by inheriting it from its corresponding quotient type.*)\nNotation \"[ 'Equality' 'of' Q 'by' <:%/ ]\" :=\n (Equality.copy Q%type (quot_type Q))\n (format \"[ 'Equality' 'of' Q 'by' <:%/ ]\") : form_scope.\n\n(*This notation endows a type with a choice structure, which allows for consistent selection of elements, by inheriting this structure from its corresponding quotient type.*)\nNotation \"[ 'Choice' 'of' Q 'by' <:%/ ]\" := (Choice.copy Q%type (quot_type Q))\n (format \"[ 'Choice' 'of' Q 'by' <:%/ ]\") : form_scope.\n\n(*This notation endows a type with a countable structure, indicating its elements can be put into one-to-one correspondence with the natural numbers, by inheriting this structure from its corresponding quotient type.*)\nNotation \"[ 'Countable' 'of' Q 'by' <:%/ ]\" := (Countable.copy Q%type (quot_type Q))\n (format \"[ 'Countable' 'of' Q 'by' <:%/ ]\") : form_scope.\n\n(*This notation endows a type with a finite structure, indicating it has a finite number of elements, by inheriting this structure from its corresponding quotient type.*)\nNotation \"[ 'Finite' 'of' Q 'by' <:%/ ]\" := (Finite.copy Q%type (quot_type Q))\n (format \"[ 'Finite' 'of' Q 'by' <:%/ ]\") : form_scope.\n\nSection EquivRel.\n\nVariable T : Type.\n\n(*This lemma states that any binary relation that is both symmetric and transitive is also left-transitive, meaning that if a second element is related to a first and also to a third, then the first element is related to the third.*)\nLemma left_trans (e : rel T) :\n symmetric e -> transitive e -> left_transitive e.\n\n(*This lemma states that any binary relation that is both symmetric and transitive is also right-transitive, meaning that if a first element is related to a third, and a second element is also related to that third, then the first element is related to the second.*)\nLemma right_trans (e : rel T) :\n symmetric e -> transitive e -> right_transitive e.\n\n(*This definition represents the properties characterizing an equivalence relation, bundling proofs that a given binary relation is reflexive, symmetric, and transitive.*)\nVariant equiv_class_of (equiv : rel T) :=\n EquivClass of reflexive equiv & symmetric equiv & transitive equiv.\n\n(*This record defines a structure for an equivalence relation, which consists of a binary relation on a type and a proof that this relation is reflexive, symmetric, and transitive.*)\nRecord equiv_rel := EquivRelPack {\n equiv :> rel T;\n _ : equiv_class_of equiv\n}.\n\nVariable e : equiv_rel.\n\n(*This definition extracts the proof component from an equivalence relation structure, which itself contains the evidence that the relation is reflexive, symmetric, and transitive.*)\nDefinition equiv_class :=\n let: EquivRelPack _ ce as e' := e return equiv_class_of e' in ce.\n\n(*This definition constructs an equivalence relation structure by packaging a given binary relation with its corresponding proof object, which certifies that the relation is reflexive, symmetric, and transitive.*)\nDefinition equiv_pack (r : rel T) ce of phant_id ce equiv_class :=\n @EquivRelPack r ce.\n\n(*This lemma states that any element is related to itself under a given equivalence relation, demonstrating the property of reflexivity.*)\nLemma equiv_refl x : e x x. \n(*This lemma states that for any two elements, if the first is related to the second under a given equivalence relation, then the second is also related to the first, demonstrating the property of symmetry.*)\nLemma equiv_sym : symmetric e. \n(*This lemma states that for any three elements, if the first is related to the second and the second is related to the third under a given equivalence relation, then the first is also related to the third, demonstrating the property of transitivity.*)\nLemma equiv_trans : transitive e. \n\n(*This lemma states that the standard equality relation on any type equipped with a decidable equality test is transitive.*)\nLemma eq_op_trans (T' : eqType) : transitive (@eq_op T').\n\n(*This lemma states that any equivalence relation is left-transitive, meaning that if a second element is related to a first and also to a third, then the first element is related to the third.*)\nLemma equiv_ltrans: left_transitive e.\n\n(*This lemma states that any equivalence relation is right-transitive, meaning that if a first element is related to a third, and a second element is also related to that third, then the first element is related to the second.*)\nLemma equiv_rtrans: right_transitive e.\n\nEnd EquivRel.\n\n#[global] Hint Resolve equiv_refl : core.\n\nNotation EquivRel r er es et := (@EquivRelPack _ r (EquivClass er es et)).\n(*This notation constructs an equivalence relation structure from a proof object that certifies the properties of reflexivity, symmetry, and transitivity, where the underlying binary relation is inferred from the context.*)\nNotation \"[ 'equiv_rel' 'of' e ]\" := (@equiv_pack _ _ e _ id)\n (format \"[ 'equiv_rel' 'of' e ]\") : form_scope.\n\nSection EncodingModuloRel.\n\nVariables (D E : Type) (ED : E -> D) (DE : D -> E) (e : rel D).\n\n(*This definition specifies the properties of a relation that is compatible with an encoding-decoding scheme between two types. It requires that for any element related to itself, the element resulting from an encode-decode round trip is related back to the original element, and that this relation is equivalent to a given background relation.*)\nVariant encModRel_class_of (r : rel D) :=\n EncModRelClassPack of (forall x, r x x -> r (ED (DE x)) x) & (r =2 e).\n\n(*This record defines a structure for a relation that is compatible with an encoding-decoding scheme. It bundles the relation with a proof of its compatibility properties.*)\nRecord encModRel := EncModRelPack {\n enc_mod_rel :> rel D;\n _ : encModRel_class_of enc_mod_rel\n}.\n\nVariable r : encModRel.\n\n(*This definition extracts the proof component from a structure representing a relation compatible with an encoding-decoding scheme. The extracted component contains the evidence of this compatibility.*)\nDefinition encModRelClass :=\n let: EncModRelPack _ c as r' := r return encModRel_class_of r' in c.\n\n(*This definition extracts a specific property from a relation compatible with an encoding scheme. The property states that for any element related to itself, the result of encoding and then decoding that element is also related to the original element.*)\nDefinition encModRelP (x : D) : r x x -> r (ED (DE x)) x.\n\n(*This definition asserts that a relation compatible with an encoding scheme is equivalent to a given background relation.*)\nDefinition encModRelE : r =2 e. \n\n(*This definition defines a new binary relation on an encoded type. Two elements in the encoded type are related if and only if their decoded counterparts in the original type are related by a given relation.*)\nDefinition encoded_equiv : rel E := [rel x y | r (ED x) (ED y)].\n\nEnd EncodingModuloRel.\n\nNotation EncModRelClass m :=\n (EncModRelClassPack (fun x _ => m x) (fun _ _ => erefl _)).\nNotation EncModRel r m := (@EncModRelPack _ _ _ _ _ r (EncModRelClass m)).\n\nSection EncodingModuloEquiv.\n\nVariables (D E : Type) (ED : E -> D) (DE : D -> E) (e : equiv_rel D).\nVariable (r : encModRel ED DE e).\n\n(*This lemma states that a relation which is compatible with an encoding-decoding scheme and equivalent to an equivalence relation is itself an equivalence relation.*)\nLemma enc_mod_rel_is_equiv : equiv_class_of (enc_mod_rel r).\n\n(*This definition packages the proof that the encoding-modulo relation is an equivalence relation into a single structure.*)\nDefinition enc_mod_rel_equiv_rel := EquivRelPack enc_mod_rel_is_equiv.\n\n(*This definition asserts that for any given element, applying the decoding function followed by the encoding function results in an element that is related to the original element under the specified relation.*)\nDefinition encModEquivP (x : D) : r (ED (DE x)) x.\n\n(*This notation serves as a local shorthand for the encoded equivalence relation.*)\nLocal Notation e' := (encoded_equiv r).\n\n(*This lemma states that the encoded equivalence relation holds for two encoded elements if and only if the original equivalence relation holds for their corresponding decoded elements.*)\nLemma encoded_equivE : e' =2 [rel x y | e (ED x) (ED y)].\n\n(*This notation provides a local alias for the lemma that characterizes the encoded equivalence relation.*)\nLocal Notation e'E := encoded_equivE.\n\n(*This lemma states that the encoded relation is an equivalence relation, meaning it is reflexive, symmetric, and transitive.*)\nLemma encoded_equiv_is_equiv : equiv_class_of e'.\n\nCanonical encoded_equiv_equiv_rel := EquivRelPack encoded_equiv_is_equiv.\n\n(*This lemma states that for any element in the encoded type, applying the decoding function followed by the encoding function yields an element that is equivalent to the original under the encoded equivalence relation.*)\nLemma encoded_equivP x : e' (DE (ED x)) x.\n\nEnd EncodingModuloEquiv.\n\nModule EquivQuot.\nSection EquivQuot.\n\nVariables (D : Type) (C : choiceType) (CD : C -> D) (DC : D -> C).\nVariables (eD : equiv_rel D) (encD : encModRel CD DC eD).\n(*A notation for an equivalence relation constructed via an encoding function. This approach is used to define an equivalence on a type by mapping its elements to a different type that has more convenient properties, such as a choice operator, and defining the equivalence on that target type.*)\nNotation eC := (encoded_equiv encD).\n\n(*This definition specifies a function that, for any given element in the choice type, selects a canonical representative from its equivalence class under the encoded equivalence relation.*)\nDefinition canon x := choose (eC x) (x).\n\n(*This record defines the structure for an element of a quotient type, which consists of a canonical representative from a choice type along with a proof that this representative is indeed canonical.*)\nRecord equivQuotient := EquivQuotient {\n erepr : C;\n _ : (frel canon) erepr erepr\n}.\n\n(*This definition creates the quotient type itself, which is defined as the type of canonical representatives, parameterized by the underlying encoding structure.*)\nDefinition type_of of (phantom (rel _) encD) := equivQuotient.\n\n(*This lemma states that the function for selecting a canonical representative is idempotent, meaning that applying it to an element that is already a canonical representative does not change it.*)\nLemma canon_id : forall x, (invariant canon canon) x.\n\n(*This definition introduces the canonical projection function, which maps an element from the choice type to its corresponding equivalence class in the quotient type.*)\nDefinition pi := locked (fun x => EquivQuotient (canon_id x)).\n\n(*This lemma provides a cancellation property, stating that extracting the canonical representative of an equivalence class created by the projection function yields the result of applying the canonical representative selection function directly to the original element.*)\nLemma ereprK : cancel erepr pi.\n\n(*This notation provides a local alias for the lemma that expands the definition of the encoding-modulo relation.*)\nLocal Notation encDE := (encModRelE encD).\n(*This notation serves as a local alias for the lemma asserting the round-trip property of the encoding and decoding functions associated with the given encoding structure.*)\nLocal Notation encDP := (encModEquivP encD).\nCanonical encD_equiv_rel := EquivRelPack (enc_mod_rel_is_equiv encD).\n\n(*This lemma states that the projection of two elements from the choice type results in the same quotient element if and only if the two original elements are equivalent under the encoded equivalence relation.*)\nLemma pi_CD (x y : C) : reflect (pi x = pi y) (eC x y).\n\n(*This lemma states that two elements from the original type are equivalent under the original equivalence relation if and only if their encoded counterparts are projected to the same quotient element.*)\nLemma pi_DC (x y : D) :\n reflect (pi (DC x) = pi (DC y)) (eD x y).\n\n(*This lemma establishes a cancellation property which asserts that encoding an element, projecting it to the quotient type, extracting its canonical representative, and finally decoding it back, results in an element that is equivalent to the original element under the original equivalence relation.*)\nLemma equivQTP : cancel (CD \\o erepr) (pi \\o DC).\n\n(*This notation serves as a local shorthand for the quotient type constructed from the given original type and encoding structure.*)\nLocal Notation qT := (type_of (Phantom (rel D) encD)).\n#[export]\nHB.instance Definition _ := isQuotient.Build D qT equivQTP.\n\n(*This lemma states that two elements are equal modulo the quotient type if and only if they are equivalent under the original equivalence relation.*)\nLemma eqmodP x y : reflect (x = y %[mod qT]) (eD x y).\n\n#[export]\nHB.instance Definition _ := Choice.copy qT (can_type ereprK).\n\n(*This lemma provides a boolean characterization of equality modulo the quotient type, stating that the boolean result of comparing two elements for equality modulo the quotient is the same as the boolean result of applying the original equivalence relation to them.*)\nLemma eqmodE x y : x == y %[mod qT] = eD x y.\n\n#[export]\n(*This notation defines a syntax for constructing a quotient type from a given encoding structure, which encapsulates the equivalence relation and encoding functions.*)\nNotation \"{eq_quot e }\" :=\n(@EquivQuot.type_of _ _ _ _ _ _ (Phantom (rel _) e)) : quotient_scope.\n(*This notation provides a convenient syntax for testing boolean equality of two elements modulo an equivalence relation, where the quotient type is implicitly constructed from the provided encoding structure.*)\nNotation \"x == y %[mod_eq r ]\" := (x == y %[mod {eq_quot r}]) : quotient_scope.\n(*This notation provides a convenient syntax for asserting the propositional equality of two elements modulo an equivalence relation, where the quotient type is implicitly constructed from the provided encoding structure.*)\nNotation \"x = y %[mod_eq r ]\" := (x = y %[mod {eq_quot r}]) : quotient_scope.\n(*This notation offers a shorthand for testing boolean inequality of two elements modulo an equivalence relation, with the quotient type being implicitly formed from the given encoding structure.*)\nNotation \"x != y %[mod_eq r ]\" := (x != y %[mod {eq_quot r}]) : quotient_scope.\n(*This notation provides a shorthand for asserting the propositional inequality of two elements modulo an equivalence relation, where the quotient type is implicitly constructed from the provided encoding structure.*)\nNotation \"x <> y %[mod_eq r ]\" := (x <> y %[mod {eq_quot r}]) : quotient_scope.\n\nSection DefaultEncodingModuloRel.\n\nVariables (D : choiceType) (r : rel D).\n\n(*This definition provides a default encoding structure for cases where the original type is also the choice type, using the identity function for both encoding and decoding.*)\nDefinition defaultEncModRelClass :=\n @EncModRelClassPack D D id id r r (fun _ rxx => rxx) (fun _ _ => erefl _).\n\nCanonical defaultEncModRel := EncModRelPack defaultEncModRelClass.\n\nEnd DefaultEncodingModuloRel.\n\nSection CountEncodingModuloRel.\n\nVariables (D : Type) (C : countType) (CD : C -> D) (DC : D -> C).\nVariables (eD : equiv_rel D) (encD : encModRel CD DC eD).\n(*This lemma states that for any two elements, if the first element is related to the second by an equivalence relation, then the second element is also related to the first by the same relation, reflecting the symmetry property.*)\nNotation eC := (encoded_equiv encD).\n\n(*This lemma states that the boolean equality test between two elements modulo a given equivalence relation is definitionally equivalent to applying the equivalence relation to those two elements.*)\nLemma eqmodE x y : x == y %[mod_eq e] = e x y.\n\n(*This lemma provides a reflection principle, stating that the proposition that two elements are equal modulo a given equivalence relation holds if and only if the boolean evaluation of the equivalence relation on those two elements is true.*)\nLemma eqmodP x y : reflect (x = y %[mod_eq e]) (e x y).\n\nEnd EquivQuotTheory.\n\nPrenex Implicits eqmodE eqmodP.\n\nSection EqQuotTheory.\n\nVariables (T : Type) (e : rel T) (Q : eqQuotType e).\n\n(*This lemma states that the boolean equality test between two elements, when considered as members of a quotient type, is definitionally equivalent to applying the underlying binary relation of that quotient type to those elements.*)\nLemma eqquotE x y : x == y %[mod Q] = e x y.\n\n(*This lemma provides a reflection principle, stating that the proposition that two elements are equal in a quotient type holds if and only if the boolean evaluation of the underlying binary relation of that quotient type on those two elements is true.*)\nLemma eqquotP x y : reflect (x = y %[mod Q]) (e x y).\n\nEnd EqQuotTheory.", - "boot.div": "From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\n(*This definition provides a recursive computation for Euclidean division, taking a modified divisor, a dividend, and an initial quotient, and returning a pair containing the final quotient and remainder.*)\nDefinition edivn_rec d :=\n fix loop m q := if m - d is m'.+1 then loop m' q.+1 else (q, m).\n\n(*This definition computes the Euclidean division of a first natural number by a second natural number, returning a pair containing the quotient and the remainder. If the divisor is zero, it returns a quotient of zero and a remainder equal to the dividend.*)\nDefinition edivn m d := if d > 0 then edivn_rec d.-1 m 0 else (0, m).\n\n(*This inductive type specifies the property of a pair of natural numbers, representing a quotient and remainder, for the Euclidean division of a given dividend by a given divisor. The property requires that the dividend equals the quotient times the divisor plus the remainder, and if the divisor is positive, the remainder must be strictly less than the divisor.*)\nVariant edivn_spec m d : nat * nat -> Type :=\n EdivnSpec q r of m = q * d + r & (d > 0) ==> (r < d) : edivn_spec m d (q, r).\n\n(*This lemma states that the pair of natural numbers produced by the Euclidean division function for a given dividend and divisor satisfies the specification of Euclidean division.*)\nLemma edivnP m d : edivn_spec m d (edivn m d).\n\n(*This lemma states that if a natural number is expressed as a multiple of a divisor plus a remainder that is strictly less than the divisor, then the Euclidean division of that number by the divisor yields the given multiplier as the quotient and the given remainder.*)\nLemma edivn_eq d q r : r < d -> edivn (q * d + r) d = (q, r).\n\n(*This definition specifies the quotient of the Euclidean division of a first natural number by a second natural number as the first component of the pair returned by the division function.*)\nDefinition divn m d := (edivn m d).1.\n\n(*This notation represents the quotient of the Euclidean division of a first natural number by a second natural number.*)\nNotation \"m %/ d\" := (divn m d) : nat_scope.\n\n(*This definition provides a recursive computation for the remainder of a Euclidean division, which repeatedly subtracts a modified divisor from a dividend until the result is smaller than the divisor.*)\nDefinition modn_rec d := fix loop m := if m - d is m'.+1 then loop m' else m.\n\n(*This definition computes the remainder of the Euclidean division of a first natural number by a second natural number. If the divisor is zero, the remainder is the dividend itself.*)\nDefinition modn m d := if d > 0 then modn_rec d.-1 m else m.\n\n(*This notation represents the remainder of the Euclidean division of a first natural number by a second natural number.*)\nNotation \"m %% d\" := (modn m d) : nat_scope.\n(*This notation expresses that two natural numbers are congruent modulo a third natural number, meaning they have the same remainder when divided by it.*)\nNotation \"m = n %[mod d ]\" := (m %% d = n %% d) : nat_scope.\n(*This notation represents a boolean value indicating whether two natural numbers are congruent modulo a third natural number, which is true if their remainders upon division by that number are equal.*)\nNotation \"m == n %[mod d ]\" := (m %% d == n %% d) : nat_scope.\n(*This notation expresses that two natural numbers are not congruent modulo a third natural number, meaning they have different remainders when divided by it.*)\nNotation \"m <> n %[mod d ]\" := (m %% d <> n %% d) : nat_scope.\n(*This notation represents a boolean value indicating whether two natural numbers are not congruent modulo a third natural number, which is true if their remainders upon division by that number are different.*)\nNotation \"m != n %[mod d ]\" := (m %% d != n %% d) : nat_scope.\n\n(*This lemma states that the remainder of the division of a first natural number by a second is equal to the second component of the pair returned by the general Euclidean division function.*)\nLemma modn_def m d : m %% d = (edivn m d).2.\n\n(*This lemma states that the result of the general Euclidean division function, which computes both quotient and remainder, is a pair formed by the separately computed quotient and remainder.*)\nLemma edivn_def m d : edivn m d = (m %/ d, m %% d).\n\n(*This lemma states that any natural number is equal to the sum of its remainder and the product of its quotient and the divisor, when divided by another natural number.*)\nLemma divn_eq m d : m = m %/ d * d + m %% d.\n\n(*This lemma states that the quotient of zero divided by any natural number is zero.*)\nLemma div0n d : 0 %/ d = 0. \n(*This lemma states that the quotient of any natural number divided by zero is zero.*)\nLemma divn0 m : m %/ 0 = 0. \n(*This lemma states that the remainder of zero divided by any natural number is zero.*)\nLemma mod0n d : 0 %% d = 0. \n(*This lemma states that the remainder of any natural number divided by zero is the number itself.*)\nLemma modn0 m : m %% 0 = m. \n\n(*This lemma states that if a first natural number is strictly less than a second natural number, its quotient when divided by the second number is zero.*)\nLemma divn_small m d : m < d -> m %/ d = 0.\n\n(*This lemma states that for a positive divisor, the quotient of the sum of a multiple of the divisor and another number, when divided by that divisor, is equal to the sum of the multiplier and the quotient of the other number divided by the divisor.*)\nLemma divnMDl q m d : 0 < d -> (q * d + m) %/ d = q + m %/ d.\n\n(*This lemma states that for a positive divisor, dividing the product of a natural number and the divisor by that same divisor yields the original natural number.*)\nLemma mulnK m d : 0 < d -> m * d %/ d = m.\n\n(*This lemma states that for a positive divisor, dividing the product of the divisor and a natural number by that same divisor yields the original natural number.*)\nLemma mulKn m d : 0 < d -> d * m %/ d = m.\n\n(*This lemma states that for a positive base, a power of the base raised to the difference of two exponents, where the first is greater than or equal to the second, is equal to the quotient of the base raised to the first exponent divided by the base raised to the second exponent.*)\nLemma expnB p m n : p > 0 -> m >= n -> p ^ (m - n) = p ^ m %/ p ^ n.\n\n(*This lemma states that the remainder of any natural number divided by one is zero.*)\nLemma modn1 m : m %% 1 = 0.\n\n(*This lemma states that the quotient of any natural number divided by one is the number itself.*)\nLemma divn1 m : m %/ 1 = m.\n\n(*This lemma states that the quotient of a natural number divided by itself is one if the number is positive, and zero otherwise.*)\nLemma divnn d : d %/ d = (0 < d).\n\n(*This lemma states that for a positive natural number, the quotient of two products can be simplified by cancelling out a common factor from both the dividend and the divisor.*)\nLemma divnMl p m d : p > 0 -> p * m %/ (p * d) = m %/ d.\n\nArguments divnMl [p m d].\n\n(*This lemma states that for a positive natural number, the quotient resulting from dividing a product by another product can be simplified by cancelling out a common factor from the right of both the dividend and the divisor.*)\nLemma divnMr p m d : p > 0 -> m * p %/ (d * p) = m %/ d.\n\nArguments divnMr [p m d].\n\n(*This lemma states that the remainder of the division of a natural number by a second natural number is strictly less than the divisor if and only if the divisor is positive.*)\nLemma ltn_mod m d : (m %% d < d) = (0 < d).\n\n(*This lemma states that if the divisor in a natural number division is positive, then the remainder is strictly less than the divisor.*)\nLemma ltn_pmod m d : 0 < d -> m %% d < d.\n\n(*This lemma states that the product of the quotient and the divisor from a natural number division is always less than or equal to the original dividend.*)\nLemma leq_divM m d : m %/ d * d <= m.\n\n#[deprecated(since=\"mathcomp 2.4.0\", note=\"Renamed to leq_divM.\")]\n(*This notation is a deprecated alias for a lemma asserting that the product of the quotient and the divisor in a natural number division is less than or equal to the original dividend.*)\nNotation leq_trunc_div := leq_divM.\n\n(*This lemma states that the remainder of a natural number division is always less than or equal to the dividend.*)\nLemma leq_mod m d : m %% d <= m.\n\n(*This lemma states that the quotient of a natural number division is always less than or equal to the dividend.*)\nLemma leq_div m d : m %/ d <= m.\n\n(*This lemma states that for a positive divisor, a natural number is strictly less than the product of its divisor and the successor of its quotient.*)\nLemma ltn_ceil m d : 0 < d -> m < (m %/ d).+1 * d.\n\n(*This lemma states that for a positive divisor, the proposition that the quotient of two natural numbers is strictly less than a third natural number is equivalent to the proposition that the original dividend is strictly less than the product of the third number and the divisor.*)\nLemma ltn_divLR m n d : d > 0 -> (m %/ d < n) = (m < n * d).\n\n(*This lemma states that for a positive divisor, the proposition that a natural number is less than or equal to a quotient is equivalent to the proposition that the product of that number and the divisor is less than or equal to the dividend of the original quotient.*)\nLemma leq_divRL m n d : d > 0 -> (m <= n %/ d) = (m * d <= n).\n\n(*This lemma states that for a positive dividend and a divisor strictly greater than one, the quotient is strictly smaller than the dividend.*)\nLemma ltn_Pdiv m d : 1 < d -> 0 < m -> m %/ d < m.\n\n(*This lemma states that for a positive divisor, the quotient of a division is positive if and only if the divisor is less than or equal to the dividend.*)\nLemma divn_gt0 d m : 0 < d -> (0 < m %/ d) = (d <= m).\n\n(*This lemma states that the natural number division operation is monotonic with respect to the dividend; that is, if one dividend is less than or equal to another, their quotients by the same divisor maintain that relationship.*)\nLemma leq_div2r d m n : m <= n -> m %/ d <= n %/ d.\n\n(*This lemma states that the natural number division operation is anti-monotonic with respect to a positive divisor; that is, if one divisor is less than or equal to another, the quotient with the larger divisor will be less than or equal to the quotient with the smaller divisor.*)\nLemma leq_div2l m d e : 0 < d -> d <= e -> m %/ e <= m %/ d.\n\n(*This lemma provides the result of the Euclidean division of a sum of two natural numbers. It states that for a positive divisor, the quotient of the sum is the sum of the individual quotients plus a carry, and the remainder of the sum is derived from the sum of the individual remainders, adjusted by the divisor and the same carry. The carry is one if the sum of the individual remainders is greater than or equal to the divisor, and zero otherwise.*)\nLemma edivnD m n d (offset := m %% d + n %% d >= d) : 0 < d ->\n edivn (m + n) d = (m %/ d + n %/ d + offset, m %% d + n %% d - offset * d).\n\n(*This lemma states that for a positive divisor, the quotient of the sum of two natural numbers divided by the divisor is the sum of their individual quotients, plus one if the sum of their individual remainders is greater than or equal to the divisor.*)\nLemma divnD m n d : 0 < d ->\n (m + n) %/ d = (m %/ d) + (n %/ d) + (m %% d + n %% d >= d).\n\n(*This lemma states that for a positive divisor, the remainder of the sum of two natural numbers divided by the divisor is the sum of their individual remainders, reduced by the value of the divisor if that sum is greater than or equal to the divisor.*)\nLemma modnD m n d : 0 < d ->\n (m + n) %% d = m %% d + n %% d - (m %% d + n %% d >= d) * d.\n\n(*This lemma states an equivalence for a positive divisor: the sum of the remainders of two numbers is greater than or equal to the divisor if and only if the remainder of the sum of the two numbers is strictly less than the remainder of the second number.*)\nLemma leqDmod m n d : 0 < d ->\n (d <= m %% d + n %% d) = ((m + n) %% d < n %% d).\n\n(*This lemma states that for a positive divisor, the quotient of the difference of two natural numbers is the difference of their individual quotients, minus one if the remainder of the first number is strictly less than the remainder of the second.*)\nLemma divnB n m d : 0 < d ->\n (m - n) %/ d = (m %/ d) - (n %/ d) - (m %% d < n %% d).\n\n(*This lemma states that for a positive divisor and two natural numbers where the second is not larger than the first, the remainder of their difference is calculated by adding the divisor to the difference of their remainders if the first remainder is smaller than the second, and is simply the difference of their remainders otherwise.*)\nLemma modnB m n d : 0 < d -> n <= m ->\n (m - n) %% d = (m %% d < n %% d) * d + m %% d - n %% d.\n\n(*This lemma provides the result of the Euclidean division of the difference of two natural numbers, where the second is not larger than the first. For a positive divisor, it states that the resulting quotient and remainder are derived from the individual quotients and remainders, adjusted by a borrow. The borrow is one if the remainder of the first number is less than the remainder of the second, and zero otherwise.*)\nLemma edivnB m n d (offset := m %% d < n %% d) : 0 < d -> n <= m ->\n edivn (m - n) d = (m %/ d - n %/ d - offset, offset * d + m %% d - n %% d).\n\n(*This lemma provides an upper bound for the quotient of a sum of two natural numbers, stating that it is less than or equal to the sum of the individual quotients plus one.*)\nLemma leq_divDl p m n : (m + n) %/ p <= m %/ p + n %/ p + 1.\n\n(*This lemma provides a bound relating the division of a difference to the difference of divisions. It states that the difference between the quotients of two natural numbers is at most one greater than the quotient of their difference.*)\nLemma geq_divBl k m p : k %/ p - m %/ p <= (k - m) %/ p + 1.\n\n(*This lemma states that dividing a natural number by a product of two other numbers is equivalent to successively dividing by each number in the product.*)\nLemma divnMA m n p : m %/ (n * p) = m %/ n %/ p.\n\n(*This lemma states that the order of successive divisions of a natural number does not affect the final quotient, showing a commutative property for iterated division.*)\nLemma divnAC m n p : m %/ n %/ p = m %/ p %/ n.\n\n(*This lemma states that if a natural number is strictly smaller than a divisor, its remainder upon division by that divisor is the number itself.*)\nLemma modn_small m d : m < d -> m %% d = m.\n\n(*This lemma states that the remainder obtained from the Euclidean division of two natural numbers is equal to the result of the canonical modulo operation between the same two numbers.*)\nLemma modn_mod m d : m %% d = m %[mod d].\n\n(*This lemma states that adding a multiple of a natural number to another number does not change the result of the modulo operation with respect to that natural number.*)\nLemma modnMDl p m d : p * d + m = m %[mod d].\n\n(*This lemma states that for three natural numbers, the product of the first number and the remainder of the second number divided by the third is equal to the remainder from the division of the product of the first and second numbers by the product of the first and third numbers.*)\nLemma muln_modr p m d : p * (m %% d) = (p * m) %% (p * d).\n\n(*This lemma states that for three natural numbers, the product of the remainder of the second number divided by the third and the first number, is equal to the remainder from the division of the product of the second and first numbers by the product of the third and first numbers.*)\nLemma muln_modl p m d : (m %% d) * p = (m * p) %% (d * p).\n\n(*This lemma states that for three natural numbers, the remainder of the quotient of the first and third numbers when divided by the second is equal to the quotient of the remainder of the first number divided by the product of the second and third, all divided by the third.*)\nLemma modn_divl m n d : (m %/ d) %% n = m %% (n * d) %/ d.\n\n(*This lemma states that for two natural numbers, the sum of the second and the first is congruent to the second number, modulo the first number.*)\nLemma modnDl m d : d + m = m %[mod d].\n\n(*This lemma states that for two natural numbers, their sum is congruent to the first number, modulo the second number.*)\nLemma modnDr m d : m + d = m %[mod d]. \n\n(*This lemma states that the remainder of a natural number divided by itself is always zero.*)\nLemma modnn d : d %% d = 0. \n\n(*This lemma states that any multiple of a natural number has a remainder of zero when divided by that number.*)\nLemma modnMl p d : p * d %% d = 0.\n\n(*This lemma states that the remainder of the division of a product formed by a natural number and another number, by that first natural number, is zero.*)\nLemma modnMr p d : d * p %% d = 0. \n\n(*This lemma states that for three natural numbers, the sum of the remainder of the first number divided by the third and the second number is congruent modulo the third number to the sum of the first and second numbers.*)\nLemma modnDml m n d : m %% d + n = m + n %[mod d].\n\n(*This lemma states that for three natural numbers, the sum of the first number and the remainder of the second number divided by the third is congruent modulo the third number to the sum of the first and second numbers.*)\nLemma modnDmr m n d : m + n %% d = m + n %[mod d].\n\n(*This lemma states that for three natural numbers, the sum of the remainder of the first number divided by the third and the remainder of the second number divided by the third is congruent modulo the third number to the sum of the first and second numbers.*)\nLemma modnDm m n d : m %% d + n %% d = m + n %[mod d].\n\n(*This lemma states that for four natural numbers, the congruence modulo the fourth number between the sum of the first and second, and the sum of the first and third, is equivalent to the congruence between the second and third numbers modulo the fourth.*)\nLemma eqn_modDl p m n d : (p + m == p + n %[mod d]) = (m == n %[mod d]).\n\n(*This lemma states that for four natural numbers, the congruence modulo the fourth number between the sum of the second and first, and the sum of the third and first, is equivalent to the congruence between the second and third numbers modulo the fourth.*)\nLemma eqn_modDr p m n d : (m + p == n + p %[mod d]) = (m == n %[mod d]).\n\n(*This lemma states that for three natural numbers, the product of the remainder of the first number divided by the third and the second number is congruent modulo the third number to the product of the first and second numbers.*)\nLemma modnMml m n d : m %% d * n = m * n %[mod d].\n\n(*This lemma states that for three natural numbers, the product of the first number and the remainder of the second number divided by the third is congruent modulo the third number to the product of the first and second numbers.*)\nLemma modnMmr m n d : m * (n %% d) = m * n %[mod d].\n\n(*This lemma states that for three natural numbers, the product of the remainder of the first number divided by the third and the remainder of the second number divided by the third is congruent modulo the third number to the product of the first and second numbers.*)\nLemma modnMm m n d : m %% d * (n %% d) = m * n %[mod d].\n\n(*This lemma states that the remainder of a natural number divided by two is equal to one if the number is odd, and zero otherwise.*)\nLemma modn2 m : m %% 2 = odd m.\n\n(*This lemma states that the integer division of a natural number by two is equivalent to applying the specific notation for halving a number.*)\nLemma divn2 m : m %/ 2 = m./2.\n\n(*This lemma states that if a divisor is an even natural number, then the oddness of the remainder of a division is the same as the oddness of the dividend.*)\nLemma odd_mod m d : odd d = false -> odd (m %% d) = odd m.\n\n(*This lemma states that for three natural numbers, raising the remainder of the division of the third by the second to the power of the first is congruent modulo the second number to the third number raised to the power of the first.*)\nLemma modnXm m n a : (a %% n) ^ m = a ^ m %[mod n].\n\n(*This lemma states that for four natural numbers, raising an expression of the form 'the first times the fourth, plus the second' to the power of the third is congruent modulo the fourth number to the second number raised to the power of the third.*)\nLemma modnMDXl p m n d : (p * d + m) ^ n = m ^ n %[mod d].\n\n(*This definition specifies that a first natural number divides a second natural number if and only if the remainder of the division of the second number by the first is zero.*)\nDefinition dvdn d m := m %% d == 0.\n\n(*This notation provides a symbol for the divisibility relation between two natural numbers, where the expression indicates that the number on the left divides the number on the right.*)\nNotation \"m %| d\" := (dvdn m d) : nat_scope.\n\n(*This lemma establishes the equivalence between the boolean statement that a first natural number divides a second one and the proposition that there exists a third natural number which, when multiplied by the first, yields the second.*)\nLemma dvdnP d m : reflect (exists k, m = k * d) (d %| m).\n\nArguments dvdnP {d m}.\n\n(*This lemma states that any natural number divides zero.*)\nLemma dvdn0 d : d %| 0.\n\n(*This lemma states that zero divides a natural number if and only if that number is itself zero.*)\nLemma dvd0n n : (0 %| n) = (n == 0).\n\n(*This lemma states that a natural number divides one if and only if that number is itself one.*)\nLemma dvdn1 d : (d %| 1) = (d == 1).\n\n(*This lemma states that the number one divides any natural number.*)\nLemma dvd1n m : 1 %| m.\n\n(*This lemma states that if a natural number divides another positive natural number, then the divisor must also be a positive number.*)\nLemma dvdn_gt0 d m : m > 0 -> d %| m -> d > 0.\n\n(*This lemma states that any natural number divides itself.*)\nLemma dvdnn m : m %| m.\n\n(*This lemma states that for three natural numbers, if the first divides the third, then the first also divides the product of the second and third natural numbers.*)\nLemma dvdn_mull d m n : d %| n -> d %| m * n.\n\n(*This lemma states that for three natural numbers, if the first divides the second, then the first also divides the product of the second and third natural numbers.*)\nLemma dvdn_mulr d m n : d %| m -> d %| m * n.\n\n#[global] Hint Resolve dvdn0 dvd1n dvdnn dvdn_mull dvdn_mulr : core.\n\n(*This lemma states that if a first natural number divides a second one, and a third natural number divides a fourth one, then the product of the first and third natural numbers divides the product of the second and fourth natural numbers.*)\nLemma dvdn_mul d1 d2 m1 m2 : d1 %| m1 -> d2 %| m2 -> d1 * d2 %| m1 * m2.\n\n(*This lemma states that the divisibility relation on natural numbers is transitive: if a first natural number divides a second one, and the second divides a third one, then the first natural number also divides the third.*)\nLemma dvdn_trans n d m : d %| n -> n %| m -> d %| m.\n\n(*This lemma states that the boolean indicating whether a first natural number divides a second one is equivalent to the boolean checking if the product of the quotient of the two numbers and the first number is equal to the second number.*)\nLemma dvdn_eq d m : (d %| m) = (m %/ d * d == m).\n\n(*This lemma states that a natural number is divisible by two if and only if it is not an odd number.*)\nLemma dvdn2 n : (2 %| n) = ~~ odd n.\n\n(*This lemma states that if a first natural number divides a second natural number, and the second number is odd, then the first number must also be odd.*)\nLemma dvdn_odd m n : m %| n -> odd n -> odd m.\n\n(*This lemma provides a cancellation rule for division, stating that if a natural number divides another, multiplying the quotient of the two numbers by the divisor yields the original dividend.*)\nLemma divnK d m : d %| m -> m %/ d * d = m.\n\n(*This lemma states that, given that one natural number divides another, an inequality asserting that their quotient is less than or equal to a third number is equivalent to an inequality asserting that the dividend is less than or equal to the product of the third number and the divisor.*)\nLemma leq_divLR d m n : d %| m -> (m %/ d <= n) = (m <= n * d).\n\n(*This lemma states that, given that one natural number divides another, a strict inequality asserting that a third number is less than their quotient is equivalent to an inequality asserting that the product of the third number and the divisor is strictly less than the dividend.*)\nLemma ltn_divRL d m n : d %| m -> (n < m %/ d) = (n * d < m).\n\n(*This lemma states that for a positive natural number that divides a second natural number, the boolean equality between a third natural number and the quotient is equivalent to the equality between the product of the third number and the divisor, and the dividend.*)\nLemma eqn_div d m n : d > 0 -> d %| m -> (n == m %/ d) = (n * d == m).\n\n(*This lemma states that for a positive natural number that divides a second natural number, the boolean equality between the second number and the product of a third number and the divisor is equivalent to the equality between the quotient and the third number.*)\nLemma eqn_mul d m n : d > 0 -> d %| m -> (m == n * d) = (m %/ d == n).\n\n(*This lemma states that if a natural number divides another, then the product of their quotient and a third natural number is equal to the quotient of the product of the dividend and the third number, divided by the original divisor.*)\nLemma divn_mulAC d m n : d %| m -> m %/ d * n = m * n %/ d.\n\n(*This lemma states that if a natural number divides another, the product of a third number and the quotient is equal to the quotient of the product of the third number and the dividend, divided by the divisor.*)\nLemma muln_divA d m n : d %| n -> m * (n %/ d) = m * n %/ d.\n\n(*This lemma states that if a natural number divides two other natural numbers, then the product of the first of these two numbers and the quotient of the second with the divisor is equal to the product of the second of these two numbers and the quotient of the first with the divisor.*)\nLemma muln_divCA d m n : d %| m -> d %| n -> m * (n %/ d) = n * (m %/ d).\n\n(*This lemma relates division by a quotient, stating that if a first natural number divides a second, then dividing a third number by the quotient of the second and first is equivalent to dividing the product of the third and first numbers by the second number.*)\nLemma divnA m n p : p %| n -> m %/ (n %/ p) = m * p %/ n.\n\n(*This lemma states that if a first natural number divides a second, the remainder of a third number modulo the first is equal to the remainder of (the third number modulo the second) modulo the first.*)\nLemma modn_dvdm m n d : d %| m -> n %% m = n %[mod d].\n\n(*This lemma states that if a natural number divides a positive natural number, then the divisor is less than or equal to the dividend.*)\nLemma dvdn_leq d m : 0 < m -> d %| m -> d <= m.\n\n(*This lemma states that it is false for a natural number to divide a smaller, positive natural number.*)\nLemma gtnNdvd n d : 0 < n -> n < d -> (d %| n) = false.\n\n(*This lemma states that two natural numbers are equal if and only if each number divides the other.*)\nLemma eqn_dvd m n : (m == n) = (m %| n) && (n %| m).\n\n(*This lemma states that for a positive natural number, the boolean indicating whether the product of this number and a second one divides the product of this number and a third one is equivalent to the boolean indicating whether the second number divides the third.*)\nLemma dvdn_pmul2l p d m : 0 < p -> (p * d %| p * m) = (d %| m).\n\nArguments dvdn_pmul2l [p d m].\n\n(*This lemma states that for a positive natural number, the boolean indicating whether the product of a second number and this number divides the product of a third number and this number is equivalent to the boolean indicating whether the second number divides the third.*)\nLemma dvdn_pmul2r p d m : 0 < p -> (d * p %| m * p) = (d %| m).\n\nArguments dvdn_pmul2r [p d m].\n\n(*This lemma states that for a positive divisor that divides a dividend, the property that their quotient divides a third number is equivalent to the property that the dividend divides the product of the third number and the positive divisor.*)\nLemma dvdn_divLR p d m : 0 < p -> p %| d -> (d %/ p %| m) = (d %| m * p).\n\n(*This lemma states that if a first natural number divides a second one, then the property that a third number divides the quotient of the second and the first is equivalent to the property that the product of the third and first numbers divides the second number.*)\nLemma dvdn_divRL p d m : p %| m -> (d %| m %/ p) = (d * p %| m).\n\n(*This lemma states that if a natural number divides another, then their quotient also divides the dividend.*)\nLemma dvdn_div d m : d %| m -> m %/ d %| m.\n\n(*This lemma states that if one natural number is less than or equal to another, then a third natural number raised to the power of the first divides the same base raised to the power of the second.*)\nLemma dvdn_exp2l p m n : m <= n -> p ^ m %| p ^ n.\n\n(*This lemma states that for a base natural number greater than one, the property that the base raised to a first exponent divides the base raised to a second exponent is equivalent to the property that the first exponent is less than or equal to the second.*)\nLemma dvdn_Pexp2l p m n : p > 1 -> (p ^ m %| p ^ n) = (m <= n).\n\n(*This lemma states that if a first natural number divides a second one, then the first number raised to any power divides the second number raised to the same power.*)\nLemma dvdn_exp2r m n k : m %| n -> m ^ k %| n ^ k.\n\n(*This lemma states a distributivity-like property for division over the modulo operation: if a divisor divides a modulus, then dividing the remainder of a third number by the divisor is equivalent to taking the remainder of the quotient of the third number and the divisor, modulo the quotient of the modulus and the divisor.*)\nLemma divn_modl m n d : d %| n -> (m %% n) %/ d = (m %/ d) %% (n %/ d).\n\n(*This lemma states that if a natural number divides a second one, the property that it also divides the sum of the second and a third number is equivalent to the property that it divides the third number.*)\nLemma dvdn_addr m d n : d %| m -> (d %| m + n) = (d %| n).\n\n(*This lemma states that if a natural number divides another natural number, then its divisibility of the sum of the second number and a third natural number is equivalent to its divisibility of the third number.*)\nLemma dvdn_addl n d m : d %| n -> (d %| m + n) = (d %| m).\n\n(*This lemma states that if a natural number divides two other natural numbers, it also divides their sum.*)\nLemma dvdn_add d m n : d %| m -> d %| n -> d %| m + n.\n\n(*This lemma states that if a natural number divides the sum of two other natural numbers, then either it divides both numbers or it divides neither of them.*)\nLemma dvdn_add_eq d m n : d %| m + n -> (d %| m) = (d %| n).\n\n(*This lemma states that for natural numbers where one is less than or equal to another, if a divisor divides the larger number, then its divisibility of their difference is equivalent to its divisibility of the smaller number.*)\nLemma dvdn_subr d m n : n <= m -> d %| m -> (d %| m - n) = (d %| n).\n\n(*This lemma states that for natural numbers where one is less than or equal to another, if a divisor divides the smaller number, then its divisibility of their difference is equivalent to its divisibility of the larger number.*)\nLemma dvdn_subl d m n : n <= m -> d %| n -> (d %| m - n) = (d %| m).\n\n(*This lemma states that if a natural number divides two other natural numbers, it also divides their difference.*)\nLemma dvdn_sub d m n : d %| m -> d %| n -> d %| m - n.\n\n(*This lemma states that if a natural number divides another natural number, it also divides any positive integer power of that number.*)\nLemma dvdn_exp k d m : 0 < k -> d %| m -> d %| (m ^ k).\n\n(*This lemma states that any positive natural number divides the factorial of any natural number greater than or equal to it.*)\nLemma dvdn_fact m n : 0 < m <= n -> m %| n`!.\n\n#[global] Hint Resolve dvdn_add dvdn_sub dvdn_exp : core.\n\n(*This lemma states that for two natural numbers where one is no more than the other, their congruence modulo a third natural number is equivalent to the third number dividing their difference.*)\nLemma eqn_mod_dvd d m n : n <= m -> (m == n %[mod d]) = (d %| m - n).\n\n(*This lemma states that for a positive divisor, the integer division of a sum, where one term is a multiple of the divisor, equals the sum of the integer division of the other term and the multiplier.*)\nLemma divnDMl q m d : 0 < d -> (m + q * d) %/ d = (m %/ d) + q.\n\n(*This lemma provides a formula for the quotient of a difference. It states that for a positive divisor, the quotient of the difference between a multiple of the divisor and another number is the multiplier minus the quotient of the other number, further reduced by one if the divisor does not divide that number.*)\nLemma divnMBl q m d : 0 < d -> (q * d - m) %/ d = q - (m %/ d) - (~~ (d %| m)).\n\n(*This lemma states that the quotient of the difference between a natural number and a multiple of a divisor is equal to the difference between the quotient of the number and the multiplier.*)\nLemma divnBMl q m d : (m - q * d) %/ d = (m %/ d) - q.\n\n(*This lemma states that if a natural number divides the first term of a sum, then the quotient of the sum by that number is equal to the sum of the individual quotients.*)\nLemma divnDl m n d : d %| m -> (m + n) %/ d = m %/ d + n %/ d.\n\n(*This lemma states that if a natural number divides the second term of a sum, then the quotient of the sum by that number is equal to the sum of the individual quotients.*)\nLemma divnDr m n d : d %| n -> (m + n) %/ d = m %/ d + n %/ d.\n\n(*This lemma states that if a divisor divides the minuend in a subtraction, the quotient of the difference is the quotient of the minuend minus the quotient of the subtrahend, further reduced by one if the divisor does not divide the subtrahend.*)\nLemma divnBl m n d : d %| m -> (m - n) %/ d = m %/ d - (n %/ d) - (~~ (d %| n)).\n\n(*This lemma states that if a natural number divides the subtrahend in a subtraction, then the quotient of the difference is equal to the difference of the individual quotients.*)\nLemma divnBr m n d : d %| n -> (m - n) %/ d = m %/ d - n %/ d.\n\n(*This lemma describes the result of Euclidean division for the successor of a natural number by a positive divisor. It states that if the divisor divides the successor, the quotient is the successor of the original number's quotient and the remainder is zero; otherwise, the quotient is unchanged and the remainder is the successor of the original remainder.*)\nLemma edivnS m d : 0 < d -> edivn m.+1 d =\n if d %| m.+1 then ((m %/ d).+1, 0) else (m %/ d, (m %% d).+1).\n\n(*This lemma describes the remainder of the successor of a natural number when divided by another. It states that the remainder is zero if the divisor divides the successor, and otherwise is the successor of the original number's remainder.*)\nLemma modnS m d : m.+1 %% d = if d %| m.+1 then 0 else (m %% d).+1.\n\n(*This lemma states that for a positive divisor, the quotient of the successor of a natural number is the quotient of the original number, incremented by one if the divisor divides the successor.*)\nLemma divnS m d : 0 < d -> m.+1 %/ d = (d %| m.+1) + m %/ d.\n\n(*This lemma relates the quotient of the predecessor of a natural number to the original quotient. It states that the quotient of the predecessor is obtained by subtracting one from the original quotient if the original number is a multiple of the divisor, and is otherwise unchanged.*)\nLemma divn_pred m d : m.-1 %/ d = (m %/ d) - (d %| m).\n\n(*This lemma describes the remainder for the predecessor of a positive natural number when divided by a divisor not equal to one. It states that if the original number is a multiple of the divisor, the remainder is the predecessor of the divisor; otherwise, it is the predecessor of the original remainder.*)\nLemma modn_pred m d : d != 1 -> 0 < m ->\n m.-1 %% d = if d %| m then d.-1 else (m %% d).-1.\n\n(*This lemma describes the result of Euclidean division for the predecessor of a positive natural number by a divisor not equal to one. It states that if the original number is a multiple of the divisor, the new quotient and remainder are the predecessors of the original quotient and the divisor, respectively; otherwise, the quotient is unchanged and the remainder is the predecessor of the original remainder.*)\nLemma edivn_pred m d : d != 1 -> 0 < m ->\n edivn m.-1 d = if d %| m then ((m %/ d).-1, d.-1) else (m %/ d, (m %% d).-1).\n\n(*This fixpoint defines a function to compute the greatest common divisor of two natural numbers using a recursive algorithm based on remainders.*)\nFixpoint gcdn m n :=\n let n' := n %% m in if n' is 0 then m else\n if m - n'.-1 is m'.+1 then gcdn (m' %% n') n' else n'.\nArguments gcdn : simpl never.\n\n(*This lemma provides an equivalent, simpler definition for the greatest common divisor function, stating that the greatest common divisor of two natural numbers is the second number if the first is zero, and is otherwise computed by recursively calling the function with the remainder of the second number divided by the first, and the first number.*)\nLemma gcdnE m n : gcdn m n = if m == 0 then n else gcdn (n %% m) m.\n\n(*This lemma states that the greatest common divisor operation is idempotent, meaning the greatest common divisor of a natural number with itself is that number.*)\nLemma gcdnn : idempotent_op gcdn.\n\n(*This lemma states that the greatest common divisor operation is commutative, meaning the result is independent of the order of the two natural number inputs.*)\nLemma gcdnC : commutative gcdn.\n\n(*This lemma states that zero is a left identity for the greatest common divisor operation, meaning the greatest common divisor of zero and any natural number is that number.*)\nLemma gcd0n : left_id 0 gcdn. \n(*This lemma states that zero is a right identity for the greatest common divisor operation, meaning the greatest common divisor of any natural number and zero is that number.*)\nLemma gcdn0 : right_id 0 gcdn. \n\n(*This lemma states that one is a left absorbing element for the greatest common divisor operation, meaning the greatest common divisor of one and any natural number is one.*)\nLemma gcd1n : left_zero 1 gcdn.\n\n(*This lemma states that one is a right absorbing element for the greatest common divisor operation, meaning the greatest common divisor of any natural number and one is one.*)\nLemma gcdn1 : right_zero 1 gcdn.\n\n(*This lemma states that the greatest common divisor of two natural numbers divides the second number.*)\nLemma dvdn_gcdr m n : gcdn m n %| n.\n\n(*This lemma states that the greatest common divisor of two natural numbers divides the first number.*)\nLemma dvdn_gcdl m n : gcdn m n %| m.\n\n(*This lemma states that the greatest common divisor of two natural numbers is greater than zero if and only if at least one of the two numbers is greater than zero.*)\nLemma gcdn_gt0 m n : (0 < gcdn m n) = (0 < m) || (0 < n).\n\n(*This lemma states that the greatest common divisor of a first natural number and the sum of a multiple of that number with a second natural number is equal to the greatest common divisor of the first and second numbers.*)\nLemma gcdnMDl k m n : gcdn m (k * m + n) = gcdn m n.\n\n(*This lemma states that the greatest common divisor of a first natural number and the sum of that number with a second natural number is equal to the greatest common divisor of the first and second numbers.*)\nLemma gcdnDl m n : gcdn m (m + n) = gcdn m n.\n\n(*This lemma states that the greatest common divisor of a first natural number and the sum of a second number with the first is equal to the greatest common divisor of the first and second numbers.*)\nLemma gcdnDr m n : gcdn m (n + m) = gcdn m n.\n\n(*This lemma states that the greatest common divisor of a natural number and a multiple of that number is the number itself.*)\nLemma gcdnMl n m : gcdn n (m * n) = n.\n\n(*This lemma states that the greatest common divisor of a natural number and the product of that number with another natural number is the number itself.*)\nLemma gcdnMr n m : gcdn n (n * m) = n.\n\n(*This lemma establishes the equivalence between two properties: that the greatest common divisor of two natural numbers is equal to the first number, and that the first number divides the second.*)\nLemma gcdn_idPl {m n} : reflect (gcdn m n = m) (m %| n).\n\n(*This lemma establishes the equivalence between two properties: that the greatest common divisor of two natural numbers is equal to the second number, and that the second number divides the first.*)\nLemma gcdn_idPr {m n} : reflect (gcdn m n = n) (n %| m).\n\n(*This lemma states that for three natural numbers, raising the first number to the power of the minimum of the other two is equal to the greatest common divisor of the first number raised to the second and the first number raised to the third.*)\nLemma expn_min e m n : e ^ minn m n = gcdn (e ^ m) (e ^ n).\n\n(*This lemma states that the greatest common divisor of two natural numbers is equal to the greatest common divisor of the first number and the remainder of the division of the second number by the first.*)\nLemma gcdn_modr m n : gcdn m (n %% m) = gcdn m n.\n\n(*This lemma states that the greatest common divisor of two natural numbers is equal to the greatest common divisor of the remainder of the division of the first number by the second and the second number itself.*)\nLemma gcdn_modl m n : gcdn (m %% n) n = gcdn m n.\n\n(*This fixpoint defines a recursive helper function that computes B\u00e9zout coefficients from a sequence of quotients generated by the extended Euclidean algorithm.*)\nFixpoint Bezout_rec km kn qs :=\n if qs is q :: qs' then Bezout_rec kn (NatTrec.add_mul q kn km) qs'\n else (km, kn).\n\n(*This fixpoint defines a tail-recursive function that implements the extended Euclidean algorithm to compute a list of quotients, using a natural number as a fuel parameter to ensure termination.*)\nFixpoint egcdn_rec m n s qs :=\n if s is s'.+1 then\n let: (q, r) := edivn m n in\n if r > 0 then egcdn_rec n r s' (q :: qs) else\n if odd (size qs) then qs else q.-1 :: qs\n else [::0].\n\n(*This definition computes the B\u00e9zout coefficients for two natural numbers by first generating the sequence of quotients using a recursive version of the extended Euclidean algorithm and then processing this sequence to find the coefficients.*)\nDefinition egcdn m n := Bezout_rec 0 1 (egcdn_rec m n n [::]).\n\n(*This variant defines the specification for the output of the extended Euclidean algorithm. It asserts that a given pair of natural numbers represents valid B\u00e9zout coefficients by satisfying both the B\u00e9zout identity and a specific bound on the second coefficient.*)\nVariant egcdn_spec m n : nat * nat -> Type :=\n EgcdnSpec km kn of km * m = kn * n + gcdn m n & kn * gcdn m n < m :\n egcdn_spec m n (km, kn).\n\n(*This lemma states that the result of the extended Euclidean algorithm for inputs zero and any natural number is the pair of coefficients one and zero.*)\nLemma egcd0n n : egcdn 0 n = (1, 0).\n\n(*This lemma states that if the first of two natural number inputs is positive, the output of the extended Euclidean algorithm on these numbers satisfies its corresponding specification, proving the correctness of the algorithm.*)\nLemma egcdnP m n : m > 0 -> egcdn_spec m n (egcdn m n).\n\n(*This lemma, a form of B\u00e9zout's identity, states that for two natural numbers where the first is positive, there exists another natural number, which is smaller than the first, such that the first number divides the sum of the greatest common divisor and the product of this third number and the second number.*)\nLemma Bezoutl m n : m > 0 -> {a | a < m & m %| gcdn m n + a * n}.\n\n(*This lemma, a symmetric form of B\u00e9zout's identity, states that for two natural numbers where the second is positive, there exists another natural number, which is smaller than the second, such that the second number divides the sum of the greatest common divisor and the product of this third number and the first number.*)\nLemma Bezoutr m n : n > 0 -> {a | a < n & n %| gcdn m n + a * m}.\n\n(*This lemma states that a natural number divides the greatest common divisor of two other natural numbers if and only if it divides both of those numbers.*)\nLemma dvdn_gcd p m n : p %| gcdn m n = (p %| m) && (p %| n).\n\n(*This lemma states that the greatest common divisor operation is right-commutative, meaning that the order of the second and third arguments can be swapped within a nested application of the operation.*)\nLemma gcdnAC : right_commutative gcdn.\n\n(*This lemma states that the greatest common divisor operation is associative.*)\nLemma gcdnA : associative gcdn.\n\n(*This lemma states that the greatest common divisor operation is left-commutative, meaning that the first and second arguments can be swapped within a nested application of the operation.*)\nLemma gcdnCA : left_commutative gcdn.\n\n(*This lemma states that the greatest common divisor operation interchanges with itself, allowing the regrouping of arguments in a nested application.*)\nLemma gcdnACA : interchange gcdn gcdn.\n\n(*This lemma states that multiplication of natural numbers is right-distributive over the greatest common divisor operation.*)\nLemma muln_gcdr : right_distributive muln gcdn.\n\n(*This lemma states that multiplication of natural numbers is left-distributive over the greatest common divisor operation.*)\nLemma muln_gcdl : left_distributive muln gcdn.\n\n(*This lemma provides the universal property of the greatest common divisor: if a natural number is a common divisor of two other numbers, and any other common divisor also divides it, then it is equal to their greatest common divisor.*)\nLemma gcdn_def d m n :\n d %| m -> d %| n -> (forall d', d' %| m -> d' %| n -> d' %| d) ->\n gcdn m n = d.\n\n(*This lemma states that for two natural numbers, the product of the first number and the quotient of the second by their greatest common divisor is equal to the product of the second number and the quotient of the first by their greatest common divisor.*)\nLemma muln_divCA_gcd n m : n * (m %/ gcdn n m) = m * (n %/ gcdn n m).\n\n(*This definition establishes the least common multiple of two natural numbers as the result of their product divided by their greatest common divisor.*)\nDefinition lcmn m n := m * n %/ gcdn m n.\n\n(*This lemma states that the least common multiple operation is commutative, meaning the order of the two natural number inputs does not affect the result.*)\nLemma lcmnC : commutative lcmn.\n\n(*This lemma states that the least common multiple of zero and any natural number is zero.*)\nLemma lcm0n : left_zero 0 lcmn. \n(*This lemma states that the least common multiple of any natural number and zero is zero.*)\nLemma lcmn0 : right_zero 0 lcmn. \n\n(*This lemma states that one is the left identity for the least common multiple operation, meaning the least common multiple of one and any natural number is that natural number itself.*)\nLemma lcm1n : left_id 1 lcmn.\n\n(*This lemma states that one is the right identity for the least common multiple operation, meaning the least common multiple of any natural number and one is that natural number itself.*)\nLemma lcmn1 : right_id 1 lcmn.\n\n(*This lemma states that the product of the least common multiple and the greatest common divisor of two natural numbers is equal to the product of the two natural numbers themselves.*)\nLemma muln_lcm_gcd m n : lcmn m n * gcdn m n = m * n.\n\n(*This lemma states that the least common multiple of two natural numbers is greater than zero if and only if both of the input natural numbers are greater than zero.*)\nLemma lcmn_gt0 m n : (0 < lcmn m n) = (0 < m) && (0 < n).\n\n(*This lemma states that multiplication of natural numbers is right-distributive over the least common multiple operation. This means multiplying the least common multiple of two numbers by a third number yields the same result as taking the least common multiple of the products of each of the first two numbers with the third.*)\nLemma muln_lcmr : right_distributive muln lcmn.\n\n(*This lemma states that multiplication of natural numbers is left-distributive over the least common multiple operation. This means multiplying a number by the least common multiple of two other numbers yields the same result as taking the least common multiple of the products of the first number with each of the other two.*)\nLemma muln_lcml : left_distributive muln lcmn.\n\n(*This lemma states that the least common multiple operation is associative, meaning that when finding the least common multiple of three natural numbers, the grouping of the operations does not affect the final result.*)\nLemma lcmnA : associative lcmn.\n\n(*This lemma states a left-commutative property for the least common multiple operation, where the least common multiple of a number with the least common multiple of two others is equal to the least common multiple of the second number with the least common multiple of the first and third.*)\nLemma lcmnCA : left_commutative lcmn.\n\n(*This lemma states a right-commutative property for the least common multiple operation, where the least common multiple of two numbers, when combined with a third, is equal to the least common multiple of the first and third numbers, combined with the second.*)\nLemma lcmnAC : right_commutative lcmn.\n\n(*This lemma states that the least common multiple operation interchanges with itself. This means that the least common multiple of two least common multiples can be regrouped by taking the least common multiples of the corresponding components.*)\nLemma lcmnACA : interchange lcmn lcmn.\n\n(*This lemma states that any natural number divides the least common multiple of itself and another natural number.*)\nLemma dvdn_lcml d1 d2 : d1 %| lcmn d1 d2.\n\n(*This lemma states that for any two natural numbers, the second number divides their least common multiple.*)\nLemma dvdn_lcmr d1 d2 : d2 %| lcmn d1 d2.\n\n(*This lemma states that the least common multiple of two natural numbers divides a third natural number if and only if each of the two original numbers individually divides that third number.*)\nLemma dvdn_lcm d1 d2 m : lcmn d1 d2 %| m = (d1 %| m) && (d2 %| m).\n\n(*This lemma states that the least common multiple of a natural number and its product with another natural number is equal to that product.*)\nLemma lcmnMl m n : lcmn m (m * n) = m * n.\n\n(*This lemma states that the least common multiple of a natural number and a product containing it as a factor is equal to that product.*)\nLemma lcmnMr m n : lcmn n (m * n) = m * n.\n\n(*This lemma states that the least common multiple of two natural numbers is equal to the second number if and only if the first number divides the second number.*)\nLemma lcmn_idPr {m n} : reflect (lcmn m n = n) (m %| n).\n\n(*This lemma states that the least common multiple of two natural numbers is equal to the first number if and only if the second number divides the first number.*)\nLemma lcmn_idPl {m n} : reflect (lcmn m n = m) (n %| m).\n\n(*This lemma states that a natural number raised to the power of the maximum of two other natural numbers is equal to the least common multiple of the base raised to each of those two powers.*)\nLemma expn_max e m n : e ^ maxn m n = lcmn (e ^ m) (e ^ n).\n\n(*This definition establishes that two natural numbers are coprime if their greatest common divisor is equal to one.*)\nDefinition coprime m n := gcdn m n == 1.\n\n(*This lemma states that the natural number one is coprime to any other natural number.*)\nLemma coprime1n n : coprime 1 n.\n\n(*This lemma states that any natural number is coprime to the natural number one.*)\nLemma coprimen1 n : coprime n 1.\n\n(*This lemma states that the coprimality relation between two natural numbers is symmetric, meaning the order of the numbers does not affect whether they are coprime.*)\nLemma coprime_sym m n : coprime m n = coprime n m.\n\n(*This lemma states that two natural numbers are coprime if and only if the remainder of the first number divided by the second is coprime to the second number.*)\nLemma coprime_modl m n : coprime (m %% n) n = coprime m n.\n\n(*This lemma states that two natural numbers are coprime if and only if the first number is coprime to the remainder of the second number divided by the first.*)\nLemma coprime_modr m n : coprime m (n %% m) = coprime m n.\n\n(*This lemma states that a natural number is coprime to two if and only if that number is odd.*)\nLemma coprime2n n : coprime 2 n = odd n.\n\n(*This lemma states that two is coprime to a natural number if and only if that number is odd.*)\nLemma coprimen2 n : coprime n 2 = odd n.\n\n(*This lemma states that for any natural number, its successor is coprime to it.*)\nLemma coprimeSn n : coprime n.+1 n.\n\n(*This lemma states that any natural number is coprime to its successor.*)\nLemma coprimenS n : coprime n n.+1.\n\n(*This lemma states that for any positive natural number, its predecessor is coprime to it.*)\nLemma coprimePn n : n > 0 -> coprime n.-1 n.\n\n(*This lemma states that any positive natural number is coprime to its predecessor.*)\nLemma coprimenP n : n > 0 -> coprime n n.-1.\n\n(*This lemma states that for a positive natural number and another natural number, they are coprime if and only if there exists a pair of natural numbers such that the first natural number multiplied by the first element of the pair minus the second natural number multiplied by the second element of the pair equals one.*)\nLemma coprimeP n m :\n n > 0 -> reflect (exists u, u.1 * n - u.2 * m = 1) (coprime n m).\n\n(*This lemma states that if a first natural number is positive and there exists a second natural number whose product with the first, taken modulo a third natural number, is equal to one, then the first and third natural numbers are coprime.*)\nLemma modn_coprime k n : 0 < k -> (exists u, (k * u) %% n = 1) -> coprime k n.\n\n(*This lemma states that if two natural numbers are coprime, their product divides a third natural number if and only if each of the two numbers individually divides the third.*)\nLemma Gauss_dvd m n p : coprime m n -> (m * n %| p) = (m %| p) && (n %| p).\n\n(*This lemma states that if a first natural number is coprime to a second, then the first number divides the product of the second and a third natural number if and only if the first number divides the third.*)\nLemma Gauss_dvdr m n p : coprime m n -> (m %| n * p) = (m %| p).\n\n(*This lemma states that if a first natural number is coprime to a third, then the first number divides the product of the second and third natural numbers if and only if the first number divides the second.*)\nLemma Gauss_dvdl m n p : coprime m p -> (m %| n * p) = (m %| n).\n\n(*This lemma states that if an odd natural number divides a positive even natural number, then twice the odd number is less than or equal to the even number.*)\nLemma dvdn_double_leq m n : m %| n -> odd m -> ~~ odd n -> 0 < n -> m.*2 <= n.\n\n(*This lemma states that if an odd natural number divides the predecessor of another odd natural number greater than one, then twice the first number is strictly less than the second.*)\nLemma dvdn_double_ltn m n : m %| n.-1 -> odd m -> odd n -> 1 < n -> m.*2 < n.\n\n(*This lemma states that if a first natural number is coprime to a second, then the greatest common divisor of the first number and the product of the second and a third natural number is equal to the greatest common divisor of the first and third numbers.*)\nLemma Gauss_gcdr p m n : coprime p m -> gcdn p (m * n) = gcdn p n.\n\n(*This lemma states that if a first natural number is coprime to a third, then the greatest common divisor of the first number and the product of the second and third natural numbers is equal to the greatest common divisor of the first and second numbers.*)\nLemma Gauss_gcdl p m n : coprime p n -> gcdn p (m * n) = gcdn p m.\n\n(*This lemma states that a natural number is coprime to a product of two other natural numbers if and only if it is coprime to each of the factors individually.*)\nLemma coprimeMr p m n : coprime p (m * n) = coprime p m && coprime p n.\n\n(*This lemma states that the product of two natural numbers is coprime to a third natural number if and only if each of the two numbers is individually coprime to the third.*)\nLemma coprimeMl p m n : coprime (m * n) p = coprime m p && coprime n p.\n\n(*This lemma states that for a positive exponent, a natural number raised to that exponent is coprime to a second natural number if and only if the base is coprime to the second number.*)\nLemma coprime_pexpl k m n : 0 < k -> coprime (m ^ k) n = coprime m n.\n\n(*This lemma states that for a positive exponent, a first natural number is coprime to a second natural number raised to that exponent if and only if the first number is coprime to the base.*)\nLemma coprime_pexpr k m n : 0 < k -> coprime m (n ^ k) = coprime m n.\n\n(*This lemma states that if two natural numbers are coprime, then any power of the first number is also coprime to the second number.*)\nLemma coprimeXl k m n : coprime m n -> coprime (m ^ k) n.\n\n(*This lemma states that if two natural numbers are coprime, then the first number is also coprime to any power of the second number.*)\nLemma coprimeXr k m n : coprime m n -> coprime m (n ^ k).\n\n(*This lemma states that if a first natural number divides a second, and the second is coprime to a third, then the first is also coprime to the third.*)\nLemma coprime_dvdl m n p : m %| n -> coprime n p -> coprime m p.\n\n(*This lemma states that if a first natural number divides a second, and a third number is coprime to the second, then the third is also coprime to the first.*)\nLemma coprime_dvdr m n p : m %| n -> coprime p n -> coprime p m.\n\n(*This lemma states that for a positive natural number and another natural number, the two components of the pair returned by the extended Euclidean algorithm are coprime.*)\nLemma coprime_egcdn n m : n > 0 -> coprime (egcdn n m).1 (egcdn n m).2.\n\n(*This lemma states that for a positive exponent, a first natural number raised to that exponent divides a second natural number raised to the same exponent if and only if the first number divides the second.*)\nLemma dvdn_pexp2r m n k : k > 0 -> (m ^ k %| n ^ k) = (m %| n).\n\nSection Chinese.\n\nVariables m1 m2 : nat.\nHypothesis co_m12 : coprime m1 m2.\n\n(*This lemma states that for two coprime natural number moduli, two numbers are congruent modulo their product if and only if they are congruent modulo each of the individual moduli.*)\nLemma chinese_remainder x y :\n (x == y %[mod m1 * m2]) = (x == y %[mod m1]) && (x == y %[mod m2]).\n\n(*This definition provides a constructive solution to the Chinese Remainder Theorem for two coprime moduli. It computes a number that is congruent to a first given remainder modulo the first modulus, and congruent to a second given remainder modulo the second modulus.*)\nDefinition chinese r1 r2 :=\n r1 * m2 * (egcdn m2 m1).1 + r2 * m1 * (egcdn m1 m2).1.\n\n(*This lemma states that the number constructed by the `chinese` function for two given remainders is congruent to the first remainder modulo the first modulus.*)\nLemma chinese_modl r1 r2 : chinese r1 r2 = r1 %[mod m1].\n\n(*This lemma states that the number constructed by the `chinese` function for two given remainders is congruent to the second remainder modulo the second modulus.*)\nLemma chinese_modr r1 r2 : chinese r1 r2 = r2 %[mod m2].\n\n(*This lemma states that any natural number is congruent, modulo the product of the two coprime moduli, to the value constructed by the `chinese` function from its own remainders with respect to these moduli.*)\nLemma chinese_mod x : x = chinese (x %% m1) (x %% m2) %[mod m1 * m2].", - "boot.ssrAC": "From HB Require Import structures.\nFrom Corelib Require Import PosDef.\n\nSet Warnings \"-hiding-delimiting-key\".\nFrom mathcomp Require Import ssreflect ssrbool ssrfun ssrnat eqtype seq bigop.\nSet Warnings \"hiding-delimiting-key\".\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope AC_scope.\n\nDelimit Scope AC_scope with AC.\n\nReserved Notation \"op .[ 'ACof' p s ]\" (p at level 1, left associativity).\nReserved Notation \"op .[ 'AC' p s ]\" (p at level 1, left associativity).\nReserved Notation \"op .[ 'ACl' s ]\" (left associativity).\n\n(*This definition changes the type of a given value to a new type, provided a proof that the original and new types are equal.*)\nDefinition change_type ty ty' (x : ty) (strategy : ty = ty') : ty' :=\n ecast ty ty strategy x.\n(*A notation for a tactic that first simplifies the goal expression and then attempts to prove it by reflexivity.*)\nNotation simplrefl := (ltac: (simpl; reflexivity)) (only parsing).\n(*A notation for a tactic that performs a call-by-value reduction on the goal expression and then attempts to prove it by reflexivity.*)\nNotation cbvrefl := (ltac: (cbv; reflexivity)) (only parsing).\n(*A notation for a tactic that uses the virtual machine to compute the goal expression and then attempts to prove it by reflexivity.*)\nNotation vmrefl := (ltac: (vm_compute; reflexivity)) (only parsing).\n\nModule Pos.\n\nImport Pos.\n\n(*A local notation defining the positive number ten, used as a base for decimal-to-binary conversions.*)\nLocal Notation ten := (xO (xI (xO xH))).\n\n(*This recursive function converts a sequence of decimal digits, representing an unsigned integer, into its corresponding positive number value. It processes the digits using an accumulator, which is multiplied by ten at each step.*)\nFixpoint of_uint_acc (d:Decimal.uint) (acc:positive) :=\n match d with\n | Decimal.Nil => acc\n | Decimal.D0 l => of_uint_acc l (mul ten acc)\n | Decimal.D1 l => of_uint_acc l (add 1 (mul ten acc))\n | Decimal.D2 l => of_uint_acc l (add 1~0 (mul ten acc))\n | Decimal.D3 l => of_uint_acc l (add 1~1 (mul ten acc))\n | Decimal.D4 l => of_uint_acc l (add 1~0~0 (mul ten acc))\n | Decimal.D5 l => of_uint_acc l (add 1~0~1 (mul ten acc))\n | Decimal.D6 l => of_uint_acc l (add 1~1~0 (mul ten acc))\n | Decimal.D7 l => of_uint_acc l (add 1~1~1 (mul ten acc))\n | Decimal.D8 l => of_uint_acc l (add 1~0~0~0 (mul ten acc))\n | Decimal.D9 l => of_uint_acc l (add 1~0~0~1 (mul ten acc))\n end.\n\n(*This function converts a sequence of decimal digits, representing an unsigned integer, into its corresponding natural number value. It properly handles leading zeros.*)\nFixpoint of_uint (d:Decimal.uint) : N :=\n match d with\n | Decimal.Nil => N0\n | Decimal.D0 l => of_uint l\n | Decimal.D1 l => Npos (of_uint_acc l 1)\n | Decimal.D2 l => Npos (of_uint_acc l 1~0)\n | Decimal.D3 l => Npos (of_uint_acc l 1~1)\n | Decimal.D4 l => Npos (of_uint_acc l 1~0~0)\n | Decimal.D5 l => Npos (of_uint_acc l 1~0~1)\n | Decimal.D6 l => Npos (of_uint_acc l 1~1~0)\n | Decimal.D7 l => Npos (of_uint_acc l 1~1~1)\n | Decimal.D8 l => Npos (of_uint_acc l 1~0~0~0)\n | Decimal.D9 l => Npos (of_uint_acc l 1~0~0~1)\n end.\n\n(*A local notation defining the positive number sixteen, used as a base for hexadecimal-to-binary conversions.*)\nLocal Notation sixteen := (xO (xO (xO (xO xH)))).\n\n(*This recursive function converts a sequence of hexadecimal digits, representing an unsigned integer, into its corresponding positive number value. It processes the digits using an accumulator, which is multiplied by sixteen at each step.*)\nFixpoint of_hex_uint_acc (d:Hexadecimal.uint) (acc:positive) :=\n match d with\n | Hexadecimal.Nil => acc\n | Hexadecimal.D0 l => of_hex_uint_acc l (mul sixteen acc)\n | Hexadecimal.D1 l => of_hex_uint_acc l (add 1 (mul sixteen acc))\n | Hexadecimal.D2 l => of_hex_uint_acc l (add 1~0 (mul sixteen acc))\n | Hexadecimal.D3 l => of_hex_uint_acc l (add 1~1 (mul sixteen acc))\n | Hexadecimal.D4 l => of_hex_uint_acc l (add 1~0~0 (mul sixteen acc))\n | Hexadecimal.D5 l => of_hex_uint_acc l (add 1~0~1 (mul sixteen acc))\n | Hexadecimal.D6 l => of_hex_uint_acc l (add 1~1~0 (mul sixteen acc))\n | Hexadecimal.D7 l => of_hex_uint_acc l (add 1~1~1 (mul sixteen acc))\n | Hexadecimal.D8 l => of_hex_uint_acc l (add 1~0~0~0 (mul sixteen acc))\n | Hexadecimal.D9 l => of_hex_uint_acc l (add 1~0~0~1 (mul sixteen acc))\n | Hexadecimal.Da l => of_hex_uint_acc l (add 1~0~1~0 (mul sixteen acc))\n | Hexadecimal.Db l => of_hex_uint_acc l (add 1~0~1~1 (mul sixteen acc))\n | Hexadecimal.Dc l => of_hex_uint_acc l (add 1~1~0~0 (mul sixteen acc))\n | Hexadecimal.Dd l => of_hex_uint_acc l (add 1~1~0~1 (mul sixteen acc))\n | Hexadecimal.De l => of_hex_uint_acc l (add 1~1~1~0 (mul sixteen acc))\n | Hexadecimal.Df l => of_hex_uint_acc l (add 1~1~1~1 (mul sixteen acc))\n end.\n\n(*This function converts a sequence of hexadecimal digits, representing an unsigned integer, into its corresponding natural number value. It properly handles leading zeros.*)\nFixpoint of_hex_uint (d:Hexadecimal.uint) : N :=\n match d with\n | Hexadecimal.Nil => N0\n | Hexadecimal.D0 l => of_hex_uint l\n | Hexadecimal.D1 l => Npos (of_hex_uint_acc l 1)\n | Hexadecimal.D2 l => Npos (of_hex_uint_acc l 1~0)\n | Hexadecimal.D3 l => Npos (of_hex_uint_acc l 1~1)\n | Hexadecimal.D4 l => Npos (of_hex_uint_acc l 1~0~0)\n | Hexadecimal.D5 l => Npos (of_hex_uint_acc l 1~0~1)\n | Hexadecimal.D6 l => Npos (of_hex_uint_acc l 1~1~0)\n | Hexadecimal.D7 l => Npos (of_hex_uint_acc l 1~1~1)\n | Hexadecimal.D8 l => Npos (of_hex_uint_acc l 1~0~0~0)\n | Hexadecimal.D9 l => Npos (of_hex_uint_acc l 1~0~0~1)\n | Hexadecimal.Da l => Npos (of_hex_uint_acc l 1~0~1~0)\n | Hexadecimal.Db l => Npos (of_hex_uint_acc l 1~0~1~1)\n | Hexadecimal.Dc l => Npos (of_hex_uint_acc l 1~1~0~0)\n | Hexadecimal.Dd l => Npos (of_hex_uint_acc l 1~1~0~1)\n | Hexadecimal.De l => Npos (of_hex_uint_acc l 1~1~1~0)\n | Hexadecimal.Df l => Npos (of_hex_uint_acc l 1~1~1~1)\n end.\n\n(*This definition converts a signed decimal integer into an optional positive number. It yields a positive number if the input is positive and non-zero, and returns nothing otherwise.*)\nDefinition of_int (d:Decimal.int) : option positive :=\n match d with\n | Decimal.Pos d =>\n match of_uint d with\n | N0 => None\n | Npos p => Some p\n end\n | Decimal.Neg _ => None\n end.\n\n(*This definition converts a signed hexadecimal integer into an optional positive number. It yields a positive number if the input is positive and non-zero, and returns nothing otherwise.*)\nDefinition of_hex_int (d:Hexadecimal.int) : option positive :=\n match d with\n | Hexadecimal.Pos d =>\n match of_hex_uint d with\n | N0 => None\n | Npos p => Some p\n end\n | Hexadecimal.Neg _ => None\n end.\n\n(*This definition converts a signed integer, which can be represented in either decimal or hexadecimal format, into an optional positive number.*)\nDefinition of_num_int (d:Number.int) : option positive :=\n match d with\n | Number.IntDecimal d => of_int d\n | Number.IntHexadecimal d => of_hex_int d\n end.\n\n(*This function converts a positive number from its binary representation into a sequence of decimal digits in little-endian order, where the least significant digit comes first.*)\nFixpoint to_little_uint p :=\n match p with\n | xH => Decimal.D1 Decimal.Nil\n | xI p => Decimal.Little.succ_double (to_little_uint p)\n | xO p => Decimal.Little.double (to_little_uint p)\n end.\n\n(*This definition converts a positive number into a sequence of decimal digits in standard big-endian order.*)\nDefinition to_uint p := Decimal.rev (to_little_uint p).\n\n(*This definition converts a positive number into a generic unsigned integer representation by first converting it to a sequence of decimal digits.*)\nDefinition to_num_uint p := Number.UIntDecimal (to_uint p).\n\n(*This definition computes the successor of a natural number, handling both the zero case and the case of a positive number.*)\nDefinition Nsucc n :=\n match n with\n | N0 => Npos xH\n | Npos p => Npos (Pos.succ p)\n end.\n\n(*This lemma states that converting the successor of a natural number to the standard natural number type is equivalent to adding one to the standard natural number conversion of the original number.*)\nLemma nat_of_succ_bin b : nat_of_bin (Nsucc b) = 1 + nat_of_bin b :> nat.\n\n(*This theorem states that the boolean equality test for two positive numbers returns true if and only if the two numbers are equal.*)\nTheorem eqb_eq p q : Pos.eqb p q = true <-> p=q.\n\nEnd Pos.\n\nModule AC.\n\n(*An inductive type for representing binary expression trees, where each leaf holds a positive number and each internal node represents a binary operation combining two sub-expressions.*)\nInductive syntax := Leaf of positive | Op of syntax & syntax.\nCoercion serial := (fix loop (acc : seq positive) (s : syntax) :=\n match s with\n | Leaf n => n :: acc\n | Op s s' => (loop^~ s (loop^~ s' acc))\n end) [::].\n\n(*This lemma states that serializing a binary expression tree node into a sequence of positive numbers is equivalent to concatenating the sequences obtained from serializing its left and right sub-expressions.*)\nLemma serial_Op s1 s2 : Op s1 s2 = s1 ++ s2 :> seq _.\n\n(*This definition provides a conversion from a natural number to a leaf in a binary expression tree, holding the corresponding positive number value.*)\nDefinition Leaf_of_nat n := Leaf (Pos.sub (pos_of_nat n n) xH).\n\nModule Import Syntax.\nBind Scope AC_scope with syntax.\nNumber Notation positive Pos.of_num_int Pos.to_num_uint : AC_scope.\nCoercion Leaf : positive >-> syntax.\nCoercion Leaf_of_nat : nat >-> syntax.\n(*A notation that defines the asterisk symbol as the constructor for an internal node in a binary expression tree, representing a binary operation between two sub-expressions.*)\nNotation \"x * y\" := (Op x%AC y%AC) : AC_scope.\nEnd Syntax.\n\n(*This definition transforms a given binary expression tree into a new one by replacing the positive numbers in its leaves. A leaf containing the number one is treated as a placeholder for a new variable, while a leaf with a number greater than one is expanded into a sub-tree of that many new, consecutive variables. The transformation is applied recursively to build the final pattern.*)\nDefinition pattern (s : syntax) := ((fix loop n s :=\n match s with\n | Leaf 1%positive => (Leaf n, Pos.succ n)\n | Leaf m => Pos.iter (fun oi => (Op oi.1 (Leaf oi.2), Pos.succ oi.2))\n (Leaf n, Pos.succ n) (Pos.sub m xH)\n | Op s s' => let: (p, n') := loop n s in\n let: (p', n'') := loop n' s' in\n (Op p p', n'')\n end) 1%positive s).1.\n\nSection eval.\nVariables (T : Type) (idx : T) (op : T -> T -> T).\n(*An inductive type representing an environment as a binary tree. An environment can be either empty or a node containing a value and two child environments, effectively mapping positive number indices to stored values.*)\nInductive env := Empty | ENode of T & env & env.\n(*This function retrieves a value from a tree-like environment at a specified positive number index. The index is interpreted as a path to a node in the binary tree, and a default value is returned if the path does not lead to a valid node.*)\nDefinition pos := fix loop (e : env) p {struct e} :=\n match e, p with\n | ENode t _ _, 1%positive => t\n | ENode t e _, (p~0)%positive => loop e p\n | ENode t _ e, (p~1)%positive => loop e p\n | _, _ => idx\nend.\n\n(*This function updates a tree-like environment by applying a given function to the value at a specified positive number index. If the path to the index does not exist, the environment is extended with default values to create it.*)\nDefinition set_pos (f : T -> T) := fix loop e p {struct p} :=\n match e, p with\n | ENode t e e', 1%positive => ENode (f t) e e'\n | ENode t e e', (p~0)%positive => ENode t (loop e p) e'\n | ENode t e e', (p~1)%positive => ENode t e (loop e' p)\n | Empty, 1%positive => ENode (f idx) Empty Empty\n | Empty, (p~0)%positive => ENode idx (loop Empty p) Empty\n | Empty, (p~1)%positive => ENode idx Empty (loop Empty p)\n end.\n\n(*This lemma states that retrieving a value from an environment at a given index, after that environment has been updated at another index, yields the updated value if the indices are the same, and the original value otherwise.*)\nLemma pos_set_pos (f : T -> T) e (p p' : positive) :\n pos (set_pos f e p) p' = if p == p' then f (pos e p) else pos e p'.\n\n(*This function reconstructs a full tree-like environment from a zipper representation, which describes the path from a focused sub-environment back to the root.*)\nFixpoint unzip z (e : env) : env := match z with\n | [::] => e\n | (x, inl e') :: z' => unzip z' (ENode x e' e)\n | (x, inr e') :: z' => unzip z' (ENode x e e')\nend.\n\n(*This function provides a tail-recursive way to update a tree-like environment. It applies a given function to the value at a specified positive number index, likely using a zipper-like accumulator to manage the recursion.*)\nDefinition set_pos_trec (f : T -> T) := fix loop z e p {struct p} :=\n match e, p with\n | ENode t e e', 1%positive => unzip z (ENode (f t) e e')\n | ENode t e e', (p~0)%positive => loop ((t, inr e') :: z) e p\n | ENode t e e', (p~1)%positive => loop ((t, inl e) :: z) e' p\n | Empty, 1%positive => unzip z (ENode (f idx) Empty Empty)\n | Empty, (p~0)%positive => loop ((idx, (inr Empty)) :: z) Empty p\n | Empty, (p~1)%positive => loop ((idx, (inl Empty)) :: z) Empty p\n end.\n\n(*This lemma states that the result of a tail-recursive function for setting a position in a tree-like data structure is equivalent to applying a post-processing step to an accumulator and the result of the non-recursive version of the function.*)\nLemma set_pos_trecE f z e p : set_pos_trec f z e p = unzip z (set_pos f e p).\n\n(*This definition specifies a recursive function that evaluates an expression represented as a syntax tree. For a leaf node, it retrieves a value from a given environment; for an operation node, it recursively evaluates the sub-expressions and combines their results using a specified binary operation.*)\nDefinition eval (e : env) := fix loop (s : syntax) :=\nmatch s with\n | Leaf n => pos e n\n | Op s s' => op (loop s) (loop s')\nend.\nEnd eval.\nArguments Empty {T}.\n\n(*This definition specifies a function that traverses a syntax tree to compute an environment mapping each leaf identifier to its number of occurrences within the tree.*)\nDefinition content := (fix loop (acc : env N) s :=\n match s with\n | Leaf n => set_pos_trec N0 Pos.Nsucc [::] acc n\n | Op s s' => loop (loop acc s') s\n end) Empty.\n\n(*This lemma states that the function for counting leaf occurrences in a syntax tree is equivalent to retrieving the corresponding count from the environment generated by the 'content' function.*)\nLemma count_memE x (t : syntax) :\n count_mem x t = nat_of_bin (pos N0 (content t) x).\n\n(*This definition introduces a structural universal quantifier over environments. It asserts that a given property holds for all environments that can be formed by following the structure of a given template environment.*)\nDefinition cforall N T : env N -> (env T -> Type) -> Type := env_rect (@^~ Empty)\n (fun _ e IHe e' IHe' R => forall x, IHe (fun xe => IHe' (R \\o ENode x xe))).\n\n(*This lemma states that if a property holds for all possible environments of a certain type, then it also satisfies the structural universal quantification defined by `cforall` with respect to any template environment.*)\nLemma cforallP N T R : (forall e : env T, R e) -> forall (e : env N), cforall e R.\n\nSection eq_eval.\nVariables (T : Type) (idx : T) (op : Monoid.com_law idx).\n\n(*This lemma asserts that if two syntax trees possess the same content, meaning they are composed of an identical multiset of leaves, then their evaluations under any commutative monoid operation will produce the same result, regardless of the values provided in the environment.*)\nLemma proof (p s : syntax) : content p = content s ->\n forall env, eval idx op env p = eval idx op env s.\n\n(*This definition encapsulates the proof of evaluation equality for two syntax trees that share the same content. It converts the proof, which holds for all environments, into a term that utilizes a structural quantifier, making it applicable to any environment structure that matches the content of the given trees.*)\nDefinition direct p s ps := cforallP (@proof p s ps) (content p).\n\nEnd eq_eval.\n\nModule Exports.\nExport AC.Syntax.\nEnd Exports.\nEnd AC.\nExport AC.Exports.\n\n(*A notation for a tactic used to validate the inputs for an associative-commutative rewriting operation. The tactic verifies that a rewriting goal is non-trivial and that the structures of the pattern and the target expression are compatible for reordering before the main rewrite rule is applied.*)\nNotation AC_check_pattern :=\n (ltac: (match goal with\n |- AC.content ?pat = AC.content ?ord =>\n let pat' := fresh \"pat\" in let pat' := eval compute in pat in\n tryif unify pat' ord then\n fail 1 \"AC: equality between\" pat\n \"and\" ord \"is trivial, cannot progress\"\n else tryif vm_compute; reflexivity then idtac\n else fail 2 \"AC: mismatch between shape\" pat \"=\" pat' \"and reordering\" ord\n | |- ?G => fail 3 \"AC: no pattern to check\" G\n end))\n (only parsing).\n\nNotation opACof law p s :=\n((fun T idx op assoc lid rid comm => (change_type (@AC.direct T idx\n (Monoid.ComLaw.Pack \n (Monoid.ComLaw.Class\n(**)\n (SemiGroup.isLaw.Axioms_ op assoc)\n (Monoid.isMonoidLaw.Axioms_ idx op lid rid)\n (SemiGroup.isCommutativeLaw.Axioms_ op comm)))\n p%AC s%AC AC_check_pattern) cbvrefl)) _ _ law\n(Monoid.mulmA _) (Monoid.mul1m _) (Monoid.mulm1 _) (Monoid.mulmC _))\n(only parsing).\n\nNotation opAC op p s := (opACof op (AC.pattern p%AC) s%AC) (only parsing).\nNotation opACl op s := (opAC op (AC.Leaf_of_nat (size (AC.serial s%AC))) s%AC)\n (only parsing).\n\n(*A notation for a proof term that asserts the equality of two expressions under a given associative and commutative monoid operation. The first expression is a pattern in a specific internal format that specifies the desired arrangement of terms, and the second expression is the term to be rewritten to match the pattern.*)\nNotation \"op .[ 'ACof' p s ]\" := (opACof op p%AC s%AC) (only parsing).\n(*A notation for a proof term asserting that two expressions are equal under an associative and commutative monoid operation. It is a variant of the 'ACof' notation that automatically converts a user-provided pattern into a canonical internal representation before applying the reordering proof.*)\nNotation \"op .[ 'AC' p s ]\" := (opAC op p%AC s%AC) (only parsing).\n(*A notation for a proof term used to normalize an expression under an associative and commutative monoid operation. It asserts that the given expression is equal to a canonical form, which is typically a right-associated sequence of its constituent atomic terms arranged in a standard order.*)\nNotation \"op .[ 'ACl' s ]\" := (opACl op s%AC) (only parsing).\n\n(*A notation defining a tactic that provides the default proof method for equalities arising from associative-commutative rewriting. This tactic proves the goal by computation, while keeping the underlying sorting functions unevaluated, and then concludes with reflexivity.*)\nNotation AC_strategy :=\n (ltac: (cbv -[Monoid.ComLaw.sort Monoid.Law.sort]; reflexivity))\n (only parsing).\nNotation ACof p s := (change_type\n (@AC.direct _ _ _ p%AC s%AC AC_check_pattern) AC_strategy)\n (only parsing).\nNotation AC p s := (ACof (AC.pattern p%AC) s%AC) (only parsing).\nNotation ACl s := (AC (AC.Leaf_of_nat (size (AC.serial s%AC))) s%AC)", - "boot.monoid": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype choice ssrnat seq.\nFrom mathcomp Require Import bigop fintype finfun.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nReserved Notation \"*%g\" (at level 0).\nReserved Notation \"\\1\" (at level 0).\nReserved Notation \"f \\* g\" (at level 40, left associativity).\n\nReserved Notation \"'{' 'multiplicative' G '->' H '}'\"\n (at level 0, G at level 98, H at level 99,\n format \"{ 'multiplicative' G -> H }\").\n\nDeclare Scope group_scope.\nDelimit Scope group_scope with g.\nLocal Open Scope group_scope.\n\n(*A structure that equips a type with a binary operation, typically referred to as multiplication.*)\nHB.mixin Record hasMul G := {\n mul : G -> G -> G\n}.\n\n#[short(type=\"magmaType\")]\n(*This structure defines a magma, which is a set equipped with a single, closed binary operation.*)\nHB.structure Definition Magma := {G of hasMul G}.\n\nBind Scope group_scope with Magma.sort.\n\n(*This structure defines a magma that is also equipped with a choice operator, allowing for the selection of a canonical element from any non-empty subtype.*)\nHB.structure Definition ChoiceMagma := {G of Magma G & Choice G}.\n\nBind Scope group_scope with ChoiceMagma.sort.\n\n(*A notation for the raw binary multiplication function of a magma-like structure, intended for use in higher-order contexts.*)\nLocal Notation \"*%g\" := (@mul _) : function_scope.\n(*This notation represents the infix binary multiplication operation between two elements of a magma.*)\nLocal Notation \"x * y\" := (mul x y) : group_scope.\n\nSection MagmaTheory.\n\nVariable G : magmaType.\nImplicit Types x y : G.\n\n(*This definition states that two elements commute if the result of multiplying them in one order is identical to the result of multiplying them in the opposite order.*)\nDefinition commute x y := x * y = y * x.\n\n(*This lemma states that any element of a magma commutes with itself.*)\nLemma commute_refl x : commute x x.\n\n(*This lemma states that the property of commutativity is symmetric, meaning if a first element commutes with a second, then the second element also commutes with the first.*)\nLemma commute_sym x y : commute x y -> commute y x.\n\nSection ClosedPredicates.\n\nVariable S : {pred G}.\n\n(*This definition specifies that a subset of a magma is closed under multiplication if the product of any two elements belonging to the subset is also an element of that subset.*)\nDefinition mulg_closed := {in S &, forall u v, u * v \\in S}.\n\nEnd ClosedPredicates.\n\nEnd MagmaTheory.\n\n(*A structure that enhances a magma by requiring its binary operation to be associative.*)\nHB.mixin Record Magma_isSemigroup G of Magma G := {\n mulgA : associative (@mul G)\n}.\n\n#[short(type=\"semigroupType\")]\n(*This structure defines a semigroup, which is a set equipped with an associative binary operation and a choice operator.*)\nHB.structure Definition Semigroup := {G of Magma_isSemigroup G & ChoiceMagma G}.\n\n(*A factory record used to construct a semigroup structure on a type that has a choice operator, by providing a binary operation and a proof of its associativity.*)\nHB.factory Record isSemigroup G of Choice G := {\n mul : G -> G -> G;\n mulgA : associative mul\n}.\n\nHB.builders Context G of isSemigroup G.\n\nHB.instance Definition _ := hasMul.Build G mul.\nHB.instance Definition _ := Magma_isSemigroup.Build G mulgA.\n\nHB.end.\n\nBind Scope group_scope with Semigroup.sort.\n\nSection SemigroupTheory.\nVariable G : semigroupType.\nImplicit Types x y : G.\n\n(*This lemma states that in a semigroup, if an element commutes with two other elements individually, it also commutes with their product.*)\nLemma commuteM x y z : commute x y -> commute x z -> commute x (y * z).\n\nEnd SemigroupTheory.\n\n(*A structure that equips a type with a distinguished element, typically serving as a multiplicative identity or 'one'.*)\nHB.mixin Record hasOne G := {\n one : G\n}.\n\n#[short(type=\"baseUMagmaType\")]\n(*This structure defines a unital magma, which is a set equipped with a binary operation and a distinguished element known as 'one'.*)\nHB.structure Definition BaseUMagma := {G of hasOne G & Magma G}.\n\nBind Scope group_scope with BaseUMagma.sort.\n\n(*This structure defines a unital magma that is also equipped with a choice operator, allowing for the selection of a canonical element from any non-empty subtype.*)\nHB.structure Definition ChoiceBaseUMagma := {G of BaseUMagma G & Choice G}.\n\nBind Scope group_scope with ChoiceBaseUMagma.sort.\n\n(*This notation represents the distinguished identity element, or 'one', of a unital magma.*)\nLocal Notation \"1\" := (@one _) : group_scope.\n(*This notation retrieves the element at a given natural number index from a sequence of elements from a unital magma, returning the multiplicative identity element 'one' if the index is out of bounds.*)\nLocal Notation \"s `_ i\" := (nth 1 s i) : group_scope.\n(*This notation denotes the iterated product of elements from a unital magma, where the elements are generated by a function over indices drawn from a given sequence, filtered by a predicate.*)\nLocal Notation \"\\prod_ ( i <- r | P ) F\" := (\\big[*%g/1]_(i <- r | P) F).\n(*This notation denotes the iterated product of elements from a unital magma, where the elements are generated by a function over all indices of a given finite type that satisfy a specific predicate.*)\nLocal Notation \"\\prod_ ( i | P ) F\" := (\\big[*%g/1]_(i | P) F).\n(*This notation denotes the iterated product of elements from a unital magma, where the elements are generated by a function over indices from a given finite set.*)\nLocal Notation \"\\prod_ ( i 'in' A ) F\" := (\\big[*%g/1]_(i in A) F).\n(*This notation denotes the iterated product of elements from a unital magma, where the elements are generated by a function over a contiguous range of natural number indices.*)\nLocal Notation \"\\prod_ ( m <= i < n ) F\" := (\\big[*%g/1%g]_(m <= i < n) F%g).\n\n(*This definition provides a way to compute the exponentiation of an element from a unital magma to a natural number power by repeatedly applying the multiplication operation, starting with the identity element.*)\nDefinition natexp (G : baseUMagmaType) (x : G) n : G := iterop n *%g x 1.\nArguments natexp : simpl never.\n\n(*This notation represents raising an element of a unital magma to the power of a natural number.*)\nLocal Notation \"x ^+ n\" := (natexp x n) : group_scope.\n\nSection baseUMagmaTheory.\n\nVariable G : baseUMagmaType.\nImplicit Types x : G.\n(*This lemma states that any element of a unital magma raised to the power of zero equals the identity element 'one'.*)\nLemma expg0 x : x ^+ 0 = 1. \n(*This lemma states that any element of a unital magma raised to the power of one equals the element itself.*)\nLemma expg1 x : x ^+ 1 = x. \n(*This lemma states that any element of a unital magma raised to the power of two equals the product of the element with itself.*)\nLemma expg2 x : x ^+ 2 = x * x. \n\n(*This lemma provides a recursive formula for exponentiation, stating that an element raised to a natural number power greater than one is equal to the product of the element itself and the element raised to the preceding natural number power.*)\nLemma expgSS x n : x ^+ n.+2 = x * x ^+ n.+1.\n\n(*This lemma states that an element of a unital magma raised to a boolean power equals the element itself if the boolean is true, and equals the identity element 'one' if the boolean is false.*)\nLemma expgb x (b : bool) : x ^+ b = (if b then x else 1).\n\nSection ClosedPredicates.\n\nVariable S : {pred G}.\n\n(*This definition specifies that a subset of a unital magma is closed if it contains the identity element 'one' and is also closed under the multiplication operation.*)\nDefinition umagma_closed := 1 \\in S /\\ mulg_closed S.\n\nEnd ClosedPredicates.\n\nEnd baseUMagmaTheory.\n\n(*This record defines the properties required to promote a base unital magma to a unital magma, specifically asserting that the distinguished element is both a left and right identity for the binary operation.*)\nHB.mixin Record BaseUMagma_isUMagma G of BaseUMagma G := {\n mul1g : left_id one (@mul G);\n mulg1 : right_id one (@mul G)\n}.\n\n(*This record provides a factory for constructing a unital magma from a magma by supplying an identity element and proofs that it acts as a two-sided identity.*)\nHB.factory Record Magma_isUMagma G of Magma G := {\n one : G;\n mul1g : left_id one (@mul G);\n mulg1 : right_id one (@mul G)\n}.\n\nHB.builders Context G of Magma_isUMagma G.\nHB.instance Definition _ := hasOne.Build G one.\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := BaseUMagma_isUMagma.Build G mul1g mulg1.\nHB.end.\n\n#[short(type=\"umagmaType\")]\n(*This structure defines a Unital Magma, an algebraic structure consisting of a type with decidable equality, a binary operation, and a two-sided identity element for that operation.*)\nHB.structure Definition UMagma := {G of Magma_isUMagma G & ChoiceMagma G}.\n\nBind Scope group_scope with UMagma.sort.\n\nSection UMagmaTheory.\n\nVariable G : umagmaType.\nImplicit Types x y : G.\n\n(*This lemma states that raising an element to the power of the successor of a natural number is equivalent to multiplying the element by itself raised to the power of that natural number.*)\nLemma expgS x n : x ^+ n.+1 = x * x ^+ n.\n\n(*This lemma states that the identity element raised to any natural number power results in the identity element itself.*)\nLemma expg1n n : 1 ^+ n = 1 :> G.\n\n(*This lemma states that any element commutes with the identity element in a unital magma.*)\nLemma commute1 x : commute x 1.\n\nEnd UMagmaTheory.\n\n#[short(type=\"monoidType\")]\n(*This structure defines a Monoid, which is an algebraic structure with an associative binary operation and an identity element.*)\nHB.structure Definition Monoid := {G of Magma_isUMagma G & Semigroup G}.\n\n(*This record provides a factory for constructing a monoid from a semigroup by supplying an identity element and proofs that it is a two-sided identity for the associative operation.*)\nHB.factory Record Semigroup_isMonoid G of Semigroup G := {\n one : G;\n mul1g : left_id one mul;\n mulg1 : right_id one mul\n}.\n\nHB.builders Context G of Semigroup_isMonoid G.\n\nHB.instance Definition _ := Magma_isUMagma.Build G mul1g mulg1.\n\nHB.end.\n\n(*This record provides a factory for constructing a monoid from a unital magma by supplying a proof that the binary operation is associative.*)\nHB.factory Record UMagma_isMonoid G of UMagma G := {\n mulgA : associative (@mul G)\n}.\n\nHB.builders Context G of UMagma_isMonoid G.\n\nHB.instance Definition _ := Magma_isSemigroup.Build G mulgA.\n\nHB.end.\n\n(*This record provides a factory for constructing a monoid structure from a type with decidable equality by supplying a binary operation, an identity element, and proofs of associativity and the identity laws.*)\nHB.factory Record isMonoid G of Choice G := {\n mul : G -> G -> G;\n one : G;\n mulgA : associative mul;\n mul1g : left_id one mul;\n mulg1 : right_id one mul\n}.\n\nHB.builders Context G of isMonoid G.\n\nHB.instance Definition _ := hasMul.Build G mul.\nHB.instance Definition _ := Magma_isSemigroup.Build G mulgA.\nHB.instance Definition _ := Magma_isUMagma.Build G mul1g mulg1.\n\nHB.end.\n\n#[export]\nHB.instance Definition _ (G : monoidType) := Monoid.isLaw.Build G 1 *%g mulgA mul1g mulg1.\n\nBind Scope group_scope with Monoid.sort.\n\nSection MonoidTheory.\n\nVariable G : monoidType.\nImplicit Types x y : G.\n\n(*This lemma states that in a monoid, raising an element to the power of the successor of a natural number is equivalent to multiplying the element raised to that number's power by the element itself.*)\nLemma expgSr x n : x ^+ n.+1 = x ^+ n * x.\n\n(*This lemma states that raising an element to the power of a sum of two natural numbers is equal to the product of the element raised to each of these numbers individually.*)\nLemma expgnDr x m n : x ^+ (m + n) = x ^+ m * x ^+ n.\n\n(*This lemma states that raising an element to a power that is the product of two natural numbers is equivalent to iterating the exponentiation by each of those numbers.*)\nLemma expgnA x m n : x ^+ (m * n) = x ^+ m ^+ n.\n\n(*This lemma states that the order of iterated exponentiation by two natural numbers can be swapped.*)\nLemma expgnAC x m n : x ^+ m ^+ n = x ^+ n ^+ m.\n\n(*This lemma states that iterating left-multiplication by a given element a specified number of times, starting from another element, is equivalent to left-multiplying by the first element raised to that power.*)\nLemma iter_mulg n x y : iter n ( *%g x) y = x ^+ n * y.\n\n(*This lemma states that iterating left-multiplication by a given element a specified number of times, starting from the identity element, yields the element raised to that power.*)\nLemma iter_mulg_1 n x : iter n ( *%g x) 1 = x ^+ n.\n\n(*This lemma states that the product of a constant element over a finite set of indices is equal to that element raised to the power of the size of the set.*)\nLemma prodg_const (I : finType) (A : pred I) x : \\prod_(i in A) x = x ^+ #|A|.\n\n(*This lemma states that the product of a constant element over a range of natural numbers is equal to that element raised to the power of the length of the range.*)\nLemma prodg_const_nat n m x : \\prod_(n <= i < m) x = x ^+ (m - n).\n\n(*This lemma states that the product of powers of a single element, with exponents determined by a function over a sequence, is equal to that element raised to the power of the sum of the exponents.*)\nLemma prodgXr x I r P (F : I -> nat) :\n \\prod_(i <- r | P i) x ^+ F i = x ^+ (\\sum_(i <- r | P i) F i).\n\n(*This lemma states that if an element commutes with every term of a product over a sequence, then it also commutes with the total product.*)\nLemma commute_prod (I : Type) (s : seq I) (P : pred I) (F : I -> G) x :\n (forall i, P i -> commute x (F i)) -> commute x (\\prod_(i <- s | P i) F i).\n\n(*This lemma states that if every element generated by a first function commutes with every element generated by a second function over a common domain, then the product of their pairwise products equals the product of their individual products.*)\nLemma prodgM_commute {I : eqType} r (P : pred I) (F H : I -> G) :\n (forall i j, P i -> P j -> commute (F i) (H j)) ->\n \\prod_(i <- r | P i) (F i * H i) =\n \\prod_(i <- r | P i) F i * \\prod_(i <- r | P i) H i.\n\n(*This lemma states that if an element commutes with every term in a product over a finite set, it can be factored out to the left, resulting in the element raised to the power of the set's size multiplied by the original product.*)\nLemma prodgMl_commute {I : finType} (A : pred I) (x : G) F :\n (forall i, A i -> commute x (F i)) ->\n \\prod_(i in A) (x * F i) = x ^+ #|A| * \\prod_(i in A) F i.\n\n(*This lemma states that if an element commutes with every term in a product over a finite set, it can be factored out to the right, resulting in the original product multiplied by the element raised to the power of the set's size.*)\nLemma prodgMr_commute {I : finType} (A : pred I) (x : G) F :\n (forall i, A i -> commute x (F i)) ->\n \\prod_(i in A) (F i * x) = \\prod_(i in A) F i * x ^+ #|A|.\n\n(*This lemma states that if two elements commute, then the first element also commutes with any natural number power of the second element.*)\nLemma commuteX x y n : commute x y -> commute x (y ^+ n).\n\n(*This lemma states that if two elements commute, then any natural number power of the first element commutes with any natural number power of the second element.*)\nLemma commuteX2 x y m n : commute x y -> commute (x ^+ m) (y ^+ n).\n\n(*This lemma states that for two commuting elements, raising their product to a power is equivalent to taking the product of each element raised to that same power.*)\nLemma expgMn x y n : commute x y -> (x * y) ^+ n = x ^+ n * y ^+ n.\n\nEnd MonoidTheory.\n\n(*This notation defines `monoid_closed` as an alias for `umagma_closed`, representing a predicate on a subset that is closed under multiplication and contains the identity element.*)\nNotation monoid_closed := umagma_closed.\n\n(*This record defines the property of a type having a unary inverse operation.*)\nHB.mixin Record hasInv G := {\n inv : G -> G\n}.\n\n#[short(type=\"baseGroupType\")]\n(*This structure defines a Base Group, which is a Base Unital Magma additionally equipped with an inverse operation.*)\nHB.structure Definition BaseGroup := {G of hasInv G & BaseUMagma G}.\n\nBind Scope group_scope with BaseGroup.sort.\n\n(*This record specifies the properties required to upgrade a structure that is both a monoid and a base group into a group, by asserting that the inverse operation provides a two-sided inverse for every element.*)\nHB.mixin Record Monoid_isGroup G of BaseGroup G := {\n mulVg : left_inverse one inv (@mul G);\n mulgV : right_inverse one inv (@mul G)\n}.\n\n#[short(type=\"groupType\")]\n(*This structure defines a group as a monoid where every element has a multiplicative inverse.*)\nHB.structure Definition Group :=\n {G of Monoid_isGroup G & BaseGroup G & Monoid G}.\n\n(*This record packages the raw components of a group structure for a given type, including an identity element, an inverse function, a multiplication operation, and the axioms of associativity, identity, and invertibility.*)\nHB.factory Record isGroup G of Choice G := {\n one : G;\n inv : G -> G;\n mul : G -> G -> G;\n mulgA : associative mul;\n mul1g : left_id one mul;\n mulg1 : right_id one mul;\n mulVg : left_inverse one inv mul;\n mulgV : right_inverse one inv mul\n}.\n\nHB.builders Context G of isGroup G.\n\nHB.instance Definition _ := hasMul.Build G mul.\nHB.instance Definition _ := Magma_isSemigroup.Build G mulgA.\nHB.instance Definition _ := Magma_isUMagma.Build G mul1g mulg1.\nHB.instance Definition _ := hasInv.Build G inv.\nHB.instance Definition _ := Monoid_isGroup.Build G mulVg mulgV.\n\nHB.end.\n\nBind Scope group_scope with Group.sort.\n\n(*This notation represents the inverse of a group element.*)\nLocal Notation \"x ^-1\" := (inv x) : group_scope.\n(*This notation represents the right division of one group element by another, defined as the first element multiplied by the inverse of the second element.*)\nLocal Notation \"x / y\" := (x * y^-1) : group_scope.\n(*This notation represents the exponentiation of a group element by a negative integer, defined as the inverse of the element raised to the corresponding positive power.*)\nLocal Notation \"x ^- n\" := ((x ^+ n)^-1) : group_scope.\n\n(*This definition describes the conjugation of one group element by another, which is computed by multiplying the inverse of the second element, the first element, and the second element in that order.*)\nDefinition conjg (G : groupType) (x y : G) := y^-1 * (x * y).\n(*This notation represents the conjugation of one group element by another.*)\nLocal Notation \"x ^ y\" := (conjg x y) : group_scope.\n\n(*This definition describes the commutator of two group elements, which measures the extent to which they fail to commute.*)\nDefinition commg (G : groupType) (x y : G) := x^-1 * (conjg x y).\n(*This notation represents the commutator of two group elements.*)\nLocal Notation \"[~ x , y ]\" := (commg x y) : group_scope.\n\nSection GroupTheory.\nVariable G : groupType.\nImplicit Types x y : G.\n\n(*This definition provides the right inverse law for group division, stating that any group element multiplied by its own inverse yields the identity element.*)\nDefinition divgg := @mulgV G.\n\n(*This lemma states that for any two given group elements, there is a unique third group element whose inverse, when multiplied by the first given element, yields the second given element.*)\nLemma mulKg : @left_loop G G (@inv G) *%g.\n\n(*This lemma states that for any two given group elements, there is a unique third group element such that the inverse of the first given element, multiplied by the third element, yields the second given element.*)\nLemma mulVKg : @rev_left_loop G G (@inv G) *%g.\n\n(*This lemma states that for any two given group elements, there is a unique third group element such that the first given element, when multiplied by the inverse of the third element, yields the second given element.*)\nLemma mulgK : @right_loop G G (@inv G) *%g.\n\n(*This lemma states that for any two given group elements, there is a unique third group element which, when multiplied by the inverse of the first given element, yields the second given element.*)\nLemma mulgVK : @rev_right_loop G G (@inv G) *%g.\n\n(*This definition provides the cancellation property for right division, stating that for any two group elements, there is a unique element that, when divided by the first, yields the second.*)\nDefinition divgK := mulgVK.\n\n(*This lemma states that right multiplication by any group element is an injective function, which means that if two elements produce the same result when right-multiplied by a third element, then the original two elements must be equal.*)\nLemma mulgI : @right_injective G G G *%g.\n\n(*This lemma states that left multiplication by any group element is an injective function, which means that if two elements produce the same result when left-multiplied by a third element, then the original two elements must be equal.*)\nLemma mulIg : @left_injective G G G *%g.\n\n(*This lemma states that the group inverse operation is an involution, meaning that applying the inverse operation twice to any group element returns the original element.*)\nLemma invgK : @involutive G (@inv G).\n\n(*This lemma states that the group inverse operation is injective, meaning that if two group elements have the same inverse, they must be equal.*)\nLemma invg_inj : @injective G G (@inv G).\n\n(*This lemma states that right division by any group element is an injective function, meaning that if two elements yield the same result when divided by a common third element, then they must be equal.*)\nLemma divgI : @right_injective G G G (fun x y => x / y).\n\n(*This lemma states that left division of a fixed group element by another is an injective function with respect to the divisor, meaning that if a fixed element divided by two different elements yields the same result, then those two divisors must be equal.*)\nLemma divIg : @left_injective G G G (fun x y => x / y).\n\n(*This lemma states that the inverse of the identity element of a group is the identity element itself.*)\nLemma invg1 : 1 ^-1 = 1 :> G.\n\n(*This lemma states that the inverse of a group element is equal to the identity element if and only if the element itself is the identity element.*)\nLemma invg_eq1 x : (x ^-1 == 1) = (x == 1).\n\n(*This lemma states that dividing any group element by the identity element results in the original element.*)\nLemma divg1 x : x / 1 = x. \n\n(*This lemma states that dividing the identity element by any group element results in the inverse of that element.*)\nLemma div1g x : 1 / x = x^-1. \n\n(*This lemma states that the inverse of the division of two group elements is equal to the division of the second element by the first.*)\nLemma invgF x y : (x / y)^-1 = y / x.\n\n(*This lemma states that the inverse operation is an anti-homomorphism, meaning the inverse of a product of two group elements is equal to the product of their inverses in reverse order.*)\nLemma invgM : {morph (@inv G): x y / x * y >-> y * x : G}.\n\n(*This lemma states that for a finite sequence of group elements, the product of their inverses is equal to the inverse of their product taken in the reverse order.*)\nLemma prodgV I r (P : pred I) (E : I -> G) :\n \\prod_(i <- r | P i) (E i)^-1 = (\\prod_(i <- rev r | P i) E i)^-1.\n\n(*This lemma states that if two group elements commute, then dividing the first element by the result of dividing the first by the second yields the second element.*)\nLemma divKg x y : commute x y -> x / (x / y) = y.\n\n(*This lemma states that a common right factor in the numerator and denominator of a fraction of group elements can be cancelled, meaning that dividing the product of a first element and a third element by the product of a second element and the same third element is equivalent to dividing the first element by the second.*)\nLemma mulgKA z x y : (x * z) / (y * z) = x / y.\n\n(*This lemma states that dividing a group element by a second, and multiplying the result by the product of the second element and a third, is equivalent to multiplying the first element by the third.*)\nLemma divgKA z x y : (x / z) * (z * y) = x * y.\n\n(*This lemma states that if the product of two group elements is the identity element, then the inverse of the first element is equal to the second element.*)\nLemma mulg1_eq x y : x * y = 1 -> x^-1 = y.\n\n(*This lemma states that if the division of one group element by another results in the identity element, then the two elements are equal.*)\nLemma divg1_eq x y : x / y = 1 -> x = y.\n\n(*This lemma states that the boolean proposition that the division of a first group element by a third is equal to a second is equivalent to the proposition that the first element is equal to the product of the second and third elements.*)\nLemma divg_eq x y z : (x / z == y) = (x == y * z).\n\n(*This lemma states that the boolean proposition that the division of a group element by another is equal to the identity element is equivalent to the proposition that the two elements are equal.*)\nLemma divg_eq1 x y : (x / y == 1) = (x == y).\n\n(*This lemma states that the boolean proposition that the product of two group elements is the identity element is equivalent to the proposition that the first element is equal to the inverse of the second.*)\nLemma mulg_eq1 x y : (x * y == 1) = (x == y^-1).\n\n(*This lemma states that the boolean proposition that the inverses of two group elements are equal is equivalent to the proposition that the elements themselves are equal.*)\nLemma eqg_inv x y : (x^-1 == y^-1) = (x == y).\n\n(*This lemma states that the boolean proposition that the inverse of a first group element is equal to a second is equivalent to the proposition that the first element is equal to the inverse of the second.*)\nLemma eqg_invLR x y : (x^-1 == y) = (x == y^-1).\n\n(*This lemma states that if a group element commutes with another, it also commutes with the inverse of that other element.*)\nLemma commuteV x y : commute x y -> commute x y^-1.\n\n(*This lemma states that raising the inverse of a group element to a natural number power is equivalent to raising the original element to the corresponding negative integer power.*)\nLemma expVgn x n : (x^-1) ^+ n = x ^- n.\n\n(*This lemma states that for two natural numbers where the second is less than or equal to the first, raising a group element to the power of their difference is equal to the division of the element raised to the first number by the element raised to the second number.*)\nLemma expgnFr x m n : n <= m -> x ^+ (m - n) = x ^+ m / x ^+ n.\n\n(*This lemma states that if two group elements commute, raising their quotient to a natural number power is equal to the quotient of each element raised to that same power.*)\nLemma expgnFl x y n : commute x y -> (x / y) ^+ n = x ^+ n / y ^+ n.\n\n(*This lemma states that the conjugation of a group element by another is defined as the product of the inverse of the second element, the first element, and the second element.*)\nLemma conjgE x y : x ^ y = y^-1 * (x * y). \n\n(*This lemma states that the product of two group elements can be reordered as the product of the second element and the conjugation of the first element by the second.*)\nLemma conjgC x y : x * y = y * x ^ y.\n\n(*This lemma states that the product of two group elements can be reordered as the product of the conjugation of the second element by the inverse of the first, followed by the first element.*)\nLemma conjgCV x y : x * y = y ^ x^-1 * x.\n\n(*This lemma states that conjugating any group element by the identity element leaves the element unchanged.*)\nLemma conjg1 x : x ^ 1 = x.\n\n(*This lemma states that conjugating the identity element by any group element results in the identity element.*)\nLemma conj1g x : 1 ^ x = 1.\n\n(*This lemma states that the conjugation of a product of two group elements by a third element is equal to the product of their individual conjugations by that same third element.*)\nLemma conjMg x y z : (x * y) ^ z = x ^ z * y ^ z.\n\n(*This lemma states that conjugating a group element by a product of two other elements is equivalent to successively conjugating by each element, first by the second factor and then by the first.*)\nLemma conjgM x y z : x ^ (y * z) = (x ^ y) ^ z.\n\n(*This lemma states that the conjugation of the inverse of a group element is equal to the inverse of its conjugation.*)\nLemma conjVg x y : x^-1 ^ y = (x ^ y)^-1.\n\n(*This lemma provides an identity for repeated conjugation, stating that conjugating an already-conjugated element is equivalent to regrouping the conjugation operations.*)\nLemma conjJg x y z : (x ^ y) ^ z = (x ^ z) ^ y ^ z.\n\n(*This lemma states that conjugating a group element raised to a natural number power is equivalent to first conjugating the base element and then raising the result to the same power.*)\nLemma conjXg x y n : (x ^+ n) ^ y = (x ^ y) ^+ n.\n\n(*This lemma states a right cancellation property for conjugation, where conjugating an element and then conjugating the result by the inverse of the conjugator restores the original element.*)\nLemma conjgK : @right_loop G G (@inv G) (@conjg G).\n\n(*This lemma states a left cancellation property for conjugation, where conjugating an element by an inverse and then conjugating the result by the original conjugator restores the initial element.*)\nLemma conjgKV : @rev_right_loop G G (@inv G) (@conjg G).\n\n(*This lemma asserts that for a fixed conjugating element, the conjugation map is injective.*)\nLemma conjg_inj : @left_injective G G G (@conjg G).\n\n(*This lemma states that the boolean proposition that the conjugation of a group element results in the identity element is equivalent to the proposition that the element itself is the identity.*)\nLemma conjg_eq1 x y : (x ^ y == 1) = (x == 1).\n\n(*This lemma expresses the commutator of two group elements as the product of the inverse of the first element and the conjugation of the first element by the second.*)\nLemma commgEl x y : [~ x, y] = x^-1 * x ^ y. \n\n(*This lemma provides an alternative expression for the commutator of two group elements as the product of the conjugation of the inverse of the second element by the first, and the second element.*)\nLemma commgEr x y : [~ x, y] = y^-1 ^ x * y.\n\n(*This lemma states that the product of two group elements is equal to their product in reverse order, followed by their commutator.*)\nLemma commgC x y : x * y = y * x * [~ x, y].\n\n(*This lemma states that the product of two group elements is equal to the commutator of their inverses, followed by their product in reverse order.*)\nLemma commgCV x y : x * y = [~ x^-1, y^-1] * (y * x).\n\n(*This lemma states that conjugating a commutator of two group elements by a third element is equivalent to computing the commutator of the two elements after they have been individually conjugated by the third element.*)\nLemma conjRg x y z : [~ x, y] ^ z = [~ x ^ z, y ^ z].\n\n(*This lemma asserts that the inverse of the commutator of two group elements is equal to the commutator of those same two elements in the reverse order.*)\nLemma invgR x y : [~ x, y]^-1 = [~ y, x].\n\n(*This lemma provides a reflective equivalence between the property that two group elements commute and the condition that their commutator is equal to the identity element.*)\nLemma commgP x y : reflect (commute x y) ([~ x, y] == 1).\n\n(*This lemma establishes that a group element is a fixed point under conjugation by another element if and only if their commutator is equal to the identity element.*)\nLemma conjg_fix x y : x ^ y == x = ([~ x, y] == 1).\n\n(*This lemma provides a reflective equivalence between the property that a group element is fixed by conjugation and the condition that its commutator with the conjugating element is equal to the identity element.*)\nLemma conjg_fixP x y : reflect (x ^ y = x) ([~ x, y] == 1).\n\n(*This lemma states that the condition for two group elements having a commutator equal to the identity is symmetric; it holds for one ordering of the elements if and only if it holds for the reversed ordering.*)\nLemma commg1_sym x y : ([~ x, y] == 1) = ([~ y, x] == 1).\n\n(*This lemma states that the commutator of any group element with the identity element is the identity element itself.*)\nLemma commg1 x : [~ x, 1] = 1.\n\n(*This lemma states that the commutator of the identity element with any group element is the identity element itself.*)\nLemma comm1g x : [~ 1, x] = 1.\n\n(*This lemma states that the commutator of any group element with itself is equal to the identity element.*)\nLemma commgg x : [~ x, x] = 1.\n\n(*This lemma states that the commutator of a group element with any positive integer power of itself is equal to the identity element.*)\nLemma commgXg x n : [~ x, x ^+ n] = 1.\n\n(*This lemma states that the commutator of a group element with its inverse is equal to the identity element.*)\nLemma commgVg x : [~ x, x^-1] = 1.\n\n(*This lemma states that the commutator of a group element with any negative integer power of itself is equal to the identity element.*)\nLemma commgXVg x n : [~ x, x ^- n] = 1.\n\nSection ClosedPredicates.\n\nVariable S : {pred G}.\n\n(*This definition specifies a property of a predicate on a group, which holds if for any group element satisfying the predicate, its inverse also satisfies the predicate.*)\nDefinition invg_closed := {in S, forall u, u^-1 \\in S}.\n(*This definition specifies a property of a predicate on a group, which holds if for any two group elements satisfying the predicate, their quotient also satisfies the predicate.*)\nDefinition divg_closed := {in S &, forall u v, u / v \\in S}.\n(*This definition specifies a property for a predicate on a group, requiring that the identity element satisfies the predicate and that the set of elements satisfying the predicate is closed under division.*)\nDefinition group_closed := 1 \\in S /\\ divg_closed.\n\n(*This lemma asserts that if a predicate on a group is group-closed, meaning it contains the identity and is closed under division, then it is also closed under the inverse operation.*)\nLemma group_closedV : group_closed -> invg_closed.\n\n(*This lemma asserts that if a predicate on a group is group-closed, meaning it contains the identity and is closed under division, then it is also closed under the multiplication operation.*)\nLemma group_closedM : group_closed -> mulg_closed S.\n\nEnd ClosedPredicates.\n\nEnd GroupTheory.\n\n(*This mixin defines the property of a function between two magmas being multiplicative, which means that the function preserves the multiplication operation.*)\nHB.mixin Record isMultiplicative (G H : magmaType) (apply : G -> H) := {\n gmulfM : {morph apply : x y / x * y}\n}.\n\n(*This structure defines a multiplicative function between two magmas as a function that is equipped with a proof that it preserves the multiplication operation.*)\nHB.structure Definition Multiplicative (G H : magmaType) :=\n {f of isMultiplicative G H f}.\n\n(*This mixin defines the property of a multiplicative function between two unital magmas also preserving the identity element.*)\nHB.mixin Record Multiplicative_isUMagmaMorphism (G H : baseUMagmaType)\n (f : G -> H) := {\n gmulf1 : f 1 = 1\n}.\n\n(*This structure defines a unital magma morphism as a function between two unital magmas that is both multiplicative and preserves the identity element.*)\nHB.structure Definition UMagmaMorphism (G H : baseUMagmaType) :=\n {f of Multiplicative_isUMagmaMorphism G H f & isMultiplicative G H f}.\n\n(*This definition specifies the property of a function between two unital magmas being a monoid morphism, which requires that it preserves both the identity element and the multiplication operation.*)\nDefinition monoid_morphism (G H : baseUMagmaType) (f : G -> H) : Prop :=\n (f 1 = 1) * {morph f : x y / x * y}.\n\n(*This factory constructs a proof that a function is a unital magma morphism from a given proof that the function satisfies the properties of a monoid morphism.*)\nHB.factory Record isUMagmaMorphism (G H : baseUMagmaType) (f : G -> H) := {\n monoid_morphism_subproof : monoid_morphism f\n}.\n\nHB.builders Context G H apply of isUMagmaMorphism G H apply.\nHB.instance Definition _ :=\n isMultiplicative.Build G H apply monoid_morphism_subproof.2.\nHB.instance Definition _ :=\n Multiplicative_isUMagmaMorphism.Build G H apply monoid_morphism_subproof.1.\nHB.end.\n\n(*This factory constructs a proof that a function between two groups is a group morphism, given a proof that the function preserves the division operation.*)\nHB.factory Record isGroupMorphism (G H : groupType) (f : G -> H) := {\n gmulfF : {morph f : x y / x / y}\n}.\n\nHB.builders Context G H apply of isGroupMorphism G H apply.\n\n(*This lemma states that any function between groups that preserves the division operation must also map the identity element of the domain to the identity element of the codomain.*)\nLocal Lemma gmulf1 : apply 1 = 1.\n\n(*This lemma states that any function between groups that preserves the division operation must also preserve the multiplication operation.*)\nLocal Lemma gmulfM : {morph apply : x y / x * y}.\n\nHB.instance Definition _ := isMultiplicative.Build G H apply gmulfM.\nHB.instance Definition _ :=\n Multiplicative_isUMagmaMorphism.Build G H apply gmulf1.\n\nHB.end.\n\nModule MultiplicativeExports.\n(*This notation provides a syntax for expressing the type of multiplicative functions from one magma to another.*)\nNotation \"{ 'multiplicative' U -> V }\" :=\n (Multiplicative.type U%type V%type) : type_scope.\nEnd MultiplicativeExports.\nHB.export MultiplicativeExports.\n\n#[non_forgetful_inheritance]\nHB.instance Definition _ G H (f : UMagmaMorphism.type G H) :=\n UMagmaMorphism.on (Multiplicative.sort f).\n\nSection LiftedMagma.\nVariables (T : Type) (G : magmaType).\n(*This definition specifies the pointwise multiplication of two functions that map from an arbitrary type to a magma. The resulting function's value at any point is the product of the values of the original two functions at that same point.*)\nDefinition mul_fun (f g : T -> G) x := f x * g x.\n\nEnd LiftedMagma.\nSection LiftedBaseUMagma.\nVariables (T : Type) (G : baseUMagmaType).\n(*This definition specifies a constant function from an arbitrary type to a unital magma, where the function returns the identity element of the magma for every input.*)\nDefinition one_fun : T -> G := fun=> 1.\n\nEnd LiftedBaseUMagma.\n\n(*This notation provides a shorthand for the constant function that always returns the identity element of the underlying unital magma.*)\nLocal Notation \"\\1\" := (one_fun _) : function_scope.\n(*This notation defines the pointwise multiplication of two functions. The resulting function, when applied to an argument, returns the product of the results of applying each of the original functions to that same argument.*)\nLocal Notation \"f \\* g\" := (mul_fun f g) : function_scope.\nArguments one_fun {_} G _ /.\nArguments mul_fun {_ _} f g _ /.\n\nSection MorphismTheory.\n\nSection Magma.\nVariables (G H : magmaType) (f : {multiplicative G -> H}).\n\n(*This lemma states that for two functions between magmas, if each function is a left and right inverse of the other under composition, then the second function is a magma morphism, meaning it preserves the multiplication operation.*)\nLemma can2_gmulfM f' : cancel f f' -> cancel f' f -> {morph f' : x y / x * y}.\n\n(*This lemma states that a magma morphism preserves commutativity. If two elements in the domain magma commute, their images under the morphism will also commute in the codomain magma.*)\nLemma gmulf_commute x y : commute x y -> commute (f x) (f y).\n\nEnd Magma.\n\nSection UMagma.\nVariables (G H : umagmaType) (f : UMagmaMorphism.type G H).\n\n(*This lemma states that for an injective morphism between magmas with a unit element, an element in the domain is mapped to the unit element of the codomain if and only if the element itself is the unit element of the domain.*)\nLemma gmulf_eq1 x : injective f -> (f x == 1) = (x == 1).\n\n(*This lemma states that for two functions between magmas with a unit element, where one is a morphism that preserves the unit, if each function is a left and right inverse of the other under composition, then the second function also maps the unit element to the unit element.*)\nLemma can2_gmulf1 f' : cancel f f' -> cancel f' f -> f' 1 = 1.\n\n(*This lemma states that a morphism between magmas with a unit element preserves positive integer exponentiation. The image of an element raised to a positive integer power is equal to the image of the element raised to that same power.*)\nLemma gmulfXn n : {morph f : x / x ^+ n}.\n\n(*This lemma states that a morphism between magmas with a unit element commutes with finite products. The image of a product of a sequence of elements is equal to the product of the images of those elements.*)\nLemma gmulf_prod I r (P : pred I) E :\n f (\\prod_(i <- r | P i) E i) = \\prod_(i <- r | P i) f (E i).\n\nEnd UMagma.\n\nSection Group.\nVariables (G H : groupType) (f : UMagmaMorphism.type G H).\n\n(*This lemma states that a group morphism preserves the inverse operation. The image of the inverse of an element is the inverse of the image of that element.*)\nLemma gmulfV : {morph f : x / x^-1}.\n\n(*This lemma states that a group morphism preserves the division operation, where division is defined as multiplication by the inverse of the second element. The image of the division of two elements is the division of their images.*)\nLemma gmulfF : {morph f : x y / x / y}.\n\n(*This lemma states that a group morphism is injective if the only element that maps to the identity element of the codomain is the identity element of the domain.*)\nLemma gmulf_inj : (forall x, f x = 1 -> x = 1) -> injective f.\n\n(*This lemma states that a group morphism preserves negative integer exponentiation. The image of an element raised to a negative integer power is equal to the image of the element raised to that same power.*)\nLemma gmulfXVn n : {morph f : x / x ^- n}.\n\n(*This lemma states that a group morphism preserves the conjugation operation. The image of an element conjugated by another is equal to the image of the first element conjugated by the image of the second.*)\nLemma gmulfJ : {morph f : x y / x ^ y}.\n\n(*This lemma states that a group morphism preserves the commutator operation. The image of the commutator of two elements is the commutator of their images.*)\nLemma gmulfR : {morph f : x y / [~ x, y]}.\n\nEnd Group.\n\nSection MulFun.\nVariables (G H K : magmaType).\nVariables (f g : {multiplicative H -> K}) (h : {multiplicative G -> H}).\n\n(*This fact states that the identity function on any magma is a magma morphism, meaning it preserves the magma's multiplication operation.*)\nFact idfun_gmulfM : {morph @idfun G : x y / x * y}.\n\nHB.instance Definition _ := isMultiplicative.Build G G idfun idfun_gmulfM.\n\n(*This fact states that the composition of two magma morphisms is itself a magma morphism.*)\nFact comp_gmulfM : {morph f \\o h : x y / x * y}.\n\n(*This fact states that the identity function on a magma with a unit element maps the unit element to itself.*)\nFact idfun_gmulf1 : idfun 1 = 1 :> H.\n\nHB.instance Definition _ :=\n Multiplicative_isUMagmaMorphism.Build H H idfun idfun_gmulf1.\n\n(*This fact states that the constant function from a magma to a magma with a unit element, which maps every element to the unit element, is a magma morphism.*)\nFact one_fun_gmulfM : {morph @one_fun G H : x y / x * y}.\n\n(*This fact states that the composition of two morphisms between magmas with a unit element, both of which preserve the unit element, also preserves the unit element.*)\nFact comp_gmulf1 : (f \\o h) 1 = 1.\n\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ :=\n Multiplicative_isUMagmaMorphism.Build G K (f \\o h) comp_gmulf1.\n\n(*This fact states that the constant function from one magma with a unit element to another, which maps every element to the codomain's unit element, maps the domain's unit element to the codomain's unit element.*)\nFact one_fun_gmulf1 : @one_fun G H 1 = 1.\n\n(*This fact states that the pointwise product of two morphisms between magmas with a unit element, where both morphisms preserve the unit element, also produces a function that preserves the unit element.*)\nFact mul_fun_gmulf1 : (f \\* g) 1 = 1.\n\nEnd Mul11Fun.\nEnd MorphismTheory.\n\n(*This record provides a property for a subset of a magma, asserting that the subset is closed under the magma's multiplication operation.*)\nHB.mixin Record isMulClosed (G : magmaType) (S : {pred G}) := {\n gpredM : mulg_closed S\n}.\n\n(*This record provides a property for a subset of a magma with a unit element, asserting that the subset contains the unit element.*)\nHB.mixin Record isMul1Closed (G : baseUMagmaType) (S : {pred G}) := {\n gpred1 : 1 \\in S\n}.\n\n(*This record provides a property for a subset of a group, asserting that the subset is closed under the group's inverse operation.*)\nHB.mixin Record isInvClosed (G : groupType) (S : {pred G}) := {\n gpredVr : invg_closed S\n}.\n\n#[short(type=\"mulgClosed\")]\n(*This definition introduces a structure for a subset of a magma that is closed under the multiplication operation.*)\nHB.structure Definition MulClosed G := {S of isMulClosed G S}.\n\n#[short(type=\"umagmaClosed\")]\n(*This definition introduces a structure for a subset of a magma with a unit element that contains the unit element and is closed under multiplication.*)\nHB.structure Definition UMagmaClosed G :=\n {S of isMul1Closed G S & isMulClosed G S}.\n\n#[short(type=\"invgClosed\")]\n(*This definition introduces a structure for a subset of a group that is closed under the inverse operation.*)\nHB.structure Definition InvClosed G := {S of isInvClosed G S}.\n\n#[short(type=\"groupClosed\")]\n(*This definition introduces a structure for a subset of a group that contains the unit element and is closed under both multiplication and inversion, thus forming a subgroup.*)\nHB.structure Definition GroupClosed G :=\n {S of isInvClosed G S & isMul1Closed G S & isMulClosed G S}.\n\nSection UMagmaPred.\nVariables (G : baseUMagmaType).\n\nSection UMagma.\nVariables S : umagmaClosed G.\n\n(*This lemma states that for a subset of a magma with a unit element that is closed under multiplication and contains the unit element, the product of any finite sequence of elements from the subset also belongs to the subset.*)\nLemma gpred_prod I r (P : pred I) F :\n (forall i, P i -> F i \\in S) -> \\prod_(i <- r | P i) F i \\in S.\n\n(*This lemma states that if a subset of a magma with a unit element contains the unit element and is closed under multiplication, then it is also closed under positive integer exponentiation.*)\nLemma gpredXn n : {in S, forall u, u ^+ n \\in S}.\n\nEnd UMagma.\nEnd UMagmaPred.\n\nSection GroupPred.\nVariables (G : groupType).\n\n(*This lemma states that for a subset of a group that is closed under the inverse operation, if an element belongs to the subset, its inverse also belongs to the subset.*)\nLemma gpredV (S : invgClosed G) : {mono (@inv G): u / u \\in S}.\n\nSection Group.\nVariables S : groupClosed G.\n\n(*This lemma states that for any two elements belonging to a subgroup, their right quotient is also a member of that subgroup.*)\nLemma gpredF : {in S &, forall u v, u / v \\in S}.\n\n(*This lemma states that for any two elements of a group, the right quotient of the first by the second belongs to a given subgroup if and only if the right quotient of the second by the first also belongs to that subgroup.*)\nLemma gpredFC u v : u / v \\in S = (v / u \\in S).\n\n(*This lemma states that for any element of a subgroup and any natural number, the group element raised to the power of the negation of that number is also a member of the subgroup.*)\nLemma gpredXNn n: {in S, forall u, u ^- n \\in S}.\n\n(*This lemma states that for an element belonging to a subgroup, right-multiplying another group element by it preserves membership in the subgroup; that is, the product is in the subgroup if and only if the other element is.*)\nLemma gpredMr x y : x \\in S -> (y * x \\in S) = (y \\in S).\n\n(*This lemma states that for an element belonging to a subgroup, left-multiplying another group element by it preserves membership in the subgroup; that is, the product is in the subgroup if and only if the other element is.*)\nLemma gpredMl x y : x \\in S -> (x * y \\in S) = (y \\in S).\n\n(*This lemma states that for an element belonging to a subgroup, right-dividing another group element by it preserves membership in the subgroup; that is, the quotient is in the subgroup if and only if the other element is also in the subgroup.*)\nLemma gpredFr x y : x \\in S -> (y / x \\in S) = (y \\in S).\n\n(*This lemma states that for a fixed element of a subgroup, its right quotient with another group element belongs to the subgroup if and only if the other group element also belongs to the subgroup.*)\nLemma gpredFl x y : x \\in S -> (x / y \\in S) = (y \\in S).\n\n(*This lemma states that if two elements belong to a subgroup, then the conjugate of the first element by the second element is also a member of that subgroup.*)\nLemma gpredJ x y : x \\in S -> y \\in S -> x ^ y \\in S.\n\n(*This lemma states that if two elements belong to a subgroup, their commutator is also a member of that subgroup.*)\nLemma gpredR x y : x \\in S -> y \\in S -> [~ x, y] \\in S.\n\nEnd Group.\nEnd GroupPred. \n\n(*This record is a mixin that equips a subtype of a magma with a magma structure, asserting that the inclusion map from the subtype to the ambient magma preserves the multiplication operation.*)\nHB.mixin Record isSubMagma (G : magmaType) (S : pred G) H\n of SubType G S H & Magma H := {\n valM_subproof : {morph (val : H -> G) : x y / x * y}\n}.\n\n#[short(type=\"subMagmaType\")]\n(*This definition introduces the structure for a submagma, which is a subset of elements from an ambient magma that is itself a magma and is closed under the ambient magma's multiplication operation.*)\nHB.structure Definition SubMagma (G : magmaType) S :=\n { H of SubChoice G S H & Magma H & isSubMagma G S H }.\n\nSection subMagma.\nContext (G : magmaType) (S : pred G) (H : subMagmaType S).\n(*This notation refers to the canonical coercion function that maps an element from an algebraic substructure, such as a subgroup, to its corresponding value within the ambient parent structure.*)\nNotation val := (val : H -> G).\n(*This lemma asserts that the inclusion map from a submagma to its parent magma is a morphism, meaning it preserves the multiplication operation.*)\nLemma valM : {morph val : x y / x * y}. \nEnd subMagma.\n\n(*This record is a factory for constructing a submagma structure from a subtype, requiring a proof that the underlying subset of elements is closed under the multiplication of the ambient magma.*)\nHB.factory Record SubChoice_isSubMagma (G : magmaType) S H\n of SubChoice G S H := {\n mulg_closed_subproof : mulg_closed S\n}.\n\nHB.builders Context G S H of SubChoice_isSubMagma G S H.\n\nHB.instance Definition _ := isMulClosed.Build G S mulg_closed_subproof.\n\nLet inH v Sv : H := Sub v Sv.\n(*This definition specifies the multiplication operation for a submagma by taking two elements from the submagma, multiplying their corresponding values in the parent magma, and lifting the result back into the submagma type.*)\nLet mulH (u1 u2 : H) := inH (gpredM _ _ (valP u1) (valP u2)).\n\nHB.instance Definition _ := hasMul.Build H mulH.\n\n(*This definition provides the proof that the inclusion map from a submagma to its parent magma preserves the multiplication operation.*)\nLemma valM : {morph (val : H -> G) : x y / x * y}.\n\nHB.instance Definition _ := isSubMagma.Build G S H valM.\n\nHB.end.\n\n#[short(type=\"subSemigroupType\")]\n(*This structure defines a sub-semigroup, which is a substructure of a given semigroup that is closed under multiplication and inherits the associative property of that operation.*)\nHB.structure Definition SubSemigroup (G : semigroupType) S :=\n { H of SubMagma G S H & Semigroup H}.\n\n(*This factory record provides the necessary components to construct a sub-semigroup. It takes a predicate defining a subset and requires a proof that this subset is closed under the multiplication of the ambient semigroup.*)\nHB.factory Record SubChoice_isSubSemigroup (G : semigroupType) S H\n of SubChoice G S H := {\n mulg_closed_subproof : mulg_closed S\n}.\n\nHB.builders Context G S H of SubChoice_isSubSemigroup G S H.\n\nHB.instance Definition _ :=\n SubChoice_isSubMagma.Build G S H mulg_closed_subproof.\n\n(*This lemma states that the multiplication operation on the sub-semigroup is associative.*)\nLemma mulgA : associative (@mul H).\n\nHB.instance Definition _ := isSemigroup.Build H mulgA.\n\nHB.end.\n\n(*This mixin record specifies the property of a sub-magma with a unit element. It asserts that the inclusion map preserves the unit element, meaning the unit of the sub-magma maps to the unit of the parent magma.*)\nHB.mixin Record isSubBaseUMagma (G : baseUMagmaType) (S : pred G) H\n of SubMagma G S H & BaseUMagma H := {\n val1_subproof : (val : H -> G) 1 = 1\n}.\n\n#[short(type=\"subBaseUMagmaType\")]\n(*This structure defines a sub-magma with a unit element. This is a subset of a parent unital magma that is closed under multiplication and contains a unit element that corresponds to the parent's unit element via the inclusion map.*)\nHB.structure Definition SubBaseUMagma (G : umagmaType) S :=\n { H of SubMagma G S H & BaseUMagma H & isSubBaseUMagma G S H}.\n\n#[short(type=\"subUMagmaType\")]\n(*This structure defines a sub-unital magma as a subset of a parent unital magma. The subset is closed under multiplication and contains a unit element that acts as a multiplicative identity and corresponds to the unit element of the parent magma.*)\nHB.structure Definition SubUMagma (G : umagmaType) S :=\n { H of SubMagma G S H & UMagma H & isSubBaseUMagma G S H}.\n\nSection subUMagma.\nContext (G : umagmaType) (S : pred G) (H : subUMagmaType S).\n(*This notation defines `val` as the canonical inclusion function that maps an element from an algebraic substructure to the corresponding element in its parent structure.*)\nNotation val := (val : H -> G).\n(*This lemma states that the inclusion map from a sub-unital magma to its parent magma maps the multiplicative identity of the sub-magma to the multiplicative identity of the parent magma.*)\nLemma val1 : val 1 = 1. \nEnd subUMagma.\n\n(*This factory record provides the components needed to construct a sub-unital magma from a predicate. It requires proof that the subset defined by the predicate contains the multiplicative identity and is closed under multiplication.*)\nHB.factory Record SubChoice_isSubUMagma (G : umagmaType) S H\n of SubChoice G S H := {\n umagma_closed_subproof : umagma_closed S\n}.\n\nHB.builders Context G S H of SubChoice_isSubUMagma G S H.\n\nHB.instance Definition _ :=\n SubChoice_isSubMagma.Build G S H (snd umagma_closed_subproof).\n\nLet inH v Sv : H := Sub v Sv.\n(*This definition specifies the unit element of a sub-unital magma, which is defined as the unit element of the parent magma, proven to be a member of the subset defining the substructure.*)\nLet oneH := inH (fst umagma_closed_subproof).\n\nHB.instance Definition _ := hasOne.Build H oneH.\n\n(*This field asserts that the identity element of the ambient unital magma is contained within the underlying subset of the sub-magma.*)\nLemma val1 : (val : H -> G) 1 = 1. \n\nHB.instance Definition _ := isSubBaseUMagma.Build G S H val1.\n\n(*This lemma states that multiplying any element of a sub-unital magma on the left by the identity element results in the original element.*)\nLemma mul1g : left_id 1 (@mul H).\n\n(*This lemma states that multiplying any element of a sub-unital magma on the right by the identity element results in the original element.*)\nLemma mulg1 : right_id 1 (@mul H).\n\nHB.instance Definition _ := BaseUMagma_isUMagma.Build H mul1g mulg1.\n\nHB.end.\n\n#[short(type=\"subMonoidType\")]\n(*This structure defines a submonoid of a given monoid as a subset that is itself a monoid under the inherited operations.*)\nHB.structure Definition SubMonoid (G : monoidType) S :=\n { H of SubUMagma G S H & Monoid H}.\n\n(*This factory constructs a submonoid from a subset of a given monoid, provided a proof that the subset is closed under multiplication and contains the identity element.*)\nHB.factory Record SubChoice_isSubMonoid (G : monoidType) S H\n of SubChoice G S H := {\n monoid_closed_subproof : monoid_closed S\n}.\n\nHB.builders Context G S H of SubChoice_isSubMonoid G S H.\n\nHB.instance Definition _ :=\n SubChoice_isSubUMagma.Build G S H monoid_closed_subproof.\nHB.instance Definition _ :=\n SubChoice_isSubSemigroup.Build G S H (snd monoid_closed_subproof).\n\nHB.end.\n\n#[short(type=\"subGroupType\")]\n(*This structure defines a subgroup of a given group as a subset that is itself a group under the inherited operations.*)\nHB.structure Definition SubGroup (G : groupType) S :=\n { H of SubUMagma G S H & Group H}.\n\n(*This factory constructs a subgroup from a subset of a given group, provided a proof that the subset is closed under multiplication, contains the identity element, and is closed under inversion.*)\nHB.factory Record SubChoice_isSubGroup (G : groupType) S H\n of SubChoice G S H := {\n group_closed_subproof : group_closed S\n}.\n\nHB.builders Context G S H of SubChoice_isSubGroup G S H.\n\n(*This lemma states that a subset closed under group operations is also closed under the operations of a unital magma, specifically multiplication and containing the identity element.*)\nLemma umagma_closed : umagma_closed S.\n\nHB.instance Definition _ := SubChoice_isSubMonoid.Build G S H umagma_closed.\nHB.instance Definition _ :=\n isInvClosed.Build G S (group_closedV group_closed_subproof).\n\n(*This definition provides a constructor function that lifts an element of an ambient group into the corresponding subgroup type, given a proof that the element belongs to the subgroup's underlying subset.*)\nLet inH v Sv : H := Sub v Sv.\n(*This definition specifies the inverse operation within a subgroup. For a given element of the subgroup, its inverse is computed in the ambient group and then lifted back into the subgroup structure.*)\nLet invH (u : H) := inH (gpredVr _ (valP u)).\n\nHB.instance Definition _ := hasInv.Build H invH.\n\n(*This lemma states that for any element in the subgroup, multiplying its inverse on the left yields the group's identity element.*)\nLemma mulVg : left_inverse 1%g invH *%g.\n\n(*This lemma states that for any element in the subgroup, multiplying its inverse on the right yields the group's identity element.*)\nLemma mulgV : right_inverse 1%g invH *%g.\n \n\nHB.instance Definition _ := Monoid_isGroup.Build H mulVg mulgV.\n\nHB.end.\n\nSection FinFunMagma.\nVariable (aT : finType) (rT : magmaType).\nImplicit Types f g : {ffun aT -> rT}.\n\n(*This definition specifies the multiplication of two functions from a finite type to a magma as a new function where the value at each point is the product of the values of the original functions at that same point.*)\nDefinition ffun_mul f g := [ffun a => f a * g a].\n\n(*This fact asserts that the pointwise multiplication of functions is associative, given that the multiplication in the codomain is associative.*)\nFact ffun_mulgA : associative (@ffun_mul aT rT).\n\n(*This definition specifies the identity element for the structure of functions from a finite type to a unital magma as the constant function that maps every input to the identity element of the codomain.*)\nDefinition ffun_one := [ffun a : aT => (1 : rT)].\n\n(*This fact asserts that the constant identity function acts as a left identity for pointwise function multiplication.*)\nFact ffun_mul1g : left_id (@ffun_one aT rT) *%g.\n\n(*This fact asserts that the constant identity function acts as a right identity for pointwise function multiplication.*)\nFact ffun_mulg1 : right_id (@ffun_one aT rT) *%g.\n\n(*This definition specifies the inverse of a function from a finite type to a group as a new function where the value at each point is the inverse of the original function's value at that same point.*)\nDefinition ffun_inv f := [ffun a => (f a)^-1].\n\n(*This fact asserts that the pointwise inverse function serves as a left inverse under pointwise function multiplication.*)\nFact ffun_mulVg :\n left_inverse (@ffun_one aT rT) (@ffun_inv _ _) (@ffun_mul _ _).\n\n(*This fact asserts that the pointwise inverse function serves as a right inverse under pointwise function multiplication.*)\nFact ffun_mulgV :\n right_inverse (@ffun_one aT rT) (@ffun_inv _ _) (@ffun_mul _ _).\n\n(*This definition specifies the multiplication of two pairs as a new pair obtained by multiplying the corresponding components of the input pairs.*)\nDefinition mul_pair (x y : G * H) := (x.1 * y.1, x.2 * y.2).\n\nHB.instance Definition _ := hasMul.Build (G * H)%type mul_pair.\n\n(*This fact asserts that the first projection from a product magma is a multiplicative morphism, meaning it preserves the multiplication operation.*)\nFact fst_is_multiplicative : {morph fst : x y / x * y}. \nHB.instance Definition _ :=\n isMultiplicative.Build _ _ fst fst_is_multiplicative.\n\n(*This fact asserts that the second projection from a product magma is a multiplicative morphism, meaning it preserves the multiplication operation.*)\nFact snd_is_multiplicative : {morph snd : x y / x * y}. \n(*This lemma states that component-wise multiplication on pairs is associative, provided the multiplication on each component type is associative.*)\nLemma pair_mulgA : associative (@mul (G * H)%type).\n\n(*This definition specifies the identity element for a product of two unital magmas as the pair of their respective identity elements.*)\nDefinition one_pair : G * H := (1, 1).\n\nHB.instance Definition _ := hasOne.Build (G * H)%type one_pair.\n\n(*This fact asserts that the first projection from a product of unital magmas maps the identity element of the product to the identity element of the first component.*)\nFact fst_is_umagma_morphism : fst (1 : G * H) = 1. \nHB.instance Definition _ :=\n Multiplicative_isUMagmaMorphism.Build _ _ fst fst_is_umagma_morphism.\n\n(*This fact asserts that the second projection from a product of unital magmas maps the identity element of the product to the identity element of the second component.*)\nFact snd_is_umagma_morphism : snd (1 : G * H) = 1. \n(*This lemma states that the pair of identity elements acts as a left identity for component-wise pair multiplication.*)\nLemma pair_mul1g : left_id (@one_pair G H) *%g.\n\n(*This lemma states that the pair of identity elements acts as a right identity for component-wise pair multiplication.*)\nLemma pair_mulg1 : right_id (@one_pair G H) *%g.\n\n(*This definition specifies the inverse of a pair of group elements as the pair of their component-wise inverses.*)\nDefinition inv_pair (u : G * H) := (u.1 ^-1, u.2 ^-1).\n\n(*This lemma states that for any element in the product of two groups, multiplying the component-wise inverse of that element by the element itself yields the identity element of the product group.*)\nLemma pair_mulVg : left_inverse one (@inv_pair G H) mul.\n\n(*This lemma states that for any element in the product of two groups, multiplying the element by its component-wise inverse yields the identity element of the product group.*)\nLemma pair_mulgV : right_inverse one (@inv_pair G H) mul.", - "boot.fintype": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool ssrnotations eqtype.\nFrom mathcomp Require Import ssrnat seq choice path div.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope fin_quant_scope.\n\n(*This definition specifies the property of a finite sequence, asserting that every element of a given type with decidable equality appears exactly once in the sequence.*)\nDefinition finite_axiom (T : eqType) e :=\n forall x : T, count_mem x e = 1.\n\n(*A structure that equips a type with decidable equality with a finite sequence containing every element of the type exactly once, thereby certifying that the type is finite.*)\nHB.mixin Record isFinite T of Equality T := {\n enum_subdef : seq T;\n enumP_subdef : finite_axiom enum_subdef\n}.\n\n#[short(type=\"finType\")]\n(*A structure that defines a finite type as a type that is both countable and possesses a canonical finite sequence enumerating all of its elements exactly once.*)\nHB.structure Definition Finite := {T of isFinite T & Countable T }.\n\nModule Export FiniteNES.\nModule Finite.\n\n(*This definition provides the canonical finite sequence containing all elements of a given finite type exactly once.*)\nHB.lock Definition enum T := isFinite.enum_subdef (Finite.class T).\n\n(*A notation that serves as an alias for the property asserting that a sequence contains every element of a given type exactly once.*)\nNotation axiom := finite_axiom.\n\n(*This lemma states that if a finite sequence contains no duplicate elements and includes all elements of a given type with decidable equality, then every element of that type appears exactly once in the sequence.*)\nLemma uniq_enumP (T : eqType) e : uniq e -> e =i T -> axiom e.\n\nSection WithCountType.\nVariable (T : countType) (n : nat).\n\n(*This definition constructs a finite sequence of elements of a countable type by applying an inverse pickling function to the sequence of natural numbers smaller than a given bound.*)\nDefinition count_enum := pmap (@pickle_inv T) (iota 0 n).\n\nHypothesis ubT : forall x : T, pickle x < n.\n\n(*This lemma asserts that, given a countable type where every element's pickled representation is smaller than a certain natural number, the sequence generated by applying the inverse pickle function to all numbers below that bound is a valid enumeration, containing each element of the type exactly once.*)\nLemma count_enumP : axiom count_enum.\n\nEnd WithCountType.\nEnd Finite.\nCanonical finEnum_unlock := Unlockable Finite.enum.unlock.\nEnd FiniteNES.\n\nSection CanonicalFinType.\nVariable (T : eqType) (s : seq T).\n\n(*This definition introduces a type that is certified as finite, derived from an underlying type and a proof that a given sequence enumerates all its elements exactly once.*)\nDefinition fin_type of finite_axiom s : Type := T.\n\nVariable (f : finite_axiom s).\n(*A notation that provides a short alias for a type that has been certified as finite through a given enumeration proof.*)\nNotation fT := (fin_type f).\n\n(*This definition provides a function that maps an element of a certified finite type to its corresponding natural number index within the canonical enumeration sequence.*)\nDefinition fin_pickle (x : fT) : nat := index x s.\n(*This definition provides a function that maps a natural number to an element of a certified finite type by retrieving the element at that index from the canonical enumeration sequence, returning no value if the index is out of bounds.*)\nDefinition fin_unpickle (n : nat) : option fT :=\n nth None (map some s) n.\n(*This lemma states that the pickling and unpickling functions for a certified finite type form a partial cancellation pair, meaning that applying the unpickling function to the pickled representation of an element restores the original element.*)\nLemma fin_pickleK : pcancel fin_pickle fin_unpickle.\n\nHB.instance Definition _ := Equality.on fT.\nHB.instance Definition _ := isCountable.Build fT fin_pickleK.\n(*This definition provides a specialized sort for predicates over a finite type, which is equivalent to the general predicate sort.*)\nDefinition fin_pred_sort (T : finType) (pT : predType T) := pred_sort pT.\nIdentity Coercion pred_sort_of_fin : fin_pred_sort >-> pred_sort.\n\n(*This definition constructs a finite sequence of all elements of a given finite type that satisfy a specific membership predicate by filtering the canonical enumeration of the type.*)\nDefinition enum_mem T (mA : mem_pred _) := filter mA (Finite.enum T).\nNotation enum A := (enum_mem (mem A)).\n(*This definition provides a way to select an element from a finite type that satisfies a given predicate, returning the first such element found in the canonical enumeration, or no value if none exists.*)\nDefinition pick (T : finType) (P : pred T) := ohead (enum P).\n\n(*A notation for selecting an element that satisfies a given boolean predicate, returning the first such element found in the canonical enumeration or no value if none exists.*)\nNotation \"[ 'pick' x | P ]\" := (pick (fun x => P%B))\n (x name, format \"[ 'pick' x | P ]\") : form_scope.\n(*A notation for selecting an element of a specified finite type that satisfies a given boolean predicate.*)\nNotation \"[ 'pick' x : T | P ]\" := (pick (fun x : T => P%B))\n (x name, only parsing) : form_scope.\n(*This definition provides a predicate that is always true for any element of a given type, used to select an arbitrary element.*)\nDefinition pick_true T (x : T) := true.\nReserved Notation \"[ 'pick' x : T ]\" (x name, format \"[ 'pick' x : T ]\").\nNotation \"[ 'pick' x : T ]\" := [pick x : T | pick_true x]\n (only parsing) : form_scope.\n(*A notation for selecting an arbitrary element from a specified finite type by using a predicate that is always true.*)\nNotation \"[ 'pick' x : T ]\" := [pick x : T | pick_true _]\n (only printing) : form_scope.\n(*A notation for selecting an arbitrary element from a finite type, where the specific type is inferred from the context.*)\nNotation \"[ 'pick' x ]\" := [pick x : _] (x name, only parsing) : form_scope.\n(*A notation for selecting an element that satisfies the conjunction of two boolean predicates.*)\nNotation \"[ 'pick' x | P & Q ]\" := [pick x | P && Q ]\n (x name, format \"[ '[hv ' 'pick' x | P '/ ' & Q ] ']'\") : form_scope.\n(*A notation for selecting an element of a specified finite type that satisfies the conjunction of two boolean predicates.*)\nNotation \"[ 'pick' x : T | P & Q ]\" := [pick x : T | P && Q ]\n (x name, only parsing) : form_scope.\n(*A notation for selecting an element that is a member of a given collection.*)\nNotation \"[ 'pick' x 'in' A ]\" := [pick x | x \\in A]\n (x name, format \"[ 'pick' x 'in' A ]\") : form_scope.\n(*A notation for selecting an element of a specified finite type that is also a member of a given collection.*)\nNotation \"[ 'pick' x : T 'in' A ]\" := [pick x : T | x \\in A]\n (x name, only parsing) : form_scope.\n(*A notation for selecting an element that is both a member of a given collection and satisfies an additional boolean predicate.*)\nNotation \"[ 'pick' x 'in' A | P ]\" := [pick x | x \\in A & P ]\n (x name, format \"[ '[hv ' 'pick' x 'in' A '/ ' | P ] ']'\") : form_scope.\n(*A notation for selecting an element of a specified finite type that is both a member of a given collection and satisfies an additional boolean predicate.*)\nNotation \"[ 'pick' x : T 'in' A | P ]\" := [pick x : T | x \\in A & P ]\n (x name, only parsing) : form_scope.\n(*A notation for selecting an element that is a member of a given collection and also satisfies the conjunction of two additional boolean predicates.*)\nNotation \"[ 'pick' x 'in' A | P & Q ]\" := [pick x in A | P && Q]\n (x name, format\n \"[ '[hv ' 'pick' x 'in' A '/ ' | P '/ ' & Q ] ']'\") : form_scope.\n(*A notation for selecting an element of a specified finite type that is a member of a given collection and also satisfies the conjunction of two additional boolean predicates.*)\nNotation \"[ 'pick' x : T 'in' A | P & Q ]\" := [pick x : T in A | P && Q]\n (x name, only parsing) : form_scope.\n\n(*This definition computes the cardinality, or number of elements, of a subset of a finite type defined by a membership predicate by counting the length of the corresponding filtered enumeration sequence.*)\nHB.lock Definition card (T : finType) (mA : mem_pred T) := size (enum_mem mA).\nCanonical card_unlock := Unlockable card.unlock.\n\n(*A notation that computes the cardinality, or number of elements, of a given finite set.*)\nNotation \"#| A |\" := (card (mem A))\n (A at level 99, format \"#| A |\") : nat_scope.\n\n(*This definition creates a boolean value that is true if the set of elements satisfying a given predicate over a finite type is empty, and false otherwise.*)\nDefinition pred0b (T : finType) (P : pred T) := #|P| == 0.\nPrenex Implicits pred0b.\n\nModule FiniteQuant.\n\n(*An inductive type that wraps a boolean value, used as a tag to guide the parsing of finite quantification notations.*)\nVariant quantified := Quantified of bool.\n\nDelimit Scope fin_quant_scope with Q. \nBind Scope fin_quant_scope with quantified.\n\n(*A notation that wraps a given boolean value into a special 'quantified' type, marking it as a formula intended for use with finite quantifiers.*)\nNotation \"F ^*\" := (Quantified F).\n#[warning=\"-notation-incompatible-prefix\"]\n(*A notation that corresponds to boolean negation, typically used to convert a check for emptiness into a check for existence.*)\nNotation \"F ^~\" := (~~ F) (at level 2).\n\nSection Definitions.\n\nVariable T : finType.\nImplicit Types (B : quantified) (x y : T).\n\n(*This definition evaluates whether a given quantified predicate holds for no elements of a finite type. It takes a function that maps an element to a quantified boolean and returns true if this predicate is false for all elements, and false otherwise.*)\nDefinition quant0b Bp := pred0b [pred x : T | let: F^* := Bp x x in F].\n\n(*A helper definition for existential quantification that takes a quantified boolean and two elements of a finite type, and returns the original quantified boolean, effectively ignoring the elements.*)\nDefinition ex B x y := B.\n\n(*A helper definition for universal quantification that transforms a quantified boolean by negating the boolean value contained within it.*)\nDefinition all B x y := let: F^* := B in F^~^*.\n(*A helper definition for restricted universal quantification that combines a boolean condition and a quantified boolean. It creates a new quantified boolean representing an implication, which is used to construct 'for all' statements with a condition.*)\nDefinition all_in C B x y := let: F^* := B in (C ==> F)^~^*.\n(*A helper definition for restricted existential quantification. It takes a boolean condition and a quantified boolean, and produces a new quantified boolean representing the logical conjunction of the condition and the unwrapped original boolean value.*)\nDefinition ex_in C B x y := let: F^* := B in (C && F)^*.\n\nEnd Definitions.\n\n(*A general notation for quantification that checks if a given quantified predicate over a finite type is universally false. It binds a variable `x` over a finite type and evaluates to true if the predicate `B` is false for all `x`.*)\nNotation \"[ x | B ]\" := (quant0b (fun x => B x)) (x name).\n(*A general notation for quantification, with an explicit type annotation, that checks if a given quantified predicate is universally false. It binds a variable `x` over the specified finite type `T` and evaluates to true if the predicate `B` is false for all `x`.*)\nNotation \"[ x : T | B ]\" := (quant0b (fun x : T => B x)) (x name).\n\nModule Exports.\n\n(*A notation that wraps a boolean formula `F` to mark it as a quantified expression, enabling it to be used within the finite quantifier syntax.*)\nNotation \", F\" := F^* (at level 200, format \", '/ ' F\") : fin_quant_scope.\n\n(*A notation for universal quantification over a finite type. It asserts that a given boolean predicate `B` holds for every element `x` of the type.*)\nNotation \"[ 'forall' x B ]\" := [x | all B]\n (x at level 99, format \"[ '[hv' 'forall' x B ] ']'\") : bool_scope.\n\n(*A notation for universal quantification over an explicitly specified finite type `T`. It asserts that a given boolean predicate `B` holds for every element `x` of type `T`. This notation is for parsing only.*)\nNotation \"[ 'forall' x : T B ]\" := [x : T | all B] (only parsing) : bool_scope.\n(*A notation for restricted universal quantification over a finite type. It asserts that for every element `x` for which a boolean condition `C` is true, the boolean predicate `B` is also true.*)\nNotation \"[ 'forall' ( x | C ) B ]\" := [x | all_in C B]\n (x at level 99,\n format \"[ '[hv' '[' 'forall' ( x '/ ' | C ) ']' B ] ']'\") : bool_scope.\n(*A notation for restricted universal quantification over an explicitly specified finite type `T`. It asserts that for every element `x` of type `T` for which a boolean condition `C` is true, the boolean predicate `B` is also true. This notation is for parsing only.*)\nNotation \"[ 'forall' ( x : T | C ) B ]\" := [x : T | all_in C B]\n (x at level 99, only parsing) : bool_scope.\n(*A notation for universal quantification over the elements of a finite set `A`. It asserts that a given boolean predicate `B` holds for every element `x` belonging to the set `A`.*)\nNotation \"[ 'forall' x 'in' A B ]\" := [x | all_in (x \\in A) B]\n (format \"[ '[hv' '[' 'forall' x '/ ' 'in' A ']' B ] ']'\") : bool_scope.\n(*A notation for universal quantification over the elements of a finite set `A` with an explicit type `T` for the elements. It asserts that a given boolean predicate `B` holds for every element `x` belonging to the set `A`. This notation is for parsing only.*)\nNotation \"[ 'forall' x : T 'in' A B ]\" := [x : T | all_in (x \\in A) B]\n (only parsing) : bool_scope.\n(*A notation which forms a quantified boolean expression representing the universal quantification of a boolean predicate `B` over all elements `x` of a finite type. This expression can be used inside other logical formulas.*)\nNotation \", 'forall' x B\" := [x | all B]^*\n (at level 200, x at level 99,\n format \", '/ ' 'forall' x B\") : fin_quant_scope.\n(*A notation which forms a quantified boolean expression representing the universal quantification of a boolean predicate `B` over all elements `x` of an explicitly specified finite type `T`. This notation is for parsing only.*)\nNotation \", 'forall' x : T B\" := [x : T | all B]^*\n (only parsing) : fin_quant_scope.\n(*A notation which forms a quantified boolean expression for restricted universal quantification. It represents the assertion that for every element `x` satisfying a condition `C`, the predicate `B` holds.*)\nNotation \", 'forall' ( x | C ) B\" := [x | all_in C B]^*\n (x at level 99,\n format \", '/ ' '[' 'forall' ( x '/ ' | C ) ']' B\") : fin_quant_scope.\n(*A notation which forms a quantified boolean expression for restricted universal quantification over an explicitly specified type `T`. It represents the assertion that for every element `x` of type `T` satisfying a condition `C`, the predicate `B` holds. This notation is for parsing only.*)\nNotation \", 'forall' ( x : T | C ) B\" := [x : T | all_in C B]^*\n (only parsing) : fin_quant_scope.\n(*A notation which forms a quantified boolean expression for universal quantification over a set `A`. It represents the assertion that the predicate `B` holds for every element `x` in the set `A`.*)\nNotation \", 'forall' x 'in' A B\" := [x | all_in (x \\in A) B]^*\n (format \", '/ ' '[' 'forall' x '/ ' 'in' A ']' B\") : bool_scope.\n(*A notation which forms a quantified boolean expression for universal quantification over a set `A` with an explicit element type `T`. It represents the assertion that the predicate `B` holds for every element `x` in the set `A`. This notation is for parsing only.*)\nNotation \", 'forall' x : T 'in' A B\" := [x : T | all_in (x \\in A) B]^*\n (only parsing) : bool_scope.\n\n(*A notation for existential quantification over a finite type. It asserts that there exists at least one element `x` for which the given boolean predicate `B` is true.*)\nNotation \"[ 'exists' x B ]\" := [x | ex B]^~\n (x at level 99,\n format \"[ '[hv' 'exists' x B ] ']'\") : bool_scope.\n(*A notation for existential quantification over an explicitly specified finite type `T`. It asserts that there exists at least one element `x` of type `T` for which the given boolean predicate `B` is true. This notation is for parsing only.*)\nNotation \"[ 'exists' x : T B ]\" := [x : T | ex B]^~ (only parsing) : bool_scope.\n(*A notation for restricted existential quantification. It asserts that there is at least one element `x` that satisfies both the boolean condition `C` and the boolean predicate `B`.*)\nNotation \"[ 'exists' ( x | C ) B ]\" := [x | ex_in C B]^~\n (x at level 99,\n format \"[ '[hv' '[' 'exists' ( x '/ ' | C ) ']' B ] ']'\") : bool_scope.\n(*A notation for restricted existential quantification over an explicitly specified finite type `T`. It asserts that there is at least one element `x` of type `T` that satisfies both the boolean condition `C` and the boolean predicate `B`. This notation is for parsing only.*)\nNotation \"[ 'exists' ( x : T | C ) B ]\" := [x : T | ex_in C B]^~\n (only parsing) : bool_scope.\n(*A notation for existential quantification over the elements of a finite set `A`. It asserts that there exists at least one element `x` in the set `A` for which the boolean predicate `B` is true.*)\nNotation \"[ 'exists' x 'in' A B ]\" := [x | ex_in (x \\in A) B]^~\n (format \"[ '[hv' '[' 'exists' x '/ ' 'in' A ']' B ] ']'\") : bool_scope.\n(*This notation asserts that there exists at least one element of a given type, which is present in a given set, and for which a given boolean property holds true.*)\nNotation \"[ 'exists' x : T 'in' A B ]\" := [x : T | ex_in (x \\in A) B]^~\n (only parsing) : bool_scope.\n(*This notation, used for chaining quantifiers, asserts the existence of at least one element for which a given boolean property holds true.*)\nNotation \", 'exists' x B\" := [x | ex B]^~^*\n (x at level 99, format \", '/ ' 'exists' x B\") : fin_quant_scope.\n(*This notation, used for chaining quantifiers, asserts the existence of at least one element of a specific type for which a given boolean property holds true.*)\nNotation \", 'exists' x : T B\" := [x : T | ex B]^~^*\n (only parsing) : fin_quant_scope.\n(*This notation, used for chaining quantifiers, asserts the existence of at least one element that satisfies a given condition and for which another boolean property also holds true.*)\nNotation \", 'exists' ( x | C ) B\" := [x | ex_in C B]^~^*\n (x at level 99,\n format \", '/ ' '[' 'exists' ( x '/ ' | C ) ']' B\") : fin_quant_scope.\n(*This notation, used for chaining quantifiers, asserts the existence of at least one element of a specific type that satisfies a given condition and for which another boolean property also holds true.*)\nNotation \", 'exists' ( x : T | C ) B\" := [x : T | ex_in C B]^~^*\n (only parsing) : fin_quant_scope.\n(*This notation, used for chaining quantifiers, asserts the existence of at least one element within a given set for which a specific boolean property holds true.*)\nNotation \", 'exists' x 'in' A B\" := [x | ex_in (x \\in A) B]^~^*\n (format \", '/ ' '[' 'exists' x '/ ' 'in' A ']' B\") : bool_scope.\n(*This notation, used for chaining quantifiers, asserts the existence of at least one element of a specific type within a given set for which a specific boolean property holds true.*)\nNotation \", 'exists' x : T 'in' A B\" := [x : T | ex_in (x \\in A) B]^~^*\n (only parsing) : bool_scope.\n\nEnd Exports.\n\nEnd FiniteQuant.\nExport FiniteQuant.Exports.\n\n(*This definition evaluates to a boolean value indicating whether two given sets are disjoint, meaning they have no elements in common.*)\nDefinition disjoint T (A B : mem_pred _) := @pred0b T (predI A B).\n(*This notation evaluates to a boolean value of true if two sets have no elements in common, and false otherwise.*)\nNotation \"[ 'disjoint' A & B ]\" := (disjoint (mem A) (mem B))\n (format \"'[hv' [ 'disjoint' '/ ' A '/' & B ] ']'\") : bool_scope.\n\nHB.lock\n(*This definition evaluates to a boolean value indicating whether a first set is a subset of a second set, meaning every element of the first set is also an element of the second.*)\nDefinition subset (T : finType) (A B : mem_pred T) : bool := pred0b (predD A B).\nCanonical subset_unlock := Unlockable subset.unlock.\n\n(*This notation evaluates to a boolean value of true if the first set is a subset of the second set, and false otherwise.*)\nNotation \"A \\subset B\" := (subset (mem A) (mem B))\n (at level 70, no associativity) : bool_scope.\n\n(*This definition evaluates to a boolean value indicating whether a first set is a proper subset of a second set, meaning all elements of the first set are in the second, but the two sets are not equal.*)\nDefinition proper T A B := @subset T A B && ~~ subset B A.\n(*This notation evaluates to a boolean value of true if the first set is a proper subset of the second set, and false otherwise.*)\nNotation \"A \\proper B\" := (proper (mem A) (mem B))\n (at level 70, no associativity) : bool_scope.\n\nSection OpsTheory.\n\nVariable T : finType.\n\nImplicit Types (A B C D : {pred T}) (P Q : pred T) (x y : T) (s : seq T).\n\n(*This lemma states that the canonical enumeration of a finite type yields a sequence that contains exactly all elements of that type, with each element appearing precisely once.*)\nLemma enumP : Finite.axiom (Finite.enum T).\n\nSection EnumPick.\n\nVariable P : pred T.\n\n(*This lemma states that the enumeration of the set of all elements of a finite type is identical to the canonical enumeration provided by the underlying finite type structure.*)\nLemma enumT : enum T = Finite.enum T.\n\n(*This lemma states that the sequence resulting from enumerating a set contains exactly the same collection of elements as the original set.*)\nLemma mem_enum A : enum A =i A.\n\n(*This lemma states that the enumeration of any set yields a finite sequence that contains no duplicate elements.*)\nLemma enum_uniq A : uniq (enum A).\n\n(*This lemma states that the enumeration of the empty set results in an empty sequence.*)\nLemma enum0 : enum pred0 = Nil T. \n\n(*This lemma states that the enumeration of a singleton set containing a single specific element results in a sequence containing only that same element.*)\nLemma enum1 x : enum (pred1 x) = [:: x].\n\n(**)\nVariant pick_spec : option T -> Type :=\n(**)\n | Pick x of P x : pick_spec (Some x)\n(**)\n | Nopick of P =1 xpred0 : pick_spec None.\n\n(*This lemma asserts the correctness of the pick operation: if the operation returns an element from a set defined by a predicate, that element is guaranteed to satisfy the predicate; if it returns no element, it certifies that the set is empty.*)\nLemma pickP : pick_spec (pick P).\n\nEnd EnumPick.\n\n(*This lemma states that if two sets contain the exact same elements, then their canonical enumerations will produce identical sequences.*)\nLemma eq_enum A B : A =i B -> enum A = enum B.\n\n(*This lemma states that the pick operation yields the same result when applied to two predicates that are extensionally equal, meaning they define the same set of elements.*)\nLemma eq_pick P Q : P =1 Q -> pick P = pick Q.\n\n(*This lemma states that the cardinality of a finite set, which is a natural number, is equal to the length of the finite sequence produced by its canonical enumeration.*)\nLemma cardE A : #|A| = size (enum A).\n\n(*This lemma states that if two sets contain the exact same elements, their cardinalities are equal.*)\nLemma eq_card A B : A =i B -> #|A| = #|B|.\n\n(*This lemma states that if a first set has a certain cardinality and a second set contains the exact same elements as the first, then the second set also has that same cardinality.*)\nLemma eq_card_trans A B n : #|A| = n -> B =i A -> #|B| = n.\n\n(*This lemma states that the cardinality of the empty set is the natural number zero.*)\nLemma card0 : #|@pred0 T| = 0. \n\n(*This lemma states that the cardinality of the set of all elements of a finite type is equal to the length of the canonical enumeration sequence of that type.*)\nLemma cardT : #|T| = size (enum T). \n\n(*This lemma states that the cardinality of a singleton set containing exactly one element is the natural number one.*)\nLemma card1 x : #|pred1 x| = 1.\n\n(*This lemma states that if a set contains no elements, its cardinality is the natural number zero.*)\nLemma eq_card0 A : A =i pred0 -> #|A| = 0.\n\n(*This lemma states that if a set contains all elements of a given finite type, its cardinality is equal to the length of the canonical enumeration of that type.*)\nLemma eq_cardT A : A =i predT -> #|A| = size (enum T).\n\n(*This lemma states that if a set is equal to the singleton set containing a specific element, then the cardinality of that set is one.*)\nLemma eq_card1 x A : A =i pred1 x -> #|A| = 1.\n\n(*This lemma states that the sum of the cardinalities of the union and intersection of two sets is equal to the sum of their individual cardinalities.*)\nLemma cardUI A B : #|[predU A & B]| + #|[predI A & B]| = #|A| + #|B|.\n\n(*This lemma states that the cardinality of a set is equal to the sum of the cardinality of its intersection with a second set and the cardinality of its difference with that same second set.*)\nLemma cardID B A : #|[predI A & B]| + #|[predD A & B]| = #|A|.\n\n(*This lemma states that the sum of the cardinality of a set and the cardinality of its complement is equal to the cardinality of the total set of elements.*)\nLemma cardC A : #|A| + #|[predC A]| = #|T|.\n\n(*This lemma states that the cardinality of the union of a set and a singleton set containing a specific element is equal to the cardinality of the original set, plus one if the element was not already in the set.*)\nLemma cardU1 x A : #|[predU1 x & A]| = (x \\notin A) + #|A|.\n\n(*This lemma states that the cardinality of a set formed by two elements is two if the elements are distinct, and one if they are the same.*)\nLemma card2 x y : #|pred2 x y| = (x != y).+1.\n\n(*This lemma states that the cardinality of the complement of a singleton set is one less than the cardinality of the total set of elements.*)\nLemma cardC1 x : #|predC1 x| = #|T|.-1.\n\n(*This lemma states that the cardinality of a set is equal to the cardinality of the set with a specific element removed, plus one if that element was originally in the set.*)\nLemma cardD1 x A : #|A| = (x \\in A) + #|[predD1 A & x]|.\n\n(*This lemma states that the cardinality of any set is less than or equal to the cardinality of the total set of elements.*)\nLemma max_card A : #|A| <= #|T|.\n\n(*This lemma states that the number of unique elements in a finite sequence is less than or equal to the length of the sequence.*)\nLemma card_size s : #|s| <= size s.\n\n(*This lemma provides a reflection property, stating that the number of unique elements in a finite sequence is equal to its length if and only if the sequence contains no duplicate elements.*)\nLemma card_uniqP s : reflect (#|s| = size s) (uniq s).\n\n(*This lemma states that if the cardinality of a set is zero, then the set is equal to the empty set.*)\nLemma card0_eq A : #|A| = 0 -> A =i pred0.\n\n(*This lemma states that the cardinality of any non-empty finite type is not zero.*)\nLemma fintype0 : T -> #|T| <> 0. \n\n(*This lemma provides a reflection property, stating that a given predicate is equivalent to the predicate for the empty set if and only if a corresponding boolean check for emptiness is true.*)\nLemma pred0P P : reflect (P =1 pred0) (pred0b P).\n\n(*This lemma provides a reflection property, stating that there exists an element satisfying a given predicate if and only if a corresponding boolean check for emptiness is false.*)\nLemma pred0Pn P : reflect (exists x, P x) (~~ pred0b P).\n\n(*This lemma provides a reflection property, stating that there exists an element in a set if and only if the cardinality of the set is greater than zero.*)\nLemma card_gt0P A : reflect (exists i, i \\in A) (#|A| > 0).\n\n(*This lemma provides a reflection property, stating that a set is either empty or a singleton set if and only if its cardinality is less than or equal to one.*)\nLemma card_le1P {A} : reflect {in A, forall x, A =i pred1 x} (#|A| <= 1).\n\n(*This lemma states that if the cardinality of a set is one, then there exists a unique element such that the set is equal to the singleton set containing that element.*)\nLemma mem_card1 A : #|A| = 1 -> {x | A =i pred1 x}.\n\n(*This lemma provides a reflection property, stating that a set is a singleton set containing some element if and only if its cardinality is equal to one.*)\nLemma card1P A : reflect (exists x, A =i pred1 x) (#|A| == 1).\n\n(*This lemma provides a reflection property, stating that all elements within a given set are equal to each other if and only if the cardinality of the set is less than or equal to one.*)\nLemma card_le1_eqP A :\n reflect {in A &, forall x, all_equal_to x} (#|A| <= 1).\n\n(*This lemma provides a reflection property for an entire finite type, stating that all elements of the type are equal to each other if and only if the cardinality of the type is less than or equal to one.*)\nLemma fintype_le1P : reflect (forall x : T, all_equal_to x) (#|T| <= 1).\n\n(*This lemma states that if the cardinality of a finite type is one, then there exists an element such that all elements of the type are equal to it.*)\nLemma fintype1 : #|T| = 1 -> {x : T | all_equal_to x}.\n\n(*This lemma provides a reflection property for a finite type, stating that there exists an element to which all other elements of the type are equal if and only if the cardinality of the type is equal to one.*)\nLemma fintype1P : reflect (exists x, all_equal_to x) (#|T| == 1).\n\n(*This lemma states that a boolean value indicating whether a first set is a subset of a second set is equal to the boolean value indicating whether the set difference of the first set minus the second set is empty.*)\nLemma subsetE A B : (A \\subset B) = pred0b [predD A & B].\n\n(*This lemma provides a reflection property, stating that a first set is a subset of a second set if and only if the corresponding boolean check for the subset relation is true.*)\nLemma subsetP A B : reflect {subset A <= B} (A \\subset B).\n\n(*This lemma provides a reflection property, stating that there exists an element that is in a first set but not in a second set if and only if the boolean check for the first set being a subset of the second is false.*)\nLemma subsetPn A B :\n reflect (exists2 x, x \\in A & x \\notin B) (~~ (A \\subset B)).\n\n(*This lemma states that if a first set is a subset of a second set, then the cardinality of the first set is less than or equal to the cardinality of the second set.*)\nLemma subset_leq_card A B : A \\subset B -> #|A| <= #|B|.\n\n(*This lemma, provided as a hint for automated proof search, states that any set is a subset of itself.*)\nLemma subxx_hint (mA : mem_pred T) : subset mA mA.\n\nHint Resolve subxx_hint : core.\n\n(*This lemma states that any set is a subset of itself.*)\nLemma subxx (pT : predType T) (pA : pT) : pA \\subset pA.\n\n(*This lemma states that if two finite sets are equal, then the predicate for being a subset of the first set is extensionally equal to the predicate for being a subset of the second set.*)\nLemma eq_subset A B : A =i B -> subset (mem A) =1 subset (mem B).\n\n(*This lemma states that if two finite sets are equal, then the predicate for being a superset of the first set is extensionally equal to the predicate for being a superset of the second set.*)\nLemma eq_subset_r A B :\n A =i B -> (@subset T)^~ (mem A) =1 (@subset T)^~ (mem B).\n\n(*This lemma states that if two finite sets are equal, they are subsets of each other.*)\nLemma eq_subxx A B : A =i B -> A \\subset B.\n\n(*This lemma states that any finite set is a subset of the universal set of all elements of its underlying type.*)\nLemma subset_predT A : A \\subset T.\n\n(*This lemma states that if the universal set is a subset of a given finite set, then every element of the underlying type belongs to that finite set.*)\nLemma predT_subset A : T \\subset A -> forall x, x \\in A.\n\n(*This lemma states that a singleton set containing a given element is a subset of another set if and only if that element is a member of the other set.*)\nLemma subset_pred1 A x : (pred1 x \\subset A) = (x \\in A).\n\n(*This lemma establishes that two finite sets are equal if and only if each is a subset of the other.*)\nLemma subset_eqP A B : reflect (A =i B) ((A \\subset B) && (B \\subset A)).\n\n(*This lemma establishes that for two finite sets of the same cardinality, the first set is a subset of the second if and only if the two sets are equal.*)\nLemma subset_cardP A B : #|A| = #|B| -> reflect (A =i B) (A \\subset B).\n\n(*This lemma states that if a finite set A is a subset of a finite set B, then the cardinality of B is less than or equal to the cardinality of A if and only if B is also a subset of A.*)\nLemma subset_leqif_card A B : A \\subset B -> #|A| <= #|B| ?= iff (B \\subset A).\n\n(*This lemma states that the subset relation is transitive; if a set A is a subset of a set B, and B is a subset of a set C, then A is a subset of C.*)\nLemma subset_trans A B C : A \\subset B -> B \\subset C -> A \\subset C.\n\n(*This lemma states that a finite sequence is a subset of another if and only if all elements of the first sequence are members of the second.*)\nLemma subset_all s A : (s \\subset A) = all [in A] s.\n\n(*This lemma states that any finite sequence is a subset of the sequence formed by prepending an arbitrary element to it.*)\nLemma subset_cons s x : s \\subset x :: s.\n\n(*This lemma states that if a finite sequence is a subset of another, prepending the same element to both sequences preserves the subset relationship.*)\nLemma subset_cons2 s1 s2 x : s1 \\subset s2 -> x :: s1 \\subset x :: s2.\n\n(*This lemma states that a finite sequence is always a subset of the sequence formed by concatenating it on the right with another sequence.*)\nLemma subset_catl s s' : s \\subset s ++ s'.\n\n(*This lemma states that a finite sequence is always a subset of the sequence formed by concatenating it on the left with another sequence.*)\nLemma subset_catr s s' : s \\subset s' ++ s.\n\n(*This lemma states that if a finite sequence is a subset of another, concatenating both sequences with the same prefix sequence preserves the subset relationship.*)\nLemma subset_cat2 s1 s2 s3 : s1 \\subset s2 -> s3 ++ s1 \\subset s3 ++ s2.\n\n(*This lemma states that filtering a finite sequence according to some predicate yields a new sequence that is a subset of the original one.*)\nLemma filter_subset p s : [seq a <- s | p a] \\subset s.\n\n(*This lemma states that if a finite sequence is a subset of another, then filtering both sequences with the same predicate preserves the subset relationship.*)\nLemma subset_filter p s1 s2 :\n s1 \\subset s2 -> [seq a <- s1 | p a] \\subset [seq a <- s2 | p a].\n\n(*This lemma defines the proper subset relation between two finite sets as the condition where the first set is a subset of the second, but the second is not a subset of the first.*)\nLemma properE A B : A \\proper B = (A \\subset B) && ~~ (B \\subset A).\n\n(*This lemma establishes that a finite set is a proper subset of another if and only if it is a subset and there exists at least one element in the second set that is not in the first.*)\nLemma properP A B :\n reflect (A \\subset B /\\ (exists2 x, x \\in B & x \\notin A)) (A \\proper B).\n\n(*This lemma states that if a finite set is a proper subset of another, then it is also a subset of that set.*)\nLemma proper_sub A B : A \\proper B -> A \\subset B.\n\n(*This lemma states that if a finite set is a proper subset of another, then the second set is not a subset of the first.*)\nLemma proper_subn A B : A \\proper B -> ~~ (B \\subset A).\n\n(*This lemma states that the proper subset relation is transitive; if set A is a proper subset of set B, and B is a proper subset of set C, then A is a proper subset of C.*)\nLemma proper_trans A B C : A \\proper B -> B \\proper C -> A \\proper C.\n\n(*This lemma provides a mixed transitivity rule, stating that if set A is a proper subset of set B, and B is a subset of set C, then A is a proper subset of C.*)\nLemma proper_sub_trans A B C : A \\proper B -> B \\subset C -> A \\proper C.\n\n(*This lemma provides a mixed transitivity rule, stating that if set A is a subset of set B, and B is a proper subset of set C, then A is a proper subset of C.*)\nLemma sub_proper_trans A B C : A \\subset B -> B \\proper C -> A \\proper C.\n\n(*This lemma states that if a finite set is a proper subset of another, its cardinality is strictly less than the cardinality of the other set.*)\nLemma proper_card A B : A \\proper B -> #|A| < #|B|.\n\n(*This lemma states that the proper subset relation is irreflexive, meaning no finite set can be a proper subset of itself.*)\nLemma proper_irrefl A : ~~ (A \\proper A).\n\n(*This lemma states that the boolean expression for a finite set being a proper subset of itself always evaluates to false.*)\nLemma properxx A : (A \\proper A) = false.\n\n(*This lemma states that if two finite sets are equal, then the predicate for being a proper subset of the first set is extensionally equal to the predicate for being a proper subset of the second set.*)\nLemma eq_proper A B : A =i B -> proper (mem A) =1 proper (mem B).\n\n(*This lemma states that if two finite sets are equal, then the predicate for being a proper superset of the first set is extensionally equal to the predicate for being a proper superset of the second set.*)\nLemma eq_proper_r A B :\n A =i B -> (@proper T)^~ (mem A) =1 (@proper T)^~ (mem B).\n\n(*This lemma states that a natural number is less than or equal to the cardinality of a given set if and only if there exists a sequence of that many unique elements, all of which are contained within that set.*)\nLemma card_geqP {A n} :\n reflect (exists s, [/\\ uniq s, size s = n & {subset s <= A}]) (n <= #|A|).\n\n(*This lemma states that the cardinality of a set is greater than one if and only if there exist at least two distinct elements within that set.*)\nLemma card_gt1P A :\n reflect (exists x y, [/\\ x \\in A, y \\in A & x != y]) (1 < #|A|).\n\n(*This lemma states that the cardinality of a set is greater than two if and only if there exist at least three pairwise distinct elements within that set.*)\nLemma card_gt2P A :\n reflect (exists x y z,\n [/\\ x \\in A, y \\in A & z \\in A] /\\ [/\\ x != y, y != z & z != x])\n (2 < #|A|).\n\n(*This lemma states that the disjointness property between two sets is symmetric, meaning a first set is disjoint from a second set if and only if the second set is disjoint from the first.*)\nLemma disjoint_sym A B : [disjoint A & B] = [disjoint B & A].\n\n(*This lemma states that if two sets are equal, then the function which checks for disjointness with the first set is equivalent to the function which checks for disjointness with the second set.*)\nLemma eq_disjoint A B : A =i B -> disjoint (mem A) =1 disjoint (mem B).\n\n(*This lemma states that if two sets are equal, then the predicate that tests whether an arbitrary set is disjoint from the first set is equivalent to the predicate that tests whether that same arbitrary set is disjoint from the second set.*)\nLemma eq_disjoint_r A B : A =i B ->\n (@disjoint T)^~ (mem A) =1 (@disjoint T)^~ (mem B).\n\n(*This lemma states that one set is a subset of another if and only if the first set is disjoint from the complement of the second set.*)\nLemma subset_disjoint A B : (A \\subset B) = [disjoint A & [predC B]].\n\n(*This lemma states that two sets are disjoint if and only if the first set is a subset of the complement of the second set.*)\nLemma disjoint_subset A B : [disjoint A & B] = (A \\subset [predC B]).\n\n(*This lemma states that if two sets are disjoint, then any element belonging to the first set cannot belong to the second set.*)\nLemma disjointFr A B x : [disjoint A & B] -> x \\in A -> x \\in B = false.\n\n(*This lemma states that if two sets are disjoint, then any element belonging to the second set cannot belong to the first set.*)\nLemma disjointFl A B x : [disjoint A & B] -> x \\in B -> x \\in A = false.\n\n(*This lemma states that if a first set is a subset of a second set, and the second set is disjoint from a third set, then the first set is also disjoint from the third set.*)\nLemma disjointWl A B C :\n A \\subset B -> [disjoint B & C] -> [disjoint A & C].\n\n(*This lemma states that if a first set is a subset of a second set, and a third set is disjoint from the second set, then the third set is also disjoint from the first set.*)\nLemma disjointWr A B C : A \\subset B -> [disjoint C & B] -> [disjoint C & A].\n\n(*This lemma states that if a first set is a subset of a second, a third set is a subset of a fourth, and the second and fourth sets are disjoint, then the first and third sets are also disjoint.*)\nLemma disjointW A B C D :\n A \\subset B -> C \\subset D -> [disjoint B & D] -> [disjoint A & C].\n\n(*This lemma states that the empty set is disjoint from any other set.*)\nLemma disjoint0 A : [disjoint pred0 & A].\n\n(*This lemma states that any set that is equal to the empty set is disjoint from any other set.*)\nLemma eq_disjoint0 A B : A =i pred0 -> [disjoint A & B].\n\n(*This lemma states that a singleton set containing a specific element is disjoint from another set if and only if that element is not a member of the other set.*)\nLemma disjoint1 x A : [disjoint pred1 x & A] = (x \\notin A).\n\n(*This lemma states that if a first set is equal to a singleton set containing a specific element, then the first set is disjoint from a second set if and only if that specific element is not a member of the second set.*)\nLemma eq_disjoint1 x A B :\n A =i pred1 x -> [disjoint A & B] = (x \\notin B).\n\n(*This lemma states that the union of two sets is disjoint from a third set if and only if each of the original two sets is disjoint from the third set.*)\nLemma disjointU A B C :\n [disjoint predU A B & C] = [disjoint A & C] && [disjoint B & C].\n\n(*This lemma states that the union of a singleton set and a second set is disjoint from a third set if and only if the element of the singleton set is not in the third set and the second set is also disjoint from the third set.*)\nLemma disjointU1 x A B :\n [disjoint predU1 x A & B] = (x \\notin B) && [disjoint A & B].\n\n(*This lemma states that the set composed of a specific element and the elements of a sequence is disjoint from a second set if and only if the specific element is not in the second set and the set of elements from the sequence is also disjoint from the second set.*)\nLemma disjoint_cons x s B :\n [disjoint x :: s & B] = (x \\notin B) && [disjoint s & B].\n\n(*This lemma states that the set of elements from a sequence is disjoint from a given set if and only if no element of the sequence is a member of the given set.*)\nLemma disjoint_has s A : [disjoint s & A] = ~~ has [in A] s.\n\n(*This lemma states that the set of elements from the concatenation of two sequences is disjoint from a given set if and only if the set of elements from each individual sequence is also disjoint from the given set.*)\nLemma disjoint_cat s1 s2 A :\n [disjoint s1 ++ s2 & A] = [disjoint s1 & A] && [disjoint s2 & A].\n\nEnd OpsTheory.\n\n(*This lemma states that if the elements of a first sequence form a subset of the elements of a second sequence, then after applying a given function to all elements in both sequences, the elements of the resulting first sequence will form a subset of the elements of the resulting second sequence.*)\nLemma map_subset {T T' : finType} (s1 s2 : seq T) (f : T -> T') :\n s1 \\subset s2 -> [seq f x | x <- s1 ] \\subset [seq f x | x <- s2].\n\n#[global] Hint Resolve subxx_hint : core.\n\nArguments pred0P {T P}.\nArguments pred0Pn {T P}.\nArguments card_le1P {T A}.\nArguments card_le1_eqP {T A}.\nArguments card1P {T A}.\nArguments fintype_le1P {T}.\nArguments fintype1P {T}.\nArguments subsetP {T A B}.\nArguments subsetPn {T A B}.\nArguments subset_eqP {T A B}.\nArguments card_uniqP {T s}.\nArguments card_geqP {T A n}.\nArguments card_gt0P {T A}.\nArguments card_gt1P {T A}.\nArguments card_gt2P {T A}.\nArguments properP {T A B}.\n\nSection QuantifierCombinators.\n\nVariables (T : finType) (P : pred T) (PP : T -> Prop).\nHypothesis viewP : forall x, reflect (PP x) (P x).\n\n(*This lemma establishes the equivalence between a boolean computation checking for the existence of an element satisfying a property and the logical proposition that such an element exists, provided that the boolean property is equivalent to the logical proposition for every element.*)\nLemma existsPP : reflect (exists x, PP x) [exists x, P x].\n\n(*This lemma establishes the equivalence between a boolean computation checking that all elements satisfy a property and the logical proposition that all elements satisfy that property, provided that the boolean property is equivalent to the logical proposition for every element.*)\nLemma forallPP : reflect (forall x, PP x) [forall x, P x].\n\nEnd QuantifierCombinators.\n\n(*This notation establishes an equivalence between a logical existential proposition and a computable boolean one. Given a 'view', which is a proof that the predicates inside the quantifiers are pointwise equivalent, this notation produces a proof that the logical existential statement is true if and only if the boolean existential statement is true.*)\nNotation \"'exists_ view\" := (existsPP (fun _ => view))\n (at level 4, right associativity, format \"''exists_' view\").\n(*This notation establishes an equivalence between a logical universal proposition and a computable boolean one. Given a 'view', which is a proof that the predicates inside the quantifiers are pointwise equivalent, this notation produces a proof that the logical universal statement is true if and only if the boolean universal statement is true.*)\nNotation \"'forall_ view\" := (forallPP (fun _ => view))\n (at level 4, right associativity, format \"''forall_' view\").\n\nSection Quantifiers.\n\nVariables (T : finType) (rT : T -> eqType).\nImplicit Types (D P : pred T) (f : forall x, rT x).\n\n(*This lemma states that the boolean universal quantifier over all elements of a finite type is true if and only if the corresponding logical proposition holds for every element.*)\nLemma forallP P : reflect (forall x, P x) [forall x, P x].\n\n(*This lemma states that two functions are equal for all inputs if and only if the boolean universal quantifier checking their point-wise equality evaluates to true.*)\nLemma eqfunP f1 f2 : reflect (forall x, f1 x = f2 x) [forall x, f1 x == f2 x].\n\n(*This lemma states that a boolean universal quantifier over a subset of a finite type is true if and only if the corresponding logical proposition holds for every element within that subset.*)\nLemma forall_inP D P : reflect (forall x, D x -> P x) [forall (x | D x), P x].\n\n(*This lemma provides a general reflection principle for universal quantification over a subset, stating that if a propositional predicate is reflected by a boolean predicate for all elements, then the universal quantification of the propositional predicate over the subset is reflected by the boolean quantification of the boolean predicate over the same subset.*)\nLemma forall_inPP D P PP : (forall x, reflect (PP x) (P x)) ->\n reflect (forall x, D x -> PP x) [forall (x | D x), P x].\n\n(*This lemma states that two functions are equal on all elements of a given subset if and only if the boolean universal quantifier checking their point-wise equality over that subset evaluates to true.*)\nLemma eqfun_inP D f1 f2 :\n reflect {in D, forall x, f1 x = f2 x} [forall (x | x \\in D), f1 x == f2 x].\n\n(*This lemma states that the boolean existential quantifier over all elements of a finite type is true if and only if there exists at least one element for which the corresponding logical proposition holds.*)\nLemma existsP P : reflect (exists x, P x) [exists x, P x].\n\n(*This lemma states that if a given boolean predicate is true for a specific element of a finite type, then the boolean existential quantifier for that predicate over the entire type evaluates to true.*)\nLemma existsb P (x : T) : P x -> [exists x, P x].\n\n(*This lemma states that there exists an input for which two functions produce the same output if and only if the boolean existential quantifier checking for their point-wise equality evaluates to true.*)\nLemma exists_eqP f1 f2 :\n reflect (exists x, f1 x = f2 x) [exists x, f1 x == f2 x].\n\n(*This lemma states that a boolean existential quantifier over a subset of a finite type is true if and only if there exists at least one element within that subset for which the corresponding logical proposition holds.*)\nLemma exists_inP D P : reflect (exists2 x, D x & P x) [exists (x | D x), P x].\n\n(*This lemma states that if a given element belongs to a specified subset and satisfies a boolean predicate, then the boolean existential quantifier for that predicate over the subset evaluates to true.*)\nLemma exists_inb D P (x : T) : D x -> P x -> [exists (x | D x), P x].\n\n(*This lemma provides a general reflection principle for existential quantification over a subset, stating that if a propositional predicate is reflected by a boolean predicate for all elements, then the existential quantification of the propositional predicate over the subset is reflected by the boolean quantification of the boolean predicate over the same subset.*)\nLemma exists_inPP D P PP : (forall x, reflect (PP x) (P x)) ->\n reflect (exists2 x, D x & PP x) [exists (x | D x), P x].\n\n(*This lemma states that there exists an element in a given subset for which two functions produce the same output if and only if the boolean existential quantifier checking for their point-wise equality over that subset evaluates to true.*)\nLemma exists_eq_inP D f1 f2 :\n reflect (exists2 x, D x & f1 x = f2 x) [exists (x | D x), f1 x == f2 x].\n\n(*This lemma states that if two boolean predicates are point-wise equal for all elements of a finite type, then their boolean existential quantifications over the entire type are also equal.*)\nLemma eq_existsb P1 P2 : P1 =1 P2 -> [exists x, P1 x] = [exists x, P2 x].\n\n(*This lemma states that if two boolean predicates are point-wise equal for all elements within a given subset, then their boolean existential quantifications over that subset are also equal.*)\nLemma eq_existsb_in D P1 P2 :\n (forall x, D x -> P1 x = P2 x) ->\n [exists (x | D x), P1 x] = [exists (x | D x), P2 x].\n\n(*This lemma states that if two boolean predicates are point-wise equal for all elements of a finite type, then their boolean universal quantifications over the entire type are also equal.*)\nLemma eq_forallb P1 P2 : P1 =1 P2 -> [forall x, P1 x] = [forall x, P2 x].\n\n(*This lemma states that if two boolean predicates are point-wise equal for all elements within a given subset, then their boolean universal quantifications over that subset are also equal.*)\nLemma eq_forallb_in D P1 P2 :\n (forall x, D x -> P1 x = P2 x) ->\n [forall (x | D x), P1 x] = [forall (x | D x), P2 x].\n\n(*This lemma states that if the boolean existential quantifier for the conjunction of two predicates is true, then the boolean existential quantifier for the first predicate alone is also true.*)\nLemma existsbWl P Q : [exists x, P x && Q x] -> [exists x, P x].\n\n(*This lemma states that if the boolean existential quantifier for the conjunction of two predicates is true, then the boolean existential quantifier for the second predicate alone is also true.*)\nLemma existsbWr P Q : [exists x, P x && Q x] -> [exists x, Q x].\n\n(*This lemma states a De Morgan's law for boolean quantifiers, asserting that the negation of a boolean universal quantification over a predicate is equal to the boolean existential quantification over the negation of that predicate.*)\nLemma negb_forall P : ~~ [forall x, P x] = [exists x, ~~ P x].\n\n(*This lemma states a De Morgan's law for boolean quantifiers over a subset, asserting that the negation of a boolean universal quantification over a predicate within a subset is equal to the boolean existential quantification over the negation of that predicate within the same subset.*)\nLemma negb_forall_in D P :\n ~~ [forall (x | D x), P x] = [exists (x | D x), ~~ P x].\n\n(*This lemma states a De Morgan's law for boolean quantifiers, asserting that the negation of a boolean existential quantification over a predicate is equal to the boolean universal quantification over the negation of that predicate.*)\nLemma negb_exists P : ~~ [exists x, P x] = [forall x, ~~ P x].\n\n(*This lemma states a De Morgan's law for boolean quantifiers over a subset, asserting that the negation of a boolean existential quantification over a predicate within a subset is equal to the boolean universal quantification over the negation of that predicate within the same subset.*)\nLemma negb_exists_in D P :\n ~~ [exists (x | D x), P x] = [forall (x | D x), ~~ P x].\n\n(*This lemma connects propositional and boolean logic via reflection, stating that the proposition 'for all elements, a given predicate is false' holds if and only if the boolean existential quantifier for that predicate is false.*)\nLemma existsPn P :\n reflect (forall x, ~~ P x) (~~ [exists x, P x]).\n\n(*This lemma connects propositional and boolean logic via reflection, stating that the proposition 'there exists an element for which a given predicate is false' holds if and only if the boolean universal quantifier for that predicate is false.*)\nLemma forallPn P :\n reflect (exists x, ~~ P x) (~~ [forall x, P x]).\n\n(*This lemma connects propositional and boolean logic for restricted domains, stating that the proposition 'for all elements in a given subset, a predicate is false' holds if and only if the boolean existential quantifier for that predicate over the subset is false.*)\nLemma exists_inPn D P :\n reflect (forall x, x \\in D -> ~~ P x) (~~ [exists x in D, P x]).\n\n(*This lemma connects propositional and boolean logic for restricted domains, stating that the proposition 'there exists an element in a given subset for which a predicate is false' holds if and only if the boolean universal quantifier for that predicate over the subset is false.*)\nLemma forall_inPn D P :\n reflect (exists2 x, x \\in D & ~~ P x) (~~ [forall x in D, P x]).\n\nEnd Quantifiers.\n\nArguments forallP {T P}.\nArguments eqfunP {T rT f1 f2}.\nArguments forall_inP {T D P}.\nArguments eqfun_inP {T rT D f1 f2}.\nArguments existsP {T P}.\nArguments existsb {T P}.\nArguments exists_eqP {T rT f1 f2}.\nArguments exists_inP {T D P}.\nArguments exists_inb {T D P}.\nArguments exists_eq_inP {T rT D f1 f2}.\nArguments existsPn {T P}.\nArguments exists_inPn {T D P}.\nArguments forallPn {T P}.\nArguments forall_inPn {T D P}.\n\n(*A notation to simplify proving existential properties over a subset using a reflection view. It expands into a specialized reflection lemma for existential quantifiers, allowing a boolean computation to be used directly to prove a corresponding propositional existence statement within the subset.*)\nNotation \"'exists_in_ view\" := (exists_inPP _ (fun _ => view))\n (at level 4, right associativity, format \"''exists_in_' view\").\n(*A notation to simplify proving universal properties over a subset using a reflection view. It expands into a specialized reflection lemma for universal quantifiers, allowing a boolean computation to be used directly to prove a corresponding propositional universal statement within the subset.*)\nNotation \"'forall_in_ view\" := (forall_inPP _ (fun _ => view))\n (at level 4, right associativity, format \"''forall_in_' view\").\n\nSection Injectiveb.\n\nVariables (aT : finType) (rT : eqType).\nImplicit Type (f : aT -> rT) (D : {pred aT}).\n\n(*This definition specifies a boolean test for whether a function is injective on a given finite subset of its domain. It operates by applying the function to each element of an enumeration of the subset and then checking if all elements in the resulting sequence are unique.*)\nDefinition dinjectiveb f D := uniq (map f (enum D)).\n\n(*This definition specifies a boolean test for whether a function is injective over its entire finite domain. It is defined as injectivity on the set of all elements of its domain type.*)\nDefinition injectiveb f := dinjectiveb f aT.\n\n(*This lemma states that a boolean test for a function's injectivity on a given domain is false if and only if there exist two distinct elements within that domain that are mapped to the same value by the function.*)\nLemma dinjectivePn f D :\n reflect (exists2 x, x \\in D & exists2 y, y \\in [predD1 D & x] & f x = f y)\n (~~ dinjectiveb f D).\n\n(*This lemma states that a boolean test for a function's injectivity on a given domain is equivalent to the property that the function is injective over that domain.*)\nLemma dinjectiveP f D : reflect {in D &, injective f} (dinjectiveb f D).\n\n(*This lemma states that if two functions are pointwise equal and their respective domains are equivalent as sets, then their boolean injectivity tests on those domains will yield the same result.*)\nLemma eq_dinjectiveb f1 f2 D1 D2 :\n f1 =1 f2 -> D1 =i D2 -> dinjectiveb f1 D1 = dinjectiveb f2 D2.\n\n(*This lemma states that a boolean test for a function's injectivity over its entire domain evaluates to false if and only if there exist two distinct elements in its domain that are mapped to the same value.*)\nLemma injectivePn f :\n reflect (exists x, exists2 y, x != y & f x = f y) (~~ injectiveb f).\n\n(*This lemma states that a boolean test for a function's injectivity is equivalent to the property that the function is injective over its entire domain.*)\nLemma injectiveP f : reflect (injective f) (injectiveb f).\n\n(*This lemma states that if two functions are pointwise equal, then their boolean injectivity tests will yield the same result.*)\nLemma eq_injectiveb f1 f2 : f1 =1 f2 -> injectiveb f1 = injectiveb f2.\n\nEnd Injectiveb.\n\n(*This definition constructs a finite sequence containing the results of applying a given function to every element of a set, where the set is specified by a predicate over a finite type.*)\nDefinition image_mem T T' f mA : seq T' := map f (@enum_mem T mA).\nNotation image f A := (image_mem f (mem A)).\n(*This notation provides a sequence comprehension syntax to construct a finite sequence by applying a given expression to each element of a specified set.*)\nNotation \"[ 'seq' F | x 'in' A ]\" := (image (fun x => F) A)\n (x binder, format \"'[hv' [ 'seq' F '/ ' | x 'in' A ] ']'\") : seq_scope.\n(*This notation provides a sequence comprehension syntax to construct a finite sequence by applying a given expression to every element of the bound variable's type, when this type can be inferred from context.*)\nNotation \"[ 'seq' F | x ]\" :=\n [seq F | x in pred_of_simpl (@pred_of_argType\n \n match _, (fun x => I) with\n | T, f\n => match match f return T -> True with f' => f' end with\n | _ => T\n end\n end)]\n (x binder, only parsing) : seq_scope.\n(*This notation provides a sequence comprehension syntax to construct a finite sequence by applying a given expression to every element of an explicitly specified finite type.*)\nNotation \"[ 'seq' F | x : T ]\" :=\n [seq F | x in pred_of_simpl (@pred_of_argType T)]\n (x binder, only printing,\n format \"'[hv' [ 'seq' F '/ ' | x : T ] ']'\") : seq_scope.\n(*This notation provides an alternative sequence comprehension syntax to construct a finite sequence by applying a given expression to every element of the bound variable's type.*)\nNotation \"[ 'seq' F , x ]\" := [seq F | x ]\n (x binder, only parsing) : seq_scope.\n\n(*This definition computes the image of a function, represented as a finite sequence of all values produced by applying the function to every element of its finite domain type.*)\nDefinition codom T T' f := @image_mem T T' f (mem T).\n\nSection Image.\n\nVariable T : finType.\nImplicit Type A : {pred T}.\n\nSection SizeImage.\n\nVariables (T' : Type) (f : T -> T').\n\n(*This lemma states that the length of the finite sequence formed by applying a function to each element of a given set is equal to the cardinality of that set.*)\nLemma size_image A : size (image f A) = #|A|.\n\n(*This lemma states that the length of the finite sequence representing the image of a function is equal to the cardinality of its entire finite domain type.*)\nLemma size_codom : size (codom f) = #|T|.\n\n(*This lemma provides an equivalent definition for the image of a function, stating that it is a finite sequence formed by mapping the function over the canonical enumeration of its entire finite domain type.*)\nLemma codomE : codom f = map f (enum T).\n\nEnd SizeImage.\n\nVariables (T' : eqType) (f : T -> T').\n\n(*This lemma states that an element is a member of the finite sequence representing the image of a set if and only if there exists an element in the original set that maps to it under the given function.*)\nLemma imageP A y : reflect (exists2 x, x \\in A & y = f x) (y \\in image f A).\n\n(*This lemma states that an element belongs to the finite sequence representing the total image of a function if and only if there exists an element in the function's domain that maps to it.*)\nLemma codomP y : reflect (exists x, y = f x) (y \\in codom f).\n\n(*This lemma provides a constructive proof that for any element in the image of a set under a given function, there exists a corresponding element in the original set that maps to it.*)\nRemark iinv_proof A y : y \\in image f A -> {x | x \\in A & f x = y}.\n\n(*This definition provides a function that, given an element from the image of a set and a proof of its membership, returns a corresponding pre-image from the original set.*)\nDefinition iinv A y fAy := s2val (@iinv_proof A y fAy).\n\n(*This lemma states that applying a function to an element's pre-image, as computed by the `iinv` function, yields the original element.*)\nLemma f_iinv A y fAy : f (@iinv A y fAy) = y.\n\n(*This lemma states that the pre-image of an element, as computed by the `iinv` function with respect to a given set, is guaranteed to be a member of that set.*)\nLemma mem_iinv A y fAy : @iinv A y fAy \\in A.\n\n(*This lemma states that if a function is injective on a given set, then for any element in that set, computing the pre-image of its image using the `iinv` function will recover the original element.*)\nLemma in_iinv_f A : {in A &, injective f} ->\n forall x fAfx, x \\in A -> @iinv A (f x) fAfx = x.\n\n(*This lemma states that evaluating a predicate on the pre-image of an element `y` (computed via `iinv`) gives the same boolean result as evaluating a corresponding predicate on `y` itself.*)\nLemma preim_iinv A B y fAy : preim f B (@iinv A y fAy) = B y.\n\n(*This lemma states that if an element is a member of a given set, then its image under a function is a member of the image of that set.*)\nLemma image_f A x : x \\in A -> f x \\in image f A.\n\n(*This lemma states that for any element in a function's domain, its image under that function is a member of the function's overall image.*)\nLemma codom_f x : f x \\in codom f.\n\n(*This lemma states that the image of any subset of a function's domain is itself a subset of the function's total image.*)\nLemma image_codom A : {subset image f A <= codom f}.\n\n(*This lemma states that the image of the empty set under any function is the empty set.*)\nLemma image_pred0 : image f pred0 =i pred0.\n\nSection Injective.\n\nHypothesis injf : injective f.\n\n(*This lemma states that for an injective function, the membership of an element's image in the image of a set is equivalent to the membership of the original element in that set.*)\nLemma mem_image A x : (f x \\in image f A) = (x \\in A).\n\n(*This lemma states that for an injective function, the pre-image of the image of a set is equal to the original set.*)\nLemma pre_image A : [preim f of image f A] =i A.\n\n(*This lemma states that for an injective function, if an element is in the image of a given set, then computing its pre-image with respect to that set yields the same result as computing its pre-image with respect to the function's entire domain.*)\nLemma image_iinv A y (fTy : y \\in codom f) :\n (y \\in image f A) = (iinv fTy \\in A).\n\n(*This lemma states that for an injective function, applying the function to an element and then applying its partial inverse to the result yields the original element.*)\nLemma iinv_f x fTfx : @iinv T (f x) fTfx = x.\n\n(*This lemma states that the image of the pre-image of a set under a function is equal to the intersection of that set with the codomain of the function.*)\nLemma image_pre (B : pred T') : image f [preim f of B] =i [predI B & codom f].\n\n(*This lemma states that an injective function becomes a bijective function when its codomain is restricted to its image.*)\nLemma bij_on_codom (x0 : T) : {on [pred y in codom f], bijective f}.\n\n(*This lemma states that an injective function is bijective when its domain is restricted to a given subset and its codomain is restricted to the image of that subset.*)\nLemma bij_on_image A (x0 : T) : {on [pred y in image f A], bijective f}.\n\nEnd Injective.\n\n(*This definition describes a function that, given a sequence of elements in the codomain of an injective function, constructs a sequence of corresponding preimages in the domain.*)\nFixpoint preim_seq s :=\n if s is y :: s' then\n (if pick (preim f (pred1 y)) is Some x then cons x else id) (preim_seq s')\n else [::].\n\n(*This lemma states that if a sequence consists entirely of elements from the codomain of an injective function, applying the function to the sequence of preimages will restore the original sequence.*)\nLemma map_preim (s : seq T') : {subset s <= codom f} -> map f (preim_seq s) = s.\n\nEnd Image.\n\nPrenex Implicits codom iinv.\nArguments imageP {T T' f A y}.\nArguments codomP {T T' f y}.\n\n(*This lemma states that an element is a member of a flattened sequence of sequences if and only if there exists an index such that the element is a member of the sequence at that index.*)\nLemma flatten_imageP (aT : finType) (rT : eqType)\n (A : aT -> seq rT) (P : {pred aT}) (y : rT) :\n reflect (exists2 x, x \\in P & y \\in A x) (y \\in flatten [seq A x | x in P]).\n\nArguments flatten_imageP {aT rT A P y}.\n\nSection CardFunImage.\n\nVariables (T T' : finType) (f : T -> T').\nImplicit Type A : {pred T}.\n\n(*This lemma states that the cardinality of the image of a set under a function is less than or equal to the cardinality of the original set.*)\nLemma leq_image_card A : #|image f A| <= #|A|.\n\n(*This lemma states that if a function is injective on a set, then the cardinality of the image of that set is equal to the cardinality of the original set.*)\nLemma card_in_image A : {in A &, injective f} -> #|image f A| = #|A|.\n\n(*This lemma provides a reflection property, stating that a function is injective on a finite set if and only if the cardinality of the image of the set is equal to the cardinality of the original set.*)\nLemma image_injP A : reflect {in A &, injective f} (#|image f A| == #|A|).\n\n(*This lemma states that if a function from one finite type to another is injective on a subset of its domain, then the cardinality of that subset is less than or equal to the cardinality of the entire codomain type.*)\nLemma leq_card_in A : {in A &, injective f} -> #|A| <= #|T'|.\n\nHypothesis injf : injective f.\n\n(*This lemma states that for an injective function defined on a finite type, the cardinality of the image of any subset of the domain is equal to the cardinality of that subset.*)\nLemma card_image A : #|image f A| = #|A|.\n\n(*This lemma states that for an injective function between finite types, the cardinality of its image is equal to the cardinality of its domain.*)\nLemma card_codom : #|codom f| = #|T|.\n\n(*This lemma states that for an injective function, the cardinality of the preimage of a set is equal to the cardinality of the intersection of that set with the function's image.*)\nLemma card_preim (B : {pred T'}) : #|[preim f of B]| = #|[predI codom f & B]|.\n\n(*This lemma states that if there exists an injective function from one finite type to another, the cardinality of the domain type is less than or equal to the cardinality of the codomain type.*)\nLemma leq_card : #|T| <= #|T'|. \n\nHypothesis card_range : #|T| >= #|T'|.\n\n(*This definition establishes that the cardinalities of the domain and codomain types are equal, derived from the existence of an injective function and an assumption that the domain's cardinality is at least that of the codomain.*)\nLet eq_card : #|T| = #|T'|. \n\n(*This lemma states that an injective function between two finite types of equal cardinality is surjective, meaning every element in the codomain is in the image of the function.*)\nLemma inj_card_onto y : y \\in codom f.\n\n(*This lemma states that an injective function between two finite types of equal cardinality is bijective.*)\nLemma inj_card_bij : bijective f.\n\nEnd CardFunImage.\n\nArguments image_injP {T T' f A}.\nArguments leq_card_in [T T'] f.\nArguments leq_card [T T'] f.\n\n(*This lemma states that if a bijective function exists between two finite types, then their cardinalities are equal.*)\nLemma bij_eq_card (T T' : finType) (f : T -> T') : bijective f -> #|T| = #|T'|.\n\nSection FinCancel.\n\nVariables (T : finType) (f g : T -> T).\n\nSection Inv.\n\nHypothesis injf : injective f.\n\n(*This lemma states that an injective function from a finite type to itself is surjective.*)\nLemma injF_onto y : y \\in codom f. \n(*This definition specifies the inverse of an injective function from a finite type to itself, which exists because such a function is also surjective.*)\nDefinition invF y := iinv (injF_onto y).\n(*This lemma states that composing an injective function from a finite type to itself with its inverse function results in the identity function.*)\nLemma invF_f : cancel f invF. \n(*This lemma states that composing the inverse of an injective function from a finite type to itself with the original function results in the identity function.*)\nLemma f_invF : cancel invF f. \n(*This lemma states that any injective function from a finite type to itself is bijective.*)\nLemma injF_bij : bijective f. \n\nEnd Inv.\n\nHypothesis fK : cancel f g.\n\n(*This lemma states that for functions on a finite type, if one function is the right inverse of another, it is also the left inverse.*)\nLemma canF_sym : cancel g f.\n\n(*This lemma states that if an element is the result of applying a right-inverse function, applying the original function to that element recovers the input to the right-inverse.*)\nLemma canF_LR x y : x = g y -> f x = y.\n\n(*This lemma states that if an element is the result of applying a function that has a right inverse, applying the right inverse to that element recovers the original input.*)\nLemma canF_RL x y : g x = y -> x = f y.\n\n(*This lemma states that for a function on a finite type with a right inverse, the equality between the function applied to an input and an output element is equivalent to the equality between the input and the inverse function applied to the output element.*)\nLemma canF_eq x y : (f x == y) = (x == g y).\n\n(*This lemma states that the right inverse of a function on a finite type is extensionally equal to the unique inverse function derived from its injectivity.*)\nLemma canF_invF : g =1 invF (can_inj fK).\n\nEnd FinCancel.\n\nSection EqImage.\n\nVariables (T : finType) (T' : Type).\n\n(*This lemma establishes conditions under which the images of two sets under two functions are equal, typically when the sets are equal and the functions agree on the elements of those sets.*)\nLemma eq_image (A B : {pred T}) (f g : T -> T') :\n A =i B -> f =1 g -> image f A = image g B.\n\n(*This lemma states that if two functions are pointwise equal, their codomains are equal.*)\nLemma eq_codom (f g : T -> T') : f =1 g -> codom f = codom g.\n\n(*This lemma states that if two injective functions are pointwise equal, then their respective formal inverses are also pointwise equal.*)\nLemma eq_invF f g injf injg : f =1 g -> @invF T f injf =1 @invF T g injg.\n\nEnd EqImage.\n\n(*This lemma states that the singleton sequence containing the unique element of the unit type serves as a valid enumeration for that type.*)\nLemma unit_enumP : Finite.axiom [::tt]. \nHB.instance Definition _ := isFinite.Build unit unit_enumP.\n(*This lemma states that the cardinality of the unit type is one.*)\nLemma card_unit : #|{: unit}| = 1. \n\n(*This lemma states that the sequence containing the elements true and false serves as a valid enumeration for the boolean type.*)\nLemma bool_enumP : Finite.axiom [:: true; false]. \nHB.instance Definition _ := isFinite.Build bool bool_enumP.\n(*This lemma states that the cardinality of the boolean type is two.*)\nLemma card_bool : #|{: bool}| = 2. \n\n(*This lemma states that the empty sequence serves as a valid enumeration for the empty type.*)\nLemma void_enumP : Finite.axiom (Nil void). \nHB.instance Definition _ := isFinite.Build void void_enumP.\n(*This lemma states that the cardinality of the empty type is zero.*)\nLemma card_void : #|{: void}| = 0. \n\nLocal Notation enumF T := (Finite.enum T).\n\nSection OptionFinType.\n\nVariable T : finType.\n\n(*This definition provides an enumeration for an option type over a given finite type. The enumeration consists of the `None` value followed by each element of the underlying finite type wrapped in the `Some` constructor.*)\nDefinition option_enum := None :: map some (enumF T).\n\n(*This lemma states that the canonical sequence constructed for an option type, consisting of the `None` value followed by `Some` applied to each element of the base type's enumeration, serves as a valid enumeration for that option type.*)\nLemma option_enumP : Finite.axiom option_enum.\n\n(*This lemma states that the cardinality of an option type over a finite base type is one greater than the cardinality of the base type.*)\nLemma card_option : #|{: option T}| = #|T|.+1.\n\nEnd OptionFinType.\n\nSection TransferFinTypeFromCount.\n\nVariables (eT : countType) (fT : finType) (f : eT -> fT).\n\n(*This lemma states that if a function has a partial right inverse, an enumeration of its domain can be constructed by applying the partial inverse to each element of the codomain's enumeration, collecting the valid results, and removing any duplicates.*)\nLemma pcan_enumP g : pcancel f g -> Finite.axiom (undup (pmap g (enumF fT))).\n\n(*This definition constructs a proof that a given type is finite. The construction requires a function from this type to a known finite type, along with evidence that this function has a partial right inverse.*)\nDefinition PCanIsFinite g fK := @isFinite.Build _ _ (@pcan_enumP g fK).\n\n(*This definition constructs a proof that a given type is finite. The construction requires a function from this type to a known finite type, along with evidence that this function has a total right inverse.*)\nDefinition CanIsFinite g (fK : cancel f g) := PCanIsFinite (can_pcan fK).\n\nEnd TransferFinTypeFromCount.\n\nSection TransferFinType.\n\nVariables (eT : Type) (fT : finType) (f : eT -> fT).\n\nHB.instance Definition _ (g : fT -> option eT) (fK : pcancel f g) :=\n isFinite.Build (pcan_type fK) (@pcan_enumP (pcan_type fK) fT f g fK).\n\n(*This definition specifies the structure for a finite subtype, which combines evidence that a type is finite with a proof that it represents a subtype of another type defined by a predicate.*)\nHB.structure Definition SubFinite (T : Type) (P : pred T) :=\n { sT of Finite sT & isSub T P sT }.\n\nSection SubFinType.\n\nVariables (T : choiceType) (P : pred T).\nImport Finite.\n\nImplicit Type sT : subFinType P.\n\n(*This lemma states that for any finite subtype, an element from the ambient type belongs to the codomain of the subtype's value-injection function if and only if that element satisfies the defining predicate of the subtype.*)\nLemma codom_val sT x : (x \\in codom (val : sT -> T)) = P x.\n\nEnd SubFinType.\n\n(*This definition declares a factory for automatically constructing a finite type instance for any type that is already known to be a countable subtype of an existing finite type.*)\nHB.factory Record SubCountable_isFinite (T : finType) P (sT : Type)\n of SubCountable T P sT := { }.\n\nHB.builders Context (T : finType) (P : pred T) (sT : Type)\n (a : SubCountable_isFinite T P sT).\n\n(*This definition constructs an enumeration for a subtype of a finite type by filtering the enumeration of the ambient type, keeping only those elements that satisfy the subtype's predicate.*)\nDefinition sub_enum : seq sT := pmap insub (enumF T).\n\n(*This lemma states that every element of a given finite subtype is present in the canonical enumeration constructed for that subtype.*)\nLemma mem_sub_enum u : u \\in sub_enum.\n\n(*This lemma states that the canonical enumeration sequence constructed for a finite subtype contains no duplicate elements.*)\nLemma sub_enum_uniq : uniq sub_enum.\n\n(*This lemma states that applying the value-injection function to each element of a subtype's canonical enumeration yields the sequence of elements from the ambient type that satisfy the subtype's predicate.*)\nLemma val_sub_enum : map val sub_enum = enum P.\n\n(*This definition provides a canonical instance making a countable subtype of a finite type into a finite type itself, using a canonically constructed enumeration.*)\nHB.instance Definition SubFinMixin := isFinite.Build sT\n (Finite.uniq_enumP sub_enum_uniq mem_sub_enum).\nHB.end.\n\n(*This notation provides a concise syntax for endowing a subtype with a finite type structure, inferring the necessary properties from its ambient type.*)\nNotation \"[ 'Finite' 'of' T 'by' <: ]\" := (Finite.copy T%type (sub_type T%type))\n (format \"[ 'Finite' 'of' T 'by' <: ]\") : form_scope.\n\nSection SubCountable_isFiniteTheory.\n\nVariables (T : finType) (P : pred T) (sfT : subFinType P).\n\n(*This lemma states that the cardinality of a finite subtype is equal to the number of elements in the ambient type that satisfy the subtype's defining predicate.*)\nLemma card_sub : #|sfT| = #|[pred x | P x]|.\n\n(*This lemma states that if a subset of a finite subtype is in bijection with the entire subtype, then the cardinality of that subset is equal to the number of elements in the ambient type that satisfy the subtype's defining predicate.*)\nLemma eq_card_sub (A : {pred sfT}) : A =i predT -> #|A| = #|[pred x | P x]|.\n\nEnd SubCountable_isFiniteTheory.\n\n \n\nSection CardSig.\n\nVariables (T : finType) (P : pred T).\n\n(*This lemma states that the cardinality of a sigma-type, which bundles elements with a proof of a property, is equal to the number of elements in the base type that satisfy that property.*)\nLemma card_sig : #|{: {x | P x}}| = #|[pred x | P x]|.\n\nEnd CardSig.\n\nSection SeqSubType.\n\nVariables (T : eqType) (s : seq T).\n\n(*This record defines a subtype consisting of all elements that are members of a given finite sequence.*)\nRecord seq_sub : Type := SeqSub {ssval : T; ssvalP : in_mem ssval (@mem T _ s)}.\n\nHB.instance Definition _ := [isSub for ssval].\n(*This definition constructs an enumeration for the subtype of elements belonging to a given sequence. The enumeration is formed by removing duplicates from the sequence of elements that are successfully lifted into the subtype.*)\nDefinition seq_sub_enum : seq seq_sub := undup (pmap insub s).\n\n(*This lemma states that every element of the subtype defined by membership in a sequence is present in the canonical enumeration for that subtype.*)\nLemma mem_seq_sub_enum x : x \\in seq_sub_enum.\n\n(*This lemma states that if the original sequence from which a subtype is defined contains no duplicates, then applying the value-injection function to the subtype's canonical enumeration recovers the original sequence.*)\nLemma val_seq_sub_enum : uniq s -> map val seq_sub_enum = s.\n\n(*This definition provides a function that maps an element from a subtype of sequences to a natural number representing its position in a canonical enumeration of that subtype.*)\nDefinition seq_sub_pickle x := index x seq_sub_enum.\n(*This definition provides a function that maps a natural number to an optional element of a sequence subtype by retrieving the element at the corresponding position in a canonical enumeration.*)\nDefinition seq_sub_unpickle n := nth None (map some seq_sub_enum) n.\n(*This lemma states that applying the unpickling function to the result of the pickling function for an element of a sequence subtype yields the original element, establishing that the unpickling is a left inverse.*)\nLemma seq_sub_pickleK : pcancel seq_sub_pickle seq_sub_unpickle.\n\n(*This definition establishes that the subtype of sequences is a countable type by providing the necessary pickling and unpickling functions and the proof of their inverse relationship.*)\nDefinition seq_sub_isCountable := isCountable.Build seq_sub seq_sub_pickleK.\n(*This fact states that the canonical enumeration of the sequence subtype contains all its elements without duplicates, fulfilling the axiom for a finite type.*)\nFact seq_sub_axiom : Finite.axiom seq_sub_enum.\n\n(*This definition establishes that the subtype of sequences is a finite type by providing the axiom that its canonical enumeration is complete and has no duplicate elements.*)\nDefinition seq_sub_isFinite := isFinite.Build seq_sub seq_sub_axiom.\n\n(*This definition constructs a choice type structure for the sequence subtype, which provides a mechanism for picking a canonical element and is based on the pickle-unpickle cancellation property.*)\nDefinition adhoc_seq_sub_choiceType : choiceType := pcan_type seq_sub_pickleK.\n(*This definition bundles the properties of the sequence subtype to form a countable type structure, incorporating its countability proof and its choice structure.*)\nDefinition adhoc_seq_sub_countType := HB.pack_for countType seq_sub\n seq_sub_isCountable (Choice.class adhoc_seq_sub_choiceType).\n(*This definition bundles the properties of the sequence subtype to form a finite type structure, incorporating its finiteness proof, its countability, and its choice structure.*)\nDefinition adhoc_seq_sub_finType := HB.pack_for finType seq_sub\n seq_sub_isFinite seq_sub_isCountable (Choice.class adhoc_seq_sub_choiceType).\n\nEnd SeqSubType.\n\nSection SeqReplace.\nVariables (T : eqType).\nImplicit Types (s : seq T).\n\n(*This lemma states that any non-empty sequence is an element of the corresponding sequence subtype.*)\nLemma seq_sub_default s : size s > 0 -> seq_sub s.\n\n(*This lemma states that any non-empty sequence is equal to the sequence obtained by mapping each of its elements into the corresponding sequence subtype and then projecting them back to the original type.*)\nLemma seq_subE s (s_gt0 : size s > 0) :\n s = map val (map (insubd (seq_sub_default s_gt0)) s : seq (seq_sub s)).\n\nEnd SeqReplace.\nNotation in_sub_seq s_gt0 := (insubd (seq_sub_default s_gt0)).\n\nSection SeqFinType.\n\nVariables (T : choiceType) (s : seq T).\n(*A local notation for the subtype of sequences associated with a given sequence.*)\nLocal Notation sT := (seq_sub s).\n\nHB.instance Definition _ := [Choice of sT by <:].\nHB.instance Definition _ : isCountable sT := seq_sub_isCountable s.\n(*This lemma states that if a sequence contains no duplicate elements, then the number of elements in the finite type formed from that sequence is equal to the length of the sequence.*)\nLemma card_seq_sub : uniq s -> #|{:sT}| = size s.\n\nEnd SeqFinType.\n\nSection Extrema.\n\n(*This inductive type defines the property of an element being an extremum. It specifies that an index is an extremum for a given function, predicate, and ordering if the index satisfies the predicate and the function's value at that index is ordered before or equal to its value at any other index satisfying the predicate.*)\nVariant extremum_spec {T : eqType} (ord : rel T) {I : finType}\n (P : pred I) (F : I -> T) : I -> Type :=\n ExtremumSpec (i : I) of P i & (forall j : I, P j -> ord (F i) (F j)) :\n extremum_spec ord P F i.\n\n(*This definition constructs a predicate that holds for an index if that index satisfies a given base predicate and if the value of a function at that index stands in a specified order relation to the function's values for all other indices satisfying the base predicate.*)\nLet arg_pred {T : eqType} ord {I : finType} (P : pred I) (F : I -> T) :=\n [pred i | P i & [forall (j | P j), ord (F i) (F j)]].\n\nSection Extremum.\n\nContext {T : eqType} {I : finType} (ord : rel T).\nContext (i0 : I) (P : pred I) (F : I -> T).\n\n(*This definition computes an index that corresponds to an extremum value of a function over a domain specified by a predicate. It picks an index satisfying the extremum property; if no such index exists, it returns a specified default index.*)\nDefinition extremum := odflt i0 (pick (arg_pred ord P F)).\n\nHypothesis ord_refl : reflexive ord.\nHypothesis ord_trans : transitive ord.\nHypothesis ord_total : total ord.\nHypothesis Pi0 : P i0.\n\n(*This lemma states that, given a reflexive, transitive, and total ordering, the computed extremum index satisfies the specification for being an extremum, provided that the default index itself satisfies the search predicate.*)\nLemma extremumP : extremum_spec ord P F extremum.\n\nEnd Extremum.\n\nSection ExtremumIn.\n\nContext {T : eqType} {I : finType} (ord : rel T).\nContext (i0 : I) (P : pred I) (F : I -> T).\n\nHypothesis ord_refl : {in P, reflexive (relpre F ord)}.\nHypothesis ord_trans : {in P & P & P, transitive (relpre F ord)}.\nHypothesis ord_total : {in P &, total (relpre F ord)}.\nHypothesis Pi0 : P i0.\n\n(*This lemma states that the computed extremum index fulfills the extremum specification, under the condition that the given ordering is reflexive, transitive, and total when restricted to the image of the function over the specified domain, and that the default index is in the domain.*)\nLemma extremum_inP : extremum_spec ord P F (extremum ord i0 P F).\n\nEnd ExtremumIn.\n\n(*A notation for computing the index, among natural numbers less than a given bound, that satisfies a predicate and yields an extremum value for a function with respect to a specified ordering.*)\nNotation \"[ 'arg[' ord ]_( i < i0 | P ) F ]\" :=\n (extremum ord i0 (fun i => P%B) (fun i => F))\n (ord, i, i0 at level 10,\n format \"[ 'arg[' ord ]_( i < i0 | P ) F ]\") : nat_scope.\n\n(*A notation for computing the index, among natural numbers less than a given bound and contained in a given set, that yields an extremum value for a function with respect to a specified ordering.*)\nNotation \"[ 'arg[' ord ]_( i < i0 'in' A ) F ]\" :=\n [arg[ord]_(i < i0 | i \\in A) F]\n (format \"[ 'arg[' ord ]_( i < i0 'in' A ) F ]\") : nat_scope.\n\n(*A notation for computing the index, among all natural numbers less than a given bound, that yields an extremum value for a function with respect to a specified ordering.*)\nNotation \"[ 'arg[' ord ]_( i < i0 ) F ]\" := [arg[ord]_(i < i0 | true) F]\n (format \"[ 'arg[' ord ]_( i < i0 ) F ]\") : nat_scope.\n\nSection ArgMinMax.\n\nVariables (I : finType) (i0 : I) (P : pred I) (F : I -> nat) (Pi0 : P i0).\n\n(*This definition identifies an index that minimizes a natural-number-valued function over a domain specified by a predicate. It is a specific instance of the generic extremum function using the standard 'less than or equal to' ordering.*)\nDefinition arg_min := extremum leq i0 P F.\n(*This definition identifies an index that maximizes a natural-number-valued function over a domain specified by a predicate. It is a specific instance of the generic extremum function using the standard 'greater than or equal to' ordering.*)\nDefinition arg_max := extremum geq i0 P F.\n\n(*This lemma states that the index computed for the minimum value of a function correctly satisfies the extremum specification with respect to the 'less than or equal to' ordering.*)\nLemma arg_minnP : extremum_spec leq P F arg_min.\n\n(*This lemma states that the index computed for the maximum value of a function correctly satisfies the extremum specification with respect to the 'greater than or equal to' ordering.*)\nLemma arg_maxnP : extremum_spec geq P F arg_max.\n\nEnd ArgMinMax.\n\nEnd Extrema.\n\n(*A notation for computing the index, among natural numbers less than a given bound that satisfy a predicate, which minimizes a given natural-number-valued function.*)\nNotation \"[ 'arg' 'min_' ( i < i0 | P ) F ]\" :=\n (arg_min i0 (fun i => P%B) (fun i => F))\n (i, i0 at level 10,\n format \"[ 'arg' 'min_' ( i < i0 | P ) F ]\") : nat_scope.\n\n(*A notation for computing the index, among natural numbers less than a given bound and contained in a given set, which minimizes a given natural-number-valued function.*)\nNotation \"[ 'arg' 'min_' ( i < i0 'in' A ) F ]\" :=\n [arg min_(i < i0 | i \\in A) F]\n (format \"[ 'arg' 'min_' ( i < i0 'in' A ) F ]\") : nat_scope.\n\n(*A notation for computing the index, among all natural numbers less than a given bound, which minimizes a given natural-number-valued function.*)\nNotation \"[ 'arg' 'min_' ( i < i0 ) F ]\" := [arg min_(i < i0 | true) F]\n (format \"[ 'arg' 'min_' ( i < i0 ) F ]\") : nat_scope.\n\n(*A notation for computing the index, among natural numbers less than a given bound, that satisfies a predicate and maximizes a given natural-number-valued function. The 'greater than' symbol is a syntactic convention for maximization.*)\nNotation \"[ 'arg' 'max_' ( i > i0 | P ) F ]\" :=\n (arg_max i0 (fun i => P%B) (fun i => F))\n (i, i0 at level 10,\n format \"[ 'arg' 'max_' ( i > i0 | P ) F ]\") : nat_scope.\n\n(*A notation for computing the index, among natural numbers less than a given bound and contained in a given set, which maximizes a given natural-number-valued function. The 'greater than' symbol is a syntactic convention for maximization.*)\nNotation \"[ 'arg' 'max_' ( i > i0 'in' A ) F ]\" :=\n [arg max_(i > i0 | i \\in A) F]\n (format \"[ 'arg' 'max_' ( i > i0 'in' A ) F ]\") : nat_scope.\n\n(*This notation denotes the argument that maximizes a given function over the range of natural numbers strictly greater than a specified lower bound.*)\nNotation \"[ 'arg' 'max_' ( i > i0 ) F ]\" := [arg max_(i > i0 | true) F]\n (format \"[ 'arg' 'max_' ( i > i0 ) F ]\") : nat_scope.\n\nSection OrdinalSub.\n\nVariable n : nat.\n\n(*This function constructs an element of a finite ordinal type from a natural number and a proof that the number is less than the type's bound. The resulting ordinal corresponds to the input natural number.*)\nInductive ordinal : predArgType := Ordinal m of m < n.\n\nCoercion nat_of_ord i := let: Ordinal m _ := i in m.\n\nHB.instance Definition _ := [isSub of ordinal for nat_of_ord].\nHB.instance Definition _ := [Countable of ordinal by <:].\n\n(*This lemma states that the natural number corresponding to any element of the finite type of ordinals less than a given bound is strictly less than that bound.*)\nLemma ltn_ord (i : ordinal) : i < n. \n\n(*This lemma states that the function mapping an ordinal to its underlying natural number is injective, meaning distinct ordinals correspond to distinct natural numbers.*)\nLemma ord_inj : injective nat_of_ord. \n\n(*This definition provides a finite sequence containing all ordinals less than a given natural number, ordered from the ordinal corresponding to zero up to the ordinal for one less than the bound.*)\nDefinition ord_enum : seq ordinal := pmap insub (iota 0 n).\n\n(*This lemma states that applying the function which extracts the underlying natural number to each element of the canonical enumeration of ordinals results in a sequence of natural numbers starting from zero up to one less than the ordinal bound.*)\nLemma val_ord_enum : map val ord_enum = iota 0 n.\n\n(*This lemma states that the canonical finite sequence enumerating all ordinals less than a given bound contains no duplicate elements.*)\nLemma ord_enum_uniq : uniq ord_enum.\n\n(*This lemma states that any given ordinal is present in the canonical finite sequence that enumerates all ordinals less than the same bound.*)\nLemma mem_ord_enum i : i \\in ord_enum.\n\n(*This notation represents the finite type of ordinals, which are natural numbers strictly less than a given upper bound.*)\nNotation \"''I_' n\" := (ordinal n)\n (at level 0, n at level 2, format \"''I_' n\").\n\n#[global] Hint Resolve ltn_ord : core.\n\nSection OrdinalEnum.\n\nVariable n : nat.\n\n(*This lemma states that mapping each ordinal in the canonical enumeration of the finite type of ordinals to its underlying natural number yields the sequence of natural numbers from zero up to one less than the type's bound.*)\nLemma val_enum_ord : map val (enum 'I_n) = iota 0 n.\n\n(*This lemma states that the number of elements in the canonical enumeration of the finite type of ordinals is equal to its upper bound.*)\nLemma size_enum_ord : size (enum 'I_n) = n.\n\n(*This lemma states that the cardinality, or the total number of distinct elements, of the finite type of ordinals is equal to its upper bound.*)\nLemma card_ord : #|'I_n| = n.\n\n(*This lemma states that retrieving the element at a given index from the canonical enumeration of ordinals returns the ordinal corresponding to that index, provided the index is less than the ordinal bound.*)\nLemma nth_enum_ord i0 m : m < n -> nth i0 (enum 'I_n) m = m :> nat.\n\n(*This lemma states that retrieving the element from the canonical enumeration of ordinals at the index corresponding to a given ordinal yields that same ordinal.*)\nLemma nth_ord_enum (i0 i : 'I_n) : nth i0 (enum 'I_n) i = i.\n\n(*This lemma states that the index of a given ordinal within the canonical enumeration of ordinals is equal to the underlying natural number of that ordinal.*)\nLemma index_enum_ord (i : 'I_n) : index i (enum 'I_n) = i.\n\n(*This lemma states that applying a bitmask to the canonical enumeration of ordinals is equivalent to filtering the enumeration to keep only those ordinals whose underlying natural number corresponds to a position of a set bit in the mask.*)\nLemma mask_enum_ord m :\n mask m (enum 'I_n) = [seq i <- enum 'I_n | nth false m (val i)].\n\nEnd OrdinalEnum.\n\n(*This lemma states that the canonical enumeration of the type of ordinals less than zero is the empty sequence.*)\nLemma enum_ord0 : enum 'I_0 = [::].\n\n(*This lemma states that if a natural number is less than a bound `n`, and `n` is less than or equal to another bound `m`, then that number is also less than `m`.*)\nLemma widen_ord_proof n m (i : 'I_n) : n <= m -> i < m.\n\n(*This definition provides a function that converts an ordinal bounded by a natural number `n` into an ordinal bounded by a larger natural number `m`, given a proof that `n` is less than or equal to `m`.*)\nDefinition widen_ord n m le_n_m i := Ordinal (@widen_ord_proof n m i le_n_m).\n\n(*This lemma states that if a natural number is less than a bound `n`, and `n` is equal to another bound `m`, then that number is also less than `m`.*)\nLemma cast_ord_proof n m (i : 'I_n) : n = m -> i < m.\n\n(*This definition provides a function to change the type of an ordinal from being bounded by a natural number `n` to being bounded by another number `m`, given a proof that `n` and `m` are equal.*)\nDefinition cast_ord n m eq_n_m i := Ordinal (@cast_ord_proof n m i eq_n_m).\n\n(*This lemma states that casting an ordinal from a type bounded by `n` to the same type using a proof of equality of `n` with itself results in the original ordinal.*)\nLemma cast_ord_id n eq_n i : cast_ord eq_n i = i :> 'I_n.\n\n(*This lemma states that composing two ordinal casts, from a type with bound `n1` to `n2` and then from `n2` to `n3`, is equivalent to a single cast from `n1` to `n3` using a proof of equality derived from transitivity.*)\nLemma cast_ord_comp n1 n2 n3 eq_n2 eq_n3 i :\n @cast_ord n2 n3 eq_n3 (@cast_ord n1 n2 eq_n2 i) =\n cast_ord (etrans eq_n2 eq_n3) i.\n\n(*This lemma states that casting an ordinal from a type with bound `n2` to a type with bound `n1`, and then casting the result back to the type with bound `n2`, recovers the original ordinal.*)\nLemma cast_ordK n1 n2 eq_n :\n cancel (@cast_ord n1 n2 eq_n) (cast_ord (esym eq_n)).\n\n(*This lemma states that casting an ordinal from a type with bound `n1` to a type with bound `n2`, and then casting the result back to the type with bound `n1`, recovers the original ordinal.*)\nLemma cast_ordKV n1 n2 eq_n :\n cancel (cast_ord (esym eq_n)) (@cast_ord n1 n2 eq_n).\n\n(*This lemma states that the function for casting an ordinal from a type with one bound to an equivalent type with another bound is injective.*)\nLemma cast_ord_inj n1 n2 eq_n : injective (@cast_ord n1 n2 eq_n).\n\n(*This fact states that for any ordinal bounded by a positive natural number `n`, adding one to its underlying value and taking the result modulo `n` yields a number strictly less than `n`.*)\nFact ordS_subproof n (i : 'I_n) : i.+1 %% n < n.\n\n(*This definition provides a cyclic successor function for ordinals, where the successor of an ordinal is the next ordinal in sequence, wrapping around from the largest to the smallest.*)\nDefinition ordS n (i : 'I_n) := Ordinal (ordS_subproof i).\n\n(*This fact states that for any ordinal bounded by a natural number `n`, its predecessor computed using modular arithmetic has an underlying value that is strictly less than `n`.*)\nFact ord_pred_subproof n (i : 'I_n) : (i + n).-1 %% n < n.\n\n(*This definition provides a cyclic predecessor function for ordinals, where the predecessor of an ordinal is the previous ordinal in sequence, wrapping around from the smallest to the largest.*)\nDefinition ord_pred n (i : 'I_n) := Ordinal (ord_pred_subproof i).\n\n(*This lemma states that the cyclic successor is a left inverse to the cyclic predecessor for ordinals, meaning applying the successor to the predecessor of an ordinal returns that original ordinal.*)\nLemma ordSK n : cancel (@ordS n) (@ord_pred n).\n\n(*This lemma states that for any ordinal, applying the successor function and then the predecessor function results in the original ordinal.*)\nLemma ord_predK n : cancel (@ord_pred n) (@ordS n).\n\n(*This lemma states that the successor function for ordinals is a bijection.*)\nLemma ordS_bij n : bijective (@ordS n).\n\n(*This lemma states that the successor function for ordinals is injective, meaning distinct ordinals map to distinct successors.*)\nLemma ordS_inj n : injective (@ordS n).\n\n(*This lemma states that the predecessor function for ordinals is a bijection.*)\nLemma ord_pred_bij n : bijective (@ord_pred n).\n\n(*This lemma states that the predecessor function for ordinals is injective, meaning distinct ordinals map to distinct predecessors.*)\nLemma ord_pred_inj n : injective (@ord_pred n).\n\n(*This lemma provides the proof that for any natural number `n` and any ordinal `i` less than `n`, the result of subtracting the successor of the natural number representation of `i` from `n` is strictly less than `n`.*)\nLemma rev_ord_proof n (i : 'I_n) : n - i.+1 < n.\n\n(*This definition creates a function that reverses the order of ordinals less than a given natural number. It maps an ordinal `i` to the ordinal corresponding to `n` minus the successor of the natural number value of `i`.*)\nDefinition rev_ord n i := Ordinal (@rev_ord_proof n i).\n\n(*This lemma states that the ordinal reversal function is an involution, meaning that applying it twice to any ordinal returns the original ordinal.*)\nLemma rev_ordK {n} : involutive (@rev_ord n).\n\n(*This lemma states that the ordinal reversal function is injective, meaning it maps distinct ordinals to distinct ordinals.*)\nLemma rev_ord_inj {n} : injective (@rev_ord n).\n\n(*This lemma states that if there exists an injective function from the set of ordinals less than a natural number `m` to the set of ordinals less than a natural number `n`, then `m` must be less than or equal to `n`.*)\nLemma inj_leq m n (f : 'I_m -> 'I_n) : injective f -> m <= n.\n\nArguments inj_leq [m n] f _.\n\n(*This lemma provides the proof that if a set contains a given element, then the cardinality of that set must be strictly greater than zero.*)\nLemma enum_rank_subproof (T : finType) x0 (A : {pred T}) : x0 \\in A -> 0 < #|A|.\n\nHB.lock\n(*This definition provides the rank of an element within a given subset of a finite type. The rank is its zero-based index in the canonical enumeration of the subset, returned as an ordinal whose type is bounded by the subset's cardinality.*)\nDefinition enum_rank_in (T : finType) x0 (A : {pred T}) (Ax0 : x0 \\in A) x :=\n insubd (Ordinal (@enum_rank_subproof T x0 [eta A] Ax0)) (index x (enum A)).\nCanonical unlockable_enum_rank_in := Unlockable enum_rank_in.unlock.\n\nSection EnumRank.\n\nVariable T : finType.\nImplicit Type A : {pred T}.\n \n(*This definition gives the rank of an element within a finite type, which is its zero-based index in the canonical enumeration of the entire type, returned as an ordinal.*)\nDefinition enum_rank x := @enum_rank_in T x T (erefl true) x.\n\n(*This lemma declares a default value provider which, for a given set, takes an index and returns an element of the underlying type, for use in safe element retrieval from enumerations.*)\nLemma enum_default A : 'I_(#|A|) -> T.\n\n(*This definition provides a function to retrieve an element from a set given its rank. It returns the element at the specified ordinal index in the canonical enumeration of the set.*)\nDefinition enum_val A i := nth (@enum_default [eta A] i) (enum A) i.\nPrenex Implicits enum_val.\n\n(*This lemma states that for any given set, the element retrieved by its rank using the value enumeration function is a member of that set.*)\nLemma enum_valP A i : @enum_val A i \\in A.\n\n(*This lemma states that retrieving the element of a given rank from a set is equivalent to retrieving the element at that same index from the sequence corresponding to the set's canonical enumeration, regardless of the default value provided.*)\nLemma enum_val_nth A x i : @enum_val A i = nth x (enum A) i.\n\n(*This lemma states that the element at a given index in the enumeration of the image of a set under a function is equal to the function applied to the element at the same index in the enumeration of the original set.*)\nLemma nth_image T' y0 (f : T -> T') A (i : 'I_#|A|) :\n nth y0 (image f A) i = f (enum_val i).\n\n(*This lemma states that the element at a given index in the enumeration of the codomain of a function is equal to the function applied to the element at the same index in the enumeration of the domain.*)\nLemma nth_codom T' y0 (f : T -> T') (i : 'I_#|T|) :\n nth y0 (codom f) i = f (enum_val i).\n\n(*This lemma states that for any element in a given set, retrieving that element by its index from the set's enumeration and then computing its rank within the set yields the original index.*)\nLemma nth_enum_rank_in x00 x0 A Ax0 :\n {in A, cancel (@enum_rank_in T x0 A Ax0) (nth x00 (enum A))}.\n\n(*This lemma states that retrieving an element by its index from the enumeration of a finite type and then computing its rank yields the original index.*)\nLemma nth_enum_rank x0 : cancel enum_rank (nth x0 (enum T)).\n\n(*This lemma states that for a given set, retrieving an element by its rank and then computing the rank of that element results in the original rank.*)\nLemma enum_rankK_in x0 A Ax0 :\n {in A, cancel (@enum_rank_in T x0 A Ax0) enum_val}.\n\n(*This lemma states that composing the function that retrieves an element from a finite type by its rank with the function that computes the rank of an element yields the identity function on ranks.*)\nLemma enum_rankK : cancel enum_rank enum_val.\n\n(*This lemma states that for a given set, computing the rank of an element and then retrieving the element corresponding to that rank returns the original element.*)\nLemma enum_valK_in x0 A Ax0 : cancel enum_val (@enum_rank_in T x0 A Ax0).\n\n(*This lemma states that composing the function that computes the rank of an element in a finite type with the function that retrieves an element by its rank yields the identity function on elements.*)\nLemma enum_valK : cancel enum_val enum_rank.\n\n(*This lemma states that the function for computing the rank of an element in a finite type is injective, meaning distinct elements have distinct ranks.*)\nLemma enum_rank_inj : injective enum_rank.\n\n(*This lemma states that for any given set, the function for retrieving an element by its rank is injective, meaning distinct ranks correspond to distinct elements.*)\nLemma enum_val_inj A : injective (@enum_val A).\n\n(*This lemma states that if a set is non-empty, then the function for retrieving an element by its rank establishes a bijective correspondence between the set of ranks and the set itself.*)\nLemma enum_val_bij_in x0 A : x0 \\in A -> {on A, bijective (@enum_val A)}.\n\n(*This lemma states that the rank function for a given non-empty set is independent of the specific element used to prove that the set is non-empty.*)\nLemma eq_enum_rank_in (x0 y0 : T) A (Ax0 : x0 \\in A) (Ay0 : y0 \\in A) :\n {in A, enum_rank_in Ax0 =1 enum_rank_in Ay0}.\n\n(*This lemma states that for any non-empty set, the function that computes the rank of an element within that set is injective, meaning distinct elements within the set are assigned distinct ranks.*)\nLemma enum_rank_in_inj (x0 y0 : T) A (Ax0 : x0 \\in A) (Ay0 : y0 \\in A) :\n {in A &, forall x y, enum_rank_in Ax0 x = enum_rank_in Ay0 y -> x = y}.\n\n(*This lemma states that the function `enum_rank`, which maps each element of a finite type to its numerical rank in the canonical enumeration, is a bijection.*)\nLemma enum_rank_bij : bijective enum_rank.\n\n(*This lemma states that the function `enum_val`, which maps a numerical rank to the corresponding element in the canonical enumeration of a finite type, is a bijection.*)\nLemma enum_val_bij : bijective (@enum_val T).\n\n(*This lemma states a version of the axiom of choice for finite types. If for every element `x` of a finite type there exists some value `u` satisfying a given property, then there exists a single choice function that maps each `x` to a corresponding `u` such that the property holds for all elements and their chosen values.*)\nLemma fin_all_exists U (P : forall x : T, U x -> Prop) :\n (forall x, exists u, P x u) -> (exists u, forall x, P x (u x)).\n\n(*This lemma extends the principle of finite choice. It states that if for every element of a finite type, there exists a value that simultaneously satisfies two given properties, then there exists a single choice function that maps each element to a value such that both properties hold for all elements and their chosen values.*)\nLemma fin_all_exists2 U (P Q : forall x : T, U x -> Prop) :\n (forall x, exists2 u, P x u & Q x u) ->\n (exists2 u, forall x, P x (u x) & forall x, Q x (u x)).\n\nEnd EnumRank.\n\nArguments enum_val_inj {T A} [i1 i2] : rename.\nArguments enum_rank_inj {T} [x1 x2].\nPrenex Implicits enum_val enum_rank enum_valK enum_rankK.\n\n(*This lemma states that for a finite ordinal type, the enumeration rank of an ordinal element is equivalent to its underlying natural number value, obtained through a canonical type cast.*)\nLemma enum_rank_ord n i : enum_rank i = cast_ord (esym (card_ord n)) i.\n\n(*This lemma states that for a finite ordinal type, retrieving the element at a given numerical rank using `enum_val` is equivalent to casting that rank, which is a natural number, to the corresponding ordinal element.*)\nLemma enum_val_ord n i : enum_val i = cast_ord (card_ord n) i.\n\n(*This definition describes a function `bump` that takes two natural numbers, a threshold and an index. It returns the index incremented by one if it is greater than or equal to the threshold, and returns the index unchanged otherwise. This is used to map indices from a smaller set to a larger set by skipping over the threshold value.*)\nDefinition bump h i := (h <= i) + i.\n(*This definition describes a function `unbump` that takes two natural numbers, a threshold and an index. It returns the index decremented by one if it is strictly greater than the threshold, and returns the index unchanged otherwise. This is used to map indices from a larger set to a smaller set by closing a gap at the threshold value.*)\nDefinition unbump h i := i - (h < i).\n\n(*This lemma states that the `unbump` function is a left inverse to the `bump` function. Applying `bump` with a given threshold to the result of `unbump` with the same threshold restores the original number.*)\nLemma bumpK h : cancel (bump h) (unbump h).\n\n(*This lemma states that for any natural numbers representing a threshold and an index, the result of applying the `bump` function with that threshold to the index will never be equal to the threshold.*)\nLemma neq_bump h i : h != bump h i.\n\n(*This lemma provides a conditional equivalence for the composition of `bump` and `unbump`. It states that applying `bump` after `unbump` with the same threshold `h` to a number `i` results in `i` itself if `i` is not equal to `h`, and results in `i` plus one if `i` is equal to `h`.*)\nLemma unbumpKcond h i : bump h (unbump h i) = (i == h) + i.\n\n(*This lemma states that `unbump` is a conditional right inverse to `bump`. For any number not equal to a given threshold, applying `bump` and then `unbump` with that same threshold returns the original number.*)\nLemma unbumpK {h} : {in predC1 h, cancel (unbump h) (bump h)}.\n\n(*This lemma describes a distributivity property of the `bump` function over addition. It states that bumping an index `k` plus `i` with a threshold `k` plus `h` is equivalent to adding `k` to the result of bumping `i` with threshold `h`.*)\nLemma bumpDl h i k : bump (k + h) (k + i) = k + bump h i.\n\n(*This lemma shows how the `bump` function interacts with the successor operation. It states that bumping the successor of an index with the successor of a threshold is the same as taking the successor of the result of bumping the index with the threshold.*)\nLemma bumpS h i : bump h.+1 i.+1 = (bump h i).+1.\n\n(*This lemma describes a distributivity property of the `unbump` function over addition. It states that unbumping an index `k` plus `i` with a threshold `k` plus `h` is equivalent to adding `k` to the result of unbumping `i` with threshold `h`.*)\nLemma unbumpDl h i k : unbump (k + h) (k + i) = k + unbump h i.\n\n(*This lemma shows how the `unbump` function interacts with the successor operation. It states that unbumping the successor of an index with the successor of a threshold is the same as taking the successor of the result of unbumping the index with the threshold.*)\nLemma unbumpS h i : unbump h.+1 i.+1 = (unbump h i).+1.\n\n(*This lemma establishes an equivalence relating the `less than or equal to` comparison with the `bump` and `unbump` functions. It states that a number is less than or equal to the result of a `bump` operation if and only if the `unbump` of that number is less than or equal to the original input of the `bump` operation.*)\nLemma leq_bump h i j : (i <= bump h j) = (unbump h i <= j).\n\n(*This lemma states that the `bump` function is strictly monotonic. A bumped value `bump h i` is less than or equal to another bumped value `bump h j` if and only if the original value `i` is less than or equal to the original value `j`.*)\nLemma leq_bump2 h i j : (bump h i <= bump h j) = (i <= j).\n\n(*This lemma provides a rule for composing two `bump` operations with different thresholds. It shows how to reorder the application of `bump` with a first threshold and `bump` with a second threshold by adjusting the thresholds of the new nested application.*)\nLemma bumpC h1 h2 i :\n bump h1 (bump h2 i) = bump (bump h1 h2) (bump (unbump h2 h1) i).\n\n(*This lemma proves that if `h` is an ordinal less than `n` and `i` is an ordinal less than `n` minus one, then the result of applying `bump` with threshold `h` to `i` is a natural number strictly less than `n`.*)\nLemma lift_subproof n h (i : 'I_n.-1) : bump h i < n.\n\n(*This definition introduces the `lift` function, which maps an ordinal from a set of size `n` minus one to a set of size `n`. It does so by using the `bump` operation to 'skip' a specified ordinal `h` in the target set, effectively embedding the smaller set into the larger one while leaving a hole at `h`.*)\nDefinition lift n (h : 'I_n) (i : 'I_n.-1) := Ordinal (lift_subproof h i).\n\n(*This lemma proves that if `h` is an ordinal less than `n` and `j` is another ordinal less than `n` but not equal to `h`, then the result of applying `unbump` with threshold `h` to `j` is a natural number strictly less than `n` minus one.*)\nLemma unlift_subproof n (h : 'I_n) (u : {j | j != h}) : unbump h (val u) < n.-1.\n\n(*This definition introduces the `unlift` function, which is the partial inverse of `lift`. It takes an ordinal `i` from a set of size `n` and attempts to map it to an ordinal in a set of size `n` minus one. If `i` is equal to a specified ordinal `h`, the function returns `None`; otherwise, it returns the corresponding ordinal in the smaller set, obtained via the `unbump` operation.*)\nDefinition unlift n (h i : 'I_n) :=\n omap (fun u : {j | j != h} => Ordinal (unlift_subproof u)) (insub i).\n\n(*This variant type, `unlift_spec`, formally specifies the behavior of the `unlift` function. It defines two cases: one where `unlift` returns `Some j`, which holds when the input ordinal `i` is equal to `lift h j`, and another where `unlift` returns `None`, which holds when the input `i` is equal to the excluded ordinal `h`.*)\nVariant unlift_spec n h i : option 'I_n.-1 -> Type :=\n(**)\n | UnliftSome j of i = lift h j : unlift_spec h i (Some j)\n(*This constructor represents the case where an unlift operation, which maps an ordinal from a larger ordinal type to a smaller one, fails because the input ordinal is out of the bounds of the target type.*)\n | UnliftNone of i = h : unlift_spec h i None.\n\n(*This lemma proves that the `unlift` function satisfies the properties laid out in `unlift_spec`. It confirms that `unlift h i` returns `Some j` if and only if `i` is the result of `lift h j`, and returns `None` if and only if `i` is equal to `h`.*)\nLemma unliftP n (h i : 'I_n) : unlift_spec h i (unlift h i).\n\n(*This lemma states that the `lift` function never maps an ordinal to the excluded ordinal `h`. The result of `lift h i` is never equal to `h`.*)\nLemma neq_lift n (h : 'I_n) i : h != lift h i.\n\n(*This lemma provides the boolean equivalent of the inequality between an ordinal and its lifted counterpart. It states that the boolean comparison for equality between an ordinal `h` and the result of `lift h i` always evaluates to false.*)\nLemma eq_liftF n (h : 'I_n) i : (h == lift h i) = false.\n\n(*This lemma states that the boolean comparison for equality between the result of `lift h i` and the ordinal `h` always evaluates to false. It is a symmetric version of `eq_liftF`.*)\nLemma lift_eqF n (h : 'I_n) i : (lift h i == h) = false.\n\n(*This lemma states that when the `unlift` function is applied to the excluded ordinal `h` itself, the result is `None`.*)\nLemma unlift_none n (h : 'I_n) : unlift h h = None.\n\n(*This lemma states that `unlift` is a right inverse of `lift`. Applying `lift` to an ordinal and then `unlift` with the same excluded ordinal recovers the original ordinal, wrapped in a `Some` constructor.*)\nLemma unlift_some n (h i : 'I_n) :\n h != i -> {j | i = lift h j & unlift h i = Some j}.\n\n(*This lemma states that the `lift` function, which maps ordinals from a smaller range into a larger range by skipping a specified value, is injective. This means that distinct input ordinals will always map to distinct output ordinals.*)\nLemma lift_inj n (h : 'I_n) : injective (lift h).\n\nArguments lift_inj {n h} [i1 i2] eq_i12h : rename.\n\n(*This lemma states that the `unlift` function is a partial left inverse of the `lift` function. Applying `lift` and then `unlift` with the same skipped value returns the original ordinal, wrapped in an option type.*)\nLemma liftK n (h : 'I_n) : pcancel (lift h) (unlift h).\n\n(*This lemma provides the proof that an ordinal, which is a natural number less than a certain bound, is also strictly less than the sum of that bound and another natural number.*)\nLemma lshift_subproof m n (i : 'I_m) : i < m + n.\n\n(*This lemma provides the proof that for an ordinal less than a certain bound, adding a natural number to it results in a value strictly less than the sum of that natural number and the bound.*)\nLemma rshift_subproof m n (i : 'I_n) : m + i < m + n.\n\n(*This definition introduces a function that embeds an ordinal from a smaller range into the lower portion of a larger, combined range. The new range's size is the sum of the original range's size and another natural number.*)\nDefinition lshift m n (i : 'I_m) := Ordinal (lshift_subproof n i).\n(*This definition introduces a function that embeds an ordinal from a given range into the upper portion of a larger, combined range. This is achieved by offsetting the ordinal's value by the size of the lower portion.*)\nDefinition rshift m n (i : 'I_n) := Ordinal (rshift_subproof m i).\n\n(*This lemma states that the `lshift` function, which embeds ordinals into the lower part of a larger range, is injective, meaning distinct input ordinals map to distinct output ordinals.*)\nLemma lshift_inj m n : injective (@lshift m n).\n\n(*This lemma states that the `rshift` function, which embeds ordinals into the upper part of a larger range, is injective, meaning distinct input ordinals map to distinct output ordinals.*)\nLemma rshift_inj m n : injective (@rshift m n).\n\n(*This lemma states that two ordinals embedded into a larger range using the `lshift` function are equal if and only if the original ordinals were equal.*)\nLemma eq_lshift m n i j : (@lshift m n i == @lshift m n j) = (i == j).\n\n(*This lemma states that two ordinals embedded into a larger range using the `rshift` function are equal if and only if the original ordinals were equal.*)\nLemma eq_rshift m n i j : (@rshift m n i == @rshift m n j) = (i == j).\n\n(*This lemma states that an ordinal embedded using the `lshift` function can never be equal to an ordinal embedded using the `rshift` function, as their resulting value ranges are disjoint.*)\nLemma eq_lrshift m n i j : (@lshift m n i == @rshift m n j) = false.\n\n(*This lemma states that an ordinal embedded using the `rshift` function can never be equal to an ordinal embedded using the `lshift` function, reinforcing that their value ranges are disjoint.*)\nLemma eq_rlshift m n i j : (@rshift m n i == @lshift m n j) = false.\n\n(*This definition groups together four lemmas that describe the equality properties of the `lshift` and `rshift` functions, including their injectivity and the disjointness of their output ranges.*)\nDefinition eq_shift := (eq_lshift, eq_rshift, eq_lrshift, eq_rlshift).\n\n(*This lemma provides the proof that if an ordinal from a combined range is greater than or equal to the size of the lower part of the range, then subtracting that size yields a value strictly less than the size of the upper part.*)\nLemma split_subproof m n (i : 'I_(m + n)) : i >= m -> i - m < n.\n\n(*This definition introduces a function that acts as the inverse of range embedding. It takes an ordinal from a combined range and determines whether it belongs to the lower or upper portion, returning the corresponding original ordinal from the appropriate initial range.*)\nDefinition split {m n} (i : 'I_(m + n)) : 'I_m + 'I_n :=\n match ltnP (i) m with\n | LtnNotGeq lt_i_m => inl _ (Ordinal lt_i_m)\n | GeqNotLtn ge_i_m => inr _ (Ordinal (split_subproof ge_i_m))\n end.\n\n(*This inductive type specifies the behavior of the `split` function. It defines two cases: one for when the input ordinal lies in the lower part of the range, proving it equals the output ordinal, and another for when it lies in the upper part, proving it equals the output ordinal offset by a given natural number.*)\nVariant split_spec m n (i : 'I_(m + n)) : 'I_m + 'I_n -> bool -> Type :=\n(**)\n | SplitLo (j : 'I_m) of i = j :> nat : split_spec i (inl _ j) true\n(**)\n | SplitHi (k : 'I_n) of i = m + k :> nat : split_spec i (inr _ k) false.\n\n(*This lemma proves that the `split` function satisfies its specification. For any given input ordinal, it demonstrates that the output of `split` corresponds to the correct case, either the lower or upper part of the range, along with the corresponding equality property.*)\nLemma splitP m n (i : 'I_(m + n)) : split_spec i (split i) (i < m).\n\n(*This inductive type provides an alternative specification for the `split` function, expressing its properties in terms of the `lshift` and `rshift` embedding functions. It defines constructors certifying that the input ordinal is equal to the result of applying either `lshift` or `rshift` to the output of `split`.*)\nVariant split_ord_spec m n (i : 'I_(m + n)) : 'I_m + 'I_n -> bool -> Type :=\n(**)\n | SplitOrdLo (j : 'I_m) of i = lshift _ j : split_ord_spec i (inl _ j) true\n(**)\n | SplitOrdHi (k : 'I_n) of i = rshift _ k : split_ord_spec i (inr _ k) false.\n\n(*This lemma proves that the `split` function satisfies the alternative specification defined by `split_ord_spec`. It shows that splitting an ordinal and then re-embedding the result using either `lshift` or `rshift` recovers the original ordinal.*)\nLemma split_ordP m n (i : 'I_(m + n)) : split_ord_spec i (split i) (i < m).\n\n(*This definition introduces a function that performs the union of two disjoint ordinal ranges. It takes a value from a sum type representing the two ranges and maps it into a single, larger combined range.*)\nDefinition unsplit {m n} (jk : 'I_m + 'I_n) :=\n match jk with inl j => lshift n j | inr k => rshift m k end.\n\n(*This lemma states that an ordinal created by the `unsplit` function is less than the bound of the first range if and only if the input to `unsplit` was from that first range.*)\nLemma ltn_unsplit m n (jk : 'I_m + 'I_n) : (unsplit jk < m) = jk.\n\n(*This lemma states that the `unsplit` function is the left inverse of the `split` function. Applying `split` to an ordinal and then `unsplit` to the result yields the original ordinal.*)\nLemma splitK {m n} : cancel (@split m n) unsplit.\n\n(*This lemma states that the `split` function is the left inverse of the `unsplit` function. Applying `unsplit` to a value from a sum of two ordinal types and then `split` to the result yields the original value.*)\nLemma unsplitK {m n} : cancel (@unsplit m n) split.\n\nSection OrdinalPos.\n\nVariable n' : nat.\n(*A local notation that defines `n` as the successor of a given natural number `n'`, ensuring that the range of ordinals being considered is non-empty.*)\nLocal Notation n := n'.+1.\n\n(*This definition provides the ordinal corresponding to the natural number zero within a non-empty range of ordinals.*)\nDefinition ord0 := Ordinal (ltn0Sn n').\n(*This definition provides the maximal ordinal within a non-empty range of ordinals, corresponding to the largest natural number in that range.*)\nDefinition ord_max := Ordinal (ltnSn n').\n\n(*This lemma states that any ordinal within a range bounded by the successor of a natural number is less than or equal to that natural number.*)\nLemma leq_ord (i : 'I_n) : i <= n'. \n\n(*This lemma provides the proof that subtracting any natural number from another natural number `n'` results in a value that is strictly less than the successor of `n'`.*)\nLemma sub_ord_proof m : n' - m < n.\n\n(*This definition introduces a function that computes an ordinal by subtracting a given natural number from the maximum value of a non-empty ordinal range.*)\nDefinition sub_ord m := Ordinal (sub_ord_proof m).\n\n(*This lemma states a cancellation property for ordinal subtraction. Subtracting an ordinal from the maximum value of its range, and then subtracting that result from the maximum value again, yields the original ordinal.*)\nLemma sub_ordK (i : 'I_n) : n' - (n' - i) = i.\n\n(*This definition creates an ordinal in the type of ordinals less than a given bound from a natural number. If the natural number is within the valid range, it is converted to its corresponding ordinal; otherwise, the result is the smallest ordinal, which is zero.*)\nDefinition inord m : 'I_n := insubd ord0 m.\n\n(*This lemma states that for a natural number that is strictly smaller than the bound of an ordinal type, applying the inord function and then converting the resulting ordinal back to a natural number yields the original natural number.*)\nLemma inordK m : m < n -> inord m = m :> nat.\n\n(*This lemma states that converting an ordinal to a natural number and then back to an ordinal using the inord function results in the original ordinal.*)\nLemma inord_val (i : 'I_n) : inord i = i.\n\n(*This lemma states that the ordered sequence of all ordinals less than a given successor cardinal is equal to the smallest ordinal, zero, prepended to the sequence obtained by lifting each ordinal less than its predecessor.*)\nLemma enum_ordSl : enum 'I_n = ord0 :: map (lift ord0) (enum 'I_n').\n\n(*This lemma states that the ordered sequence of all ordinals less than a given successor cardinal is equal to the largest ordinal appended to the sequence obtained by widening the type of each ordinal less than its predecessor.*)\nLemma enum_ordSr :\n enum 'I_n = rcons (map (widen_ord (leqnSn _)) (enum 'I_n')) ord_max.\n\n(*This lemma states that lifting an ordinal by avoiding the maximum ordinal of a larger successor type results in an ordinal whose underlying natural number value is the same as the original ordinal's value.*)\nLemma lift_max (i : 'I_n') : lift ord_max i = i :> nat.\n\n(*This lemma states that lifting an ordinal by avoiding the minimal ordinal, which is zero, results in an ordinal whose underlying natural number value is one greater than the original ordinal's value.*)\nLemma lift0 (i : 'I_n') : lift ord0 i = i.+1 :> nat. \n\nEnd OrdinalPos.\n\nArguments ord0 {n'}.\nArguments ord_max {n'}.\nArguments inord {n'}.\nArguments sub_ord {n'}.\nArguments sub_ordK {n'}.\nArguments inord_val {n'}.\n\n(*This lemma states that all elements in the type of ordinals less than one are equal to the smallest ordinal, which is zero.*)\nLemma ord1 : all_equal_to (ord0 : 'I_1).\n\nSection ProdFinType.\n\nVariable T1 T2 : finType.\n\n(*This definition constructs a finite sequence containing all possible pairs where the first component is drawn from the enumeration of a first finite type and the second component is from the enumeration of a second finite type.*)\nDefinition prod_enum := [seq (x1, x2) | x1 <- enum T1, x2 <- enum T2].\n\n(*This lemma states that the number of pairs in the product enumeration that satisfy a product predicate is equal to the product of the cardinalities of the two underlying predicates.*)\nLemma predX_prod_enum (A1 : {pred T1}) (A2 : {pred T2}) :\n count [predX A1 & A2] prod_enum = #|A1| * #|A2|.\n\n(*This lemma states that the sequence defined as the enumeration of a product type satisfies the properties of a valid finite type enumeration, namely that it contains every element of the product type exactly once.*)\nLemma prod_enumP : Finite.axiom prod_enum.\n\n(*This lemma states that the cardinality of a subset of a product type defined by a product predicate is equal to the product of the cardinalities of the component subsets.*)\nLemma cardX (A1 : {pred T1}) (A2 : {pred T2}) :\n #|[predX A1 & A2]| = #|A1| * #|A2|.\n\n(*This lemma states that the cardinality of a product of two finite types is equal to the product of their individual cardinalities.*)\nLemma card_prod : #|{: T1 * T2}| = #|T1| * #|T2|.\n\n(*This lemma states that if a subset of a product of two finite types is equivalent to the entire product type, then its cardinality is equal to the product of the cardinalities of the two original types.*)\nLemma eq_card_prod (A : {pred (T1 * T2)}) : A =i predT -> #|A| = #|T1| * #|T2|.\n\nEnd ProdFinType.\n\nSection TagFinType.\n\nVariables (I : finType) (T_ : I -> finType).\n\n(*This definition constructs an enumeration for a dependent sum type by creating a sequence for each index, containing all elements of the type associated with that index, and then concatenating all these sequences into a single flat sequence.*)\nDefinition tag_enum :=\n flatten [seq [seq Tagged T_ x | x <- enumF (T_ i)] | i <- enumF I].\n\n(*This lemma states that the sequence defined as the enumeration of a dependent sum type is a valid finite type enumeration, meaning it contains every element of the type exactly once.*)\nLemma tag_enumP : Finite.axiom tag_enum.\n\n(*This lemma states that the cardinality of a dependent sum type is equal to the sum of the cardinalities of all the types in the indexed family.*)\nLemma card_tagged :\n #|{: {i : I & T_ i}}| = sumn (map (fun i => #|T_ i|) (enum I)).\n\nEnd TagFinType.\n\nSection SumFinType.\n\nVariables T1 T2 : finType.\n\n(*This definition creates an enumeration for a sum of two finite types by concatenating two sequences: the first contains all elements of the first type injected into the sum, and the second contains all elements of the second type injected into the sum.*)\nDefinition sum_enum :=\n [seq inl _ x | x <- enumF T1] ++ [seq inr _ y | y <- enumF T2].\n\n(*This lemma states that the enumeration for a sum type, constructed by concatenating the injected enumerations of the component types, contains no duplicate elements.*)\nLemma sum_enum_uniq : uniq sum_enum.\n\n(*This lemma states that any given element of a sum type is a member of the constructed enumeration for that sum type.*)\nLemma mem_sum_enum u : u \\in sum_enum.\n\n(*This canonical instance declares that the sum of two finite types is itself a finite type, providing the constructive proof based on the properties of its enumeration.*)\nHB.instance Definition sum_isFinite := isFinite.Build (T1 + T2)%type\n (Finite.uniq_enumP sum_enum_uniq mem_sum_enum).\n\n(*This lemma states that the cardinality of a sum of two finite types is equal to the sum of their individual cardinalities.*)\nLemma card_sum : #|{: T1 + T2}| = #|T1| + #|T2|.", - "boot.finfun": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice.\nFrom mathcomp Require Import fintype tuple.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nSection Def.\n\nVariables (aT : finType) (rT : aT -> Type).\n\n(**)\nInductive finfun_on : seq aT -> Type :=\n(**)\n| finfun_nil : finfun_on [::]\n(**)\n| finfun_cons x s of rT x & finfun_on s : finfun_on (x :: s).\n\n(*This definition describes a recursive function that constructs a data representation of a dependent function over a given sequence of domain elements by applying a provided function to each element.*)\nLocal Fixpoint finfun_rec (g : forall x, rT x) s : finfun_on s :=\n if s is x1 :: s1 then finfun_cons (g x1) (finfun_rec g s1) else finfun_nil.\n\n(*This definition describes a recursive function that retrieves the value associated with a given element from the data representation of a dependent function, provided with evidence that the element belongs to the function's domain.*)\nLocal Fixpoint fun_of_fin_rec x s (f_s : finfun_on s) : x \\in s -> rT x :=\n if f_s is finfun_cons x1 s1 y1 f_s1 then\n if eqP is ReflectT Dx in reflect _ Dxb return Dxb || (x \\in s1) -> rT x then\n fun=> ecast x (rT x) (esym Dx) y1\n else fun_of_fin_rec f_s1\n else fun isF => False_rect (rT x) (notF isF).\n\n(*This definition provides a type for dependent functions with a finite domain, implemented as a data structure storing the function's values for each element of the domain's canonical enumeration.*)\nVariant finfun_of (ph : phant (forall x, rT x)) : predArgType :=\n FinfunOf of finfun_on (enum aT).\n\n(*This definition provides an alias for the type of dependent functions with a finite domain, used for notational or type-checking convenience.*)\nDefinition dfinfun_of ph := finfun_of ph.\n\n(*This definition provides a coercion that allows a data structure representing a finite dependent function to be used as a standard callable function.*)\nDefinition fun_of_fin ph (f : finfun_of ph) x :=\n let: FinfunOf f_aT := f in fun_of_fin_rec f_aT (mem_enum aT x).\n\nEnd Def.\n\nCoercion fun_of_fin : finfun_of >-> Funclass.\nIdentity Coercion unfold_dfinfun_of : dfinfun_of >-> finfun_of.\nArguments fun_of_fin {aT rT ph} f x.\n\n(*This notation provides a syntax for the type of dependent functions over a finite domain, where the argument 'fT' specifies the dependent function's type signature.*)\nNotation \"{ 'ffun' fT }\" := (finfun_of (Phant fT))\n (format \"{ 'ffun' '[hv' fT ']' }\") : type_scope.\n\n(*This notation provides an alternative syntax for the type of dependent functions over a finite domain, where the argument 'fT' specifies the dependent function's type signature.*)\nNotation \"{ 'dffun' fT }\" := (dfinfun_of (Phant fT))\n (format \"{ 'dffun' '[hv' fT ']' }\") : type_scope.\n\n(*This definition creates a finite type of natural numbers strictly less than a given natural number.*)\nDefinition exp_finIndexType n : finType := 'I_n.\n(*This notation represents the type of functions from the finite domain of natural numbers less than a given number to a given type, effectively denoting the type of fixed-length tuples of elements of that type.*)\nNotation \"T ^ n\" :=\n (@finfun_of (exp_finIndexType n) (fun=> T) (Phant _)) : type_scope.\n\nLocal Notation finPi aT rT := (forall x : Finite.sort aT, rT x) (only parsing).\n\n(*This definition provides a constructor to build the data representation of a finite function from a standard Coq function by tabulating its values over the entire finite domain.*)\nHB.lock Definition finfun aT rT g :=\n FinfunOf (Phant (finPi aT rT)) (finfun_rec g (enum aT)).\nCanonical finfun_unlock := Unlockable finfun.unlock.\nArguments finfun {aT rT} g.\n\n(*This notation provides a syntax for creating a dependent function from a finite type, where 'x' is the bound variable and 'E' is the expression defining the function's body.*)\nNotation \"[ 'ffun' x : aT => E ]\" := (finfun (fun x : aT => E))\n (x name) : function_scope.\n\n(*This notation provides a syntax for creating a dependent function where the domain type is inferred, 'x' is the bound variable, and 'E' is the expression defining the function's body.*)\nNotation \"[ 'ffun' x => E ]\" := (@finfun _ (fun=> _) (fun x => E))\n (x name, format \"[ 'ffun' x => E ]\") : function_scope.\n\n(*This notation provides a compact syntax for creating a dependent function where both the domain type and the bound variable are inferred, and 'E' is the expression defining the function's body.*)\nNotation \"[ 'ffun' => E ]\" := [ffun _ => E]\n (format \"[ 'ffun' => E ]\") : function_scope.\n\nUnset Elimination Schemes.\n(*An inductive type for representing finitely branching trees, where each node contains a value indicating its number of children and a function that provides each child subtree.*)\nInductive tree := node n of tree ^ n.\n(*This definition computes the size of a tree, defined as one plus the sum of the sizes of all its children subtrees.*)\nFixpoint size t := let: node n f := t in sumn (codom (size \\o f)) + 1.\n(*This example illustrates the type signature of a step function required for structural induction on trees. It asserts that to prove a property for a parent node, one must show it holds assuming the property is true for all its children.*)\nExample tree_step (K : tree -> Type) :=\n forall n st (t := node st) & forall i : 'I_n, K (st i), K t.\n(*This example illustrates the general recursion principle for trees, stating that a property holds for all trees if it can be proven for a given tree under the assumption that it holds for all its subtrees.*)\nExample tree_rect K (Kstep : tree_step K) : forall t, K t.\n\n(*An inductive type for representing a family of dependently typed trees, where a node in a tree indexed by a natural number has children that are themselves trees indexed by ordinals less than that number.*)\nInductive tri_tree n := tri_row of {ffun forall i : 'I_n, tri_tree i}.\n(*This definition computes the size of a dependently typed tree, defined as one plus the sum of the sizes of all its children subtrees.*)\nFixpoint tri_size n (t : tri_tree n) :=\n let: tri_row f := t in sumn [seq tri_size (f i) | i : 'I_n] + 1.\n(*This example illustrates the type signature of a step function for structural induction on dependently typed trees. It asserts that to prove a property for a parent node indexed by a number, one must show it holds assuming the property is true for all of its children, where each child is a tree of a dependent type.*)\nExample tri_tree_step (K : forall n, tri_tree n -> Type) :=\n forall n st (t := tri_row st) & forall i : 'I_n, K i (st i), K n t.\n(*This example illustrates the general recursion principle for the dependently typed tree type, stating that a property holds for all such trees if it can be proven for a given tree under the assumption that it holds for all its subtrees.*)\nExample tri_tree_rect K (Kstep : tri_tree_step K) : forall n t, K n t.\n\nSet Elimination Schemes.\n \n\nSection DepPlainTheory.\nVariables (aT : finType) (rT : aT -> Type).\n(*This notation is an abbreviation for the type of dependent functions from a given finite type to a dependent type family.*)\nNotation fT := {ffun finPi aT rT}.\nImplicit Type f : fT.\n\n(*This fact asserts the existence of a term representing the empty function, which is a function whose domain is a finite type with zero elements.*)\nFact ffun0 (aT0 : #|aT| = 0) : fT.\n\n(*This lemma states that applying a finite function, constructed from a given standard function, to an argument yields the same result as applying the original standard function to that argument.*)\nLemma ffunE g x : (finfun g : fT) x = g x.\n\n(*This lemma states that two finite functions are equal if and only if they are extensionally equal, meaning they produce the same output for every input in their common domain.*)\nLemma ffunP (f1 f2 : fT) : (forall x, f1 x = f2 x) <-> f1 = f2.\n\n(*This lemma states that converting a standard function into its finite function representation and then converting it back yields the original function.*)\nLemma ffunK : @cancel (finPi aT rT) fT fun_of_fin finfun.\n\n(*This lemma states that if two functions are pointwise equal over a finite domain, then their corresponding finite function representations are also equal.*)\nLemma eq_dffun (g1 g2 : forall x, rT x) :\n (forall x, g1 x = g2 x) -> finfun g1 = finfun g2.\n\n(*This definition applies a dependent function to an argument and packages the result into a dependent pair, which includes both the value and its specific type from the codomain family.*)\nDefinition total_fun g x := Tagged rT (g x : rT x).\n\n(*This definition constructs the graph of a dependent finite function as a tuple of its outputs, where each output is represented as a dependent pair containing both the value and its type.*)\nDefinition tfgraph f := codom_tuple (total_fun f).\n\n(*This lemma states that the sequence of outputs generated by applying a dependent function across its domain is identical to the function's graph represented as a tuple of dependent pairs.*)\nLemma codom_tffun f : codom (total_fun f) = tfgraph f. \n\n(*This definition constructs the inverse of the graph operation for dependent functions, attempting to reconstruct a dependent finite function from a given tuple of dependent pairs. The operation may fail, in which case it returns no value.*)\nLocal Definition tfgraph_inv (G : #|aT|.-tuple {x : aT & rT x}) : option fT :=\n if eqfunP isn't ReflectT Dtg then None else\n Some [ffun x => ecast x (rT x) (Dtg x) (tagged (tnth G (enum_rank x)))].\n\n(*This lemma states that composing the graph-to-function conversion with the function-to-graph conversion acts as a cancellative operation, meaning applying them in sequence restores the original dependent finite function.*)\nLocal Lemma tfgraphK : pcancel tfgraph tfgraph_inv.\n\n(*This lemma states that the operation that computes the graph of a dependent finite function is injective, which means that two distinct functions will always produce distinct graphs.*)\nLemma tfgraph_inj : injective tfgraph. \n\n(*This definition specifies a predicate on dependent finite functions, which holds for a function if for every input, the function's output is an element of a corresponding specified set from a family of sets.*)\nDefinition family_mem mF := [pred f : fT | [forall x, in_mem (f x) (mF x)]].\n\nVariables (pT : forall x, predType (rT x)) (F : forall x, pT x).\n\n(*This definition provides a shorthand for obtaining the membership test for a specific predicate from a family of predicates indexed by elements of a finite type.*)\nLocal Definition fmem F x := mem (F x : pT x).\n\n(*This lemma establishes a logical equivalence, showing that a dependent finite function belongs to a family predicate if and only if for every input, the function's output satisfies the corresponding individual predicate in the family.*)\nLemma familyP f : reflect (forall x, f x \\in F x) (f \\in family_mem (fmem F)).\n\nEnd DepPlainTheory.\n\nArguments ffunK {aT rT} f : rename.\nArguments ffun0 {aT rT} aT0.\nArguments eq_dffun {aT rT} [g1] g2 eq_g12.\nArguments total_fun {aT rT} g x.\nArguments tfgraph {aT rT} f.\nArguments tfgraphK {aT rT} f : rename.\nArguments tfgraph_inj {aT rT} [f1 f2] : rename.\n\nArguments fmem {aT rT pT} F x /.\nArguments familyP {aT rT pT F f}.\nNotation family F := (family_mem (fmem F)).\n\nSection InheritedStructures.\n\nVariable aT : finType.\nNotation dffun_aT rT rS := {dffun forall x : aT, rT x : rS}.\n\n#[hnf] HB.instance Definition _ rT := Equality.copy (dffun_aT rT eqType)\n (pcan_type tfgraphK).\n#[hnf] HB.instance Definition _ (rT : eqType) :=\n Equality.copy {ffun aT -> rT} {dffun forall _, rT}.\n\n#[hnf] HB.instance Definition _ rT := Choice.copy (dffun_aT rT choiceType)\n (pcan_type tfgraphK).\n#[hnf] HB.instance Definition _ (rT : choiceType) :=\n Choice.copy {ffun aT -> rT} {dffun forall _, rT}.\n\n#[hnf] HB.instance Definition _ rT := Countable.copy (dffun_aT rT countType)\n (pcan_type tfgraphK).\n#[hnf] HB.instance Definition _ (rT : countType) :=\n Countable.copy {ffun aT -> rT} {dffun forall _, rT}.\n\n#[hnf] HB.instance Definition _ rT := Finite.copy (dffun_aT rT finType)\n (pcan_type tfgraphK).\n(*This definition converts a finite function, defined over a domain of a specific natural number size, into a tuple containing the function's output values.*)\nDefinition tuple_of_finfun (f : T ^ n) : n.-tuple T := [tuple f i | i < n].\n\n(*This definition converts a tuple of a specific length into a finite function, where the function's output for a given index is the element at that same index in the tuple.*)\nDefinition finfun_of_tuple (t : n.-tuple T) : (T ^ n) := [ffun i => tnth t i].\n\n(*This lemma states that converting a tuple to a finite function and then back to a tuple yields the original tuple.*)\nLemma finfun_of_tupleK : cancel finfun_of_tuple tuple_of_finfun.\n\n(*This lemma states that converting a finite function to a tuple and then back to a finite function yields the original function.*)\nLemma tuple_of_finfunK : cancel tuple_of_finfun finfun_of_tuple.\n\nEnd FinFunTuple.\n\nSection FunPlainTheory.\n\nVariables (aT : finType) (rT : Type).\n(*This notation defines `fT` as a shorthand for the type of non-dependent finite functions from a given finite domain type to a given codomain type.*)\nNotation fT := {ffun aT -> rT}.\nImplicit Types (f : fT) (R : pred rT).\n\n(*This definition computes the graph of a finite function as a tuple composed of all its output values, ordered according to the enumeration of the function's domain.*)\nDefinition fgraph f := codom_tuple f.\n\n(*This definition constructs a finite function from a tuple of values, where the function's output for a given input is determined by looking up the value in the tuple at the index corresponding to the input's rank in the domain's enumeration.*)\nDefinition Finfun (G : #|aT|.-tuple rT) := [ffun x => tnth G (enum_rank x)].\n\n(*This lemma states that accessing the element at a specific index in the graph of a finite function is equivalent to applying the function to the domain element that corresponds to that index.*)\nLemma tnth_fgraph f i : tnth (fgraph f) i = f (enum_val i).\n\n(*This lemma states that constructing a finite function from its own graph results in the original function.*)\nLemma FinfunK : cancel Finfun fgraph.\n\n(*This lemma states that computing the graph of a finite function that was constructed from a tuple results in the original tuple.*)\nLemma fgraphK : cancel fgraph Finfun.\n\n(*This lemma states that the graph of a constant-valued function is represented as an empty sequence.*)\nLemma fgraph_ffun0 aT0 : fgraph (ffun0 aT0) = nil :> seq rT.\n\n(*This lemma states that the sequence of output values of a finite function, ordered by the domain enumeration, is identical to the function's graph.*)\nLemma codom_ffun f : codom f = fgraph f. \n\n(*This lemma establishes an equality that relates the graph of a function as a tuple of dependent pairs to the graph of the same function as a tuple of simple values, through a mapping of a tagging function.*)\nLemma tagged_tfgraph f : @map _ rT tagged (tfgraph f) = fgraph f.\n\n(*This lemma states that if two underlying Coq functions are extensionally equal, meaning they produce the same output for every input, then their representations as finite function structures are also equal.*)\nLemma eq_ffun (g1 g2 : aT -> rT) : g1 =1 g2 -> finfun g1 = finfun g2.\n\n(*This lemma asserts that the graph of a finite function is definitionally equal to the tuple formed by its output values.*)\nLemma fgraph_codom f : fgraph f = codom_tuple f.\n\n(*This definition creates a predicate over finite functions that is satisfied if and only if all output values of a function belong to a given set.*)\nDefinition ffun_on_mem (mR : mem_pred rT) := family_mem (fun _ : aT => mR).\n\n(*This lemma establishes a logical equivalence, showing that a finite function is a member of a predicate set if and only if all of its output values are contained within the corresponding base set.*)\nLemma ffun_onP R f : reflect (forall x, f x \\in R) (f \\in ffun_on_mem (mem R)).\n\nEnd FunPlainTheory.\n\nArguments Finfun {aT rT} G.\nArguments fgraph {aT rT} f.\nArguments FinfunK {aT rT} G : rename.\nArguments fgraphK {aT rT} f : rename.\nArguments eq_ffun {aT rT} [g1] g2 eq_g12.\nArguments ffun_onP {aT rT R f}.\n\nNotation ffun_on R := (ffun_on_mem _ (mem R)).\n(*This notation defines a predicate asserting that a finite function from a given source type to a target type has its image entirely contained within a specified subset of the target type.*)\nNotation \"@ 'ffun_on' aT R\" :=\n (ffun_on R : simpl_pred (finfun_of (Phant (aT -> id _))))\n (at level 10, aT, R at level 9).\n\n(*This lemma states that for a finite function defined on a finite range of natural numbers, retrieving the element at a specific index from the sequence representing its graph is equivalent to applying the function to that same index.*)\nLemma nth_fgraph_ord T n (x0 : T) (i : 'I_n) f : nth x0 (fgraph f) i = f i.\n\nSection Support.\n\nVariables (aT : Type) (rT : eqType).\n\n(*This definition specifies the support of a function with respect to a given value as the set of all inputs for which the function's output is not equal to that value.*)\nDefinition support_for y (f : aT -> rT) := [pred x | f x != y].\n\n(*This lemma provides an equivalence, stating that an element belongs to the support of a function with respect to a given value if and only if the function's output for that element is not equal to the given value.*)\nLemma supportE x y f : (x \\in support_for y f) = (f x != y). \n\nEnd Support.\n\n(*This notation provides a concise syntax for defining the support of a function relative to a specific value.*)\nNotation \"y .-support\" := (support_for y)\n (at level 2, format \"y .-support\") : function_scope.\n\nSection EqTheory.\n\nVariables (aT : finType) (rT : eqType).\n(*This notation defines `fT` as a shorthand for the type of non-dependent finite functions from a given finite domain type to a given codomain type.*)\nNotation fT := {ffun aT -> rT}.\nImplicit Types (y : rT) (D : {pred aT}) (R : {pred rT}) (f : fT).\n\n(*This lemma establishes an equivalence: the support of a function relative to a given value is a subset of a given domain if and only if the function maps every element outside that domain to the given value.*)\nLemma supportP y D g :\n reflect (forall x, x \\notin D -> g x = y) (y.-support g \\subset D).\n\n(*This definition constructs a set of functions that satisfy a family of predicates on a specified domain. For any input within the given domain, the function's output must satisfy the corresponding predicate from the family. For any input outside the domain, the function's output must be equal to a specified default value.*)\nDefinition pfamily_mem y mD (mF : aT -> mem_pred rT) :=\n family (fun i : aT => if in_mem i mD then pred_of_simpl (mF i) else pred1 y).\n\n(*This lemma establishes an equivalence, stating that a function belongs to a partial family of predicates defined on a domain if and only if two conditions are met: first, the support of the function relative to a default value is a subset of the domain, and second, for every element within that domain, the function's output satisfies the corresponding predicate from the family.*)\nLemma pfamilyP (pT : predType rT) y D (F : aT -> pT) f :\n reflect (y.-support f \\subset D /\\ {in D, forall x, f x \\in F x})\n (f \\in pfamily_mem y (mem D) (fmem F)).\n\n(*This definition creates a set of functions that are constrained on a specific domain. For inputs within the given domain, the function's output must belong to a specified target set. For inputs outside the domain, the function's output must be equal to a specified default value.*)\nDefinition pffun_on_mem y mD mR := pfamily_mem y mD (fun _ => mR).\n\n(*This lemma provides an equivalence, stating that a function belongs to a set of partially constrained functions if and only if two conditions hold: first, the support of the function relative to a default value is a subset of the specified domain, and second, the image of that domain under the function is a subset of the specified target set.*)\nLemma pffun_onP y D R f :\n reflect (y.-support f \\subset D /\\ {subset image f D <= R})\n (f \\in pffun_on_mem y (mem D) (mem R)).\n\nEnd EqTheory.\n\nArguments supportP {aT rT y D g}.\nArguments pfamilyP {aT rT pT y D F f}.\nArguments pffun_onP {aT rT y D R f}.\n\nNotation pfamily y D F := (pfamily_mem y (mem D) (fmem F)).\nNotation pffun_on y D R := (pffun_on_mem y (mem D) (mem R)).\n\nSection FinDepTheory.\n\nVariables (aT : finType) (rT : aT -> finType).\n(*A notation for the type of all functions mapping elements from a finite domain type to a finite codomain type.*)\nNotation fT := {dffun forall x : aT, rT x}.\n\n(*This lemma states that the total number of dependent functions satisfying a given family of predicates is calculated by multiplying the number of valid output values for each input value in the domain. A valid output value is one that satisfies the predicate associated with that specific input.*)\nLemma card_family (F : forall x, pred (rT x)) :\n #|(family F : simpl_pred fT)| = foldr muln 1 [seq #|F x| | x : aT].\n\n(*This lemma states that the total number of dependent functions from a finite domain type to a family of finite codomain types is equal to the product of the sizes of each codomain type, taken over all elements of the domain.*)\nLemma card_dep_ffun : #|fT| = foldr muln 1 [seq #|rT x| | x : aT].\n\nEnd FinDepTheory.\n\nSection FinFunTheory.\n\nVariables aT rT : finType.\n(*This is a notation for the type of finite functions from a given finite domain type to a specified codomain type.*)\nNotation fT := {ffun aT -> rT}.\nImplicit Types (D : {pred aT}) (R : {pred rT}) (F : aT -> pred rT).\n\n(*This lemma states that the cardinality of a dependent product over a subset of a type is equal to the product of the cardinalities of the component types indexed by the elements of that subset.*)\nLemma card_pfamily y0 D F :\n #|pfamily y0 D F| = foldr muln 1 [seq #|F x| | x in D].\n\n(*This lemma states that the cardinality of the type of finite functions from a given subset of a domain type to a codomain type is equal to the cardinality of the codomain raised to the power of the cardinality of the subset.*)\nLemma card_pffun_on y0 D R : #|pffun_on y0 D R| = #|R| ^ #|D|.\n\n(*This lemma states that the cardinality of the type of finite functions from a domain type to a codomain type is equal to the cardinality of the codomain raised to the power of the cardinality of the domain.*)\nLemma card_ffun_on R : #|@ffun_on aT R| = #|R| ^ #|aT|.\n\n(*This lemma states that the cardinality of the type of finite functions between two finite types is equal to the cardinality of the codomain type raised to the power of the cardinality of the domain type.*)\nLemma card_ffun : #|fT| = #|rT| ^ #|aT|.\n\nEnd FinFunTheory.\n\nSection DependentFiniteProduct.\n\nVariables (I : finType) (T_ : I -> finType).\n(*This notation defines 'fprod_type' as a dependent function type, representing functions that map each element of a finite index type to an element of a corresponding type from a given family of types.*)\nNotation fprod_type := (forall i : I, T_ i) (only parsing).\n\n(*This record defines a dependent product of a family of finite types, bundling a function with a proof that its output at each index belongs to the correct type within the family.*)\nRecord fprod : predArgType := FProd\n { fprod_fun : {ffun I -> {i : I & T_ i}} ;\n fprod_prop : [forall i : I, tag (fprod_fun i) == i] }.\n\n(*This lemma states that for any element of a dependent product and any index, the tag associated with the value at that index is equal to the index itself.*)\nLemma tag_fprod_fun (f : fprod) i : tag (fprod_fun f i) = i.\n\n(*This definition provides a function that converts an element of the dependent product record type into a standard dependent function by extracting the underlying values.*)\nDefinition fun_of_fprod (f : fprod) : fprod_type :=\n fun i => etagged ('forall_eqP (fprod_prop f) i).\nCoercion fun_of_fprod : fprod >-> Funclass.\n\n#[hnf] HB.instance Definition _ := [isSub for fprod_fun].\n(*This lemma provides the proof component required to construct a dependent product record from a standard dependent function, asserting that for any index, the tag of the newly-created tagged value correctly corresponds to that index.*)\nLemma fprod_of_prod_type_subproof (f : fprod_type) :\n [forall i : I, tag ([ffun i => Tagged T_ (f i)] i) == i].\n\n(*This definition provides a function that converts a standard dependent function into an element of the dependent product record type by packaging the function with the necessary proof of its type correctness.*)\nDefinition fprod_of_fun (f : fprod_type) : fprod :=\n FProd (fprod_of_prod_type_subproof f).\n\n(*This lemma states that converting a standard dependent function to a dependent product record and then back to a standard dependent function results in the original function.*)\nLemma fprodK : cancel fun_of_fprod fprod_of_fun.\n\n(*This lemma states that converting a dependent function into a dependent product record and then applying the resulting record as a function to an index yields the same value as applying the original function to that index.*)\nLemma fprodE g i : fprod_of_fun g i = g i.\n\n(*This lemma establishes function extensionality for the dependent product record type, stating that two such records are equal if and only if their underlying functions produce equal outputs for all inputs in the index type.*)\nLemma fprodP (f1 f2 : fprod) : (forall x, f1 x = f2 x) <-> f1 = f2.\n\n(*This definition provides a function to convert an element from the dependent product record type to the canonical dependent finite function type.*)\nDefinition dffun_of_fprod (f : fprod) : {dffun forall i : I, T_ i} :=\n [ffun x => f x].\n\n(*This definition provides a function to convert an element from the canonical dependent finite function type to the dependent product record type.*)\nDefinition fprod_of_dffun (f : {dffun forall i : I, T_ i}) : fprod :=\n fprod_of_fun f.\n\n(*This lemma states that converting a dependent finite function to a dependent product record and then back to a dependent finite function results in the original function.*)\nLemma dffun_of_fprodK : cancel dffun_of_fprod fprod_of_dffun.\n\n#[local] Hint Resolve dffun_of_fprodK : core.\n\n(*This lemma states that converting a dependent product record to a dependent finite function and then back to a record results in the original record.*)\nLemma fprod_of_dffunK : cancel fprod_of_dffun dffun_of_fprod.\n\n#[local] Hint Resolve fprod_of_dffunK : core.\n\n(*This lemma states that the conversion from the dependent product record type to the canonical dependent finite function type is a bijective mapping.*)\nLemma dffun_of_fprod_bij : bijective dffun_of_fprod.\n\n(*This lemma states that the conversion from the canonical dependent finite function type to the dependent product record type is a bijective mapping.*)\nLemma fprod_of_dffun_bij : bijective fprod_of_dffun.\n\n(*This definition provides a function to convert a dependent product record into an element of a dependent family of tagged types, which is an alternative representation of a dependent product.*)\nDefinition to_family_tagged_with (f : fprod) : {x in family (tagged_with T_)} :=\n exist _ (fprod_fun f) (fprod_prop f).\n\n(*This definition provides a function to convert an element from a dependent family of tagged types back into a dependent product record.*)\nDefinition of_family_tagged_with (f : {x in family (tagged_with T_)}) : fprod :=\n FProd (valP f).\n\n(*This lemma states that converting an element from a dependent family of tagged types to a dependent product record and then back again results in the original dependent family element.*)\nLemma to_family_tagged_withK :\n cancel to_family_tagged_with of_family_tagged_with.\n\n#[local] Hint Resolve to_family_tagged_withK : core.\n\n(*This lemma states that converting a dependent product record to an element of a dependent family of tagged types and then back again results in the original record.*)\nLemma of_family_tagged_withK :\n cancel of_family_tagged_with to_family_tagged_with.\n\n#[local] Hint Resolve of_family_tagged_withK : core.\n\n(*This lemma states that the conversion from a dependent product record to an element of a dependent family of tagged types is a bijective mapping.*)\nLemma to_family_tagged_with_bij : bijective to_family_tagged_with.\n\n(*This lemma states that the conversion from an element of a dependent family of tagged types to a dependent product record is a bijective mapping.*)\nLemma of_family_tagged_with_bij : bijective of_family_tagged_with.\n\n(*This lemma states that for an element of a dependent product record, unwrapping a tagged value at a given index using a proof of its tag's correctness yields the same result as directly applying the coerced dependent function to that index.*)\nLemma etaggedE (a : fprod) (i : I) (e : tag (fprod_fun a i) = i) :\n etagged e = a i.\n\nEnd DependentFiniteProduct.\n\nArguments to_family_tagged_with {I T_}.\nArguments of_family_tagged_with {I T_}.\n\n(*This notation provides syntax to construct an element of the dependent product record type from a function defined with an explicit index variable and its type.*)\nNotation \"[ 'fprod' i : I => F ]\" := (fprod_of_fun (fun i : I => F))\n (i name, only parsing) : function_scope.\n\n(*This notation provides syntax to construct an element of the dependent product record type from a function that produces a constant value for all inputs from a given index type.*)\nNotation \"[ 'fprod' : I => F ]\" := (fprod_of_fun (fun _ : I => F))\n (only parsing) : function_scope.\n\n(*This notation provides a more concise syntax to construct an element of the dependent product record type from a function, where the type of the index variable is inferred automatically.*)\nNotation \"[ 'fprod' i => F ]\" := [fprod i : _ => F]\n (i name, format \"[ 'fprod' i => F ]\") : function_scope.\n\n(*A notation that computes the finite product, such as the iterated meet or join, of all elements in a given sequence from an ordered type. The choice between meet, join, or another similar operation is determined by the display context.*)\nNotation \"[ 'fprod' => F ]\" := [fprod : _ => F]", - "order.all_order": "", - "order.order": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat choice seq.\nFrom mathcomp Require Import path fintype tuple bigop finset div prime finfun.\nFrom mathcomp Require Import finset.\nFrom mathcomp Require Export preorder.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope order_scope.\n\nDelimit Scope order_scope with O.\nLocal Open Scope order_scope.\n\nReserved Notation \"A `&` B\" (at level 48, left associativity).\nReserved Notation \"A `|` B\" (at level 52, left associativity).\nReserved Notation \"A `\\` B\" (at level 50, left associativity).\nReserved Notation \"~` A\" (at level 35, right associativity).\n\nReserved Notation \"A `&^d` B\" (at level 48, left associativity).\nReserved Notation \"A `|^d` B\" (at level 52, left associativity).\nReserved Notation \"A `\\^d` B\" (at level 50, left associativity).\nReserved Notation \"~^d` A\" (at level 35, right associativity).\n\nReserved Notation \"A `&^p` B\" (at level 48, left associativity).\nReserved Notation \"A `|^p` B\" (at level 52, left associativity).\nReserved Notation \"A `\\^p` B\" (at level 50, left associativity).\nReserved Notation \"~^p` A\" (at level 35, right associativity).\n\nReserved Notation \"A `&^sp` B\" (at level 48, left associativity).\nReserved Notation \"A `|^sp` B\" (at level 52, left associativity).\nReserved Notation \"A `\\^sp` B\" (at level 50, left associativity).\nReserved Notation \"~^sp` A\" (at level 35, right associativity).\n\nReserved Notation \"A `&^l` B\" (at level 48, left associativity).\nReserved Notation \"A `|^l` B\" (at level 52, left associativity).\nReserved Notation \"A `\\^l` B\" (at level 50, left associativity).\nReserved Notation \"~^l` A\" (at level 35, right associativity).\n\nReserved Notation \"A `&^sl` B\" (at level 48, left associativity).\nReserved Notation \"A `|^sl` B\" (at level 52, left associativity).\nReserved Notation \"A `\\^sl` B\" (at level 50, left associativity).\nReserved Notation \"~^sl` A\" (at level 35, right associativity).\n\nReserved Notation \"\\gcd_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\gcd_ i '/ ' F ']'\").\nReserved Notation \"\\gcd_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\gcd_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\gcd_ ( i <- r ) F\"\n (F at level 41,\n format \"'[' \\gcd_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\gcd_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\gcd_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\gcd_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\gcd_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\gcd_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\gcd_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\gcd_ ( i : t | P ) F\"\n (F at level 41).\nReserved Notation \"\\gcd_ ( i : t ) F\"\n (F at level 41).\nReserved Notation \"\\gcd_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\gcd_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\gcd_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\gcd_ ( i < n ) F ']'\").\nReserved Notation \"\\gcd_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\gcd_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\gcd_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\gcd_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\lcm_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\lcm_ i '/ ' F ']'\").\nReserved Notation \"\\lcm_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\lcm_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\lcm_ ( i <- r ) F\"\n (F at level 41,\n format \"'[' \\lcm_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\lcm_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\lcm_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\lcm_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\lcm_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\lcm_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\lcm_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\lcm_ ( i : t | P ) F\"\n (F at level 41).\nReserved Notation \"\\lcm_ ( i : t ) F\"\n (F at level 41).\nReserved Notation \"\\lcm_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\lcm_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\lcm_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\lcm_ ( i < n ) F ']'\").\nReserved Notation \"\\lcm_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\lcm_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\lcm_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\lcm_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\meet_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\meet_ i '/ ' F ']'\").\nReserved Notation \"\\meet_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\meet_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\meet_ ( i <- r ) F\"\n (F at level 41, r at level 50,\n format \"'[' \\meet_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\meet_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\meet_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\meet_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\meet_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\meet_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\meet_ ( i : t | P ) F\"\n (F at level 41).\nReserved Notation \"\\meet_ ( i : t ) F\"\n (F at level 41).\nReserved Notation \"\\meet_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\meet_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\meet_ ( i < n ) F ']'\").\nReserved Notation \"\\meet_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\meet_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\meet_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\meet_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\join_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\join_ i '/ ' F ']'\").\nReserved Notation \"\\join_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\join_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\join_ ( i <- r ) F\"\n (F at level 41, r at level 50,\n format \"'[' \\join_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\join_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\join_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\join_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\join_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\join_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\join_ ( i : t | P ) F\"\n (F at level 41).\nReserved Notation \"\\join_ ( i : t ) F\"\n (F at level 41).\nReserved Notation \"\\join_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\join_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\join_ ( i < n ) F ']'\").\nReserved Notation \"\\join_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\join_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\join_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\join_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\meet^d_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\meet^d_ i '/ ' F ']'\").\nReserved Notation \"\\meet^d_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\meet^d_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^d_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\meet^d_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\meet^d_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\meet^d_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^d_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\meet^d_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\meet^d_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\meet^d_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^d_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\meet^d_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\meet^d_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\meet^d_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^d_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\meet^d_ ( i < n ) F ']'\").\nReserved Notation \"\\meet^d_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\meet^d_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^d_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\meet^d_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\join^d_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\join^d_ i '/ ' F ']'\").\nReserved Notation \"\\join^d_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\join^d_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\join^d_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\join^d_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\join^d_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\join^d_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join^d_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\join^d_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\join^d_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\join^d_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\join^d_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\join^d_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\join^d_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\join^d_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join^d_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\join^d_ ( i < n ) F ']'\").\nReserved Notation \"\\join^d_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\join^d_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\join^d_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\join^d_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\meet^p_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\meet^p_ i '/ ' F ']'\").\nReserved Notation \"\\meet^p_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\meet^p_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^p_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\meet^p_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\meet^p_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\meet^p_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^p_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\meet^p_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\meet^p_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\meet^p_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^p_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\meet^p_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\meet^p_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\meet^p_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^p_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\meet^p_ ( i < n ) F ']'\").\nReserved Notation \"\\meet^p_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\meet^p_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^p_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\meet^p_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\join^p_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\join^p_ i '/ ' F ']'\").\nReserved Notation \"\\join^p_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\join^p_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\join^p_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\join^p_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\join^p_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\join^p_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join^p_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\join^p_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\join^p_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\join^p_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\join^p_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\join^p_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\join^p_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\join^p_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join^p_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\join^p_ ( i < n ) F ']'\").\nReserved Notation \"\\join^p_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\join^p_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\join^p_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\join^p_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\min^p_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\min^p_ i '/ ' F ']'\").\nReserved Notation \"\\min^p_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\min^p_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\min^p_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\min^p_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\min^p_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\min^p_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min^p_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\min^p_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\min^p_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\min^p_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\min^p_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\min^p_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\min^p_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\min^p_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min^p_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\min^p_ ( i < n ) F ']'\").\nReserved Notation \"\\min^p_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\min^p_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\min^p_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\min^p_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\max^p_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\max^p_ i '/ ' F ']'\").\nReserved Notation \"\\max^p_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\max^p_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\max^p_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\max^p_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\max^p_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\max^p_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max^p_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\max^p_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\max^p_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\max^p_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\max^p_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\max^p_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\max^p_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\max^p_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max^p_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\max^p_ ( i < n ) F ']'\").\nReserved Notation \"\\max^p_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\max^p_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\max^p_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\max^p_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\meet^sp_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\meet^sp_ i '/ ' F ']'\").\nReserved Notation \"\\meet^sp_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\meet^sp_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^sp_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\meet^sp_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\meet^sp_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\meet^sp_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^sp_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\meet^sp_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\meet^sp_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\meet^sp_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^sp_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\meet^sp_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\meet^sp_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\meet^sp_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^sp_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\meet^sp_ ( i < n ) F ']'\").\nReserved Notation \"\\meet^sp_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\meet^sp_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^sp_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\meet^sp_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\join^sp_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\join^sp_ i '/ ' F ']'\").\nReserved Notation \"\\join^sp_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\join^sp_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\join^sp_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\join^sp_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\join^sp_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\join^sp_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join^sp_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\join^sp_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\join^sp_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\join^sp_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\join^sp_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\join^sp_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\join^sp_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\join^sp_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join^sp_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\join^sp_ ( i < n ) F ']'\").\nReserved Notation \"\\join^sp_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\join^sp_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\join^sp_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\join^sp_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\min^sp_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\min^sp_ i '/ ' F ']'\").\nReserved Notation \"\\min^sp_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\min^sp_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\min^sp_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\min^sp_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\min^sp_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\min^sp_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min^sp_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\min^sp_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\min^sp_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\min^sp_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\min^sp_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\min^sp_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\min^sp_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\min^sp_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min^sp_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\min^sp_ ( i < n ) F ']'\").\nReserved Notation \"\\min^sp_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\min^sp_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\min^sp_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\min^sp_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\max^sp_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\max^sp_ i '/ ' F ']'\").\nReserved Notation \"\\max^sp_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\max^sp_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\max^sp_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\max^sp_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\max^sp_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\max^sp_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max^sp_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\max^sp_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\max^sp_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\max^sp_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\max^sp_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\max^sp_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\max^sp_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\max^sp_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max^sp_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\max^sp_ ( i < n ) F ']'\").\nReserved Notation \"\\max^sp_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\max^sp_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\max^sp_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\max^sp_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\meet^l_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\meet^l_ i '/ ' F ']'\").\nReserved Notation \"\\meet^l_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\meet^l_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^l_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\meet^l_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\meet^l_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\meet^l_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^l_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\meet^l_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\meet^l_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\meet^l_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^l_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\meet^l_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\meet^l_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\meet^l_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^l_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\meet^l_ ( i < n ) F ']'\").\nReserved Notation \"\\meet^l_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\meet^l_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\meet^l_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\meet^l_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\join^l_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\join^l_ i '/ ' F ']'\").\nReserved Notation \"\\join^l_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\join^l_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\join^l_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\join^l_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\join^l_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\join^l_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join^l_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\join^l_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\join^l_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\join^l_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\join^l_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\join^l_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\join^l_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\join^l_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\join^l_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\join^l_ ( i < n ) F ']'\").\nReserved Notation \"\\join^l_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\join^l_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\join^l_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\join^l_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\min^l_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\min^l_ i '/ ' F ']'\").\nReserved Notation \"\\min^l_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\min^l_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\min^l_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\min^l_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\min^l_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\min^l_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min^l_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\min^l_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\min^l_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\min^l_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\min^l_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\min^l_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\min^l_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\min^l_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min^l_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\min^l_ ( i < n ) F ']'\").\nReserved Notation \"\\min^l_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\min^l_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\min^l_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\min^l_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\max^l_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\max^l_ i '/ ' F ']'\").\nReserved Notation \"\\max^l_ ( i <- r | P ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\max^l_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\max^l_ ( i <- r ) F\"\n (at level 41, F at level 41, i, r at level 50,\n format \"'[' \\max^l_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\max^l_ ( m <= i < n | P ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\max^l_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max^l_ ( m <= i < n ) F\"\n (at level 41, F at level 41, i, m, n at level 50,\n format \"'[' \\max^l_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\max^l_ ( i | P ) F\"\n (at level 41, F at level 41, i at level 50,\n format \"'[' \\max^l_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\max^l_ ( i : t | P ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\max^l_ ( i : t ) F\"\n (at level 41, F at level 41, i at level 50).\nReserved Notation \"\\max^l_ ( i < n | P ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\max^l_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max^l_ ( i < n ) F\"\n (at level 41, F at level 41, i, n at level 50,\n format \"'[' \\max^l_ ( i < n ) F ']'\").\nReserved Notation \"\\max^l_ ( i 'in' A | P ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\max^l_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\max^l_ ( i 'in' A ) F\"\n (at level 41, F at level 41, i, A at level 50,\n format \"'[' \\max^l_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"'{' 'omorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'omorphism' U -> V }\").\nReserved Notation \"'{' 'mlmorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'mlmorphism' U -> V }\").\nReserved Notation \"'{' 'jlmorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'jlmorphism' U -> V }\").\nReserved Notation \"'{' 'lmorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'lmorphism' U -> V }\").\nReserved Notation \"'{' 'blmorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'blmorphism' U -> V }\").\nReserved Notation \"'{' 'tlmorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'tlmorphism' U -> V }\").\nReserved Notation \"'{' 'tblmorphism' U '->' V '}'\"\n (U at level 98, V at level 99, format \"{ 'tblmorphism' U -> V }\").\n\nModule Order.\n\nExport Order.\n\n#[key=\"T\", primitive]\n(*This record defines the property of antisymmetry for a preorder, which asserts that if an element is less than or equal to another and vice versa, then the two elements must be equal. This property holds for both the primary order relation and its dual, effectively turning the preorder into a partial order.*)\nHB.mixin Record Preorder_isDuallyPOrder (d : disp_t) T of Preorder d T := {\n le_anti : antisymmetric (@le d T);\n ge_anti : antisymmetric (fun x y => @le d T y x);\n}.\n\n#[short(type=\"porderType\")]\n(*This definition describes a type equipped with a partial order relation, which is a binary relation that is reflexive, transitive, and antisymmetric.*)\nHB.structure Definition POrder (d : disp_t) :=\n { T of Preorder d T & Preorder_isDuallyPOrder d T }.\n\n#[short(type=\"bPOrderType\")]\n(*This definition describes a type that has a partial order and is equipped with a bottom element, which is the unique least element under that order.*)\nHB.structure Definition BPOrder d := { T of hasBottom d T & POrder d T }.\n#[short(type=\"tPOrderType\")]\n(*This definition describes a type that has a partial order and is equipped with a top element, which is the unique greatest element under that order.*)\nHB.structure Definition TPOrder d := { T of hasTop d T & POrder d T }.\n#[short(type=\"tbPOrderType\")]\n(*This definition describes a type that has a partial order and is equipped with both a top element, which is the greatest, and a bottom element, which is the least.*)\nHB.structure Definition TBPOrder d := { T of hasTop d T & BPOrder d T }.\n\nModule POrderExports.\nArguments le_trans {d s} [_ _ _].\nEnd POrderExports.\nHB.export POrderExports.\n\n#[key=\"T\", primitive]\n(*This record defines the structure of a meet-semilattice on a partially ordered type. It introduces a binary meet operation, representing the greatest lower bound of two elements. The defining property is that an element is less than or equal to the meet of two others if and only if it is less than or equal to each of them individually.*)\nHB.mixin Record POrder_isMeetSemilattice d (T : Type) of POrder d T := {\n meet : T -> T -> T;\n lexI : forall x y z, (x <= meet y z) = (x <= y) && (x <= z);\n}.\n\n#[key=\"T\", primitive]\n(*This record defines the structure of a join-semilattice on a partially ordered type. It introduces a binary join operation, representing the least upper bound of two elements. The defining property is that the join of two elements is less than or equal to a third element if and only if both original elements are individually less than or equal to the third one.*)\nHB.mixin Record POrder_isJoinSemilattice d T of POrder d T := {\n join : T -> T -> T;\n leUx : forall x y z, (join x y <= z) = (x <= z) && (y <= z);\n}.\n\n#[short(type=\"meetSemilatticeType\")]\n(*This definition describes a type that is a meet-semilattice, which is a partially ordered set where every pair of elements has a greatest lower bound, also known as a meet.*)\nHB.structure Definition MeetSemilattice d :=\n { T of POrder d T & POrder_isMeetSemilattice d T }.\n\n#[short(type=\"bMeetSemilatticeType\")]\n(*This definition describes a meet-semilattice that also has a bottom element, which is the least element in the set.*)\nHB.structure Definition BMeetSemilattice d :=\n { T of MeetSemilattice d T & hasBottom d T }.\n\n#[short(type=\"tMeetSemilatticeType\")]\n(*This definition describes a meet-semilattice that also has a top element, which is the greatest element in the set and acts as an identity for the meet operation.*)\nHB.structure Definition TMeetSemilattice d :=\n { T of MeetSemilattice d T & hasTop d T }.\n\n#[short(type=\"tbMeetSemilatticeType\")]\n(*This definition describes a meet-semilattice that has both a top element, which is the greatest element, and a bottom element, which is the least element.*)\nHB.structure Definition TBMeetSemilattice d :=\n { T of BMeetSemilattice d T & hasTop d T }.\n\n#[short(type=\"joinSemilatticeType\")]\n(*This definition describes a type that is a join-semilattice, which is a partially ordered set where every pair of elements has a least upper bound, also known as a join.*)\nHB.structure Definition JoinSemilattice d :=\n { T of POrder d T & POrder_isJoinSemilattice d T }.\n\n#[short(type=\"bJoinSemilatticeType\")]\n(*This definition describes a join-semilattice that also has a bottom element, which is the least element in the set and acts as an identity for the join operation.*)\nHB.structure Definition BJoinSemilattice d :=\n { T of JoinSemilattice d T & hasBottom d T }.\n\n#[short(type=\"tJoinSemilatticeType\")]\n(*This definition describes a join-semilattice that also has a top element, which is the greatest element in the set.*)\nHB.structure Definition TJoinSemilattice d :=\n { T of JoinSemilattice d T & hasTop d T }.\n\n#[short(type=\"tbJoinSemilatticeType\")]\n(*This definition describes a join-semilattice that has both a top element, which is the greatest element, and a bottom element, which is the least element.*)\nHB.structure Definition TBJoinSemilattice d :=\n { T of BJoinSemilattice d T & hasTop d T }.\n\n#[short(type=\"latticeType\")]\n(*This definition describes a type that is a lattice, which is a partially ordered set where every pair of elements has both a least upper bound (join) and a greatest lower bound (meet).*)\nHB.structure Definition Lattice d :=\n { T of JoinSemilattice d T & POrder_isMeetSemilattice d T }.\n\n#[short(type=\"bLatticeType\")]\n(*This definition describes a lattice that also has a bottom element, which is the least element in the set.*)\nHB.structure Definition BLattice d := { T of Lattice d T & hasBottom d T }.\n\n#[short(type=\"tLatticeType\")]\n(*This definition describes a lattice that also has a top element, which is the greatest element in the set.*)\nHB.structure Definition TLattice d := { T of Lattice d T & hasTop d T }.\n\n#[short(type=\"tbLatticeType\")]\n(*This definition describes a bounded lattice, which is a lattice that has both a greatest element (top) and a least element (bottom).*)\nHB.structure Definition TBLattice d := { T of BLattice d T & hasTop d T }.\n\nSection LatticeDef.\nContext {disp : disp_t} {T : latticeType disp}.\n\n(*This inductive type provides a constructive proof that for any two elements in a partial order, one is either less than or equal to the other, or the second is strictly less than the first. It has two constructors representing these mutually exclusive cases.*)\nVariant lel_xor_gt (x y : T) :\n T -> T -> T -> T -> T -> T -> T -> T -> bool -> bool -> Set :=\n(**)\n | LelNotGt of x <= y : lel_xor_gt x y x x y y x x y y true false\n(**)\n | GtlNotLe of y < x : lel_xor_gt x y y y x x y y x x false true.\n\n(*This inductive type provides a constructive proof that for any two elements in a partial order, one is either strictly less than the other, or the second is greater than or equal to the first. It has two constructors representing these mutually exclusive cases.*)\nVariant ltl_xor_ge (x y : T) :\n T -> T -> T -> T -> T -> T -> T -> T -> bool -> bool -> Set :=\n(**)\n | LtlNotGe of x < y : ltl_xor_ge x y x x y y x x y y false true\n(**)\n | GelNotLt of y <= x : ltl_xor_ge x y y y x x y y x x true false.\n\n(*This inductive type provides a constructive three-way comparison for two comparable elements. It has three constructors representing the mutually exclusive outcomes: the first element is strictly less than the second, the second is strictly less than the first, or the two elements are equal.*)\nVariant comparel (x y : T) :\n T -> T -> T -> T -> T -> T -> T -> T ->\n bool -> bool -> bool -> bool -> bool -> bool -> Set :=\n(**)\n | ComparelLt of x < y : comparel x y\n x x y y x x y y false false false true false true\n(**)\n | ComparelGt of y < x : comparel x y\n y y x x y y x x false false true false true false\n(**)\n | ComparelEq of x = y : comparel x y\n x x x x x x x x true true true true false false.\n\n(*This inductive type provides a constructive four-way comparison for any two elements in a lattice. It has four constructors representing the mutually exclusive outcomes: the first element is strictly less than the second, the second is strictly less than the first, the elements are incomparable, or the elements are equal.*)\nVariant incomparel (x y : T) :\n T -> T -> T -> T -> T -> T -> T -> T ->\n bool -> bool -> bool -> bool -> bool -> bool -> bool -> bool -> Set :=\n(**)\n | InComparelLt of x < y : incomparel x y\n x x y y x x y y false false false true false true true true\n(*This constructor of a comparison result type indicates that the first element is strictly greater than the second.*)\n | InComparelGt of y < x : incomparel x y\n y y x x y y x x false false true false true false true true\n(*This inductive type represents the outcome of comparing two elements from a partially ordered type, which can be less than, equal to, greater than, or incomparable.*)\n | InComparel of x >< y : incomparel x y\n x y y x (meet y x) (meet x y) (join y x) (join x y)\n false false false false false false false false\n(*This constructor of a comparison result type indicates that the two compared elements are equal.*)\n | InComparelEq of x = y : incomparel x y\n x x x x x x x x true true true true false false true true.\n\nEnd LatticeDef.\n\nModule LatticeSyntax.\n\n(*This notation defines the binary meet operation, which computes the greatest lower bound (infimum) of two elements in a meet-semilattice.*)\nNotation \"x `&` y\" := (meet x y) : order_scope.\n(*This notation defines the binary join operation, which computes the least upper bound (supremum) of two elements in a join-semilattice.*)\nNotation \"x `|` y\" := (join x y) : order_scope.\n\nEnd LatticeSyntax.\nHB.export LatticeSyntax.\n\nModule BLatticeSyntax.\n\n(*This notation computes the iterated join of a sequence of values. It applies a function to each element of an input sequence that satisfies a given predicate, and then computes the join of all the resulting values. If no elements satisfy the predicate, it returns the bottom element of the lattice.*)\nNotation \"\\join_ ( i <- r | P ) F\" :=\n (\\big[@join _ _ / \\bot]_(i <- r | P%B) F%O) : order_scope.\n(*This notation computes the iterated join of a sequence of values. It applies a function to each element of an input sequence and then computes the join of all the resulting values. If the sequence is empty, it returns the bottom element of the lattice.*)\nNotation \"\\join_ ( i <- r ) F\" :=\n (\\big[@join _ _ / \\bot]_(i <- r) F%O) : order_scope.\n(*This notation computes the join of values over all elements of a given finite type that satisfy a specific predicate. It applies a function to each qualifying element and then computes the join of all the results.*)\nNotation \"\\join_ ( i | P ) F\" :=\n (\\big[@join _ _ / \\bot]_(i | P%B) F%O) : order_scope.\n(*This notation computes the join of values over all elements of a given finite type. It applies a function to each element of the type and then computes the join of all the resulting values.*)\nNotation \"\\join_ i F\" :=\n (\\big[@join _ _ / \\bot]_i F%O) : order_scope.\n(*This notation computes the join of values over all elements of an explicitly specified type that satisfy a given predicate. It applies a function to each qualifying element and computes the join of the results. This is typically used for finite types.*)\nNotation \"\\join_ ( i : I | P ) F\" :=\n (\\big[@join _ _ / \\bot]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the join, or least upper bound, of a family of elements indexed by a type. The values are produced by applying a function to each index.*)\nNotation \"\\join_ ( i : I ) F\" :=\n (\\big[@join _ _ / \\bot]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for computing the join, or least upper bound, of a family of elements. The elements are generated by a function applied to natural number indices within a specified range from a lower bound up to, but not including, an upper bound, and which also satisfy a given boolean predicate.*)\nNotation \"\\join_ ( m <= i < n | P ) F\" :=\n (\\big[@join _ _ / \\bot]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the join, or least upper bound, of a family of elements. The elements are generated by a function applied to natural number indices within a specified range from a lower bound up to, but not including, an upper bound.*)\nNotation \"\\join_ ( m <= i < n ) F\" :=\n (\\big[@join _ _ / \\bot]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the join, or least upper bound, of a family of elements. The elements are generated by a function applied to natural number indices less than a given upper bound, and which also satisfy a given boolean predicate.*)\nNotation \"\\join_ ( i < n | P ) F\" :=\n (\\big[@join _ _ / \\bot]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the join, or least upper bound, of a family of elements. The elements are generated by a function applied to natural number indices less than a given upper bound.*)\nNotation \"\\join_ ( i < n ) F\" :=\n (\\big[@join _ _ / \\bot]_(i < n) F%O) : order_scope.\n(*A notation for computing the join, or least upper bound, of a family of elements. The elements are generated by a function applied to indices that are members of a given finite set and also satisfy a given boolean predicate.*)\nNotation \"\\join_ ( i 'in' A | P ) F\" :=\n (\\big[@join _ _ / \\bot]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the join, or least upper bound, of a family of elements. The elements are generated by a function applied to indices that are members of a given finite set.*)\nNotation \"\\join_ ( i 'in' A ) F\" :=\n (\\big[@join _ _ / \\bot]_(i in A) F%O) : order_scope.\n\nEnd BLatticeSyntax.\nHB.export BLatticeSyntax.\n\nModule TLatticeSyntax.\n\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to items drawn from a given sequence, provided that these items also satisfy a given boolean predicate.*)\nNotation \"\\meet_ ( i <- r | P ) F\" :=\n (\\big[meet / \\top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to each item drawn from a given sequence.*)\nNotation \"\\meet_ ( i <- r ) F\" :=\n (\\big[meet / \\top]_(i <- r) F%O) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to any index that satisfies a given boolean predicate.*)\nNotation \"\\meet_ ( i | P ) F\" :=\n (\\big[meet / \\top]_(i | P%B) F%O) : order_scope.\n(*A notation representing the value of a function applied to a single index, typically used for consistency within expressions involving iterated meet operations.*)\nNotation \"\\meet_ i F\" :=\n (\\big[meet / \\top]_i F%O) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements indexed by a type, where the indices must also satisfy a given boolean predicate. The values are produced by applying a function to each qualifying index.*)\nNotation \"\\meet_ ( i : I | P ) F\" :=\n (\\big[meet / \\top]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements indexed by a type. The values are produced by applying a function to each index.*)\nNotation \"\\meet_ ( i : I ) F\" :=\n (\\big[meet / \\top]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to natural number indices within a specified range from a lower bound up to, but not including, an upper bound, and which also satisfy a given boolean predicate.*)\nNotation \"\\meet_ ( m <= i < n | P ) F\" :=\n (\\big[meet / \\top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to natural number indices within a specified range from a lower bound up to, but not including, an upper bound.*)\nNotation \"\\meet_ ( m <= i < n ) F\" :=\n (\\big[meet / \\top]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to natural number indices less than a given upper bound, and which also satisfy a given boolean predicate.*)\nNotation \"\\meet_ ( i < n | P ) F\" :=\n (\\big[meet / \\top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to natural number indices less than a given upper bound.*)\nNotation \"\\meet_ ( i < n ) F\" :=\n (\\big[meet / \\top]_(i < n) F%O) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to indices that are members of a given finite set and also satisfy a given boolean predicate.*)\nNotation \"\\meet_ ( i 'in' A | P ) F\" :=\n (\\big[meet / \\top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the meet, or greatest lower bound, of a family of elements. The elements are generated by a function applied to indices that are members of a given finite set.*)\nNotation \"\\meet_ ( i 'in' A ) F\" :=\n (\\big[meet / \\top]_(i in A) F%O) : order_scope.\n\nEnd TLatticeSyntax.\nHB.export TLatticeSyntax.\n\n#[key=\"T\", primitive]\n(*This record is a mixin that equips a lattice structure with the properties of distributivity. It contains fields asserting that the meet operation distributes over the join operation, and that the join operation distributes over the meet operation.*)\nHB.mixin Record Lattice_isDistributive d (T : Type) of Lattice d T := {\n meetUl : @left_distributive T T meet join;\n joinIl : @left_distributive T T join meet; \n}.\n\n#[short(type=\"distrLatticeType\")]\n(*This structure defines a distributive lattice, which is a partially ordered set where every two elements have a unique least upper bound (join) and a unique greatest lower bound (meet), and these two operations distribute over each other.*)\nHB.structure Definition DistrLattice d :=\n { T of Lattice_isDistributive d T & Lattice d T }.\n\n#[short(type=\"bDistrLatticeType\")]\n(*This structure defines a bounded distributive lattice with a bottom element. It is a distributive lattice that also contains a least element, which is the identity for the join operation.*)\nHB.structure Definition BDistrLattice d :=\n { T of DistrLattice d T & hasBottom d T }.\n\n#[short(type=\"tDistrLatticeType\")]\n(*This structure defines a bounded distributive lattice with a top element. It is a distributive lattice that also contains a greatest element, which is the identity for the meet operation.*)\nHB.structure Definition TDistrLattice d :=\n { T of DistrLattice d T & hasTop d T }.\n\n#[short(type=\"tbDistrLatticeType\")]\n(*This structure defines a bounded distributive lattice, which is a distributive lattice containing both a least element (bottom) and a greatest element (top).*)\nHB.structure Definition TBDistrLattice d :=\n { T of BDistrLattice d T & hasTop d T }.\n\n#[key=\"T\", primitive]\n(*This record is a mixin for a distributive lattice that adds the property of having a total order. It contains a field asserting that for any two elements, one is less than or equal to the other.*)\nHB.mixin Record DistrLattice_isTotal d T of DistrLattice d T :=\n { le_total : total (<=%O : rel T) }.\n\n#[short(type=\"orderType\")]\n(*This structure defines a totally ordered distributive lattice, also known as a chain. It is a distributive lattice in which the order relation is total, meaning any two elements are comparable.*)\nHB.structure Definition Total d :=\n { T of DistrLattice_isTotal d T & DistrLattice d T }.\n\n#[short(type=\"bOrderType\")]\n(*This structure defines a totally ordered distributive lattice with a bottom element. It combines the properties of a total order and a distributive lattice with a guaranteed least element.*)\nHB.structure Definition BTotal d := { T of Total d T & hasBottom d T }.\n\n#[short(type=\"tOrderType\")]\n(*This structure defines a totally ordered distributive lattice with a top element. It combines the properties of a total order and a distributive lattice with a guaranteed greatest element.*)\nHB.structure Definition TTotal d := { T of Total d T & hasTop d T }.\n\n#[short(type=\"tbOrderType\")]\n(*This structure defines a totally ordered distributive lattice with both a top and a bottom element. It is a chain that is also a bounded lattice.*)\nHB.structure Definition TBTotal d := { T of BTotal d T & hasTop d T }.\n\n#[key=\"T\", primitive]\n(*This record is a mixin for a distributive lattice that asserts it is relatively complemented. This means that for any two elements that form an interval, any element within that interval has a complement relative to the interval's bounds.*)\nHB.mixin Record DistrLattice_hasRelativeComplement d T of DistrLattice d T := {\n \n rcompl : T -> T -> T -> T;\n rcomplPmeet : forall x y z, ((x `&` y) `|` z) `&` rcompl x y z = x `&` y;\n rcomplPjoin : forall x y z, ((y `|` x) `&` z) `|` rcompl x y z = y `|` x;\n}.\n\n#[short(type=\"cDistrLatticeType\")]\n(*This structure defines a type that is a relatively complemented distributive lattice, where every interval defined by two elements contains a relative complement for any element within that interval.*)\nHB.structure Definition CDistrLattice d :=\n { T of DistrLattice d T & DistrLattice_hasRelativeComplement d T }.\n\n#[key=\"T\", primitive]\n(*This mixin endows a relatively complemented distributive lattice that has a bottom element with a sectional complement operation, commonly understood as a difference. The difference of two elements is defined as the relative complement of the second element within the interval from the bottom element to the first element.*)\nHB.mixin Record CDistrLattice_hasSectionalComplement d T\n of CDistrLattice d T & hasBottom d T := {\n diff : T -> T -> T;\n \n diffErcompl : forall x y, diff x y = rcompl (\\bot : T) x y;\n}.\n\n#[short(type=\"cbDistrLatticeType\")]\n(*This structure defines a type that is a relatively complemented distributive lattice equipped with a bottom element and a sectional complement, or difference, operation.*)\nHB.structure Definition CBDistrLattice d :=\n { T of CDistrLattice d T & hasBottom d T &\n CDistrLattice_hasSectionalComplement d T }.\n\n#[key=\"T\", primitive]\n(*This mixin endows a relatively complemented distributive lattice that has a top element with a dual sectional complement operation. This operation computes the relative complement of the second element within the interval from the first element to the top element.*)\nHB.mixin Record CDistrLattice_hasDualSectionalComplement d T\n of CDistrLattice d T & hasTop d T := {\n codiff : T -> T -> T;\n codiffErcompl : forall x y, codiff x y = rcompl x \\top y;\n}.\n\n#[short(type=\"ctDistrLatticeType\")]\n(*This structure defines a type that is a relatively complemented distributive lattice equipped with a top element and a dual sectional complement operation.*)\nHB.structure Definition CTDistrLattice d :=\n { T of CDistrLattice d T & hasTop d T &\n CDistrLattice_hasDualSectionalComplement d T }.\n\nModule Import CBDistrLatticeSyntax.\n(*This notation represents the sectional complement, or difference, between two elements in a relatively complemented distributive lattice with a bottom element.*)\nNotation \"x `\\` y\" := (diff x y) : order_scope.\nEnd CBDistrLatticeSyntax.\n\n#[key=\"T\", primitive]\n(*This mixin provides a standard complement operation for a distributive lattice that has both top and bottom elements. The complement of an element is defined as its relative complement within the entire lattice, from the bottom element to the top element.*)\nHB.mixin Record CDistrLattice_hasComplement d T of\n CTDistrLattice d T & CBDistrLattice d T := {\n compl : T -> T;\n \n complEdiff : forall x : T, compl x = (\\top : T) `\\` x;\n complEcodiff : forall x : T, compl x = codiff (\\bot : T) x;\n}.\n\n#[short(type=\"ctbDistrLatticeType\")]\n(*This structure defines a type that is a complemented, bounded, distributive lattice, also known as a Boolean algebra. It possesses top and bottom elements, meet and join operations, and a complement for every element.*)\nHB.structure Definition CTBDistrLattice d :=\n { T of CBDistrLattice d T & CTDistrLattice d T &\n CDistrLattice_hasComplement d T }.\n\nModule Import CTBDistrLatticeSyntax.\n(*This notation represents the complement of an element in a bounded, complemented, distributive lattice.*)\nNotation \"~` A\" := (compl A) : order_scope.\nEnd CTBDistrLatticeSyntax.\n\n#[short(type=\"finPOrderType\")]\n(*This structure defines a type that is both finite and equipped with a partial order.*)\nHB.structure Definition FinPOrder d := { T of Finite T & POrder d T }.\n\n#[short(type=\"finBPOrderType\")]\n(*This structure defines a type that is finite, equipped with a partial order, and has a least element, also known as a bottom.*)\nHB.structure Definition FinBPOrder d := { T of FinPOrder d T & hasBottom d T }.\n\n#[short(type=\"finTPOrderType\")]\n(*This structure defines a type that is finite, equipped with a partial order, and has a greatest element, also known as a top.*)\nHB.structure Definition FinTPOrder d := { T of FinPOrder d T & hasTop d T }.\n\n#[short(type=\"finTBPOrderType\")]\n(*This structure defines a type that is finite, equipped with a partial order, and has both a greatest and a least element.*)\nHB.structure Definition FinTBPOrder d := { T of FinBPOrder d T & hasTop d T }.\n\n#[short(type=\"finMeetSemilatticeType\")]\n(*This structure defines a type that is both finite and equipped with a meet-semilattice structure, guaranteeing the existence of a greatest lower bound for any pair of elements.*)\nHB.structure Definition FinMeetSemilattice d :=\n { T of Finite T & MeetSemilattice d T }.\n\n#[short(type=\"finBMeetSemilatticeType\")]\n(*This structure defines a type that is finite and forms a bounded meet-semilattice, meaning it has a meet operation and a bottom element that is less than or equal to all other elements.*)\nHB.structure Definition FinBMeetSemilattice d :=\n { T of Finite T & BMeetSemilattice d T }.\n\n#[short(type=\"finJoinSemilatticeType\")]\n(*This structure defines a type that is both finite and equipped with a join-semilattice structure, guaranteeing the existence of a least upper bound for any pair of elements.*)\nHB.structure Definition FinJoinSemilattice d :=\n { T of Finite T & JoinSemilattice d T }.\n\n#[short(type=\"finTJoinSemilatticeType\")]\n(*This structure defines a type that is finite and forms a bounded join-semilattice, meaning it has a join operation and a top element that is greater than or equal to all other elements.*)\nHB.structure Definition FinTJoinSemilattice d :=\n { T of Finite T & TJoinSemilattice d T }.\n\n#[short(type=\"finLatticeType\")]\n(*This structure defines a type that is both finite and equipped with a lattice structure, having both a meet and a join operation.*)\nHB.structure Definition FinLattice d := { T of Finite T & Lattice d T }.\n\n#[short(type=\"finTBLatticeType\")]\n(*This structure defines a type that is finite and forms a bounded lattice, meaning it has meet and join operations as well as both a top and a bottom element.*)\nHB.structure Definition FinTBLattice d := { T of Finite T & TBLattice d T }.\n\n#[short(type=\"finDistrLatticeType\")]\n(*This structure defines a type that is both finite and equipped with a distributive lattice structure, where the meet and join operations distribute over each other.*)\nHB.structure Definition FinDistrLattice d :=\n { T of Finite T & DistrLattice d T }.\n\n#[short(type=\"finTBDistrLatticeType\")]\n(*This structure defines a type that is finite and forms a bounded distributive lattice, having top and bottom elements, and meet and join operations that distribute over each other.*)\nHB.structure Definition FinTBDistrLattice d :=\n { T of Finite T & TBDistrLattice d T }.\n\n#[short(type=\"finOrderType\")]\n(*This structure defines a type that is both finite and equipped with a total order, meaning any two elements are comparable.*)\nHB.structure Definition FinTotal d := { T of Finite T & Total d T }.\n\n#[short(type=\"finTBOrderType\")]\n(*This structure defines a type that is finite, equipped with a total order, and has both a greatest and a least element.*)\nHB.structure Definition FinTBTotal d := { T of Finite T & TBTotal d T }.\n\n#[short(type=\"finCDistrLatticeType\")]\n(*This structure defines a type that is both finite and forms a relatively complemented distributive lattice.*)\nHB.structure Definition FinCDistrLattice d :=\n { T of Finite T & CDistrLattice d T }.\n\n#[short(type=\"finCTBDistrLatticeType\")]\n(*This structure defines a type that is both finite and forms a complemented, bounded, distributive lattice, also known as a finite Boolean algebra.*)\nHB.structure Definition FinCTBDistrLattice d :=\n { T of Finite T & CTBDistrLattice d T }.\n\n(*This notation defines the meet operation for the dual of an ordered type. It is equivalent to the join operation of the original, non-dual type.*)\nNotation dual_meet := (@meet (dual_display _) _).\n(*This notation defines the join operation for the dual of an ordered type. It is equivalent to the meet operation of the original, non-dual type.*)\nNotation dual_join := (@join (dual_display _) _).\n\nModule Import DualSyntax.\n\n(*This notation represents the meet operation in a dual lattice structure, which corresponds to the join operation in the original lattice.*)\nNotation \"x `&^d` y\" := (dual_meet x y) : order_scope.\n(*This notation represents the join operation in a dual lattice structure, which corresponds to the meet operation in the original lattice.*)\nNotation \"x `|^d` y\" := (dual_join x y) : order_scope.\n\n(*This notation represents the bottom element of a dual ordered structure, which is equivalent to the top element of the original, non-dual structure.*)\nLocal Notation \"\\bot\" := dual_bottom.\n(*A notation for the top element in a dual order structure. This element corresponds to the bottom element of the original order.*)\nLocal Notation \"\\top\" := dual_top.\n(*A notation for the binary join operation (least upper bound) within a dual order structure. This corresponds to the meet operation (greatest lower bound) in the original order.*)\nLocal Notation join := dual_join.\n(*A notation for the binary meet operation (greatest lower bound) within a dual order structure. This corresponds to the join operation (least upper bound) in the original order.*)\nLocal Notation meet := dual_meet.\n(*A notation for the binary minimum operation within a dual order structure. This corresponds to the maximum operation in the original order.*)\nLocal Notation min := dual_min.\n(*A notation for the binary maximum operation within a dual order structure. This corresponds to the minimum operation in the original order.*)\nLocal Notation max := dual_max.\n\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to elements of a given finite sequence that satisfy a predicate. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( i <- r | P ) F\" :=\n (\\big[join / \\bot]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to all elements of a given finite sequence. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( i <- r ) F\" :=\n (\\big[join / \\bot]_(i <- r) F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to all elements of a finite type that satisfy a given predicate. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( i | P ) F\" :=\n (\\big[join / \\bot]_(i | P%B) F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to all elements of a finite type. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ i F\" :=\n (\\big[join / \\bot]_i F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to elements of a specified type that satisfy a predicate. This operation corresponds to an iterated join in the dual order and is for parsing only.*)\nNotation \"\\join^d_ ( i : I | P ) F\" :=\n (\\big[join / \\bot]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to all elements of a specified type. This operation corresponds to an iterated join in the dual order and is for parsing only.*)\nNotation \"\\join^d_ ( i : I ) F\" :=\n (\\big[join / \\bot]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to natural numbers within a specified range that satisfy a predicate. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( m <= i < n | P ) F\" :=\n (\\big[join / \\bot]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to all natural numbers within a specified range. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( m <= i < n ) F\" :=\n (\\big[join / \\bot]_(m <= i < n) F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of-values. The values are generated by applying a function to natural numbers less than a given bound that satisfy a predicate. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( i < n | P ) F\" :=\n (\\big[join / \\bot]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to all natural numbers less than a given bound. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( i < n ) F\" :=\n (\\big[join / \\bot]_(i < n) F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to elements of a given finite set that satisfy a predicate. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( i 'in' A | P ) F\" :=\n (\\big[join / \\bot]_(i in A | P%B) F%O) : order_scope.\n(*A notation for the greatest lower bound (infimum) of a collection of values. The values are generated by applying a function to all elements of a given finite set. This operation corresponds to an iterated join in the dual order.*)\nNotation \"\\join^d_ ( i 'in' A ) F\" :=\n (\\big[join / \\bot]_(i in A) F%O) : order_scope.\n\nNotation \"\\meet^d_ ( i <- r | P ) F\" :=\n (\\big[meet / \\top]_(i <- r | P%B) F%O) : order_scope.\nNotation \"\\meet^d_ ( i <- r ) F\" :=\n (\\big[meet / \\top]_(i <- r) F%O) : order_scope.\nNotation \"\\meet^d_ ( i | P ) F\" :=\n (\\big[meet / \\top]_(i | P%B) F%O) : order_scope.\nNotation \"\\meet^d_ i F\" :=\n (\\big[meet / \\top]_i F%O) : order_scope.\nNotation \"\\meet^d_ ( i : I | P ) F\" :=\n (\\big[meet / \\top]_(i : I | P%B) F%O) (only parsing) : order_scope.\nNotation \"\\meet^d_ ( i : I ) F\" :=\n (\\big[meet / \\top]_(i : I) F%O) (only parsing) : order_scope.\nNotation \"\\meet^d_ ( m <= i < n | P ) F\" :=\n (\\big[meet / \\top]_(m <= i < n | P%B) F%O) : order_scope.\nNotation \"\\meet^d_ ( m <= i < n ) F\" :=\n (\\big[meet / \\top]_(m <= i < n) F%O) : order_scope.\nNotation \"\\meet^d_ ( i < n | P ) F\" :=\n (\\big[meet / \\top]_(i < n | P%B) F%O) : order_scope.\nNotation \"\\meet^d_ ( i < n ) F\" :=\n (\\big[meet / \\top]_(i < n) F%O) : order_scope.\nNotation \"\\meet^d_ ( i 'in' A | P ) F\" :=\n (\\big[meet / \\top]_(i in A | P%B) F%O) : order_scope.\nNotation \"\\meet^d_ ( i 'in' A ) F\" :=\n (\\big[meet / \\top]_(i in A) F%O) : order_scope.\n\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to elements of a given finite sequence that satisfy a predicate. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( i <- r | P ) F\" :=\n (\\big[meet / \\top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to all elements of a given finite sequence. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( i <- r ) F\" :=\n (\\big[meet / \\top]_(i <- r) F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to all elements of a finite type that satisfy a given predicate. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( i | P ) F\" :=\n (\\big[meet / \\top]_(i | P%B) F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to all elements of a finite type. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ i F\" :=\n (\\big[meet / \\top]_i F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to elements of a specified type that satisfy a predicate. This operation corresponds to an iterated meet in the dual order and is for parsing only.*)\nNotation \"\\meet^d_ ( i : I | P ) F\" :=\n (\\big[meet / \\top]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to all elements of a specified type. This operation corresponds to an iterated meet in the dual order and is for parsing only.*)\nNotation \"\\meet^d_ ( i : I ) F\" :=\n (\\big[meet / \\top]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to natural numbers within a specified range that satisfy a predicate. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( m <= i < n | P ) F\" :=\n (\\big[meet / \\top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to all natural numbers within a specified range. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( m <= i < n ) F\" :=\n (\\big[meet / \\top]_(m <= i < n) F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to natural numbers less than a given bound that satisfy a predicate. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( i < n | P ) F\" :=\n (\\big[meet / \\top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to all natural numbers less than a given bound. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( i < n ) F\" :=\n (\\big[meet / \\top]_(i < n) F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to elements of a given finite set that satisfy a predicate. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( i 'in' A | P ) F\" :=\n (\\big[meet / \\top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for the least upper bound (supremum) of a collection of values. The values are generated by applying a function to all elements of a given finite set. This operation corresponds to an iterated meet in the dual order.*)\nNotation \"\\meet^d_ ( i 'in' A ) F\" :=\n (\\big[meet / \\top]_(i in A) F%O) : order_scope.\n\n(*A notation for the maximum value within a collection of values. The values are generated by applying a function to all elements of a finite type. This operation corresponds to an iterated minimum in the dual order.*)\nNotation \"\\min^d_ i F\" :=\n (\\big[min/top]_i F) : order_scope.\n(*A notation for the maximum value of a function over a finite sequence of elements that satisfy a given predicate. The maximum is determined with respect to the original order. If no elements satisfy the predicate, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i <- r | P ) F\" :=\n (\\big[min/top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for the maximum value of a function over a range of natural numbers from zero up to a given bound. The maximum is determined with respect to the original order. If the range is empty, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i < r ) F\" :=\n (\\big[min/top]_(i <- r) F%O) : order_scope.\n(*A notation for the maximum value of a function over a range of natural numbers that satisfy a given predicate. The maximum is determined with respect to the original order. If no numbers in the range satisfy the predicate, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( m <= i < n | P ) F\" :=\n (\\big[min/top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the maximum value of a function over a range of natural numbers. The maximum is determined with respect to the original order. If the range is empty, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( m <= i < n ) F\" :=\n (\\big[min/top]_(m <= i < n) F%O) : order_scope.\n(*A notation for the maximum value of a function over all elements of a finite type that satisfy a given predicate. The maximum is determined with respect to the original order. If no elements satisfy the predicate, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i | P ) F\" :=\n (\\big[min/top]_(i | P%B) F%O) : order_scope.\n(*A notation for parsing the maximum value of a function over all elements of a given finite type that satisfy a predicate. The maximum is determined with respect to the original order. If no elements satisfy the predicate, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i : t | P ) F\" :=\n (\\big[min/top]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(*A notation for parsing the maximum value of a function over all elements of a given finite type. The maximum is determined with respect to the original order. If the type is empty, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i : t ) F\" :=\n (\\big[min/top]_(i : t) F%O) (only parsing) : order_scope.\n(*A notation for the maximum value of a function over a range of natural numbers from zero up to a given bound, considering only those numbers that satisfy a predicate. The maximum is determined with respect to the original order. If no numbers in the range satisfy the predicate, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i < n | P ) F\" :=\n (\\big[min/top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the maximum value of a function over a range of natural numbers from zero up to a given bound. The maximum is determined with respect to the original order. If the range is empty, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i < n ) F\" :=\n (\\big[min/top]_(i < n) F%O) : order_scope.\n(*A notation for the maximum value of a function over all elements in a given finite set that also satisfy a predicate. The maximum is determined with respect to the original order. If no elements in the set satisfy the predicate, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i 'in' A | P ) F\" :=\n (\\big[min/top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for the maximum value of a function over all elements in a given finite set. The maximum is determined with respect to the original order. If the set is empty, the result is the bottom element of the codomain's order.*)\nNotation \"\\min^d_ ( i 'in' A ) F\" :=\n (\\big[min/top]_(i in A) F%O) : order_scope.\n\n(*A notation for the minimum value among the elements of a given finite sequence. The minimum is determined with respect to the original order. If the sequence is empty, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ i F\" :=\n (\\big[max/bottom]_i F%O) : order_scope.\n(*A notation for the minimum value of a function over a finite sequence of elements that satisfy a given predicate. The minimum is determined with respect to the original order. If no elements satisfy the predicate, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i <- r | P ) F\" :=\n (\\big[max/bottom]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for the minimum value of a function over a range of natural numbers from zero up to a given bound. The minimum is determined with respect to the original order. If the range is empty, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i < r ) F\" :=\n (\\big[max/bottom]_(i <- r) F%O) : order_scope.\n(*A notation for the minimum value of a function over a range of natural numbers that satisfy a given predicate. The minimum is determined with respect to the original order. If no numbers in the range satisfy the predicate, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( m <= i < n | P ) F\" :=\n (\\big[max/bottom]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the minimum value of a function over a range of natural numbers. The minimum is determined with respect to the original order. If the range is empty, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( m <= i < n ) F\" :=\n (\\big[max/bottom]_(m <= i < n) F%O) : order_scope.\n(*A notation for the minimum value of a function over all elements of a finite type that satisfy a given predicate. The minimum is determined with respect to the original order. If no elements satisfy the predicate, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i | P ) F\" :=\n (\\big[max/bottom]_(i | P%B) F%O) : order_scope.\n(*A notation for parsing the minimum value of a function over all elements of a given finite type that satisfy a predicate. The minimum is determined with respect to the original order. If no elements satisfy the predicate, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i : t | P ) F\" :=\n (\\big[max/bottom]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(*A notation for parsing the minimum value of a function over all elements of a given finite type. The minimum is determined with respect to the original order. If the type is empty, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i : t ) F\" :=\n (\\big[max/bottom]_(i : t) F%O) (only parsing) : order_scope.\n(*A notation for the minimum value of a function over a range of natural numbers from zero up to a given bound, considering only those numbers that satisfy a predicate. The minimum is determined with respect to the original order. If no numbers in the range satisfy the predicate, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i < n | P ) F\" :=\n (\\big[max/bottom]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the minimum value of a function over a range of natural numbers from zero up to a given bound. The minimum is determined with respect to the original order. If the range is empty, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i < n ) F\" :=\n (\\big[max/bottom]_(i < n) F%O) : order_scope.\n(*A notation for the minimum value of a function over all elements in a given finite set that also satisfy a predicate. The minimum is determined with respect to the original order. If no elements in the set satisfy the predicate, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i 'in' A | P ) F\" :=\n (\\big[max/bottom]_(i in A | P%B) F%O) : order_scope.\n(*A notation for the minimum value of a function over all elements in a given finite set. The minimum is determined with respect to the original order. If the set is empty, the result is the top element of the codomain's order.*)\nNotation \"\\max^d_ ( i 'in' A ) F\" :=\n (\\big[max/bottom]_(i in A) F%O) : order_scope.\n\nEnd DualSyntax.\n\nModule DualOrder.\n\nHB.instance Definition _ (d : disp_t) (T : porderType d) :=\n Preorder_isDuallyPOrder.Build (dual_display d) T^d\n ge_anti le_anti.\n\nHB.instance Definition _ d (T : joinSemilatticeType d) :=\n POrder_isMeetSemilattice.Build (dual_display d) T^d (fun x y z => leUx y z x).\n\n(*This lemma states that the meet of two elements in the dual of a join-semilattice is equivalent to the join of those same two elements in the original join-semilattice.*)\nLemma meetEdual d (T : joinSemilatticeType d) (x y : T) :\n ((x : T^d) `&^d` y) = (x `|` y).\n\nHB.instance Definition _ d (T : meetSemilatticeType d) :=\n POrder_isJoinSemilattice.Build (dual_display d) T^d (fun x y z => lexI z x y).\n\n(*This lemma states that the join of two elements in the dual of a meet-semilattice is equivalent to the meet of those same two elements in the original meet-semilattice.*)\nLemma joinEdual d (T : meetSemilatticeType d) (x y : T) :\n ((x : T^d) `|^d` y) = (x `&` y).\n\nHB.saturate.\n\nHB.instance Definition _ d (T : distrLatticeType d) :=\n Lattice_isDistributive.Build (dual_display d) T^d joinIl meetUl.\n\nHB.instance Definition _ d (T : orderType d) :=\n DistrLattice_isTotal.Build (dual_display d) T^d (fun x y => le_total y x).\n\nHB.saturate.\n\nHB.instance Definition _ d (T : cDistrLatticeType d) :=\n DistrLattice_hasRelativeComplement.Build (dual_display d) T^d\n (fun x y => rcomplPjoin y x) (fun x y => rcomplPmeet y x).\nHB.instance Definition _ d (T : ctDistrLatticeType d) :=\n CDistrLattice_hasSectionalComplement.Build (dual_display d) T^d codiffErcompl.\nHB.instance Definition _ d (T : cbDistrLatticeType d) :=\n CDistrLattice_hasDualSectionalComplement.Build (dual_display d) T^d\n diffErcompl.\n(*This lemma states that the less-than-or-equal-to relation is antisymmetric, meaning that if a first element is less than or equal to a second element, and the second element is also less than or equal to the first, then the two elements must be equal.*)\nLemma le_anti: antisymmetric (<=%O : rel T).\n\n(*This lemma states that the greater-than-or-equal-to relation is antisymmetric, meaning that if a first element is greater than or equal to a second element, and the second element is also greater than or equal to the first, then the two elements must be equal.*)\nLemma ge_anti: antisymmetric (>=%O : rel T).\n\n(*This lemma states that two elements are equal precisely when each is less than or equal to the other.*)\nLemma eq_le x y: (x == y) = (x <= y <= x).\n\n(*This lemma states that the strict less-than relation holds between a first and a second element precisely when the first element is less than or equal to the second, and the two elements are not equal.*)\nLemma lt_def x y : (x < y) = (y != x) && (x <= y).\n\n(*This lemma states that the strict less-than relation holds for a first and second element when they are not equal and the first is less than or equal to the second.*)\nLemma lt_neqAle x y: (x < y) = (x != y) && (x <= y).\n\n(*This lemma states that for any two elements, the first element is less than or equal to the second if and only if the first element is equal to the second or the first element is strictly less than the second.*)\nLemma le_eqVlt x y: (x <= y) = (x == y) || (x < y).\n\n(*This definition provides a collection of proofs related to the antisymmetry of order relations. It includes the fact that two elements are equal if and only if each is less than or equal to the other, as well as the asymmetric properties of the strict 'less than' relation.*)\nDefinition lte_anti := (=^~ eq_le, @lt_asym disp T, @lt_le_asym disp T, @le_lt_asym disp T).\n\n(*This lemma states that a finite sequence is sorted in strictly increasing order if and only if its elements are all unique and it is sorted in non-decreasing order.*)\nLemma lt_sorted_uniq_le s : sorted <%O s = uniq s && sorted <=%O s.\n\n(*This lemma states that if two finite sequences are both sorted in non-decreasing order and are permutations of each other, then the two sequences must be identical.*)\nLemma le_sorted_eq s1 s2 :\n sorted <=%O s1 -> sorted <=%O s2 -> perm_eq s1 s2 -> s1 = s2.\n\n(*This lemma states that an element is a member of a given finite sequence if and only if the number of elements in the sequence that are strictly less than the element is strictly less than the number of elements that are less than or equal to it.*)\nLemma count_lt_le_mem x s : (count (< x) s < count (<= x) s)%N = (x \\in s).\n\n(*This lemma provides an elimination principle for two comparable elements, allowing for case analysis on whether the first element is strictly less than, equal to, or strictly greater than the second, and provides corresponding values for minimum and maximum in each case.*)\nLemma comparable_ltgtP x y : x >=< y ->\n compare x y (min y x) (min x y) (max y x) (max x y)\n (y == x) (x == y) (x >= y) (x <= y) (x > y) (x < y).\n\n(*This lemma provides a case analysis for two comparable elements, asserting that exactly one of two cases is true: either the first element is less than or equal to the second, or the second element is strictly less than the first.*)\nLemma comparable_leP x y : x >=< y ->\n le_xor_gt x y (min y x) (min x y) (max y x) (max x y) (x <= y) (y < x).\n\n(*This lemma provides a case analysis for two comparable elements, asserting that exactly one of two cases is true: either the first element is strictly less than the second, or the second is less than or equal to the first.*)\nLemma comparable_ltP x y : x >=< y ->\n lt_xor_ge x y (min y x) (min x y) (max y x) (max x y) (y <= x) (x < y).\n\n(*This lemma provides a principle of case analysis for any two elements, allowing one to prove a property by considering two separate cases: one where the elements are comparable, and one where they are incomparable.*)\nLemma comparableP x y : incompare x y\n (min y x) (min x y) (max y x) (max x y)\n (y == x) (x == y) (x >= y) (x <= y) (x > y) (x < y)\n (y >=< x) (x >=< y).\n\n(*This lemma establishes the logical meaning of a boolean comparison involving a condition. It asserts that this boolean test is true if and only if the following holds: if the given boolean condition is true, the two elements are equal, and otherwise, the first element is strictly less than the second.*)\nLemma leifP x y C : reflect (x <= y ?= iff C) (if C then x == y else x < y).\n\n(*This lemma states a transitivity property for the 'le if' comparison. If the ordering between a first and second element is determined by a first boolean condition, and the ordering between the second and a third element is determined by a second boolean condition, then the ordering between the first and third elements is determined by the conjunction of the two boolean conditions.*)\nLemma leif_trans x1 x2 x3 C12 C23 :\n x1 <= x2 ?= iff C12 -> x2 <= x3 ?= iff C23 -> x1 <= x3 ?= iff C12 && C23.\n\n(*This lemma states that for two elements where the first is less than or equal to the second, the 'le if' comparison can be constructed using the boolean condition 'the first element is greater than or equal to the second'.*)\nLemma leif_le x y : x <= y -> x <= y ?= iff (x >= y).\n\n(*This lemma states that for two elements where the first is less than or equal to the second, the 'le if' comparison holds when using the equality of the two elements as the boolean condition.*)\nLemma leif_eq x y : x <= y -> x <= y ?= iff (x == y).\n\n(*This lemma states that if the 'less than or equal to' relationship between a first and second element is captured by a boolean condition via the 'le if' construct, then the proposition 'the second element is less than or equal to the first' is equivalent to that same boolean condition.*)\nLemma ge_leif x y C : x <= y ?= iff C -> (y <= x) = C.\n\n(*This lemma states that if a 'le if' comparison between two elements holds with a certain boolean condition, then the 'strictly less than' comparison between those elements is equivalent to the negation of that boolean condition.*)\nLemma lt_leif x y C : x <= y ?= iff C -> (x < y) = ~~ C.\n\n(*This lemma states that if a 'le if' comparison between two elements holds with the negation of a certain boolean condition, then the 'strictly less than' comparison between those elements is equivalent to that boolean condition itself.*)\nLemma ltNleif x y C : x <= y ?= iff ~~ C -> (x < y) = C.\n\n(*This lemma states an anti-symmetry property for a conditionally-weakened strict inequality. It asserts that if a first element is conditionally less than or equal to a second, and the second is also conditionally less than or equal to the first, then this is equivalent to both conditions being true and the elements being equal.*)\nLemma lteif_anti C1 C2 x y :\n (x < y ?<= if C1) && (y < x ?<= if C2) = C1 && C2 && (x == y).\n\n(*This lemma provides an asymmetry rule for conditionally weakened inequalities: if a first element is less than or equal to a second, where equality is permitted only if a given boolean condition is false, then it cannot be true that the second is less than or equal to the first, where equality is permitted if that same condition is true.*)\nLemma lteifN C x y : x < y ?<= if ~~ C -> ~~ (y < x ?<= if C).\n\n(*This lemma defines the minimum of two elements as the first element if it is less than or equal to the second, and the second element otherwise.*)\nLemma minEle x y : min x y = if x <= y then x else y.\n\n(*This lemma defines the maximum of two elements as the second element if the first is less than or equal to it, and the first element otherwise.*)\nLemma maxEle x y : max x y = if x <= y then y else x.\n\n(*This lemma states that for two comparable elements, their minimum is equal to the second element if the first is strictly greater than it, and the first element otherwise.*)\nLemma comparable_minEgt x y : x >=< y -> min x y = if x > y then y else x.\n\n(*This lemma states that for two comparable elements, their maximum is equal to the first element if it is strictly greater than the second, and the second element otherwise.*)\nLemma comparable_maxEgt x y : x >=< y -> max x y = if x > y then x else y.\n\n(*This lemma states that for two comparable elements, their minimum is equal to the second element if the first is greater than or equal to it, and is the first element otherwise.*)\nLemma comparable_minEge x y : x >=< y -> min x y = if x >= y then y else x.\n\n(*This lemma states that for two comparable elements, their maximum is equal to the first element if it is greater than or equal to the second, and is the second element otherwise.*)\nLemma comparable_maxEge x y : x >=< y -> max x y = if x >= y then x else y.\n\n(*This lemma states that if a first element is less than or equal to a second element, their minimum is the first element.*)\nLemma min_l x y : x <= y -> min x y = x. \n(*This lemma states that if a second element is less than or equal to a first element, their minimum is the second element.*)\nLemma min_r x y : y <= x -> min x y = y. \n(*This lemma states that if a second element is less than or equal to a first element, their maximum is the first element.*)\nLemma max_l x y : y <= x -> max x y = x. \n(*This lemma states that if a first element is less than or equal to a second element, their maximum is the second element.*)\nLemma max_r x y : x <= y -> max x y = y. \n\n(*This lemma states that the minimum of two elements is equal to the first element if and only if the first element is less than or equal to the second element.*)\nLemma eq_minl x y : (min x y == x) = (x <= y).\n\n(*This lemma states that the maximum of two elements is equal to the second element if and only if the first element is less than or equal to the second element.*)\nLemma eq_maxr x y : (max x y == y) = (x <= y).\n\n(*This lemma states that the minimum of two elements is equal to the first element if and only if the first element is less than or equal to the second.*)\nLemma min_idPl x y : reflect (min x y = x) (x <= y).\n\n(*This lemma states that the maximum of two elements is equal to the second element if and only if the first element is less than or equal to the second.*)\nLemma max_idPr x y : reflect (max x y = y) (x <= y).\n\nSection Comparable2.\nContext (z x y : T) (cmp_xy : x >=< y).\n\n(*This lemma states that for any two comparable elements, the minimum operation is commutative.*)\nLemma comparable_minC : min x y = min y x.\n\n(*This lemma states that for any two comparable elements, the maximum operation is commutative.*)\nLemma comparable_maxC : max x y = max y x.\n\n(*This lemma states that for two comparable elements, the boolean statement that their minimum is equal to the second element is equivalent to the proposition that the second element is less than or equal to the first.*)\nLemma comparable_eq_minr : (min x y == y) = (y <= x).\n\n(*This lemma states that for two comparable elements, the boolean statement that their maximum is equal to the first element is equivalent to the proposition that the second element is less than or equal to the first.*)\nLemma comparable_eq_maxl : (max x y == x) = (y <= x).\n\n(*This lemma states that for two comparable elements, their minimum is equal to the second element if and only if the second element is less than or equal to the first.*)\nLemma comparable_min_idPr : reflect (min x y = y) (y <= x).\n\n(*This lemma states that for two comparable elements, their maximum is equal to the first element if and only if the second element is less than or equal to the first.*)\nLemma comparable_max_idPl : reflect (max x y = x) (y <= x).\n\n(*This lemma provides a rule for negating a conditional less-than comparison between two comparable elements. It states that the conditional expression 'if a given boolean is false then the first element is strictly less than the second, else the first is less than or equal to the second' is equivalent to the negation of 'if the same boolean is true then the second element is strictly less than the first, else the second is less than or equal to the first'.*)\nLemma comparable_lteifNE C : x >=< y -> x < y ?<= if ~~ C = ~~ (y < x ?<= if C).\n\nEnd Comparable2.\n\nSection Comparable3.\nContext (x y z : T) (cmp_xy : x >=< y) (cmp_xz : x >=< z) (cmp_yz : y >=< z).\n(*This definition creates a shorthand for a function that converts a boolean proof of comparability between two elements into a propositional proof of comparability.*)\nLet P := comparableP.\n\n(*This lemma states that for any three pairwise comparable elements, the maximum operation distributes over the minimum operation. That is, the maximum of the minimum of the first two elements and the third element is equal to the minimum of two values: the maximum of the first and third elements, and the maximum of the second and third elements.*)\nLemma comparable_max_minl : max (min x y) z = min (max x z) (max y z).\n\nEnd Comparable3.\n\nSection Comparable4.\nContext (x y z w : T) (cmp_xy : x >=< y) (cmp_zw : z >=< w).\n\n(*This lemma states that the minimum operation is monotonic with respect to the order relation for comparable arguments. If a first element is less than or equal to a third, and a second element is less than or equal to a fourth, then the minimum of the first and second elements is less than or equal to the minimum of the third and fourth elements, provided the first two elements are comparable and the last two are comparable.*)\nLemma comparable_le_min2 : x <= z -> y <= w ->\n Order.min x y <= Order.min z w.\n\n(*This lemma states that the maximum operation is monotonic with respect to the order relation for comparable arguments. If a first element is less than or equal to a third, and a second element is less than or equal to a fourth, then the maximum of the first and second elements is less than or equal to the maximum of the third and fourth elements, provided the first two elements are comparable and the last two are comparable.*)\nLemma comparable_le_max2 : x <= z -> y <= w ->\n Order.max x y <= Order.max z w.\n\nEnd Comparable4.\n\n(*This lemma establishes an exchange property for the minimum operation over three pairwise comparable elements. It states that taking the minimum of the minimum of the first two elements and the third is equivalent to taking the minimum of the minimum of the first and third elements and the second.*)\nLemma comparable_minAC x y z : x >=< y -> x >=< z -> y >=< z ->\n min (min x y) z = min (min x z) y.\n\n(*This lemma establishes an exchange property for the maximum operation over three pairwise comparable elements. It states that taking the maximum of the maximum of the first two elements and the third is equivalent to taking the maximum of the maximum of the first and third elements and the second.*)\nLemma comparable_maxAC x y z : x >=< y -> x >=< z -> y >=< z ->\n max (max x y) z = max (max x z) y.\n\n(*This lemma establishes an exchange property for the minimum operation over three pairwise comparable elements. It states that taking the minimum of the first element and the minimum of the other two is equivalent to taking the minimum of the second element and the minimum of the first and third.*)\nLemma comparable_minCA x y z : x >=< y -> x >=< z -> y >=< z ->\n min x (min y z) = min y (min x z).\n\n(*This lemma establishes an exchange property for the maximum operation over three pairwise comparable elements. It states that taking the maximum of the first element and the maximum of the other two is equivalent to taking the maximum of the second element and the maximum of the first and third.*)\nLemma comparable_maxCA x y z : x >=< y -> x >=< z -> y >=< z ->\n max x (max y z) = max y (max x z).\n\n(*This lemma provides a middle-four exchange property for the minimum operation over four pairwise comparable elements. It asserts that the minimum of two values, where the first is the minimum of elements one and two, and the second is the minimum of elements three and four, is equal to the minimum of two other values, where the first is the minimum of elements one and three, and the second is the minimum of elements two and four.*)\nLemma comparable_minACA x y z t :\n x >=< y -> x >=< z -> x >=< t -> y >=< z -> y >=< t -> z >=< t ->\n min (min x y) (min z t) = min (min x z) (min y t).\n\n(*This lemma provides a middle-four exchange property for the maximum operation over four pairwise comparable elements. It asserts that the maximum of two values, where the first is the maximum of elements one and two, and the second is the maximum of elements three and four, is equal to the maximum of two other values, where the first is the maximum of elements one and three, and the second is the maximum of elements two and four.*)\nLemma comparable_maxACA x y z t :\n x >=< y -> x >=< z -> x >=< t -> y >=< z -> y >=< t -> z >=< t ->\n max (max x y) (max z t) = max (max x z) (max y t).\n\n(*This lemma states that for any three pairwise comparable elements, the minimum operation distributes over the maximum operation. Specifically, the minimum of the first element and the maximum of the other two is equal to the maximum of two values: the minimum of the first and second elements, and the minimum of the first and third elements.*)\nLemma comparable_min_maxr x y z : x >=< y -> x >=< z -> y >=< z ->\n min x (max y z) = max (min x y) (min x z).\n\n(*This lemma states that for a monotonic function over a given subset, a conditional equality involving a boolean comparison of the function's values at two points from the subset is equivalent to the same conditional equality for the comparison of the two points themselves.*)\nLemma mono_in_leif (A : {pred T}) (f : T -> T) C :\n {in A &, {mono f : x y / x <= y}} ->\n {in A &, forall x y, (f x <= f y ?= iff C) = (x <= y ?= iff C)}.\n\n(*This lemma states that for a monotonic function, a conditional equality involving a boolean comparison of the function's values at two points is equivalent to the same conditional equality for the comparison of the two points themselves.*)\nLemma mono_leif (f : T -> T) C :\n {mono f : x y / x <= y} ->\n forall x y, (f x <= f y ?= iff C) = (x <= y ?= iff C).\n\n(*This lemma states that for a non-increasing function over a given subset, a conditional equality involving a boolean comparison of the function's values at two points from the subset is equivalent to the same conditional equality for the reversed comparison of the two points themselves.*)\nLemma nmono_in_leif (A : {pred T}) (f : T -> T) C :\n {in A &, {mono f : x y /~ x <= y}} ->\n {in A &, forall x y, (f x <= f y ?= iff C) = (y <= x ?= iff C)}.\n\n(*This lemma states that for a non-increasing function, a conditional equality involving a boolean comparison of the function's values at two points is equivalent to the same conditional equality for the reversed comparison of the two points themselves.*)\nLemma nmono_leif (f : T -> T) C : {mono f : x y /~ x <= y} ->\n forall x y, (f x <= f y ?= iff C) = (y <= x ?= iff C).\n\nSection bigminmax.\nContext (I : Type) (r : seq I) (f : I -> T) (x0 x : T) (P : pred I).\n\n(*This lemma states that an element is an upper bound for a bounded iterated maximum over a sequence. If a default element is less than or equal to a given bound, and if a function's value for each element of a sequence satisfying a predicate is also less than or equal to that bound, then the iterated maximum is also less than or equal to the bound.*)\nLemma bigmax_le : x0 <= x -> (forall i, P i -> f i <= x) ->\n \\big[max/x0]_(i <- r | P i) f i <= x.\n\n(*This lemma states that an element is a lower bound for a bounded iterated minimum over a sequence. If a given bound is less than or equal to a default element, and if the bound is also less than or equal to a function's value for each element of a sequence satisfying a predicate, then the bound is also less than or equal to the iterated minimum.*)\nLemma le_bigmin : x <= x0 -> (forall i, P i -> x <= f i) ->\n x <= \\big[min/x0]_(i <- r | P i) f i.\n\nEnd bigminmax.\n\nEnd POrderTheory.\n\n#[global] Hint Resolve comparable_minr comparable_minl : core.\n#[global] Hint Resolve comparable_maxr comparable_maxl : core.\n\nSection ContraTheory.\nContext {disp1 disp2 : disp_t} {T1 : porderType disp1} {T2 : porderType disp2}.\nImplicit Types (x y : T1) (z t : T2) (b : bool) (m n : nat) (P : Prop).\n\n(*This lemma provides a rule of contraposition involving a boolean and a less-than comparison. It states that if an implication holds where the negation of a boolean implies that a first element is strictly less than a second, then another implication holds where the second element being less than or equal to the first implies that the boolean is true.*)\nLemma contra_leT b x y : (~~ b -> x < y) -> (y <= x -> b).\n\n(*This lemma provides a rule of contraposition involving a boolean and a less-than-or-equal-to comparison. It states that if an implication holds where the negation of a boolean implies that a first element is less than or equal to a second, then another implication holds where the second element being strictly less than the first implies that the boolean is true.*)\nLemma contra_ltT b x y : (~~ b -> x <= y) -> (y < x -> b).\n\n(*This lemma provides a rule of contraposition involving a boolean and a less-than comparison. It states that if an implication holds where a boolean implies that a first element is strictly less than a second, then another implication holds where the second element being less than or equal to the first implies that the boolean is false.*)\nLemma contra_leN b x y : (b -> x < y) -> (y <= x -> ~~ b).\n\n(*This lemma provides a rule of contraposition involving a boolean and a less-than-or-equal-to comparison. It states that if an implication holds where a boolean implies that a first element is less than or equal to a second, then another implication holds where the second element being strictly less than the first implies that the boolean is false.*)\nLemma contra_ltN b x y : (b -> x <= y) -> (y < x -> ~~ b).\n\n(*This lemma states that if a given proposition implies that a first element is strictly less than a second element, then the fact that the second element is less than or equal to the first element implies that the proposition is false.*)\nLemma contra_le_not P x y : (P -> x < y) -> (y <= x -> ~ P).\n\n(*This lemma states that if a given proposition implies that a first element is less than or equal to a second element, then the fact that the second element is strictly less than the first element implies that the proposition is false.*)\nLemma contra_lt_not P x y : (P -> x <= y) -> (y < x -> ~ P).\n\n(*This lemma states that if a boolean value being true implies that a first element is strictly less than a second element, then the fact that the second element is less than or equal to the first element implies that the boolean is false.*)\nLemma contra_leF b x y : (b -> x < y) -> (y <= x -> b = false).\n\n(*This lemma states that if a boolean value being true implies that a first element is less than or equal to a second element, then the fact that the second element is strictly less than the first element implies that the boolean is false.*)\nLemma contra_ltF b x y : (b -> x <= y) -> (y < x -> b = false).\n\n(*This lemma states that if a strict less-than relation between a first and a second natural number implies a reversed strict less-than relation between two elements of an ordered type, then a non-strict less-than-or-equal relation between those elements implies that the second natural number is less than or equal to the first.*)\nLemma contra_le_leq x y m n : ((n < m)%N -> y < x) -> (x <= y -> (m <= n)%N).\n\n(*This lemma states that if a non-strict less-than-or-equal relation between a first and a second natural number implies a reversed strict less-than relation between two elements of an ordered type, then a non-strict less-than-or-equal relation between those elements implies that the second natural number is strictly less than the first.*)\nLemma contra_le_ltn x y m n : ((n <= m)%N -> y < x) -> (x <= y -> (m < n)%N).\n\n(*This lemma states that if a strict less-than relation between a first and a second natural number implies a reversed non-strict less-than-or-equal relation between two elements of an ordered type, then a strict less-than relation between those elements implies that the second natural number is less than or equal to the first.*)\nLemma contra_lt_leq x y m n : ((n < m)%N -> y <= x) -> (x < y -> (m <= n)%N).\n\n(*This lemma states that if a non-strict less-than-or-equal relation between a first and a second natural number implies a reversed non-strict less-than-or-equal relation between two elements of an ordered type, then a strict less-than relation between those elements implies that the second natural number is strictly less than the first.*)\nLemma contra_lt_ltn x y m n : ((n <= m)%N -> y <= x) -> (x < y -> (m < n)%N).\n\nEnd ContraTheory.\n\nSection POrderMonotonyTheory.\nContext {disp disp' : disp_t} {T : porderType disp} {T' : porderType disp'}.\nContext (D D' : {pred T}) (f : T -> T').\n\n(*This definition provides a local alias for the antisymmetry property of the 'less than or equal to' relation, which states that if two elements are less than or equal to each other, they must be equal.*)\nLet leT_anti := @le_anti _ T.\nHint Resolve lexx lt_neqAle : core.\n\n(*This lemma asserts the antisymmetry of the 'greater than or equal to' relation, meaning that if a first element is greater than or equal to a second, and the second is also greater than or equal to the first, then the two elements are equal.*)\nLet ge_antiT : antisymmetric (>=%O : rel T).\n\n(*This lemma states that a function that preserves the strict 'less than' relation between any two elements also preserves the non-strict 'less than or equal to' relation.*)\nLemma ltW_homo : {homo f : x y / x < y} -> {homo f : x y / x <= y}.\n\n(*This lemma states that a function that reflects the strict 'less than' relation, meaning that the relation on the function's outputs implies the same relation on its inputs, also reflects the non-strict 'less than or equal to' relation.*)\nLemma ltW_nhomo : {homo f : x y /~ x < y} -> {homo f : x y /~ x <= y}.\n\n(*This lemma states that an injective function that preserves the non-strict 'less than or equal to' relation also preserves the strict 'less than' relation.*)\nLemma inj_homo_lt :\n injective f -> {homo f : x y / x <= y} -> {homo f : x y / x < y}.\n\n(*This lemma states that an injective function that reflects the non-strict 'less than or equal to' relation also reflects the strict 'less than' relation.*)\nLemma inj_nhomo_lt :\n injective f -> {homo f : x y /~ x <= y} -> {homo f : x y /~ x < y}.\n\n(*This lemma states that a function that is strictly increasing, meaning the 'less than or equal to' relation holds for its outputs if and only if it holds for its inputs, is necessarily an injective function.*)\nLemma inc_inj : {mono f : x y / x <= y} -> injective f.\n\n(*This lemma states that a function that is strictly decreasing, meaning the 'less than or equal to' relation holds for its outputs if and only if it does not hold for its inputs, is necessarily an injective function.*)\nLemma dec_inj : {mono f : x y /~ x <= y} -> injective f.\n\n(*This lemma states that for a function between two subsets of ordered types, if the function preserves the strict 'less than' relation for all elements in its domain subset, it also preserves the non-strict 'less than or equal to' relation on that same subset.*)\nLemma ltW_homo_in :\n {in D & D', {homo f : x y / x < y}} -> {in D & D', {homo f : x y / x <= y}}.\n\n(*This lemma states that for a function between two subsets of ordered types, if the function reflects the strict 'less than' relation for all elements in its domain subset, it also reflects the non-strict 'less than or equal to' relation on that same subset.*)\nLemma ltW_nhomo_in :\n {in D & D', {homo f : x y /~ x < y}} -> {in D & D', {homo f : x y /~ x <= y}}.\n\n(*This lemma states that for a function between two subsets of ordered types, if the function is injective on its domain subset and preserves the non-strict 'less than or equal to' relation, then it also preserves the strict 'less than' relation on that subset.*)\nLemma inj_homo_lt_in :\n {in D & D', injective f} -> {in D & D', {homo f : x y / x <= y}} ->\n {in D & D', {homo f : x y / x < y}}.\n\n(*This lemma states that for a function between two subsets of ordered types, if the function is injective on its domain subset and reflects the non-strict 'less than or equal to' relation, then it also reflects the strict 'less than' relation on that subset.*)\nLemma inj_nhomo_lt_in :\n {in D & D', injective f} -> {in D & D', {homo f : x y /~ x <= y}} ->\n {in D & D', {homo f : x y /~ x < y}}.\n\n(*This lemma states that a function defined on a subset of an ordered type is injective on that subset if it is strictly increasing on it, meaning the 'less than or equal to' relation holds for outputs if and only if it holds for inputs from that subset.*)\nLemma inc_inj_in : {in D &, {mono f : x y / x <= y}} ->\n {in D &, injective f}.\n\n(*This lemma states that a function defined on a subset of an ordered type is injective on that subset if it is strictly decreasing on it, meaning the 'less than or equal to' relation holds for outputs if and only if it does not hold for inputs from that subset.*)\nLemma dec_inj_in :\n {in D &, {mono f : x y /~ x <= y}} -> {in D &, injective f}.\n\nEnd POrderMonotonyTheory.\n\nEnd POrderTheory.\n\nArguments leifP {disp T x y C}.\nArguments mono_in_leif [disp T A f C].\nArguments nmono_in_leif [disp T A f C].\nArguments mono_leif [disp T f C].\nArguments nmono_leif [disp T f C].\nArguments min_idPl {disp T x y}.\nArguments max_idPr {disp T x y}.\nArguments comparable_min_idPr {disp T x y _}.\nArguments comparable_max_idPl {disp T x y _}.\n\nModule Import BPOrderTheory.\n\nExport BPreorderTheory.\n\nSection BPOrderTheory.\nContext {disp : disp_t} {T : bPOrderType disp}.\nImplicit Types (x y : T).\n\n(*This lemma states that an element is less than or equal to the bottom element if and only if that element is equal to the bottom element.*)\nLemma lex0 x : (x <= \\bot) = (x == \\bot).\n\n(*This lemma states that the bottom element is strictly less than another element if and only if that element is not equal to the bottom element.*)\nLemma lt0x x : (\\bot < x) = (x != \\bot).\n\n(*This inductive type provides a proof of casework, establishing that for any given element, it is either equal to the bottom element or strictly greater than the bottom element, with constructors for each of these two mutually exclusive possibilities.*)\nVariant eq0_xor_gt0 x : bool -> bool -> Set :=\n Eq0NotPOs : x = \\bot -> eq0_xor_gt0 x true false\n(*This lemma states that a type having a partial order structure does not imply that it has a zero element with decidable equality.*)\n | POsNotEq0 : \\bot < x -> eq0_xor_gt0 x false true.\n\n(*This lemma provides a constructive proof that for any given element, it is either equal to the bottom element or strictly greater than the bottom element, demonstrating the exclusive disjunction between these two properties.*)\nLemma posxP x : eq0_xor_gt0 x (x == \\bot) (\\bot < x).\n\nEnd BPOrderTheory.\nEnd BPOrderTheory.\n\nModule Import TPOrderTheory.\nSection TPOrderTheory.\nContext {disp : disp_t} {T : tPOrderType disp}.\nImplicit Types (x y : T).\n\n(*This lemma states that the top element is less than or equal to another element if and only if that element is equal to the top element.*)\nLemma le1x x : (\\top <= x) = (x == \\top). \n(*This lemma states that an element is strictly less than the top element if and only if that element is not equal to the top element.*)\nLemma ltx1 x : (x < \\top) = (x != \\top). \n\nEnd TPOrderTheory.\nEnd TPOrderTheory.\n\nModule Import MeetTheory.\nSection MeetTheory.\nContext {disp : disp_t} {L : meetSemilatticeType disp}.\nImplicit Types (x y : L).\n\n(*This lemma states that an element is less than or equal to the meet of two other elements if and only if it is less than or equal to both of those elements individually.*)\nLemma lexI x y z : (x <= y `&` z) = (x <= y) && (x <= z).\n\n(*This lemma states that the meet of two elements is less than or equal to the second of these two elements.*)\nLemma leIr x y : y `&` x <= x.\n\n(*This lemma states that the meet of two elements in a meet-semilattice is always less than or equal to the first element.*)\nLemma leIl x y : x `&` y <= x.\n\n(*This lemma states that if a first element is less than or equal to a second element, then the meet of the first element and a third element is also less than or equal to the second element.*)\nLemma leIxl x y z : y <= x -> y `&` z <= x.\n\n(*This lemma states that if a second element is less than or equal to a first element, then the meet of some other element and the second element is also less than or equal to the first element.*)\nLemma leIxr x y z : z <= x -> y `&` z <= x.\n\n(*This lemma states that if at least one of two given elements is less than or equal to a third element, then the meet of those two elements is also less than or equal to the third element.*)\nLemma leIx2 x y z : (y <= x) || (z <= x) -> y `&` z <= x.\n\n(*This lemma establishes an equivalence, stating that a first element is less than or equal to a second element if and only if the meet of the two elements is equal to the first element.*)\nLemma leEmeet x y : (x <= y) = (x `&` y == x).\n\n(*This lemma establishes an equivalence, stating that the meet of two elements equals the first element if and only if the first element is less than or equal to the second.*)\nLemma eq_meetl x y : (x `&` y == x) = (x <= y).\n\n(*This lemma establishes an equivalence, stating that the meet of two elements equals the second element if and only if the second element is less than or equal to the first.*)\nLemma eq_meetr x y : (x `&` y == y) = (y <= x).\n\n(*This lemma states that two properties are equivalent: the property that the meet of a first and a second element is equal to the first element, and the property that the first element is less than or equal to the second element.*)\nLemma meet_idPl {x y} : reflect (x `&` y = x) (x <= y).\n\n(*This lemma states that the property that the meet of a second and a first element equals the first element is equivalent to the property that the first element is less than or equal to the second.*)\nLemma meet_idPr {x y} : reflect (y `&` x = x) (x <= y).\n\n(*This lemma states that if a first element is less than or equal to a second element, their meet is equal to the first element.*)\nLemma meet_l x y : x <= y -> x `&` y = x. \n(*This lemma states that if a second element is less than or equal to a first element, their meet is equal to the second element.*)\nLemma meet_r x y : y <= x -> x `&` y = y. \n\n(*This lemma states that an element is less than or equal to the meet of itself and another element if and only if it is less than or equal to that other element.*)\nLemma leIidl x y : (x <= x `&` y) = (x <= y).\n\n(*This lemma states that an element is less than or equal to the meet of another element and itself if and only if it is less than or equal to that other element.*)\nLemma leIidr x y : (x <= y `&` x) = (x <= y).\n\n(*This lemma states that the meet operation is monotonic in both arguments: if a first element is less than or equal to a third, and a second element is less than or equal to a fourth, then the meet of the first and second elements is less than or equal to the meet of the third and fourth elements.*)\nLemma leI2 x y z t : x <= z -> y <= t -> x `&` y <= z `&` t.\n\n(*This lemma states that the meet operation is commutative.*)\nLemma meetC : commutative (@meet _ L).\n\n(*This lemma states that the meet operation is associative.*)\nLemma meetA : associative (@meet _ L).\n\n(*This lemma states that the meet operation is idempotent, meaning applying it to an element with itself yields the same element.*)\nLemma meetxx : idempotent_op (@meet _ L).\n\n(*This lemma states that the meet operation is right-commutative, meaning that the meet of a meet of two elements with a third is the same as the meet of the meet of the first and third elements with the second.*)\nLemma meetAC : right_commutative (@meet _ L).\n\n(*This lemma states that the meet operation is left-commutative, meaning that the meet of an element with the meet of two others is the same as the meet of the second element with the meet of the first and third.*)\nLemma meetCA : left_commutative (@meet _ L).\n\n(*This lemma states that the meet operation interchanges with itself, meaning the meet of two meets can be reordered by taking the meet of their first components and the meet of their second components.*)\nLemma meetACA : interchange (@meet _ L) (@meet _ L).\n\n(*This lemma provides an absorption law for the meet operation, stating that the meet of an element with the meet of itself and another element simplifies to the meet of the two elements.*)\nLemma meetKI y x : x `&` (x `&` y) = x `&` y.\n\n(*This lemma provides an absorption law for the meet operation, stating that the meet of a meet of two elements with the second element simplifies to the meet of the two original elements.*)\nLemma meetIK y x : (x `&` y) `&` y = x `&` y.\n\n(*This lemma provides an absorption law for the meet operation, stating that the meet of an element with the meet of another element and itself simplifies to the meet of the first and second elements.*)\nLemma meetKIC y x : x `&` (y `&` x) = x `&` y.\n\n(*This lemma provides an absorption law for the meet operation, stating that the meet of a second element, a first element, and the second element again simplifies to the meet of the first and second elements.*)\nLemma meetIKC y x : y `&` x `&` y = x `&` y.\n\nEnd MeetTheory.\nEnd MeetTheory.\n\nArguments meet_idPl {disp L x y}.\nArguments meet_idPr {disp L x y}.\n\nModule Import BMeetTheory.\nSection BMeetTheory.\nContext {disp : disp_t} {L : bMeetSemilatticeType disp}.\n\n(*This lemma states that the bottom element is a left annihilator for the meet operation; the meet of the bottom element and any other element results in the bottom element.*)\nLemma meet0x : left_zero \\bot (@meet _ L).\n\n(*This lemma states that the bottom element is a right annihilator for the meet operation; the meet of any element and the bottom element results in the bottom element.*)\nLemma meetx0 : right_zero \\bot (@meet _ L).\n\n(*This lemma states that the top element is a right identity for the meet operation; the meet of any element with the top element results in the original element.*)\nLemma meetx1 : right_id \\top (@meet _ L).\n\n(*This lemma states that the top element is a left identity for the meet operation; the meet of the top element with any element results in that element.*)\nLemma meet1x : left_id \\top (@meet _ L).\n\n(*This lemma states that the meet of two elements equals the top element if and only if both elements are individually equal to the top element.*)\nLemma meet_eq1 x y : (x `&` y == \\top) = (x == \\top) && (y == \\top).\n\n(*This lemma states that the iterated meet of values produced by applying a function to elements of a sequence that satisfy a predicate serves as a lower bound to any single one of those values.*)\nLemma meets_inf_seq T (r : seq T) (P : {pred T}) (F : T -> L) (x : T) :\n x \\in r -> P x -> \\meet_(i <- r | P i) F i <= F x.\n\n(*This lemma states that if an element of a sequence satisfies a predicate and its image under a function is less than or equal to a given element, then the meet of the function over all sequence elements satisfying the predicate is also less than or equal to that given element.*)\nLemma meets_max_seq T (r : seq T) (P : {pred T}) (F : T -> L) (x : T) (u : L) :\n x \\in r -> P x -> F x <= u -> \\meet_(x <- r | P x) F x <= u.\n\n(*This lemma states that the meet of a function over a set of indices satisfying a predicate is less than or equal to the function's value at any specific index that satisfies the predicate.*)\nLemma meets_inf I (j : I) (P : {pred I}) (F : I -> L) :\n P j -> \\meet_(i | P i) F i <= F j.\n\n(*This lemma states that if an index satisfies a predicate and the function's value at this index is less than or equal to a given element, then the meet of the function over all indices satisfying the predicate is also less than or equal to that given element.*)\nLemma meets_max I (j : I) (u : L) (P : {pred I}) (F : I -> L) :\n P j -> F j <= u -> \\meet_(i | P i) F i <= u.\n\n(*This lemma states that if an element is a lower bound for all values of a function over indices from a sequence that satisfy a predicate, then this element is also less than or equal to the meet of the function over those same indices.*)\nLemma meets_ge J (r : seq J) (P : {pred J}) (F : J -> L) (u : L) :\n (forall x : J, P x -> u <= F x) -> u <= \\meet_(x <- r | P x) F x.\n\n(*This lemma provides an equivalence, stating that an element is less than or equal to the meet of a function over a filtered finite sequence if and only if that element is a lower bound for the function's value at every point in the sequence that satisfies the filter's predicate.*)\nLemma meetsP_seq T (r : seq T) (P : {pred T}) (F : T -> L) (l : L) :\n reflect (forall x : T, x \\in r -> P x -> l <= F x)\n (l <= \\meet_(x <- r | P x) F x).\n\n(*This lemma provides an equivalence, stating that an element is less than or equal to the meet of a function over a filtered domain if and only if that element is a lower bound for the function's value at every point in the domain that satisfies the filter's predicate.*)\nLemma meetsP I (l : L) (P : {pred I}) (F : I -> L) :\n reflect (forall i : I, P i -> l <= F i) (l <= \\meet_(i | P i) F i).\n\n(*This lemma states that the meet of a function over a set of indices is greater than or equal to the meet of the same function over any superset of those indices.*)\nLemma le_meets I (A B : {set I}) (F : I -> L) :\n A \\subset B -> \\meet_(i in B) F i <= \\meet_(i in A) F i.\n\n(*This lemma states that the meet of a function over the union of two sets of indices is equal to the meet of the function's meet over the first set and its meet over the second set.*)\nLemma meets_setU I (A B : {set I}) (F : I -> L) :\n \\meet_(i in (A :|: B)) F i = \\meet_(i in A) F i `&` \\meet_(i in B) F i.\n\n(*This lemma states that the meet of a function's values for indices drawn from a finite sequence is identical to the meet of the function's values for indices drawn from the set of elements contained in that sequence.*)\nLemma meets_seq I (r : seq I) (F : I -> L) :\n \\meet_(i <- r) F i = \\meet_(i in r) F i.\n\nEnd TMeetTheory.\nEnd TMeetTheory.\n\nModule Import JoinTheory.\nSection JoinTheory.\nContext {disp : disp_t} {L : joinSemilatticeType disp}.\nImplicit Types (x y : L).\n\n(*This lemma states that the join of two elements is less than or equal to a third element if and only if both of the original two elements are less than or equal to the third element.*)\nLemma leUx x y z : (x `|` y <= z) = (x <= z) && (y <= z).\n\n(*This lemma states that an element is always less than or equal to the join of a second element with the first element.*)\nLemma leUr x y : x <= y `|` x. \n(*This lemma states that an element is always less than or equal to the join of itself with a second element.*)\nLemma leUl x y : x <= x `|` y. \n\n(*This lemma states that if a first element is less than or equal to a second, then the first element is also less than or equal to the join of the second element with a third.*)\nLemma lexUl x y z : x <= y -> x <= y `|` z.\n\n(*This lemma states that if a first element is less than or equal to a third, then the first element is also less than or equal to the join of a second element with the third.*)\nLemma lexUr x y z : x <= z -> x <= y `|` z.\n\n(*This lemma states that if an element is less than or equal to at least one of two other elements, then it is also less than or equal to their join.*)\nLemma lexU2 x y z : (x <= y) || (x <= z) -> x <= y `|` z.\n\n(*This lemma establishes an equivalence, stating that one element is less than or equal to another if and only if their join is equal to the second element.*)\nLemma leEjoin x y : (x <= y) = (x `|` y == y).\n\n(*This lemma establishes an equivalence, stating that the join of a first and a second element is equal to the first element if and only if the second element is less than or equal to the first.*)\nLemma eq_joinl x y : (x `|` y == x) = (y <= x).\n\n(*This lemma establishes an equivalence, stating that the join of a first and a second element is equal to the second element if and only if the first element is less than or equal to the second.*)\nLemma eq_joinr x y : (x `|` y == y) = (x <= y).\n\n(*This lemma provides a reflection property, showing that the proposition that the join of a second element and a first element equals the second element is logically equivalent to the proposition that the first element is less than or equal to the second.*)\nLemma join_idPl {x y} : reflect (y `|` x = y) (x <= y).\n\n(*This lemma provides a reflection property, showing that the proposition that the join of a first element and a second element equals the second element is logically equivalent to the proposition that the first element is less than or equal to the second.*)\nLemma join_idPr {x y} : reflect (x `|` y = y) (x <= y).\n\n(*This lemma states that if a second element is less than or equal to a first element, then their join is equal to the first element.*)\nLemma join_l x y : y <= x -> x `|` y = x. \n(*This lemma states that if a first element is less than or equal to a second element, then their join is equal to the second element.*)\nLemma join_r x y : x <= y -> x `|` y = y. \n\n(*This lemma establishes the equivalence between the statement that the join of two elements is less than or equal to the second element, and the statement that the first element is less than or equal to the second.*)\nLemma leUidl x y : (x `|` y <= y) = (x <= y).\n\n(*This lemma establishes the equivalence between the statement that the join of a second element with a first is less than or equal to the second element, and the statement that the first element is less than or equal to the second.*)\nLemma leUidr x y : (y `|` x <= y) = (x <= y).\n\n(*This lemma states that the join operation is monotonic in both of its arguments: if a first element is less than or equal to a third, and a second element is less than or equal to a fourth, then the join of the first and second elements is less than or equal to the join of the third and fourth.*)\nLemma leU2 x y z t : x <= z -> y <= t -> x `|` y <= z `|` t.\n\n(*This lemma states that the join operation is commutative.*)\nLemma joinC : commutative (@join _ L). \n(*This lemma states that the join operation is associative.*)\nLemma joinA : associative (@join _ L). \n\n(*This lemma states that the join operation is idempotent, meaning the join of an element with itself is the element itself.*)\nLemma joinxx : idempotent_op (@join _ L).\n\n(*This lemma states that the join operation is right-commutative, meaning that joining two elements and then joining the result with a third is the same as joining the first and third elements and then joining that result with the second.*)\nLemma joinAC : right_commutative (@join _ L).\n\n(*This lemma states that the join operation is left-commutative, meaning that joining a first element with the join of a second and third is the same as joining the second element with the join of the first and third.*)\nLemma joinCA : left_commutative (@join _ L).\n\n(*This lemma states that for any three elements, the join of the join of the first two with the third is equal to the join of the join of the first and third with the second, which is a property derived from associativity and commutativity.*)\nLemma joinACA : interchange (@join _ L) (@join _ L).\n\n(*This lemma states that the join of an element with the join of itself and another element is equal to the join of the two elements.*)\nLemma joinKU y x : x `|` (x `|` y) = x `|` y.\n\n(*This lemma states that the join of the join of two elements with the second element is equal to the join of the two elements.*)\nLemma joinUK y x : (x `|` y) `|` y = x `|` y.\n\n(*This lemma states that the join of an element with the join of another element and itself is equal to the join of the two initial elements.*)\nLemma joinKUC y x : x `|` (y `|` x) = x `|` y.\n\n(*This lemma states that for any two elements, the join of the join of the second element with the first, with that second element, is equal to the join of the first element with the second.*)\nLemma joinUKC y x : y `|` x `|` y = x `|` y.\n\nEnd JoinTheory.\nEnd JoinTheory.\n\nArguments join_idPl {disp L x y}.\nArguments join_idPr {disp L x y}.\n\nModule Import BJoinTheory.\nSection BJoinTheory.\nContext {disp : disp_t} {L : bJoinSemilatticeType disp}.\nImplicit Types (I : finType) (T : eqType) (x y : L).\n\n(*This lemma states that the bottom element is a right identity for the join operation, meaning that the join of any element with the bottom element is the element itself.*)\nLemma joinx0 : right_id \\bot (@join _ L).\n\n(*This lemma states that the bottom element is a left identity for the join operation, meaning that the join of the bottom element with any element is that element itself.*)\nLemma join0x : left_id \\bot (@join _ L).\n\n(*This lemma states that the join of two elements is equal to the bottom element if and only if both elements are individually equal to the bottom element.*)\nLemma join_eq0 x y : (x `|` y == \\bot) = (x == \\bot) && (y == \\bot).\n\n(*This lemma states that for a finite sequence of elements, a function, and a predicate, if an element is in the sequence and satisfies the predicate, then the function applied to that element is less than or equal to the join of the function applied to all elements in the sequence that satisfy the predicate.*)\nLemma joins_sup_seq T (r : seq T) (P : {pred T}) (F : T -> L) (x : T) :\n x \\in r -> P x -> F x <= \\join_(i <- r | P i) F i.\n\n(*This lemma states that for a finite sequence of elements, a function, and a predicate, if a given value is less than or equal to the function applied to an element that is in the sequence and satisfies the predicate, then that value is also less than or equal to the join of the function applied to all elements in the sequence that satisfy the predicate.*)\nLemma joins_min_seq T (r : seq T) (P : {pred T}) (F : T -> L) (x : T) (l : L) :\n x \\in r -> P x -> l <= F x -> l <= \\join_(x <- r | P x) F x.\n\n(*This lemma states that for a finite type, a function, and a predicate, if an element of the type satisfies the predicate, then the function applied to that element is less than or equal to the join of the function applied to all elements of the type that satisfy the predicate.*)\nLemma joins_sup I (j : I) (P : {pred I}) (F : I -> L) :\n P j -> F j <= \\join_(i | P i) F i.\n\n(*This lemma states that for a finite type, a function, and a predicate, if a given value is less than or equal to the function applied to an element that satisfies the predicate, then that value is also less than or equal to the join of the function applied to all elements of the type that satisfy the predicate.*)\nLemma joins_min I (j : I) (l : L) (P : {pred I}) (F : I -> L) :\n P j -> l <= F j -> l <= \\join_(i | P i) F i.\n\n(*This lemma states that for a finite sequence, a function, and a predicate, if a given value is an upper bound for the function applied to all elements in the sequence that satisfy the predicate, then that value is also an upper bound for the join of those function values.*)\nLemma joins_le J (r : seq J) (P : {pred J}) (F : J -> L) (u : L) :\n (forall x : J, P x -> F x <= u) -> \\join_(x <- r | P x) F x <= u.\n\n(*This lemma establishes an equivalence: the join of a function over a filtered finite sequence is less than or equal to a given value if and only if that value is an upper bound for the function applied to every element in the sequence that satisfies the filter condition.*)\nLemma joinsP_seq T (r : seq T) (P : {pred T}) (F : T -> L) (u : L) :\n reflect (forall x : T, x \\in r -> P x -> F x <= u)\n (\\join_(x <- r | P x) F x <= u).\n\n(*This lemma establishes an equivalence: the join of a function over a filtered finite type is less than or equal to a given value if and only if that value is an upper bound for the function applied to every element of the type that satisfies the filter condition.*)\nLemma joinsP I (u : L) (P : {pred I}) (F : I -> L) :\n reflect (forall i : I, P i -> F i <= u) (\\join_(i | P i) F i <= u).\n\n(*This lemma states that for a given function, the join of its values over a set of indices is less than or equal to the join of its values over any superset of those indices.*)\nLemma le_joins I (A B : {set I}) (F : I -> L) :\n A \\subset B -> \\join_(i in A) F i <= \\join_(i in B) F i.\n\n(*This lemma states that for a given function, the join of its values over the union of two sets of indices is equal to the join of the join over the first set and the join over the second set.*)\nLemma joins_setU I (A B : {set I}) (F : I -> L) :\n \\join_(i in (A :|: B)) F i = \\join_(i in A) F i `|` \\join_(i in B) F i.\n\n(*This lemma states that for a given function, the join of its values over a finite sequence is equal to the join of its values over the set of unique elements contained in that sequence.*)\nLemma joins_seq I (r : seq I) (F : I -> L) :\n \\join_(i <- r) F i = \\join_(i in r) F i.\n\nEnd BJoinTheory.\nEnd BJoinTheory.\n\nModule Import TJoinTheory.\nSection TJoinTheory.\nContext {disp : disp_t} {L : tJoinSemilatticeType disp}.\n\n(*This lemma states that the top element is a right absorbing element for the join operation, meaning that the join of any element with the top element is the top element itself.*)\nLemma joinx1 : right_zero \\top (@join _ L). \n(*This lemma states that the top element is a left absorbing element for the join operation, meaning that the join of the top element with any element is that element itself.*)\nLemma join1x : left_zero \\top (@join _ L). \n\n(*This lemma states one of the lattice absorption laws: the join of the meet of two elements with the second element is equal to the second element.*)\nLemma meetUK x y : (x `&` y) `|` y = y. \n(*This lemma states a commutative variant of a lattice absorption law: for any two elements, the join of their meet, taken in reverse order, with the second element is equal to that second element.*)\nLemma meetUKC x y : (y `&` x) `|` y = y. \n(*This lemma states another lattice absorption law: the join of an element with the meet of another element and itself is equal to the original element.*)\nLemma meetKUC y x : x `|` (y `&` x) = x. \n(*This lemma states one of the standard lattice absorption laws: the join of an element with the meet of itself and another element is equal to the first element.*)\nLemma meetKU y x : x `|` (x `&` y) = x. \n\n(*This lemma states a dual lattice absorption law: the meet of the join of two elements with the second element is equal to the second element.*)\nLemma joinIK x y : (x `|` y) `&` y = y. \n(*This lemma states a commutative variant of a dual lattice absorption law: for any two elements, the meet of their join, taken in reverse order, with the second element is equal to that second element.*)\nLemma joinIKC x y : (y `|` x) `&` y = y. \n(*This lemma states another dual lattice absorption law: the meet of an element with the join of another element and itself is equal to the original element.*)\nLemma joinKIC y x : x `&` (y `|` x) = x. \n(*This lemma states one of the standard lattice absorption laws: the meet of an element with the join of itself and another element is equal to that first element.*)\nLemma joinKI y x : x `&` (x `|` y) = x. \n\n(*This lemma provides a reflection property, proving that two elements in a lattice are comparable by evaluating a comprehensive set of boolean predicates involving their order relations, equality, minimum, maximum, meet, and join.*)\nLemma lcomparableP x y : incomparel x y\n (min y x) (min x y) (max y x) (max x y)\n (y `&` x) (x `&` y) (y `|` x) (x `|` y)\n (y == x) (x == y) (x >= y) (x <= y) (x > y) (x < y) (y >=< x) (x >=< y).\n\n(*This lemma states that if two elements are comparable, then the logical disjunction of one being strictly less than the other, the other being strictly less than the first, or the two being equal, is reflected by the equivalent boolean disjunction.*)\nLemma lcomparable_ltgtP x y : x >=< y ->\n comparel x y (min y x) (min x y) (max y x) (max x y)\n (y `&` x) (x `&` y) (y `|` x) (x `|` y)\n (y == x) (x == y) (x >= y) (x <= y) (x > y) (x < y).\n\n(*This lemma states that for any two comparable elements in a lattice, it is the case that either the first element is less than or equal to the second, or the second element is strictly less than the first, but not both.*)\nLemma lcomparable_leP x y : x >=< y ->\n lel_xor_gt x y (min y x) (min x y) (max y x) (max x y)\n (y `&` x) (x `&` y) (y `|` x) (x `|` y) (x <= y) (y < x).\n\n(*This lemma states that for any two comparable elements in a lattice, it is the case that either the second element is less than or equal to the first, or the first element is strictly less than the second, but not both.*)\nLemma lcomparable_ltP x y : x >=< y ->\n ltl_xor_ge x y (min y x) (min x y) (max y x) (max x y)\n (y `&` x) (x `&` y) (y `|` x) (x `|` y) (y <= x) (x < y).\n\nEnd LatticeTheory.\nEnd LatticeTheory.\n\nModule Import DistrLatticeTheory.\nSection DistrLatticeTheory.\nContext {disp : disp_t} {L : distrLatticeType disp}.\n\n(*This lemma states that in a distributive lattice, the meet operation distributes over the join operation from the left.*)\nLemma meetUl : left_distributive (@meet _ L) (@join _ L).\n\n(*This lemma states that in a distributive lattice, the meet operation distributes over the join operation from the right.*)\nLemma meetUr : right_distributive (@meet _ L) (@join _ L).\n\n(*This lemma states that in a distributive lattice, the join operation distributes over the meet operation from the left.*)\nLemma joinIl : left_distributive (@join _ L) (@meet _ L).\n\n(*This lemma states that in a distributive lattice, the join operation distributes over the meet operation from the right.*)\nLemma joinIr : right_distributive (@join _ L) (@meet _ L).\n\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := Monoid.isAddLaw.Build L meet join meetUl meetUr.\n(*This lemma states that in a bounded distributive lattice, if the meet of a first and second element is the bottom element, and the join of the first element and a third element is less than or equal to the join of a fourth element and the second element, then the first element is less than or equal to the fourth element.*)\nLemma leU2l_le y t x z : x `&` t = \\bot -> x `|` y <= z `|` t -> x <= z.\n\n(*This lemma states that in a bounded distributive lattice, if the meet of a first and second element is the bottom element, and the join of a third element and the first element is less than or equal to the join of the second element and a fourth element, then the first element is less than or equal to the fourth element.*)\nLemma leU2r_le y t x z : x `&` t = \\bot -> y `|` x <= t `|` z -> x <= z.\n\n(*This lemma states that in a bounded distributive lattice, if two elements are disjoint, meaning their meet is the bottom element, then the proposition that the first element is less than or equal to the join of a third element and the second element is equivalent to the proposition that the first element is less than or equal to the third element.*)\nLemma disjoint_lexUl z x y : x `&` z = \\bot -> (x <= y `|` z) = (x <= y).\n\n(*This lemma states that in a bounded distributive lattice, if two elements are disjoint, meaning their meet is the bottom element, then the proposition that the first element is less than or equal to the join of the second element and a third element is equivalent to the proposition that the first element is less than or equal to the third element.*)\nLemma disjoint_lexUr z x y : x `&` z = \\bot -> (x <= z `|` y) = (x <= y).\n\n(*This lemma provides an equivalence for comparing joins of disjoint pairs in a bounded distributive lattice. It states that if a first element is disjoint from a second, and a third element is disjoint from a fourth, then the join of the first and third elements is less than or equal to the join of the fourth and second elements if and only if the first element is less than or equal to the fourth and the third element is less than or equal to the second.*)\nLemma leU2E x y z t : x `&` t = \\bot -> y `&` z = \\bot ->\n (x `|` y <= z `|` t) = (x <= z) && (y <= t).\n\n(*This lemma states that in a bounded distributive lattice, if an element is disjoint from every element in a finite indexed family of elements, then it is also disjoint from their join.*)\nLemma joins_disjoint (I : finType) (d : L) (P : {pred I}) (F : I -> L) :\n (forall i : I, P i -> d `&` F i = \\bot) -> d `&` \\join_(i | P i) F i = \\bot.\n\nEnd BDistrLatticeTheory.\nEnd BDistrLatticeTheory.\n\nModule Import TDistrLatticeTheory.\nSection TDistrLatticeTheory.\nContext {disp : disp_t} {L : tDistrLatticeType disp}.\nImplicit Types (x y : L).\n\n(*This lemma provides a condition for inferring an inequality in a distributive lattice with a top element. It states that if the join of a first and a second element is the top element, and the meet of a third element with the first is less than or equal to the meet of the second element with a fourth, then the third element is less than or equal to the second element.*)\nLemma leI2l_le y t x z : y `|` z = \\top -> x `&` y <= z `&` t -> x <= z.\n\n(*This lemma provides a condition for inferring an inequality in a distributive lattice with a top element. It states that if the join of a first and a second element is the top element, and the meet of the first element with a third is less than or equal to the meet of a fourth element with the second, then the third element is less than or equal to the second element.*)\nLemma leI2r_le y t x z : y `|` z = \\top -> y `&` x <= t `&` z -> x <= z.\n\n(*This lemma states that in a distributive lattice with a top element, if the join of a first and a second element is the top element, then the proposition that the meet of a third element and the first element is less than or equal to the second element is equivalent to the proposition that the third element is less than or equal to the second element.*)\nLemma cover_leIxl z x y : z `|` y = \\top -> (x `&` z <= y) = (x <= y).\n\n(*This lemma states that in a distributive lattice with a top element, if the join of a first and a second element is the top element, then the proposition that the meet of the first element and a third element is less than or equal to the second element is equivalent to the proposition that the third element is less than or equal to the second element.*)\nLemma cover_leIxr z x y : z `|` y = \\top -> (z `&` x <= y) = (x <= y).\n\n(*This lemma relates a comparison of meets to a conjunction of comparisons in a distributive lattice with a top element. Given four elements such that the first and second join to the top element, and the third and fourth also join to the top element, it asserts that the meet of the first and third is less than or equal to the meet of the fourth and second if and only if the first is less than or equal to the fourth and the third is less than or equal to the second.*)\nLemma leI2E x y z t : x `|` t = \\top -> y `|` z = \\top ->\n (x `&` y <= z `&` t) = (x <= z) && (y <= t).\n\n(*This lemma states that in a distributive lattice with a top element, if an element joins to the top with every element in a finite indexed family of elements, then it also joins to the top with their meet.*)\nLemma meets_total (I : finType) (d : L) (P : {pred I}) (F : I -> L) :\n (forall i : I, P i -> d `|` F i = \\top) -> d `|` \\meet_(i | P i) F i = \\top.\n\nEnd TDistrLatticeTheory.\nEnd TDistrLatticeTheory.\n\nModule Import TotalTheory.\nSection TotalTheory.\nContext {disp : disp_t} {T : orderType disp}.\nImplicit Types (x y z t : T) (s : seq T).\n\n(*This lemma states that the less-than-or-equal-to relation on a totally ordered type is total, meaning that for any pair of elements, one is less than or equal to the other.*)\nDefinition le_total : total (<=%O : rel T) := le_total.\nHint Resolve le_total : core.\n\n(*This lemma states that the greater-than-or-equal-to relation on a totally ordered type is total, meaning that for any pair of elements, one is greater than or equal to the other.*)\nLemma ge_total : total (>=%O : rel T).\n\nHint Resolve ge_total : core.\n\n(*This lemma states that any two elements in a totally ordered type are comparable, meaning one is less than or equal to the other.*)\nLemma comparableT x y : x >=< y. \nHint Extern 0 (is_true (_ >=< _)%O) => solve [apply: comparableT] : core.\n\n(*This lemma states that the result of sorting any given finite sequence of elements is a sequence that is sorted with respect to the less-than-or-equal-to relation.*)\nLemma sort_le_sorted s : sorted <=%O (sort <=%O s).\n\nHint Resolve sort_le_sorted : core.\n\n(*This lemma asserts that applying a strict sorting filter to a sequence that has been sorted by the less-than-or-equal-to relation yields the sequence of unique elements from the original sequence.*)\nLemma sort_lt_sorted s : sorted <%O (sort <=%O s) = uniq s.\n\n(*This lemma establishes that two finite sequences are permutations of each other if and only if their versions sorted by the less-than-or-equal-to relation are identical.*)\nLemma perm_sort_leP s1 s2 : reflect (sort <=%O s1 = sort <=%O s2) (perm_eq s1 s2).\n\n(*This lemma states that for any given predicate and any finite sequence, filtering the sequence after it has been sorted by the less-than-or-equal-to relation is equivalent to sorting the sequence after it has been filtered.*)\nLemma filter_sort_le p s : filter p (sort <=%O s) = sort <=%O (filter p s).\n\n(*This lemma asserts that for any finite sequence and any bitmask, there exists another bitmask such that masking the sorted version of the sequence with this new bitmask yields the same result as sorting the sequence after it has been masked with the original bitmask.*)\nLemma mask_sort_le s (m : bitseq) :\n {m_s : bitseq | mask m_s (sort <=%O s) = sort <=%O (mask m s)}.\n\n(*This lemma states that if masking a finite sequence with a bitmask results in a sequence that is already sorted, then there exists another bitmask which, when applied to the sorted version of the original sequence, reproduces the initially masked sequence.*)\nLemma sorted_mask_sort_le s (m : bitseq) :\n sorted <=%O (mask m s) -> {m_s : bitseq | mask m_s (sort <=%O s) = mask m s}.\n\n(*This lemma asserts that the sorting operation is a homomorphism from the multiset inclusion relation to the subsequence relation; if a first finite sequence is a multiset sub-bag of a second, its sorted version is a subsequence of the second's sorted version.*)\nLemma subseq_sort_le : {homo sort <=%O : s1 s2 / @subseq T s1 s2}.\n\n(*This lemma states that if a finite sequence is already sorted with respect to the less-than-or-equal-to relation and is a subsequence of a second finite sequence, then the first sequence is also a subsequence of the sorted version of the second sequence.*)\nLemma sorted_subseq_sort_le s1 s2 :\n subseq s1 s2 -> sorted <=%O s1 -> subseq s1 (sort <=%O s2).\n\n(*This lemma states that if a first element is less than or equal to a second element, and both elements are members of a given finite sequence, then both elements will also be members of the sequence after it has been sorted.*)\nLemma mem2_sort_le s x y : x <= y -> mem2 s x y -> mem2 (sort <=%O s) x y.\n\n(*This lemma states that the proposition 'a first element is less than or equal to a second element' is logically equivalent to the double negation of the proposition 'the second element is strictly less than the first element'.*)\nLemma leNgt x y : (x <= y) = ~~ (y < x). \n\n(*This lemma states that the proposition 'a first element is strictly less than a second element' is logically equivalent to the double negation of the proposition 'the second element is less than or equal to the first element'.*)\nLemma ltNge x y : (x < y) = ~~ (y <= x). \n\n(*This definition provides a decidable test for whether a first element is strictly less than a second element or, conversely, the second is strictly less than the first, for any two comparable elements.*)\nDefinition ltgtP x y := LatticeTheory.lcomparable_ltgtP (comparableT x y).\n(*This definition provides a decidable test for whether a first element is less than or equal to a second element or, conversely, the second is strictly less than the first, for any two comparable elements.*)\nDefinition leP x y := LatticeTheory.lcomparable_leP (comparableT x y).\n(*This definition provides a decidable test for whether a first element is strictly less than a second element or, conversely, the second is less than or equal to the first, for any two comparable elements.*)\nDefinition ltP x y := LatticeTheory.lcomparable_ltP (comparableT x y).\n\n(*This lemma provides a 'without loss of generality' proof principle for properties of two elements in a totally ordered type. It states that to prove a property holds for any two elements, it is sufficient to prove it for the case where the first element is less than or equal to the second, provided the property is also shown to be symmetric.*)\nLemma wlog_le P :\n (forall x y, P y x -> P x y) -> (forall x y, x <= y -> P x y) ->\n forall x y, P x y.\n\n(*This lemma provides a 'without loss of generality' proof principle for properties of two elements in a totally ordered type. It states that to prove a property holds for any two elements, it is sufficient to prove it for the case where the elements are equal, for the case where the first element is strictly less than the second, and to show that the property is symmetric.*)\nLemma wlog_lt P :\n (forall x, P x x) ->\n (forall x y, (P y x -> P x y)) -> (forall x y, x < y -> P x y) ->\n forall x y, P x y.\n\n(*This lemma states that for any two elements in a totally ordered type, the proposition that they are not equal is equivalent to the proposition that either the first element is strictly less than the second or the second element is strictly less than the first.*)\nLemma neq_lt x y : (x != y) = (x < y) || (y < x). \n\n(*This lemma asserts the property of trichotomy for totally ordered types, stating that if two distinct elements are given, then either the first is strictly less than the second, or the second is strictly less than the first.*)\nLemma lt_total x y : x != y -> (x < y) || (y < x). \n\n(*This lemma provides a logical principle for establishing the equivalence of two less-than-or-equal-to propositions. It states that the proposition 'a first element is less than or equal to a second' is equivalent to 'a third element is less than or equal to a fourth' if it can be shown that the first proposition implies the second, and that the strict inequality of the second and first elements implies the strict inequality of the fourth and third elements.*)\nLemma eq_leLR x y z t :\n (x <= y -> z <= t) -> (y < x -> t < z) -> (x <= y) = (z <= t).\n\n(*This lemma provides a logical principle for establishing the equivalence of two less-than-or-equal-to propositions. It states that the proposition 'a third element is less than or equal to a fourth' is equivalent to 'a first element is less than or equal to a second' if it can be shown that the first proposition implies the second, and that the strict inequality of the second and first elements implies the strict inequality of the fourth and third elements.*)\nLemma eq_leRL x y z t :\n (x <= y -> z <= t) -> (y < x -> t < z) -> (z <= t) = (x <= y).\n\n(*This lemma provides a logical principle for establishing the equivalence of two strict less-than propositions. It states that the proposition 'a first element is strictly less than a second' is equivalent to 'a third element is strictly less than a fourth' if it can be shown that the first proposition implies the second, and that the non-strict inequality of the second and first elements implies the non-strict inequality of the fourth and third elements.*)\nLemma eq_ltLR x y z t :\n (x < y -> z < t) -> (y <= x -> t <= z) -> (x < y) = (z < t).\n\n(*This lemma provides a logical principle for establishing the equivalence of two strict less-than propositions. It states that the proposition 'a third element is strictly less than a fourth' is equivalent to 'a first element is strictly less than a second' if it can be shown that the first proposition implies the second, and that the non-strict inequality of the second and first elements implies the non-strict inequality of the fourth and third elements.*)\nLemma eq_ltRL x y z t :\n (x < y -> z < t) -> (y <= x -> t <= z) -> (z < t) = (x < y).\n\n(*This lemma states that in a totally ordered type that also forms a lattice, the meet operation on any two elements is equivalent to taking their minimum.*)\nLemma meetEtotal x y : x `&` y = min x y. \n(*This lemma states that in a totally ordered type that also forms a lattice, the join operation on any two elements is equivalent to taking their maximum.*)\nLemma joinEtotal x y : x `|` y = max x y. \n\n(*This lemma provides an explicit definition for the minimum of two elements: it is the second element if the first is strictly greater than the second, and the first element otherwise.*)\nLemma minEgt x y : min x y = if x > y then y else x. \n(*This lemma states that the maximum of two elements is the first element if it is strictly greater than the second, and the second element otherwise.*)\nLemma maxEgt x y : max x y = if x > y then x else y. \n(*This lemma states that the minimum of two elements is the second element if the first is greater than or equal to the second, and the first element otherwise.*)\nLemma minEge x y : min x y = if x >= y then y else x. \n(*This lemma states that the maximum of two elements is the first element if it is greater than or equal to the second, and the second element otherwise.*)\nLemma maxEge x y : max x y = if x >= y then x else y. \n\n(*This lemma states that the minimum operation is commutative, meaning the order of the two input elements does not affect the result.*)\nLemma minC : commutative (min : T -> T -> T).\n\n(*This lemma states that the maximum operation is commutative, meaning the order of the two input elements does not affect the result.*)\nLemma maxC : commutative (max : T -> T -> T).\n\n(*This lemma states that the minimum operation is associative, meaning that when taking the minimum of three elements, the grouping of operations does not change the result.*)\nLemma minA : associative (min : T -> T -> T).\n\n(*This lemma states that the maximum operation is associative, meaning that when taking the maximum of three elements, the grouping of operations does not change the result.*)\nLemma maxA : associative (max : T -> T -> T).\n\n(*This lemma states that the minimum operation is right-commutative, meaning that taking the minimum of an element with the minimum of two other elements is the same as taking the minimum of the second element with the minimum of the first and third elements.*)\nLemma minAC : right_commutative (min : T -> T -> T).\n\n(*This lemma states that the maximum operation is right-commutative, meaning that taking the maximum of an element with the maximum of two other elements is the same as taking the maximum of the second element with the maximum of the first and third elements.*)\nLemma maxAC : right_commutative (max : T -> T -> T).\n\n(*This lemma states that the minimum operation is left-commutative, meaning that taking the minimum of the minimum of two elements with a third element is the same as taking the minimum of the minimum of the first and third elements with the second element.*)\nLemma minCA : left_commutative (min : T -> T -> T).\n\n(*This lemma states that the maximum operation is left-commutative, meaning that taking the maximum of the maximum of two elements with a third element is the same as taking the maximum of the maximum of the first and third elements with the second element.*)\nLemma maxCA : left_commutative (max : T -> T -> T).\n\n(*This lemma states that the minimum operation interchanges with itself, meaning the minimum of two separate minimums can be re-grouped by taking the minimum of the first elements of each pair and the minimum of the second elements of each pair.*)\nLemma minACA : interchange (min : T -> T -> T) min.\n\n(*This lemma states that the maximum operation interchanges with itself, meaning the maximum of two separate maximums can be re-grouped by taking the maximum of the first elements of each pair and the maximum of the second elements of each pair.*)\nLemma maxACA : interchange (max : T -> T -> T) max.\n\n(*This lemma states that the boolean statement 'the minimum of two elements is equal to the second element' is equivalent to the boolean statement 'the second element is less than or equal to the first element'.*)\nLemma eq_minr x y : (min x y == y) = (y <= x).\n\n(*This lemma states that the boolean statement 'the maximum of two elements is equal to the first element' is equivalent to the boolean statement 'the second element is less than or equal to the first element'.*)\nLemma eq_maxl x y : (max x y == x) = (y <= x).\n\n(*This lemma states that the proposition that the minimum of two elements is equal to the second element holds if and only if the second element is less than or equal to the first.*)\nLemma min_idPr x y : reflect (min x y = y) (y <= x).\n\n(*This lemma states that the proposition that the maximum of two elements is equal to the first element holds if and only if the second element is less than or equal to the first.*)\nLemma max_idPl x y : reflect (max x y = x) (y <= x).\n\n(*This lemma states that an element is less than or equal to the minimum of two other elements if and only if it is less than or equal to both of those elements.*)\nLemma le_min z x y : (z <= min x y) = (z <= x) && (z <= y).\n\n(*This lemma states that for totally ordered types, the minimum of two elements is less than or equal to a third element if and only if at least one of the original two elements is less than or equal to the third.*)\nLemma ge_min z x y : (min x y <= z) = (x <= z) || (y <= z).\n\n(*This lemma states that an element is strictly less than the minimum of two other elements if and only if it is strictly less than both of those elements.*)\nLemma lt_min z x y : (z < min x y) = (z < x) && (z < y).\n\n(*This lemma states that for totally ordered types, the minimum of two elements is strictly less than a third element if and only if at least one of the original two elements is strictly less than the third.*)\nLemma gt_min z x y : (min x y < z) = (x < z) || (y < z).\n\n(*This lemma states that for totally ordered types, an element is less than or equal to the maximum of two other elements if and only if it is less than or equal to at least one of those elements.*)\nLemma le_max z x y : (z <= max x y) = (z <= x) || (z <= y).\n\n(*This lemma states that the maximum of two elements is less than or equal to a third element if and only if both of the original two elements are less than or equal to the third.*)\nLemma ge_max z x y : (max x y <= z) = (x <= z) && (y <= z).\n\n(*This lemma states that for totally ordered types, an element is strictly less than the maximum of two other elements if and only if it is strictly less than at least one of those elements.*)\nLemma lt_max z x y : (z < max x y) = (z < x) || (z < y).\n\n(*This lemma states that the maximum of two elements is strictly less than a third element if and only if both of the original two elements are strictly less than the third.*)\nLemma gt_max z x y : (max x y < z) = (x < z) && (y < z).\n\n(*This lemma states an absorption law: the maximum of the minimum of two elements and the second of those two elements simplifies to the second element.*)\nLemma minxK x y : max (min x y) y = y. \n(*This lemma states an absorption law: the maximum of the first of two elements and the minimum of both elements simplifies to the first element.*)\nLemma minKx x y : max x (min x y) = x. \n(*This lemma states an absorption law: the minimum of the maximum of two elements and the second of those two elements simplifies to the second element.*)\nLemma maxxK x y : min (max x y) y = y. \n(*This lemma states an absorption law: the minimum of the first of two elements and the maximum of both elements simplifies to the first element.*)\nLemma maxKx x y : min x (max x y) = x. \n\n(*This lemma states that the maximum operation distributes over the minimum operation from the left, meaning the maximum of an element and the minimum of two others is equal to the minimum of the maximums of the first element with each of the other two.*)\nLemma max_minl : left_distributive (max : T -> T -> T) min.\n\n(*This lemma states that for any three elements of an ordered type that forms a lattice, the minimum of the first element and the maximum of the other two is equal to the maximum of two values: the minimum of the first and second elements, and the minimum of the first and third elements.*)\nLemma min_maxl : left_distributive (min : T -> T -> T) max.\n\n(*This lemma states that for any three elements of an ordered type that forms a lattice, the maximum of the minimum of the first two elements and a third element is equal to the minimum of two values: the maximum of the first and third elements, and the maximum of the second and third elements.*)\nLemma max_minr : right_distributive (max : T -> T -> T) min.\n\n(*This lemma states that for any three elements of an ordered type that forms a lattice, the minimum of the maximum of the first two elements and a third element is equal to the maximum of two values: the minimum of the first and third elements, and the minimum of the second and third elements.*)\nLemma min_maxr : right_distributive (min : T -> T -> T) max.\n\nHB.instance Definition _ := SemiGroup.isComLaw.Build T max maxA maxC.\n(*This lemma states that for any three elements of a lattice-ordered type, the meet (minimum) of the second and third elements is less than or equal to the first element if and only if the second element is less than or equal to the first element, or the third element is less than or equal to the first element.*)\nLemma leIx x y z : (meet y z <= x) = (y <= x) || (z <= x).\n\n(*This lemma states that for any three elements of a lattice-ordered type, the first element is less than or equal to the join (maximum) of the second and third elements if and only if the first element is less than or equal to the second element, or the first element is less than or equal to the third element.*)\nLemma lexU x y z : (x <= join y z) = (x <= y) || (x <= z).\n\n(*This lemma states that for any three elements of a lattice-ordered type, the first element is strictly less than the meet (minimum) of the second and third elements if and only if the first element is strictly less than both the second and third elements.*)\nLemma ltxI x y z : (x < meet y z) = (x < y) && (x < z).\n\n(*This lemma states that for any three elements of a lattice-ordered type, the meet (minimum) of the second and third elements is strictly less than the first element if and only if the second element is strictly less than the first element, or the third element is strictly less than the first element.*)\nLemma ltIx x y z : (meet y z < x) = (y < x) || (z < x).\n\n(*This lemma states that for any three elements of a lattice-ordered type, the first element is strictly less than the join (maximum) of the second and third elements if and only if the first element is strictly less than the second element, or the first element is strictly less than the third element.*)\nLemma ltxU x y z : (x < join y z) = (x < y) || (x < z).\n\n(*This lemma states that for any three elements of a lattice-ordered type, the join (maximum) of the second and third elements is strictly less than the first element if and only if both the second and third elements are strictly less than the first element.*)\nLemma ltUx x y z : (join y z < x) = (y < x) && (z < x).\n\n(*This definition creates a pair of lemmas for reasoning about an element in relation to a meet. The first lemma asserts that an element is less than or equal to the meet of two others if and only if it is less than or equal to both. The second lemma asserts that an element is strictly less than the meet of two others if and only if it is strictly less than both.*)\nDefinition ltexI := (@lexI _ T, ltxI).\n(*This definition creates a pair of lemmas for reasoning about a meet in relation to an element. The first lemma asserts that the meet of two elements is less than or equal to a third if and only if at least one of the two elements is less than or equal to the third. The second lemma asserts that the meet of two elements is strictly less than a third if and only if at least one of the two elements is strictly less than the third.*)\nDefinition lteIx := (leIx, ltIx).\n(*This definition creates a pair of lemmas for reasoning about an element in relation to a join. The first lemma asserts that an element is less than or equal to the join of two others if and only if it is less than or equal to at least one of them. The second lemma asserts that an element is strictly less than the join of two others if and only if it is strictly less than at least one of them.*)\nDefinition ltexU := (lexU, ltxU).\n(*This definition creates a pair of lemmas for reasoning about a join in relation to an element. The first lemma asserts that the join of two elements is less than or equal to a third if and only if both elements are less than or equal to the third. The second lemma asserts that the join of two elements is strictly less than a third if and only if both elements are strictly less than the third.*)\nDefinition lteUx := (@leUx _ T, ltUx).\n\n(*This lemma states that the minimum operation is monotone. Specifically, if a first element is less than or equal to a third element, and a second element is less than or equal to a fourth element, then the minimum of the first and second elements is less than or equal to the minimum of the third and fourth elements.*)\nLemma le_min2 x y z t : x <= z -> y <= t -> Order.min x y <= Order.min z t.\n\n(*This lemma states that the maximum operation is monotone. Specifically, if a first element is less than or equal to a third element, and a second element is less than or equal to a fourth element, then the maximum of the first and second elements is less than or equal to the maximum of the third and fourth elements.*)\nLemma le_max2 x y z t : x <= z -> y <= t -> Order.max x y <= Order.max z t.\n\n(*This lemma states an equivalence between two conditional boolean expressions involving strict inequality. It asserts that the expression 'if a boolean condition is true then a first element is strictly less than a second, otherwise true' is equal to the expression 'if the same boolean condition is true then the second element is strictly less than the first, otherwise true'.*)\nLemma lteifNE x y C : x < y ?<= if ~~ C = ~~ (y < x ?<= if C).\n\n(*This lemma shows how a conditional strict inequality check distributes over a minimum on the right. It states that checking if an element is strictly less than the minimum of two others, conditioned on a boolean, is equivalent to the logical conjunction of two separate conditional checks: one for the element being strictly less than the first of the pair, and one for it being strictly less than the second.*)\nLemma lteif_minr z x y C :\n (z < min x y ?<= if C) = (z < x ?<= if C) && (z < y ?<= if C).\n\n(*This lemma shows how a conditional strict inequality check involving a minimum on the left can be expanded. It states that checking if the minimum of two elements is strictly less than a third element, conditioned on a boolean, is equivalent to the logical disjunction of two separate conditional checks: one for the first element of the pair being strictly less than the third, and one for the second element being strictly less than the third.*)\nLemma lteif_minl z x y C :\n (min x y < z ?<= if C) = (x < z ?<= if C) || (y < z ?<= if C).\n\n(*This lemma shows how a conditional strict inequality check distributes over a maximum on the right. It states that checking if an element is strictly less than the maximum of two others, conditioned on a boolean, is equivalent to the logical disjunction of two separate conditional checks: one for the element being strictly less than the first of the pair, and one for it being strictly less than the second.*)\nLemma lteif_maxr z x y C :\n (z < max x y ?<= if C) = (z < x ?<= if C) || (z < y ?<= if C).\n\n(*This lemma shows how a conditional strict inequality check involving a maximum on the left can be expanded. It states that checking if the maximum of two elements is strictly less than a third element, conditioned on a boolean, is equivalent to the logical conjunction of two separate conditional checks: one for the first element of the pair being strictly less than the third, and one for the second element being strictly less than the third.*)\nLemma lteif_maxl z x y C :\n (max x y < z ?<= if C) = (x < z ?<= if C) && (y < z ?<= if C).\n\nSection ArgExtremum.\nContext (I : finType) (i0 : I) (P : {pred I}) (F : I -> T) (Pi0 : P i0).\n\n(*This lemma states that the element returned by the argument-minimizing operator satisfies the specification for being a true minimum. Specifically, for a given function over a finite type, a predicate, and a default index, the computed index satisfies the predicate, and the function's value at this index is less than or equal to its value at any other index satisfying the predicate.*)\nLemma arg_minP: extremum_spec <=%O P F (arg_min i0 P F).\n\n(*This lemma states that the element returned by the argument-maximizing operator satisfies the specification for being a true maximum. Specifically, for a given function over a finite type, a predicate, and a default index, the computed index satisfies the predicate, and the function's value at this index is greater than or equal to its value at any other index satisfying the predicate.*)\nLemma arg_maxP: extremum_spec >=%O P F (arg_max i0 P F).\n\nEnd ArgExtremum.\n\n(*This lemma states that for a totally ordered type, the number of elements in a finite sequence that are less than or equal to a given value is equal to the total size of the sequence minus the number of elements that are strictly greater than that value.*)\nLemma count_le_gt x s : count (<= x) s = size s - count (> x) s.\n\n(*This lemma states that for a totally ordered type, the number of elements in a finite sequence that are strictly less than a given value is equal to the total size of the sequence minus the number of elements that are greater than or equal to that value.*)\nLemma count_lt_ge x s : count (< x) s = size s - count (>= x) s.\n\nSection bigminmax_Type.\nContext (I : Type) (r : seq I) (x : T).\nImplicit Types (P : pred I) (F : I -> T).\n\n(*This lemma states that computing the minimum of a function over a filtered sequence is equivalent to computing the minimum over the entire sequence of a conditional expression. The minimum of a function's values for elements satisfying a predicate can be found by taking the minimum of values produced by a new function that returns the original function's value if the predicate holds and a default value otherwise.*)\nLemma bigmin_mkcond P F : \\big[min/x]_(i <- r | P i) F i =\n \\big[min/x]_(i <- r) (if P i then F i else x).\n\n(*This lemma states that computing the maximum of a function over a filtered sequence is equivalent to computing the maximum over the entire sequence of a conditional expression. The maximum of a function's values for elements satisfying a predicate can be found by taking the maximum of values produced by a new function that returns the original function's value if the predicate holds and a default value otherwise.*)\nLemma bigmax_mkcond P F :\n \\big[max/x]_(i <- r | P i) F i = \\big[max/x]_(i <- r) if P i then F i else x.\n\n(*This lemma provides a way to rewrite an iterated minimum over a sequence filtered by a conjunction of two predicates. It states that taking the minimum over elements that satisfy both predicates is equivalent to taking the minimum over elements that satisfy the second predicate, where the value contributed by each element is conditionally determined by the first predicate: if the first predicate holds, the original function's value is used, otherwise a default value is used.*)\nLemma bigmin_mkcondl P Q F :\n \\big[min/x]_(i <- r | P i && Q i) F i\n = \\big[min/x]_(i <- r | Q i) if P i then F i else x.\n\n(*This lemma provides a way to rewrite an iterated minimum over a sequence filtered by a conjunction of two predicates. It states that taking the minimum over elements that satisfy both predicates is equivalent to taking the minimum over elements that satisfy the first predicate, where the value contributed by each element is conditionally determined by the second predicate: if the second predicate holds, the original function's value is used, otherwise a default value is used.*)\nLemma bigmin_mkcondr P Q F :\n \\big[min/x]_(i <- r | P i && Q i) F i\n = \\big[min/x]_(i <- r | P i) if Q i then F i else x.\n\n(*This lemma provides a way to rewrite an iterated maximum over a sequence filtered by a conjunction of two predicates. It states that taking the maximum over elements that satisfy both predicates is equivalent to taking the maximum over elements that satisfy the second predicate, where the value contributed by each element is conditionally determined by the first predicate: if the first predicate holds, the original function's value is used, otherwise a default value is used.*)\nLemma bigmax_mkcondl P Q F :\n \\big[max/x]_(i <- r | P i && Q i) F i\n = \\big[max/x]_(i <- r | Q i) if P i then F i else x.\n\n(*This lemma provides a way to rewrite an iterated maximum over a sequence filtered by a conjunction of two predicates. It states that taking the maximum over elements that satisfy both predicates is equivalent to taking the maximum over elements that satisfy the first predicate, where the value contributed by each element is conditionally determined by the second predicate: if the second predicate holds, the original function's value is used, otherwise a default value is used.*)\nLemma bigmax_mkcondr P Q F :\n \\big[max/x]_(i <- r | P i && Q i) F i\n = \\big[max/x]_(i <- r | P i) if Q i then F i else x.\n\n(*This lemma states that the indexed minimum over a sequence of the pointwise minimum of two functions is equal to the minimum of the indexed minimums of each function computed separately.*)\nLemma bigmin_split P F1 F2 :\n \\big[min/x]_(i <- r | P i) (min (F1 i) (F2 i)) =\n min (\\big[min/x]_(i <- r | P i) F1 i) (\\big[min/x]_(i <- r | P i) F2 i).\n\n(*This lemma states that the indexed maximum over a sequence of the pointwise maximum of two functions is equal to the maximum of the indexed maximums of each function computed separately.*)\nLemma bigmax_split P F1 F2 :\n \\big[max/x]_(i <- r | P i) (max (F1 i) (F2 i)) =\n max (\\big[max/x]_(i <- r | P i) F1 i) (\\big[max/x]_(i <- r | P i) F2 i).\n\n(*This lemma states that the indexed minimum of a function over a sequence is equal to the minimum of the default value and the indexed minimum itself.*)\nLemma bigmin_idl P F :\n \\big[min/x]_(i <- r | P i) F i = min x (\\big[min/x]_(i <- r | P i) F i).\n\n(*This lemma states that the indexed maximum of a function over a sequence is equal to the maximum of the default value and the indexed maximum itself.*)\nLemma bigmax_idl P F :\n \\big[max/x]_(i <- r | P i) F i = max x (\\big[max/x]_(i <- r | P i) F i).\n\n(*This lemma states that the indexed minimum of a function over a sequence is equal to the minimum of the indexed minimum itself and the default value.*)\nLemma bigmin_idr P F :\n \\big[min/x]_(i <- r | P i) F i = min (\\big[min/x]_(i <- r | P i) F i) x.\n\n(*This lemma states that the indexed maximum of a function over a sequence is equal to the maximum of the indexed maximum itself and the default value.*)\nLemma bigmax_idr P F :\n \\big[max/x]_(i <- r | P i) F i = max (\\big[max/x]_(i <- r | P i) F i) x.\n\n(*This lemma states that the indexed minimum of a function over a sequence satisfying a predicate can be computed by taking the minimum of two separate indexed minimums: one where the elements satisfy an additional boolean condition, and another where they satisfy the negation of that condition.*)\nLemma bigminID a P F : \\big[min/x]_(i <- r | P i) F i =\n min (\\big[min/x]_(i <- r | P i && a i) F i)\n (\\big[min/x]_(i <- r | P i && ~~ a i) F i).\n\n(*This lemma states that the indexed maximum of a function over a sequence satisfying a predicate can be computed by taking the maximum of two separate indexed maximums: one where the elements satisfy an additional boolean condition, and another where they satisfy the negation of that condition.*)\nLemma bigmaxID a P F : \\big[max/x]_(i <- r | P i) F i =\n max (\\big[max/x]_(i <- r | P i && a i) F i)\n (\\big[max/x]_(i <- r | P i && ~~ a i) F i).\n\nEnd bigminmax_Type.\n\n(*This statement asserts that an element is greater than or equal to the minimum of itself and another element.*)\nLet ge_min_id (x y : T) : x >= min x y. \n(*This statement asserts that an element is less than or equal to the maximum of itself and another element.*)\nLet le_max_id (x y : T) : x <= max x y. \n\n(*This lemma states that if a first predicate is implied by a second predicate, then the indexed minimum of a function over the first predicate is less than or equal to the indexed minimum over the second predicate.*)\nLemma sub_bigmin [x0] I r (P P' : {pred I}) (F : I -> T) :\n (forall i, P' i -> P i) ->\n \\big[min/x0]_(i <- r | P i) F i <= \\big[min/x0]_(i <- r | P' i) F i.\n\n(*This lemma states that if a first predicate implies a second predicate, then the indexed maximum of a function over the first predicate is less than or equal to the indexed maximum over the second predicate.*)\nLemma sub_bigmax [x0] I r (P P' : {pred I}) (F : I -> T) :\n (forall i, P i -> P' i) ->\n \\big[max/x0]_(i <- r | P i) F i <= \\big[max/x0]_(i <- r | P' i) F i.\n\n(*This notation defines the subset relation between two sequences, where one sequence is considered a subset of another if all elements of the first sequence are present in the second.*)\nLocal Notation \"'{subset' x '<=' y '}'\" :=\n (sub_mem (mem x) (mem y)) (at level 0, x, y at level 1).\n\n(*This lemma states that if a first sequence is a subset of a second sequence, the indexed minimum of a function over the second sequence is less than or equal to the indexed minimum over the first sequence.*)\nLemma sub_bigmin_seq [x0] (I : eqType) r r' P (F : I -> T) : {subset r' <= r} ->\n \\big[min/x0]_(i <- r | P i) F i <= \\big[min/x0]_(i <- r' | P i) F i.\n\n(*This lemma states that if a first sequence is a subset of a second sequence, the indexed maximum of a function over the first sequence is less than or equal to the indexed maximum over the second sequence.*)\nLemma sub_bigmax_seq [x0] (I : eqType) r r' P (F : I -> T) : {subset r <= r'} ->\n \\big[max/x0]_(i <- r | P i) F i <= \\big[max/x0]_(i <- r' | P i) F i.\n\n(*This lemma states that if the sequence of elements satisfying a first predicate over a first range is a subset of the sequence of elements satisfying a second predicate over a second range, then the indexed minimum over the second range and predicate is less than or equal to the indexed minimum over the first range and predicate.*)\nLemma sub_bigmin_cond [x0] (I : eqType) r r' P P' (F : I -> T) :\n {subset ([seq i <- r | P i]) <= ([seq i <- r' | P' i])} ->\n \\big[min/x0]_(i <- r' | P' i) F i <= \\big[min/x0]_(i <- r | P i) F i.\n\n(*This lemma states that if the sequence of elements satisfying a first predicate over a first range is a subset of the sequence of elements satisfying a second predicate over a second range, then the indexed maximum over the first range and predicate is less than or equal to the indexed maximum over the second range and predicate.*)\nLemma sub_bigmax_cond [x0] (I : eqType) r r' P P' (F : I -> T) :\n {subset ([seq i <- r | P i]) <= ([seq i <- r' | P' i])} ->\n \\big[max/x0]_(i <- r | P i) F i <= \\big[max/x0]_(i <- r' | P' i) F i.\n\n(*This lemma states that if for all elements in a given sequence, a second predicate implies a first predicate, then the indexed minimum of a function over that sequence with the first predicate is less than or equal to the indexed minimum over the same sequence with the second predicate.*)\nLemma sub_in_bigmin [x0] [I : eqType] (r : seq I) (P P' : {pred I}) F :\n {in r, forall i, P' i -> P i} ->\n \\big[min/x0]_(i <- r | P i) F i <= \\big[min/x0]_(i <- r | P' i) F i.\n\n(*This lemma states that if for all elements in a given sequence, a first predicate implies a second predicate, then the indexed maximum of a function over that sequence with the first predicate is less than or equal to the indexed maximum over the same sequence with the second predicate.*)\nLemma sub_in_bigmax [x0] [I : eqType] (r : seq I) (P P' : {pred I}) F :\n {in r, forall i, P i -> P' i} ->\n \\big[max/x0]_(i <- r | P i) F i <= \\big[max/x0]_(i <- r | P' i) F i.\n\n(*This lemma states that the indexed minimum of a function over a range of natural numbers is less than or equal to the indexed minimum of the same function over a sub-range of those numbers.*)\nLemma le_bigmin_nat [x0] n m n' m' P (F : nat -> T) :\n (n <= n')%N -> (m' <= m)%N ->\n \\big[min/x0]_(n <= i < m | P i) F i <= \\big[min/x0]_(n' <= i < m' | P i) F i.\n\n(*This lemma states that the indexed maximum of a function over a range of natural numbers is less than or equal to the indexed maximum of the same function over a super-range of those numbers.*)\nLemma le_bigmax_nat [x0] n m n' m' P (F : nat -> T) :\n (n' <= n)%N -> (m <= m')%N ->\n \\big[max/x0]_(n <= i < m | P i) F i <= \\big[max/x0]_(n' <= i < m' | P i) F i.\n\n(*This lemma states that if a first range of natural numbers contains a second range, and for all numbers in the second range a second predicate implies a first predicate, then the indexed minimum over the first range with the first predicate is less than or equal to the indexed minimum over the second range with the second predicate.*)\nLemma le_bigmin_nat_cond [x0] n m n' m' (P P' : pred nat) (F : nat -> T) :\n (n <= n')%N -> (m' <= m)%N -> (forall i, (n' <= i < m')%N -> P' i -> P i) ->\n \\big[min/x0]_(n <= i < m | P i) F i <= \\big[min/x0]_(n' <= i < m' | P' i) F i.\n\n(*This lemma states that if a first range of natural numbers is contained within a second range, and for all numbers in the first range a first predicate implies a second predicate, then the indexed maximum over the first range with the first predicate is less than or equal to the indexed maximum over the second range with the second predicate.*)\nLemma le_bigmax_nat_cond [x0] n m n' m' (P P' : {pred nat}) (F : nat -> T) :\n (n' <= n)%N -> (m <= m')%N -> (forall i, (n <= i < m)%N -> P i -> P' i) ->\n \\big[max/x0]_(n <= i < m | P i) F i <= \\big[max/x0]_(n' <= i < m' | P' i) F i.\n\n(*This lemma states that if a first natural number is greater than or equal to a second natural number, then the indexed minimum of a function over the range from zero up to the first number is less than or equal to the indexed minimum over the range from zero up to the second number.*)\nLemma le_bigmin_ord [x0] n m (P : pred nat) (F : nat -> T) : (m <= n)%N ->\n \\big[min/x0]_(i < n | P i) F i <= \\big[min/x0]_(i < m | P i) F i.\n\n(*This lemma states that if a first natural number is less than or equal to a second natural number, then the indexed maximum of a function over the range from zero up to the first number is less than or equal to the indexed maximum over the range from zero up to the second number.*)\nLemma le_bigmax_ord [x0] n m (P : {pred nat}) (F : nat -> T) : (n <= m)%N ->\n \\big[max/x0]_(i < n | P i) F i <= \\big[max/x0]_(i < m | P i) F i.\n\n(*This lemma states that if a first natural number is greater than or equal to a second, and for all numbers in the range from zero up to the second a second predicate implies a first predicate, then the indexed minimum over the range from zero up to the first number with the first predicate is less than or equal to the indexed minimum over the range from zero up to the second number with the second predicate.*)\nLemma le_bigmin_ord_cond [x0] n m (P P' : pred nat) (F : nat -> T) :\n (m <= n)%N -> (forall i : 'I_m, P' i -> P i) ->\n \\big[min/x0]_(i < n | P i) F i <= \\big[min/x0]_(i < m | P' i) F i.\n\n(*This lemma states that if a first natural number is less than or equal to a second, and for all numbers in the range from zero up to the first a first predicate implies a second predicate, then the indexed maximum over the range from zero up to the first number with the first predicate is less than or equal to the indexed maximum over the range from zero up to the second number with the second predicate.*)\nLemma le_bigmax_ord_cond [x0] n m (P P' : {pred nat}) (F : nat -> T) :\n (n <= m)%N -> (forall i : 'I_n, P i -> P' i) ->\n \\big[max/x0]_(i < n | P i) F i <= \\big[max/x0]_(i < m | P' i) F i.\n\n(*This lemma states that if a first finite set is a subset of a second finite set, the indexed minimum of a function over the elements of the second set is less than or equal to the indexed minimum over the elements of the first set.*)\nLemma subset_bigmin [x0] [I : finType] [A A' P : {pred I}] (F : I -> T) :\n A' \\subset A ->\n \\big[min/x0]_(i in A | P i) F i <= \\big[min/x0]_(i in A' | P i) F i.\n\n(*This lemma states that if a first finite set is a subset of a second finite set, the indexed maximum of a function over the elements of the first set is less than or equal to the indexed maximum over the elements of the second set.*)\nLemma subset_bigmax [x0] [I : finType] (A A' P : {pred I}) (F : I -> T) :\n A \\subset A' ->\n \\big[max/x0]_(i in A | P i) F i <= \\big[max/x0]_(i in A' | P i) F i.\n\n(*This lemma states that if a first finite set contains a second finite set, and for all elements in the second set a second predicate implies a first predicate, then the indexed minimum over the first set with the first predicate is less than or equal to the indexed minimum over the second set with the second predicate.*)\nLemma subset_bigmin_cond [x0] (I : finType) (A A' P P' : {pred I}) (F : I -> T) :\n [set i in A' | P' i] \\subset [set i in A | P i] ->\n \\big[min/x0]_(i in A | P i) F i <= \\big[min/x0]_(i in A' | P' i) F i.\n\n(*This lemma states that the maximum of a function over a set of indices is monotonic with respect to the set: if a first set of indices is a subset of a second set, then the maximum over the first set is less than or equal to the maximum over the second set.*)\nLemma subset_bigmax_cond [x0] (I : finType) (A A' P P' : {pred I}) (F : I -> T) :\n [set i in A | P i] \\subset [set i in A' | P' i] ->\n \\big[max/x0]_(i in A | P i) F i <= \\big[max/x0]_(i in A' | P' i) F i.\n\nSection bigminmax_eqType.\nContext (I : eqType) (r : seq I) (x : T).\nImplicit Types (P : pred I) (F : I -> T).\n\n(*This lemma states that the minimum of a function over a sequence of indices, computed with a given default value, is always less than or equal to that default value.*)\nLemma bigmin_le_id P F : \\big[min/x]_(i <- r | P i) F i <= x.\n\n(*This lemma states that the maximum of a function over a sequence of indices, computed with a given default value, is always greater than or equal to that default value.*)\nLemma bigmax_ge_id P F : \\big[max/x]_(i <- r | P i) F i >= x.\n\n(*This lemma states that if a given default value is less than or equal to all values of a function over a sequence of indices satisfying a predicate, then the minimum of the function over those indices, computed with that default value, is equal to the default value.*)\nLemma bigmin_eq_id P F :\n (forall i, P i -> x <= F i) -> \\big[min/x]_(i <- r | P i) F i = x.\n\n(*This lemma states that if a given default value is greater than or equal to all values of a function over a sequence of indices satisfying a predicate, then the maximum of the function over those indices, computed with that default value, is equal to the default value.*)\nLemma bigmax_eq_id P F :\n (forall i, P i -> x >= F i) -> \\big[max/x]_(i <- r | P i) F i = x.\n\nEnd bigminmax_eqType.\n\nSection bigminmax_finType.\nContext (I : finType) (x : T).\nImplicit Types (P : pred I) (F : I -> T).\n\n(*This lemma provides a decomposition rule for the minimum over a set of indices. It states that if a given index satisfies a predicate, the minimum of a function over all indices satisfying the predicate can be computed as the minimum of the function's value at that index and the minimum over the remaining indices.*)\nLemma bigminD1 j P F : P j ->\n \\big[min/x]_(i | P i) F i = min (F j) (\\big[min/x]_(i | P i && (i != j)) F i).\n\n(*This lemma provides a decomposition rule for the maximum over a set of indices. It states that if a given index satisfies a predicate, the maximum of a function over all indices satisfying the predicate can be computed as the maximum of the function's value at that index and the maximum over the remaining indices.*)\nLemma bigmaxD1 j P F : P j ->\n \\big[max/x]_(i | P i) F i = max (F j) (\\big[max/x]_(i | P i && (i != j)) F i).\n\n(*This lemma states that if a given index satisfies a predicate, then the minimum of a function over all indices satisfying that predicate is less than or equal to the function's value at that specific index.*)\nLemma bigmin_le_cond j P F : P j -> \\big[min/x]_(i | P i) F i <= F j.\n\n(*This lemma states that if a given index satisfies a predicate, then the function's value at that specific index is less than or equal to the maximum of the function over all indices satisfying that predicate.*)\nLemma le_bigmax_cond j P F : P j -> F j <= \\big[max/x]_(i | P i) F i.\n\n(*This lemma states that the minimum of a function over its entire domain is less than or equal to the function's value at any given index.*)\nLemma bigmin_le j F : \\big[min/x]_i F i <= F j.\n\n(*This lemma states that a function's value at any given index is less than or equal to the maximum of the function over its entire domain.*)\nLemma le_bigmax F j : F j <= \\big[max/x]_i F i.\n\n(*This lemma states that if a function's value at a specific index is less than or equal to some value, and that index satisfies a given predicate, then the minimum of the function over all indices satisfying the predicate is also less than or equal to that value.*)\nLemma bigmin_inf j P m F : P j -> F j <= m -> \\big[min/x]_(i | P i) F i <= m.\n\n(*This lemma states that if some value is less than or equal to a function's value at a specific index, and that index satisfies a given predicate, then that value is also less than or equal to the maximum of the function over all indices satisfying the predicate.*)\nLemma bigmax_sup j P m F : P j -> m <= F j -> m <= \\big[max/x]_(i | P i) F i.\n\n(*This lemma establishes an equivalence: a value is less than or equal to the minimum of a function over a set of indices (with a default value) if and only if the value is less than or equal to the default value and also less than or equal to the function's value for all indices in the set.*)\nLemma bigmin_geP m P F :\n reflect (m <= x /\\ forall i, P i -> m <= F i)\n (m <= \\big[min/x]_(i | P i) F i).\n\n(*This lemma establishes an equivalence: the maximum of a function over a set of indices (with a default value) is less than or equal to a value if and only if the default value is less than or equal to the value and the function's value for all indices in the set is also less than or equal to the value.*)\nLemma bigmax_leP m P F :\n reflect (x <= m /\\ forall i, P i -> F i <= m)\n (\\big[max/x]_(i | P i) F i <= m).\n\n(*This lemma establishes an equivalence for strict inequality: a value is strictly less than the minimum of a function over a set of indices (with a default value) if and only if it is strictly less than the default value and also strictly less than the function's value for all indices in the set.*)\nLemma bigmin_gtP m P F :\n reflect (m < x /\\ forall i, P i -> m < F i) (m < \\big[min/x]_(i | P i) F i).\n\n(*This lemma establishes an equivalence for strict inequality: the maximum of a function over a set of indices (with a default value) is strictly less than a value if and only if the default value is strictly less than the value and the function's value for all indices in the set is also strictly less than the value.*)\nLemma bigmax_ltP m P F :\n reflect (x < m /\\ forall i, P i -> F i < m) (\\big[max/x]_(i | P i) F i < m).\n\n(*This lemma states that under certain conditions, the minimum of a function over a set of indices is equal to the value of the function at the index that minimizes it. The conditions are that the set of indices is non-empty and that all function values over these indices are less than or equal to the default value used in the minimum computation.*)\nLemma bigmin_eq_arg j P F : P j -> (forall i, P i -> F i <= x) ->\n \\big[min/x]_(i | P i) F i = F [arg min_(i < j | P i) F i].\n\n(*This lemma states that under certain conditions, the maximum of a function over a set of indices is equal to the value of the function at the index that maximizes it. The conditions are that the set of indices is non-empty and that all function values over these indices are greater than or equal to the default value used in the maximum computation.*)\nLemma bigmax_eq_arg j P F : P j -> (forall i, P i -> x <= F i) ->\n \\big[max/x]_(i | P i) F i = F [arg max_(i > j | P i) F i].\n\n(*This lemma asserts the existence of an index within a given set for which a function achieves its minimum value, provided the set is non-empty and all function values over it are less than or equal to the default value.*)\nLemma eq_bigmin j P F : P j -> (forall i, P i -> F i <= x) ->\n {i0 | i0 \\in P & \\big[min/x]_(i | P i) F i = F i0}.\n\n(*This lemma asserts the existence of an index within a given set for which a function achieves its maximum value, provided the set is non-empty and all function values over it are greater than or equal to the default value.*)\nLemma eq_bigmax j P F : P j -> (forall i, P i -> x <= F i) ->\n {i0 | i0 \\in P & \\big[max/x]_(i | P i) F i = F i0}.\n\n(*This lemma states that the indexed minimum operation is monotonic with respect to the function. If a first function is pointwise less than or equal to a second function over a given set of indices, then the minimum of the first function over that set is less than or equal to the minimum of the second function, when computed with the same default value.*)\nLemma le_bigmin2 P F1 F2 : (forall i, P i -> F1 i <= F2 i) ->\n \\big[min/x]_(i | P i) F1 i <= \\big[min/x]_(i | P i) F2 i.\n\n(*This lemma states that the indexed maximum operation is monotonic with respect to the function. If a first function is pointwise less than or equal to a second function over a given set of indices, then the maximum of the first function over that set is less than or equal to the maximum of the second function, when computed with the same default value.*)\nLemma le_bigmax2 P F1 F2 : (forall i, P i -> F1 i <= F2 i) ->\n \\big[max/x]_(i | P i) F1 i <= \\big[max/x]_(i | P i) F2 i.\n\n(*This lemma states that the maximum of a function over a set is less than or equal to the maximum of the same function over the union of that set with another set.*)\nLemma bigmaxUl (A B : {set I}) F :\n \\big[max/x]_(i in A) F i <= \\big[max/x]_(i in A :|: B) F i.\n\n(*This lemma states that the maximum of a function over a set is less than or equal to the maximum of the same function over the union of another set with that set.*)\nLemma bigmaxUr (A B : {set I}) F :\n \\big[max/x]_(i in B) F i <= \\big[max/x]_(i in A :|: B) F i.\n\n(*This lemma states that the minimum of a function over a set is greater than or equal to the minimum of the same function over the union of that set with another set.*)\nLemma bigminUl (A B : {set I}) F :\n \\big[min/x]_(i in A) F i >= \\big[min/x]_(i in A :|: B) F i.\n\n(*This lemma states that the minimum of a function over a set is greater than or equal to the minimum of the same function over the union of another set with that set.*)\nLemma bigminUr (A B : {set I}) F :\n \\big[min/x]_(i in B) F i >= \\big[min/x]_(i in A :|: B) F i.\n\n(*This lemma states that the maximum of a function over a set is greater than or equal to the maximum of the same function over the intersection of that set with another set.*)\nLemma bigmaxIl (A B : {set I}) F :\n \\big[max/x]_(i in A) F i >= \\big[max/x]_(i in A :&: B) F i.\n\n(*This lemma states that the maximum of a function over a set is greater than or equal to the maximum of the same function over the intersection of another set with that set.*)\nLemma bigmaxIr (A B : {set I}) F :\n \\big[max/x]_(i in B) F i >= \\big[max/x]_(i in A :&: B) F i.\n\n(*This lemma states that the minimum of a function over a set is less than or equal to the minimum of the same function over the intersection of that set with another set.*)\nLemma bigminIl (A B : {set I}) F :\n \\big[min/x]_(i in A) F i <= \\big[min/x]_(i in A :&: B) F i.\n\n(*This lemma states that the indexed minimum of a function over a set is less than or equal to its indexed minimum over any subset of that set. Specifically, the minimum taken over a set `B` is less than or equal to the minimum taken over the intersection of `B` with another set `A`.*)\nLemma bigminIr (A B : {set I}) F :\n \\big[min/x]_(i in B) F i <= \\big[min/x]_(i in A :&: B) F i.\n\n(*This lemma states that the indexed maximum of a function over a set `B` is greater than or equal to its indexed maximum over the elements of `B` that are not in another set `A`.*)\nLemma bigmaxD (A B : {set I}) F :\n \\big[max/x]_(i in B) F i >= \\big[max/x]_(i in B :\\: A) F i.\n\n(*This lemma states that the indexed minimum of a function over a set `B` is less than or equal to its indexed minimum over the elements of `B` that are not in another set `A`.*)\nLemma bigminD (A B : {set I}) F :\n \\big[min/x]_(i in B) F i <= \\big[min/x]_(i in B :\\: A) F i.\n\n(*This lemma states that the indexed maximum of a function over the union of two sets is equal to the maximum of the indexed maximums computed over each set individually.*)\nLemma bigmaxU (A B : {set I}) F :\n \\big[max/x]_(i in A :|: B) F i\n = max (\\big[max/x]_(i in A) F i) (\\big[max/x]_(i in B) F i).\n\n(*This lemma states that the indexed minimum of a function over the union of two sets is equal to the minimum of the indexed minimums computed over each set individually.*)\nLemma bigminU (A B : {set I}) F :\n \\big[min/x]_(i in A :|: B) F i\n = min (\\big[min/x]_(i in A) F i) (\\big[min/x]_(i in B) F i).\n\n(*This lemma states that the indexed minimum of a function over a singleton set containing a single element is equal to the minimum of the function's value at that element and the given default value.*)\nLemma bigmin_set1 j F : \\big[min/x]_(i in [set j]) F i = min (F j) x.\n\n(*This lemma states that the indexed maximum of a function over a singleton set containing a single element is equal to the maximum of the function's value at that element and the given default value.*)\nLemma bigmax_set1 j F : \\big[max/x]_(i in [set j]) F i = max (F j) x.\n\nEnd bigminmax_finType.\n\n(*This lemma provides a change-of-variable formula for the indexed minimum, stating that the minimum of a function over the image of a set under another function is equal to the minimum of the composite function over the original set.*)\nLemma bigmin_imset [I J : finType] x [h : I -> J] [A : {set I}] (F : J -> T) :\n \\big[min/x]_(j in [set h x | x in A]) F j = \\big[min/x]_(i in A) F (h i).\n\n(*This lemma provides a change-of-variable formula for the indexed maximum, stating that the maximum of a function over the image of a set under another function is equal to the maximum of the composite function over the original set.*)\nLemma bigmax_imset [I J : finType] x [h : I -> J] [A : {set I}] (F : J -> T) :\n \\big[max/x]_(j in [set h x | x in A]) F j = \\big[max/x]_(i in A) F (h i).\n\nEnd TotalTheory.\n\n#[global] Hint Resolve le_total : core.\n#[global] Hint Resolve ge_total : core.\n#[global] Hint Extern 0 (is_true (_ >=< _)%O) => solve [apply: comparableT]\n : core.\n#[global] Hint Resolve sort_le_sorted : core.\n\nArguments min_idPr {disp T x y}.\nArguments max_idPl {disp T x y}.\nArguments bigmin_mkcond {disp T I r}.\nArguments bigmax_mkcond {disp T I r}.\nArguments bigminID {disp T I r}.\nArguments bigmaxID {disp T I r}.\nArguments bigminD1 {disp T I x} j.\nArguments bigmaxD1 {disp T I x} j.\nArguments bigmin_inf {disp T I x} j.\nArguments bigmax_sup {disp T I x} j.\nArguments bigmin_eq_arg {disp T I} x j.\nArguments bigmax_eq_arg {disp T I} x j.\nArguments eq_bigmin {disp T I x} j.\nArguments eq_bigmax {disp T I x} j.\n\nModule Import DualTotalTheory.\nSection DualTotalTheory.\nContext {disp : disp_t} {T : orderType disp}.\nImplicit Type s : seq T.\n\n(*This lemma states that for a sorted sequence, filtering it to retain only the elements strictly greater than a given value is equivalent to dropping a prefix of the sequence whose length is the number of elements less than or equal to that value.*)\nLemma sorted_filter_gt x s :\n sorted <=%O s -> [seq y <- s | x < y] = drop (count (<= x) s) s.\n\n(*This lemma states that for a sorted sequence, filtering it to retain only the elements greater than or equal to a given value is equivalent to dropping a prefix of the sequence whose length is the number of elements strictly less than that value.*)\nLemma sorted_filter_ge x s :\n sorted <=%O s -> [seq y <- s | x <= y] = drop (count (< x) s) s.\n\n(*This lemma states that in a sorted sequence, any element at an index greater than or equal to the count of elements strictly less than a given value must be greater than or equal to that value.*)\nLemma nth_count_ge x x0 s i : sorted <=%O s ->\n (count (< x) s <= i < size s)%N -> x <= nth x0 s i.\n\n(*This lemma states that in a sorted sequence, any element at an index greater than or equal to the count of elements less than or equal to a given value must be strictly greater than that value.*)\nLemma nth_count_gt x x0 s i : sorted <=%O s ->\n (count (<= x) s <= i < size s)%N -> x < nth x0 s i.\n\n(*This lemma states that in a sorted sequence, any element at an index between the count of elements strictly less than a given value and the count of elements less than or equal to that value must be equal to that value.*)\nLemma nth_count_eq x x0 s i : sorted <=%O s ->\n (count (< x) s <= i < count (<= x) s)%N -> nth x0 s i = x.\n\nEnd DualTotalTheory.\nEnd DualTotalTheory.\n\nSection ContraTheory.\nContext {disp1 disp2 : disp_t} {T1 : porderType disp1} {T2 : orderType disp2}.\nImplicit Types (x y : T1) (z t : T2) (b : bool) (m n : nat) (P : Prop).\n\n(*This lemma provides a contrapositive rule for reasoning about inequalities in a total order. It states that if an element `t` being strictly less than an element `z` implies a boolean `b` is true, then `b` being true implies that `z` is less than or equal to `t`.*)\nLemma contraTle b z t : (t < z -> ~~ b) -> (b -> z <= t).\n\n(*This lemma provides a contrapositive rule for reasoning about inequalities in a total order. It states that if an element `t` being less than or equal to an element `z` implies a boolean `b` is true, then `b` being true implies that `z` is strictly less than `t`.*)\nLemma contraTlt b z t : (t <= z -> ~~ b) -> (b -> z < t).\n\n(*This lemma provides a contrapositive rule for reasoning about inequalities in a total order. It states that if an element `t` being strictly less than an element `z` implies a proposition `P` is false, then `P` being true implies that `z` is less than or equal to `t`.*)\nLemma contraPle P z t : (t < z -> ~ P) -> (P -> z <= t).\n\n(*This lemma provides a contrapositive rule for reasoning about inequalities in a total order. It states that if an element `t` being less than or equal to an element `z` implies a proposition `P` is false, then `P` being true implies that `z` is strictly less than `t`.*)\nLemma contraPlt P z t : (t <= z -> ~ P) -> (P -> z < t).\n\n(*This lemma provides a contrapositive rule for reasoning about inequalities in a total order. It states that if an element `t` being strictly less than an element `z` implies that a boolean `b` is true, then `b` being true implies that `z` is less than or equal to `t`.*)\nLemma contraNle b z t : (t < z -> b) -> (~~ b -> z <= t).\n\n(*This lemma provides a contrapositive rule for reasoning about inequalities in a total order. It states that if an element `t` being less than or equal to an element `z` implies that a boolean `b` is true, then `b` being true implies that `z` is strictly less than `t`.*)\nLemma contraNlt b z t : (t <= z -> b) -> (~~ b -> z < t).\n\n(*This lemma provides a contrapositive rule for an inequality in a total order. It states that if `t` being strictly less than `z` implies a proposition `P`, then the negation of `P` implies that `z` is less than or equal to `t`.*)\nLemma contra_not_le P z t : (t < z -> P) -> (~ P -> z <= t).\n\n(*This lemma provides a contrapositive rule for an inequality in a total order. It states that if `t` being less than or equal to `z` implies a proposition `P`, then the negation of `P` implies that `z` is strictly less than `t`.*)\nLemma contra_not_lt P z t : (t <= z -> P) -> (~ P -> z < t).\n\n(*This lemma provides a contrapositive rule for an inequality in a total order. It states that if `t` being strictly less than `z` implies a boolean `b` is true, then `b` being false implies that `z` is less than or equal to `t`.*)\nLemma contraFle b z t : (t < z -> b) -> (b = false -> z <= t).\n\n(*This lemma provides a contrapositive rule for an inequality in a total order. It states that if `t` being less than or equal to `z` implies a boolean `b` is true, then `b` being false implies that `z` is strictly less than `t`.*)\nLemma contraFlt b z t : (t <= z -> b) -> (b = false -> z < t).\n\n(*This lemma provides a contrapositive rule for relating two inequalities. It states that if an element `t` being strictly less than `z` implies that a natural number `n` is strictly less than `m`, then `m` being less than or equal to `n` implies that `z` is less than or equal to `t`.*)\nLemma contra_leq_le m n z t : (t < z -> (n < m)%N) -> ((m <= n)%N -> z <= t).\n\n(*This lemma provides a contrapositive rule for relating two inequalities. It states that if an element `t` being less than or equal to `z` implies that a natural number `n` is strictly less than `m`, then `m` being less than or equal to `n` implies that `z` is strictly less than `t`.*)\nLemma contra_leq_lt m n z t : (t <= z -> (n < m)%N) -> ((m <= n)%N -> z < t).\n\n(*This lemma provides a contrapositive rule for relating two inequalities. It states that if an element `t` being strictly less than `z` implies that a natural number `n` is less than or equal to `m`, then `m` being strictly less than `n` implies that `z` is less than or equal to `t`.*)\nLemma contra_ltn_le m n z t : (t < z -> (n <= m)%N) -> ((m < n)%N -> z <= t).\n\n(*This lemma provides a contrapositive rule for relating two inequalities. It states that if an element `t` being less than or equal to `z` implies that a natural number `n` is less than or equal to `m`, then `m` being strictly less than `n` implies that `z` is strictly less than `t`.*)\nLemma contra_ltn_lt m n z t : (t <= z -> (n <= m)%N) -> ((m < n)%N -> z < t).\n\n(*This lemma provides a contrapositive rule for inequalities across different types. It states that if an element `t` being strictly less than `z` in a totally ordered type implies that `y` is strictly less than `x` in a partially ordered type, then `x` being less than or equal to `y` implies `z` is less than or equal to `t`.*)\nLemma contra_le x y z t : (t < z -> y < x) -> (x <= y -> z <= t).\n\n(*This lemma provides a contrapositive rule for inequalities across different types. It states that if an element `t` being less than or equal to `z` in a totally ordered type implies that `y` is strictly less than `x` in a partially ordered type, then `x` being less than or equal to `y` implies `z` is strictly less than `t`.*)\nLemma contra_le_lt x y z t : (t <= z -> y < x) -> (x <= y -> z < t).\n\n(*This lemma states a contraposition-style inference rule for ordered elements. If it is assumed that a fourth element `t` being strictly less than a third element `z` implies that a second element `y` is less than or equal to a first element `x`, then it logically follows that `x` being strictly less than `y` implies that `z` is less than or equal to `t`.*)\nLemma contra_lt_le x y z t : (t < z -> y <= x) -> (x < y -> z <= t).\n\n(*This lemma states a contraposition-style inference rule for ordered elements. If it is assumed that a fourth element `t` being less than or equal to a third element `z` implies that a second element `y` is less than or equal to a first element `x`, then it logically follows that `x` being strictly less than `y` implies that `z` is strictly less than `t`.*)\nLemma contra_lt x y z t : (t <= z -> y <= x) -> (x < y -> z < t).\n\nEnd ContraTheory.\n\nSection TotalMonotonyTheory.\nContext {disp disp' : disp_t} {T : orderType disp} {T' : porderType disp'}.\nContext (D : {pred T}) (f : T -> T').\nImplicit Types (x y z : T) (u v w : T').\n\n(*This definition assigns a name to the antisymmetry property of the order relation on the source type, which states that if two elements are less than or equal to each other, they must be equal.*)\nLet leT_anti := @le_anti _ T.\n(*This definition assigns a name to the antisymmetry property of the order relation on the target type, which states that if two elements are less than or equal to each other, they must be equal.*)\nLet leT'_anti := @le_anti _ T'.\n(*This definition assigns a name to the property that defines the strict less-than relation on the source type as the conjunction of being not equal and being less than or equal.*)\nLet ltT_neqAle := @lt_neqAle _ T.\n(*This definition assigns a name to the property that defines the strict less-than relation on the target type as the conjunction of being not equal and being less than or equal.*)\nLet ltT'_neqAle := @lt_neqAle _ T'.\n(*This definition assigns a name to the standard definition of the strict less-than relation on the source type, which is defined as the negation of the greater-than-or-equal-to relation.*)\nLet ltT_def := @lt_def _ T.\n(*This definition assigns a name to the totality property of the order relation on the source type, which states that for any two elements, one must be less than or equal to the other.*)\nLet leT_total := @le_total _ T.\n\n(*This lemma states that for a function from a totally ordered type to a partially ordered type, if the function preserves the strict less-than relation, then it also preserves the less-than-or-equal-to relation.*)\nLemma le_mono : {homo f : x y / x < y} -> {mono f : x y / x <= y}.\n\n(*This lemma states that for a function from a totally ordered type to a partially ordered type, if the function reflects the strict less-than relation, then it also reflects the less-than-or-equal-to relation.*)\nLemma le_nmono : {homo f : x y /~ x < y} -> {mono f : x y /~ x <= y}.\n\n(*This lemma states that for a function from a totally ordered type to a partially ordered type, if the function preserves the strict less-than relation for all inputs within a given subset of its domain, then it also preserves the less-than-or-equal-to relation for inputs within that same subset.*)\nLemma le_mono_in :\n {in D &, {homo f : x y / x < y}} -> {in D &, {mono f : x y / x <= y}}.\n\n(*This lemma states that for a function from a totally ordered type to a partially ordered type, if the function reflects the strict less-than relation for all inputs within a given subset of its domain, then it also reflects the less-than-or-equal-to relation for inputs within that same subset.*)\nLemma le_nmono_in :\n {in D &, {homo f : x y /~ x < y}} -> {in D &, {mono f : x y /~ x <= y}}.\n\nEnd TotalMonotonyTheory.\n\nEnd TotalTheory.\n\nModule Import CDistrLatticeTheory.\nSection CDistrLatticeTheory.\nContext {disp : disp_t} {L : cDistrLatticeType disp}.\nImplicit Types (x y z : L).\n\n(*This lemma establishes an absorption property involving the relative complement in a complemented distributive lattice. It states that the meet of the relative complement of `x`, `y`, and `z` with the join of `z` and the meet of `x` and `y` is equal to the meet of `x` and `y`.*)\nLemma rcomplPmeet x y z : ((x `&` y) `|` z) `&` rcompl x y z = x `&` y.\n\n(*This lemma establishes an absorption property involving the relative complement in a complemented distributive lattice. It states that the join of the relative complement of `x`, `y`, and `z` with the meet of `z` and the join of `x` and `y` is equal to the join of `x` and `y`.*)\nLemma rcomplPjoin x y z : ((y `|` x) `&` z) `|` rcompl x y z = y `|` x.\n\n(*This lemma states a fundamental property of the relative complement within a complemented distributive lattice. Under the condition that an element `x` is less than or equal to an element `y`, it asserts that the meet of the join of `x` and a third element `z` with the relative complement of `x`, `y`, and `z` is equal to `x`.*)\nLemma rcomplKI x y z : x <= y -> (x `|` z) `&` rcompl x y z = x.\n\n(*This lemma states a property of the relative complement within a complemented distributive lattice. Under the condition that an element `x` is less than or equal to an element `y`, it asserts that the join of the meet of `y` and a third element `z` with the relative complement of `x`, `y`, and `z` is equal to `y`.*)\nLemma rcomplKU x y z : x <= y -> (y `&` z) `|` rcompl x y z = y.\n\nEnd CDistrLatticeTheory.\nEnd CDistrLatticeTheory.\n\nModule Import CBDistrLatticeTheory.\nSection CBDistrLatticeTheory.\nContext {disp : disp_t} {L : cbDistrLatticeType disp}.\nImplicit Types (x y z : L).\n\n(*This lemma asserts that the lattice difference between two elements `x` and `y` is equivalent to the relative complement operation applied to the bottom element, `x`, and `y`.*)\nLemma diffErcompl x y : x `\\` y = rcompl \\bot x y.\n\n(*This lemma states that in a complemented and bounded distributive lattice, the meet of an element `y` with the lattice difference of an element `x` and `y` is equal to the bottom element.*)\nLemma diffKI x y : y `&` (x `\\` y) = \\bot.\n\n(*This lemma is a commutative variant of a property of lattice difference, stating that the meet of the lattice difference of `x` minus `y` with the element `y` is equal to the bottom element.*)\nLemma diffIK x y : (x `\\` y) `&` y = \\bot.\n\n(*This lemma generalizes a property of lattice difference by stating that the meet of the lattice difference of `x` and `y` with the meet of a third element `z` and `y` is equal to the bottom element.*)\nLemma meetIB z x y : (z `&` y) `&` (x `\\` y) = \\bot.\n\n(*This lemma is a commutative variant of a generalized property of lattice difference, stating that the meet of the lattice difference of `x` and `y` with the meet of `z` and `y` is equal to a bottom element.*)\nLemma meetBI z x y : (x `\\` y) `&` (z `&` y) = \\bot.\n\n(*This lemma provides a decomposition of an element `x` using lattice operations. It states that the join of the meet of `x` and `y` with the lattice difference of `x` and `y` is equal to `x`.*)\nLemma joinIB y x : (x `&` y) `|` (x `\\` y) = x.\n\n(*This lemma is a commutative variant of the decomposition of an element `x`, stating that the join of the lattice difference of `x` and `y` with the meet of `x` and `y` is equal to `x`.*)\nLemma joinBI y x : (x `\\` y) `|` (x `&` y) = x.\n\n(*This lemma is another variant of the decomposition of an element `x`, based on the commutativity of the meet operation. It states that the join of the meet of `y` and `x` with the lattice difference of `x` and `y` is equal to `x`.*)\nLemma joinIBC y x : (y `&` x) `|` (x `\\` y) = x.\n\n(*This lemma is a commutative variant of the decomposition of an element `x`, stating that the join of the lattice difference of `x` and `y` with the meet of `y` and `x` is equal to `x`.*)\nLemma joinBIC y x : (x `\\` y) `|` (y `&` x) = x.\n\n(*This lemma states that the lattice difference of an element `x` and an element `y` is less than or equal to `x`.*)\nLemma leBx x y : x `\\` y <= x.\n\nHint Resolve leBx : core.\n\n(*This lemma states that the lattice difference of any element with itself is equal to the bottom element.*)\nLemma diffxx x : x `\\` x = \\bot.\n\n(*This lemma asserts that the lattice difference operation is monotonic in its first argument. If `x` is less than or equal to `y`, then the lattice difference of `x` and a third element `z` is less than or equal to the lattice difference of `y` and `z`.*)\nLemma leBl z x y : x <= y -> x `\\` z <= y `\\` z.\n\n(*This lemma states that the join of an element `y` with the lattice difference of an element `x` and `y` is equal to the join of `y` and `x`.*)\nLemma diffKU y x : y `|` (x `\\` y) = y `|` x.\n\n(*This lemma is a commutative variant of a property of lattice difference and join. It states that the join of the lattice difference of an element `x` and `y` with the element `y` is equal to the join of `x` and `y`.*)\nLemma diffUK y x : (x `\\` y) `|` y = x `|` y.\n\n(*This lemma states that for two lattice elements where the first is less than or equal to the second, the join of the first element with the difference of the second and the first element is equal to the second element.*)\nLemma leBKU y x : y <= x -> y `|` (x `\\` y) = x.\n\n(*This lemma states that for two lattice elements where one is less than or equal to the other, the join of the difference of the greater and the lesser element with the lesser element is equal to the greater element.*)\nLemma leBUK y x : y <= x -> (x `\\` y) `|` y = x.\n\n(*This lemma states that for three lattice elements, the statement that the difference of the first and second elements is less than or equal to the third is equivalent to the statement that the first element is less than or equal to the join of the second and third elements.*)\nLemma leBLR x y z : (x `\\` y <= z) = (x <= y `|` z).\n\n(*This lemma states that for three lattice elements, the difference of the join of the first two elements and the third element is equal to the join of the difference of the first and third elements and the difference of the second and third elements.*)\nLemma diffUx x y z : (x `|` y) `\\` z = (x `\\` z) `|` (y `\\` z).\n\n(*This lemma states that for two lattice elements, the difference of the first and second elements is equal to the bottom element if and only if the first element is less than or equal to the second.*)\nLemma diff_eq0 x y : (x `\\` y == \\bot) = (x <= y).\n\n(*This lemma states that for three lattice elements, the join of the first element with the difference of the second and third elements is equal to the join of two quantities: the difference between the join of the first and second elements and the third element, and the meet of the first and third elements.*)\nLemma joinxB x y z : x `|` (y `\\` z) = ((x `|` y) `\\` z) `|` (x `&` z).\n\n(*This lemma states that for three lattice elements, the join of the difference between the second and third elements with the first element is equal to the join of two terms: the difference between the join of the second and first elements and the third element, and the meet of the third and first elements.*)\nLemma joinBx x y z : (y `\\` z) `|` x = ((y `|` x) `\\` z) `|` (z `&` x).\n\n(*This lemma states that for three lattice elements, if the second element is less than or equal to the third, then the difference of the first element and the third is less than or equal to the difference of the first element and the second.*)\nLemma leBr z x y : x <= y -> z `\\` y <= z `\\` x.\n\n(*This lemma states that for four lattice elements, if the first is less than or equal to the third and the fourth is less than or equal to the second, then the difference of the first and second elements is less than or equal to the difference of the third and fourth elements.*)\nLemma leB2 x y z t : x <= z -> t <= y -> x `\\` y <= z `\\` t.\n\n(*This lemma states that for three lattice elements, given that the second element is less than or equal to the first, the condition that the meet of the second and third elements equals the bottom element is equivalent to the condition that the second element is less than or equal to the difference of the first and third elements.*)\nLemma meet_eq0E_diff z x y : x <= z -> (x `&` y == \\bot) = (x <= z `\\` y).\n\n(*This lemma states that for three lattice elements, the condition that the first element is less than or equal to the difference of the third and second elements is equivalent to the conjunction of two conditions: that the first element is less than or equal to the third, and that the meet of the first and second elements is equal to the bottom element.*)\nLemma leBRL x y z : (x <= z `\\` y) = (x <= z) && (x `&` y == \\bot).\n\n(*This lemma states that for three lattice elements, the third element is equal to the difference of the first and second elements if and only if three conditions hold simultaneously: the third element is less than or equal to the first, the first element is less than or equal to the join of the second and third elements, and the meet of the third and second elements is equal to the bottom element.*)\nLemma eq_diff x y z : (x `\\` y == z) = (z <= x <= y `|` z) && (z `&` y == \\bot).\n\n(*This lemma states that for three lattice elements, the difference of the third element and the join of the first and second elements is equal to the meet of the difference between the third and first elements, and the difference between the third and second elements.*)\nLemma diffxU x y z : z `\\` (x `|` y) = (z `\\` x) `&` (z `\\` y).\n\n(*This lemma states that for any lattice element, its difference with the bottom element is the element itself.*)\nLemma diffx0 x : x `\\` \\bot = x.\n\n(*This lemma states that for any lattice element, the difference of the bottom element and that element is the bottom element.*)\nLemma diff0x x : \\bot `\\` x = \\bot.\n\n(*This lemma states that for three lattice elements, the difference of the meet of the first two elements and the third element is equal to the meet of two terms: the difference of the first and third elements, and the difference of the second and third elements.*)\nLemma diffIx x y z : (x `&` y) `\\` z = (x `\\` z) `&` (y `\\` z).\n\n(*This lemma states that for three lattice elements, the meet of the first element with the difference of the second and third is equal to the difference of the meet of the first and second elements with the third.*)\nLemma meetxB x y z : x `&` (y `\\` z) = (x `&` y) `\\` z.\n\n(*This lemma states that for three lattice elements, the meet of the difference between the first and second elements with the third element is equal to the difference between the meet of the first and third elements and the second element.*)\nLemma meetBx x y z : (x `\\` y) `&` z = (x `&` z) `\\` y.\n\n(*This lemma states that for three lattice elements, the difference of the first element and the meet of the second and third elements is equal to the join of two terms: the difference of the first and second elements, and the difference of the first and third elements.*)\nLemma diffxI x y z : x `\\` (y `&` z) = (x `\\` y) `|` (x `\\` z).\n\n(*This lemma states that for three lattice elements, taking the difference of the difference of the first and second elements with the third is equivalent to taking the difference of the first element with the join of the second and third.*)\nLemma diffBx x y z : (x `\\` y) `\\` z = x `\\` (y `|` z).\n\n(*This lemma states that for three lattice elements, the difference of the first element and the difference of the second and third elements is equal to the join of two terms: the difference of the first and second elements, and the meet of the first and third elements.*)\nLemma diffxB x y z : x `\\` (y `\\` z) = (x `\\` y) `|` (x `&` z).\n\n(*This lemma states that for two lattice elements, the difference between their join and the second element is equal to the difference between the first and the second element.*)\nLemma joinBK x y : (y `|` x) `\\` x = (y `\\` x).\n\n(*This lemma states that for two lattice elements, the difference between their join and the first element is equal to the difference between the second and the first element.*)\nLemma joinBKC x y : (x `|` y) `\\` x = (y `\\` x).\n\n(*This lemma states that for two disjoint lattice elements, whose meet is the bottom element, the first element is less than or equal to the second if and only if the first element is the bottom element.*)\nLemma disj_le x y : x `&` y == \\bot -> x <= y = (x == \\bot).\n\n(*This lemma states that for two lattice elements whose meet is the bottom element, the first is less than or equal to the second if and only if the first is equal to the bottom element.*)\nLemma disj_leC x y : y `&` x == \\bot -> x <= y = (x == \\bot).\n\n(*This lemma states that for two disjoint lattice elements, whose meet is the bottom element, the difference of the first and second elements is equal to the first element.*)\nLemma disj_diffl x y : x `&` y == \\bot -> x `\\` y = x.\n\n(*This lemma states that for two disjoint lattice elements, whose meet is the bottom element, the difference of the second and first elements is equal to the second element.*)\nLemma disj_diffr x y : x `&` y == \\bot -> y `\\` x = y.\n\n(*This lemma states that for two lattice elements, if the first is strictly less than the second, then the bottom element is strictly less than the difference of the second and the first.*)\nLemma lt0B x y : x < y -> \\bot < y `\\` x.\n\nEnd CBDistrLatticeTheory.\nEnd CBDistrLatticeTheory.\n\nModule Import CTDistrLatticeTheory.\nSection CTDistrLatticeTheory.\nContext {disp : disp_t} {L : ctDistrLatticeType disp}.\nImplicit Types (x y z : L).\n\n(*This lemma states that for two lattice elements in a complemented lattice with a top element, their co-difference is equal to the join of the complement of the first element and the second element.*)\nLemma codiffErcompl x y : codiff x y = rcompl x \\top y.\n\nEnd CTDistrLatticeTheory.\nEnd CTDistrLatticeTheory.\n\nModule Import CTBDistrLatticeTheory.\nSection CTBDistrLatticeTheory.\nContext {disp : disp_t} {L : ctbDistrLatticeType disp}.\nImplicit Types (x y z : L).\n\n(*This lemma states that for a lattice element in a complemented lattice with a top element, its complement is equal to the difference between the top element and the lattice element itself.*)\nLemma complEdiff x : ~` x = \\top `\\` x. \n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use complEdiff instead.\")]\n(*This deprecated notation is an alias for a theorem asserting that the complement of an element equals the difference between the top element and that element.*)\nNotation complE := complEdiff.\n\n(*This lemma states that the complement of an element is equal to the co-difference between the bottom element and the given element.*)\nLemma complEcodiff x : ~` x = codiff \\bot x. \n\n(*This lemma states that the complement of an element is equal to its relative complement within the interval bounded by the bottom and top elements.*)\nLemma complErcompl x : ~` x = rcompl \\bot \\top x.\n\n(*This lemma states that the difference between the top element and a given element is equal to the complement of that element.*)\nLemma diff1x x : \\top `\\` x = ~` x.\n\n(*This lemma states that the difference between two elements is equivalent to the meet of the first element and the complement of the second element.*)\nLemma diffE x y : x `\\` y = x `&` ~` y.\n\n(*This lemma states that the complement operation is an involution, which means that applying the complement operation twice to an element returns the original element.*)\nLemma complK : involutive (@compl _ L).\n\n(*This lemma states that the complement operation is injective, meaning that if two elements have the same complement, then the elements themselves must be equal.*)\nLemma compl_inj : injective (@compl _ L).\n\n(*This lemma states that two elements are disjoint, meaning their meet is the bottom element, if and only if the first element is less than or equal to the complement of the second element.*)\nLemma disj_leC x y : (x `&` y == \\bot) = (x <= ~` y).\n\n(*This lemma states that the complement of a first element being less than or equal to a second element is equivalent to the complement of the second element being less than or equal to the first element.*)\nLemma leCx x y : (~` x <= y) = (~` y <= x).\n\n(*This lemma states that a first element being less than or equal to the complement of a second element is equivalent to the second element being less than or equal to the complement of the first element.*)\nLemma lexC x y : (x <= ~` y) = (y <= ~` x).\n\n(*This lemma states that the complement of a first element is less than or equal to the complement of a second element if and only if the second element is less than or equal to the first element.*)\nLemma leC x y : (~` x <= ~` y) = (y <= x).\n\n(*This lemma provides one of De Morgan's laws, stating that the complement of the join of two elements is equal to the meet of their respective complements.*)\nLemma complU x y : ~` (x `|` y) = ~` x `&` ~` y.\n\n(*This lemma provides one of De Morgan's laws, stating that the complement of the meet of two elements is equal to the join of their respective complements.*)\nLemma complI x y : ~` (x `&` y) = ~` x `|` ~` y.\n\n(*This lemma states that the join of an element and its complement equals the top element of the lattice.*)\nLemma joinxC x : x `|` ~` x = \\top.\n\n(*This lemma states that the join of the complement of an element with the element itself equals the top element of the lattice.*)\nLemma joinCx x : ~` x `|` x = \\top.\n\n(*This lemma states that the meet of an element and its complement equals the bottom element of the lattice.*)\nLemma meetxC x : x `&` ~` x = \\bot.\n\n(*This lemma states that the meet of the complement of an element with the element itself equals the bottom element of the lattice.*)\nLemma meetCx x : ~` x `&` x = \\bot.\n\n(*This lemma states that the complement of the top element is the bottom element.*)\nLemma compl1 : ~` \\top = \\bot :> L.\n\n(*This lemma states that the complement of the bottom element is the top element.*)\nLemma compl0 : ~` \\bot = \\top :> L.\n\n(*This lemma states that the complement of the difference of two elements is equal to the join of the complement of the first element with the second element.*)\nLemma complB x y : ~` (x `\\` y) = ~` x `|` y.\n\n(*This lemma states that the difference between a first element and a second element is less than or equal to the complement of the second element.*)\nLemma leBC x y : x `\\` y <= ~` y.\n\n(*This lemma states a generalized De Morgan's law, asserting that for a given function, the complement of the indexed join of its results over a sequence is equal to the indexed meet of the complements of those results.*)\nLemma compl_joins (J : Type) (r : seq J) (P : {pred J}) (F : J -> L) :\n ~` (\\join_(j <- r | P j) F j) = \\meet_(j <- r | P j) ~` F j.\n\n(*This lemma states a generalized De Morgan's law, asserting that for a given function, the complement of the indexed meet of its results over a sequence is equal to the indexed join of the complements of those results.*)\nLemma compl_meets (J : Type) (r : seq J) (P : {pred J}) (F : J -> L) :\n ~` (\\meet_(j <- r | P j) F j) = \\join_(j <- r | P j) ~` F j.\n\nEnd CTBDistrLatticeTheory.\nEnd CTBDistrLatticeTheory.\n\n(*This record encapsulates the property of antisymmetry, which is required to upgrade a preorder structure into a partial order structure.*)\nHB.factory Record Preorder_isPOrder (d : disp_t) T of Preorder d T := {\n le_anti : antisymmetric (@le d T);\n}.\n\nHB.builders Context (d : disp_t) T of Preorder_isPOrder d T.\n\n(*This definition establishes that the greater-than-or-equal-to relation is antisymmetric, a property derived from the antisymmetry of the less-than-or-equal-to relation.*)\nLet ge_anti : antisymmetric (fun x y => @le d T y x).\n\nHB.instance Definition _ := Preorder_isDuallyPOrder.Build d T le_anti ge_anti.\n\nHB.end.\n\n(*This record defines a partial order structure by packaging a less-than-or-equal-to relation and a less-than relation, along with proofs asserting that the less-than-or-equal-to relation is reflexive, antisymmetric, and transitive.*)\nHB.factory Record isPOrder (d : disp_t) T of Choice T := {\n le : rel T;\n lt : rel T;\n lt_def : forall x y, lt x y = (y != x) && (le x y);\n le_refl : reflexive le;\n le_anti : antisymmetric le;\n le_trans : transitive le;\n}.\n\nHB.builders Context (d : disp_t) T of isPOrder d T.\n\nLet lt_le_def x y : lt x y = le x y && ~~ le y x.\n\nHB.instance Definition _ := isPreorder.Build d T lt_le_def le_refl le_trans.\nHB.instance Definition _ := Preorder_isPOrder.Build d T le_anti.\n\nHB.end.\n\n(*This record defines a partial order structure based on a given less-than-or-equal-to relation, requiring proofs that this relation is reflexive, antisymmetric, and transitive.*)\nHB.factory Record Le_isPOrder (d : disp_t) T of Choice T := {\n le : rel T;\n le_refl : reflexive le;\n le_anti : antisymmetric le;\n le_trans : transitive le;\n}.\n\nHB.builders Context (d : disp_t) T of Le_isPOrder d T.\n\nHB.instance Definition _ := @Le_isPreorder.Build d T le le_refl le_trans.\nHB.instance Definition _ := @Preorder_isPOrder.Build d T le_anti.\nHB.end.\n\n(*This record defines a partial order structure from a given strict less-than relation, requiring proofs that this relation is irreflexive and transitive, and specifying that the less-than-or-equal-to relation is defined as the disjunction of equality and the strict less-than relation.*)\nHB.factory Record LtLe_isPOrder (d : disp_t) T of Choice T := {\n le : rel T;\n lt : rel T;\n le_def : forall x y, le x y = (x == y) || lt x y;\n lt_irr : irreflexive lt;\n lt_trans : transitive lt;\n}.\n\nHB.builders Context (d : disp_t) T of LtLe_isPOrder d T.\n\nHB.instance Definition _ := @LtLe_isPreorder.Build d T le lt le_def lt_irr lt_trans.\n\nLet le_anti : antisymmetric le.\n\nHB.instance Definition _ := @Preorder_isPOrder.Build d T le_anti.\n\nHB.end.\n\n(*This record defines a partial order structure derived entirely from a strict less-than relation, requiring proofs that this relation is irreflexive and transitive.*)\nHB.factory Record Lt_isPOrder (d : disp_t) T of Choice T := {\n lt : rel T;\n lt_irr : irreflexive lt;\n lt_trans : transitive lt;\n}.\n\nHB.builders Context d T of Lt_isPOrder d T.\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := @LtLe_isPOrder.Build d T\n _ lt (fun _ _ => erefl) lt_irr lt_trans.\nHB.end.\n\n(*This record provides the structure for a meet-semilattice on a type that already has a partial order, typically by defining a meet operation and proving it is a greatest lower bound.*)\nHB.factory Record POrder_Meet_isSemilattice d T of POrder d T := {\n meet : T -> T -> T;\n meetC : commutative meet;\n meetA : associative meet;\n leEmeet : forall x y, (x <= y) = (meet x y == x);\n}.\n\nHB.builders Context d T of POrder_Meet_isSemilattice d T.\n\nFact meetxx : idempotent_op meet.\n\nFact lexI x y z : (x <= meet y z) = (x <= y) && (x <= z).\n\nHB.instance Definition _ := @POrder_isMeetSemilattice.Build d T meet lexI.\n\nHB.end.\n\n(*A structure representing a join-semilattice, which is a partially ordered type equipped with a binary join operation that is commutative, associative, and connected to the order relation such that the join of two elements is the first element if and only if the second element is less than or equal to the first.*)\nHB.factory Record POrder_Join_isSemilattice d T of POrder d T := {\n join : T -> T -> T;\n joinC : commutative join;\n joinA : associative join;\n leEjoin : forall x y, (y <= x) = (join x y == x);\n}.\n\nHB.builders Context d T of POrder_Join_isSemilattice d T.\n\nFact joinxx : idempotent_op join.\n\nFact leUx x y z : (join x y <= z) = (x <= z) && (y <= z).\n\nHB.instance Definition _ := @POrder_isJoinSemilattice.Build d T join leUx.\n\nHB.end.\n\n(*A structure representing a lattice on a partially ordered type, defined by providing binary meet and join operations whose properties are characterized through the order relation. Specifically, an element is less than or equal to the meet of two others if and only if it is less than or equal to both, and the join of two elements is less than or equal to a third if and only if both are less than or equal to the third.*)\nHB.factory Record POrder_MeetJoin_isLattice d T of POrder d T := {\n meet : T -> T -> T;\n join : T -> T -> T;\n meetP : forall x y z, (x <= meet y z) = (x <= y) && (x <= z);\n joinP : forall x y z, (join x y <= z) = (x <= z) && (y <= z);\n}.\n\nHB.builders Context d T of POrder_MeetJoin_isLattice d T.\nHB.instance Definition _ := @POrder_isMeetSemilattice.Build d T meet meetP.\nHB.instance Definition _ := @POrder_isJoinSemilattice.Build d T join joinP.\nHB.end.\n\n(*A structure representing a lattice on a partially ordered type, defined axiomatically with binary meet and join operations. These operations are required to be commutative, associative, satisfy the absorption laws, and connect to the order relation such that one element is less than or equal to another if and only if their meet equals the first element.*)\nHB.factory Record POrder_isLattice d T of POrder d T := {\n meet : T -> T -> T;\n join : T -> T -> T;\n meetC : commutative meet;\n joinC : commutative join;\n meetA : associative meet;\n joinA : associative join;\n joinKI : forall y x, meet x (join x y) = x;\n meetKU : forall y x, join x (meet x y) = x;\n leEmeet : forall x y, (x <= y) = (meet x y == x);\n}.\n\nHB.builders Context d T of POrder_isLattice d T.\n\n(*This lemma states that for any two elements in a lattice, the second element is less than or equal to the first if and only if their join is equal to the first element.*)\nFact leEjoin x y : (y <= x) = (join x y == x).\n\n(*This fact states that the meet operation is idempotent, meaning that the meet of an element with itself is the element itself.*)\nFact meetxx : idempotent_op meet.\n\n(*This fact states that an element is less than or equal to the meet of two other elements if and only if it is less than or equal to each of those two elements individually.*)\nFact lexI x y z : (x <= meet y z) = (x <= y) && (x <= z).\n\n(*This lemma states that the join operation is idempotent, meaning applying it to two identical elements yields that same element.*)\nFact joinxx : idempotent_op join.\n\n(*This lemma states that in a lattice, the join of two elements is less than or equal to a third element if and only if each of the two original elements is less than or equal to that third element.*)\nFact leUx x y z : (join x y <= z) = (x <= z) && (y <= z).\n\nHB.instance Definition _ := @POrder_MeetJoin_isLattice.Build d T\n meet join lexI leUx.\n\nHB.end.\n\n(*A structure that enhances a lattice to a distributive lattice by adding the requirement that the meet operation distributes over the join operation from the left.*)\nHB.factory Record Lattice_Meet_isDistrLattice d T of Lattice d T := {\n meetUl : @left_distributive T T meet join;\n}.\n\nHB.builders Context d T of Lattice_Meet_isDistrLattice d T.\n\n(*This theorem states that in a lattice, if the meet operation is left-distributive over the join operation, then it is also right-distributive over the join operation.*)\nLet meetUr : right_distributive (@meet _ T) (@join _ T).\n\n(*This theorem states that in a lattice, if the meet operation is left-distributive over the join operation, then the join operation is left-distributive over the meet operation.*)\nLet joinIl : left_distributive (@join _ T) (@meet _ T).\n\nHB.instance Definition _ := Lattice_isDistributive.Build d T meetUl joinIl.\n\nHB.end.\n\n(*A structure representing a distributive lattice built upon a partially ordered type, defined by providing binary meet and join operations that are commutative, associative, satisfy the absorption and distributivity laws, and are linked to the order through the meet operation.*)\nHB.factory Record POrder_Meet_isDistrLattice d T of POrder d T := {\n meet : T -> T -> T;\n join : T -> T -> T;\n meetC : commutative meet;\n joinC : commutative join;\n meetA : associative meet;\n joinA : associative join;\n joinKI : forall y x, meet x (join x y) = x;\n meetKU : forall y x, join x (meet x y) = x;\n leEmeet : forall x y, (x <= y) = (meet x y == x);\n meetUl : left_distributive meet join;\n}.\n\nHB.builders Context d T of POrder_Meet_isDistrLattice d T.\n\nHB.instance Definition _ := @POrder_isLattice.Build d T\n meet join meetC joinC meetA joinA joinKI meetKU leEmeet.\nHB.instance Definition _ :=\n Lattice_Meet_isDistrLattice.Build d T meetUl.\n\nHB.end.\n\n(*A structure that defines a distributive lattice starting from binary meet and join operations. It specifies properties such as commutativity, associativity, absorption, and distributivity, and defines the less-than-or-equal and less-than relations in terms of the meet operation.*)\nHB.factory Record isMeetJoinDistrLattice (d : disp_t) T of Choice T := {\n le : rel T;\n lt : rel T;\n meet : T -> T -> T;\n join : T -> T -> T;\n le_def : forall x y : T, le x y = (meet x y == x);\n lt_def : forall x y : T, lt x y = (y != x) && le x y;\n meetC : commutative meet;\n joinC : commutative join;\n meetA : associative meet;\n joinA : associative join;\n joinKI : forall y x : T, meet x (join x y) = x;\n meetKU : forall y x : T, join x (meet x y) = x;\n meetUl : left_distributive meet join;\n meetxx : idempotent_op meet;\n}.\n\nHB.builders Context d T of isMeetJoinDistrLattice d T.\n\nFact le_refl : reflexive le. \n\nFact le_anti : antisymmetric le.\n\nFact le_trans : transitive le.\n\nFact lt_le_def x y : lt x y = (le x y) && ~~ (le y x).\n\nHB.instance Definition _ := isPreorder.Build d T\n lt_le_def le_refl le_trans.\nHB.instance Definition _ := Preorder_isPOrder.Build d T le_anti.\n\nHB.instance Definition _ := @POrder_Meet_isDistrLattice.Build d T\n meet join meetC joinC meetA joinA joinKI meetKU le_def meetUl.\n\nHB.end.\n\n(*A structure that equips a bounded distributive lattice with a sectional complement, which is a binary difference operation. This operation ensures that the meet of an element with its difference from another is the bottom element, and that the join of the meet of two elements with their difference reconstructs the first element.*)\nHB.factory Record BDistrLattice_hasSectionalComplement d T\n of BDistrLattice d T := {\n diff : T -> T -> T;\n diffKI : forall x y, y `&` diff x y = \\bot;\n joinIB : forall x y, (x `&` y) `|` diff x y = x;\n}.\n\nModule hasRelativeComplement.\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use BDistrLattice_hasSectionalComplement.Build instead.\")]\nNotation Build d T :=\n (BDistrLattice_hasSectionalComplement.Build d T) (only parsing).\nEnd hasRelativeComplement.\n\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use BDistrLattice_hasSectionalComplement instead.\")]\nNotation hasRelativeComplement d T :=\n (BDistrLattice_hasSectionalComplement d T) (only parsing).\n\nHB.builders Context d T of BDistrLattice_hasSectionalComplement d T.\n\nDefinition rcompl x y z := (x `&` y) `|` diff (y `|` x) z.\n\nFact rcomplPmeet x y z : ((x `&` y) `|` z) `&` rcompl x y z = x `&` y.\n\nFact rcomplPjoin x y z : ((y `|` x) `&` z) `|` rcompl x y z = y `|` x.\n\nHB.instance Definition _ :=\n @DistrLattice_hasRelativeComplement.Build d T rcompl rcomplPmeet rcomplPjoin.\n\n(*This fact states that the difference between two elements is equivalent to the relative complement of the second element with respect to the first, within the interval starting from the bottom element.*)\nFact diffErcompl x y : diff x y = rcompl \\bot x y.\n\nHB.instance Definition _ :=\n @CDistrLattice_hasSectionalComplement.Build d T diff diffErcompl.\n\nHB.end.\n\n(*A structure that equips a top-bounded distributive lattice with a dual sectional complement, which is a binary co-difference operation. This operation ensures that the join of an element with its co-difference from another is the top element, and that the meet of the join of two elements with their co-difference reconstructs the first element.*)\nHB.factory Record TDistrLattice_hasDualSectionalComplement d T\n of TDistrLattice d T := {\n codiff : T -> T -> T;\n codiffKU : forall x y, y `|` codiff x y = \\top;\n meetUB : forall x y, (x `|` y) `&` codiff x y = x;\n}.\n\nHB.builders Context d T of TDistrLattice_hasDualSectionalComplement d T.\n\nDefinition rcompl x y z := (y `|` x) `&` codiff (x `&` y) z.\n\n(*This fact states an identity involving the meet, join, and relative complement operations. It asserts that the meet of '(the join of z with the meet of x and y)' with 'the relative complement of y in the interval from z to x' is equal to 'the meet of x and y'.*)\nFact rcomplPmeet x y z : ((x `&` y) `|` z) `&` rcompl x y z = x `&` y.\n\n(*This fact states an identity involving the join, meet, and relative complement operations. It asserts that taking the join of '(the join of y and x) meet z' with 'the relative complement of y in the interval from z to x' results in 'the join of y and x'.*)\nFact rcomplPjoin x y z : ((y `|` x) `&` z) `|` rcompl x y z = y `|` x.\n\nHB.instance Definition _ :=\n @DistrLattice_hasRelativeComplement.Build d T rcompl rcomplPmeet rcomplPjoin.\n\nFact codiffErcompl x y : codiff x y = rcompl x \\top y.\n\nHB.instance Definition _ :=\n @CDistrLattice_hasDualSectionalComplement.Build d T codiff codiffErcompl.\n\nHB.end.\n\n(*A structure that equips a bounded distributive lattice that has a top element with a complement operation, where the complement of an element is defined as its difference from the top element.*)\nHB.factory Record CBDistrLattice_hasComplement d T\n of CBDistrLattice d T & hasTop d T := {\n compl : T -> T;\n complEdiff : forall x, compl x = (\\top : T) `\\` x; \n}.\n\nModule hasComplement.\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use CBDistrLattice_hasComplement.Build instead.\")]\nNotation Build d T := (CBDistrLattice_hasComplement.Build d T) (only parsing).\nEnd hasComplement.\n\n#[deprecated(since=\"mathcomp 2.3.0\",\n note=\"Use CBDistrLattice_hasComplement instead.\")]\nNotation hasComplement d T := (CBDistrLattice_hasComplement d T) (only parsing).\n\nHB.builders Context d T of CBDistrLattice_hasComplement d T.\n\nHB.instance Definition _ := @CDistrLattice_hasDualSectionalComplement.Build d T\n (fun x y => rcompl x \\top y) (fun _ _ => erefl).\n\nFact complEcodiff (x : T) : compl x = codiff (\\bot : T) x.\n\nHB.instance Definition _ :=\n @CDistrLattice_hasComplement.Build d T compl complEdiff complEcodiff.\n\nHB.end.\n\n(*A structure that equips a top-bounded distributive lattice that has a bottom element with a complement operation, where the complement of an element is defined as its co-difference from the bottom element.*)\nHB.factory Record CTDistrLattice_hasComplement d T\n of CTDistrLattice d T & hasBottom d T := {\n compl : T -> T;\n complEcodiff : forall x, compl x = codiff (\\bot : T) x;\n}.\n\nHB.builders Context d T of CTDistrLattice_hasComplement d T.\n\nHB.instance Definition _ := @CDistrLattice_hasSectionalComplement.Build d T\n (fun x y => rcompl (\\bot : T) x y) (fun _ _ => erefl).\n\nFact complEdiff (x : T) : compl x = (\\top : T) `\\` x.\n\nHB.instance Definition _ :=\n @CDistrLattice_hasComplement.Build d T compl complEdiff complEcodiff.\n\nHB.end.\n\n(*A structure representing a complemented distributive lattice with both top and bottom elements. It provides a unary complement operation such that the join of any element with its complement is the top element, and their meet is the bottom element.*)\nHB.factory Record TBDistrLattice_hasComplement d T of TBDistrLattice d T := {\n compl : T -> T;\n joinxC : forall x, x `|` compl x = \\top;\n meetxC : forall x, x `&` compl x = \\bot;\n}.\n\nHB.builders Context d T of TBDistrLattice_hasComplement d T.\n\n(*This definition specifies the difference of two elements as the meet of the first element and the complement of the second.*)\nDefinition diff x y := x `&` compl y.\n(*This definition specifies the co-difference of two elements as the join of the first element and the complement of the second.*)\nDefinition codiff x y := x `|` compl y.\n(*This definition specifies the relative complement of three elements as the join of the meet of the first two elements with the difference between the join of the second and first elements and the third element.*)\nDefinition rcompl x y z := (x `&` y) `|` diff (y `|` x) z.\n\n(*This lemma states that the meet of an element with the difference between a second element and the first element is always the bottom element.*)\nFact diffKI x y : y `&` diff x y = \\bot.\n\n(*This lemma states that the join of the meet of two elements with their difference is equal to the first element.*)\nFact joinIB x y : (x `&` y) `|` diff x y = x.\n\nHB.instance Definition _ :=\n @BDistrLattice_hasSectionalComplement.Build d T diff diffKI joinIB.\n\n(*This lemma states that the co-difference of two elements is equivalent to the relative complement of the first element, the top element, and the second element.*)\nFact codiffErcompl x y : codiff x y = rcompl x \\top y.\n\nHB.instance Definition _ :=\n @CDistrLattice_hasDualSectionalComplement.Build d T codiff codiffErcompl.\n\n(*This lemma states that the complement of an element is equal to the difference between the top element and that element.*)\nFact complEdiff x : compl x = diff \\top x. \n(*This lemma states that the complement of an element is equal to the co-difference between the bottom element and that element.*)\nFact complEcodiff x : compl x = codiff \\bot x. \n\nHB.instance Definition _ :=\n @CDistrLattice_hasComplement.Build d T compl complEdiff complEcodiff.\n\nHB.end.\n\n(*A structure that refines a lattice by asserting that its underlying partial order is a total order, meaning any two elements in the type are comparable.*)\nHB.factory Record Lattice_isTotal d T of Lattice d T := {\n le_total : total (<=%O : rel T)\n}.\n\nHB.builders Context d T of Lattice_isTotal d T.\n\nFact meetUl : @left_distributive T T meet join.\n\nHB.instance Definition _ := Lattice_Meet_isDistrLattice.Build d T meetUl.\nHB.instance Definition _ := DistrLattice_isTotal.Build d T le_total.\n\nHB.end.\n\n(*This factory enhances a partially ordered type into a totally ordered type by requiring a proof that its 'less-than-or-equal-to' relation is total, meaning any two elements are comparable.*)\nHB.factory Record POrder_isTotal d T of POrder d T := {\n le_total : total (<=%O : rel T) }.\n\nHB.builders Context d T of POrder_isTotal d T.\n\nImplicit Types (x y z : T).\n\n(*This definition establishes that any two elements from a totally ordered type are comparable, meaning one is less than or equal to the other.*)\nLet comparableT x y : x >=< y := le_total x y.\n\n(*This lemma provides a case analysis principle for any two elements of a totally ordered type, relating their comparison to their minimum, maximum, equality, and their strict and non-strict order relationships.*)\nFact ltgtP x y :\n compare x y (min y x) (min x y) (max y x) (max x y)\n (y == x) (x == y) (x >= y) (x <= y) (x > y) (x < y).\n\n(*This lemma provides a case analysis for two elements in a totally ordered type, asserting that either the first is less than or equal to the second, or the second is strictly less than the first, and connects this dichotomy to their minimum and maximum values.*)\nFact leP x y : le_xor_gt x y\n (min y x) (min x y) (max y x) (max x y) (x <= y) (y < x).\n\nDefinition meet := @min _ T.\nDefinition join := @max _ T.\n\nFact meetC : commutative meet.\n\nFact joinC : commutative join.\n\nFact meetA : associative meet.\n\nFact joinA : associative join.\n\nFact joinKI y x : meet x (join x y) = x.\n\n(*This fact states the absorption law for lattices, asserting that the join of an element with the meet of that same element and another element yields the original element.*)\nFact meetKU y x : join x (meet x y) = x.\n\n(*This lemma states that an element is less than or equal to another element if and only if their meet (minimum) is equal to the first element.*)\nFact leEmeet x y : (x <= y) = (meet x y == x).\n\nHB.instance Definition _ := @POrder_isLattice.Build d T\n meet join meetC joinC meetA joinA joinKI meetKU leEmeet.\nHB.instance Definition _ :=\n Lattice_isTotal.Build d T comparableT.\nHB.end.\n\n(*This factory record defines the structure of a total order on a type. It requires a 'less-than-or-equal-to' relation that is antisymmetric, transitive, and total, and from this, it defines the 'less-than' relation as well as the 'meet' and 'join' operations.*)\nHB.factory Record isOrder (d : disp_t) T of Choice T := {\n le : rel T;\n lt : rel T;\n meet : T -> T -> T;\n join : T -> T -> T;\n lt_def : forall x y, lt x y = (y != x) && le x y;\n meet_def : forall x y, meet x y = if lt x y then x else y;\n join_def : forall x y, join x y = if lt x y then y else x;\n le_anti : antisymmetric le;\n le_trans : transitive le;\n le_total : total le;\n}.\n\nHB.builders Context d T of isOrder d T.\n\n(*This lemma states that the 'less-than-or-equal-to' relation defined within a total order structure is reflexive, meaning every element is less than or equal to itself.*)\nFact le_refl : reflexive le.\n\n(*This lemma states that one element is strictly less than another if and only if the first is less than or equal to the second, and the second is not less than or equal to the first.*)\nFact lt_le_def x y : lt x y = (le x y) && ~~ (le y x).\n\nHB.instance Definition _ := isPreorder.Build d T\n lt_le_def le_refl le_trans.\nHB.instance Definition _ := Preorder_isPOrder.Build d T le_anti.\n\nSection GeneratedOrder.\n\n(*This is a local alias for the carrier type of the total order structure, created to associate it with new canonical instances within a specific scope.*)\nLocal Definition T' := T.\nHB.instance Definition _ := POrder.on T'.\n(*This lemma states that the 'meet' operation, defined constructively using a conditional on the 'less-than' relation, is equivalent to the canonical meet operation of the generated lattice structure.*)\nFact meetE x y : meet x y = x `&` y. \n(*This lemma states that the 'join' operation, defined constructively using a conditional on the 'less-than' relation, is equivalent to the canonical join operation of the generated lattice structure.*)\nFact joinE x y : join x y = x `|` y. \n(*This lemma states that the 'meet' operation is commutative, meaning the order of its two arguments does not affect the result.*)\nFact meetC : commutative meet.\n\n(*This lemma states that the 'join' operation is commutative, meaning the order of its two arguments does not affect the result.*)\nFact joinC : commutative join.\n\n(*This lemma states that the 'meet' operation is associative, meaning that when applied to three elements, the grouping of the operations does not affect the final result.*)\nFact meetA : associative meet.\n\n(*This lemma states that the 'join' operation is associative, meaning that when applied to three elements, the grouping of the operations does not affect the final result.*)\nFact joinA : associative join.\n\n(*This lemma states that for any two elements from a lattice, the meet (minimum) of the first element with the join (maximum) of both elements is equal to the first element. This is also known as an absorption law.*)\nFact joinKI y x : meet x (join x y) = x.\n\n(*This lemma states that for any two elements from a lattice, the join (maximum) of the first element with the meet (minimum) of both elements is equal to the first element. This is also known as an absorption law.*)\nFact meetKU y x : join x (meet x y) = x.\n\n(*This fact states that the meet operation distributes over the join operation from the left.*)\nFact meetUl : left_distributive meet join.\n\n(*This fact states that the meet operation is idempotent, meaning the meet of an element with itself is the element itself.*)\nFact meetxx : idempotent_op meet.\n\n(*This fact defines the less-than-or-equal-to relation in terms of the meet operation, stating that one element is less than or equal to another if and only if their meet is the first element.*)\nFact le_def x y : x <= y = (meet x y == x).\n\nEnd GeneratedOrder.\n\nHB.instance Definition _ := @POrder_Meet_isDistrLattice.Build d T\n meet join meetC joinC meetA joinA joinKI meetKU le_def meetUl.\nHB.instance Definition _ := DistrLattice_isTotal.Build d T le_total.\n\nHB.end.\n\n(*This record defines the structure of a strict total order, where the less-than-or-equal-to relation, meet, and join are all derived from a primitive, irreflexive, transitive, and total 'less than' relation.*)\nHB.factory Record LtOrder (d : disp_t) T of Choice T := {\n le : rel T;\n lt : rel T;\n meet : T -> T -> T;\n join : T -> T -> T;\n le_def : forall x y, le x y = (x == y) || lt x y;\n meet_def : forall x y, meet x y = if lt x y then x else y;\n join_def : forall x y, join x y = if lt x y then y else x;\n lt_irr : irreflexive lt;\n lt_trans : transitive lt;\n lt_total : forall x y, x != y -> lt x y || lt y x;\n}.\n\nHB.builders Context d T of LtOrder d T.\n\n(*This fact defines the strict less-than relation in terms of the non-strict less-than-or-equal-to relation, stating that one element is strictly less than another if it is less than or equal to the other and not equal to it.*)\nFact lt_def x y : lt x y = (y != x) && le x y.\n\n(*This fact defines the meet of two elements in a total order based on the strict less-than relation: it is the first element if it is strictly less than the second, and the second element otherwise.*)\nFact meet_def_le x y : meet x y = if lt x y then x else y.\n\n(*This fact defines the join of two elements in a total order based on the strict less-than relation: it is the second element if the first is strictly less than it, and the first element otherwise.*)\nFact join_def_le x y : join x y = if lt x y then y else x.\n\n(*This fact states that the less-than-or-equal-to relation is antisymmetric, meaning if two elements are less than or equal to each other, they must be equal.*)\nFact le_anti : antisymmetric le.\n\n(*This fact states that the less-than-or-equal-to relation is transitive, meaning if a first element is less than or equal to a second, and the second is less than or equal to a third, then the first is less than or equal to the third.*)\nFact le_trans : transitive le.\n\n(*This fact states that the less-than-or-equal-to relation is total, meaning for any pair of elements, one must be less than or equal to the other.*)\nFact le_total : total le.\n\nHB.instance Definition _ :=\n isOrder.Build d T lt_def meet_def_le join_def_le le_anti le_trans le_total.\nHB.end.\n\n(*This record provides a structure to prove that a preorder is total by exhibiting a monotonic function from it to another type that is already equipped with a total order.*)\nHB.factory Record MonoTotal disp T of POrder disp T := {\n disp' : disp_t;\n T' : orderType disp';\n f : T -> T';\n f_mono : {mono f : x y / x <= y}\n}.\nHB.builders Context disp T of MonoTotal disp T.\n(*This fact states that the underlying preorder relation is total, a property derived from the existence of a monotonic function to a total order as specified by the context.*)\nFact totalT : total (<=%O : rel T).\n\nHB.instance Definition _ := POrder_isTotal.Build disp T totalT.\nHB.end.\n\nModule CancelPartial.\nImport PreCancelPartial.\nSection CancelPartial.\nVariables (disp : disp_t) (T : choiceType).\nVariables (disp' : disp_t) (T' : porderType disp') (f : T -> T').\n\nSection Pcan.\nVariables (f' : T' -> option T) (f_can : pcancel f f').\n\n(*This fact asserts that the relation induced on a type by a function mapping into a partial order is antisymmetric, provided the function has a partial inverse.*)\nFact anti : antisymmetric (le f).\n\n(*This definition specifies that one element is strictly less than another if and only if the two elements are not equal and the first element is less than or equal to the second.*)\nFact lt_def x y :\n lt f x y = (y != x) && le f x y.\n\n(*This definition constructs a partial order structure on a given choice type by inheriting the order from another partially ordered type through a function that has a partial inverse.*)\nDefinition Pcan := isPOrder.Build disp (Choice.Pack (Choice.class T))\n lt_def (@refl T disp' T' f) anti (@trans T disp' T' f).\n\nEnd Pcan.\n\n(*This definition constructs a partial order structure on a choice type by inheriting the order from another partially ordered type through a function that has a total inverse.*)\nDefinition Can f' (f_can : cancel f f') := Pcan (can_pcan f_can).\n\nEnd CancelPartial.\nEnd CancelPartial.\n\n(*This notation provides an alias for the construction that builds a partial order structure from a function with a partial inverse, highlighting that the resulting structure is a partial order.*)\nNotation PCanIsPartial := CancelPartial.Pcan.\n(*This notation provides an alias for the construction that builds a partial order structure from a function with a total inverse, emphasizing that the resulting structure is a partial order.*)\nNotation CanIsPartial := CancelPartial.Can.\n\n#[export]\nHB.instance Definition _ (disp : disp_t) (T : choiceType)\n (disp' : disp_t) (T' : porderType disp') (f : T -> T')\n (f' : T' -> option T) (f_can : pcancel f f') :=\n Preorder_isPOrder.Build disp (pcan_type f_can) (CancelPartial.anti f_can).\n\n#[export]\nHB.instance Definition _ (disp : disp_t) (T : choiceType)\n (disp' : disp_t) (T' : porderType disp') (f : T -> T') (f' : T' -> T)\n (f_can : cancel f f') :=\n Preorder_isPOrder.Build disp (can_type f_can)\n (CancelPartial.anti (can_pcan f_can)).\n\nSection CancelTotal.\nVariables (disp : disp_t) (T : choiceType).\nVariables (disp' : disp_t) (T' : orderType disp') (f : T -> T').\n\nSection PCan.\n\nVariables (f' : T' -> option T) (f_can : pcancel f f').\n\n#[local]\n(*This definition proves that if an order is pulled back from a totally ordered type via a function with a partial inverse, the resulting order on the source type is also total.*)\nDefinition PCanIsTotal : DistrLattice_isTotal _ (pcan_type f_can) :=\n Total.on (pcan_type f_can).\n\nEnd PCan.\n\nSection Can.\n\nVariables (f' : T' -> T) (f_can : cancel f f').\n\n#[local]\n(*This definition proves that if an order is pulled back from a totally ordered type via a function with a total inverse, the resulting order on the source type is also total.*)\nDefinition CanIsTotal : DistrLattice_isTotal _ (can_type f_can) :=\n Total.on (can_type f_can).\n\nEnd Can.\nEnd CancelTotal.\n\n(*This record factory defines the structure for a type that is a lattice by virtue of being isomorphic to another existing lattice. It packages the type, its partial order, the isomorphic target lattice, the pair of inverse functions establishing the isomorphism, and the proof that the forward function is monotone.*)\nHB.factory Record IsoLattice disp T of POrder disp T := {\n disp' : disp_t;\n T' : latticeType disp';\n f : T -> T';\n f' : T' -> T;\n f_can : cancel f f';\n f'_can : cancel f' f;\n f_mono : {mono f : x y / x <= y};\n}.\n\nHB.builders Context disp T of IsoLattice disp T.\n\n(*This definition specifies the meet operation on an isomorphic lattice. The meet of two elements is calculated by mapping both elements to the target lattice, computing their meet in that lattice, and then mapping the result back.*)\nDefinition meet (x y : T) := f' (meet (f x) (f y)).\n(*This definition specifies the join operation on an isomorphic lattice. The join of two elements is calculated by mapping both elements to the target lattice, computing their join in that lattice, and then mapping the result back.*)\nDefinition join (x y : T) := f' (join (f x) (f y)).\n\n(*This fact asserts that the meet operation is commutative.*)\nFact meetC : commutative meet. \n(*This fact asserts that the join operation is commutative.*)\nFact joinC : commutative join. \n(*This fact asserts that the meet operation is associative.*)\nFact meetA : associative meet.\n\n(*This fact asserts that the join operation is associative.*)\nFact joinA : associative join.\n\n(*This fact states the absorption law for lattices, asserting that the meet of an element with the join of that same element and another element yields the original element.*)\nFact joinKI y x : meet x (join x y) = x.\n\n(*This lemma states the absorption law for the join and meet operations on the isomorphic lattice, specifically that the join of an element with the meet of that same element and another is equal to the original element.*)\nFact meetKI y x : join x (meet x y) = x.\n\n(*This lemma establishes the equivalence between the partial order relation and the meet operation. It states that one element is less than or equal to another if and only if their meet is equal to the first element.*)\nFact meet_eql x y : (x <= y) = (meet x y == x).\n\nHB.instance Definition _ := POrder_isLattice.Build _ T\n meetC joinC meetA joinA joinKI meetKI meet_eql.\n\nHB.end.\n\n(*This record factory defines the structure for a type that is a distributive lattice by virtue of being isomorphic to another existing distributive lattice. It packages the type, its partial order, the isomorphic target lattice, the inverse functions establishing the isomorphism, and the proof that the forward function is monotone.*)\nHB.factory Record IsoDistrLattice disp T of POrder disp T := {\n disp' : disp_t;\n T' : distrLatticeType disp';\n f : T -> T';\n f' : T' -> T;\n f_can : cancel f f';\n f'_can : cancel f' f;\n f_mono : {mono f : x y / x <= y};\n}.\n\nHB.builders Context disp T of IsoDistrLattice disp T.\n\nHB.instance Definition _ := IsoLattice.Build _ T f_can f'_can f_mono.\n\n(*This lemma states that the meet operation is left-distributive over the join operation in the isomorphic distributive lattice.*)\nFact meetUl : left_distributive (meet : T -> T -> T) join.\n\nHB.instance Definition _ := Lattice_Meet_isDistrLattice.Build _ T meetUl.\n\nHB.end.\n\nExport OrderMorphismTheory.\n\n(*This lemma states that an injective order-preserving function between two partially ordered types also preserves the strict less-than relation.*)\nLemma omorph_lt (d : disp_t) (T : porderType d) (d' : disp_t) (T' : porderType d')\n(f : {omorphism T -> T'}) : injective f -> {homo f : x y / x < y}.\n\n(*This definition specifies the property of a function being a meet-morphism between two lattice types. A function has this property if it preserves the meet operation, meaning the function applied to the meet of two elements is equal to the meet of the function applied to each element individually.*)\nDefinition meet_morphism d (T : latticeType d) d' (T' : latticeType d')\n (f : T -> T') : Prop := {morph f : x y / x `&` y}.\n\n(*This definition specifies the property of a function being a join-morphism between two lattice types. A function has this property if it preserves the join operation, meaning the function applied to the join of two elements is equal to the join of the function applied to each element individually.*)\nDefinition join_morphism d (T : latticeType d) d' (T' : latticeType d')\n (f : T -> T') : Prop := {morph f : x y / x `|` y}.\n\n(*This record mixin captures the property of a function being a meet-morphism between two lattices. It requires a proof that the function preserves the meet operation.*)\nHB.mixin Record isMeetLatticeMorphism d (T : latticeType d)\n d' (T' : latticeType d') (apply : T -> T') := {\n omorphI_subproof : meet_morphism apply;\n}.\n\n(*This record mixin captures the property of a function being a join-morphism between two lattices. It requires a proof that the function preserves the join operation.*)\nHB.mixin Record isJoinLatticeMorphism d (T : latticeType d)\n d' (T' : latticeType d') (apply : T -> T') := {\n omorphU_subproof : join_morphism apply;\n}.\n\n(*This structure defines a meet-lattice morphism as a function between two lattice types that is both an order-preserving morphism and a meet-preserving morphism.*)\nHB.structure Definition MeetLatticeMorphism d (T : latticeType d)\n d' (T' : latticeType d') :=\n {f of isMeetLatticeMorphism d T d' T' f & @OrderMorphism d T d' T' f}.\n\n(*This structure defines a join-lattice morphism as a function between two lattice types that is both an order-preserving morphism and a join-preserving morphism.*)\nHB.structure Definition JoinLatticeMorphism d (T : latticeType d)\n d' (T' : latticeType d') :=\n {f of isJoinLatticeMorphism d T d' T' f & @OrderMorphism d T d' T' f}.\n\n(*This structure defines a lattice morphism as a function between two lattice types that preserves both the meet and join operations.*)\nHB.structure Definition LatticeMorphism d (T : latticeType d)\n d' (T' : latticeType d') :=\n {f of @MeetLatticeMorphism d T d' T' f & @JoinLatticeMorphism d T d' T' f}.\n\n(*This factory defines a lattice morphism as an order-preserving function between two lattices that additionally preserves both the meet and join operations.*)\nHB.factory Record isLatticeMorphism d (T : latticeType d)\n d' (T' : latticeType d') (f : T -> T') of @OrderMorphism d T d' T' f := {\n omorphI_subproof : meet_morphism f;\n omorphU_subproof : join_morphism f;\n}.\n\nHB.builders Context d T d' T' f of isLatticeMorphism d T d' T' f.\nHB.instance Definition _ := isMeetLatticeMorphism.Build d T d' T' f\n omorphI_subproof.\nHB.instance Definition _ := isJoinLatticeMorphism.Build d T d' T' f\n omorphU_subproof.\nHB.end.\n\nModule LatticeMorphismExports.\n(*A notation for the type of meet-lattice morphisms, which are functions between two lattices that preserve the meet operation.*)\nNotation \"{ 'mlmorphism' T -> T' }\" :=\n (@MeetLatticeMorphism.type _ T%type _ T'%type) : type_scope.\n(*A notation for the type of join-lattice morphisms, which are functions between two lattices that preserve the join operation.*)\nNotation \"{ 'jlmorphism' T -> T' }\" :=\n (@JoinLatticeMorphism.type _ T%type _ T'%type) : type_scope.\n(*A notation for the type of lattice morphisms, which are functions between two lattices that preserve both the meet and join operations.*)\nNotation \"{ 'lmorphism' T -> T' }\" :=\n (@LatticeMorphism.type _ T%type _ T'%type) : type_scope.\n(*A notation for creating a meet-lattice morphism from a given function and explicitly naming the resulting morphism.*)\nNotation \"[ 'mlmorphism' 'of' f 'as' g ]\" :=\n (MeetLatticeMorphism.clone _ _ _ _ f%function g)\n (format \"[ 'mlmorphism' 'of' f 'as' g ]\") : form_scope.\n(*A notation for creating a meet-lattice morphism from a given function, with the name of the resulting morphism being automatically inferred.*)\nNotation \"[ 'mlmorphism' 'of' f ]\" :=\n (MeetLatticeMorphism.clone _ _ _ _ f%function _)\n (format \"[ 'mlmorphism' 'of' f ]\") : form_scope.\n(*A notation for creating a join-lattice morphism from a given function and explicitly naming the resulting morphism.*)\nNotation \"[ 'jlmorphism' 'of' f 'as' g ]\" :=\n (JoinLatticeMorphism.clone _ _ _ _ f%function g)\n (format \"[ 'jlmorphism' 'of' f 'as' g ]\") : form_scope.\n(*A notation for creating a join-lattice morphism from a given function, with the name of the resulting morphism being automatically inferred.*)\nNotation \"[ 'jlmorphism' 'of' f ]\" :=\n (JoinLatticeMorphism.clone _ _ _ _ f%function _)\n (format \"[ 'jlmorphism' 'of' f ]\") : form_scope.\n(*A notation for creating a lattice morphism from a given function and explicitly naming the resulting morphism.*)\nNotation \"[ 'lmorphism' 'of' f 'as' g ]\" :=\n (LatticeMorphism.clone _ _ _ _ f%function g)\n (format \"[ 'lmorphism' 'of' f 'as' g ]\") : form_scope.\n(*A notation for creating a lattice morphism from a given function, with the name of the resulting morphism being automatically inferred.*)\nNotation \"[ 'lmorphism' 'of' f ]\" :=\n (LatticeMorphism.clone _ _ _ _ f%function _)\n (format \"[ 'lmorphism' 'of' f ]\") : form_scope.\nEnd LatticeMorphismExports.\nHB.export LatticeMorphismExports.\n\nModule Import LatticeMorphismTheory.\nSection LatticeMorphismTheory.\n\nSection Properties.\n\nVariables (d : disp_t) (T : latticeType d) (d' : disp_t) (T' : latticeType d').\n\n(*This lemma states that applying a meet-lattice morphism to the meet of two elements is equivalent to computing the meet of the results of applying the morphism to each element separately.*)\nLemma omorphI (f : {mlmorphism T -> T'}) : {morph f : x y / x `&` y}.\n\n(*This lemma states that applying a join-lattice morphism to the join of two elements is equivalent to computing the join of the results of applying the morphism to each element separately.*)\nLemma omorphU (f : {jlmorphism T -> T'}) : {morph f : x y / x `|` y}.\n\nEnd Properties.\n\nSection IdCompFun.\n\nVariables (d : disp_t) (T : latticeType d) (d' : disp_t) (T' : latticeType d').\nVariables (d'' : disp_t) (T'' : latticeType d'').\n\nSection MeetCompFun.\n\nVariables (f : {mlmorphism T' -> T''}) (g : {mlmorphism T -> T'}).\n\n(*This fact states that the identity function on a lattice is a meet-morphism, meaning it preserves the meet operation.*)\nFact idfun_is_meet_morphism : meet_morphism (@idfun T). \n#[export]\nHB.instance Definition _ := isMeetLatticeMorphism.Build d T d T idfun\n idfun_is_meet_morphism.\n\n(*This fact states that the composition of two meet-lattice morphisms is also a meet-lattice morphism.*)\nFact comp_is_meet_morphism : meet_morphism (f \\o g).\n\n#[export]\n(*This fact states that the identity function on a lattice is a join-morphism, meaning it preserves the join operation.*)\nFact idfun_is_join_morphism : join_morphism (@idfun T). \n#[export]\nHB.instance Definition _ := isJoinLatticeMorphism.Build d T d T idfun\n idfun_is_join_morphism.\n\n(*This fact states that the composition of two join-lattice morphisms is also a join-lattice morphism.*)\nFact comp_is_join_morphism : join_morphism (f \\o g).\n\n#[export]\n(*This mixin record specifies the property for a function between two lattices with bottom elements to be a bottom-preserving morphism, requiring that it maps the bottom element of the domain to the bottom element of the codomain.*)\nHB.mixin Record isBLatticeMorphism d (T : bLatticeType d)\n d' (T' : bLatticeType d') (apply : T -> T') := {\n omorph0_subproof : apply \\bot = \\bot;\n}.\n\n(*This mixin record specifies the property for a function between two lattices with top elements to be a top-preserving morphism, requiring that it maps the top element of the domain to the top element of the codomain.*)\nHB.mixin Record isTLatticeMorphism d (T : tLatticeType d)\n d' (T' : tLatticeType d') (apply : T -> T') := {\n omorph1_subproof : apply \\top = \\top;\n}.\n\n(*This definition establishes the structure for a bottom-lattice morphism, which is a function between two lattices with bottom elements that preserves the bottom element.*)\nHB.structure Definition BLatticeMorphism d (T : bLatticeType d)\n d' (T' : bLatticeType d') := {f of isBLatticeMorphism d T d' T' f}.\n\n(*This definition establishes the structure for a top-lattice morphism, which is a function between two lattices with top elements that preserves the top element.*)\nHB.structure Definition TLatticeMorphism d (T : tLatticeType d)\n d' (T' : tLatticeType d') := {f of isTLatticeMorphism d T d' T' f}.\n\n(*This definition establishes the structure for a top-and-bottom-lattice morphism, which is a function between two lattices with both top and bottom elements that preserves both extremal elements.*)\nHB.structure Definition TBLatticeMorphism d (T : tbLatticeType d)\n d' (T' : tbLatticeType d') :=\n {f of @BLatticeMorphism d T d' T' f & @TLatticeMorphism d T d' T' f}.\n\nModule TBLatticeMorphismExports.\n(*A notation for the type of bottom-lattice morphisms, representing functions between lattices with bottom elements that preserve the bottom element.*)\nNotation \"{ 'blmorphism' T -> T' }\" :=\n (@BLatticeMorphism.type _ T%type _ T'%type) : type_scope.\n(*A notation for the type of top-lattice morphisms, representing functions between lattices with top elements that preserve the top element.*)\nNotation \"{ 'tlmorphism' T -> T' }\" :=\n (@TLatticeMorphism.type _ T%type _ T'%type) : type_scope.\n(*A notation for the type of top-and-bottom-lattice morphisms, representing functions between lattices with top and bottom elements that preserve both.*)\nNotation \"{ 'tblmorphism' T -> T' }\" :=\n (@TBLatticeMorphism.type _ T%type _ T'%type) : type_scope.\nEnd TBLatticeMorphismExports.\nHB.export TBLatticeMorphismExports.\n\nModule Import BLatticeMorphismTheory.\nSection BLatticeMorphismTheory.\n\nSection Properties.\n\nVariables (d : disp_t) (T : bLatticeType d).\nVariables (d' : disp_t) (T' : bLatticeType d').\nVariables (f : {blmorphism T -> T'}).\n\n(*This lemma states that a bottom-lattice morphism maps the bottom element of the source lattice to the bottom element of the target lattice.*)\nLemma omorph0 : f \\bot = \\bot.\n\nEnd Properties.\n\nSection IdCompFun.\n\nVariables (d : disp_t) (T : bLatticeType d).\nVariables (d' : disp_t) (T' : bLatticeType d').\nVariables (d'' : disp_t) (T'' : bLatticeType d'').\nVariables (f : {blmorphism T' -> T''}) (g : {blmorphism T -> T'}).\n\n(*This fact states that the identity function on a lattice with a bottom element preserves the bottom element, making it a bottom-lattice morphism.*)\nFact idfun_is_bottom_morphism : (@idfun T) \\bot = \\bot. \n#[export]\nHB.instance Definition _ := isBLatticeMorphism.Build d T d T idfun\n idfun_is_bottom_morphism.\n\n(*This fact states that the composition of two bottom-lattice morphisms results in another bottom-lattice morphism.*)\nFact comp_is_bottom_morphism : (f \\o g) \\bot = \\bot.\n\n#[export]\n(*This lemma states that a top-lattice morphism maps the top element of the source lattice to the top element of the target lattice.*)\nLemma omorph1 : f \\top = \\top.\n\nEnd Properties.\n\nSection IdCompFun.\n\nVariables (d : disp_t) (T : tLatticeType d).\nVariables (d' : disp_t) (T' : tLatticeType d').\nVariables (d'' : disp_t) (T'' : tLatticeType d'').\nVariables (f : {tlmorphism T' -> T''}) (g : {tlmorphism T -> T'}).\n\n(*This fact states that the identity function on a lattice with a top element preserves the top element, making it a top-lattice morphism.*)\nFact idfun_is_top_morphism : (@idfun T) \\top = \\top. \n#[export]\nHB.instance Definition _ := isTLatticeMorphism.Build d T d T idfun\n idfun_is_top_morphism.\n\n(*This fact states that the composition of two top-lattice morphisms results in another top-lattice morphism.*)\nFact comp_is_top_morphism : (f \\o g) \\top = \\top.\n\n#[export]\n(*This definition specifies the property that a subset of a lattice is closed under the meet operation, meaning that the meet of any two elements from the subset is also contained within the subset.*)\nDefinition meet_closed := {in S &, forall u v, u `&` v \\in S}.\n\n(*This definition specifies the property that a subset of a lattice is closed under the join operation, meaning that the join of any two elements from the subset is also contained within the subset.*)\nDefinition join_closed := {in S &, forall u v, u `|` v \\in S}.\n\nEnd ClosedPredicates.\nEnd ClosedPredicates.\n\n(*A mixin for a record that certifies a subset of a lattice is closed under the meet operation.*)\nHB.mixin Record isMeetLatticeClosed d (T : latticeType d) (S : {pred T}) := {\n opredI : meet_closed S;\n}.\n\n(*A mixin for a record that certifies a subset of a lattice is closed under the join operation.*)\nHB.mixin Record isJoinLatticeClosed d (T : latticeType d) (S : {pred T}) := {\n opredU : join_closed S;\n}.\n\n(*A mixin for a record that certifies a subset of a lattice with a bottom element contains that bottom element.*)\nHB.mixin Record isBLatticeClosed d (T : bLatticeType d) (S : {pred T}) := {\n opred0 : \\bot \\in S;\n}.\n\n(*A mixin for a record that certifies a subset of a lattice with a top element contains that top element.*)\nHB.mixin Record isTLatticeClosed d (T : tLatticeType d) (S : {pred T}) := {\n opred1 : \\top \\in S;\n}.\n\n#[short(type=\"meetLatticeClosed\")]\n(*This definition creates a structure representing a subset of a lattice that is closed under its meet operation.*)\nHB.structure Definition MeetLatticeClosed d T :=\n {S of isMeetLatticeClosed d T S}.\n\n#[short(type=\"joinLatticeClosed\")]\n(*This definition creates a structure representing a subset of a lattice that is closed under its join operation.*)\nHB.structure Definition JoinLatticeClosed d T :=\n {S of isJoinLatticeClosed d T S}.\n\n#[short(type=\"latticeClosed\")]\n(*This definition creates a structure representing a subset of a lattice that is closed under both its meet and join operations, forming a sublattice.*)\nHB.structure Definition LatticeClosed d T :=\n {S of @MeetLatticeClosed d T S & @JoinLatticeClosed d T S}.\n\n#[short(type=\"bLatticeClosed\")]\n(*This definition creates a structure representing a subset of a lattice with a bottom element that contains the bottom element.*)\nHB.structure Definition BLatticeClosed d T := {S of isBLatticeClosed d T S}.\n\n#[short(type=\"bJoinLatticeClosed\")]\n(*This definition creates a structure representing a subset of a lattice that contains the bottom element and is closed under the join operation.*)\nHB.structure Definition BJoinLatticeClosed d T :=\n {S of isBLatticeClosed d T S & @JoinLatticeClosed d T S}.\n\n#[short(type=\"tLatticeClosed\")]\n(*This definition creates a structure representing a subset of a lattice with a top element that contains the top element.*)\nHB.structure Definition TLatticeClosed d T := {S of isTLatticeClosed d T S}.\n\n#[short(type=\"tMeetLatticeClosed\")]\n(*This definition creates a structure representing a subset of a lattice that contains the top element and is closed under the meet operation.*)\nHB.structure Definition TMeetLatticeClosed d T :=\n {S of isTLatticeClosed d T S & @MeetLatticeClosed d T S}.\n\n#[short(type=\"tbLatticeClosed\")]\n(*This definition creates a structure representing a subset of a lattice with both top and bottom elements that contains both the top and bottom elements.*)\nHB.structure Definition TBLatticeClosed d (T : tbLatticeType d) :=\n {S of @BLatticeClosed d T S & @TLatticeClosed d T S}.\n\n(*A factory for a record that certifies a subset of a lattice is closed under both the meet and join operations.*)\nHB.factory Record isLatticeClosed d (T : latticeType d) (S : {pred T}) := {\n opredI : meet_closed S;\n opredU : join_closed S;\n}.\n\nHB.builders Context d T S of isLatticeClosed d T S.\nHB.instance Definition _ := isMeetLatticeClosed.Build d T S opredI.\nHB.instance Definition _ := isJoinLatticeClosed.Build d T S opredU.\nHB.end.\n\n(*A factory for a record that certifies a subset of a lattice with top and bottom elements is a sublattice containing both the top and bottom elements.*)\nHB.factory Record isTBLatticeClosed d (T : tbLatticeType d) (S : {pred T}) := {\n opredI : meet_closed S;\n opredU : join_closed S;\n opred0 : \\bot \\in S;\n opred1 : \\top \\in S;\n}.\n\nHB.builders Context d T S of isTBLatticeClosed d T S.\nHB.instance Definition _ := isLatticeClosed.Build d T S opredI opredU.\nHB.instance Definition _ := isBLatticeClosed.Build d T S opred0.\nHB.instance Definition _ := isTLatticeClosed.Build d T S opred1.\nHB.end.\n\nModule Import LatticePred.\nSection LatticePred.\n\nVariables (d : disp_t) (T : latticeType d).\n\n(*This lemma states that for any subset of a lattice that is closed under meet, the meet of any two elements within that subset is also an element of the subset.*)\nLemma opredI (S : meetLatticeClosed T) : {in S &, forall u v, u `&` v \\in S}.\n\n(*This lemma states that for any subset of a lattice that is closed under join, the join of any two elements within that subset is also an element of the subset.*)\nLemma opredU (S : joinLatticeClosed T) : {in S &, forall u v, u `|` v \\in S}.\n\nEnd LatticePred.\n\nSection BLatticePred.\n\nVariables (d : disp_t) (T : bLatticeType d).\n\n(*This lemma states that any subset of a bounded lattice structured as being closed with respect to the bottom element must contain that bottom element.*)\nLemma opred0 (S : bLatticeClosed T) : \\bot \\in S.\n\n(*This lemma states that for a subset of a lattice that contains the bottom element and is closed under binary joins, the indexed join of a family of elements is also in the subset, provided that every element in the family is in the subset.*)\nLemma opred_joins (S : bJoinLatticeClosed T) I r (P : pred I) F :\n (forall i, P i -> F i \\in S) -> \\join_(i <- r | P i) F i \\in S.\n\nEnd BLatticePred.\n\nSection TLatticePred.\n\nVariables (d : disp_t) (T : tLatticeType d).\n\n(*This lemma states that any subset of a bounded lattice structured as being closed with respect to the top element must contain that top element.*)\nLemma opred1 (S : tLatticeClosed T) : \\top \\in S.\n\n(*This lemma states that for a subset of a lattice that contains the top element and is closed under binary meets, the indexed meet of a family of elements is also in the subset, provided that every element in the family is in the subset.*)\nLemma opred_meets (S : tMeetLatticeClosed T) I r (P : pred I) F :\n (forall i, P i -> F i \\in S) -> \\meet_(i <- r | P i) F i \\in S.\n\nEnd TLatticePred.\nEnd LatticePred.\n\n#[short(type=\"subPOrder\")]\n(*This definition creates a structure for a partially ordered subtype, which consists of a subset of a partially ordered type that is itself endowed with a partial order structure, such that the inclusion map is order-preserving.*)\nHB.structure Definition SubPOrder d (T : porderType d) S d' :=\n { U of SubEquality T S U & POrder d' U & isSubPreorder d T S d' U }.\n\n(*A factory for a record that constructs a partial order structure on a chosen subtype of an existing partially ordered type, ensuring the induced order is also a partial order.*)\nHB.factory Record SubChoice_isSubPOrder d (T : porderType d) S (d' : disp_t) U\n of SubChoice T S U := {}.\n\nHB.builders Context d T S d' U of SubChoice_isSubPOrder d T S d' U.\nHB.instance Definition _ := SubChoice_isSubPreorder.Build d T S d' U.\nHB.instance Definition _ := Preorder_isPOrder.Build d' U\n (@CancelPartial.anti U d T _ _ (@valK _ _ U)).\nHB.end.\n\n#[export]\nHB.instance Definition _ d (T : porderType d) (S : pred T) (d' : disp_t)\n (U : subType S) := SubChoice_isSubPOrder.Build d T S d' (sub_type U).\n\n(*A mixin for a record that certifies the inclusion map from a sublattice into its parent lattice preserves the meet operation.*)\nHB.mixin Record isMeetSubLattice d (T : latticeType d) (S : pred T) d' U\n of SubType T S U & Lattice d' U := {\n valI_subproof : {morph (val : U -> T) : x y / x `&` y};\n}.\n\n(*A mixin for a record that certifies the inclusion map from a sublattice into its parent lattice preserves the join operation.*)\nHB.mixin Record isJoinSubLattice d (T : latticeType d) (S : pred T) d' U\n of SubType T S U & Lattice d' U := {\n valU_subproof : {morph (val : U -> T) : x y / x `|` y};\n}.\n\n#[short(type=\"subPOrderLattice\")]\n(*This definition creates a structure for a subtype of a lattice that is itself a lattice and inherits a compatible partial order from the parent type.*)\nHB.structure Definition SubPOrderLattice d (T : latticeType d) S d' :=\n { U of @SubPOrder d T S d' U & Lattice d' U }.\n\n#[short(type=\"subPOrderBLattice\")]\n(*This definition creates a structure for a sublattice that is also a partially ordered subtype and possesses a bottom element.*)\nHB.structure Definition SubPOrderBLattice d (T : latticeType d) S d' :=\n { U of @SubPOrderLattice d T S d' U & BLattice d' U }.\n\n#[short(type=\"subPOrderTLattice\")]\n(*This definition creates a structure for a sublattice that is also a partially ordered subtype and possesses a top element.*)\nHB.structure Definition SubPOrderTLattice d (T : latticeType d) S d' :=\n { U of @SubPOrderLattice d T S d' U & TLattice d' U }.\n\n#[short(type=\"subPOrderTBLattice\")]\n(*This definition creates a structure for a sublattice that is also a partially ordered subtype and possesses both a top and a bottom element.*)\nHB.structure Definition SubPOrderTBLattice d (T : latticeType d) S d' :=\n { U of @SubPOrderLattice d T S d' U & TBLattice d' U }.\n\n#[short(type=\"meetSubLattice\")]\n(*Defines the structure for a meet-sublattice, which is a subtype of a given lattice that is closed under the meet operation of the ambient lattice.*)\nHB.structure Definition MeetSubLattice d (T : latticeType d) S d' :=\n { U of @SubPOrderLattice d T S d' U & isMeetSubLattice d T S d' U }.\n\n#[short(type=\"meetSubBLattice\")]\n(*Defines the structure for a meet-sublattice that is also a bounded lattice with a bottom element.*)\nHB.structure Definition MeetSubBLattice d (T : latticeType d) S d' :=\n { U of @MeetSubLattice d T S d' U & BLattice d' U }.\n\n#[short(type=\"meetSubTLattice\")]\n(*Defines the structure for a meet-sublattice that is also a bounded lattice with a top element.*)\nHB.structure Definition MeetSubTLattice d (T : latticeType d) S d' :=\n { U of @MeetSubLattice d T S d' U & TLattice d' U }.\n\n#[short(type=\"meetSubTBLattice\")]\n(*Defines the structure for a meet-sublattice that is also a bounded lattice with both a top and a bottom element.*)\nHB.structure Definition MeetSubTBLattice d (T : latticeType d) S d' :=\n { U of @MeetSubLattice d T S d' U & TBLattice d' U }.\n\n#[short(type=\"joinSubLattice\")]\n(*Defines the structure for a join-sublattice, which is a subtype of a given lattice that is closed under the join operation of the ambient lattice.*)\nHB.structure Definition JoinSubLattice d (T : latticeType d) S d' :=\n { U of @SubPOrderLattice d T S d' U & isJoinSubLattice d T S d' U }.\n\n#[short(type=\"joinSubBLattice\")]\n(*Defines the structure for a join-sublattice that is also a bounded lattice with a bottom element.*)\nHB.structure Definition JoinSubBLattice d (T : latticeType d) S d' :=\n { U of @JoinSubLattice d T S d' U & BLattice d' U }.\n\n#[short(type=\"joinSubTLattice\")]\n(*Defines the structure for a join-sublattice that is also a bounded lattice with a top element.*)\nHB.structure Definition JoinSubTLattice d (T : latticeType d) S d' :=\n { U of @JoinSubLattice d T S d' U & TLattice d' U }.\n\n#[short(type=\"joinSubTBLattice\")]\n(*Defines the structure for a join-sublattice that is also a bounded lattice with both a top and a bottom element.*)\nHB.structure Definition JoinSubTBLattice d (T : latticeType d) S d' :=\n { U of @JoinSubLattice d T S d' U & TBLattice d' U }.\n\n#[short(type=\"subLattice\")]\n(*Defines the structure for a sublattice, which is a subtype of a given lattice that is closed under both the meet and join operations of the ambient lattice.*)\nHB.structure Definition SubLattice d (T : latticeType d) S d' :=\n { U of @MeetSubLattice d T S d' U & @JoinSubLattice d T S d' U }.\n\n#[short(type=\"subBLattice\")]\n(*Defines the structure for a sublattice that is also a bounded lattice with a bottom element.*)\nHB.structure Definition SubBLattice d (T : latticeType d) S d' :=\n { U of @SubLattice d T S d' U & BLattice d' U }.\n\n#[short(type=\"subTLattice\")]\n(*Defines the structure for a sublattice that is also a bounded lattice with a top element.*)\nHB.structure Definition SubTLattice d (T : latticeType d) S d' :=\n { U of @SubLattice d T S d' U & TLattice d' U }.\n\n#[short(type=\"subTBLattice\")]\n(*Defines the structure for a sublattice that is also a bounded lattice with both a top and a bottom element.*)\nHB.structure Definition SubTBLattice d (T : latticeType d) S d' :=\n { U of @SubLattice d T S d' U & TBLattice d' U }.\n\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (d : disp_t) (T : latticeType d) (S : pred T)\n d' (U : MeetSubLattice.type S d') :=\n isMeetLatticeMorphism.Build d' U d T val valI_subproof.\n\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (d : disp_t) (T : latticeType d) (S : pred T)\n d' (U : JoinSubLattice.type S d') :=\n isJoinLatticeMorphism.Build d' U d T val valU_subproof.\n\n(*A factory for constructing a sublattice structure from a sub-preorder of a lattice, requiring proofs that the underlying subset is closed under the ambient meet and join operations.*)\nHB.factory Record SubPOrder_isSubLattice d (T : latticeType d) S d' U\n of @SubPOrder d T S d' U := {\n opredI_subproof : meet_closed S;\n opredU_subproof : join_closed S;\n}.\n\nHB.builders Context d T S d' U of SubPOrder_isSubLattice d T S d' U.\n\nHB.instance Definition _ := isLatticeClosed.Build d T S\n opredI_subproof opredU_subproof.\n\nLet inU v Sv : U := Sub v Sv.\n(*Defines the meet operation on the sublattice by taking two elements from the sublattice, computing their meet in the ambient lattice, and returning the result as an element of the sublattice.*)\nLet meetU (u1 u2 : U) : U := inU (opredI (valP u1) (valP u2)).\n(*Defines the join operation on the sublattice by taking two elements from the sublattice, computing their join in the ambient lattice, and returning the result as an element of the sublattice.*)\nLet joinU (u1 u2 : U) : U := inU (opredU (valP u1) (valP u2)).\n\n(*This lemma asserts that the meet operation on the sublattice is commutative.*)\nLet meetUC : commutative meetU.\n\n(*This lemma asserts that the join operation on the sublattice is commutative.*)\nLet joinUC : commutative joinU.\n\n(*This lemma asserts that the meet operation on the sublattice is associative.*)\nLet meetUA : associative meetU.\n\n(*This lemma asserts that the join operation on the sublattice is associative.*)\nLet joinUA : associative joinU.\n\n(*This lemma states the absorption law for the sublattice, asserting that the meet of an element with the join of itself and another element is equal to the original element.*)\nLemma joinUKI y x : meetU x (joinU x y) = x.\n\n(*This lemma states the absorption law for the sublattice, asserting that the join of an element with the meet of itself and another element is equal to the original element.*)\nLet meetUKU y x : joinU x (meetU x y) = x.\n\n(*This lemma states that for any two elements in the sublattice, the first is less than or equal to the second if and only if their meet is equal to the first element.*)\nLet le_meetU x y : (x <= y) = (meetU x y == x).\n\nHB.instance Definition _ := POrder_isLattice.Build d' U\n meetUC joinUC meetUA joinUA joinUKI meetUKU le_meetU.\n\n(*This fact asserts that the inclusion map from the sublattice to the ambient lattice is a meet-morphism, meaning it preserves the meet operation.*)\nFact valI : meet_morphism (val : U -> T).\n\n(*This fact asserts that the inclusion map from the sublattice to the ambient lattice is a join-morphism, meaning it preserves the join operation.*)\nFact valU : join_morphism (val : U -> T).\n\nHB.instance Definition _ := isMeetSubLattice.Build d T S d' U valI.\nHB.instance Definition _ := isJoinSubLattice.Build d T S d' U valU.\nHB.end.\n\n(*A factory for constructing a sublattice structure from a subtype with a choice function, requiring proofs that the underlying subset is closed under the ambient meet and join operations.*)\nHB.factory Record SubChoice_isSubLattice d (T : latticeType d) S (d' : disp_t) U\n of SubChoice T S U := {\n opredI_subproof : meet_closed S;\n opredU_subproof : join_closed S;\n}.\n\nHB.builders Context d T S d' U of SubChoice_isSubLattice d T S d' U.\nHB.instance Definition _ := SubChoice_isSubPOrder.Build d T S d' U.\nHB.instance Definition _ := SubPOrder_isSubLattice.Build d T S d' U\n opredI_subproof opredU_subproof.\nHB.end.\n\n(*A mixin for a subtype that is also a bounded lattice, requiring that the inclusion map from the subtype to the ambient type sends the bottom element of the subtype to the bottom element of the ambient type.*)\nHB.mixin Record isBSubLattice d (T : bLatticeType d) (S : pred T) d' U\n of SubType T S U & BLattice d' U := {\n val0_subproof : (val : U -> T) \\bot = \\bot;\n}.\n\n#[short(type=\"bJoinSubLattice\")]\n(*Defines the structure for a bounded join-sublattice, which is a join-sublattice that is also a bounded lattice whose bottom element coincides with the bottom element of the ambient lattice.*)\nHB.structure Definition BJoinSubLattice d (T : bLatticeType d) S d' :=\n { U of @JoinSubLattice d T S d' U & BLattice d' U & isBSubLattice d T S d' U }.\n\n#[short(type=\"bJoinSubTLattice\")]\n(*Defines the structure for a bounded join-sublattice that possesses both a top and a bottom element.*)\nHB.structure Definition BJoinSubTLattice d (T : bLatticeType d) S d' :=\n { U of @BJoinSubLattice d T S d' U & TBLattice d' U }.\n\n#[short(type=\"bSubLattice\")]\n(*Defines the structure for a bounded sublattice, which is a sublattice whose bottom element coincides with the bottom element of the ambient bounded lattice.*)\nHB.structure Definition BSubLattice d (T : bLatticeType d) S d' :=\n { U of @SubLattice d T S d' U & @BJoinSubLattice d T S d' U }.\n\n#[short(type=\"bSubTLattice\")]\n(*Defines the structure for a bounded sublattice that possesses both a top and a bottom element.*)\nHB.structure Definition BSubTLattice d (T : bLatticeType d) S d' :=\n { U of @BSubLattice d T S d' U & TBLattice d' U }.\n\n#[export]\nHB.instance Definition _ (d : disp_t) (T : bLatticeType d) (S : pred T)\n d' (U : BJoinSubLattice.type S d') :=\n isBLatticeMorphism.Build d' U d T val val0_subproof.\n\n(*This factory constructs a bounded sublattice structure with a bottom element on a subpreorder. It requires a proof that the bottom element of the ambient lattice is a member of the predicate defining the subtype.*)\nHB.factory Record SubPOrder_isBSubLattice d (T : bLatticeType d) S d' U\n of @SubPOrder d T S d' U & Lattice d' U := {\n opred0_subproof : \\bot \\in S;\n}.\n\nHB.builders Context d T S d' U of SubPOrder_isBSubLattice d T S d' U.\n\nLet inU v Sv : U := Sub v Sv.\n(*This definition establishes the bottom element of the sublattice, which is the bottom element of the ambient lattice, guaranteed to exist within the defining subset.*)\nLet zeroU : U := inU opred0_subproof.\n\n(*This fact states that the bottom element of the sublattice is less than or equal to any other element in the sublattice.*)\nFact le0x x : zeroU <= x. \nHB.instance Definition _ := hasBottom.Build d' U le0x.\n\n(*This fact asserts that the inclusion map from the sublattice to the ambient lattice sends the bottom element of the sublattice to the bottom element of the ambient lattice.*)\nFact val0 : (val : U -> T) \\bot = \\bot. \n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := isBSubLattice.Build d T S d' U val0.\nHB.end.\n\n(*This factory constructs a bounded sublattice structure with a bottom element on a subtype with a choice operator. It requires proofs that the defining predicate for the subtype is closed under the meet and join operations of the ambient lattice and that it contains the bottom element of the ambient lattice.*)\nHB.factory Record SubChoice_isBSubLattice\n d (T : bLatticeType d) S (d' : disp_t) U of SubChoice T S U := {\n opredI_subproof : meet_closed S;\n opredU_subproof : join_closed S;\n opred0_subproof : \\bot \\in S;\n}.\n\nHB.builders Context d T S d' U of SubChoice_isBSubLattice d T S d' U.\nHB.instance Definition _ := SubChoice_isSubLattice.Build d T S d' U\n opredI_subproof opredU_subproof.\nHB.instance Definition _ := SubPOrder_isBSubLattice.Build d T S d' U\n opred0_subproof.\nHB.end.\n\n(*A mixin that characterizes a sublattice as having a top element that corresponds to the top element of its ambient lattice under the inclusion map.*)\nHB.mixin Record isTSubLattice d (T : tLatticeType d) (S : pred T) d' U\n of SubType T S U & TLattice d' U := {\n val1_subproof : (val : U -> T) \\top = \\top;\n}.\n\n#[short(type=\"tMeetSubLattice\")]\n(*This structure defines a top-meet-sublattice, which is a subtype of a lattice with a top element, forming a lattice with a top element itself, being closed under the meet operation of the ambient lattice, and whose top element coincides with the ambient lattice's top element.*)\nHB.structure Definition TMeetSubLattice d (T : tLatticeType d) S d' :=\n { U of @MeetSubLattice d T S d' U & TLattice d' U & isTSubLattice d T S d' U }.\n\n#[short(type=\"tMeetSubBLattice\")]\n(*This structure defines a top-meet-sub-bottom-lattice, which is a top-meet-sublattice that is also equipped with a bottom element, making it a bounded lattice.*)\nHB.structure Definition TMeetSubBLattice d (T : tLatticeType d) S d' :=\n { U of @TMeetSubLattice d T S d' U & TBLattice d' U }.\n\n#[short(type=\"tSubLattice\")]\n(*This structure defines a top-sublattice, which is a subtype of a lattice with a top element that is itself a lattice with a top element, is closed under both the meet and join operations of the ambient lattice, and whose top element coincides with the ambient lattice's top element.*)\nHB.structure Definition TSubLattice d (T : tLatticeType d) S d' :=\n { U of @SubLattice d T S d' U & @TMeetSubLattice d T S d' U }.\n\n#[short(type=\"tSubBLattice\")]\n(*This structure defines a top-sub-bottom-lattice, which is a top-sublattice that is also equipped with a bottom element, making it a bounded lattice.*)\nHB.structure Definition TSubBLattice d (T : tLatticeType d) S d' :=\n { U of @TSubLattice d T S d' U & TBLattice d' U }.\n\n#[export]\nHB.instance Definition _ (d : disp_t) (T : tLatticeType d) (S : pred T)\n d' (U : TMeetSubLattice.type S d') :=\n isTLatticeMorphism.Build d' U d T val val1_subproof.\n\n(*This factory constructs a bounded sublattice structure with a top element on a subpreorder. It requires a proof that the top element of the ambient lattice is a member of the predicate defining the subtype.*)\nHB.factory Record SubPOrder_isTSubLattice d (T : tLatticeType d) S d' U\n of @SubPOrder d T S d' U & Lattice d' U := {\n opred1_subproof : \\top \\in S;\n}.\n\nHB.builders Context d T S d' U of SubPOrder_isTSubLattice d T S d' U.\n\n(*This definition provides a local helper function for creating an element of the subtype by packaging an element of the ambient type with a proof that it satisfies the subtype's defining predicate.*)\nLet inU v Sv : U := Sub v Sv.\n(*This definition establishes the top element of the sublattice, which is the top element of the ambient lattice, guaranteed to exist within the defining subset.*)\nLet oneU : U := inU opred1_subproof.\n\n(*This fact states that any element in the sublattice is less than or equal to the top element of the sublattice.*)\nFact lex1 x : x <= oneU. \nHB.instance Definition _ := hasTop.Build d' U lex1.\n\n(*This fact asserts that the inclusion map from the sublattice to the ambient lattice sends the top element of the sublattice to the top element of the ambient lattice.*)\nFact val1 : (val : U -> T) \\top = \\top. \n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := isTSubLattice.Build d T S d' U val1.\nHB.end.\n\n(*This factory constructs a bounded sublattice structure with a top element on a subtype with a choice operator. It requires proofs that the defining predicate for the subtype is closed under the meet and join operations of the ambient lattice and that it contains the top element of the ambient lattice.*)\nHB.factory Record SubChoice_isTSubLattice\n d (T : tLatticeType d) S (d' : disp_t) U of SubChoice T S U := {\n opredI_subproof : meet_closed S;\n opredU_subproof : join_closed S;\n opred1_subproof : \\top \\in S;\n}.\n\nHB.builders Context d T S d' U of SubChoice_isTSubLattice d T S d' U.\nHB.instance Definition _ := SubChoice_isSubLattice.Build d T S d' U\n opredI_subproof opredU_subproof.\nHB.instance Definition _ := SubPOrder_isTSubLattice.Build d T S d' U\n opred1_subproof.\nHB.end.\n\n#[short(type=\"tbSubLattice\")]\n(*This structure defines a top-and-bottom sublattice, which is a subtype of a bounded lattice that is itself a bounded lattice and whose top and bottom elements coincide with those of the ambient lattice.*)\nHB.structure Definition TBSubLattice d (T : tbLatticeType d) S d' :=\n { U of @BSubLattice d T S d' U & @TSubLattice d T S d' U}.\n\n#[export]\nHB.instance Definition _ (d : disp_t) (T : tbLatticeType d) (S : pred T) d'\n (U : TBSubLattice.type S d') := BLatticeMorphism.on (val : U -> T).\n\n(*This factory constructs a bounded sublattice structure with both a top and a bottom element on a subpreorder. It requires proofs that both the top and bottom elements of the ambient bounded lattice are members of the predicate defining the subtype.*)\nHB.factory Record SubPOrder_isTBSubLattice d (T : tbLatticeType d) S d' U\n of @SubPOrder d T S d' U & Lattice d' U := {\n opred0_subproof : \\bot \\in S;\n opred1_subproof : \\top \\in S;\n}.\n\nHB.builders Context d T S d' U of SubPOrder_isTBSubLattice d T S d' U.\nHB.instance Definition _ := SubPOrder_isBSubLattice.Build d T S d' U\n opred0_subproof.\nHB.instance Definition _ := SubPOrder_isTSubLattice.Build d T S d' U\n opred1_subproof.\nHB.end.\n\n(*This factory constructs a bounded sublattice structure with both top and bottom elements on a subtype with a choice operator. It requires proofs that the defining predicate is closed under the meet and join operations and that it contains both the top and bottom elements of the ambient lattice.*)\nHB.factory Record SubChoice_isTBSubLattice d (T : tbLatticeType d) S\n (d' : disp_t) U of SubChoice T S U := {\n opredI_subproof : meet_closed S;\n opredU_subproof : join_closed S;\n opred0_subproof : \\bot \\in S;\n opred1_subproof : \\top \\in S;\n}.\n\nHB.builders Context d T S d' U of SubChoice_isTBSubLattice d T S d' U.\nHB.instance Definition _ := SubChoice_isSubLattice.Build d T S d' U\n opredI_subproof opredU_subproof.\nHB.instance Definition _ := SubPOrder_isTBSubLattice.Build d T S d' U\n opred0_subproof opred1_subproof.\nHB.end.\n\n#[short(type=\"subOrder\")]\n(*This structure defines a sub-order as a subtype of a totally ordered type that forms a sublattice and is itself totally ordered with respect to the induced order.*)\nHB.structure Definition SubOrder d (T : orderType d) S d' :=\n { U of @SubLattice d T S d' U & Total d' U }.\n\n(*This factory constructs a total suborder structure from a sublattice of a totally ordered type. The totality of the suborder is derived from the totality of the ambient order.*)\nHB.factory Record SubLattice_isSubOrder d (T : orderType d) S d' U\n of @SubLattice d T S d' U := {}.\n\nHB.builders Context d T S d' U of SubLattice_isSubOrder d T S d' U.\n(*This lemma states that the order relation on the sublattice is total, meaning any two elements are comparable.*)\nLemma totalU : total (<=%O : rel U).\n\nHB.instance Definition _ := Lattice_isTotal.Build d' U totalU.\nHB.end.\n\n(*This factory constructs a total suborder structure from a subpreorder of a totally ordered type. It leverages the fact that any subpreorder of a total order is necessarily a sublattice.*)\nHB.factory Record SubPOrder_isSubOrder d (T : orderType d) S d' U\n of @SubPOrder d T S d' U := {}.\n\nHB.builders Context d T S d' U of SubPOrder_isSubOrder d T S d' U.\n(*This fact asserts that the predicate defining the subpreorder is closed under the meet operation of the ambient totally ordered type.*)\nFact opredI : meet_closed S.\n\n(*This fact asserts that the predicate defining the subpreorder is closed under the join operation of the ambient totally ordered type.*)\nFact opredU : join_closed S.\n\nHB.instance Definition _ := SubPOrder_isSubLattice.Build d T S d' U opredI opredU.\nHB.instance Definition _ := SubLattice_isSubOrder.Build d T S d' U.\nHB.end.\n\n(*This factory constructs a total suborder structure on a subtype with a choice operator, provided the ambient type is totally ordered.*)\nHB.factory Record SubChoice_isSubOrder d (T : orderType d) S (d' : disp_t) U\n of @SubChoice T S U := {}.\n\nHB.builders Context d T S d' U of SubChoice_isSubOrder d T S d' U.\nHB.instance Definition _ := SubChoice_isSubPOrder.Build d T S d' U.\n(*A notation for constructing a sub-preorder structure on a given subtype. This command automatically infers the necessary properties from the context using the default display for the order.*)\nNotation \"[ 'SubChoice_isSubPOrder' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubPOrder.Build _ _ _ _ U)\n (format \"[ 'SubChoice_isSubPOrder' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a sub-preorder structure on a given subtype. This command automatically infers the necessary properties from the context using an explicitly provided display for the order.*)\nNotation \"[ 'SubChoice_isSubPOrder' 'of' U 'by' <: 'with' disp ]\" :=\n (SubChoice_isSubPOrder.Build _ _ _ disp U)\n (format \"[ 'SubChoice_isSubPOrder' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a sublattice structure from a sub-preorder. This command automatically supplies proofs that the subtype is closed under meet and join, using the default display for the order.*)\nNotation \"[ 'SubPOrder_isSubLattice' 'of' U 'by' <: ]\" :=\n (SubPOrder_isSubLattice.Build _ _ _ _ U (@opredI _ _ _) (@opredU _ _ _))\n (format \"[ 'SubPOrder_isSubLattice' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a sublattice structure from a sub-preorder. This command automatically supplies proofs that the subtype is closed under meet and join, using an explicitly provided display for the order.*)\nNotation \"[ 'SubPOrder_isSubLattice' 'of' U 'by' <: 'with' disp ]\" :=\n (SubPOrder_isSubLattice.Build _ _ _ disp U (@opredI _ _ _) (@opredU _ _ _))\n (format \"[ 'SubPOrder_isSubLattice' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical sublattice structure on a subtype of a choice type. This construction requires that the subtype is closed under the meet and join operations of the ambient lattice.*)\nNotation \"[ 'SubChoice_isSubLattice' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubLattice.Build _ _ _ _ U (@opredI _ _ _) (@opredU _ _ _))\n (format \"[ 'SubChoice_isSubLattice' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical sublattice structure on a subtype of a choice type, specifying an explicit display for the order relation. This construction requires that the subtype is closed under the meet and join operations of the ambient lattice.*)\nNotation \"[ 'SubChoice_isSubLattice' 'of' U 'by' <: 'with' disp ]\" :=\n (SubChoice_isSubLattice.Build _ _ _ disp U (@opredI _ _ _) (@opredU _ _ _))\n (format \"[ 'SubChoice_isSubLattice' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with a bottom element, on a subtype of a partially ordered type. This construction requires that the subtype contains the bottom element of the ambient type.*)\nNotation \"[ 'SubPOrder_isBSubLattice' 'of' U 'by' <: ]\" :=\n (SubPOrder_isBSubLattice.Build _ _ _ _ U (opred0 _))\n (format \"[ 'SubPOrder_isBSubLattice' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with a bottom element, on a subtype of a partially ordered type, specifying an explicit display for the order relation. This construction requires that the subtype contains the bottom element of the ambient type.*)\nNotation \"[ 'SubPOrder_isBSubLattice' 'of' U 'by' <: 'with' disp ]\" :=\n (SubPOrder_isBSubLattice.Build _ _ _ disp U (opred0 _))\n (format \"[ 'SubPOrder_isBSubLattice' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with a bottom element, on a subtype of a choice type. This construction requires that the subtype is closed under meet and join and contains the bottom element of the ambient lattice.*)\nNotation \"[ 'SubChoice_isBSubLattice' 'of' U 'by' <: ]\" :=\n (SubChoice_isBSubLattice.Build _ _ _ _ U\n (@opredI _ _ _) (@opredU _ _ _) (opred0 _))\n (format \"[ 'SubChoice_isBSubLattice' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with a bottom element, on a subtype of a choice type, specifying an explicit display for the order relation. This construction requires that the subtype is closed under meet and join and contains the bottom element of the ambient lattice.*)\nNotation \"[ 'SubChoice_isBSubLattice' 'of' U 'by' <: 'with' disp ]\" :=\n (SubChoice_isBSubLattice.Build _ _ _ disp U\n (@opredI _ _ _) (@opredU _ _ _) (opred0 _))\n (format \"[ 'SubChoice_isBSubLattice' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with a top element, on a subtype of a partially ordered type. This construction requires that the subtype contains the top element of the ambient type.*)\nNotation \"[ 'SubPOrder_isTSubLattice' 'of' U 'by' <: ]\" :=\n (SubPOrder_isTSubLattice.Build _ _ _ _ U (opred1 _))\n (format \"[ 'SubPOrder_isTSubLattice' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with a top element, on a subtype of a partially ordered type, specifying an explicit display for the order relation. This construction requires that the subtype contains the top element of the ambient type.*)\nNotation \"[ 'SubPOrder_isTSubLattice' 'of' U 'by' <: 'with' disp ]\" :=\n (SubPOrder_isTSubLattice.Build _ _ _ disp U (opred1 _))\n (format \"[ 'SubPOrder_isTSubLattice' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with a top element, on a subtype of a choice type. This construction requires that the subtype is closed under meet and join and contains the top element of the ambient lattice.*)\nNotation \"[ 'SubChoice_isTSubLattice' 'of' U 'by' <: ]\" :=\n (SubChoice_isTSubLattice.Build _ _ _ _ U\n (@opredI _ _ _) (@opredU _ _ _) (opred1 _))\n (format \"[ 'SubChoice_isTSubLattice' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with a top element, on a subtype of a choice type, specifying an explicit display for the order relation. This construction requires that the subtype is closed under meet and join and contains the top element of the ambient lattice.*)\nNotation \"[ 'SubChoice_isTSubLattice' 'of' U 'by' <: 'with' disp ]\" :=\n (SubChoice_isTSubLattice.Build _ _ _ disp U\n (@opredI _ _ _) (@opredU _ _ _) (opred1 _))\n (format \"[ 'SubChoice_isTSubLattice' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with both top and bottom elements, on a subtype of a partially ordered type. This construction requires that the subtype contains both the top and bottom elements of the ambient type.*)\nNotation \"[ 'SubPOrder_isTBSubLattice' 'of' U 'by' <: ]\" :=\n (SubPOrder_isTBSubLattice.Build _ _ _ _ U (opred0 _) (opred1 _))\n (format \"[ 'SubPOrder_isTBSubLattice' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with both top and bottom elements, on a subtype of a partially ordered type, specifying an explicit display for the order relation. This construction requires that the subtype contains both the top and bottom elements of the ambient type.*)\nNotation \"[ 'SubPOrder_isTBSubLattice' 'of' U 'by' <: 'with' disp ]\" :=\n (SubPOrder_isTBSubLattice.Build _ _ _ disp U (opred0 _) (opred1 _))\n (format \"[ 'SubPOrder_isTBSubLattice' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with both top and bottom elements, on a subtype of a choice type. This construction requires that the subtype is closed under meet and join and contains both the top and bottom elements of the ambient lattice.*)\nNotation \"[ 'SubChoice_isTBSubLattice' 'of' U 'by' <: ]\" :=\n (SubChoice_isTBSubLattice.Build _ _ _ _ U\n (@opredI _ _ _) (@opredU _ _ _) (opred0 _) (opred1 _))\n (format \"[ 'SubChoice_isTBSubLattice' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical bounded sublattice structure, with both top and bottom elements, on a subtype of a choice type, specifying an explicit display for the order relation. This construction requires that the subtype is closed under meet and join and contains both the top and bottom elements of the ambient lattice.*)\nNotation \"[ 'SubChoice_isTBSubLattice' 'of' U 'by' <: 'with' disp ]\" :=\n (SubChoice_isTBSubLattice.Build _ _ _ disp U\n (@opredI _ _ _) (@opredU _ _ _) (opred0 _) (opred1 _))\n (format \"[ 'SubChoice_isTBSubLattice' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical partial order structure on a subtype that is already known to be a sublattice. This formally recognizes the subtype as a partial order.*)\nNotation \"[ 'SubLattice_isSubOrder' 'of' U 'by' <: ]\" :=\n (SubLattice_isSubOrder.Build _ _ _ _ U)\n (format \"[ 'SubLattice_isSubOrder' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical partial order structure on a subtype that is already known to be a sublattice, specifying an explicit display for the order relation. This formally recognizes the subtype as a partial order.*)\nNotation \"[ 'SubLattice_isSubOrder' 'of' U 'by' <: 'with' disp ]\" :=\n (SubLattice_isSubOrder.Build _ _ _ disp U)\n (format \"[ 'SubLattice_isSubOrder' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical partial order structure on a subtype of a type with a preorder. This is applicable when the inherited preorder relation is antisymmetric on the subtype.*)\nNotation \"[ 'SubPOrder_isSubOrder' 'of' U 'by' <: ]\" :=\n (SubPOrder_isSubOrder.Build _ _ _ _ U)\n (format \"[ 'SubPOrder_isSubOrder' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical partial order structure on a subtype of a type with a preorder, specifying an explicit display for the order relation. This is applicable when the inherited preorder relation is antisymmetric on the subtype.*)\nNotation \"[ 'SubPOrder_isSubOrder' 'of' U 'by' <: 'with' disp ]\" :=\n (SubPOrder_isSubOrder.Build _ _ _ disp U)\n (format \"[ 'SubPOrder_isSubOrder' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n(*A notation for constructing a canonical partial order structure on a subtype of a choice type. This is applicable when the inherited preorder relation on the subtype is antisymmetric.*)\nNotation \"[ 'SubChoice_isSubOrder' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubOrder.Build _ _ _ _ U)\n (format \"[ 'SubChoice_isSubOrder' 'of' U 'by' <: ]\")\n : form_scope.\n(*A notation for constructing a canonical partial order structure on a subtype of a choice type, specifying an explicit display for its order relation. This is applicable when the inherited preorder relation on the subtype is antisymmetric.*)\nNotation \"[ 'SubChoice_isSubOrder' 'of' U 'by' <: 'with' disp ]\" :=\n (SubChoice_isSubOrder.Build _ _ _ disp U)\n (format \"[ 'SubChoice_isSubOrder' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n\nEnd SubOrderExports.\nHB.export SubOrderExports.\n\nModule DeprecatedSubOrder.\n\nSection Total.\nContext {disp : disp_t} {T : orderType disp} (P : {pred T}) (sT : subType P).\n\n#[export]\n(*A deprecated notation for declaring a partial order structure on a type by treating the type itself as a subtype. This was used to explicitly instantiate a generic partial order structure.*)\nNotation \"[ 'POrder' 'of' T 'by' <: ]\" :=\n (POrder.copy T%type (sub_type T%type))\n (format \"[ 'POrder' 'of' T 'by' <: ]\") : form_scope.\n(*A deprecated notation for declaring a total order structure on a type by treating the type itself as a subtype. This was used to explicitly instantiate a generic total order structure.*)\nNotation \"[ 'Order' 'of' T 'by' <: ]\" :=\n (Total.copy T%type (sub_type T%type))\n (only parsing) : form_scope.\nEnd Exports.\nEnd DeprecatedSubOrder.\nHB.export DeprecatedSubOrder.Exports.\n\nModule NatOrder.\nSection NatOrder.\n\nExport NatOrder.\n\n#[export]\nHB.instance Definition _ :=\n Preorder_isPOrder.Build nat_display nat anti_leq.\n#[export]\n(*This lemma states that a function from a convex set of natural numbers to a partially ordered type is non-decreasing if, for any two consecutive natural numbers within that set, the function's value at the successor is strictly greater than its value at the predecessor.*)\nLemma incn_inP : {in D, forall i, i.+1 \\in D -> f i < f i.+1} ->\n {in D &, {mono f : i j / i <= j}}.\n\n(*This lemma states that a function from a convex set of natural numbers to a partially ordered type is non-increasing if, for any two consecutive natural numbers within that set, the function's value at the successor is strictly less than its value at the predecessor.*)\nLemma decn_inP : {in D, forall i, i.+1 \\in D -> f i > f i.+1} ->\n {in D &, {mono f : i j /~ i <= j}}.\n\n(*This lemma states that a function from the set of all natural numbers to a partially ordered type is non-decreasing if its value at any natural number is strictly less than its value at that number's successor.*)\nLemma incnP : (forall i, f i < f i.+1) -> {mono f : i j / i <= j}.\n\n(*This lemma states that a function from the set of all natural numbers to a partially ordered type is non-increasing if its value at any natural number is strictly greater than its value at that number's successor.*)\nLemma decnP : (forall i, f i > f i.+1) -> {mono f : i j /~ i <= j}.\n\nEnd NatMonotonyTheory.\nArguments incn_inP {disp T} [D f].\nArguments decn_inP {disp T} [D f].\nArguments incnP {disp T} [f].\nArguments decnP {disp T} [f].\nEnd NatMonotonyTheory.\n\nModule DvdSyntax.\n\nExport DvdSyntax.\n\n(*A notation for the greatest common divisor operation, which is defined as the meet, or greatest lower bound, with respect to the divisibility partial order.*)\nNotation gcd := (@meet dvd_display _).\n(*A notation to obtain the binary function that computes the greatest common divisor of two elements of a given type. This notation provides the function itself, which can be passed as an argument, and corresponds to the meet operation under the divisibility order.*)\nNotation \"@ 'gcd' T\" := (@meet dvd_display T)\n (at level 10, T at level 8, only parsing) : function_scope.\n(*A notation for the least common multiple operation, which is defined as the join, or least upper bound, with respect to the divisibility partial order.*)\nNotation lcm := (@join dvd_display _).\n(*A notation to obtain the binary function that computes the least common multiple of two elements of a given type. This notation provides the function itself, which can be passed as an argument, and corresponds to the join operation under the divisibility order.*)\nNotation \"@ 'lcm' T\" := (@join dvd_display T)\n (at level 10, T at level 8, only parsing) : function_scope.\n\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each element of a given finite sequence that satisfies a specific predicate.*)\nNotation \"\\gcd_ ( i <- r | P ) F\" :=\n (\\big[gcd/nat0]_(i <- r | P%B) F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each element of a given finite sequence.*)\nNotation \"\\gcd_ ( i <- r ) F\" :=\n (\\big[gcd/nat0]_(i <- r) F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each element of a finite type that satisfies a specific predicate.*)\nNotation \"\\gcd_ ( i | P ) F\" :=\n (\\big[gcd/nat0]_(i | P%B) F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to every element of a given finite type.*)\nNotation \"\\gcd_ i F\" :=\n (\\big[gcd/nat0]_i F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each element of an explicitly specified finite type that satisfies a specific predicate.*)\nNotation \"\\gcd_ ( i : I | P ) F\" :=\n (\\big[gcd/nat0]_(i : I | P%B) F%O) (only parsing) :\n order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to every element of an explicitly specified finite type.*)\nNotation \"\\gcd_ ( i : I ) F\" :=\n (\\big[gcd/nat0]_(i : I) F%O) (only parsing) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each natural number from a starting value up to, but not including, an ending value, provided that the number satisfies a given predicate.*)\nNotation \"\\gcd_ ( m <= i < n | P ) F\" :=\n (\\big[gcd/nat0]_(m <= i < n | P%B) F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each natural number from a starting value up to, but not including, an ending value.*)\nNotation \"\\gcd_ ( m <= i < n ) F\" :=\n (\\big[gcd/nat0]_(m <= i < n) F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each natural number less than a given upper bound, provided that the number satisfies a given predicate.*)\nNotation \"\\gcd_ ( i < n | P ) F\" :=\n (\\big[gcd/nat0]_(i < n | P%B) F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each natural number less than a given upper bound.*)\nNotation \"\\gcd_ ( i < n ) F\" :=\n (\\big[gcd/nat0]_(i < n) F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each element of a given finite set that satisfies a specific predicate.*)\nNotation \"\\gcd_ ( i 'in' A | P ) F\" :=\n (\\big[gcd/nat0]_(i in A | P%B) F%O) : order_scope.\n(*This notation defines the greatest common divisor of a set of natural numbers. The numbers are generated by applying a function to each element of a given finite set.*)\nNotation \"\\gcd_ ( i 'in' A ) F\" :=\n (\\big[gcd/nat0]_(i in A) F%O) : order_scope.\n\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each element of a given finite sequence that satisfies a specific predicate.*)\nNotation \"\\lcm_ ( i <- r | P ) F\" :=\n (\\big[lcm/nat1]_(i <- r | P%B) F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each element of a given finite sequence.*)\nNotation \"\\lcm_ ( i <- r ) F\" :=\n (\\big[lcm/nat1]_(i <- r) F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each element of a finite type that satisfies a specific predicate.*)\nNotation \"\\lcm_ ( i | P ) F\" :=\n (\\big[lcm/nat1]_(i | P%B) F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to every element of a given finite type.*)\nNotation \"\\lcm_ i F\" :=\n (\\big[lcm/nat1]_i F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each element of an explicitly specified finite type that satisfies a specific predicate.*)\nNotation \"\\lcm_ ( i : I | P ) F\" :=\n (\\big[lcm/nat1]_(i : I | P%B) F%O) (only parsing) :\n order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to every element of an explicitly specified finite type.*)\nNotation \"\\lcm_ ( i : I ) F\" :=\n (\\big[lcm/nat1]_(i : I) F%O) (only parsing) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each natural number from a starting value up to, but not including, an ending value, provided that the number satisfies a given predicate.*)\nNotation \"\\lcm_ ( m <= i < n | P ) F\" :=\n (\\big[lcm/nat1]_(m <= i < n | P%B) F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each natural number from a starting value up to, but not including, an ending value.*)\nNotation \"\\lcm_ ( m <= i < n ) F\" :=\n (\\big[lcm/nat1]_(m <= i < n) F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each natural number less than a given upper bound, provided that the number satisfies a given predicate.*)\nNotation \"\\lcm_ ( i < n | P ) F\" :=\n (\\big[lcm/nat1]_(i < n | P%B) F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each natural number less than a given upper bound.*)\nNotation \"\\lcm_ ( i < n ) F\" :=\n (\\big[lcm/nat1]_(i < n) F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each element of a given finite set that satisfies a specific predicate.*)\nNotation \"\\lcm_ ( i 'in' A | P ) F\" :=\n (\\big[lcm/nat1]_(i in A | P%B) F%O) : order_scope.\n(*This notation defines the least common multiple of a set of natural numbers. The numbers are generated by applying a function to each element of a given finite set.*)\nNotation \"\\lcm_ ( i 'in' A ) F\" :=\n (\\big[lcm/nat1]_(i in A) F%O) : order_scope.\n\nEnd DvdSyntax.\n\nModule NatDvd.\n\nExport NatDvd.\n\nSection NatDvd.\nImplicit Types (m n p : natdvd).\n\n(*This lemma states that the least common multiple of a natural number with itself is that same natural number.*)\nLemma lcmnn n : lcmn n n = n.\n\n(*This lemma states that a first natural number divides a second natural number if and only if their greatest common divisor is equal to the first natural number.*)\nLemma le_def m n : m %| n = (gcdn m n == m)%N.\n\n(*This lemma states that the greatest common divisor of a natural number and the least common multiple of that same number with another natural number is equal to the first number.*)\nLemma joinKI n m : gcdn m (lcmn m n) = m.\n\n(*This lemma states that the least common multiple of a natural number and the greatest common divisor of that same number with another natural number is equal to the first number.*)\nLemma meetKU n m : lcmn m (gcdn m n) = m.\n\n(*This lemma states that the greatest common divisor operation on natural numbers is left-distributive over the least common multiple operation. This means that the greatest common divisor of a given natural number with the least common multiple of two other natural numbers is equal to the least common multiple of two results: the greatest common divisor of the first and second numbers, and the greatest common divisor of the first and third numbers.*)\nLemma meetUl : left_distributive gcdn lcmn.\n\n(*This fact asserts that the divisibility relation on natural numbers is antisymmetric. This means that if a first natural number divides a second, and the second natural number also divides the first, then the two numbers must be equal.*)\nFact dvdn_anti : antisymmetric dvdn.\n\n#[export]\nHB.instance Definition _ := Preorder_isPOrder.Build dvd_display t dvdn_anti.\n\n#[export]\n(*This lemma states that a natural number strictly divides another natural number if and only if the two numbers are not equal and the first number divides the second.*)\nLemma sdvdE (m n : t) : m %<| n = (n != m) && (m %| n).\n\n(*This lemma states that the generic greatest common divisor operation on natural numbers under the divisibility order is equivalent to the standard computational function for the greatest common divisor.*)\nLemma gcdE : gcd = gcdn :> (t -> t -> t). \n(*This lemma states that the generic least common multiple operation on natural numbers under the divisibility order is equivalent to the standard computational function for the least common multiple.*)\nLemma lcmE : lcm = lcmn :> (t -> t -> t). \n\nEnd NatDvd.\nModule Exports.\nHB.reexport NatDvd.\n(*This definition asserts that a natural number strictly divides another if and only if the two numbers are not equal and the first divides the second.*)\nDefinition sdvdEnat := sdvdE.\n(*This definition asserts that the generic greatest common divisor for natural numbers under the divisibility order corresponds to the standard greatest common divisor function.*)\nDefinition gcdEnat := gcdE.\n(*This definition asserts that the generic least common multiple for natural numbers under the divisibility order corresponds to the standard least common multiple function.*)\nDefinition lcmEnat := lcmE.\nEnd Exports.\nEnd NatDvd.\nHB.export NatDvd.Exports.\n\nModule OrdinalOrder.\n\nExport OrdinalOrder.\n\n#[export]\n(*This fact states that the logical conjunction of two booleans is equivalent to their minimum under the canonical order where false is less than true.*)\nFact andbE x y : x && y = if (x < y)%N then x else y.\n\n(*This fact states that the logical disjunction of two booleans is equivalent to their maximum under the canonical order where false is less than true.*)\nFact orbE x y : x || y = if (x < y)%N then y else x.\n\n(*This fact states that the standard less-than-or-equal-to relation on booleans is antisymmetric, which means that if a first boolean is less than or equal to a second and the second is also less than or equal to the first, then they must be equal.*)\nFact anti : antisymmetric (leq : rel bool).\n\n#[export] HB.instance Definition _ := Preorder_isPOrder.Build bool_display bool\n anti.\n\n(*This fact establishes an absorption law for boolean logic, asserting that the logical conjunction of a given boolean with the logical disjunction of itself and another boolean evaluates to the given boolean.*)\nFact orKb b a : a && (a || b) = a.\n\n(*This fact establishes an absorption law for boolean logic, asserting that the logical disjunction of a given boolean with the logical conjunction of itself and another boolean evaluates to the given boolean.*)\nFact andKb y x : x || x && y = x.\n\n(*This fact states that for any two booleans, the first is less than or equal to the second if and only if their logical conjunction equals the first boolean.*)\nFact leEmeet x y : (x <= y) = (x && y == x).\n\n#[export] HB.instance Definition _ := @POrder_Meet_isDistrLattice.Build\n bool_display bool andb orb andbC orbC andbA orbA orKb andKb leEmeet andb_orl.\n#[export] HB.instance Definition _ := DistrLattice_isTotal.Build bool_display \n bool leq_total.\n(*This lemma states that the generic meet operation within the boolean lattice structure is equivalent to the logical conjunction function.*)\nLemma andEbool : meet = andb. \n(*This lemma states that the generic join operation within the boolean lattice structure is equivalent to the logical disjunction function.*)\nLemma orEbool : meet = andb. \n(*This lemma states that the lattice difference between two booleans is defined as the logical conjunction of the first boolean with the logical negation of the second.*)\nLemma subEbool x y : x `\\` y = x && ~~ y. \n(*This lemma states that the generic complement operation within the boolean lattice is equivalent to the logical negation function.*)\nLemma complEbool : compl = negb. \n\nEnd BoolOrder.\nModule Exports.\nHB.reexport BoolOrder.\n(*This definition asserts that the less-than-or-equal-to relation between two booleans is equivalent to boolean implication from the first boolean to the second.*)\nDefinition leEbool := leEbool.\n(*This definition asserts that for two booleans, the first is strictly less than the second if and only if the first is false and the second is true.*)\nDefinition ltEbool := ltEbool.\n(*This definition represents the logical AND operation on two boolean values, which corresponds to the infimum, or greatest lower bound, in the standard boolean lattice where false is less than true.*)\nDefinition andEbool := andEbool.\n(*This definition represents the logical OR operation on two boolean values, which corresponds to the supremum, or least upper bound, in the standard boolean lattice where false is less than true.*)\nDefinition orEbool := orEbool.\n(*This definition represents an operation on two boolean values that returns true if and only if the first input is true and the second input is false.*)\nDefinition subEbool := subEbool.\n(*This definition represents the logical NOT operation, which returns the complement of a boolean value, inverting true to false and false to true.*)\nDefinition complEbool := complEbool.\nEnd Exports.\nEnd BoolOrder.\nHB.export BoolOrder.Exports.\n\nModule Import ProdSyntax.\n\nExport ProdSyntax.\n\n(*A local notation for the bottom element, or least element, of a product type equipped with the component-wise order.*)\nLocal Notation \"\\bot\" := (@bottom (prod_display _ _) _).\n(*A local notation for the top element, or greatest element, of a product type equipped with the component-wise order.*)\nLocal Notation \"\\top\" := (@top (prod_display _ _) _).\n(*A local notation for the meet operation, which computes the greatest lower bound, or infimum, of two elements in a product type under the component-wise order.*)\nLocal Notation meet := (@meet (prod_display _ _) _).\n(*A local notation for the join operation, which computes the least upper bound, or supremum, of two elements in a product type under the component-wise order.*)\nLocal Notation join := (@join (prod_display _ _) _).\n(*A local notation for the binary minimum operation on a product type, which returns the element that is less than or equal to the other according to the component-wise order.*)\nLocal Notation min := (@min (prod_display _ _) _).\n(*A local notation for the binary maximum operation on a product type, which returns the element that is greater than or equal to the other according to the component-wise order.*)\nLocal Notation max := (@max (prod_display _ _) _).\n\n(*A notation for the meet operation, or greatest lower bound, between two elements of a product type, based on the component-wise order.*)\nNotation \"x `&^p` y\" := (meet x y) : order_scope.\n(*A notation for the join operation, or least upper bound, between two elements of a product type, based on the component-wise order.*)\nNotation \"x `|^p` y\" := (join x y) : order_scope.\n\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to indices from a given list that satisfy a boolean predicate.*)\nNotation \"\\join^p_ ( i <- r | P ) F\" :=\n (\\big[join / \\bot]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to every index from a given list.*)\nNotation \"\\join^p_ ( i <- r ) F\" :=\n (\\big[join / \\bot]_(i <- r) F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to indices from an inferred finite type that satisfy a boolean predicate.*)\nNotation \"\\join^p_ ( i | P ) F\" :=\n (\\big[join / \\bot]_(i | P%B) F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to every index of an inferred finite type.*)\nNotation \"\\join^p_ i F\" :=\n (\\big[join / \\bot]_i F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to indices from a specified finite type that satisfy a boolean predicate.*)\nNotation \"\\join^p_ ( i : I | P ) F\" :=\n (\\big[join / \\bot]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to every index from a specified finite type.*)\nNotation \"\\join^p_ ( i : I ) F\" :=\n (\\big[join / \\bot]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to natural number indices within a given range that satisfy a boolean predicate.*)\nNotation \"\\join^p_ ( m <= i < n | P ) F\" :=\n (\\big[join / \\bot]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to every natural number index within a given range.*)\nNotation \"\\join^p_ ( m <= i < n ) F\" :=\n (\\big[join / \\bot]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to natural number indices below a given bound that satisfy a boolean predicate.*)\nNotation \"\\join^p_ ( i < n | P ) F\" :=\n (\\big[join / \\bot]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to every natural number index below a given bound.*)\nNotation \"\\join^p_ ( i < n ) F\" :=\n (\\big[join / \\bot]_(i < n) F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to indices from a given finite set that satisfy a boolean predicate.*)\nNotation \"\\join^p_ ( i 'in' A | P ) F\" :=\n (\\big[join / \\bot]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the iterated join, or supremum, of a family of elements of a product type, generated by applying a function to every index from a given finite set.*)\nNotation \"\\join^p_ ( i 'in' A ) F\" :=\n (\\big[join / \\bot]_(i in A) F%O) : order_scope.\n\n(*A notation for computing the iterated meet, or infimum, of a family of elements of a product type, generated by applying a function to indices from a given list that satisfy a boolean predicate.*)\nNotation \"\\meet^p_ ( i <- r | P ) F\" :=\n (\\big[meet / \\top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the iterated meet, or infimum, of a family of elements of a product type, generated by applying a function to every index from a given list.*)\nNotation \"\\meet^p_ ( i <- r ) F\" :=\n (\\big[meet / \\top]_(i <- r) F%O) : order_scope.\n(*A notation for computing the iterated meet, or infimum, of a family of elements of a product type, generated by applying a function to indices from an inferred finite type that satisfy a boolean predicate.*)\nNotation \"\\meet^p_ ( i | P ) F\" :=\n (\\big[meet / \\top]_(i | P%B) F%O) : order_scope.\n(*A notation for computing the iterated meet, or infimum, of a family of elements of a product type, generated by applying a function to every index of an inferred finite type.*)\nNotation \"\\meet^p_ i F\" :=\n (\\big[meet / \\top]_i F%O) : order_scope.\n(*A notation for computing the iterated meet, or infimum, of a family of elements of a product type, generated by applying a function to indices from a specified finite type that satisfy a boolean predicate.*)\nNotation \"\\meet^p_ ( i : I | P ) F\" :=\n (\\big[meet / \\top]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the iterated meet, or infimum, of a family of elements of a product type, generated by applying a function to every index from a specified finite type.*)\nNotation \"\\meet^p_ ( i : I ) F\" :=\n (\\big[meet / \\top]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for the component-wise infimum (meet) of a family of values generated by a function `F` over a natural number index `i`. The index ranges from a lower bound `m` up to, but not including, an upper bound `n`, and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the top element.*)\nNotation \"\\meet^p_ ( m <= i < n | P ) F\" :=\n (\\big[meet / \\top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the component-wise infimum (meet) of a family of values generated by a function `F` over a natural number index `i`. The index ranges from a lower bound `m` up to, but not including, an upper bound `n`. If this range of indices is empty, the result is the top element.*)\nNotation \"\\meet^p_ ( m <= i < n ) F\" :=\n (\\big[meet / \\top]_(m <= i < n) F%O) : order_scope.\n(*A notation for the component-wise infimum (meet) of a family of values generated by a function `F` over a natural number index `i`. The index ranges from zero up to, but not including, an upper bound `n`, and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the top element.*)\nNotation \"\\meet^p_ ( i < n | P ) F\" :=\n (\\big[meet / \\top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the component-wise infimum (meet) of a family of values generated by a function `F` over a natural number index `i`. The index ranges from zero up to, but not including, an upper bound `n`. If this range of indices is empty, the result is the top element.*)\nNotation \"\\meet^p_ ( i < n ) F\" :=\n (\\big[meet / \\top]_(i < n) F%O) : order_scope.\n(*A notation for the component-wise infimum (meet) of a family of values generated by a function `F` over an index `i`. The index is taken from a given finite set `A` and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the top element.*)\nNotation \"\\meet^p_ ( i 'in' A | P ) F\" :=\n (\\big[meet / \\top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for the component-wise infimum (meet) of a family of values generated by a function `F` over the elements `i` of a given finite set `A`. If the set `A` is empty, the result is the top element.*)\nNotation \"\\meet^p_ ( i 'in' A ) F\" :=\n (\\big[meet / \\top]_(i in A) F%O) : order_scope.\n\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over an index `i`. The index ranges over all elements of an inferred finite type. If this type is empty, the result is the top element.*)\nNotation \"\\min^p_ i F\" :=\n (\\big[min/top]_i F) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over an index `i`. The index iterates over the elements of a given finite sequence `r` and must also satisfy a given predicate `P`. If no element satisfies the predicate, the result is the top element.*)\nNotation \"\\min^p_ ( i <- r | P ) F\" :=\n (\\big[min/top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over an index `i`. The index iterates over all elements of a given finite sequence `r`. If the sequence is empty, the result is the top element.*)\nNotation \"\\min^p_ ( i < r ) F\" :=\n (\\big[min/top]_(i <- r) F%O) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over a natural number index `i`. The index ranges from a lower bound `m` up to, but not including, an upper bound `n`, and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the top element.*)\nNotation \"\\min^p_ ( m <= i < n | P ) F\" :=\n (\\big[min/top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over a natural number index `i`. The index ranges from a lower bound `m` up to, but not including, an upper bound `n`. If this range of indices is empty, the result is the top element.*)\nNotation \"\\min^p_ ( m <= i < n ) F\" :=\n (\\big[min/top]_(m <= i < n) F%O) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over an index `i`. The index ranges over all elements of an inferred finite type that also satisfy a given predicate `P`. If no element satisfies the predicate, the result is the top element.*)\nNotation \"\\min^p_ ( i | P ) F\" :=\n (\\big[min/top]_(i | P%B) F%O) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over an index `i` of a given finite type `t`. The index must also satisfy a given predicate `P`. If no element satisfies the predicate, the result is the top element. This notation is for parsing only.*)\nNotation \"\\min^p_ ( i : t | P ) F\" :=\n (\\big[min/top]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over an index `i`. The index ranges over all elements of a given finite type `t`. If the type is empty, the result is the top element. This notation is for parsing only.*)\nNotation \"\\min^p_ ( i : t ) F\" :=\n (\\big[min/top]_(i : t) F%O) (only parsing) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over a natural number index `i`. The index ranges from zero up to, but not including, an upper bound `n`, and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the top element.*)\nNotation \"\\min^p_ ( i < n | P ) F\" :=\n (\\big[min/top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over a natural number index `i`. The index ranges from zero up to, but not including, an upper bound `n`. If this range of indices is empty, the result is the top element.*)\nNotation \"\\min^p_ ( i < n ) F\" :=\n (\\big[min/top]_(i < n) F%O) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over an index `i`. The index is taken from a given finite set `A` and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the top element.*)\nNotation \"\\min^p_ ( i 'in' A | P ) F\" :=\n (\\big[min/top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for the component-wise minimum of a family of values generated by a function `F` over the elements `i` of a given finite set `A`. If the set `A` is empty, the result is the top element.*)\nNotation \"\\min^p_ ( i 'in' A ) F\" :=\n (\\big[min/top]_(i in A) F%O) : order_scope.\n\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over an index `i`. The index ranges over all elements of an inferred finite type. If this type is empty, the result is the bottom element.*)\nNotation \"\\max^p_ i F\" :=\n (\\big[max/bottom]_i F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over an index `i`. The index iterates over the elements of a given finite sequence `r` and must also satisfy a given predicate `P`. If no element satisfies the predicate, the result is the bottom element.*)\nNotation \"\\max^p_ ( i <- r | P ) F\" :=\n (\\big[max/bottom]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over an index `i`. The index iterates over all elements of a given finite sequence `r`. If the sequence is empty, the result is the bottom element.*)\nNotation \"\\max^p_ ( i < r ) F\" :=\n (\\big[max/bottom]_(i <- r) F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over a natural number index `i`. The index ranges from a lower bound `m` up to, but not including, an upper bound `n`, and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the bottom element.*)\nNotation \"\\max^p_ ( m <= i < n | P ) F\" :=\n (\\big[max/bottom]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over a natural number index `i`. The index ranges from a lower bound `m` up to, but not including, an upper bound `n`. If this range of indices is empty, the result is the bottom element.*)\nNotation \"\\max^p_ ( m <= i < n ) F\" :=\n (\\big[max/bottom]_(m <= i < n) F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over an index `i`. The index ranges over all elements of an inferred finite type that also satisfy a given predicate `P`. If no element satisfies the predicate, the result is the bottom element.*)\nNotation \"\\max^p_ ( i | P ) F\" :=\n (\\big[max/bottom]_(i | P%B) F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over an index `i` of a given finite type `t`. The index must also satisfy a given predicate `P`. If no element satisfies the predicate, the result is the bottom element. This notation is for parsing only.*)\nNotation \"\\max^p_ ( i : t | P ) F\" :=\n (\\big[max/bottom]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over an index `i`. The index ranges over all elements of a given finite type `t`. If the type is empty, the result is the bottom element. This notation is for parsing only.*)\nNotation \"\\max^p_ ( i : t ) F\" :=\n (\\big[max/bottom]_(i : t) F%O) (only parsing) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over a natural number index `i`. The index ranges from zero up to, but not including, an upper bound `n`, and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the bottom element.*)\nNotation \"\\max^p_ ( i < n | P ) F\" :=\n (\\big[max/bottom]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over a natural number index `i`. The index ranges from zero up to, but not including, an upper bound `n`. If this range of indices is empty, the result is the bottom element.*)\nNotation \"\\max^p_ ( i < n ) F\" :=\n (\\big[max/bottom]_(i < n) F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over an index `i`. The index is taken from a given finite set `A` and must also satisfy a given predicate `P`. If no index satisfies these conditions, the result is the bottom element.*)\nNotation \"\\max^p_ ( i 'in' A | P ) F\" :=\n (\\big[max/bottom]_(i in A | P%B) F%O) : order_scope.\n(*A notation for the component-wise maximum of a family of values generated by a function `F` over the elements `i` of a given finite set `A`. If the set `A` is empty, the result is the bottom element.*)\nNotation \"\\max^p_ ( i 'in' A ) F\" :=\n (\\big[max/bottom]_(i in A) F%O) : order_scope.\n\nEnd ProdSyntax.\n\nModule Import SeqProdSyntax.\n\nExport SeqProdSyntax.\n\n(*A local notation for the bottom element in a sequence type with the product order. This element is a sequence where each component is the bottom element of its respective type.*)\nLocal Notation \"\\bot\" := (@bottom (seqprod_display _) _).\n(*A local notation for the top element in a sequence type with the product order. This element is a sequence where each component is the top element of its respective type.*)\nLocal Notation \"\\top\" := (@top (seqprod_display _) _).\n(*A local notation for the meet, or greatest lower bound, operation for sequences under the product order. This operation computes the result component-wise.*)\nLocal Notation meet := (@meet (seqprod_display _) _).\n(*A local notation for the join, or least upper bound, operation for sequences under the product order. This operation computes the result component-wise.*)\nLocal Notation join := (@join (seqprod_display _) _).\n(*A local notation for the minimum operation for sequences under the product order, which computes the component-wise minimum of two sequences.*)\nLocal Notation min := (@min (seqprod_display _) _).\n(*A local notation for the maximum operation for sequences under the product order, which computes the component-wise maximum of two sequences.*)\nLocal Notation max := (@max (seqprod_display _) _).\n\n(*A notation for the meet, or greatest lower bound, of two sequences under the component-wise product order. The `sp` suffix indicates 'sequence product'.*)\nNotation \"x `&^sp` y\" := (meet x y) : order_scope.\n(*A notation for the join, or least upper bound, of two sequences under the component-wise product order. The `sp` suffix indicates 'sequence product'.*)\nNotation \"x `|^sp` y\" := (join x y) : order_scope.\n\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The iteration is over the indices `i` from a given finite sequence `r` that satisfy a predicate `P`. For each such index, a sequence is generated by a function `F`. The result is the component-wise join of all these generated sequences. If no index satisfies the predicate, the result is the bottom element of the sequence product order.*)\nNotation \"\\join^sp_ ( i <- r | P ) F\" :=\n (\\big[join / \\bot]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The iteration is over all indices `i` from a given finite sequence `r`. For each such index, a sequence is generated by a function `F`. The result is the component-wise join of all these generated sequences. If the input sequence `r` is empty, the result is the bottom element of the sequence product order.*)\nNotation \"\\join^sp_ ( i <- r ) F\" :=\n (\\big[join / \\bot]_(i <- r) F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The index `i` ranges over all elements of its finite type, and only those that satisfy a predicate `P` are considered. For each valid index, a sequence is generated by a function `F`. The result is the component-wise join of all these generated sequences. If no index satisfies the predicate, the result is the bottom element of the sequence product order.*)\nNotation \"\\join^sp_ ( i | P ) F\" :=\n (\\big[join / \\bot]_(i | P%B) F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The index `i` ranges over all elements of its finite type. For each index, a sequence is generated by a function `F`. The result is the component-wise join of all these generated sequences. If the index type is empty, the result is the bottom element of the sequence product order.*)\nNotation \"\\join^sp_ i F\" :=\n (\\big[join / \\bot]_i F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences, used for parsing only. The index `i` of a specified finite type `I` ranges over all its elements, filtered by a predicate `P`. For each valid index, a function `F` generates a sequence. The result is the component-wise join of all such sequences. The default for an empty iteration is the bottom element.*)\nNotation \"\\join^sp_ ( i : I | P ) F\" :=\n (\\big[join / \\bot]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences, used for parsing only. The index `i` of a specified finite type `I` ranges over all its elements. For each index, a function `F` generates a sequence. The result is the component-wise join of all such sequences. The default for an empty iteration is the bottom element.*)\nNotation \"\\join^sp_ ( i : I ) F\" :=\n (\\big[join / \\bot]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The index `i` ranges over the natural numbers from `m` up to, but not including, `n`. Only indices satisfying a predicate `P` are considered. For each valid index, a function `F` generates a sequence. The result is the component-wise join of all such sequences. The default for an empty iteration is the bottom element.*)\nNotation \"\\join^sp_ ( m <= i < n | P ) F\" :=\n (\\big[join / \\bot]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The index `i` ranges over the natural numbers from `m` up to, but not including, `n`. For each index, a function `F` generates a sequence. The result is the component-wise join of all such sequences. The default for an empty iteration is the bottom element.*)\nNotation \"\\join^sp_ ( m <= i < n ) F\" :=\n (\\big[join / \\bot]_(m <= i < n) F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The index `i` ranges over the natural numbers from zero up to, but not including, `n`. Only indices satisfying a predicate `P` are considered. For each valid index, a function `F` generates a sequence. The result is the component-wise join of all such sequences. The default for an empty iteration is the bottom element.*)\nNotation \"\\join^sp_ ( i < n | P ) F\" :=\n (\\big[join / \\bot]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The index `i` ranges over the natural numbers from zero up to, but not including, `n`. For each index, a function `F` generates a sequence. The result is the component-wise join of all such sequences. The default for an empty iteration is the bottom element.*)\nNotation \"\\join^sp_ ( i < n ) F\" :=\n (\\big[join / \\bot]_(i < n) F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The index `i` ranges over all elements of a given finite set `A`. Only indices satisfying a predicate `P` are considered. For each valid index, a function `F` generates a sequence. The result is the component-wise join of all such sequences. The default for an empty iteration is the bottom element.*)\nNotation \"\\join^sp_ ( i 'in' A | P ) F\" :=\n (\\big[join / \\bot]_(i in A | P%B) F%O) : order_scope.\n(*A notation for the iterated join, or component-wise supremum, of a family of sequences. The index `i` ranges over all elements of a given finite set `A`. For each index, a function `F` generates a sequence. The result is the component-wise join of all such sequences. The default for an empty iteration is the bottom element.*)\nNotation \"\\join^sp_ ( i 'in' A ) F\" :=\n (\\big[join / \\bot]_(i in A) F%O) : order_scope.\n\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences. The iteration is over the indices `i` from a given finite sequence `r` that satisfy a predicate `P`. For each such index, a sequence is generated by a function `F`. The result is the component-wise meet of all these generated sequences. If no index satisfies the predicate, the result is the top element of the sequence product order.*)\nNotation \"\\meet^sp_ ( i <- r | P ) F\" :=\n (\\big[meet / \\top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences. The iteration is over all indices `i` from a given finite sequence `r`. For each such index, a sequence is generated by a function `F`. The result is the component-wise meet of all these generated sequences. If the input sequence `r` is empty, the result is the top element of the sequence product order.*)\nNotation \"\\meet^sp_ ( i <- r ) F\" :=\n (\\big[meet / \\top]_(i <- r) F%O) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences. The index `i` ranges over all elements of its finite type, and only those that satisfy a predicate `P` are considered. For each valid index, a sequence is generated by a function `F`. The result is the component-wise meet of all these generated sequences. If no index satisfies the predicate, the result is the top element of the sequence product order.*)\nNotation \"\\meet^sp_ ( i | P ) F\" :=\n (\\big[meet / \\top]_(i | P%B) F%O) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences. The index `i` ranges over all elements of its finite type. For each index, a sequence is generated by a function `F`. The result is the component-wise meet of all these generated sequences. If the index type is empty, the result is the top element of the sequence product order.*)\nNotation \"\\meet^sp_ i F\" :=\n (\\big[meet / \\top]_i F%O) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences, used for parsing only. The index `i` of a specified finite type `I` ranges over all its elements, filtered by a predicate `P`. For each valid index, a function `F` generates a sequence. The result is the component-wise meet of all such sequences. The default for an empty iteration is the top element.*)\nNotation \"\\meet^sp_ ( i : I | P ) F\" :=\n (\\big[meet / \\top]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences, used for parsing only. The index `i` of a specified finite type `I` ranges over all its elements. For each index, a function `F` generates a sequence. The result is the component-wise meet of all such sequences. The default for an empty iteration is the top element.*)\nNotation \"\\meet^sp_ ( i : I ) F\" :=\n (\\big[meet / \\top]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences. The index `i` ranges over the natural numbers from `m` up to, but not including, `n`. Only indices satisfying a predicate `P` are considered. For each valid index, a function `F` generates a sequence. The result is the component-wise meet of all such sequences. The default for an empty iteration is the top element.*)\nNotation \"\\meet^sp_ ( m <= i < n | P ) F\" :=\n (\\big[meet / \\top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences. The index `i` ranges over the natural numbers from `m` up to, but not including, `n`. For each index, a function `F` generates a sequence. The result is the component-wise meet of all such sequences. The default for an empty iteration is the top element.*)\nNotation \"\\meet^sp_ ( m <= i < n ) F\" :=\n (\\big[meet / \\top]_(m <= i < n) F%O) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences. The index `i` ranges over the natural numbers from zero up to, but not including, `n`. Only indices satisfying a predicate `P` are considered. For each valid index, a function `F` generates a sequence. The result is the component-wise meet of all such sequences. The default for an empty iteration is the top element.*)\nNotation \"\\meet^sp_ ( i < n | P ) F\" :=\n (\\big[meet / \\top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for the iterated meet, or component-wise infimum, of a family of sequences. The index `i` ranges over the natural numbers from zero up to, but not including, `n`. For each index, a function `F` generates a sequence. The result is the component-wise meet of all such sequences. The default for an empty iteration is the top element.*)\nNotation \"\\meet^sp_ ( i < n ) F\" :=\n (\\big[meet / \\top]_(i < n) F%O) : order_scope.\n(*A notation for computing the greatest lower bound of a family of values given by an expression `F`, indexed by elements `i` in a finite set `A` that satisfy a predicate `P`. The computation uses the component-wise sequence product order. If no index satisfies the conditions, the result is the top element of the order.*)\nNotation \"\\meet^sp_ ( i 'in' A | P ) F\" :=\n (\\big[meet / \\top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the greatest lower bound of a family of values given by an expression `F`, indexed by all elements `i` in a finite set `A`. The computation uses the component-wise sequence product order. If the set `A` is empty, the result is the top element of the order.*)\nNotation \"\\meet^sp_ ( i 'in' A ) F\" :=\n (\\big[meet / \\top]_(i in A) F%O) : order_scope.\n\n(*A notation for computing the minimum value of an expression `F` over an implicitly-defined range of indices `i`, with respect to the component-wise sequence product order. If the range of indices is empty, the result is the top element of the order.*)\nNotation \"\\min^sp_ i F\" :=\n (\\big[min/top]_i F) : order_scope.\n(*A notation for computing the minimum value of an expression `F` for all items `i` in a finite sequence `r` that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no item satisfies the predicate, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i <- r | P ) F\" :=\n (\\big[min/top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the minimum value of an expression `F` over all enumerated elements `i` of a finite type `r`, with respect to the component-wise sequence product order. If the type `r` is empty, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i < r ) F\" :=\n (\\big[min/top]_(i <- r) F%O) : order_scope.\n(*A notation for computing the minimum value of an expression `F` for all natural numbers `i` in the range from `m` up to, but not including, `n` that satisfy a predicate `P`. The minimum is computed using the component-wise sequence product order. If no number in the range satisfies the predicate, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( m <= i < n | P ) F\" :=\n (\\big[min/top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the minimum value of an expression `F` for all natural numbers `i` in the range from `m` up to, but not including, `n`. The minimum is computed using the component-wise sequence product order. If the range is empty, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( m <= i < n ) F\" :=\n (\\big[min/top]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the minimum value of an expression `F` over all values `i` of an inferred type that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no value satisfies the predicate, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i | P ) F\" :=\n (\\big[min/top]_(i | P%B) F%O) : order_scope.\n(*A notation for computing the minimum value of an expression `F` over all values `i` of a given type `t` that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no value satisfies the predicate, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i : t | P ) F\" :=\n (\\big[min/top]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the minimum value of an expression `F` over all values `i` of a given type `t`, with respect to the component-wise sequence product order. If the type `t` has no elements, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i : t ) F\" :=\n (\\big[min/top]_(i : t) F%O) (only parsing) : order_scope.\n(*A notation for computing the minimum value of an expression `F` for all natural numbers `i` less than `n` that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no number satisfies the predicate, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i < n | P ) F\" :=\n (\\big[min/top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the minimum value of an expression `F` for all natural numbers `i` less than `n`, with respect to the component-wise sequence product order. If `n` is zero, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i < n ) F\" :=\n (\\big[min/top]_(i < n) F%O) : order_scope.\n(*A notation for computing the minimum value of an expression `F` for all elements `i` in a finite set `A` that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no element satisfies the predicate, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i 'in' A | P ) F\" :=\n (\\big[min/top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the minimum value of an expression `F` for all elements `i` in a finite set `A`, with respect to the component-wise sequence product order. If the set `A` is empty, the result is the top element of the order.*)\nNotation \"\\min^sp_ ( i 'in' A ) F\" :=\n (\\big[min/top]_(i in A) F%O) : order_scope.\n\n(*A notation for computing the maximum value of an expression `F` over an implicitly-defined range of indices `i`, with respect to the component-wise sequence product order. If the range of indices is empty, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ i F\" :=\n (\\big[max/bottom]_i F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` for all items `i` in a finite sequence `r` that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no item satisfies the predicate, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i <- r | P ) F\" :=\n (\\big[max/bottom]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` over all enumerated elements `i` of a finite type `r`, with respect to the component-wise sequence product order. If the type `r` is empty, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i < r ) F\" :=\n (\\big[max/bottom]_(i <- r) F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` for all natural numbers `i` in the range from `m` up to, but not including, `n` that satisfy a predicate `P`. The maximum is computed using the component-wise sequence product order. If no number in the range satisfies the predicate, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( m <= i < n | P ) F\" :=\n (\\big[max/bottom]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` for all natural numbers `i` in the range from `m` up to, but not including, `n`. The maximum is computed using the component-wise sequence product order. If the range is empty, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( m <= i < n ) F\" :=\n (\\big[max/bottom]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` over all values `i` of an inferred type that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no value satisfies the predicate, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i | P ) F\" :=\n (\\big[max/bottom]_(i | P%B) F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` over all values `i` of a given type `t` that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no value satisfies the predicate, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i : t | P ) F\" :=\n (\\big[max/bottom]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the maximum value of an expression `F` over all values `i` of a given type `t`, with respect to the component-wise sequence product order. If the type `t` has no elements, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i : t ) F\" :=\n (\\big[max/bottom]_(i : t) F%O) (only parsing) : order_scope.\n(*A notation for computing the maximum value of an expression `F` for all natural numbers `i` less than `n` that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no number satisfies the predicate, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i < n | P ) F\" :=\n (\\big[max/bottom]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` for all natural numbers `i` less than `n`, with respect to the component-wise sequence product order. If `n` is zero, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i < n ) F\" :=\n (\\big[max/bottom]_(i < n) F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` for all elements `i` in a finite set `A` that satisfy a predicate `P`, with respect to the component-wise sequence product order. If no element satisfies the predicate, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i 'in' A | P ) F\" :=\n (\\big[max/bottom]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the maximum value of an expression `F` for all elements `i` in a finite set `A`, with respect to the component-wise sequence product order. If the set `A` is empty, the result is the bottom element of the order.*)\nNotation \"\\max^sp_ ( i 'in' A ) F\" :=\n (\\big[max/bottom]_(i in A) F%O) : order_scope.\n\nEnd SeqProdSyntax.\n\nModule Import LexiSyntax.\n\nExport LexiSyntax.\n\n(*This definition provides the greatest lower bound (meet) operation for pairs of elements under the lexicographic order.*)\nNotation meetlexi := (@meet (lexi_display _ _) _).\n(*This definition provides the least upper bound (join) operation for pairs of elements under the lexicographic order.*)\nNotation joinlexi := (@join (lexi_display _ _) _).\n\n(**)\nNotation \"x `&^l` y\" := (meetlexi x y) : order_scope.\n(**)\nNotation \"x `|^l` y\" := (joinlexi x y) : order_scope.\n\n(**)\nLocal Notation \"\\bot\" := (@bottom (lexi_display _ _) _).\n(**)\nLocal Notation \"\\top\" := (@top (lexi_display _ _) _).\n(*This notation provides a symbolic representation for the meet operation, which computes the greatest lower bound of two elements in a lattice with a lexicographic order.*)\nLocal Notation meet := (@meet (lexi_display _ _) _).\n(*This notation provides a symbolic representation for the join operation, which computes the least upper bound of two elements in a lattice with a lexicographic order.*)\nLocal Notation join := (@join (lexi_display _ _) _).\n(*This notation provides a symbolic representation for the minimum operation in a totally ordered structure, which is defined as the meet operation, specifically in a context with a lexicographic order.*)\nLocal Notation min := (@min (lexi_display _ _) _).\n(*This notation provides a symbolic representation for the maximum operation in a totally ordered structure, which is defined as the join operation, specifically in a context with a lexicographic order.*)\nLocal Notation max := (@max (lexi_display _ _) _).\n\n(**)\nNotation \"\\join^l_ ( i <- r | P ) F\" :=\n (\\big[join / \\bot]_(i <- r | P%B) F%O) : order_scope.\n(**)\nNotation \"\\join^l_ ( i <- r ) F\" :=\n (\\big[join / \\bot]_(i <- r) F%O) : order_scope.\n(**)\nNotation \"\\join^l_ ( i | P ) F\" :=\n (\\big[join / \\bot]_(i | P%B) F%O) : order_scope.\n(**)\nNotation \"\\join^l_ i F\" :=\n (\\big[join / \\bot]_i F%O) : order_scope.\n(**)\nNotation \"\\join^l_ ( i : I | P ) F\" :=\n (\\big[join / \\bot]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(**)\nNotation \"\\join^l_ ( i : I ) F\" :=\n (\\big[join / \\bot]_(i : I) F%O) (only parsing) : order_scope.\n(**)\nNotation \"\\join^l_ ( m <= i < n | P ) F\" :=\n (\\big[join / \\bot]_(m <= i < n | P%B) F%O) : order_scope.\n(**)\nNotation \"\\join^l_ ( m <= i < n ) F\" :=\n (\\big[join / \\bot]_(m <= i < n) F%O) : order_scope.\n(**)\nNotation \"\\join^l_ ( i < n | P ) F\" :=\n (\\big[join / \\bot]_(i < n | P%B) F%O) : order_scope.\n(**)\nNotation \"\\join^l_ ( i < n ) F\" :=\n (\\big[join / \\bot]_(i < n) F%O) : order_scope.\n(**)\nNotation \"\\join^l_ ( i 'in' A | P ) F\" :=\n (\\big[join / \\bot]_(i in A | P%B) F%O) : order_scope.\n(**)\nNotation \"\\join^l_ ( i 'in' A ) F\" :=\n (\\big[join / \\bot]_(i in A) F%O) : order_scope.\n\n(**)\nNotation \"\\meet^l_ ( i <- r | P ) F\" :=\n (\\big[meet / \\top]_(i <- r | P%B) F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ ( i <- r ) F\" :=\n (\\big[meet / \\top]_(i <- r) F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ ( i | P ) F\" :=\n (\\big[meet / \\top]_(i | P%B) F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ i F\" :=\n (\\big[meet / \\top]_i F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ ( i : I | P ) F\" :=\n (\\big[meet / \\top]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(**)\nNotation \"\\meet^l_ ( i : I ) F\" :=\n (\\big[meet / \\top]_(i : I) F%O) (only parsing) : order_scope.\n(**)\nNotation \"\\meet^l_ ( m <= i < n | P ) F\" :=\n (\\big[meet / \\top]_(m <= i < n | P%B) F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ ( m <= i < n ) F\" :=\n (\\big[meet / \\top]_(m <= i < n) F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ ( i < n | P ) F\" :=\n (\\big[meet / \\top]_(i < n | P%B) F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ ( i < n ) F\" :=\n (\\big[meet / \\top]_(i < n) F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ ( i 'in' A | P ) F\" :=\n (\\big[meet / \\top]_(i in A | P%B) F%O) : order_scope.\n(**)\nNotation \"\\meet^l_ ( i 'in' A ) F\" :=\n (\\big[meet / \\top]_(i in A) F%O) : order_scope.\n\n(**)\nNotation \"\\min^l_ i F\" :=\n (\\big[min/top]_i F) : order_scope.\n(**)\nNotation \"\\min^l_ ( i <- r | P ) F\" :=\n (\\big[min/top]_(i <- r | P%B) F%O) : order_scope.\n(**)\nNotation \"\\min^l_ ( i < r ) F\" :=\n (\\big[min/top]_(i <- r) F%O) : order_scope.\n(**)\nNotation \"\\min^l_ ( m <= i < n | P ) F\" :=\n (\\big[min/top]_(m <= i < n | P%B) F%O) : order_scope.\n(**)\nNotation \"\\min^l_ ( m <= i < n ) F\" :=\n (\\big[min/top]_(m <= i < n) F%O) : order_scope.\n(**)\nNotation \"\\min^l_ ( i | P ) F\" :=\n (\\big[min/top]_(i | P%B) F%O) : order_scope.\n(**)\nNotation \"\\min^l_ ( i : t | P ) F\" :=\n (\\big[min/top]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(**)\nNotation \"\\min^l_ ( i : t ) F\" :=\n (\\big[min/top]_(i : t) F%O) (only parsing) : order_scope.\n(**)\nNotation \"\\min^l_ ( i < n | P ) F\" :=\n (\\big[min/top]_(i < n | P%B) F%O) : order_scope.\n(**)\nNotation \"\\min^l_ ( i < n ) F\" :=\n (\\big[min/top]_(i < n) F%O) : order_scope.\n(**)\nNotation \"\\min^l_ ( i 'in' A | P ) F\" :=\n (\\big[min/top]_(i in A | P%B) F%O) : order_scope.\n(**)\nNotation \"\\min^l_ ( i 'in' A ) F\" :=\n (\\big[min/top]_(i in A) F%O) : order_scope.\n\n(**)\nNotation \"\\max^l_ i F\" :=\n (\\big[max/bottom]_i F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( i <- r | P ) F\" :=\n (\\big[max/bottom]_(i <- r | P%B) F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( i < r ) F\" :=\n (\\big[max/bottom]_(i <- r) F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( m <= i < n | P ) F\" :=\n (\\big[max/bottom]_(m <= i < n | P%B) F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( m <= i < n ) F\" :=\n (\\big[max/bottom]_(m <= i < n) F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( i | P ) F\" :=\n (\\big[max/bottom]_(i | P%B) F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( i : t | P ) F\" :=\n (\\big[max/bottom]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(**)\nNotation \"\\max^l_ ( i : t ) F\" :=\n (\\big[max/bottom]_(i : t) F%O) (only parsing) : order_scope.\n(**)\nNotation \"\\max^l_ ( i < n | P ) F\" :=\n (\\big[max/bottom]_(i < n | P%B) F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( i < n ) F\" :=\n (\\big[max/bottom]_(i < n) F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( i 'in' A | P ) F\" :=\n (\\big[max/bottom]_(i in A | P%B) F%O) : order_scope.\n(**)\nNotation \"\\max^l_ ( i 'in' A ) F\" :=\n (\\big[max/bottom]_(i in A) F%O) : order_scope.\n\nEnd LexiSyntax.\n\nModule Import SeqLexiSyntax.\n\nExport SeqLexiSyntax.\n\n(*A definition for the meet operation, which computes the greatest lower bound of two sequences under the lexicographic order.*)\nNotation meetlexi := (@meet (seqlexi_display _) _).\n(*A definition for the join operation, which computes the least upper bound of two sequences under the lexicographic order.*)\nNotation joinlexi := (@join (seqlexi_display _) _).\n\n(*This is a notation for computing the greatest lower bound (meet) of two elements, `x` and `y`, under the lexicographic order.*)\nNotation \"x `&^l` y\" := (meetlexi x y) : order_scope.\n(*This is a notation for computing the least upper bound (join) of two elements, `x` and `y`, under the lexicographic order.*)\nNotation \"x `|^l` y\" := (joinlexi x y) : order_scope.\n\n(*A notation for the bottom element, which is the least element in a type equipped with a lexicographic order.*)\nLocal Notation \"\\bot\" := (@bottom (lexi_display _ _) _).\n(*A notation for the top element, which is the greatest element in a type equipped with a lexicographic order.*)\nLocal Notation \"\\top\" := (@top (lexi_display _ _) _).\n(*A local notation for the binary meet operation, which computes the greatest lower bound of two elements with respect to the lexicographic order.*)\nLocal Notation meet := (@meet (lexi_display _ _) _).\n(*A local notation for the binary join operation, which computes the least upper bound of two elements with respect to the lexicographic order.*)\nLocal Notation join := (@join (lexi_display _ _) _).\n(*A local notation for the binary minimum operation, which computes the smaller of two elements with respect to the lexicographic order.*)\nLocal Notation min := (@min (lexi_display _ _) _).\n(*A local notation for the binary maximum operation, which computes the larger of two elements with respect to the lexicographic order.*)\nLocal Notation max := (@max (lexi_display _ _) _).\n\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i that is drawn from a given finite sequence r and satisfies a boolean predicate P. If the set of indices is empty, it returns the bottom element.*)\nNotation \"\\join^l_ ( i <- r | P ) F\" :=\n (\\big[join / \\bot]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i from a given finite sequence r. If the sequence is empty, it returns the bottom element.*)\nNotation \"\\join^l_ ( i <- r ) F\" :=\n (\\big[join / \\bot]_(i <- r) F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i from a finite type that satisfies a boolean predicate P. If no index satisfies the predicate, it returns the bottom element.*)\nNotation \"\\join^l_ ( i | P ) F\" :=\n (\\big[join / \\bot]_(i | P%B) F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to every index i in a finite type. If the type is empty, it returns the bottom element.*)\nNotation \"\\join^l_ i F\" :=\n (\\big[join / \\bot]_i F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i of a specified finite type I that satisfies a boolean predicate P. If no index satisfies the predicate, it returns the bottom element. This is a parsing-only notation.*)\nNotation \"\\join^l_ ( i : I | P ) F\" :=\n (\\big[join / \\bot]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to every index i of a specified finite type I. If the type I is empty, it returns the bottom element. This is a parsing-only notation.*)\nNotation \"\\join^l_ ( i : I ) F\" :=\n (\\big[join / \\bot]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each natural number i in the range from m to n (exclusive) that satisfies a boolean predicate P. If the range is empty or no number satisfies the predicate, it returns the bottom element.*)\nNotation \"\\join^l_ ( m <= i < n | P ) F\" :=\n (\\big[join / \\bot]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each natural number i in the range from m to n (exclusive). If the range is empty, it returns the bottom element.*)\nNotation \"\\join^l_ ( m <= i < n ) F\" :=\n (\\big[join / \\bot]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each natural number i less than n that satisfies a boolean predicate P. If n is zero or no number satisfies the predicate, it returns the bottom element.*)\nNotation \"\\join^l_ ( i < n | P ) F\" :=\n (\\big[join / \\bot]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each natural number i less than n. If n is zero, it returns the bottom element.*)\nNotation \"\\join^l_ ( i < n ) F\" :=\n (\\big[join / \\bot]_(i < n) F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each element i of a finite set A that satisfies a boolean predicate P. If the set A is empty or no element satisfies the predicate, it returns the bottom element.*)\nNotation \"\\join^l_ ( i 'in' A | P ) F\" :=\n (\\big[join / \\bot]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the least upper bound (join) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each element i of a finite set A. If the set A is empty, it returns the bottom element.*)\nNotation \"\\join^l_ ( i 'in' A ) F\" :=\n (\\big[join / \\bot]_(i in A) F%O) : order_scope.\n\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i that is drawn from a given finite sequence r and satisfies a boolean predicate P. If the set of indices is empty, it returns the top element.*)\nNotation \"\\meet^l_ ( i <- r | P ) F\" :=\n (\\big[meet / \\top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i from a given finite sequence r. If the sequence is empty, it returns the top element.*)\nNotation \"\\meet^l_ ( i <- r ) F\" :=\n (\\big[meet / \\top]_(i <- r) F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i from a finite type that satisfies a boolean predicate P. If no index satisfies the predicate, it returns the top element.*)\nNotation \"\\meet^l_ ( i | P ) F\" :=\n (\\big[meet / \\top]_(i | P%B) F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to every index i in a finite type. If the type is empty, it returns the top element.*)\nNotation \"\\meet^l_ i F\" :=\n (\\big[meet / \\top]_i F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i of a specified finite type I that satisfies a boolean predicate P. If no index satisfies the predicate, it returns the top element. This is a parsing-only notation.*)\nNotation \"\\meet^l_ ( i : I | P ) F\" :=\n (\\big[meet / \\top]_(i : I | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to every index i of a specified finite type I. If the type I is empty, it returns the top element. This is a parsing-only notation.*)\nNotation \"\\meet^l_ ( i : I ) F\" :=\n (\\big[meet / \\top]_(i : I) F%O) (only parsing) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each natural number i in the range from m to n (exclusive) that satisfies a boolean predicate P. If the range is empty or no number satisfies the predicate, it returns the top element.*)\nNotation \"\\meet^l_ ( m <= i < n | P ) F\" :=\n (\\big[meet / \\top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each natural number i in the range from m to n (exclusive). If the range is empty, it returns the top element.*)\nNotation \"\\meet^l_ ( m <= i < n ) F\" :=\n (\\big[meet / \\top]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each natural number i less than n that satisfies a boolean predicate P. If n is zero or no number satisfies the predicate, it returns the top element.*)\nNotation \"\\meet^l_ ( i < n | P ) F\" :=\n (\\big[meet / \\top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each natural number i less than n. If n is zero, it returns the top element.*)\nNotation \"\\meet^l_ ( i < n ) F\" :=\n (\\big[meet / \\top]_(i < n) F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each element i of a finite set A that satisfies a boolean predicate P. If the set A is empty or no element satisfies the predicate, it returns the top element.*)\nNotation \"\\meet^l_ ( i 'in' A | P ) F\" :=\n (\\big[meet / \\top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the greatest lower bound (meet) of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each element i of a finite set A. If the set A is empty, it returns the top element.*)\nNotation \"\\meet^l_ ( i 'in' A ) F\" :=\n (\\big[meet / \\top]_(i in A) F%O) : order_scope.\n\n(*A notation for computing the minimum of a set of values with respect to the lexicographic order. The values are generated by applying a function F to every index i in a finite type. If the type is empty, it returns the top element.*)\nNotation \"\\min^l_ i F\" :=\n (\\big[min/top]_i F) : order_scope.\n(*A notation for computing the minimum of a set of values with respect to the lexicographic order. The values are generated by applying a function F to each index i that is drawn from a given finite sequence r and satisfies a boolean predicate P. If the set of indices is empty, it returns the top element.*)\nNotation \"\\min^l_ ( i <- r | P ) F\" :=\n (\\big[min/top]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the minimum of the values of a function over the elements of a given finite sequence, using lexicographic comparison. If the sequence is empty, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( i < r ) F\" :=\n (\\big[min/top]_(i <- r) F%O) : order_scope.\n(*A notation for computing the minimum of the values of a function over a range of natural numbers that satisfy a predicate, using lexicographic comparison. If no number in the range satisfies the predicate, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( m <= i < n | P ) F\" :=\n (\\big[min/top]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the minimum of the values of a function over a range of natural numbers, using lexicographic comparison. If the range is empty, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( m <= i < n ) F\" :=\n (\\big[min/top]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the minimum of the values of a function over all elements of a finite type that satisfy a given predicate, using lexicographic comparison. If no element satisfies the predicate, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( i | P ) F\" :=\n (\\big[min/top]_(i | P%B) F%O) : order_scope.\n(*A notation for computing the minimum of the values of a function over all elements of a specified finite type that satisfy a given predicate, using lexicographic comparison. If no element satisfies the predicate, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( i : t | P ) F\" :=\n (\\big[min/top]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the minimum of the values of a function over all elements of a specified finite type, using lexicographic comparison. If the type is empty, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( i : t ) F\" :=\n (\\big[min/top]_(i : t) F%O) (only parsing) : order_scope.\n(*A notation for computing the minimum of the values of a function over natural numbers less than a given bound that satisfy a predicate, using lexicographic comparison. If no number satisfies the predicate, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( i < n | P ) F\" :=\n (\\big[min/top]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the minimum of the values of a function over natural numbers less than a given bound, using lexicographic comparison. If the bound is zero, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( i < n ) F\" :=\n (\\big[min/top]_(i < n) F%O) : order_scope.\n(*A notation for computing the minimum of the values of a function over the elements of a finite set that satisfy a given predicate, using lexicographic comparison. If no element in the set satisfies the predicate, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( i 'in' A | P ) F\" :=\n (\\big[min/top]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the minimum of the values of a function over the elements of a finite set, using lexicographic comparison. If the set is empty, the result is the top element of the ordering.*)\nNotation \"\\min^l_ ( i 'in' A ) F\" :=\n (\\big[min/top]_(i in A) F%O) : order_scope.\n\n(*A notation for computing the maximum of the values of a function over all elements of a finite type, using lexicographic comparison. If the type is empty, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ i F\" :=\n (\\big[max/bottom]_i F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over the elements of a finite sequence that satisfy a given predicate, using lexicographic comparison. If no element satisfies the predicate, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i <- r | P ) F\" :=\n (\\big[max/bottom]_(i <- r | P%B) F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over the elements of a given finite sequence, using lexicographic comparison. If the sequence is empty, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i < r ) F\" :=\n (\\big[max/bottom]_(i <- r) F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over a range of natural numbers that satisfy a predicate, using lexicographic comparison. If no number in the range satisfies the predicate, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( m <= i < n | P ) F\" :=\n (\\big[max/bottom]_(m <= i < n | P%B) F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over a range of natural numbers, using lexicographic comparison. If the range is empty, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( m <= i < n ) F\" :=\n (\\big[max/bottom]_(m <= i < n) F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over all elements of a finite type that satisfy a given predicate, using lexicographic comparison. If no element satisfies the predicate, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i | P ) F\" :=\n (\\big[max/bottom]_(i | P%B) F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over all elements of a specified finite type that satisfy a given predicate, using lexicographic comparison. If no element satisfies the predicate, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i : t | P ) F\" :=\n (\\big[max/bottom]_(i : t | P%B) F%O) (only parsing) : order_scope.\n(*A notation for computing the maximum of the values of a function over all elements of a specified finite type, using lexicographic comparison. If the type is empty, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i : t ) F\" :=\n (\\big[max/bottom]_(i : t) F%O) (only parsing) : order_scope.\n(*A notation for computing the maximum of the values of a function over natural numbers less than a given bound that satisfy a predicate, using lexicographic comparison. If no number satisfies the predicate, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i < n | P ) F\" :=\n (\\big[max/bottom]_(i < n | P%B) F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over natural numbers less than a given bound, using lexicographic comparison. If the bound is zero, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i < n ) F\" :=\n (\\big[max/bottom]_(i < n) F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over the elements of a finite set that satisfy a given predicate, using lexicographic comparison. If no element in the set satisfies the predicate, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i 'in' A | P ) F\" :=\n (\\big[max/bottom]_(i in A | P%B) F%O) : order_scope.\n(*A notation for computing the maximum of the values of a function over the elements of a finite set, using lexicographic comparison. If the set is empty, the result is the bottom element of the ordering.*)\nNotation \"\\max^l_ ( i 'in' A ) F\" :=\n (\\big[max/bottom]_(i in A) F%O) : order_scope.\n\nEnd SeqLexiSyntax.\n\nModule ProdOrder.\n\nExport ProdOrder.\n\nLocal Open Scope type_scope. \n\nSection POrder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : porderType disp1) (T2 : porderType disp2).\n\n(*This fact asserts the antisymmetry property for a given 'less than or equal to' relation, which states that if two elements are less than or equal to each other, they must be equal.*)\nFact anti : antisymmetric (@le disp1 disp2 disp2 T1 T2).\n\nEnd POrder.\n\nSection POrder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : porderType disp1) (T2 : porderType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := POrder.on T1'.\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := POrder.on T2'.\n\n#[export]\n(*This lemma states that an element of a product type is strictly less than another element if and only if they are not equal, and each component of the first element is less than or equal to the corresponding component of the second.*)\nLemma ltEprod x y : (x < y) = [&& x != y, x.1 <= y.1 & x.2 <= y.2].\n\n(*This lemma provides an equivalence for the strict less-than relation on pairs from a product type, stating that one pair is strictly less than another if and only if their components are pointwise less than or equal, and at least one pair of corresponding components is not equal.*)\nLemma lt_pair (x1 y1 : T1) (x2 y2 : T2) : (x1, x2) < (y1, y2) :> T1 * T2 =\n [&& (x1 != y1) || (x2 != y2), x1 <= y1 & x2 <= y2].\n\nEnd POrder.\n\nSection MeetSemilattice.\nContext (disp1 disp2 : disp_t).\nContext (T1 : meetSemilatticeType disp1) (T2 : meetSemilatticeType disp2).\nLocal Notation \"T1 * T2\" := (type (Disp tt tt) T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\nLet meet x y := (x.1 `&` y.1, x.2 `&` y.2).\n\n(*This lemma states that in a lattice, an element is less than or equal to the meet of two other elements if and only if it is less than or equal to each of those two elements individually.*)\nFact lexI x y z : (x <= meet y z) = (x <= y) && (x <= z).\n\nEnd MeetSemilattice.\n\nSection MeetSemilattice.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : meetSemilatticeType disp1) (T2 : meetSemilatticeType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := MeetSemilattice.on T1'.\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := MeetSemilattice.on T2'.\n\n(*This definition specifies a function to compute the meet of two elements in a product of meet-semilattices. It takes two pairs as input and returns a new pair where each component is the meet of the corresponding components from the input pairs.*)\nDefinition meet x y := (x.1 `&` y.1, x.2 `&` y.2).\n\n#[export]\n(*This lemma states that the meet operation on a product of two meet-semilattices is defined component-wise. That is, the meet of two pairs is a new pair where the first component is the meet of the first components of the inputs, and the second component is the meet of their second components.*)\nLemma meetEprod x y : x `&` y = (x.1 `&` y.1, x.2 `&` y.2). \n\nEnd MeetSemilattice.\n\nSection JoinSemilattice.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : joinSemilatticeType disp1) (T2 : joinSemilatticeType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\n(*This definition establishes the join operation for pairs of elements coming from two join-semilattices. The resulting join is a new pair where the first component is the join of the first components of the input pairs, and the second component is the join of the second components.*)\nDefinition join x y := (x.1 `|` y.1, x.2 `|` y.2).\n\n#[export]\n(*This lemma states that the join operation on the product of two join-semilattices is computed component-wise. Specifically, the join of two pairs is equal to a new pair formed by the join of their first components and the join of their second components.*)\nLemma joinEprod x y : x `|` y = (x.1 `|` y.1, x.2 `|` y.2). \n\nEnd JoinSemilattice.\n\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : bPOrderType disp1) (T2 : bPOrderType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : tPOrderType disp1) (T2 : tPOrderType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : tbPOrderType disp1) (T2 : tbPOrderType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : bMeetSemilatticeType disp1) (T2 : bMeetSemilatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : tMeetSemilatticeType disp1) (T2 : tMeetSemilatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : tbMeetSemilatticeType disp1) (T2 : tbMeetSemilatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : bJoinSemilatticeType disp1) (T2 : bJoinSemilatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : tJoinSemilatticeType disp1) (T2 : tJoinSemilatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : tbJoinSemilatticeType disp1) (T2 : tbJoinSemilatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : latticeType disp1) (T2 : latticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : bLatticeType disp1) (T2 : bLatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : tLatticeType disp1) (T2 : tLatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (disp1 disp2 disp3 : disp_t)\n (T1 : tbLatticeType disp1) (T2 : tbLatticeType disp2) :=\n POrder.on (type disp3 T1 T2).\n\nSection DistrLattice.\nContext (disp1 disp2 : disp_t).\nContext (T1 : distrLatticeType disp1) (T2 : distrLatticeType disp2).\nLocal Notation \"T1 * T2\" := (type (Disp tt tt) T1 T2) : type_scope.\n\n(*This fact asserts that the meet operation distributes over the join operation from the left within the product of two distributive lattices. This means that taking the meet of an element with the join of two other elements yields the same result as taking the join of the meets of the first element with each of the other two elements.*)\nFact meetUl : @left_distributive (T1 * T2) _ Order.meet Order.join.\n\nEnd DistrLattice.\n\nSection DistrLattice.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : distrLatticeType disp1) (T2 : distrLatticeType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\n\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := DistrLattice.on T1'.\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := DistrLattice.on T2'.\n\n#[export]\n(*This fact states an identity involving the meet, join, and relative complement operations. It asserts that the meet of '(the join of z with the meet of x and y)' with 'the relative complement of y in the interval from z to x' is equal to 'the meet of x and y'.*)\nFact rcomplPmeet x y z : ((x `&` y) `|` z) `&` rcompl x y z = x `&` y.\n\nEnd CDistrLattice.\n\nSection CDistrLattice.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : cDistrLatticeType disp1) (T2 : cDistrLatticeType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y z : T1 * T2).\n\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := CDistrLattice.on T1'.\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := CDistrLattice.on T2'.\n\n(*This definition specifies the relative complement operation on a product of two complemented distributive lattices. Given three elements from this product lattice, it computes a new element by applying the relative complement operation from the underlying lattices to each component of the inputs. The result is a pair whose components are the respective relative complements.*)\nDefinition rcompl x y z := (rcompl x.1 y.1 z.1, rcompl x.2 y.2 z.2).\n\n#[export]\n(*This lemma states that the relative complement of three elements in a product of complemented distributive lattices is equal to a pair formed by computing the relative complement for each component separately using the operation from the respective underlying lattice.*)\nLemma rcomplEprod x y z :\n rcompl x y z = (Order.rcompl x.1 y.1 z.1, Order.rcompl x.2 y.2 z.2).\n\nEnd CDistrLattice.\n\nSection CBDistrLattice.\nContext (disp1 disp2 : disp_t).\nContext (T1 : cbDistrLatticeType disp1) (T2 : cbDistrLatticeType disp2).\nLocal Notation \"T1 * T2\" := (type (Disp tt tt) T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\nLet diff x y := (diff x.1 y.1, diff x.2 y.2).\n\n(*This lemma states that the difference of two elements is equivalent to the relative complement of the bottom element and the first element with respect to the second element.*)\nFact diffErcompl x y : diff x y = rcompl \\bot x y.\n\nEnd CBDistrLattice.\n\nSection CBDistrLattice.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : cbDistrLatticeType disp1) (T2 : cbDistrLatticeType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := CBDistrLattice.on T1'.\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := CBDistrLattice.on T2'.\n\n(*This definition specifies the relative complement operation for elements in a product of two complemented bounded distributive lattices. The operation is applied componentwise, yielding a new pair where each component is the relative complement of the corresponding components from the input pairs.*)\nDefinition diff x y := (diff x.1 y.1, diff x.2 y.2).\n\n#[export]\n(*This lemma states that the relative complement operator, denoted by a backslash, distributes over the components of pairs in a product lattice. Computing the relative complement of two pairs is equivalent to creating a new pair from the relative complements of their respective components.*)\nLemma diffEprod x y : x `\\` y = (x.1 `\\` y.1, x.2 `\\` y.2). \n\nEnd CBDistrLattice.\n\nSection CTDistrLattice.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : ctDistrLatticeType disp1) (T2 : ctDistrLatticeType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\n(*This definition specifies the codifference operation for a product type. The codifference of two pairs is defined as a new pair, where the first component is the codifference of the first components of the input pairs, and the second component is the codifference of the second components.*)\nDefinition codiff x y := (codiff x.1 y.1, codiff x.2 y.2).\n\n#[export]\n(*This lemma states that the codifference of two pairs is equal to a pair formed by computing the codifference of the respective first components and second components of the input pairs.*)\nLemma codiffEprod x y :\n codiff x y = (Order.codiff x.1 y.1, Order.codiff x.2 y.2).\n\nEnd CTDistrLattice.\n\nSection CTBDistrLattice.\nContext (disp1 disp2 : disp_t).\nContext (T1 : ctbDistrLatticeType disp1) (T2 : ctbDistrLatticeType disp2).\nLocal Notation \"T1 * T2\" := (type (Disp tt tt) T1 T2) : type_scope.\nImplicit Types (x : T1 * T2).\n\nLet compl x := (~` x.1, ~` x.2).\n\n(*This lemma states that the component-wise complement of a pair in a product lattice is equal to the lattice difference between the top element of that lattice and the given pair.*)\nFact complEdiff x : compl x = (\\top : T1 * T2) `\\` x.\n\nEnd CTBDistrLattice.\n\nSection CTBDistrLattice.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : ctbDistrLatticeType disp1) (T2 : ctbDistrLatticeType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x : T1 * T2).\n\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := CTBDistrLattice.on T1'.\n(*This definition creates a local alias for a type, typically used to make the type available within a specific scope or module.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := CTBDistrLattice.on T2'.\n\n(*This definition specifies the complement operation for pairs in a product lattice, where the complement of a pair is the pair of the complements of its elements.*)\nDefinition compl x := (~` x.1, ~` x.2).\n\n#[export]\n(*This lemma asserts that the complement of a pair of elements in a product lattice is computed component-wise, resulting in a pair of the complements of the original elements.*)\nLemma complEprod x : ~` x = (~` x.1, ~` x.2). \n\nEnd CTBDistrLattice.\n\nSection FinOrder.\nContext (disp1 disp2 disp3 : disp_t).\n\n#[export]\nHB.instance Definition _ (T1 : finPOrderType disp1)\n (T2 : finPOrderType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finBPOrderType disp1)\n (T2 : finBPOrderType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finTPOrderType disp1)\n (T2 : finTPOrderType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finTBPOrderType disp1)\n (T2 : finTBPOrderType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finMeetSemilatticeType disp1)\n (T2 : finMeetSemilatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finBMeetSemilatticeType disp1)\n (T2 : finBMeetSemilatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finJoinSemilatticeType disp1)\n (T2 : finJoinSemilatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finTJoinSemilatticeType disp1)\n (T2 : finTJoinSemilatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finLatticeType disp1)\n (T2 : finLatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finTBLatticeType disp1)\n (T2 : finTBLatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finDistrLatticeType disp1)\n (T2 : finDistrLatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finTBDistrLatticeType disp1)\n (T2 : finTBDistrLatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finCDistrLatticeType disp1)\n (T2 : finCDistrLatticeType disp2) := POrder.on (type disp3 T1 T2).\n#[export]\n(*This lemma asserts that for the product order, one pair is strictly less than another if and only if its components are less than or equal to the corresponding components of the other pair, and at least one of these component comparisons is strict.*)\nDefinition ltEprod := @ltEprod.\n(*This lemma provides a constructive rule for proving a strict inequality between two pairs in the product order, stating that if one component is strictly smaller and the other is less than or equal, the overall pair is strictly smaller.*)\nDefinition lt_pair := @lt_pair.\n(*This lemma asserts that the meet operation, also known as the greatest lower bound, on pairs in a product lattice is computed component-wise.*)\nDefinition meetEprod := @meetEprod.\n(*This lemma asserts that the join operation, also known as the least upper bound, on pairs in a product lattice is computed component-wise.*)\nDefinition joinEprod := @joinEprod.\n(*This lemma asserts that the relative complement of two pairs in a product lattice is computed component-wise.*)\nDefinition rcomplEprod := @rcomplEprod.\n(*This lemma asserts that the difference of two pairs in a product lattice is computed component-wise.*)\nDefinition diffEprod := @diffEprod.\n(*This lemma asserts that the codifference of two pairs in a product lattice is computed component-wise.*)\nDefinition codiffEprod := @codiffEprod.\n(*This definition provides an equation for the complement of a pair in a product lattice, stating that it is equal to the pair of the complements of its components.*)\nDefinition complEprod := @complEprod.\nEnd Exports.\nEnd ProdOrder.\nHB.export ProdOrder.Exports.\n\nModule DefaultProdOrder.\n\nExport DefaultProdOrder.\n\nSection DefaultProdOrder.\nContext {disp1 disp2 : disp_t}.\n\n(*This definition provides a local shorthand for creating a product type from two given ordered types, where the resulting type of pairs is endowed with the component-wise product order.*)\nLet prod T1 T2 := T1 *prod[prod_display disp1 disp2] T2.\n\nHB.instance Definition _ (T1 : porderType disp1) (T2 : porderType disp2) :=\n POrder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _ (T1 : bPOrderType disp1) (T2 : bPOrderType disp2) :=\n BPOrder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _ (T1 : tPOrderType disp1) (T2 : tPOrderType disp2) :=\n TPOrder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _ (T1 : tbPOrderType disp1) (T2 : tbPOrderType disp2) :=\n TBPOrder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : meetSemilatticeType disp1) (T2 : meetSemilatticeType disp2) :=\n MeetSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : bMeetSemilatticeType disp1) (T2 : bMeetSemilatticeType disp2) :=\n BMeetSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : tMeetSemilatticeType disp1) (T2 : tMeetSemilatticeType disp2) :=\n TMeetSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : tbMeetSemilatticeType disp1) (T2 : tbMeetSemilatticeType disp2) :=\n TBMeetSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : joinSemilatticeType disp1) (T2 : joinSemilatticeType disp2) :=\n JoinSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : bJoinSemilatticeType disp1) (T2 : bJoinSemilatticeType disp2) :=\n BJoinSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : tJoinSemilatticeType disp1) (T2 : tJoinSemilatticeType disp2) :=\n TJoinSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : tbJoinSemilatticeType disp1) (T2 : tbJoinSemilatticeType disp2) :=\n TBJoinSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _ (T1 : latticeType disp1) (T2 : latticeType disp2) :=\n Lattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _ (T1 : bLatticeType disp1) (T2 : bLatticeType disp2) :=\n BLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _ (T1 : tLatticeType disp1) (T2 : tLatticeType disp2) :=\n TLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : tbLatticeType disp1) (T2 : tbLatticeType disp2) :=\n TBLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : distrLatticeType disp1) (T2 : distrLatticeType disp2) :=\n DistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : bDistrLatticeType disp1) (T2 : bDistrLatticeType disp2) :=\n BDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : tDistrLatticeType disp1) (T2 : tDistrLatticeType disp2) :=\n TDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : tbDistrLatticeType disp1) (T2 : tbDistrLatticeType disp2) :=\n TBDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : cDistrLatticeType disp1) (T2 : cDistrLatticeType disp2) :=\n CDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : cbDistrLatticeType disp1) (T2 : cbDistrLatticeType disp2) :=\n CBDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : ctDistrLatticeType disp1) (T2 : ctDistrLatticeType disp2) :=\n CTDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : ctbDistrLatticeType disp1) (T2 : ctbDistrLatticeType disp2) :=\n CTBDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finPOrderType disp1) (T2 : finPOrderType disp2) :=\n FinPOrder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finBPOrderType disp1) (T2 : finBPOrderType disp2) :=\n FinBPOrder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finTPOrderType disp1) (T2 : finTPOrderType disp2) :=\n FinTPOrder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finTBPOrderType disp1) (T2 : finTBPOrderType disp2) :=\n FinTBPOrder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finMeetSemilatticeType disp1) (T2 : finMeetSemilatticeType disp2) :=\n FinMeetSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finBMeetSemilatticeType disp1) (T2 : finBMeetSemilatticeType disp2) :=\n FinBMeetSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finJoinSemilatticeType disp1) (T2 : finJoinSemilatticeType disp2) :=\n FinJoinSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finTJoinSemilatticeType disp1) (T2 : finTJoinSemilatticeType disp2) :=\n FinTJoinSemilattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finLatticeType disp1) (T2 : finLatticeType disp2) :=\n FinLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finTBLatticeType disp1) (T2 : finTBLatticeType disp2) :=\n FinTBLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finDistrLatticeType disp1) (T2 : finDistrLatticeType disp2) :=\n FinDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finTBDistrLatticeType disp1) (T2 : finTBDistrLatticeType disp2) :=\n FinTBDistrLattice.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finCDistrLatticeType disp1) (T2 : finCDistrLatticeType disp2) :=\n FinCDistrLattice.copy (T1 * T2)%type (prod T1 T2).\n(*This definition specifies the 'less than or equal to' relation for dependent pairs. An element is less than or equal to another if its first component is less than or equal to the other's first component, and if their first components are equivalent, then its second component must be less than or equal to the other's second component.*)\nDefinition le x y := (tag x <= tag y) &&\n ((tag x >= tag y) ==> (tagged x <= tagged_as x y)).\n(*This definition specifies the 'strictly less than' relation for dependent pairs. An element is strictly less than another if its first component is less than or equal to the other's first component, and if their first components are equivalent, then its second component must be strictly less than the other's second component.*)\nDefinition lt x y := (tag x <= tag y) &&\n ((tag x >= tag y) ==> (tagged x < tagged_as x y)).\n\n(*This fact asserts that the 'less than or equal to' relation defined on dependent pairs is reflexive, meaning any element is less than or equal to itself.*)\nFact refl : reflexive le.\n\n(*This fact asserts that the 'less than or equal to' relation defined on dependent pairs is antisymmetric, meaning if a first element is less than or equal to a second, and the second is also less than or equal to the first, then the two elements must be equal.*)\nFact anti : antisymmetric le.\n\n(*This fact asserts that the 'less than or equal to' relation defined on dependent pairs is transitive, meaning if a first element is less than or equal to a second, and the second is less than or equal to a third, then the first is less than or equal to the third.*)\nFact trans : transitive le.\n\n(*This fact provides an alternative definition for the 'strictly less than' relation on dependent pairs, stating that one element is strictly less than another if and only if it is less than or equal to the other, but the other is not less than or equal to it.*)\nFact lt_le_def x y : lt x y = le x y && ~~ le y x.\n\n#[export]\nHB.instance Definition _ :=\n isPreorder.Build disp2 {t : T & T' t} lt_le_def refl trans.\n#[export]\n(*This lemma provides an explicit characterization of the 'less than or equal to' relation for dependent pairs. It equates the standard relation with a formula that checks if the first component is less than or equal to the other's, and if they are equivalent, if the second component is less than or equal to the other's.*)\nLemma leEsig x y : x <= y =\n (tag x <= tag y) && ((tag x >= tag y) ==> (tagged x <= tagged_as x y)).\n\n(*This lemma provides an explicit characterization of the 'strictly less than' relation for dependent pairs. It equates the standard relation with a formula that checks if the first component is less than or equal to the other's, and if they are equivalent, if the second component is strictly less than the other's.*)\nLemma ltEsig x y : x < y =\n (tag x <= tag y) && ((tag x >= tag y) ==> (tagged x < tagged_as x y)).\n\n(*This lemma states that a dependent pair, constructed from a given value and sharing the same first component as another pair, is less than or equal to that other pair if and only if the given value is less than or equal to the second component of the other pair.*)\nLemma le_Taggedl x (u : T' (tag x)) : (Tagged T' u <= x) = (u <= tagged x).\n\n(*This lemma states that a dependent pair is less than or equal to another pair constructed from a given value, where both pairs share the same first component, if and only if the first pair's second component is less than or equal to the given value.*)\nLemma le_Taggedr x (u : T' (tag x)) : (x <= Tagged T' u) = (tagged x <= u).\n\n(*This lemma states that a dependent pair, constructed from a given value and sharing the same first component as another pair, is strictly less than that other pair if and only if the given value is strictly less than the second component of the other pair.*)\nLemma lt_Taggedl x (u : T' (tag x)) : (Tagged T' u < x) = (u < tagged x).\n\n(*This lemma states that a dependent pair is strictly less than another pair constructed from a given value, where both pairs share the same first component, if and only if the first pair's second component is strictly less than the given value.*)\nLemma lt_Taggedr x (u : T' (tag x)) : (x < Tagged T' u) = (tagged x < u).\n\nEnd POrder.\n\nSection BPOrder.\nContext (T : bPOrderType disp1) (T' : T -> bPOrderType disp2).\n\n(*This fact asserts that a dependent pair formed by the bottom element of the index type and the bottom element of the corresponding fiber type is the minimum element in the dependent product type, and is therefore less than or equal to any other element.*)\nFact le0x (x : {t : T & T' t}) : Tagged T' (\\bot : T' \\bot) <= x.\n\n#[export]\n(*This lemma identifies the bottom element of a dependent pair type. It states that this bottom element is the pair constructed from the bottom element of the first component's type and the bottom element of the second component's type, indexed by that first bottom element.*)\nLemma botEsig : \\bot = Tagged T' (\\bot : T' \\bot). \n\nEnd BPOrder.\n\nSection TPOrder.\nContext (T : tPOrderType disp1) (T' : T -> tPOrderType disp2).\n\n(*This fact asserts that a dependent pair formed by the top element of the index type and the top element of the corresponding fiber type is the maximum element in the dependent product type, and that any other element is therefore less than or equal to it.*)\nFact lex1 (x : {t : T & T' t}) : x <= Tagged T' (\\top : T' \\top).\n\n#[export]\n(*This lemma identifies the top element of a dependent pair type. It states that this top element is the pair constructed from the top element of the first component's type and the top element of the second component's type, indexed by that first top element.*)\nLemma topEsig : \\top = Tagged T' (\\top : T' \\top). \n\nEnd TPOrder.\n\nSection Total.\nContext (T : orderType disp1) (T' : T -> orderType disp2).\nImplicit Types (x y : {t : T & T' t}).\n\n(*This fact asserts that if the two component types of a dependent pair are both totally ordered, then the resulting lexicographic-like order on the dependent pair type is also total, meaning any two pairs can be compared.*)\nFact total : total (<=%O : rel {t : T & T' t}).\n\n#[export]\n(*This definition specifies the lexicographic less-than-or-equal relation for a dependent pair type. A pair is considered less than or equal to another if its first component is strictly less than the other's, or if their first components are equal and its second component is less than or equal to the other's.*)\nDefinition leEsig := @leEsig.\n(*This definition specifies the strict lexicographic less-than relation for a dependent pair type. A pair is considered strictly less than another if its first component is strictly less than the other's, or if their first components are equal and its second component is strictly less than the other's.*)\nDefinition ltEsig := @ltEsig.\n(*This definition specifies the left-to-right lexicographic less-than-or-equal relation on a tagged product type. A pair is considered less than or equal to another if its first component is strictly less than the other's, or if their first components are equal and its second component is less than or equal to the other's.*)\nDefinition le_Taggedl := @le_Taggedl.\n(*This definition specifies the strict left-to-right lexicographic less-than relation on a tagged product type. A pair is considered strictly less than another if its first component is strictly less than the other's, or if their first components are equal and its second component is strictly less than the other's.*)\nDefinition lt_Taggedl := @lt_Taggedl.\n(*This definition specifies the right-to-left lexicographic less-than-or-equal relation on a tagged product type. A pair is considered less than or equal to another if its second component is strictly less than the other's, or if their second components are equal and its first component is less than or equal to the other's.*)\nDefinition le_Taggedr := @le_Taggedr.\n(*This definition specifies the strict right-to-left lexicographic less-than relation on a tagged product type. A pair is considered strictly less than another if its second component is strictly less than the other's, or if their second components are equal and its first component is strictly less than the other's.*)\nDefinition lt_Taggedr := @lt_Taggedr.\n(*This definition specifies the greatest element, or top, for an ordered dependent pair type as the pair formed by the greatest element of the first component's type and the greatest element of the corresponding second component's type.*)\nDefinition topEsig := @topEsig.\n(*This definition specifies the least element, or bottom, for an ordered dependent pair type as the pair formed by the least element of the first component's type and the least element of the corresponding second component's type.*)\nDefinition botEsig := @botEsig.\nEnd Exports.\nEnd SigmaOrder.\nHB.export SigmaOrder.Exports.\n\nModule ProdLexiOrder.\n\nExport ProdLexiOrder.\n\nLocal Open Scope type_scope. \n\nSection POrder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : porderType disp1) (T2 : porderType disp2).\n\n(*This fact proves that the lexicographic order relation on the product of two partial order types is antisymmetric, meaning that if one pair is less than or equal to a second pair and the second pair is also less than or equal to the first, then the two pairs must be equal.*)\nFact anti : antisymmetric (@le disp1 disp2 disp2 T1 T2).\n\nEnd POrder.\n\nSection POrder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : porderType disp1) (T2 : porderType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\n(*This definition introduces an alias for the underlying type of the first of two given meet-semilattices.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := POrder.on T1'.\n(*This definition introduces an alias for the underlying type of the second of two given meet-semilattices.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := POrder.on T2'.\n\n#[export]\n(*A notation representing the product of two types, where the resulting product type is equipped with a specific order structure controlled by a display parameter.*)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\n\n(*This lemma states that the lexicographic order on the product of two totally ordered types is itself total, meaning any two pairs are comparable.*)\nFact total : total (<=%O : rel (T1 * T2)).\n\n#[export]\n(*This definition creates an alias for the type representing the lexicographic product of two ordered types. An element of this type is a pair, and pairs are compared by first comparing their first components, and only if they are equal, comparing their second components.*)\nLet prodlexi T1 T2 := T1 *lexi[lexi_display disp1 disp2] T2.\n\nHB.instance Definition _ (T1 : porderType disp1) (T2 : porderType disp2) :=\n POrder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _ (T1 : orderType disp1) (T2 : orderType disp2) :=\n Total.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _\n (T1 : finPOrderType disp1) (T2 : finPOrderType disp2) :=\n FinPOrder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _\n (T1 : finBPOrderType disp1) (T2 : finBPOrderType disp2) :=\n FinBPOrder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _\n (T1 : finTPOrderType disp1) (T2 : finTPOrderType disp2) :=\n FinTPOrder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _\n (T1 : finTBPOrderType disp1) (T2 : finTBPOrderType disp2) :=\n FinTBPOrder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _\n (T1 : finOrderType disp1) (T2 : finOrderType disp2) :=\n FinTotal.copy (T1 * T2)%type (prodlexi T1 T2).\n(*This notation defines a local alias for the underlying carrier type of a structure, which in this context is intended to represent a sequence type.*)\nLocal Notation seq := (type disp').\n\nSection POrder.\nVariable T : porderType disp.\nImplicit Types s : seq T.\n\n(*This lemma states that the pointwise order relation on sequences is antisymmetric, meaning if a first sequence is less than or equal to a second sequence and the second is also less than or equal to the first, then the two sequences must be identical.*)\nFact anti : antisymmetric (@le disp disp' T).\n\n#[export]\n(*This function computes the element-wise meet of two sequences. The resulting sequence contains the meet of corresponding elements from the input sequences, and its length is the minimum of the lengths of the two input sequences.*)\nFixpoint meet s1 s2 :=\n match s1, s2 with\n | x1 :: s1', x2 :: s2' => (x1 `&` x2) :: meet s1' s2'\n | _, _ => [::]\n end.\n\n(*This lemma states that a sequence is less than or equal to the element-wise meet of two other sequences if and only if it is less than or equal to each of those two sequences individually.*)\nFact lexI s1 s2 s3 : (s1 <= meet s2 s3) = (s1 <= s2) && (s1 <= s3).\n\n#[export]\n(*This lemma provides an alternative definition for the element-wise meet of two sequences, stating that the result is equivalent to the sequence formed by taking the meet of corresponding elements from the two input sequences, up to the length of the shorter sequence.*)\nLemma meetEseq s1 s2 : s1 `&` s2 = [seq x.1 `&` x.2 | x <- zip s1 s2].\n\n(*This lemma states that the element-wise meet of two non-empty sequences is a new sequence whose first element is the meet of the first elements of the input sequences and whose tail is the element-wise meet of their tails.*)\nLemma meet_cons x1 s1 x2 s2 :\n (x1 :: s1 : seq T) `&` (x2 :: s2) = (x1 `&` x2) :: s1 `&` s2.\n\nEnd MeetSemilattice.\n\nSection JoinSemilattice.\nContext (T : joinSemilatticeType disp).\nImplicit Types (s : seq T).\n\n(*This function computes the element-wise join of two sequences. For the common length of the sequences, the result contains the join of corresponding elements. If one sequence is longer than the other, the remaining elements of the longer sequence are appended to the result.*)\nFixpoint join s1 s2 :=\n match s1, s2 with\n | [::], _ => s2 | _, [::] => s1\n | x1 :: s1', x2 :: s2' => (x1 `|` x2) :: join s1' s2'\n end.\n\n(*This lemma states that the element-wise join of two sequences is less than or equal to a third sequence if and only if each of the two original sequences is less than or equal to the third sequence.*)\nFact leUx s1 s2 s3 : (join s1 s2 <= s3) = (s1 <= s3) && (s2 <= s3).\n\n#[export]\n(*This lemma provides an explicit case analysis for the element-wise join of two sequences, specifying that if either sequence is empty, the result is the other sequence, and otherwise, the result is constructed by joining the heads and recursively joining the tails.*)\nLemma joinEseq s1 s2 : s1 `|` s2 =\n match s1, s2 with\n | [::], _ => s2 | _, [::] => s1\n | x1 :: s1', x2 :: s2' => (x1 `|` x2) :: ((s1' : seq _) `|` s2')\n end.\n\n(*This lemma states that the element-wise join of two non-empty sequences is a new sequence whose first element is the join of the first elements of the input sequences and whose tail is the element-wise join of their tails.*)\nLemma join_cons x1 s1 x2 s2 :\n (x1 :: s1 : seq T) `|` (x2 :: s2) = (x1 `|` x2) :: s1 `|` s2.\n\nEnd JoinSemilattice.\n\n#[export]\n(*This lemma states that the element-wise meet operation on sequences is left-distributive over the element-wise join operation on sequences.*)\nFact meetUl : left_distributive (@meet T) (@join T).\n\n#[export]\n(*This definition states that a finite sequence is the meet (greatest lower bound) of two other finite sequences under the product order if and only if all three sequences have the same length, and each element of the resulting sequence is the meet of the elements at the corresponding positions in the two input sequences.*)\nDefinition meetEseq := @meetEseq.\n(*This definition specifies that the meet (greatest lower bound) of two non-empty finite sequences under the product order is a new sequence where the head is the meet of the original heads, and the tail is the meet of the original tails.*)\nDefinition meet_cons := @meet_cons.\n(*This definition states that a finite sequence is the join (least upper bound) of two other finite sequences under the product order if and only if all three sequences have the same length, and each element of the resulting sequence is the join of the elements at the corresponding positions in the two input sequences.*)\nDefinition joinEseq := @joinEseq.\n\nEnd Exports.\nEnd SeqProdOrder.\nHB.export SeqProdOrder.Exports.\n\nModule DefaultSeqProdOrder.\n\nExport DefaultSeqProdOrder.\n\nSection DefaultSeqProdOrder.\nContext {disp : disp_t}.\n\nHB.instance Definition _ (T : porderType disp) :=\n POrder.copy (seq T) (seqprod T).\nHB.instance Definition _ (T : meetSemilatticeType disp) :=\n BMeetSemilattice.copy (seq T) (seqprod T).\nHB.instance Definition _ (T : joinSemilatticeType disp) :=\n BJoinSemilattice.copy (seq T) (seqprod T).\nHB.instance Definition _ (T : latticeType disp) :=\n BLattice.copy (seq T) (seqprod T).\n(*A local notation for the type of finite sequences whose elements are drawn from a given ordered type.*)\nLocal Notation seq := (type disp').\n\nSection POrder.\nVariable T : porderType disp.\nImplicit Types s : seq T.\n\n(*This fact states that the lexicographic order relation on finite sequences is antisymmetric. This means that if a first finite sequence is less than or equal to a second finite sequence, and the second is also less than or equal to the first, then the two sequences must be identical.*)\nFact anti: antisymmetric (@le disp disp' T).\n\n#[export]\n(*This lemma states that for two non-empty finite sequences with distinct head elements, the first sequence is lexicographically less than or equal to the second if and only if the head of the first sequence is strictly less than the head of the second sequence.*)\nLemma neqhead_lexiE (x y : T) s1 s2 : x != y ->\n (x :: s1 <= y :: s2 :> seq _) = (x < y).\n\n(*This lemma states that for two non-empty finite sequences with distinct head elements, the first sequence is strictly lexicographically less than the second if and only if the head of the first sequence is strictly less than the head of the second sequence.*)\nLemma neqhead_ltxiE (x y : T) s1 s2 : x != y ->\n (x :: s1 < y :: s2 :> seq _) = (x < y).\n\nEnd POrder.\n\nSection Total.\nContext (T : orderType disp).\n\n(*This fact states that the lexicographic order relation on finite sequences is total, provided the elements of the sequences are drawn from a totally ordered type. This means that for any two finite sequences, either the first is less than or equal to the second, or the second is less than or equal to the first.*)\nFact total : total (<=%O : rel (seq T)).\n\n#[export]\n(*This lemma states that for two non-empty sequences with differing first elements, their lexicographical less-than-or-equal-to comparison is equivalent to the less-than-or-equal-to comparison of their first elements.*)\nDefinition neqhead_lexiE := @neqhead_lexiE.\n(*This definition provides an alias for a lemma asserting that for two non-empty sequences with differing first elements, their strict lexicographical less-than comparison is equivalent to the strict less-than comparison of their first elements.*)\nDefinition neqhead_ltxiE := @neqhead_ltxiE.\n\nEnd Exports.\nEnd SeqLexiOrder.\nHB.export SeqLexiOrder.Exports.\n\nModule DefaultSeqLexiOrder.\n\nExport DefaultSeqLexiOrder.\n\nSection DefaultSeqLexiOrder.\nContext {disp : disp_t}.\n\nHB.instance Definition _ (T : porderType disp) :=\n POrder.copy (seq T) (seqlexi T).\n(**)\nLocal Notation \"n .-tuple\" := (type disp' n) : type_scope.\n\nSection POrder.\nImplicit Types (T : porderType disp).\n\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ n T := SubChoice.on (n.-tuple T).\n#[export]\n(*This definition specifies the meet operation on two tuples of the same length, resulting in a new tuple where each element is the meet of the corresponding elements from the input tuples.*)\nDefinition meet t1 t2 : n.-tuple T := [tuple tnth t1 i `&` tnth t2 i | i < n].\n\n(*This lemma establishes a fundamental property of the meet operation on tuples, stating that a tuple is less than or equal to the meet of two other tuples if and only if it is less than or equal to each of those two tuples individually.*)\nFact lexI t1 t2 t3 : (t1 <= meet t2 t3) = (t1 <= t2) && (t1 <= t3).\n\n#[export]\n(*This lemma states that the i-th element of the meet of two tuples is equal to the meet of the i-th elements of each tuple.*)\nLemma tnth_meet t1 t2 i : tnth (t1 `&` t2) i = tnth t1 i `&` tnth t2 i.\n\n(*This lemma provides an equational view of the meet operation on tuples, stating that the meet of two tuples is a new tuple constructed by taking the meet of their corresponding elements.*)\nLemma meetEtprod t1 t2 : t1 `&` t2 = [tuple tnth t1 i `&` tnth t2 i | i < n].\n\nEnd MeetSemilattice.\n\nSection JoinSemilattice.\nContext (n : nat) (T : joinSemilatticeType disp).\nImplicit Types (t : n.-tuple T).\n\n(*This definition specifies the join operation on two tuples of the same length, resulting in a new tuple where each element is the join of the corresponding elements from the input tuples.*)\nDefinition join t1 t2 : n.-tuple T := [tuple tnth t1 i `|` tnth t2 i | i < n].\n\n(*This lemma states that a tuple is an upper bound for the join of two other tuples if and only if it is an upper bound for each of these two tuples individually.*)\nFact leUx t1 t2 t3 : (join t1 t2 <= t3) = (t1 <= t3) && (t2 <= t3).\n\n#[export]\n(*This lemma states that the i-th element of the join of two tuples is equal to the join of the i-th elements of each tuple.*)\nLemma tnth_join t1 t2 i : tnth (t1 `|` t2) i = tnth t1 i `|` tnth t2 i.\n\n(*This lemma provides an equational view of the join operation on tuples, stating that the join of two tuples is a new tuple constructed by taking the join of their corresponding elements.*)\nLemma joinEtprod t1 t2 : t1 `|` t2 = [tuple tnth t1 i `|` tnth t2 i | i < n].\n\nEnd JoinSemilattice.\n\n#[export]\nHB.instance Definition _ (n : nat) (T : bMeetSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tMeetSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tbMeetSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : bJoinSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tJoinSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tbJoinSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : latticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : bLatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tLatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tbLatticeType disp) :=\n POrder.on (n.-tuple T).\n\nSection DistrLattice.\nContext (n : nat) (T : distrLatticeType disp).\nImplicit Types (t : n.-tuple T).\n\n(*This lemma asserts that for tuples, the meet operation is left-distributive over the join operation.*)\nFact meetUl : left_distributive (@meet n T) (@join n T).\n\n#[export]\n(*This definition specifies the relative complement operation on three tuples of the same length, producing a new tuple where each element is the relative complement of the corresponding elements from the input tuples.*)\nDefinition rcompl t1 t2 t3 :=\n [tuple rcompl (tnth t1 i) (tnth t2 i) (tnth t3 i) | i < n].\n\n(*This lemma asserts a property of the relative complement in a product of two complemented distributive lattices. It states that if one takes the meet of two elements, joins the result with a third element, and then takes the meet of that with the relative complement of all three original elements, the final result is simply the meet of the first two elements.*)\nFact rcomplPmeet x y z : ((x `&` y) `|` z) `&` rcompl x y z = x `&` y.\n\n(*This lemma gives another property of the relative complement construction: for any three elements, the join of the meet of the third element and the join of the first two, with their relative complement, simplifies to the join of the first two elements.*)\nFact rcomplPjoin x y z : ((y `|` x) `&` z) `|` rcompl x y z = y `|` x.\n\n#[export]\n(*This lemma asserts that the i-th element of the relative complement of three tuples is equal to the relative complement of their respective i-th elements.*)\nLemma tnth_rcompl t1 t2 t3 i :\n tnth (Order.rcompl t1 t2 t3) i =\n Order.rcompl (tnth t1 i) (tnth t2 i) (tnth t3 i).\n\n(*This lemma provides an equational view of the relative complement operation, stating that the relative complement of three tuples is a new tuple constructed by applying the relative complement operation pointwise to their corresponding elements.*)\nLemma rcomplEtprod t1 t2 t3 :\n Order.rcompl t1 t2 t3 =\n [tuple Order.rcompl (tnth t1 i) (tnth t2 i) (tnth t3 i) | i < n].\n\nEnd CDistrLattice.\n\nSection CBDistrLattice.\nContext (n : nat) (T : cbDistrLatticeType disp).\nImplicit Types (t : n.-tuple T).\n\n(*This definition specifies the difference operation on two tuples of the same length, producing a new tuple where each element is the difference of the corresponding elements from the input tuples.*)\nDefinition diff t1 t2 : n.-tuple T := [tuple tnth t1 i `\\` tnth t2 i | i < n].\n\n(*This lemma states that the difference of two tuples is equivalent to a specific instance of the relative complement operation, applied to the bottom element, the first tuple, and the second tuple.*)\nFact diffErcompl t1 t2 : diff t1 t2 = rcompl \\bot t1 t2.\n\n(*This lemma states that the i-th element of the difference of two tuples is equal to the difference of their respective i-th elements.*)\nLemma tnth_diff t1 t2 i : tnth (diff t1 t2) i = tnth t1 i `\\` tnth t2 i.\n\n(*This lemma provides an equational view of the difference operation, stating that the difference of two tuples is a new tuple constructed by taking the difference of their corresponding elements.*)\nLemma diffEtprod t1 t2 : t1 `\\` t2 = [tuple tnth t1 i `\\` tnth t2 i | i < n].\n\nEnd CBDistrLattice.\n\nSection CTDistrLattice.\nContext (n : nat) (T : ctDistrLatticeType disp).\nImplicit Types (t : n.-tuple T).\n\n(*This definition specifies the co-difference operation on two tuples of the same length, producing a new tuple where each element is the co-difference of the corresponding elements from the input tuples.*)\nDefinition codiff t1 t2 : n.-tuple T :=\n [tuple Order.codiff (tnth t1 i) (tnth t2 i) | i < n].\n\n(*This lemma states that the co-difference of two tuples is equivalent to a specific instance of the relative complement operation, applied to the first tuple, the top element, and the second tuple.*)\nFact codiffErcompl t1 t2 : codiff t1 t2 = rcompl t1 \\top t2.\n\n(*This lemma states that the i-th element of the co-difference of two tuples is equal to the co-difference of their respective i-th elements.*)\nLemma tnth_codiff t1 t2 i :\n tnth (Order.codiff t1 t2) i = Order.codiff (tnth t1 i) (tnth t2 i).\n\n(*This lemma provides an equational view of the co-difference operation, stating that the co-difference of two tuples is a new tuple constructed by taking the co-difference of their corresponding elements.*)\nLemma codiffEtprod t1 t2 :\n Order.codiff t1 t2 = [tuple Order.codiff (tnth t1 i) (tnth t2 i) | i < n].\n\nEnd CTDistrLattice.\n\nSection CTBDistrLattice.\nContext (n : nat) (T : ctbDistrLatticeType disp).\nImplicit Types (t : n.-tuple T).\n\n(*This definition specifies the complement operation on a tuple, which produces a new tuple by applying the complement operation to each of its elements.*)\nDefinition compl t : n.-tuple T := map_tuple compl t.\n\n(*This lemma states that the complement of a tuple is equivalent to the difference between the top tuple and the given tuple.*)\nFact complEdiff t : compl t = (\\top : n.-tuple T) `\\` t.\n\n(*This lemma states that the complement of a tuple is equivalent to the co-difference between the bottom tuple and the given tuple.*)\nFact complEcodiff t : compl t = codiff (\\bot : n.-tuple T) t.\n\n(*This lemma states that the i-th element of the complement of a tuple is equal to the complement of the tuple's i-th element.*)\nLemma tnth_compl t i : tnth (~` t) i = ~` tnth t i.\n\n(*This lemma provides an equational view of the complement operation, stating that the complement of a tuple is obtained by applying the complement function to each of its elements.*)\nLemma complEtprod t : ~` t = map_tuple Order.compl t.\n\nEnd CTBDistrLattice.\n\n#[export]\nHB.instance Definition _ (n : nat) (T : finPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finBPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finTPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finTBPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finMeetSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finBMeetSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finJoinSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finTJoinSemilatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finLatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finTBLatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finDistrLatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finTBDistrLatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finCDistrLatticeType disp) :=\n POrder.on (n.-tuple T).\n#[export]\n(*This lemma states that the component at a given index of the meet of two tuples under the product order is equal to the meet of the components from the two original tuples at that same index.*)\nDefinition tnth_meet := @tnth_meet.\n(*This lemma states that the meet of two tuples under the product order is a new tuple where each component is the meet of the corresponding components from the original tuples.*)\nDefinition meetEtprod := @meetEtprod.\n(*This lemma states that the component at a given index of the join of two tuples under the product order is equal to the join of the components from the two original tuples at that same index.*)\nDefinition tnth_join := @tnth_join.\n(*This lemma states that the join of two tuples under the product order is a new tuple where each component is the join of the corresponding components from the original tuples.*)\nDefinition joinEtprod := @joinEtprod.\n(*This lemma states that the component at a given index of the relative complement of two tuples is equal to the relative complement of the components of the two tuples at that same index.*)\nDefinition tnth_rcompl := @tnth_rcompl.\n(*This lemma states that the relative complement of two tuples is a new tuple where each component is the relative complement of the corresponding components from the original tuples.*)\nDefinition rcomplEtprod := @rcomplEtprod.\n(*This lemma states that the component at a given index of the lattice difference of two tuples is equal to the lattice difference of the components of the two tuples at that same index.*)\nDefinition tnth_diff := @tnth_diff.\n(*This lemma states that the lattice difference of two tuples is a new tuple where each component is the lattice difference of the corresponding components from the original tuples.*)\nDefinition diffEtprod := @diffEtprod.\n(*This lemma states that the component at a given index of the lattice co-difference of two tuples is equal to the lattice co-difference of the components of the two tuples at that same index.*)\nDefinition tnth_codiff := @tnth_codiff.\n(*This lemma states that the lattice co-difference of two tuples is a new tuple where each component is the lattice co-difference of the corresponding components from the original tuples.*)\nDefinition codiffEtprod := @codiffEtprod.\n(*This lemma states that the component at a given index of the complement of a tuple is equal to the complement of the component of the tuple at that same index.*)\nDefinition tnth_compl := @tnth_compl.\n(*This lemma states that the complement of a tuple is a new tuple where each component is the complement of the corresponding component from the original tuple.*)\nDefinition complEtprod := @complEtprod.\n\nEnd Exports.\nEnd TupleProdOrder.\nHB.export TupleProdOrder.Exports.\n\nModule DefaultTupleProdOrder.\n\nExport DefaultTupleProdOrder.\n\nSection DefaultTupleProdOrder.\nContext {disp : disp_t}.\n\nHB.instance Definition _ n (T : porderType disp) :=\n POrder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : bPOrderType disp) :=\n BPOrder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tPOrderType disp) :=\n TPOrder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tbPOrderType disp) :=\n TBPOrder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : meetSemilatticeType disp) :=\n MeetSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : bMeetSemilatticeType disp) :=\n BMeetSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tMeetSemilatticeType disp) :=\n TMeetSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tbMeetSemilatticeType disp) :=\n TBMeetSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : joinSemilatticeType disp) :=\n JoinSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : bJoinSemilatticeType disp) :=\n BJoinSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tJoinSemilatticeType disp) :=\n TJoinSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tbJoinSemilatticeType disp) :=\n TBJoinSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : latticeType disp) :=\n Lattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : bLatticeType disp) :=\n BLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tLatticeType disp) :=\n TLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tbLatticeType disp) :=\n TBLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : distrLatticeType disp) :=\n DistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : bDistrLatticeType disp) :=\n BDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tDistrLatticeType disp) :=\n TDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tbDistrLatticeType disp) :=\n TBDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : cDistrLatticeType disp) :=\n CDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : cbDistrLatticeType disp) :=\n CBDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : ctDistrLatticeType disp) :=\n CTDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : ctbDistrLatticeType disp) :=\n CTBDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finPOrderType disp) :=\n FinPOrder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finBPOrderType disp) :=\n FinBPOrder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finTPOrderType disp) :=\n FinTPOrder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finTBPOrderType disp) :=\n FinTBPOrder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finMeetSemilatticeType disp) :=\n FinMeetSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finBMeetSemilatticeType disp) :=\n FinBMeetSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finJoinSemilatticeType disp) :=\n FinJoinSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finTJoinSemilatticeType disp) :=\n FinTJoinSemilattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finLatticeType disp) :=\n FinLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finTBLatticeType disp) :=\n FinTBLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finDistrLatticeType disp) :=\n FinDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finTBDistrLatticeType disp) :=\n FinTBDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : finCDistrLatticeType disp) :=\n FinCDistrLattice.copy (n.-tuple T) (n.-tupleprod T).\n(*A notation representing the type of fixed-length sequences, also known as tuples, of a given length. It is used with a natural number specifying the length and an element type to construct the type of tuples intended to be equipped with a lexicographic order.*)\nLocal Notation \"n .-tuple\" := (type disp' n) : type_scope.\n\nSection POrder.\nImplicit Types (n : nat) (T : porderType disp).\n\n(*This lemma provides a characterization of the non-strict lexicographical order relation between two tuples. It asserts that one tuple is less than or equal to another if and only if there exists an index `k` (from zero to the tuple length) such that for all indices `i` up to `k` (and less than the tuple length), the component-wise less-than-or-equal relation holds if and only if `i` is not equal to `k`.*)\nLemma lexi_tupleP n T (t1 t2 : n.-tuple T) :\n reflect (exists k : 'I_n.+1, forall i : 'I_n, (i <= k)%N ->\n tnth t1 i <= tnth t2 i ?= iff (i != k :> nat)) (t1 <= t2).\n\n(*This lemma provides a characterization of the strict lexicographical order relation between two tuples. It asserts that one tuple is strictly less than another if and only if there exists an index `k` within the tuple bounds, such that for all indices `i` up to `k`, the component-wise less-than-or-equal relation holds if and only if `i` is not equal to `k`.*)\nLemma ltxi_tupleP n T (t1 t2 : n.-tuple T) :\n reflect (exists k : 'I_n, forall i : 'I_n, (i <= k)%N ->\n tnth t1 i <= tnth t2 i ?= iff (i != k :> nat)) (t1 < t2).\n\n(*This lemma provides a characterization for the strict lexicographical less-than comparison on two tuples. It states that one tuple is strictly less than another if and only if there exists an index where the first tuple's component is strictly less than the second's, while all preceding components are equal.*)\nLemma ltxi_tuplePlt n T (t1 t2 : n.-tuple T) : reflect\n (exists2 k : 'I_n, forall i : 'I_n, (i < k)%N -> tnth t1 i = tnth t2 i\n & tnth t1 k < tnth t2 k)\n (t1 < t2).\n\nEnd POrder.\n\n#[export] HB.instance Definition _ n (T : orderType disp) :=\n [SubChoice_isSubOrder of n.-tuple T by <: with disp'].\n\n#[export]\nHB.instance Definition _ (n : nat) (T : bPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tbPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : bOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : tbOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finBPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finTPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finTBPOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finOrderType disp) :=\n POrder.on (n.-tuple T).\n#[export]\n(*This definition provides a boolean reflection for the lexicographical less-than-or-equal comparison on tuples. It states that the lexicographical relation holds between two tuples of the same length if and only if a corresponding boolean function evaluates to true.*)\nDefinition lexi_tupleP := @lexi_tupleP.\nArguments lexi_tupleP {disp disp' n T t1 t2}.\n(*This definition provides a boolean reflection for the strict lexicographical less-than comparison on tuples. It states that one tuple is strictly lexicographically less than another of the same length if and only if a corresponding boolean function evaluates to true.*)\nDefinition ltxi_tupleP := @ltxi_tupleP.\nArguments ltxi_tupleP {disp disp' n T t1 t2}.\n(*This lemma states that the boolean predicate for strict lexicographical less-than on tuples is equivalent to the propositional strict less-than relation on those tuples. In other words, the boolean predicate is true if and only if the first tuple is strictly lexicographically smaller than the second.*)\nDefinition ltxi_tuplePlt := @ltxi_tuplePlt.\nArguments ltxi_tuplePlt {disp disp' n T t1 t2}.\n\nEnd Exports.\nEnd TupleLexiOrder.\nHB.export TupleLexiOrder.Exports.\n\nModule DefaultTupleLexiOrder.\n\nExport DefaultTupleLexiOrder.\n\nSection DefaultTupleLexiOrder.\nContext {disp : disp_t}.\n\nHB.instance Definition _ n (T : porderType disp) :=\n POrder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : bPOrderType disp) :=\n BPOrder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : tPOrderType disp) :=\n TPOrder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : tbPOrderType disp) :=\n TBPOrder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : orderType disp) :=\n Lattice.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : orderType disp) :=\n DistrLattice.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : orderType disp) :=\n Total.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : bOrderType disp) :=\n BTotal.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : tOrderType disp) :=\n TTotal.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : tbOrderType disp) :=\n TBTotal.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : finPOrderType disp) :=\n FinPOrder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : finBPOrderType disp) :=\n FinBPOrder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : finTPOrderType disp) :=\n FinTPOrder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : finTBPOrderType disp) :=\n FinTBPOrder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : finOrderType disp) :=\n FinTotal.copy (n.-tuple T) (n.-tuplelexi T).\n(*This notation defines an alias for the type of finite sets over a given finite base type, indicating that these sets are to be considered with the subset inclusion relation as their order.*)\nLocal Notation \"{ 'subset' T }\" := (type disp T).\nImplicit Type (A B C : type disp T).\n\n(*This lemma states the absorption law for sets, asserting that the intersection of a set with the union of itself and another set is equal to the original set.*)\nLemma setKUC B A : A :&: (A :|: B) = A.\n\n(*This lemma states the absorption law for sets, asserting that the union of a set with the intersection of itself and another set is equal to the original set.*)\nLemma setKIC B A : A :|: (A :&: B) = A.\n\n(*This fact asserts that the subset relation is antisymmetric, meaning that if a first set is a subset of a second set, and the second set is also a subset of the first, then the two sets must be equal.*)\nFact le_anti : antisymmetric (fun A B => A \\subset B).\n\n#[export]\nHB.instance Definition _ := Preorder_isPOrder.Build disp {subset T} le_anti.\n#[export]\nHB.instance Definition _ := POrder_Meet_isDistrLattice.Build disp {subset T}\n (@setIC _) (@setUC _) (@setIA _) (@setUA _) setKUC setKIC le_def (@setIUl _).\n\n(*This lemma states that the intersection of a second set with the set difference of a first set and the second set is always the empty set.*)\nLemma setIDv A B : B :&: (A :\\: B) = set0.\n\n#[export]\nHB.instance Definition _ :=\n @BDistrLattice_hasSectionalComplement.Build disp {subset T}\n (@setD _) setIDv (@setID _).\n\n(*This lemma states that the complement of a set is equivalent to the set difference between the universal set and the given set.*)\nLemma setTDsym A : ~: A = setT :\\: A.\n\n#[export]\n(*This lemma states that the generic meet operation on two sets, when ordered by the subset relation, is equivalent to the set intersection of those two sets.*)\nLemma meetEsubset A B : A `&` B = A :&: B.\n\n(*This lemma states that the generic join operation on two sets, when ordered by the subset relation, is equivalent to the set union of those two sets.*)\nLemma joinEsubset A B : A `|` B = A :|: B.\n\n(*This lemma states that the generic bottom element in the context of sets ordered by the subset relation is equivalent to the empty set.*)\nLemma botEsubset : \\bot = set0 :> {subset T}.\n\n(*This lemma states that the generic top element in the context of sets ordered by the subset relation is equivalent to the universal set, which contains all elements of the base type.*)\nLemma topEsubset : \\top = setT :> {subset T}.\n\n(*This lemma states that the generic sectional complement operation on two sets, within the lattice of sets ordered by inclusion, corresponds to the set difference between those two sets.*)\nLemma subEsubset A B : A `\\` B = A :\\: B.\n\n(*This lemma states that the generic complement operation on a set, within the boolean algebra of sets ordered by inclusion, is equivalent to the standard set-theoretic complement of that set.*)\nLemma complEsubset A : ~` A = ~: A.\n\nEnd SetSubsetOrder.\n\nModule Exports.\n\nHB.reexport.\n\n(*This definition provides an alias for the lemma stating that the meet operation on sets, when ordered by inclusion, is equivalent to set intersection.*)\nDefinition meetEsubset := @meetEsubset.\n(*This definition provides an alias for the lemma stating that the join operation on sets, when ordered by inclusion, is equivalent to set union.*)\nDefinition joinEsubset := @joinEsubset.\n(*This definition provides an alias for the lemma stating that the bottom element in the lattice of subsets ordered by inclusion is the empty set.*)\nDefinition botEsubset := @botEsubset.\n(*This definition provides an alias for the lemma stating that the top element in the lattice of subsets of a finite type, when ordered by inclusion, is the universal set containing all elements of that type.*)\nDefinition topEsubset := @topEsubset.\n(*This definition provides an alias for the lemma stating that the 'less than or equal to' relation in the lattice of subsets corresponds to the standard subset inclusion relation.*)\nDefinition subEsubset := @subEsubset.\n(*This definition provides an alias for the lemma stating that the complement operation in the lattice of subsets corresponds to the set-theoretic complement with respect to the universal set.*)\nDefinition complEsubset := @complEsubset.\n\nEnd Exports.\nEnd SetSubsetOrder.\nExport SetSubsetOrder.Exports.\n\nModule DefaultSetSubsetOrder.\n\nExport DefaultSetSubsetOrder.\n\n(*This lemma states that for any two monotonic functions between two finite ordered types, if the domain is totally ordered and its cardinality is greater than or equal to the cardinality of the codomain, then the two functions must be identical.*)\nLemma mono_unique d (T T' : finPOrderType d) (f g : T -> T') :\n total (<=%O : rel T) -> (#|T'| <= #|T|)%N ->\n {mono f : x y / x <= y} -> {mono g : x y / x <= y} ->\n f =1 g.\n\nModule Import EnumVal.\n\nExport EnumVal.\n\nSection EnumVal.\nImport OrdinalOrder.Exports.\nVariables (d : disp_t) (T : finPOrderType d).\nImplicit Types (x : T) (A : {pred T}).\n\nSection total.\n\nHypothesis (leT_total : total (<=%O : rel T)).\n\n(*This lemma states that for a totally ordered finite type, the function that retrieves an element from a given subset using its ordinal rank is monotonic. This means that if one rank is less than or equal to another, the element corresponding to the first rank is less than or equal to the element corresponding to the second rank.*)\nLemma le_enum_val A : {mono @enum_val _ _ A : i j / i <= j}.\n\n(*This lemma states that for a totally ordered finite type, the function that computes the ordinal rank of an element within a given subset is monotonic for all elements within that subset. This means that for any two elements in the subset, if the first is less than or equal to the second, the rank of the first will be less than or equal to the rank of the second.*)\nLemma le_enum_rank_in x0 A (Ax0 : x0 \\in A) :\n {in A &, {mono enum_rank_in Ax0 : x y / x <= y}}.\n\n(*This lemma states that for a totally ordered finite type, the function which computes the ordinal rank of an element is monotonic. This means that if one element is less than or equal to another, the rank of the first element will be less than or equal to the rank of the second element.*)\nLemma le_enum_rank : {mono @enum_rank d T : i j / i <= j}.\n\nEnd total.\nEnd EnumVal.\nEnd EnumVal.\n\n(*This lemma states that the function mapping an ordinal rank to its corresponding element in a finite ordered type is monotonic. Specifically, if a first rank is less than or equal to a second rank, then the element corresponding to the first rank is less than or equal to the element corresponding to the second rank.*)\nNotation le_enum_val := le_enum_val.\n(*This notation is a shorthand for a lemma used to prove that the 'enum_rank' function preserves the less-than-or-equal relation. It asserts that if a first element is less than or equal to a second element in a finite ordered type, then the ordinal rank of the first element is less than or equal to the ordinal rank of the second.*)\nNotation le_enum_rank_in := le_enum_rank_in.\n(*This notation represents a lemma asserting that the function which computes the ordinal rank of an element in a finite ordered type is monotonic. This means that for any two elements, if one is less than or equal to the other, its rank will also be less than or equal to the other's rank.*)\nNotation le_enum_rank := le_enum_rank.\n\nModule Syntax.\nExport PreOSyntax.\nExport DualSyntax.\nExport DvdSyntax.\nExport LatticeSyntax.\nExport BLatticeSyntax.\nExport TLatticeSyntax.\nExport CBDistrLatticeSyntax.\nExport CTBDistrLatticeSyntax.\nExport DualSyntax.\nExport DvdSyntax.\nEnd Syntax.\n\nModule LTheory.\nExport PreorderTheory.\nExport BPreorderTheory.\nExport TPreorderTheory.\nExport DualPreorder. \nExport PreOCoercions.\nExport PreorderTheory.\nExport POrderTheory.\nExport BPOrderTheory.\nExport TPOrderTheory.\nExport MeetTheory.\nExport BMeetTheory.\nExport TMeetTheory.\nExport JoinTheory.\nExport BJoinTheory.\nExport TJoinTheory.\nExport LatticeTheory.\nExport DistrLatticeTheory.\nExport BDistrLatticeTheory.\nExport TDistrLatticeTheory.\nExport DualTotalTheory. \nExport DualOrder. \n\nExport OrderMorphismTheory.\nExport LatticeMorphismTheory.\nExport BLatticeMorphismTheory.\nExport TLatticeMorphismTheory.\n\nExport ClosedPredicates.\nExport LatticePred.\n\nExport SubPreorderTheory.\nEnd LTheory.\n\nModule CTheory.\nExport LTheory.\nExport CDistrLatticeTheory.\nExport CBDistrLatticeTheory.\nExport CTDistrLatticeTheory.\nExport CTBDistrLatticeTheory.\nEnd CTheory.\n\nModule TTheory.\nExport LTheory TotalTheory.\nEnd TTheory.\n\nModule Theory.\nExport CTheory TotalTheory.\nEnd Theory.\n\nModule Exports.\nHB.reexport.\nEnd Exports.\nEnd Order.\n\nExport Order.Exports.\n\nExport Order.Syntax.\n\nExport order.Order.Exports.\nExport Order.POrder.Exports.\nExport Order.BPOrder.Exports.\nExport Order.TPOrder.Exports.\nExport Order.TBPOrder.Exports.\nExport Order.MeetSemilattice.Exports.\nExport Order.BMeetSemilattice.Exports.\nExport Order.TMeetSemilattice.Exports.\nExport Order.TBMeetSemilattice.Exports.\nExport Order.JoinSemilattice.Exports.\nExport Order.BJoinSemilattice.Exports.\nExport Order.TJoinSemilattice.Exports.\nExport Order.TBJoinSemilattice.Exports.\nExport Order.Lattice.Exports.\nExport Order.BLattice.Exports.\nExport Order.TLattice.Exports.\nExport Order.TBLattice.Exports.\nExport Order.DistrLattice.Exports.\nExport Order.BDistrLattice.Exports.\nExport Order.TDistrLattice.Exports.\nExport Order.TBDistrLattice.Exports.\nExport Order.Total.Exports.\nExport Order.BTotal.Exports.\nExport Order.TTotal.Exports.\nExport Order.TBTotal.Exports.\nExport Order.CDistrLattice.Exports.\nExport Order.CBDistrLattice.Exports.\nExport Order.CTDistrLattice.Exports.\nExport Order.CTBDistrLattice.Exports.\nExport Order.FinPOrder.Exports.\nExport Order.FinBPOrder.Exports.\nExport Order.FinTPOrder.Exports.\nExport Order.FinTBPOrder.Exports.\nExport Order.FinMeetSemilattice.Exports.\nExport Order.FinBMeetSemilattice.Exports.\nExport Order.FinJoinSemilattice.Exports.\nExport Order.FinTJoinSemilattice.Exports.\nExport Order.FinLattice.Exports.\nExport Order.FinTBLattice.Exports.\nExport Order.FinDistrLattice.Exports.\nExport Order.FinTBDistrLattice.Exports.\nExport Order.FinTotal.Exports.\nExport Order.FinTBTotal.Exports.\nExport Order.FinCDistrLattice.Exports.\nExport Order.FinCTBDistrLattice.Exports.\n\nModule DefaultProdOrder := Order.DefaultProdOrder.\nModule DefaultSeqProdOrder := Order.DefaultSeqProdOrder.\nModule DefaultTupleProdOrder := Order.DefaultTupleProdOrder.\nModule DefaultProdLexiOrder := Order.DefaultProdLexiOrder.\nModule DefaultSeqLexiOrder := Order.DefaultSeqLexiOrder.\nModule DefaultTupleLexiOrder := Order.DefaultTupleLexiOrder.\n\nImport Order.Theory.\n\nModule tagnat.\nSection tagnat.\nImport Order.EnumVal.\n\nContext {n : nat} {p_ : 'I_n -> nat}.\n\n(*This notation defines an ordinal type whose cardinality is the sum of a sequence of natural numbers that represent the sizes of a family of types.*)\nLocal Notation ordsum := 'I_(\\sum_i p_ i)%N.\n(*This notation defines a dependent pair type representing the disjoint union of a family of finite types. An element of this type consists of a pair containing an index and an element from the finite type corresponding to that index.*)\nLocal Notation T := {i & 'I_(p_ i)}.\n\nImplicit Types (i : 'I_n) (s : ordsum) (p : T).\n\n(*This lemma states that the cardinality of the dependent sum type is equal to the sum of the cardinalities of the individual types that form the disjoint union.*)\nLemma card : #|{: T}| = \\sum_i p_ i.\n\n(*This definition introduces a function that converts a single ordinal from a flattened enumeration into its structured representation as a dependent pair, effectively identifying which component type the element belongs to and its position within that type.*)\nDefinition sig : ordsum -> T := enum_val \\o cast_ord (esym card).\n(*This definition introduces a function that converts a dependent pair from a structured disjoint union into a single ordinal rank, effectively flattening the structure into a linear enumeration.*)\nDefinition rank : T -> ordsum := cast_ord card \\o enum_rank.\n\n(*This lemma states that the 'sig' function is a left inverse of the 'rank' function. Applying 'rank' and then 'sig' to a structured pair returns the original pair.*)\nLemma sigK : cancel sig rank.\n\n(*This lemma states that the 'sig' function, which maps a flattened index to a structured pair, is injective, meaning distinct indices map to distinct pairs.*)\nLemma sig_inj : injective sig. \n\n(*This lemma states that the 'rank' function is a left inverse of the 'sig' function. Applying 'sig' and then 'rank' to a flattened index returns the original index.*)\nLemma rankK : cancel rank sig.\n\n(*This lemma states that the 'rank' function, which maps a structured pair to a flattened index, is injective, meaning distinct pairs map to distinct indices.*)\nLemma rank_inj : injective rank. \n\n(*This definition introduces a function that extracts the first component from the structured pair that results from applying the 'sig' function to a flattened index. This component identifies which type in the family the element belongs to.*)\nDefinition sig1 s : 'I_n := tag (sig s).\n(*This definition introduces a function that extracts the second component from the structured pair that results from applying the 'sig' function to a flattened index. This component identifies the element's position within its specific type.*)\nDefinition sig2 s : 'I_(p_ (sig1 s)) := tagged (sig s).\n(*This definition provides a curried version of the 'rank' function. It takes two arguments, an index for a type and an element within that type, and computes the corresponding single flattened numerical rank.*)\nDefinition Rank i (j : 'I_(p_ i)) := rank (Tagged _ j).\n\n(*This lemma provides an equational property of the 'sig' function, stating that applying 'sig' to a flattened index yields the same structured pair as constructing a pair from the results of the 'sig1' and 'sig2' extractor functions applied to that same index.*)\nLemma sigE12 s : sig s = @Tagged _ (sig1 s) _ (sig2 s).\n\n(*This lemma provides an equational property of the 'rank' function, stating that applying 'rank' to a structured pair is equivalent to applying the curried 'Rank' function to the first and second components of that pair.*)\nLemma rankE p : rank p = @Rank (tag p) (tagged p). \n\n(*This lemma states that applying the 'Rank' function to the two components extracted by the 'sig1' and 'sig2' functions from a given flattened index reconstructs the original flattened index.*)\nLemma sig2K s : Rank (sig2 s) = s. \n\n(*This lemma states that if one computes the flattened rank of a pair and then uses the 'sig1' function to extract the first component of the corresponding un-flattened pair, the result is the same as the first component of the original pair.*)\nLemma Rank1K i0 (k : 'I_(p_ i0)) : sig1 (Rank k) = i0.\n\n(*This lemma states that if one computes the flattened rank of a pair and then uses the 'sig2' function to extract the second component of the corresponding un-flattened pair, the result, after appropriate type casting, is the same as the second component of the original pair.*)\nLemma Rank2K i0 (k : 'I_(p_ i0)) :\n sig2 (Rank k) = cast_ord (congr1 p_ (esym (Rank1K k))) k.\n\n#[local] Hint Resolve sigK rankK : core.\n\n(*This lemma states that the 'rank' function, which flattens a structured pair into an index, is a bijection.*)\nLemma rank_bij : bijective rank. \n(*This lemma states that the 'sig' function, which maps a flattened index to a structured pair, is a bijection.*)\nLemma sig_bij : bijective sig. \n\n(*This lemma states that the 'rank' function is a bijection on the set of all elements of its domain.*)\nLemma rank_bij_on : {on [pred _ | true], bijective rank}.\n\n(*This lemma states that the 'sig' function is a bijection on the set of all elements of its domain.*)\nLemma sig_bij_on : {on [pred _ | true], bijective sig}.\n\n(*This lemma states that the 'sig' function is monotonic. If a first flattened index is less than or equal to a second, the corresponding structured pair for the first is less than or equal to the pair for the second under the lexicographic order.*)\nLemma le_sig : {mono sig : i j / i <= j}.\n\n(*This lemma states that the 'sig1' function, which extracts the first component from a structured pair, is monotonic. A larger flattened index results in a first component that is greater than or equal to the first component of a smaller index.*)\nLemma le_sig1 : {homo sig1 : i j / i <= j}.\n\n(*This lemma states that the 'rank' function is monotonic. If a first structured pair is less than or equal to a second under the lexicographic order, the flattened rank of the first is less than or equal to the rank of the second.*)\nLemma le_rank : {mono rank : p q / p <= q}.\n\n(*This lemma states that for any fixed first component, the curried 'Rank' function is monotonic with respect to its second argument.*)\nLemma le_Rank i : {mono @Rank i : j k / j <= k}.\n\n(*This lemma states that the 'sig' function is strictly monotonic. If a first flattened index is strictly less than a second, the corresponding structured pair for the first is strictly less than the pair for the second under the lexicographic order.*)\nLemma lt_sig : {mono sig : i j / i < j}.\n\n(*This lemma states that the 'rank' function is strictly monotonic. If a first structured pair is strictly less than a second under the lexicographic order, the flattened rank of the first is strictly less than the rank of the second.*)\nLemma lt_rank : {mono rank : p q / p < q}.\n\n(*This lemma states that for a fixed component index, the global Rank function is strictly increasing with respect to the value within that component. If a value is less than another within the same component, its global Rank will also be less.*)\nLemma lt_Rank i : {mono @Rank i : j k / j < k}.\n\n(*This lemma asserts that the Rank function is injective with respect to its two arguments. The Rank values for two sets of arguments are equal if and only if their corresponding first arguments are equal and their second arguments are equal.*)\nLemma eq_Rank i i' (j : 'I_(p_ i)) (j': 'I_(p_ i')) :\n (Rank j == Rank j' :> nat) = (i == i') && (j == j' :> nat).\n\n(*This lemma provides a formula for the rank of an element. The rank is calculated by summing the sizes of all components that precede the element's own component, and then adding the element's value within its component.*)\nLemma rankEsum p : rank p = \\sum_(i < n | (i < tag p)%N) p_ i + tagged p :> nat.\n\n(*This lemma provides a formula for the Rank function. The Rank of an element, specified by its component index and its value, is calculated by summing the sizes of all components preceding it, and then adding the element's value.*)\nLemma RankEsum i j : @Rank i j = \\sum_(k < n | (k < i)%N) p_ k + j :> nat.\n\n(*This lemma asserts that a natural number representing a flattened element from a dependent sum can be uniquely decomposed back into its constituent parts. The number is shown to be equal to the sum of the sizes of all preceding components plus the value within its component, where the component index and the value are obtained through projection functions.*)\nLemma rect s : s = \\sum_(i < n | (i < sig1 s)%N) p_ i + sig2 s :> nat.\n\n(*This lemma states that the rank function is injective, meaning two elements are equal if and only if their corresponding ranks are equal.*)\nLemma eqRank (i0 j : nat) (li0 : (i0 < n)%N) (lj : (j < p_ (Ordinal li0))%N) :\n (\\sum_(i < n | (i < i0)%N) p_ i) + j = Rank (Ordinal lj) :> nat.\n\nEnd tagnat.\nEnd tagnat.", - "order.preorder": "From HB Require Import structures.\nFrom mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat choice seq.\nFrom mathcomp Require Import path fintype tuple bigop finset div prime finfun.\nFrom mathcomp Require Import finset.\n\nSet Implicit Arguments.\nUnset Strict Implicit.\nUnset Printing Implicit Defensive.\n\nDeclare Scope order_scope.\n\nDelimit Scope order_scope with O.\nLocal Open Scope order_scope.\n\nReserved Notation \"<= y\" (at level 35).\nReserved Notation \">= y\" (at level 35).\nReserved Notation \"< y\" (at level 35).\nReserved Notation \"> y\" (at level 35).\nReserved Notation \"<= y :> T\" (at level 35, y at next level).\nReserved Notation \">= y :> T\" (at level 35, y at next level).\nReserved Notation \"< y :> T\" (at level 35, y at next level).\nReserved Notation \"> y :> T\" (at level 35, y at next level).\nReserved Notation \"x >=< y\" (at level 70, no associativity).\nReserved Notation \">=< y\" (at level 35).\nReserved Notation \">=< y :> T\" (at level 35, y at next level).\nReserved Notation \"x >< y\" (at level 70, no associativity).\nReserved Notation \">< x\" (at level 35).\nReserved Notation \">< y :> T\" (at level 35, y at next level).\nReserved Notation \"f \\min g\" (at level 50, left associativity).\nReserved Notation \"f \\max g\" (at level 50, left associativity).\n\nReserved Notation \"x < y ?<= 'if' c\" (c at next level,\n format \"x '[hv' < y '/' ?<= 'if' c ']'\").\nReserved Notation \"x < y ?<= 'if' c :> T\" (\n format \"x '[hv' < y '/' ?<= 'if' c :> T ']'\").\n\nReserved Notation \"\\bot\".\nReserved Notation \"\\top\".\n\nReserved Notation \"x <=^d y\" (at level 70, y at next level).\nReserved Notation \"x >=^d y\" (at level 70, y at next level).\nReserved Notation \"x <^d y\" (at level 70, y at next level).\nReserved Notation \"x >^d y\" (at level 70, y at next level).\nReserved Notation \"x <=^d y :> T\" (at level 70, y at next level).\nReserved Notation \"x >=^d y :> T\" (at level 70, y at next level).\nReserved Notation \"x <^d y :> T\" (at level 70, y at next level).\nReserved Notation \"x >^d y :> T\" (at level 70, y at next level).\nReserved Notation \"<=^d y\" (at level 35).\nReserved Notation \">=^d y\" (at level 35).\nReserved Notation \"<^d y\" (at level 35).\nReserved Notation \">^d y\" (at level 35).\nReserved Notation \"<=^d y :> T\" (at level 35, y at next level).\nReserved Notation \">=^d y :> T\" (at level 35, y at next level).\nReserved Notation \"<^d y :> T\" (at level 35, y at next level).\nReserved Notation \">^d y :> T\" (at level 35, y at next level).\nReserved Notation \"x >=<^d y\" (at level 70, no associativity).\nReserved Notation \">=<^d y\" (at level 35).\nReserved Notation \">=<^d y :> T\" (at level 35, y at next level).\nReserved Notation \"x ><^d y\" (at level 70, no associativity).\nReserved Notation \"><^d x\" (at level 35).\nReserved Notation \"><^d y :> T\" (at level 35, y at next level).\n\nReserved Notation \"x <=^d y <=^d z\" (at level 70, y, z at next level).\nReserved Notation \"x <^d y <=^d z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^d y <^d z\" (at level 70, y, z at next level).\nReserved Notation \"x <^d y <^d z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^d y ?= 'iff' c\" (at level 70, y, c at next level,\n format \"x '[hv' <=^d y '/' ?= 'iff' c ']'\").\nReserved Notation \"x <=^d y ?= 'iff' c :> T\" (at level 70, y, c at next level,\n format \"x '[hv' <=^d y '/' ?= 'iff' c :> T ']'\").\nReserved Notation \"x <^d y ?<= 'if' c\" (at level 70, y, c at next level,\n format \"x '[hv' <^d y '/' ?<= 'if' c ']'\").\nReserved Notation \"x <^d y ?<= 'if' c :> T\" (at level 70, y, c at next level,\n format \"x '[hv' <^d y '/' ?<= 'if' c :> T ']'\").\n\nReserved Notation \"\\bot^d\".\nReserved Notation \"\\top^d\".\n\nReserved Notation \"x <=^p y\" (at level 70, y at next level).\nReserved Notation \"x >=^p y\" (at level 70, y at next level).\nReserved Notation \"x <^p y\" (at level 70, y at next level).\nReserved Notation \"x >^p y\" (at level 70, y at next level).\nReserved Notation \"x <=^p y :> T\" (at level 70, y at next level).\nReserved Notation \"x >=^p y :> T\" (at level 70, y at next level).\nReserved Notation \"x <^p y :> T\" (at level 70, y at next level).\nReserved Notation \"x >^p y :> T\" (at level 70, y at next level).\nReserved Notation \"<=^p y\" (at level 35).\nReserved Notation \">=^p y\" (at level 35).\nReserved Notation \"<^p y\" (at level 35).\nReserved Notation \">^p y\" (at level 35).\nReserved Notation \"<=^p y :> T\" (at level 35, y at next level).\nReserved Notation \">=^p y :> T\" (at level 35, y at next level).\nReserved Notation \"<^p y :> T\" (at level 35, y at next level).\nReserved Notation \">^p y :> T\" (at level 35, y at next level).\nReserved Notation \"x >=<^p y\" (at level 70, no associativity).\nReserved Notation \">=<^p x\" (at level 35).\nReserved Notation \">=<^p y :> T\" (at level 35, y at next level).\nReserved Notation \"x ><^p y\" (at level 70, no associativity).\nReserved Notation \"><^p x\" (at level 35).\nReserved Notation \"><^p y :> T\" (at level 35, y at next level).\n\nReserved Notation \"x <=^p y <=^p z\" (at level 70, y, z at next level).\nReserved Notation \"x <^p y <=^p z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^p y <^p z\" (at level 70, y, z at next level).\nReserved Notation \"x <^p y <^p z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^p y ?= 'iff' c\" (at level 70, y, c at next level,\n format \"x '[hv' <=^p y '/' ?= 'iff' c ']'\").\nReserved Notation \"x <=^p y ?= 'iff' c :> T\" (at level 70, y, c at next level,\n format \"x '[hv' <=^p y '/' ?= 'iff' c :> T ']'\").\n\nReserved Notation \"\\bot^p\".\nReserved Notation \"\\top^p\".\n\nReserved Notation \"x <=^sp y\" (at level 70, y at next level).\nReserved Notation \"x >=^sp y\" (at level 70, y at next level).\nReserved Notation \"x <^sp y\" (at level 70, y at next level).\nReserved Notation \"x >^sp y\" (at level 70, y at next level).\nReserved Notation \"x <=^sp y :> T\" (at level 70, y at next level).\nReserved Notation \"x >=^sp y :> T\" (at level 70, y at next level).\nReserved Notation \"x <^sp y :> T\" (at level 70, y at next level).\nReserved Notation \"x >^sp y :> T\" (at level 70, y at next level).\nReserved Notation \"<=^sp y\" (at level 35).\nReserved Notation \">=^sp y\" (at level 35).\nReserved Notation \"<^sp y\" (at level 35).\nReserved Notation \">^sp y\" (at level 35).\nReserved Notation \"<=^sp y :> T\" (at level 35, y at next level).\nReserved Notation \">=^sp y :> T\" (at level 35, y at next level).\nReserved Notation \"<^sp y :> T\" (at level 35, y at next level).\nReserved Notation \">^sp y :> T\" (at level 35, y at next level).\nReserved Notation \"x >=<^sp y\" (at level 70, no associativity).\nReserved Notation \">=<^sp x\" (at level 35).\nReserved Notation \">=<^sp y :> T\" (at level 35, y at next level).\nReserved Notation \"x ><^sp y\" (at level 70, no associativity).\nReserved Notation \"><^sp x\" (at level 35).\nReserved Notation \"><^sp y :> T\" (at level 35, y at next level).\n\nReserved Notation \"x <=^sp y <=^sp z\" (at level 70, y, z at next level).\nReserved Notation \"x <^sp y <=^sp z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^sp y <^sp z\" (at level 70, y, z at next level).\nReserved Notation \"x <^sp y <^sp z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^sp y ?= 'iff' c\" (at level 70, y, c at next level,\n format \"x '[hv' <=^sp y '/' ?= 'iff' c ']'\").\nReserved Notation \"x <=^sp y ?= 'iff' c :> T\" (at level 70, y, c at next level,\n format \"x '[hv' <=^sp y '/' ?= 'iff' c :> T ']'\").\n\nReserved Notation \"\\bot^sp\".\nReserved Notation \"\\top^sp\".\n\nReserved Notation \"x <=^l y\" (at level 70, y at next level).\nReserved Notation \"x >=^l y\" (at level 70, y at next level).\nReserved Notation \"x <^l y\" (at level 70, y at next level).\nReserved Notation \"x >^l y\" (at level 70, y at next level).\nReserved Notation \"x <=^l y :> T\" (at level 70, y at next level).\nReserved Notation \"x >=^l y :> T\" (at level 70, y at next level).\nReserved Notation \"x <^l y :> T\" (at level 70, y at next level).\nReserved Notation \"x >^l y :> T\" (at level 70, y at next level).\nReserved Notation \"<=^l y\" (at level 35).\nReserved Notation \">=^l y\" (at level 35).\nReserved Notation \"<^l y\" (at level 35).\nReserved Notation \">^l y\" (at level 35).\nReserved Notation \"<=^l y :> T\" (at level 35, y at next level).\nReserved Notation \">=^l y :> T\" (at level 35, y at next level).\nReserved Notation \"<^l y :> T\" (at level 35, y at next level).\nReserved Notation \">^l y :> T\" (at level 35, y at next level).\nReserved Notation \"x >=<^l y\" (at level 70, no associativity).\nReserved Notation \">=<^l x\" (at level 35).\nReserved Notation \">=<^l y :> T\" (at level 35, y at next level).\nReserved Notation \"x ><^l y\" (at level 70, no associativity).\nReserved Notation \"><^l x\" (at level 35).\nReserved Notation \"><^l y :> T\" (at level 35, y at next level).\n\nReserved Notation \"x <=^l y <=^l z\" (at level 70, y, z at next level).\nReserved Notation \"x <^l y <=^l z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^l y <^l z\" (at level 70, y, z at next level).\nReserved Notation \"x <^l y <^l z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^l y ?= 'iff' c\" (at level 70, y, c at next level,\n format \"x '[hv' <=^l y '/' ?= 'iff' c ']'\").\nReserved Notation \"x <=^l y ?= 'iff' c :> T\" (at level 70, y, c at next level,\n format \"x '[hv' <=^l y '/' ?= 'iff' c :> T ']'\").\n\nReserved Notation \"\\bot^l\".\nReserved Notation \"\\top^l\".\n\nReserved Notation \"x <=^sl y\" (at level 70, y at next level).\nReserved Notation \"x >=^sl y\" (at level 70, y at next level).\nReserved Notation \"x <^sl y\" (at level 70, y at next level).\nReserved Notation \"x >^sl y\" (at level 70, y at next level).\nReserved Notation \"x <=^sl y :> T\" (at level 70, y at next level).\nReserved Notation \"x >=^sl y :> T\" (at level 70, y at next level).\nReserved Notation \"x <^sl y :> T\" (at level 70, y at next level).\nReserved Notation \"x >^sl y :> T\" (at level 70, y at next level).\nReserved Notation \"<=^sl y\" (at level 35).\nReserved Notation \">=^sl y\" (at level 35).\nReserved Notation \"<^sl y\" (at level 35).\nReserved Notation \">^sl y\" (at level 35).\nReserved Notation \"<=^sl y :> T\" (at level 35, y at next level).\nReserved Notation \">=^sl y :> T\" (at level 35, y at next level).\nReserved Notation \"<^sl y :> T\" (at level 35, y at next level).\nReserved Notation \">^sl y :> T\" (at level 35, y at next level).\nReserved Notation \"x >=<^sl y\" (at level 70, no associativity).\nReserved Notation \">=<^sl x\" (at level 35).\nReserved Notation \">=<^sl y :> T\" (at level 35, y at next level).\nReserved Notation \"x ><^sl y\" (at level 70, no associativity).\nReserved Notation \"><^sl x\" (at level 35).\nReserved Notation \"><^sl y :> T\" (at level 35, y at next level).\n\nReserved Notation \"x <=^sl y <=^sl z\" (at level 70, y, z at next level).\nReserved Notation \"x <^sl y <=^sl z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^sl y <^sl z\" (at level 70, y, z at next level).\nReserved Notation \"x <^sl y <^sl z\" (at level 70, y, z at next level).\nReserved Notation \"x <=^sl y ?= 'iff' c\" (at level 70, y, c at next level,\n format \"x '[hv' <=^sl y '/' ?= 'iff' c ']'\").\nReserved Notation \"x <=^sl y ?= 'iff' c :> T\" (at level 70, y, c at next level,\n format \"x '[hv' <=^sl y '/' ?= 'iff' c :> T ']'\").\n\nReserved Notation \"\\bot^sl\".\nReserved Notation \"\\top^sl\".\n\nReserved Notation \"x %<| y\" (at level 70, no associativity).\n\nReserved Notation \"\\min_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\min_ i '/ ' F ']'\").\nReserved Notation \"\\min_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\min_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\min_ ( i <- r ) F\"\n (F at level 41,\n format \"'[' \\min_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\min_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\min_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\min_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\min_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\min_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\min_ ( i : t | P ) F\" (F at level 41).\nReserved Notation \"\\min_ ( i : t ) F\" (F at level 41).\nReserved Notation \"\\min_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\min_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\min_ ( i < n ) F ']'\").\nReserved Notation \"\\min_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\min_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\min_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\min_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\max_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\max_ i '/ ' F ']'\").\nReserved Notation \"\\max_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\max_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i <- r ) F\"\n (F at level 41,\n format \"'[' \\max_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\max_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\max_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\max_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i : t | P ) F\" (F at level 41).\nReserved Notation \"\\max_ ( i : t ) F\" (F at level 41).\nReserved Notation \"\\max_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\max_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\max_ ( i < n ) F ']'\").\nReserved Notation \"\\max_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\max_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\max_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\max_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\min^d_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\min^d_ i '/ ' F ']'\").\nReserved Notation \"\\min^d_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\min^d_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\min^d_ ( i <- r ) F\"\n (F at level 41, r at level 50,\n format \"'[' \\min^d_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\min^d_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\min^d_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min^d_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\min^d_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\min^d_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\min^d_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\min^d_ ( i : t | P ) F\" (F at level 41).\nReserved Notation \"\\min^d_ ( i : t ) F\" (F at level 41).\nReserved Notation \"\\min^d_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\min^d_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\min^d_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\min^d_ ( i < n ) F ']'\").\nReserved Notation \"\\min^d_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\min^d_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\min^d_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\min^d_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"\\max^d_ i F\"\n (at level 41, F at level 41, i at level 0,\n format \"'[' \\max^d_ i '/ ' F ']'\").\nReserved Notation \"\\max^d_ ( i <- r | P ) F\"\n (F at level 41, i, r at level 50,\n format \"'[' \\max^d_ ( i <- r | P ) '/ ' F ']'\").\nReserved Notation \"\\max^d_ ( i <- r ) F\"\n (F at level 41, r at level 50,\n format \"'[' \\max^d_ ( i <- r ) '/ ' F ']'\").\nReserved Notation \"\\max^d_ ( m <= i < n | P ) F\"\n (F at level 41, i, n at level 50,\n format \"'[' \\max^d_ ( m <= i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max^d_ ( m <= i < n ) F\"\n (F at level 41,\n format \"'[' \\max^d_ ( m <= i < n ) '/ ' F ']'\").\nReserved Notation \"\\max^d_ ( i | P ) F\"\n (F at level 41,\n format \"'[' \\max^d_ ( i | P ) '/ ' F ']'\").\nReserved Notation \"\\max^d_ ( i : t | P ) F\" (F at level 41).\nReserved Notation \"\\max^d_ ( i : t ) F\" (F at level 41).\nReserved Notation \"\\max^d_ ( i < n | P ) F\"\n (F at level 41, n at level 50,\n format \"'[' \\max^d_ ( i < n | P ) '/ ' F ']'\").\nReserved Notation \"\\max^d_ ( i < n ) F\"\n (F at level 41,\n format \"'[' \\max^d_ ( i < n ) F ']'\").\nReserved Notation \"\\max^d_ ( i 'in' A | P ) F\"\n (F at level 41, A at level 50,\n format \"'[' \\max^d_ ( i 'in' A | P ) '/ ' F ']'\").\nReserved Notation \"\\max^d_ ( i 'in' A ) F\"\n (F at level 41,\n format \"'[' \\max^d_ ( i 'in' A ) '/ ' F ']'\").\n\nReserved Notation \"'{' 'omorphism' U '->' V '}'\"\n (at level 0, U at level 98, V at level 99,\n format \"{ 'omorphism' U -> V }\").\n\nModule Order.\n\n(*A record representing a display token used to disambiguate between different order relations defined on the same type. This token controls how notations are parsed and printed.*)\n#[projections(primitive)] Record disp_t := Disp {d1 : unit; d2 : unit}.\n\n#[key=\"T\", primitive]\n(*A record that specifies the properties of a type equipped with a preorder relation. It provides a 'less-than-or-equal-to' relation and a 'less-than' relation, and requires proofs that the 'less-than-or-equal-to' relation is reflexive and transitive, and that its dual relation (greater-than-or-equal-to) is also reflexive and transitive.*)\nHB.mixin Record isDuallyPreorder (d : disp_t) T of Equality T := {\n le : rel T;\n lt : rel T;\n lt_def : forall x y, lt x y = (le x y) && ~~ (le y x);\n gt_def : forall x y, lt y x = (le y x) && ~~ (le x y);\n le_refl : reflexive le;\n ge_refl : reflexive (fun x y => le y x);\n le_trans : transitive le;\n ge_trans : transitive (fun x y => le y x);\n}.\n\n#[short(type=\"preorderType\")]\n(*A structure that defines a preorder type, which is a type equipped with a reflexive and transitive 'less-than-or-equal-to' relation, parameterized by a display token. This structure bundles a type that has a choice operator with the properties of a preorder.*)\nHB.structure Definition Preorder (d : disp_t) :=\n { T of Choice T & isDuallyPreorder d T }.\n\n#[key=\"T\", primitive]\n(*A record that enriches a preorder type with a bottom element. It provides an element called 'bottom' and requires a proof that this element is less than or equal to all other elements in the type.*)\nHB.mixin Record hasBottom d T of Preorder d T := {\n bottom : T;\n le0x : forall x, le bottom x;\n}.\n\n#[key=\"T\", primitive]\n(*A record that enriches a preorder type with a top element. It provides an element called 'top' and requires a proof that all other elements in the type are less than or equal to this element.*)\nHB.mixin Record hasTop d T of Preorder d T := {\n top : T;\n lex1 : forall x, le x top;\n}.\n\n#[short(type=\"bPreorderType\")]\n(*A structure that defines a preorder type that has a bottom element, which is an element that is less than or equal to all other elements in the type.*)\nHB.structure Definition BPreorder d := { T of hasBottom d T & Preorder d T }.\n#[short(type=\"tPreorderType\")]\n(*A structure that defines a preorder type that has a top element, which is an element that is greater than or equal to all other elements in the type.*)\nHB.structure Definition TPreorder d := { T of hasTop d T & Preorder d T }.\n#[short(type=\"tbPreorderType\")]\n(*A structure that defines a preorder type that has both a top element and a bottom element.*)\nHB.structure Definition TBPreorder d := { T of hasTop d T & BPreorder d T }.\n\nSection PreorderDef.\n\nVariable (disp : disp_t) (T : preorderType disp).\n\n(*A notation for the 'less-than-or-equal-to' relation between two elements of a preorder type.*)\nLocal Notation \"x <= y\" := (le x y) : order_scope.\n(*A notation for the 'less-than' relation between two elements of a preorder type, which holds if the first element is less than or equal to the second, and the second is not less than or equal to the first.*)\nLocal Notation \"x < y\" := (lt x y) : order_scope.\n\n(*This definition introduces a binary relation that holds between two elements if the first is less than or equal to the second, or the second is less than or equal to the first. It signifies that the two elements are related in the order, not incomparable.*)\nDefinition comparable : rel T := fun (x y : T) => (x <= y) || (y <= x).\n(*A notation that represents the comparability relation, which is true if two elements can be ordered with respect to each other using 'less-than-or-equal-to'.*)\nLocal Notation \"x >=< y\" := (comparable x y) : order_scope.\n(*A notation that represents the incomparability relation, which is true if two elements cannot be ordered with respect to each other, meaning neither is less than or equal to the other.*)\nLocal Notation \"x >< y\" := (~~ (x >=< y)) : order_scope.\n\n(*This definition introduces the 'greater-than-or-equal-to' relation, which holds between two elements if the second element is less than or equal to the first.*)\nDefinition ge : simpl_rel T := [rel x y | y <= x].\n(*This definition introduces the 'greater-than' relation, which holds between two elements if the second element is strictly less than the first.*)\nDefinition gt : simpl_rel T := [rel x y | y < x].\n(*This definition constructs a proposition that asserts two conditions: first, that an element is less than or equal to another element, and second, that the boolean result of comparing these two elements for equality is equal to a given boolean value.*)\nDefinition leif (x y : T) C : Prop := ((x <= y) * ((x == y) = C))%type.\n\n(*This definition extracts a proof of the 'less-than-or-equal-to' relation from a proof of the 'leif' proposition, which itself bundles the 'less-than-or-equal-to' relation with an equality condition.*)\nDefinition le_of_leif x y C (le_xy : @leif x y C) := le_xy.1 : le x y.\n\n(*This definition provides a relation that evaluates to 'less-than-or-equal-to' if a given boolean is true, and to 'less-than' if the boolean is false.*)\nDefinition lteif (x y : T) C := if C then x <= y else x < y.\n\n(*An inductive type that represents the outcome of comparing two elements, capturing the exclusive choice between the 'less-than-or-equal-to' relation and the 'greater-than' relation. It has a constructor for when the first element is less than or equal to the second, and another for when the first element is greater than the second.*)\nVariant le_xor_gt (x y : T) :\n T -> T -> T -> T -> bool -> bool -> Set :=\n(**)\n | LeNotGt of x <= y : le_xor_gt x y x x y y true false\n(**)\n | GtNotLe of y < x : le_xor_gt x y y y x x false true.\n\n(*An inductive type that represents the outcome of comparing two elements, capturing the exclusive choice between the 'less-than' relation and the 'greater-than-or-equal-to' relation. It has a constructor for when the first element is less than the second, and another for when the first element is greater than or equal to the second.*)\nVariant lt_xor_ge (x y : T) :\n T -> T -> T -> T -> bool -> bool -> Set :=\n(**)\n | LtNotGe of x < y : lt_xor_ge x y x x y y false true\n(**)\n | GeNotLt of y <= x : lt_xor_ge x y y y x x true false.\n\n(*This definition computes the minimum of two elements from an ordered type. It returns the first element if it is strictly less than the second, and the second element otherwise.*)\nDefinition min (x y : T) := if x < y then x else y.\n(*This definition computes the maximum of two elements from an ordered type. It returns the second element if the first is strictly less than the second, and the first element otherwise.*)\nDefinition max (x y : T) := if x < y then y else x.\n\n(*An inductive type that provides a detailed comparison of two elements, assuming a total order. It has three constructors, indicating whether the first element is strictly less than, strictly greater than, or equal to the second element. It also provides the minimum and maximum of the two elements and several boolean flags summarizing the comparison.*)\nVariant compare (x y : T) :\n T -> T -> T -> T ->\n bool -> bool -> bool -> bool -> bool -> bool -> Set :=\n(**)\n | CompareLt of x < y : compare x y\n x x y y false false false true false true\n(**)\n | CompareGt of y < x : compare x y\n y y x x false false true false true false\n(**)\n | CompareEq of x = y : compare x y\n x x x x true true true true false false.\n\n(*An inductive type that provides a detailed comparison of two elements in a partial order. It has four constructors, indicating whether the first element is strictly less than, strictly greater than, equal to, or incomparable to the second element. It also provides various boolean flags summarizing the comparison.*)\nVariant incompare (x y : T) :\n T -> T -> T -> T ->\n bool -> bool -> bool -> bool -> bool -> bool -> bool -> bool -> Set :=\n(**)\n | InCompareLt of x < y : incompare x y\n x x y y false false false true false true true true\n(**)\n | InCompareGt of y < x : incompare x y\n y y x x false false true false true false true true\n(**)\n | InCompare of x >< y : incompare x y\n x y y x false false false false false false false false\n(**)\n | InCompareEq of x = y : incompare x y\n x x x x true true true true false false true true.\n\n(*This definition finds an element in a given finite domain that minimizes a function mapping from that domain to an ordered type. The returned element is one that produces a value that is less-than-or-equal-to all other values produced by the function.*)\nDefinition arg_min {I : finType} := @extremum T I le.\n(*This definition finds an element in a given finite domain that maximizes a function mapping from that domain to an ordered type. The returned element is one that produces a value that is greater-than-or-equal-to all other values produced by the function.*)\nDefinition arg_max {I : finType} := @extremum T I ge.\n\nSection LiftedPreorder.\nVariable T' : Type.\nImplicit Type f : T' -> T.\n(*This definition creates a new function that, for any given input, returns the minimum of the values produced by two other functions for that same input. This is the pointwise minimum of two functions.*)\nDefinition min_fun f g x := min (f x) (g x).\n(*This definition creates a new function that, for any given input, returns the maximum of the values produced by two other functions for that same input. This is the pointwise maximum of two functions.*)\nDefinition max_fun f g x := max (f x) (g x).\nEnd LiftedPreorder.\n\n(*This definition specifies that a function between two preordered types is nondecreasing if it preserves the order relation, meaning that for any two elements in the domain, if the first is less than or equal to the second, then their images under the function maintain the same relationship in the codomain.*)\nDefinition nondecreasing disp' (T' : preorderType disp') (f : T -> T') : Prop :=\n {homo f : x y / x <= y}.\n\nEnd PreorderDef.\n\nPrenex Implicits lt le leif lteif.\nArguments ge {_ _}.\nArguments gt {_ _}.\nArguments min {_ _}.\nArguments max {_ _}.\nArguments comparable {_ _}.\nArguments min_fun {_ _ _} f g _ /.\nArguments max_fun {_ _ _} f g _ /.\n\nModule Import Def.\n\n(*This term describes a function that preserves an order relation. When a first input is less than or equal to a second input, the function's output for the first input will be less than or equal to its output for the second input.*)\nNotation nondecreasing := nondecreasing.\n(*A notation for the binary minimum function, which takes two elements from an ordered type and returns the one that is smaller according to the order relation.*)\nNotation min := min.\n(*A notation for the binary maximum function, which takes two elements from an ordered type and returns the one that is larger according to the order relation.*)\nNotation max := max.\n\nEnd Def.\n\nModule Import PreOSyntax.\n\n(*A notation for the curried function representing the 'less than or equal to' relation. It takes two elements and returns a proposition asserting that the first element is less than or equal to the second.*)\nNotation \"<=%O\" := le : function_scope.\n(*A notation for the curried function representing the 'greater than or equal to' relation. It takes two elements and returns a proposition asserting that the first element is greater than or equal to the second.*)\nNotation \">=%O\" := ge : function_scope.\n(*A notation for the curried function representing the 'less than' relation. It takes two elements and returns a proposition asserting that the first element is strictly less than the second.*)\nNotation \"<%O\" := lt : function_scope.\n(*A notation for the curried function representing the 'greater than' relation. It takes two elements and returns a proposition asserting that the first element is strictly greater than the second.*)\nNotation \">%O\" := gt : function_scope.\n(*A notation for a boolean comparison function that checks the 'less than or equal to' relation. It takes two elements and returns true if the first is less than or equal to the second, and false otherwise.*)\nNotation \"=<%O\" := comparable : function_scope.\n(*A notation for a function that determines if two elements are incomparable. It returns a proposition that is true if the two elements are not comparable, meaning neither is less than or equal to the other.*)\nNotation \"><%O\" := (fun x y => ~~ (comparable x y)) : function_scope.\n\n(*A notation for a unary predicate that asserts an element is less than or equal to a given value 'y'.*)\nNotation \"<= y\" := (ge y) : order_scope.\n(*A notation for a unary predicate that asserts an element is less than or equal to a given value 'y'. This variant includes a type annotation to specify that 'y' belongs to a particular type 'T', which helps the system resolve the correct order relation to use.*)\nNotation \"<= y :> T\" := (<= (y : T)) (only parsing) : order_scope.\n(*A notation for a unary predicate that asserts an element is greater than or equal to a given value 'y'.*)\nNotation \">= y\" := (le y) : order_scope.\n(*A notation for a unary predicate that asserts an element is greater than or equal to a given value 'y'. This variant includes a type annotation to specify that 'y' belongs to a particular type 'T', which helps the system resolve the correct order relation to use.*)\nNotation \">= y :> T\" := (>= (y : T)) (only parsing) : order_scope.\n\n(*A notation for a unary predicate that asserts an element is strictly less than a given value 'y'.*)\nNotation \"< y\" := (gt y) : order_scope.\n(*A notation for a unary predicate that asserts an element is strictly less than a given value 'y'. This variant includes a type annotation to specify that 'y' belongs to a particular type 'T', which helps the system resolve the correct order relation to use.*)\nNotation \"< y :> T\" := (< (y : T)) (only parsing) : order_scope.\n(*A notation for a unary predicate that asserts an element is strictly greater than a given value 'y'.*)\nNotation \"> y\" := (lt y) : order_scope.\n(*A notation for a unary predicate that asserts an element is strictly greater than a given value 'y'. This variant includes a type annotation to specify that 'y' belongs to a particular type 'T', which helps the system resolve the correct order relation to use.*)\nNotation \"> y :> T\" := (> (y : T)) (only parsing) : order_scope.\n\n(*A notation for the binary relation asserting that a first element 'x' is less than or equal to a second element 'y'.*)\nNotation \"x <= y\" := (le x y) : order_scope.\n(*A notation asserting that a first element 'x' is less than or equal to a second element 'y'. This variant includes a type annotation to specify that both 'x' and 'y' belong to a particular type 'T', guiding the system to use the appropriate order relation.*)\nNotation \"x <= y :> T\" := ((x : T) <= (y : T)) (only parsing) : order_scope.\n(*A notation for the binary relation asserting that a first element 'x' is greater than or equal to a second element 'y'. This is defined as the second element being less than or equal to the first.*)\nNotation \"x >= y\" := (y <= x) (only parsing) : order_scope.\n(*A notation asserting that a first element 'x' is greater than or equal to a second element 'y'. This variant includes a type annotation to specify that both 'x' and 'y' belong to a particular type 'T'.*)\nNotation \"x >= y :> T\" := ((x : T) >= (y : T)) (only parsing) : order_scope.\n\n(*A notation for the binary relation asserting that a first element 'x' is strictly less than a second element 'y'.*)\nNotation \"x < y\" := (lt x y) : order_scope.\n(*A notation asserting that a first element 'x' is strictly less than a second element 'y'. This variant includes a type annotation to specify that both 'x' and 'y' belong to a particular type 'T'.*)\nNotation \"x < y :> T\" := ((x : T) < (y : T)) (only parsing) : order_scope.\n(*A notation for the binary relation asserting that a first element 'x' is strictly greater than a second element 'y'. This is defined as the second element being strictly less than the first.*)\nNotation \"x > y\" := (y < x) (only parsing) : order_scope.\n(*A notation asserting that a first element 'x' is strictly greater than a second element 'y'. This variant includes a type annotation to specify that both 'x' and 'y' belong to a particular type 'T'.*)\nNotation \"x > y :> T\" := ((x : T) > (y : T)) (only parsing) : order_scope.\n\n(*A notation for a chained comparison that returns a boolean value. It asserts that a first element 'x' is less than or equal to a second element 'y', and that 'y' is also less than or equal to a third element 'z'.*)\nNotation \"x <= y <= z\" := ((x <= y) && (y <= z)) : order_scope.\n(*A notation for a chained comparison that returns a boolean value. It asserts that a first element 'x' is strictly less than a second element 'y', and that 'y' is less than or equal to a third element 'z'.*)\nNotation \"x < y <= z\" := ((x < y) && (y <= z)) : order_scope.\n(*A notation for a chained comparison that returns a boolean value. It asserts that a first element 'x' is less than or equal to a second element 'y', and that 'y' is strictly less than a third element 'z'.*)\nNotation \"x <= y < z\" := ((x <= y) && (y < z)) : order_scope.\n(*This notation provides a way to express a chain of strict inequalities, asserting that a first element is strictly less than a second, and that the second element is strictly less than a third.*)\nNotation \"x < y < z\" := ((x < y) && (y < z)) : order_scope.\n\n(*This notation represents a boolean statement asserting that the relation 'the first element is less than or equal to the second element' holds if and only if a given boolean condition is true.*)\nNotation \"x <= y ?= 'iff' C\" := (leif x y C) : order_scope.\n(*This notation provides a way to parse an expression that asserts that the relation 'the first element is less than or equal to the second element' within a specified type holds if and only if a given boolean condition is true.*)\nNotation \"x <= y ?= 'iff' C :> T\" := ((x : T) <= (y : T) ?= iff C)\n (only parsing) : order_scope.\n\n(*This notation represents a boolean statement that asserts a conditional inequality: if a given boolean condition is true, it asserts that the first element is strictly less than the second; otherwise, it asserts that the first element is less than or equal to the second.*)\nNotation \"x < y ?<= 'if' C\" := (lteif x y C) : order_scope.\n(*This notation provides a way to parse an expression representing a conditional inequality within a specified type: if a given boolean condition is true, it asserts that the first element is strictly less than the second; otherwise, it asserts that the first element is less than or equal to the second.*)\nNotation \"x < y ?<= 'if' C :> T\" := ((x : T) < (y : T) ?<= if C)\n (only parsing) : order_scope.\n\n(*This notation defines a predicate that holds for any element that is comparable to a given element, meaning either the element is less than or equal to the given element, or the given element is less than or equal to the element.*)\nNotation \">=< y\" := [pred x | comparable x y] : order_scope.\n(*This notation provides a way to parse a predicate that holds for any element of a specified type that is comparable with a given element of the same type.*)\nNotation \">=< y :> T\" := (>=< (y : T)) (only parsing) : order_scope.\n(*This notation represents a boolean value that is true if two given elements are comparable, meaning that one is less than or equal to the other.*)\nNotation \"x >=< y\" := (comparable x y) : order_scope.\n\n(*This notation defines a predicate that holds for any element that is incomparable to a given element, meaning neither is less than or equal to the other.*)\nNotation \">< y\" := [pred x | ~~ comparable x y] : order_scope.\n(*This notation provides a way to parse a predicate that holds for any element of a specified type that is incomparable with a given element of the same type.*)\nNotation \">< y :> T\" := (>< (y : T)) (only parsing) : order_scope.\n(*This notation represents a boolean value that is true if two given elements are incomparable, meaning neither is less than or equal to the other.*)\nNotation \"x >< y\" := (~~ (comparable x y)) : order_scope.\n\n(*This notation denotes an argument that minimizes a given function, where the search is restricted to natural numbers less than a specified upper bound that also satisfy a given predicate.*)\nNotation \"[ 'arg' 'min_' ( i < i0 | P ) F ]\" :=\n (arg_min i0 (fun i => P%B) (fun i => F))\n (i, i0 at level 10,\n format \"[ 'arg' 'min_' ( i < i0 | P ) F ]\") : order_scope.\n\n(*This notation denotes an argument that minimizes a given function, where the search is restricted to natural numbers that are less than a specified upper bound and are also members of a given set.*)\nNotation \"[ 'arg' 'min_' ( i < i0 'in' A ) F ]\" :=\n [arg min_(i < i0 | i \\in A) F]\n (format \"[ 'arg' 'min_' ( i < i0 'in' A ) F ]\") : order_scope.\n\n(*This notation denotes an argument that minimizes a given function, where the search is restricted to all natural numbers strictly less than a specified upper bound.*)\nNotation \"[ 'arg' 'min_' ( i < i0 ) F ]\" := [arg min_(i < i0 | true) F]\n (i0 at level 10,\n format \"[ 'arg' 'min_' ( i < i0 ) F ]\") : order_scope.\n\n(*This notation denotes an argument that maximizes a given function, where the search is restricted to natural numbers up to a specified upper bound that also satisfy a given predicate.*)\nNotation \"[ 'arg' 'max_' ( i > i0 | P ) F ]\" :=\n (arg_max i0 (fun i => P%B) (fun i => F))\n (i, i0 at level 10,\n format \"[ 'arg' 'max_' ( i > i0 | P ) F ]\") : order_scope.\n\n(*This notation denotes an argument that maximizes a given function, where the search is restricted to natural numbers that are up to a specified upper bound and are also members of a given set.*)\nNotation \"[ 'arg' 'max_' ( i > i0 'in' A ) F ]\" :=\n [arg max_(i > i0 | i \\in A) F]\n (i, i0 at level 10,\n format \"[ 'arg' 'max_' ( i > i0 'in' A ) F ]\") : order_scope.\n\n(*This notation denotes an argument that maximizes a given function, where the search is restricted to all natural numbers up to a specified upper bound.*)\nNotation \"[ 'arg' 'max_' ( i > i0 ) F ]\" := [arg max_(i > i0 | true) F]\n (i, i0 at level 10,\n format \"[ 'arg' 'max_' ( i > i0 ) F ]\") : order_scope.\n\n(*This notation defines a new function that, for any given input, returns the minimum of the outputs of two original functions when applied to that same input.*)\nNotation \"f \\min g\" := (min_fun f g) : function_scope.\n(*This notation defines a new function that, for any given input, returns the maximum of the outputs of two original functions when applied to that same input.*)\nNotation \"f \\max g\" := (max_fun f g) : function_scope.\n\n(*This notation defines a pattern for use in proof tactics that matches the expression on the left-hand side of a less-than-or-equal-to relation.*)\nNotation leLHS := (X in (X <= _)%O)%pattern.\n(*This notation defines a pattern for use in proof tactics that matches the expression on the right-hand side of a less-than-or-equal-to relation.*)\nNotation leRHS := (X in (_ <= X)%O)%pattern.\n(*This notation defines a pattern for use in proof tactics that matches the expression on the left-hand side of a strict less-than relation.*)\nNotation ltLHS := (X in (X < _)%O)%pattern.\n(*This notation defines a pattern for use in proof tactics that matches the expression on the right-hand side of a strict less-than relation.*)\nNotation ltRHS := (X in (_ < X)%O)%pattern.\n\n(*This notation represents the bottom or least element in a preordered type, which is an element that is less than or equal to every other element in the type.*)\nNotation \"\\bot\" := bottom : order_scope.\n(*This notation represents the top or greatest element in a preordered type, which is an element that is greater than or equal to every other element in the type.*)\nNotation \"\\top\" := top : order_scope.\n\nEnd PreOSyntax.\nHB.export PreOSyntax.\n\nModule PreOCoercions.\nCoercion le_of_leif : leif >-> is_true.\nEnd PreOCoercions.\nHB.export PreOCoercions.\n\n#[short(type=\"finPreorderType\")]\n(*This definition specifies the structure for a type that is both a finite type and equipped with a preorder, which is a binary relation that is reflexive and transitive.*)\nHB.structure Definition FinPreorder d := { T of Finite T & Preorder d T }.\n\n#[short(type=\"finBPreorderType\")]\n(*This definition specifies the structure for a type that is a finite preorder and also possesses a bottom element, which is an element less than or equal to all others.*)\nHB.structure Definition FinBPreorder d := { T of FinPreorder d T & hasBottom d T }.\n\n#[short(type=\"finTPreorderType\")]\n(*This definition specifies the structure for a type that is a finite preorder and also possesses a top element, which is an element greater than or equal to all others.*)\nHB.structure Definition FinTPreorder d := { T of FinPreorder d T & hasTop d T }.\n\n#[short(type=\"finTBPreorderType\")]\n(*This definition specifies the structure for a type that is a finite preorder and possesses both a bottom element and a top element.*)\nHB.structure Definition FinTBPreorder d := { T of FinBPreorder d T & hasTop d T }.\n\n(*This definition creates a type alias that serves as a marker to indicate that the dual order should be used for the underlying type, where the dual order reverses the original less-than-or-equal-to relation.*)\nDefinition dual T : Type := T.\n(*This definition constructs a new display configuration for a dual order from a given display. It achieves this by swapping the two internal components of the original display, effectively reversing the direction of all associated order relations.*)\nDefinition dual_display (d : disp_t) := {| d1 := d2 d; d2 := d1 d |}.\n\n(*This definition establishes the 'less than or equal to' relation for a dual order. An element is considered less than or equal to another in the dual order if and only if it is greater than or equal to the other in the original order.*)\nNotation dual_le := (@le (dual_display _) _).\n(*This definition establishes the 'less than' relation for a dual order. An element is considered less than another in the dual order if and only if it is greater than the other in the original order.*)\nNotation dual_lt := (@lt (dual_display _) _).\n(*This definition establishes the comparability relation for a dual order. Two elements are considered comparable in the dual order if and only if they are comparable in the original order.*)\nNotation dual_comparable := (@comparable (dual_display _) _).\n(*This definition establishes the 'greater than or equal to' relation for a dual order. An element is considered greater than or equal to another in the dual order if and only if it is less than or equal to the other in the original order.*)\nNotation dual_ge := (@ge (dual_display _) _).\n(*This definition establishes the 'greater than' relation for a dual order. An element is considered greater than another in the dual order if and only if it is less than the other in the original order.*)\nNotation dual_gt := (@gt (dual_display _) _).\n(*This definition provides a boolean test for the 'less than or equal to' relation in a dual order. The function returns true if the first input is less than or equal to the second input according to the dual ordering.*)\nNotation dual_leif := (@leif (dual_display _) _).\n(*This definition provides a boolean test for the 'less than' relation in a dual order. The function returns true if the first input is strictly less than the second input according to the dual ordering.*)\nNotation dual_lteif := (@lteif (dual_display _) _).\n(*This definition provides the maximum operation for a dual order. The maximum of two elements in the dual order is equivalent to their minimum in the original order.*)\nNotation dual_max := (@max (dual_display _) _).\n(*This definition provides the minimum operation for a dual order. The minimum of two elements in the dual order is equivalent to their maximum in the original order.*)\nNotation dual_min := (@min (dual_display _) _).\n(*This definition identifies the bottom, or least, element within a dual order structure. This element corresponds to the top, or greatest, element of the original order.*)\nNotation dual_bottom := (@bottom (dual_display _) _).\n(*This definition identifies the top, or greatest, element within a dual order structure. This element corresponds to the bottom, or least, element of the original order.*)\nNotation dual_top := (@top (dual_display _) _).\n\nModule Import DualSyntax.\n\n(*This notation serves as a type-level operator to denote the dual of an ordered type 'T'. The resulting type 'T ^d' shares the same underlying elements as 'T' but is equipped with the reversed order relation.*)\nNotation \"T ^d\" := (dual T) (at level 2, format \"T ^d\") : type_scope.\n(*This notation represents the 'less than or equal to' relation of a dual order as a two-argument function. It evaluates to true if the first argument is greater than or equal to the second argument in the original order.*)\nNotation \"<=^d%O\" := dual_le : function_scope.\n(*This notation represents the 'greater than or equal to' relation of a dual order as a two-argument function. It evaluates to true if the first argument is less than or equal to the second argument in the original order.*)\nNotation \">=^d%O\" := dual_ge : function_scope.\n(*This notation represents the 'less than' relation of a dual order as a two-argument function. It evaluates to true if the first argument is greater than the second argument in the original order.*)\nNotation \"<^d%O\" := dual_lt : function_scope.\n(*This notation represents the 'greater than' relation of a dual order as a two-argument function. It evaluates to true if the first argument is less than the second argument in the original order.*)\nNotation \">^d%O\" := dual_gt : function_scope.\n(*This notation represents a boolean test for the 'less than or equal to' relation in a dual order, provided as a two-argument function.*)\nNotation \"=<^d%O\" := dual_comparable : function_scope.\n(*This notation represents the test for incomparability in a dual order as a two-argument function. It evaluates to true if the two arguments are not comparable.*)\nNotation \"><^d%O\" := (fun x y => ~~ dual_comparable x y) : function_scope.\n\n(*This notation creates a predicate that checks if an element is less than or equal to a given element 'y' with respect to the original, non-dual order.*)\nNotation \"<=^d y\" := (>=^d%O y) : order_scope.\n(*This notation is a parsing aid that explicitly specifies the type of the element 'y' to be 'T' when forming a predicate that tests whether an element is less than or equal to 'y' in the original order.*)\nNotation \"<=^d y :> T\" := (<=^d (y : T)) (only parsing) : order_scope.\n(*This notation creates a predicate that checks if an element is greater than or equal to a given element 'y' with respect to the original, non-dual order.*)\nNotation \">=^d y\" := (<=^d%O y) : order_scope.\n(*This notation is a parsing aid that explicitly specifies the type of the element 'y' to be 'T' when forming a predicate that tests whether an element is greater than or equal to 'y' in the original order.*)\nNotation \">=^d y :> T\" := (>=^d (y : T)) (only parsing) : order_scope.\n\n(*This notation creates a predicate that checks if an element is strictly less than a given element 'y' with respect to the original, non-dual order.*)\nNotation \"<^d y\" := (>^d%O y) : order_scope.\n(*This notation is a parsing aid that explicitly specifies the type of the element 'y' to be 'T' when forming a predicate that tests whether an element is strictly less than 'y' in the original order.*)\nNotation \"<^d y :> T\" := (<^d (y : T)) (only parsing) : order_scope.\n(*This notation creates a predicate that checks if an element is strictly greater than a given element 'y' with respect to the original, non-dual order.*)\nNotation \">^d y\" := (<^d%O y) : order_scope.\n(*This notation is a parsing aid that explicitly specifies the type of the element 'y' to be 'T' when forming a predicate that tests whether an element is strictly greater than 'y' in the original order.*)\nNotation \">^d y :> T\" := (>^d (y : T)) (only parsing) : order_scope.\n\n(*This notation is an infix operator expressing that an element 'x' is less than or equal to an element 'y' in the dual order, which is equivalent to 'x' being greater than or equal to 'y' in the original order.*)\nNotation \"x <=^d y\" := (<=^d%O x y) : order_scope.\n(*A notation for comparing two elements of a given ordered type using the dual 'less than or equal to' relation, which holds if and only if the second element is less than or equal to the first in the original order.*)\nNotation \"x <=^d y :> T\" := ((x : T) <=^d (y : T)) (only parsing) : order_scope.\n(*A notation for the dual 'greater than or equal to' relation, which asserts that the first element is greater than or equal to the second in the an order's dual. This is equivalent to the first element being less than or equal to the second in the original order.*)\nNotation \"x >=^d y\" := (y <=^d x) (only parsing) : order_scope.\n(*A notation for comparing two elements of a given ordered type using the dual 'greater than or equal to' relation. This relation holds if and only if the first element is less than or equal to the second in the original order.*)\nNotation \"x >=^d y :> T\" := ((x : T) >=^d (y : T)) (only parsing) : order_scope.\n\n(*A notation for the dual 'less than' relation, which asserts that the first element is strictly less than the second in an order's dual. This is equivalent to the second element being strictly less than the first in the original order.*)\nNotation \"x <^d y\" := (<^d%O x y) : order_scope.\n(*A notation for comparing two elements of a given ordered type using the dual 'less than' relation. This relation holds if and only if the second element is strictly less than the first in the original order.*)\nNotation \"x <^d y :> T\" := ((x : T) <^d (y : T)) (only parsing) : order_scope.\n(*A notation for the dual 'greater than' relation, which asserts that the first element is strictly greater than the second in an order's dual. This is equivalent to the first element being strictly less than the second in the original order.*)\nNotation \"x >^d y\" := (y <^d x) (only parsing) : order_scope.\n(*A notation for comparing two elements of a given ordered type using the dual 'greater than' relation. This relation holds if and only if the first element is strictly less than the second in the original order.*)\nNotation \"x >^d y :> T\" := ((x : T) >^d (y : T)) (only parsing) : order_scope.\n\n(*A notation for a chained comparison asserting that the first element is less than or equal to the second, and the second is less than or equal to the third, all within the dual order.*)\nNotation \"x <=^d y <=^d z\" := ((x <=^d y) && (y <=^d z)) : order_scope.\n(*A notation for a chained comparison asserting that the first element is strictly less than the second, and the second is less than or equal to the third, all within the dual order.*)\nNotation \"x <^d y <=^d z\" := ((x <^d y) && (y <=^d z)) : order_scope.\n(*A notation for a chained comparison asserting that the first element is less than or equal to the second, and the second is strictly less than the third, all within the dual order.*)\nNotation \"x <=^d y <^d z\" := ((x <=^d y) && (y <^d z)) : order_scope.\n(*A notation for a chained comparison asserting that the first element is strictly less than the second, and the second is strictly less than the third, all within the dual order.*)\nNotation \"x <^d y <^d z\" := ((x <^d y) && (y <^d z)) : order_scope.\n\n(*A notation for a boolean reflection of the dual 'less than or equal to' relation. It evaluates to true if the first element is less than or equal to the second in the dual order, and false otherwise, optionally using a provided proof argument.*)\nNotation \"x <=^d y ?= 'iff' C\" := ( T\" := ((x : T) <=^d (y : T) ?= iff C)\n (only parsing) : order_scope.\n\n(*A notation for a reflected, decidable 'less than' comparison in the dual order. It evaluates to a boolean, typically conditioned on a provided proof that justifies the comparison.*)\nNotation \"x <^d y ?<= 'if' C\" := ( T\" := ((x : T) <^d (y : T) ?<= if C)\n (only parsing) : order_scope.\n\n(*A notation for a predicate that checks if an element is comparable to the given element in the dual order. An element is dually comparable if it is either less than or equal to, or greater than or equal to, the given element in the dual order.*)\nNotation \">=<^d x\" := (>=<^d%O x) : order_scope.\n(*A notation for a predicate on a specified type that checks if an element is comparable to the given element in the dual order. An element is dually comparable if it is either less than or equal to, or greater than or equal to, the given element in the dual order.*)\nNotation \">=<^d y :> T\" := (>=<^d (y : T)) (only parsing) : order_scope.\n(*A notation that asserts two elements are comparable in the dual order, meaning one is less than or equal to the other in that order.*)\nNotation \"x >=<^d y\" := (>=<^d%O x y) : order_scope.\n\n(*A notation for a predicate that checks if an element is incomparable to the given element in the dual order. Two elements are dually incomparable if neither is less than or equal to the other in the dual order.*)\nNotation \"><^d y\" := [pred x | ~~ dual_comparable x y] : order_scope.\n(*A notation for a predicate on a specified type that checks if an element is incomparable to the given element in the dual order. Two elements are dually incomparable if neither is less than or equal to the other in the dual order.*)\nNotation \"><^d y :> T\" := (><^d (y : T)) (only parsing) : order_scope.\n(*A notation that asserts two elements are incomparable in the dual order, meaning that neither is less than or equal to the other in that order.*)\nNotation \"x ><^d y\" := (~~ (><^d%O x y)) : order_scope.\n\n(*A notation for the bottom element of the dual order, which corresponds to the top element of the original order.*)\nNotation \"\\bot^d\" := dual_bottom : order_scope.\n(*A notation for the top element of the dual order, which corresponds to the bottom element of the original order.*)\nNotation \"\\top^d\" := dual_top : order_scope.\n\nEnd DualSyntax.\n\nModule DualPreorder.\n\nHB.instance Definition _ (T : eqType) := Equality.on T^d.\nHB.instance Definition _ (T : choiceType) := Choice.on T^d.\nHB.instance Definition _ (T : countType) := Countable.on T^d.\nHB.instance Definition _ (T : finType) := Finite.on T^d.\n\nHB.instance Definition _ (d : disp_t) (T : preorderType d) :=\n isDuallyPreorder.Build (dual_display d) T^d\n gt_def lt_def ge_refl le_refl ge_trans le_trans.\n\n(*This lemma states that for any two elements in an ordered type, the first element is less than or equal to the second in the dual order if and only if the second element is less than or equal to the first in the original order.*)\nLemma leEdual (d : disp_t) (T : preorderType d) (x y : T) :\n (x <=^d y :> T^d) = (y <= x).\n\n(*This lemma states that for any two elements in an ordered type, the first element is strictly less than the second in the dual order if and only if the second element is strictly less than the first in the original order.*)\nLemma ltEdual (d : disp_t) (T : preorderType d) (x y : T) :\n (x <^d y :> T^d) = (y < x).\n\nHB.instance Definition _ d (T : tPreorderType d) :=\n hasBottom.Build (dual_display d) T^d lex1.\n\n(*This lemma states that for any ordered type with a top element, the bottom element of its dual type is equal to the top element of the original type.*)\nLemma botEdual d (T : tPreorderType d) : (dual_bottom : T^d) = \\top :> T.\n\n(*This lemma states that for any ordered type with a bottom element, the top element of its dual type is equal to the bottom element of the original type.*)\nLemma topEdual d (T : bPreorderType d) : (dual_top : T^d) = \\bot :> T.\n\nEnd DualPreorder.\nHB.export DualPreorder.\n\nModule Import PreorderTheory.\nSection PreorderTheory.\n\nContext {disp : disp_t} {T : preorderType disp}.\n\nImplicit Types (x y : T) (s : seq T).\n\n(*This definition specifies that a function between two ordered types is nondecreasing, also known as monotonic, if for any two elements in the domain, the image of the first is less than or equal to the image of the second whenever the first is less than or equal to the second.*)\nDefinition nondecreasing disp' (T' : preorderType disp') (f : T -> T') : Prop :=\n {homo f : x y / x <= y}.\n\n(*This lemma states that an element is greater than or equal to another element if and only if the second element is less than or equal to the first.*)\nLemma geE x y : ge x y = (y <= x). \n(*This lemma states that an element is strictly greater than another element if and only if the second element is strictly less than the first.*)\nLemma gtE x y : gt x y = (y < x). \n\n(*This lemma states that any element from an ordered type is less than or equal to itself.*)\nLemma lexx (x : T) : x <= x.\n\nHint Resolve lexx : core.\n\n(*This definition establishes the reflexivity of the 'less than or equal to' relation, asserting that every element is less than or equal to itself.*)\nDefinition le_refl : reflexive le := lexx.\n(*This definition establishes the reflexivity of the 'greater than or equal to' relation, asserting that every element is greater than or equal to itself.*)\nDefinition ge_refl : reflexive ge := lexx.\nHint Resolve le_refl : core.\n\n(*This lemma states that the 'less than or equal to' relation is transitive, meaning if a first element is less than or equal to a second, and the second is less than or equal to a third, then the first is less than or equal to the third.*)\nLemma le_trans: transitive (<=%O : rel T).\n\n(*This lemma states that the 'greater than or equal to' relation is transitive, meaning if a first element is greater than or equal to a second, and the second is greater than or equal to a third, then the first is greater than or equal to the third.*)\nLemma ge_trans: transitive (>=%O : rel T).\n\n(*This lemma states a chained transitivity property: if a first element is less than or equal to a second, the second is less than or equal to a third, and the third is less than or equal to a fourth, then the first element is less than or equal to the fourth.*)\nLemma le_le_trans x y z t : z <= x -> y <= t -> x <= y -> z <= t.\n\n(*This lemma states that an element is strictly less than another element if and only if the first is less than or equal to the second, and the second is not less than or equal to the first.*)\nLemma lt_le_def x y: (x < y) = (x <= y) && ~~ (y <= x).\n\n(*This lemma states that the proposition that an element is strictly less than itself is always false.*)\nLemma ltxx x: x < x = false.\n\n(*This definition establishes the irreflexivity of the 'less than' relation, asserting that no element can be strictly less than itself.*)\nDefinition lt_irreflexive : irreflexive lt := ltxx.\nHint Resolve lt_irreflexive : core.\n\n(*This definition combines the proof that the 'less than or equal to' relation is reflexive with the proof that the 'less than' relation is irreflexive.*)\nDefinition ltexx := (lexx, ltxx).\n\n(*This lemma states that if a first element is strictly less than a second element, then the two elements cannot be equal.*)\nLemma lt_eqF x y: x < y -> x == y = false.\n\n(*This lemma states that if a first element is strictly greater than a second element, then the two elements cannot be equal.*)\nLemma gt_eqF x y : y < x -> x == y = false.\n\n(*This lemma states that if a first element is strictly less than a second element, it is also less than or equal to the second element.*)\nLemma ltW x y: x < y -> x <= y.\n\n(*This lemma states a mixed transitivity property: if a first element is strictly less than a second, and the second is less than or equal to a third, then the first element is strictly less than the third.*)\nLemma lt_le_trans y x z: x < y -> y <= z -> x < z.\n\n(*This lemma states that the 'less than' relation is transitive, meaning if a first element is strictly less than a second, and the second is strictly less than a third, then the first is strictly less than the third.*)\nLemma lt_trans: transitive (<%O : rel T).\n\n(*This lemma states a mixed transitivity property: if a first element is less than or equal to a second, and the second is strictly less than a third, then the first element is strictly less than the third.*)\nLemma le_lt_trans y x z: x <= y -> y < z -> x < z.\n\n(*This lemma states that it is impossible for a first element to be strictly less than a second element while the second is also strictly less than the first.*)\nLemma lt_nsym x y : x < y -> y < x -> False.\n\n(*This lemma states that the proposition that an element is strictly less than a second element which is in turn strictly less than the first is always false.*)\nLemma lt_asym x y : x < y < x = false.\n\n(*This lemma states that if a first element is less than or equal to a second element, then it is false that the second element is strictly less than the first.*)\nLemma le_gtF x y: x <= y -> y < x = false.\n\n(*This lemma states that if a first element is strictly less than a second element, then it is false that the second element is less than or equal to the first.*)\nLemma lt_geF x y : x < y -> y <= x = false.\n\n(*This definition provides a proof that if a first element is strictly less than a second, then the proposition that the second is strictly less than the first is false.*)\nDefinition lt_gtF x y hxy := le_gtF (@ltW x y hxy).\n\n(*This lemma provides an alternative definition for the 'less than' relation, stating that an element is strictly less than another if and only if the first is less than or equal to the second and it is not the case that the second is less than or equal to the first.*)\nLemma lt_leAnge x y : (x < y) = (x <= y) && ~~ (y <= x).\n\n(*This lemma states that the proposition that a first element is strictly less than a second element which is in turn less than or equal to the first is always false.*)\nLemma lt_le_asym x y : x < y <= x = false.\n\n(*This lemma states that the proposition that a first element is less than or equal to a second element which is in turn strictly less than the first is always false.*)\nLemma le_lt_asym x y : x <= y < x = false.\n\n(*This lemma states that if a finite sequence of elements forms a 'less than or equal to' path starting from a given initial element, then every element in that sequence is greater than or equal to the initial element.*)\nLemma le_path_min x s : path <=%O x s -> all (>= x) s.\n\n(*This lemma states that if a finite sequence of elements forms a 'strictly less than' path starting from a given initial element, then every element in that sequence is strictly greater than the initial element.*)\nLemma lt_path_min x s : path <%O x s -> all (> x) s.\n\n(*This lemma states that a finite sequence of elements forms a 'less than or equal to' path starting from a given initial element if and only if two conditions hold: all elements in the sequence are greater than or equal to the initial element, and the sequence itself is sorted in non-decreasing order.*)\nLemma le_path_sortedE x s : path <=%O x s = all (>= x) s && sorted <=%O s.\n\n(*This lemma states that a finite sequence of elements forms a 'strictly less than' path starting from a given initial element if and only if two conditions hold: all elements in the sequence are strictly greater than the initial element, and the sequence itself is sorted in strictly increasing order.*)\nLemma lt_path_sortedE x s : path <%O x s = all (> x) s && sorted <%O s.\n\n(*This lemma states that a finite sequence is sorted in non-decreasing order if and only if the 'less than or equal to' relation holds for every pair of adjacent elements in the sequence.*)\nLemma le_sorted_pairwise s : sorted <=%O s = pairwise <=%O s.\n\n(*This lemma states that a finite sequence is sorted in strictly increasing order if and only if the 'strictly less than' relation holds for every pair of adjacent elements in the sequence.*)\nLemma lt_sorted_pairwise s : sorted <%O s = pairwise <%O s.\n\n(*This lemma states that the 'less than or equal to' path relation holding for an element and a sequence is equivalent to the pairwise 'less than or equal to' relation holding for the new sequence formed by prepending the element to the original sequence.*)\nLemma le_path_pairwise x s : path <=%O x s = pairwise <=%O (x :: s).\n\n(*This lemma states that the 'less than' path relation holding for an element and a sequence is equivalent to the pairwise 'less than' relation holding for the new sequence formed by prepending the element to the original sequence.*)\nLemma lt_path_pairwise x s : path <%O x s = pairwise <%O (x :: s).\n\n(*This lemma states that if a sequence is sorted in strictly increasing order, then it contains no duplicate elements and is also sorted in non-decreasing order.*)\nLemma lt_sorted_is_uniq_le s : sorted <%O s -> uniq s && sorted <=%O s.\n\n(*This lemma states that if a sequence is sorted in non-decreasing order, then any subsequence created by applying a boolean mask will also be sorted in non-decreasing order.*)\nLemma le_sorted_mask m s : sorted <=%O s -> sorted <=%O (mask m s).\n\n(*This lemma states that if a sequence is sorted in strictly increasing order, then any subsequence created by applying a boolean mask will also be sorted in strictly increasing order.*)\nLemma lt_sorted_mask m s : sorted <%O s -> sorted <%O (mask m s).\n\n(*This lemma states that if a sequence is sorted in non-decreasing order, then any subsequence created by filtering its elements with a predicate will also be sorted in non-decreasing order.*)\nLemma le_sorted_filter a s : sorted <=%O s -> sorted <=%O (filter a s).\n\n(*This lemma states that if a sequence is sorted in strictly increasing order, then any subsequence created by filtering its elements with a predicate will also be sorted in strictly increasing order.*)\nLemma lt_sorted_filter a s : sorted <%O s -> sorted <%O (filter a s).\n\n(*This lemma states that if the 'less than or equal to' path relation holds for an element and a sequence, then this relation also holds for that element and any subsequence formed by applying a boolean mask to the original sequence.*)\nLemma le_path_mask x m s : path <=%O x s -> path <=%O x (mask m s).\n\n(*This lemma states that if the 'less than' path relation holds for an element and a sequence, then this relation also holds for that element and any subsequence formed by applying a boolean mask to the original sequence.*)\nLemma lt_path_mask x m s : path <%O x s -> path <%O x (mask m s).\n\n(*This lemma states that if the 'less than or equal to' path relation holds for an element and a sequence, then this relation also holds for that element and any subsequence formed by filtering the original sequence with a predicate.*)\nLemma le_path_filter x a s : path <=%O x s -> path <=%O x (filter a s).\n\n(*This lemma states that if the 'less than' path relation holds for an element and a sequence, then this relation also holds for that element and any subsequence formed by filtering the original sequence with a predicate.*)\nLemma lt_path_filter x a s : path <%O x s -> path <%O x (filter a s).\n\n(*This lemma states that for any non-decreasingly sorted sequence, the function that retrieves an element by its index is monotonic; if one index is strictly less than another, the element at the first index is less than or equal to the element at the second index.*)\nLemma le_sorted_ltn_nth (x0 : T) (s : seq T) : sorted <=%O s ->\n {in [pred n | (n < size s)%N] &,\n {homo nth x0 s : i j / (i < j)%N >-> i <= j}}.\n\n(*This lemma states that for any non-decreasingly sorted sequence, the function that retrieves an element by its index is monotonic; if one index is less than or equal to another, the element at the first index is less than or equal to the element at the second index.*)\nLemma le_sorted_leq_nth (x0 : T) (s : seq T) : sorted <=%O s ->\n {in [pred n | (n < size s)%N] &,\n {homo nth x0 s : i j / (i <= j)%N >-> i <= j}}.\n\n(*This lemma states that for any strictly increasing sequence, the function that retrieves an element by its index is non-decreasing; if one index is less than or equal to another, the element at the first index is less than or equal to the element at the second index.*)\nLemma lt_sorted_leq_nth (x0 : T) (s : seq T) : sorted <%O s ->\n {in [pred n | (n < size s)%N] &,\n {mono nth x0 s : i j / (i <= j)%N >-> i <= j}}.\n\n(*This lemma states that for any strictly increasing sequence, the function that retrieves an element by its index is strictly monotonic; if one index is strictly less than another, the element at the first index is strictly less than the element at the second index.*)\nLemma lt_sorted_ltn_nth (x0 : T) (s : seq T) : sorted <%O s ->\n {in [pred n | (n < size s)%N] &,\n {mono nth x0 s : i j / (i < j)%N >-> i < j}}.\n\n(*This lemma states that if a 'less than or equal to' path relation holds for an element and a sequence, then this relation also holds for the element and any subsequence of that sequence.*)\nLemma subseq_le_path x s1 s2 : subseq s1 s2 -> path <=%O x s2 -> path <=%O x s1.\n\n(*This lemma states that if a 'less than' path relation holds for an element and a sequence, then this relation also holds for the element and any subsequence of that sequence.*)\nLemma subseq_lt_path x s1 s2 : subseq s1 s2 -> path <%O x s2 -> path <%O x s1.\n\n(*This lemma states that if a sequence is sorted in non-decreasing order, then any of its subsequences is also sorted in non-decreasing order.*)\nLemma subseq_le_sorted s1 s2 : subseq s1 s2 -> sorted <=%O s2 -> sorted <=%O s1.\n\n(*This lemma states that if a sequence is sorted in strictly increasing order, then any of its subsequences is also sorted in strictly increasing order.*)\nLemma subseq_lt_sorted s1 s2 : subseq s1 s2 -> sorted <%O s2 -> sorted <%O s1.\n\n(*This lemma states that any sequence sorted in strictly increasing order contains no duplicate elements.*)\nLemma lt_sorted_uniq s : sorted <%O s -> uniq s.\n\n(*This lemma states that if two strictly increasing sorted sequences contain the same elements with the same multiplicities, then the two sequences are identical.*)\nLemma lt_sorted_eq s1 s2 :\n sorted <%O s1 -> sorted <%O s2 -> s1 =i s2 -> s1 = s2.\n\n(*This lemma states that for a strictly increasing sequence, filtering the sequence to keep only elements that are strictly less than the element at a given valid index results in the prefix of the sequence up to that index.*)\nLemma filter_lt_nth x0 s i : sorted <%O s -> (i < size s)%N ->\n [seq x <- s | x < nth x0 s i] = take i s.\n\n(*This lemma states that for a strictly increasing sequence, the number of elements that are strictly less than the element at a given valid index is equal to that index.*)\nLemma count_lt_nth x0 s i : sorted <%O s -> (i < size s)%N ->\n count (< nth x0 s i) s = i.\n\n(*This lemma states that for a strictly increasing sequence, filtering the sequence to keep only elements that are less than or equal to the element at a given valid index results in the prefix of the sequence of length index plus one.*)\nLemma filter_le_nth x0 s i : sorted <%O s -> (i < size s)%N ->\n [seq x <- s | x <= nth x0 s i] = take i.+1 s.\n\n(*This lemma states that for a strictly increasing sequence, the number of elements that are less than or equal to the element at a given valid index is equal to that index plus one.*)\nLemma count_le_nth x0 s i : sorted <%O s -> (i < size s)%N ->\n count (<= nth x0 s i) s = i.+1.\n\n(*This lemma states that for a non-decreasingly sorted sequence, filtering it to retain only elements strictly less than a given value is equivalent to taking a prefix of the sequence, where the length of the prefix is the number of elements strictly less than that value.*)\nLemma sorted_filter_lt x s :\n sorted <=%O s -> [seq y <- s | y < x] = take (count (< x) s) s.\n\n(*This lemma states that for a non-decreasingly sorted sequence, filtering it to retain only elements less than or equal to a given value is equivalent to taking a prefix of the sequence, where the length of the prefix is the number of elements less than or equal to that value.*)\nLemma sorted_filter_le x s :\n sorted <=%O s -> [seq y <- s | y <= x] = take (count (<= x) s) s.\n\n(*This lemma states that for any element in a non-decreasingly sorted sequence, if its index is less than the total count of elements less than or equal to a given value, then that element itself must be less than or equal to the given value.*)\nLemma nth_count_le x x0 s i : sorted <=%O s ->\n (i < count (<= x) s)%N -> nth x0 s i <= x.\n\n(*This lemma states that for any element in a non-decreasingly sorted sequence, if its index is less than the total count of elements strictly less than a given value, then that element itself must be strictly less than the given value.*)\nLemma nth_count_lt x x0 s i : sorted <=%O s ->\n (i < count (< x) s)%N -> nth x0 s i < x.\n\n(*This lemma states that sorting a sequence that is already sorted in non-decreasing order results in the original sequence, demonstrating the idempotence of the sorting function.*)\nLemma sort_le_id s : sorted <=%O s -> sort <=%O s = s.\n\n(*This lemma states that if a finite sequence is already sorted according to a given order, then applying the sorting function to this sequence returns the sequence unchanged.*)\nLemma sort_lt_id s : sorted <%O s -> sort <%O s = s.\n\n(*This lemma states that for any two comparable elements, the first element is less than or equal to the second if and only if it is not the case that the second element is strictly less than the first.*)\nLemma comparable_leNgt x y : x >=< y -> (x <= y) = ~~ (y < x).\n\n(*This lemma states that for any two comparable elements, the first element is strictly less than the second if and only if it is not the case that the second element is less than or equal to the first.*)\nLemma comparable_ltNge x y : x >=< y -> (x < y) = ~~ (y <= x).\n\n(*This lemma states that the property of two elements being comparable is symmetric; that is, one element is comparable to a second if and only if the second element is comparable to the first.*)\nLemma comparable_sym x y : (y >=< x) = (x >=< y).\n\n(*This lemma states that any element is always comparable to itself.*)\nLemma comparablexx x : x >=< x.\n\n(*This lemma states that if two elements are incomparable, then they cannot be equal.*)\nLemma incomparable_eqF x y : (x >< y) -> (x == y) = false.\n\n(*This lemma states that if two elements are incomparable, then it is false that the first element is less than or equal to the second.*)\nLemma incomparable_leF x y : (x >< y) -> (x <= y) = false.\n\n(*This lemma states that if two elements are incomparable, then it is false that the first element is strictly less than the second.*)\nLemma incomparable_ltF x y : (x >< y) -> (x < y) = false.\n\n(*This lemma states that if a first element is less than or equal to a second element, then these two elements are comparable.*)\nLemma le_comparable (x y : T) : x <= y -> x >=< y.\n\n(*This lemma states that if a first element is strictly less than a second element, then these two elements are comparable.*)\nLemma lt_comparable (x y : T) : x < y -> x >=< y.\n\n(*This lemma states that if a second element is less than or equal to a first element, then these two elements are comparable.*)\nLemma ge_comparable (x y : T) : y <= x -> x >=< y.\n\n(*This lemma states that if a second element is strictly less than a first element, then these two elements are comparable.*)\nLemma gt_comparable (x y : T) : y < x -> x >=< y.\n\n(*This lemma states that an element is conditionally less than or equal to itself if and only if the given boolean condition is true.*)\nLemma leif_refl x C : reflect (x <= x ?= iff C) C.\n\n(*This lemma states that if a conditional less-than-or-equal comparison between two elements holds, an equality test between the elements evaluates to the same boolean as the condition, typically in a context where the elements are not strictly ordered.*)\nLemma eq_leif x y C : x <= y ?= iff C -> (x == y) = C.\n\n(*This lemma asserts that if a conditional less-than-or-equal comparison between two elements holds, and the condition itself is true, then the two elements must be equal.*)\nLemma eqTleif x y C : x <= y ?= iff C -> C -> x = y.\n\n(*This lemma establishes a transitivity property for the conditional less-than relation, stating that if a first element is conditionally less than a second, and the second is conditionally less than a third, then the first is conditionally less than the third under the conjunction of the two boolean conditions.*)\nLemma lteif_trans x y z C1 C2 :\n x < y ?<= if C1 -> y < z ?<= if C2 -> x < z ?<= if C1 && C2.\n\n(*This lemma states that an element is conditionally less than itself if and only if the given boolean condition is true.*)\nLemma lteifxx x C : (x < x ?<= if C) = C.\n\n(*This lemma provides a form of anti-symmetry for the conditional less-than relation. It states that if a second element is conditionally less than a first under a negated boolean condition, then it is false that the first element is conditionally less than the second under the original boolean condition.*)\nLemma lteifNF x y C : y < x ?<= if ~~ C -> x < y ?<= if C = false.\n\n(*This lemma states that if a first element is strictly less than a second element, then it is also conditionally less than the second element, regardless of the boolean condition.*)\nLemma lteifS x y C : x < y -> x < y ?<= if C.\n\n(*This lemma shows that the conditional less-than relation, when the condition is true, is equivalent to the standard less-than-or-equal relation.*)\nLemma lteifT x y : x < y ?<= if true = (x <= y). \n\n(*This lemma shows that the conditional less-than relation, when the condition is false, is equivalent to the standard strict less-than relation.*)\nLemma lteifF x y : x < y ?<= if false = (x < y). \n\n(*This lemma states that the conditional less-than relation distributes over boolean disjunction. That is, an element is conditionally less than another under a disjunction of two conditions if and only if it is conditionally less than it under the first condition or under the second condition.*)\nLemma lteif_orb x y : {morph lteif x y : p q / p || q}.\n\n(*This lemma states that the conditional less-than relation respects boolean conjunction. That is, an element is conditionally less than another under a conjunction of two conditions if and only if it is conditionally less than it under the first condition and also under the second condition.*)\nLemma lteif_andb x y : {morph lteif x y : p q / p && q}.\n\n(*This lemma shows that the conditional less-than relation is monotonic with respect to its boolean condition. If a first boolean condition implies a second one, then a conditional relation holding under the first condition also holds under the second.*)\nLemma lteif_imply C1 C2 x y : C1 ==> C2 -> x < y ?<= if C1 -> x < y ?<= if C2.\n\n(*This lemma states that if a conditional less-than relation holds between two elements, then the corresponding non-strict less-than-or-equal relation also holds between them.*)\nLemma lteifW C x y : x < y ?<= if C -> x <= y.\n\n(*This lemma states that if a first element is strictly less than a second, then the conditional less-than relation also holds between them for any boolean condition.*)\nLemma ltrW_lteif C x y : x < y -> x < y ?<= if C.\n\n(*This lemma provides a definitional equivalence for the minimum of two elements. The minimum is the first element if it is strictly less than the second, and the second element otherwise.*)\nLemma minElt x y : min x y = if x < y then x else y. \n(*This lemma provides a definitional equivalence for the maximum of two elements. The maximum is the second element if the first is strictly less than it, and the first element otherwise.*)\nLemma maxElt x y : max x y = if x < y then y else x. \n\n(*This lemma states that the minimum operation is idempotent, meaning that the minimum of an element with itself is that same element.*)\nLemma minxx : idempotent_op (min : T -> T -> T).\n\n(*This lemma states that the maximum operation is idempotent, meaning that the maximum of an element with itself is that same element.*)\nLemma maxxx : idempotent_op (max : T -> T -> T).\n\n(*This lemma states that for any two elements from an ordered type, the minimum of the second element and the minimum of both elements is equal to the minimum of both elements.*)\nLemma min_minKx x y : min (min x y) y = min x y.\n\n(*This lemma states that for any two elements from an ordered type, the minimum of the first element and the minimum of both elements is equal to the minimum of both elements.*)\nLemma min_minxK x y : min x (min x y) = min x y.\n\n(*This lemma states that for any two elements from an ordered type, the maximum of the second element and the maximum of both elements is equal to the maximum of both elements.*)\nLemma max_maxKx x y : max (max x y) y = max x y.\n\n(*This lemma states that for any two elements from an ordered type, the maximum of the first element and the maximum of both elements is equal to the maximum of both elements.*)\nLemma max_maxxK x y : max x (max x y) = max x y.\n\n(*This lemma states that if an element from an ordered type is comparable to all other elements, then it is also comparable to the minimum of any two elements from that type.*)\nLemma comparable_minl z : {in >=< z &, forall x y, min x y >=< z}.\n\n(*This lemma states that if an element from an ordered type is comparable to all other elements, then it is also comparable to the minimum of any two elements from that type.*)\nLemma comparable_minr z : {in >=<%O z &, forall x y, z >=< min x y}.\n\n(*This lemma states that if an element from an ordered type is comparable to all other elements, then it is also comparable to the maximum of any two elements from that type.*)\nLemma comparable_maxl z : {in >=< z &, forall x y, max x y >=< z}.\n\n(*This lemma states that if an element from an ordered type is comparable to all other elements, then it is also comparable to the maximum of any two elements from that type.*)\nLemma comparable_maxr z : {in >=<%O z &, forall x y, z >=< max x y}.\n\nSection Comparable2.\nVariables (z x y : T) (cmp_xy : x >=< y).\n\n(*This lemma states that for three elements where the second and third are comparable, the first element is less than or equal to the minimum of the second and third if and only if it is less than or equal to both of them individually.*)\nLemma comparable_le_min : (z <= min x y) = (z <= x) && (z <= y).\n\n(*This lemma states that for three elements where the first two are comparable, their minimum is less than or equal to the third element if and only if at least one of the first two elements is less than or equal to the third.*)\nLemma comparable_ge_min : (min x y <= z) = (x <= z) || (y <= z).\n\n(*This lemma states that for three elements where the second and third are comparable, the first element is strictly less than the minimum of the second and third if and only if it is strictly less than both of them individually.*)\nLemma comparable_lt_min : (z < min x y) = (z < x) && (z < y).\n\n(*This lemma states that for three elements where the first two are comparable, their minimum is strictly less than the third element if and only if at least one of the first two elements is strictly less than the third.*)\nLemma comparable_gt_min : (min x y < z) = (x < z) || (y < z).\n\n(*This lemma states that for three elements where the second and third are comparable, the first element is less than or equal to the maximum of the second and third if and only if it is less than or equal to at least one of them.*)\nLemma comparable_le_max : (z <= max x y) = (z <= x) || (z <= y).\n\n(*This lemma states that for three elements where the first two are comparable, their maximum is less than or equal to the third element if and only if both of the first two elements are less than or equal to the third.*)\nLemma comparable_ge_max : (max x y <= z) = (x <= z) && (y <= z).\n\n(*This lemma states that for three elements where the second and third are comparable, the first element is strictly less than the maximum of the second and third if and only if it is strictly less than at least one of them.*)\nLemma comparable_lt_max : (z < max x y) = (z < x) || (z < y).\n\n(*This lemma states that for three elements where the first two are comparable, their maximum is strictly less than the third element if and only if both of the first two elements are strictly less than the third.*)\nLemma comparable_gt_max : (max x y < z) = (x < z) && (y < z).\n\n(*This lemma states that for two comparable elements from an ordered type, the maximum of the second element and the minimum of both elements is equal to the second element.*)\nLemma comparable_minxK : max (min x y) y = y.\n\n(*This lemma states that for two comparable elements, the maximum of the first element and the minimum of both elements is equal to the first element.*)\nLemma comparable_minKx : max x (min x y) = x.\n\n(*This lemma states that for two comparable elements, the minimum of the maximum of both elements and the second element is equal to the second element.*)\nLemma comparable_maxxK : min (max x y) y = y.\n\n(*This lemma states that for two comparable elements, the minimum of the first element and the maximum of both elements is equal to the first element.*)\nLemma comparable_maxKx : min x (max x y) = x.\n\n(*This lemma states that for three comparable elements and a boolean condition, a third element satisfies a conditional comparison, being strictly less than or less than or equal to, the minimum of the first two elements if and only if it satisfies that same comparison with both the first and the second elements individually.*)\nLemma comparable_lteif_minr C :\n (z < min x y ?<= if C) = (z < x ?<= if C) && (z < y ?<= if C).\n\n(*This lemma states that for three comparable elements and a boolean condition, the minimum of the first two elements satisfies a conditional comparison, being strictly less than or less than or equal to, a third element if and only if at least one of the first two elements satisfies that same comparison with the third element.*)\nLemma comparable_lteif_minl C :\n (min x y < z ?<= if C) = (x < z ?<= if C) || (y < z ?<= if C).\n\n(*This lemma states that for three comparable elements and a boolean condition, a third element satisfies a conditional comparison, being strictly less than or less than or equal to, the maximum of the first two elements if and only if it satisfies that same comparison with at least one of the first two elements.*)\nLemma comparable_lteif_maxr C :\n (z < max x y ?<= if C) = (z < x ?<= if C) || (z < y ?<= if C).\n\n(*This lemma states that for three comparable elements and a boolean condition, the maximum of the first two elements satisfies a conditional comparison, being strictly less than or less than or equal to, a third element if and only if both of the first two elements satisfy that same comparison with the third element.*)\nLemma comparable_lteif_maxl C :\n (max x y < z ?<= if C) = (x < z ?<= if C) && (y < z ?<= if C).\n\nEnd Comparable2.\n\nSection Comparable3.\nVariables (x y z : T) (cmp_xy : x >=< y) (cmp_xz : x >=< z) (cmp_yz : y >=< z).\n\n(*This lemma states that for three mutually comparable elements, the minimum operation is associative.*)\nLemma comparable_minA : min x (min y z) = min (min x y) z.\n\n(*This lemma states that for three mutually comparable elements, the maximum operation is associative.*)\nLemma comparable_maxA : max x (max y z) = max (max x y) z.\n\n(*This lemma states that for three mutually comparable elements, the minimum of the maximum of the first two elements and a third element is equal to the maximum of two values: the minimum of the first and third elements, and the minimum of the second and third elements.*)\nLemma comparable_min_maxl : min (max x y) z = max (min x z) (min y z).\n\n(*This lemma states that for three mutually comparable elements, the maximum of an element and the minimum of two other elements is equal to the minimum of two values: the maximum of the first and second elements, and the maximum of the first and third elements.*)\nLemma comparable_max_minr :\n max x (min y z) = min (max x y) (max x z).\n\nEnd Comparable3.\n\nSection ArgExtremum.\n\nContext (I : finType) (i0 : I) (P : {pred I}) (F : I -> T) (Pi0 : P i0).\nHypothesis F_comparable : {in P &, forall i j, F i >=< F j}.\n\n(*This lemma states that for a function over a finite domain whose values are all mutually comparable, the element returned by the argument minimum operator satisfies the specification of a minimum; that is, it fulfills a given predicate, and its function value is less than or equal to the function value of any other domain element that also fulfills the predicate.*)\nLemma comparable_arg_minP: extremum_spec <=%O P F (arg_min i0 P F).\n\n(*This lemma states that for a function over a finite domain whose values are all mutually comparable, the element returned by the argument maximum operator satisfies the specification of a maximum; that is, it fulfills a given predicate, and its function value is greater than or equal to the function value of any other domain element that also fulfills the predicate.*)\nLemma comparable_arg_maxP: extremum_spec >=%O P F (arg_max i0 P F).\n\nEnd ArgExtremum.\n\n(*This lemma states that if a binary operator preserves comparability with a given reference element for all its inputs, an initial value is comparable with the reference element, and a function's values are all comparable with the reference element, then the result of folding the operator over the function's values is also comparable with the reference element.*)\nLemma comparable_bigl x x0 op I (P : pred I) F (s : seq I) :\n {in >=< x &, forall y z, op y z >=< x} -> x0 >=< x ->\n {in P, forall i, F i >=< x} -> \\big[op/x0]_(i <- s | P i) F i >=< x.\n\n(*This lemma states that if a binary operator preserves comparability with a given reference element for all its inputs, an initial value is comparable with the reference element, and a function's values are all comparable with the reference element, then the reference element is comparable with the result of folding the operator over the function's values.*)\nLemma comparable_bigr x x0 op I (P : pred I) F (s : seq I) :\n {in >=<%O x &, forall y z, x >=< op y z} -> x >=< x0 ->\n {in P, forall i, x >=< F i} -> x >=< \\big[op/x0]_(i <- s | P i) F i.\n\nSection bigminmax.\n\nVariables (I : Type) (r : seq I) (f : I -> T) (x0 x : T) (P : pred I).\n\n(*This lemma states that if an element is strictly greater than an initial value and also strictly greater than all values produced by a function over a sequence, then it is also strictly greater than the maximum of those values computed using the given initial value.*)\nLemma bigmax_lt : x0 < x -> (forall i, P i -> f i < x) ->\n \\big[max/x0]_(i <- r | P i) f i < x.\n\n(*This lemma states that if an element is strictly less than an initial value and also strictly less than all values produced by a function over a sequence, then it is also strictly less than the minimum of those values computed using the given initial value.*)\nLemma lt_bigmin : x < x0 -> (forall i, P i -> x < f i) ->\n x < \\big[min/x0]_(i <- r | P i) f i.\n\nEnd bigminmax.\n\nEnd PreorderTheory.\n#[global] Hint Resolve comparable_minr comparable_minl : core.\n#[global] Hint Resolve comparable_maxr comparable_maxl : core.\n\nSection ContraTheory.\nContext {disp1 disp2 : disp_t} {T1 : preorderType disp1} {T2 : preorderType disp2}.\nImplicit Types (x y : T1) (z t : T2) (b : bool) (m n : nat) (P : Prop).\n\n(*This lemma provides a contrapositive-style argument for comparable elements, stating that if the second element being strictly less than the first implies the double negation of a boolean, then that boolean being true implies the first element is less than or equal to the second.*)\nLemma comparable_contraTle b x y : x >=< y -> (y < x -> ~~ b) -> (b -> x <= y).\n\n(*This lemma provides a contrapositive-style argument for comparable elements, stating that if the second element being less than or equal to the first implies the double negation of a boolean, then that boolean being true implies the first element is strictly less than the second.*)\nLemma comparable_contraTlt b x y : x >=< y -> (y <= x -> ~~ b) -> (b -> x < y).\n\n(*This lemma provides a contrapositive argument for comparable elements, stating that if the second element being strictly less than the first implies the negation of a proposition, then that proposition being true implies the first element is less than or equal to the second.*)\nLemma comparable_contraPle P x y : x >=< y -> (y < x -> ~ P) -> (P -> x <= y).\n\n(*This lemma provides a contrapositive argument for comparable elements, stating that if the second element being less than or equal to the first implies the negation of a proposition, then that proposition being true implies the first element is strictly less than the second.*)\nLemma comparable_contraPlt P x y : x >=< y -> (y <= x -> ~ P) -> (P -> x < y).\n\n(*This lemma provides a contrapositive argument for comparable elements, stating that if the second element being strictly less than the first implies a boolean is true, then the double negation of that boolean being true implies the first element is less than or equal to the second.*)\nLemma comparable_contraNle b x y : x >=< y -> (y < x -> b) -> (~~ b -> x <= y).\n\n(*This lemma provides a contrapositive argument for comparable elements, stating that if the second element being less than or equal to the first implies a boolean is true, then the double negation of that boolean being true implies the first element is strictly less than the second.*)\nLemma comparable_contraNlt b x y : x >=< y -> (y <= x -> b) -> (~~ b -> x < y).\n\n(*This lemma provides a contrapositive argument for comparable elements, stating that if the second element being strictly less than the first implies a proposition, then the negation of that proposition implies the first element is less than or equal to the second.*)\nLemma comparable_contra_not_le P x y : x >=< y -> (y < x -> P) -> (~ P -> x <= y).\n\n(*This lemma provides a contrapositive argument for comparable elements, stating that if the second element being less than or equal to the first implies a proposition, then the negation of that proposition implies the first element is strictly less than the second.*)\nLemma comparable_contra_not_lt P x y : x >=< y -> (y <= x -> P) -> (~ P -> x < y).\n\n(*This lemma provides a contrapositive argument for comparable elements using a boolean, stating that if the second element being strictly less than the first implies a boolean is true, then that boolean being false implies the first element is less than or equal to the second.*)\nLemma comparable_contraFle b x y : x >=< y -> (y < x -> b) -> (b = false -> x <= y).\n\n(*This lemma provides a contrapositive argument for comparable elements using a boolean, stating that if the second element being less than or equal to the first implies a boolean is true, then that boolean being false implies the first element is strictly less than the second.*)\nLemma comparable_contraFlt b x y : x >=< y -> (y <= x -> b) -> (b = false -> x < y).\n\n(*This lemma provides a specialized contrapositive argument using natural number comparison. It asserts that if two elements are comparable, and the second being strictly less than the first implies a strict inequality between two natural numbers, then the corresponding non-strict inequality between those numbers implies the first element is less than or equal to the second.*)\nLemma comparable_contra_leq_le m n x y : x >=< y ->\n (y < x -> (n < m)%N) -> ((m <= n)%N -> x <= y).\n\n(*This lemma provides a specialized contrapositive argument using natural number comparison. It asserts that if two elements are comparable, and the second being less than or equal to the first implies a strict inequality between two natural numbers, then the corresponding non-strict inequality between those numbers implies the first element is strictly less than the second.*)\nLemma comparable_contra_leq_lt m n x y : x >=< y ->\n (y <= x -> (n < m)%N) -> ((m <= n)%N -> x < y).\n\n(*This lemma states that for any two comparable elements in a preordered type and any two natural numbers, if the second element being strictly less than the first implies that the second natural number is less than or equal to the first, then the first natural number being strictly less than the second implies that the first element is less than or equal to the second.*)\nLemma comparable_contra_ltn_le m n x y : x >=< y ->\n (y < x -> (n <= m)%N) -> ((m < n)%N -> x <= y).\n\n(*This lemma states that for any two comparable elements in a preordered type and any two natural numbers, if the second element being less than or equal to the first implies that the second natural number is less than or equal to the first, then the first natural number being strictly less than the second implies that the first element is strictly less than the second.*)\nLemma comparable_contra_ltn_lt m n x y : x >=< y ->\n (y <= x -> (n <= m)%N) -> ((m < n)%N -> x < y).\n\n(*This lemma states that for any four elements in a preordered type, if the third and fourth elements are comparable, and if the fourth being strictly less than the third implies that the second is strictly less than the first, then the first being less than or equal to the second implies that the third is less than or equal to the fourth.*)\nLemma comparable_contra_le x y z t : z >=< t ->\n (t < z -> y < x) -> (x <= y -> z <= t).\n\n(*This lemma states that for any four elements in a preordered type, if the third and fourth elements are comparable, and if the fourth being less than or equal to the third implies that the second is strictly less than the first, then the first being less than or equal to the second implies that the third is strictly less than the fourth.*)\nLemma comparable_contra_le_lt x y z t : z >=< t ->\n (t <= z -> y < x) -> (x <= y -> z < t).\n\n(*This lemma states that for any four elements in a preordered type, if the third and fourth elements are comparable, and if the fourth being strictly less than the third implies that the second is less than or equal to the first, then the first being strictly less than the second implies that the third is less than or equal to the fourth.*)\nLemma comparable_contra_lt_le x y z t : z >=< t ->\n (t < z -> y <= x) -> (x < y -> z <= t).\n\n(*This lemma states that for any four elements in a preordered type, if the third and fourth elements are comparable, and if the fourth being less than or equal to the third implies that the second is less than or equal to the first, then the first being strictly less than the second implies that the third is strictly less than the fourth.*)\nLemma comparable_contra_lt x y z t : z >=< t ->\n (t <= z -> y <= x) -> (x < y -> z < t).\n\nEnd ContraTheory.\n\nSection PreorderMonotonyTheory.\n\nContext {disp disp' : disp_t}.\nContext {T : preorderType disp} {T' : preorderType disp'}.\nImplicit Types (m n p : nat) (x y z : T) (u v w : T').\nVariables (D D' : {pred T}) (f : T -> T').\n\nHint Resolve lexx lt_le_def : core.\n\n(*This lemma states that a function that is monotonic with respect to the less-than-or-equal relation is also monotonic with respect to the strictly-less-than relation.*)\nLemma leW_mono : {mono f : x y / x <= y} -> {mono f : x y / x < y}.\n\n(*This lemma states that a function that is monotonic with respect to the boolean less-than-or-equal relation is also monotonic with respect to the boolean strictly-less-than relation.*)\nLemma leW_nmono : {mono f : x y /~ x <= y} -> {mono f : x y /~ x < y}.\n\n(*This lemma states that if a function is monotonic with respect to the less-than-or-equal relation for all elements within a given domain, it is also monotonic with respect to the strictly-less-than relation for those elements.*)\nLemma leW_mono_in :\n {in D &, {mono f : x y / x <= y}} -> {in D &, {mono f : x y / x < y}}.\n\n(*This lemma states that if a function is monotonic with respect to the boolean less-than-or-equal relation for all elements within a given domain, it is also monotonic with respect to the boolean strictly-less-than relation for those elements.*)\nLemma leW_nmono_in :\n {in D &, {mono f : x y /~ x <= y}} -> {in D &, {mono f : x y /~ x < y}}.\n\nEnd PreorderMonotonyTheory.\n\nEnd PreorderTheory.\n\n#[global] Hint Resolve lexx le_refl ltxx lt_irreflexive ltW lt_eqF : core.\n\nArguments leif_refl {disp T x C}.\n\nModule Import BPreorderTheory.\nSection BPreorderTheory.\nContext {disp : disp_t} {T : bPreorderType disp}.\nImplicit Types (x y : T).\n\n(*This lemma states that the bottom element of a preordered type with a bottom element is less than or equal to any other element.*)\nLemma le0x x : \\bot <= x. \n\n(*This lemma states that no element of a preordered type with a bottom element can be strictly less than the bottom element.*)\nLemma ltx0 x : (x < \\bot) = false.\n\nEnd BPreorderTheory.\nEnd BPreorderTheory.\n\nModule Import TPreorderTheory.\nSection TPreorderTheory.\nContext {disp : disp_t} {T : tPreorderType disp}.\nImplicit Types (x y : T).\n\n(*This lemma states that any element of a preordered type with a top element is less than or equal to the top element.*)\nLemma lex1 x : x <= \\top. \n(*This lemma states that the top element of a preordered type with a top element cannot be strictly less than any other element.*)\nLemma lt1x x : (\\top < x) = false. \n\nEnd TPreorderTheory.\nEnd TPreorderTheory.\n\n#[global] Hint Extern 0 (is_true (\\bot <= _)) => exact: le0x : core.\n#[global] Hint Extern 0 (is_true (_ <= \\top)) => exact: lex1 : core.\n\n(*This record defines the structure of a preorder, specifying a less-than-or-equal relation, a strictly-less-than relation derived from it, and requiring that the less-than-or-equal relation is both reflexive and transitive.*)\nHB.factory Record isPreorder (d : disp_t) T of Equality T := {\n le : rel T;\n lt : rel T;\n lt_def : forall x y, lt x y = (le x y) && ~~ (le y x);\n le_refl : reflexive le;\n le_trans : transitive le;\n}.\n\nHB.builders Context (d : disp_t) T of isPreorder d T.\n\n(*This definition establishes that the greater-than-or-equal relation, defined as the inverse of the less-than-or-equal relation, is transitive.*)\nLet ge_trans : transitive (fun x y => le y x).\n\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := @isDuallyPreorder.Build d T\n le _ lt_def (fun x y => lt_def y x) le_refl le_refl le_trans ge_trans.\nHB.end.\n\n(*This record provides a factory for defining a preorder structure, requiring only a less-than-or-equal relation along with proofs of its reflexivity and transitivity.*)\nHB.factory Record Le_isPreorder (d : disp_t) T of Equality T := {\n le : rel T;\n le_refl : reflexive le;\n le_trans : transitive le;\n}.\n\nHB.builders Context (d : disp_t) T of Le_isPreorder d T.\n\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := @isPreorder.Build d T\n le _ (fun _ _ => erefl) le_refl le_trans.\nHB.end.\n\n(*This record provides a factory for defining a preorder structure from a strictly-less-than relation, where the less-than-or-equal relation is defined as the disjunction of equality and the strictly-less-than relation, which must be irreflexive and transitive.*)\nHB.factory Record LtLe_isPreorder (d : disp_t) T of Equality T := {\n le : rel T;\n lt : rel T;\n le_def : forall x y, le x y = (x == y) || lt x y;\n lt_irr : irreflexive lt;\n lt_trans : transitive lt;\n}.\nHB.builders Context (d : disp_t) T of LtLe_isPreorder d T.\n\n(*This definition establishes the reflexivity of the less-than-or-equal relation, showing that any element is less than or equal to itself.*)\nLet le_refl : reflexive le. \n\n(*This definition establishes the transitivity of the less-than-or-equal relation, derived from the transitivity of the strictly-less-than relation and properties of equality.*)\nLet le_trans : transitive le.\n\n(*This definition shows that the strictly-less-than relation is equivalent to the conjunction of the less-than-or-equal relation and the negation of the converse less-than-or-equal relation.*)\nLet lt_le_def x y : lt x y = (le x y) && ~~ (le y x).\n\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := @isPreorder.Build d T\n le lt lt_le_def le_refl le_trans .\n\nHB.end.\n\n(*This record provides a factory for defining a preorder structure based solely on a strictly-less-than relation, which must be irreflexive and transitive.*)\nHB.factory Record Lt_isPreorder (d : disp_t) T of Equality T := {\n lt : rel T;\n lt_irr : irreflexive lt;\n lt_trans : transitive lt;\n}.\n\nHB.builders Context (d : disp_t) (T : Type) of Lt_isPreorder d T.\n#[warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ := @LtLe_isPreorder.Build d T\n _ lt (fun _ _ => erefl) lt_irr lt_trans.\nHB.end.\n\nModule PreCancelPartial.\nSection PreCancelPartial.\nVariables (disp : disp_t) (T : choiceType).\nVariables (disp' : disp_t) (T' : preorderType disp') (f : T -> T').\n\n(*This definition introduces a less-than-or-equal relation on a source type by applying a function to its arguments and comparing the results using the order of a target preordered type.*)\nDefinition le (x y : T) := f x <= f y.\n(*This definition introduces a strictly-less-than relation on a source type by applying a function to its arguments and comparing the results using the strict order of a target preordered type.*)\nDefinition lt (x y : T) := f x < f y.\n\n(*This lemma states the reflexivity property for a preorder on a product-like type, asserting that any pair is less than or equal to itself.*)\nFact refl : reflexive le. \n(*This lemma states the transitivity property of a preorder relation on a product-like type.*)\nFact trans : transitive le. \n(*This lemma states that the greater-than-or-equal-to relation is transitive. For any three elements, if a first element is greater than or equal to a second, and the second is greater than or equal to a third, then the first element is also greater than or equal to the third.*)\nFact ge_trans : transitive (fun x y => le y x). \n(*This lemma states that the strict 'less than' relation between two elements holds if and only if the first element is less than or equal to the second, and the second element is not less than or equal to the first.*)\nFact lt_le_def x y : lt x y = le x y && ~~ le y x.\n\n(*This definition provides a canonical construction for a preorder structure. It builds the structure from a display, a type, a definition of the strict less-than relation, and proofs that the non-strict relation is reflexive and transitive.*)\nDefinition PrePcan := isPreorder.Build disp T lt_le_def refl trans.\n\nEnd PreCancelPartial.\nEnd PreCancelPartial.\n\n#[export]\nHB.instance Definition _ (disp : disp_t) (T : Type)\n (disp' : disp_t) (T' : preorderType disp') (f : T -> T')\n (f' : T' -> option T) (f_can : pcancel f f') : isPreorder disp (pcan_type f_can) :=\n @PreCancelPartial.PrePcan disp (pcan_type f_can) disp' T' f.\n\n#[export]\nHB.instance Definition _ (disp : disp_t) (T : Type)\n (disp' : disp_t) (T' : preorderType disp') (f : T -> T')\n (f' : T' -> T) (f_can : cancel f f') : isPreorder disp (can_type f_can) :=\n @PreCancelPartial.PrePcan disp (can_type f_can) disp' T' f.\n\n(*This definition specifies the property of a function between two preordered types being an order morphism. The property holds if the function is monotonic, which means that the less-than-or-equal-to relation between any two elements in the source type implies the same relation between their images in the target type.*)\nDefinition order_morphism d (T : preorderType d) d' (T' : preorderType d')\n (f : T -> T') : Prop := {mono f : x y / x <= y}.\n\n(*This record structure provides the property for a function to be an order morphism between two preordered types. It contains a proof field certifying that the function is monotonic, meaning it preserves the less-than-or-equal-to relationship.*)\nHB.mixin Record isOrderMorphism d (T : preorderType d) d' (T' : preorderType d')\n (apply : T -> T') := {\n omorph_le_subproof : {homo apply : x y / x <= y} ;\n}.\n\n(*This definition specifies the structure of an order morphism, which is a function between two preordered types that is bundled with a proof of its monotonicity. This packages the function and its order-preserving property into a single object.*)\nHB.structure Definition OrderMorphism d (T : preorderType d)\n d' (T' : preorderType d') := {f of isOrderMorphism d T d' T' f}.\n\nModule OrderMorphismExports.\n(*This notation provides a readable syntax for the type of all order-preserving functions, known as order morphisms, from a source preordered type to a target preordered type.*)\nNotation \"{ 'omorphism' T -> T' }\" :=\n (@OrderMorphism.type _ T%type _ T'%type) : type_scope.\nEnd OrderMorphismExports.\nHB.export OrderMorphismExports.\n\nModule Import OrderMorphismTheory.\nSection OrderMorphismTheory.\n\n(*This lemma states that any function with the structure of an order morphism preserves the less-than-or-equal-to relation. If one element is less than or equal to another in the source type, their images under the function will also satisfy this relation in the target type.*)\nLemma omorph_le (d : disp_t) (T : preorderType d) (d' : disp_t) (T' : preorderType d')\n(f : {omorphism T -> T'}) : {homo f : x y / x <= y}.\n\nSection IdCompFun.\n\nVariables (d : disp_t) (T : preorderType d) (d' : disp_t) (T' : preorderType d').\nVariables (d'' : disp_t) (T'' : preorderType d'').\nVariables (f : {omorphism T' -> T''}) (g : {omorphism T -> T'}).\n\n(*This fact asserts that the identity function on any preordered type is nondecreasing, which means the function preserves the less-than-or-equal-to relation between elements.*)\nFact idfun_is_nondecreasing : nondecreasing (@idfun T).\n\n#[export]\nHB.instance Definition _ := isOrderMorphism.Build d T d T idfun\n idfun_is_nondecreasing.\n\n(*This fact asserts that the composition of two nondecreasing functions is also a nondecreasing function. This property ensures that chaining order-preserving functions results in a composite function that is also order-preserving.*)\nFact comp_is_nondecreasing : nondecreasing (f \\o g).\n\n#[export]\n(*This record structure defines the property for a subtype to be a valid sub-preorder of a larger preordered type. It requires that the inclusion map from the subtype to the parent type is monotonic, ensuring the order on the subtype is compatible with the order on the parent type.*)\nHB.mixin Record isSubPreorder d (T : preorderType d) (S : pred T) d' U\n of SubType T S U & Preorder d' U := {\n le_val : {mono (val : U -> T) : x y / x <= y};\n}.\n\n#[short(type=\"subPreorder\")]\n(*This definition specifies the structure of a sub-preorder. It combines a subtype of a preordered type with its own preorder structure, along with a proof that this new structure is a valid sub-preorder, meaning its order is inherited from the parent type.*)\nHB.structure Definition SubPreorder d (T : preorderType d) S d' :=\n { U of SubEquality T S U & Preorder d' U & isSubPreorder d T S d' U }.\n\nModule Import SubPreorderTheory.\nSection SubPreorderTheory.\nContext (d : disp_t) (T : preorderType d) (S : pred T).\nContext (d' : disp_t) (U : SubPreorder.type S d').\n(*The function `val` is the canonical embedding that maps an element from a subtype into its corresponding element in the parent type.*)\nLocal Notation val := (val : U -> T).\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use le_val instead.\")]\n(*This lemma states that the less-than-or-equal-to relation holds between two elements of a sub-preorder if and only if the same relation holds between their corresponding elements in the parent type.*)\nLemma leEsub x y : (x <= y) = (val x <= val y). \n(*This lemma states that the embedding function from a sub-preorder to its parent type is strictly monotonic. If an element in the subtype is strictly less than another, their images in the parent type will also be strictly less than each other.*)\nLemma lt_val : {mono val : x y / x < y}.\n\n#[deprecated(since=\"mathcomp 2.3.0\", note=\"Use lt_val instead.\")]\n(*This lemma states that the strict less-than relation holds between two elements of a sub-preorder if and only if the same strict relation holds between their corresponding elements in the parent type.*)\nLemma ltEsub x y : (x < y) = (val x < val y). \n(*This lemma states that the embedding function from a sub-preorder to its parent type preserves the less-than-or-equal-to relation. If one element is less than or equal to another in the subtype, this relation is guaranteed to hold for their images in the parent type.*)\nLemma le_wval : {homo val : x y / x <= y}. \n(*This lemma states that the embedding function from a sub-preorder to its parent type preserves the strict less-than relation. If one element is strictly less than another in the subtype, this relation is guaranteed to hold for their images in the parent type.*)\nLemma lt_wval : {homo val : x y / x < y}. \n(*This factory record provides a mechanism for automatically constructing a sub-preorder structure on a subtype that is formed by choosing elements from a parent type. It equips the subtype with the induced order inherited from the parent type.*)\nHB.factory Record SubChoice_isSubPreorder d (T : preorderType d) S (d' : disp_t) U\n of SubChoice T S U := {}.\n\nHB.builders Context d T S d' U of SubChoice_isSubPreorder d T S d' U.\nHB.instance Definition _ : isPreorder d' U :=\n @PreCancelPartial.PrePcan d' U d T val.\n(*This fact states that the embedding function from a subtype to its parent type is an order morphism, bundling the monotonicity proof of this function into a formal order morphism structure.*)\nFact valD : order_morphism (val : U -> T). \n(*This notation provides a concise syntax for building a sub-preorder structure on a given subtype, using the induced order from the parent type and a default display.*)\nNotation \"[ 'SubChoice_isSubPreorder' 'of' U 'by' <: ]\" :=\n (SubChoice_isSubPreorder.Build _ _ _ _ U)\n (at level 0, format \"[ 'SubChoice_isSubPreorder' 'of' U 'by' <: ]\")\n : form_scope.\n(*This notation provides a concise syntax for building a sub-preorder structure on a given subtype, using the induced order from the parent type and an explicitly provided display.*)\nNotation \"[ 'SubChoice_isSubPreorder' 'of' U 'by' <: 'with' disp ]\" :=\n (SubChoice_isSubPreorder.Build _ _ _ disp U)\n (at level 0, format \"[ 'SubChoice_isSubPreorder' 'of' U 'by' <: 'with' disp ]\")\n : form_scope.\n\nEnd SubOrderExports.\nHB.export SubOrderExports.\n\nModule NatOrder.\nSection NatOrder.\n \n(*This fact declares a specific display object used to represent the standard numerical order on the type of natural numbers.*)\nFact nat_display : disp_t. \n\n(*This lemma defines the strict less-than relation for natural numbers. It states that one natural number is strictly less than another if and only if the first is less than or equal to the second, and the second is not less than or equal to the first.*)\nLemma ltn_def x y : (x < y)%N = (x <= y)%N && ~~ (y <= x)%N.\n\n#[export]\nHB.instance Definition _ :=\n isPreorder.Build nat_display nat ltn_def leqnn leq_trans.\n\n#[export]\n(*This lemma states that the generic less-than-or-equal-to relation, when instantiated for natural numbers under their standard ordering, is equivalent to the built-in less-than-or-equal-to predicate for natural numbers.*)\nLemma leEnat : le = leq. \n(*This lemma states that the generic strict less-than relation, when instantiated for natural numbers under their standard ordering, is equivalent to the built-in strict less-than predicate for natural numbers.*)\nLemma ltEnat : lt = ltn. \n(*This lemma states that the generic minimum operation, when applied to two natural numbers under their standard ordering, is equivalent to the built-in minimum function for natural numbers.*)\nLemma minEnat : min = minn. \n(*This lemma states that the generic maximum operation, when applied to two natural numbers under their standard ordering, is equivalent to the built-in maximum function for natural numbers.*)\nLemma maxEnat : max = maxn. \n(*This lemma states that the generic bottom element, representing the minimum value in a preordered type, corresponds to the natural number zero when the type is that of natural numbers with their standard ordering.*)\nLemma botEnat : \\bot = 0%N :> nat. \n\nEnd NatOrder.\n\nModule Exports.\nHB.reexport NatOrder.\n(*This definition provides the 'less than or equal to' comparison relation for extended natural numbers.*)\nDefinition leEnat := leEnat.\n(*This definition provides the 'strictly less than' comparison relation for extended natural numbers.*)\nDefinition ltEnat := ltEnat.\n(*This definition provides a function that computes the minimum of two extended natural numbers.*)\nDefinition minEnat := minEnat.\n(*This definition provides a function that computes the maximum of two extended natural numbers.*)\nDefinition maxEnat := maxEnat.\n(*This definition provides the least element of the set of extended natural numbers, which corresponds to zero.*)\nDefinition botEnat := botEnat.\nEnd Exports.\nEnd NatOrder.\nHB.export NatOrder.Exports.\n\nModule NatMonotonyTheory.\nSection NatMonotonyTheory.\n\nContext {disp : disp_t} {T : preorderType disp}.\nVariables (D : {pred nat}) (f : nat -> T).\nHypothesis Dconvex : {in D &, forall i j k, i < k < j -> k \\in D}.\n\n(*This lemma states that a function from natural numbers to an ordered type is non-decreasing over a convex set if it is strictly increasing between consecutive numbers within that set.*)\nLemma homo_ltn_lt_in : {in D, forall i, i.+1 \\in D -> f i < f i.+1} ->\n {in D &, {homo f : i j / i < j}}.\n\n(*This lemma states that a function from natural numbers to an ordered type is non-decreasing over a convex set if it is non-decreasing between consecutive numbers within that set.*)\nLemma nondecn_inP : {in D, forall i, i.+1 \\in D -> f i <= f i.+1} ->\n {in D &, {homo f : i j / i <= j}}.\n\n(*This lemma states that a function from natural numbers to an ordered type is non-increasing over a convex set if it is strictly decreasing between consecutive numbers within that set.*)\nLemma nhomo_ltn_lt_in : {in D, forall i, i.+1 \\in D -> f i > f i.+1} ->\n {in D &, {homo f : i j /~ i < j}}.\n\n(*This lemma states that a function from natural numbers to an ordered type is non-increasing over a convex set if it is non-increasing between consecutive numbers within that set.*)\nLemma nonincn_inP : {in D, forall i, i.+1 \\in D -> f i >= f i.+1} ->\n {in D &, {homo f : i j /~ i <= j}}.\n\n(*This lemma states that a function from natural numbers to an ordered type is non-decreasing if it is strictly increasing between any natural number and its successor.*)\nLemma homo_ltn_lt : (forall i, f i < f i.+1) -> {homo f : i j / i < j}.\n\n(*This lemma states that a function from natural numbers to an ordered type is non-decreasing if it is non-decreasing between any natural number and its successor.*)\nLemma nondecnP : (forall i, f i <= f i.+1) -> {homo f : i j / i <= j}.\n\n(*This lemma states that a function from natural numbers to an ordered type is non-increasing if it is strictly decreasing between any natural number and its successor.*)\nLemma nhomo_ltn_lt : (forall i, f i > f i.+1) -> {homo f : i j /~ i < j}.\n\n(*This lemma states that a function from natural numbers to an ordered type is non-increasing if it is non-increasing between any natural number and its successor.*)\nLemma nonincnP : (forall i, f i >= f i.+1) -> {homo f : i j /~ i <= j}.\n\nEnd NatMonotonyTheory.\nArguments homo_ltn_lt_in {disp T} [D f].\nArguments nondecn_inP {disp T} [D f].\nArguments nhomo_ltn_lt_in {disp T} [D f].\nArguments nonincn_inP {disp T} [D f].\nArguments homo_ltn_lt {disp T} [f].\nArguments nondecnP {disp T} [f].\nArguments nhomo_ltn_lt {disp T} [f].\nArguments nonincnP {disp T} [f].\nEnd NatMonotonyTheory.\n\n(*A constant that serves as a display parameter to select the divisibility order and its associated notations, specifically for the type of natural numbers.*)\nFact dvd_display : disp_t. \n\nModule DvdSyntax.\n\n(*A notation that represents the divisibility relation, where one number divides another.*)\nNotation dvd := (@le dvd_display _).\n(*A notation intended for parsing only, which allows specifying the divisibility relation as a two-argument function on a given type.*)\nNotation \"@ 'dvd' T\" := (@le dvd_display T)\n (at level 10, T at level 8, only parsing) : function_scope.\n(*A notation that represents the strict divisibility relation, where one number divides another but is not equal to it.*)\nNotation sdvd := (@lt dvd_display _).\n(*A notation intended for parsing only, which allows specifying the strict divisibility relation as a two-argument function on a given type.*)\nNotation \"@ 'sdvd' T\" := (@lt dvd_display T)\n (at level 10, T at level 8, only parsing) : function_scope.\n\n(*An infix notation for the divisibility relation, asserting that the natural number on the left divides the natural number on the right.*)\nNotation \"x %| y\" := (dvd x y) : order_scope.\n(*An infix notation for the strict divisibility relation, asserting that the natural number on the left divides the natural number on the right and is not equal to it.*)\nNotation \"x %<| y\" := (sdvd x y) : order_scope.\n\n(*A notation for the natural number zero, representing the greatest element in the divisibility preorder, as it is divisible by every natural number.*)\nNotation nat0 := (@top dvd_display _).\n(*A notation for the natural number one, representing the least element in the divisibility preorder, as it divides every natural number.*)\nNotation nat1 := (@bottom dvd_display _).\n\nEnd DvdSyntax.\n\nModule NatDvd.\nSection NatDvd.\nImplicit Types (m n p : nat).\n\n(*This definition creates a type alias for the type of natural numbers, which is used to associate it with the divisibility order structure.*)\nDefinition t := nat.\n\n#[export]\nHB.instance Definition _ := Choice.copy t nat.\n\n#[export]\nHB.instance Definition _ := @Le_isPreorder.Build\n dvd_display t dvdn dvdnn dvdn_trans.\n\n#[export]\nHB.instance Definition _ := @hasBottom.Build _ t 1 dvd1n.\n\n#[export]\n(*This lemma states that the divisibility relation derived from the abstract preorder structure is equivalent to the standard concrete definition of divisibility on natural numbers.*)\nLemma dvdE : dvd = dvdn :> rel t. \n(*This lemma states that the element defined as the bottom of the divisibility preorder on natural numbers is equal to the number one.*)\nLemma nat1E : nat1 = 1%N :> t. \n(*This lemma states that the element defined as the top of the divisibility preorder on natural numbers is equal to the number zero.*)\nLemma nat0E : nat0 = 0%N :> t. \n\nEnd NatDvd.\nModule Exports.\nHB.reexport NatDvd.\n(*A notation that serves as an alias for the type of natural numbers, signaling that subsequent operations and proofs should use the context of the divisibility order.*)\nNotation natdvd := t.\n(*This definition provides a statement asserting that the abstract divisibility relation is identical to the standard definition of divisibility for natural numbers.*)\nDefinition dvdEnat := dvdE.\n(*This definition establishes that the representation of the number one in the divisibility preorder on natural numbers is definitionally equal to the standard natural number one.*)\nDefinition nat1E := nat1E.\n(*This definition establishes that the representation of the number zero in the divisibility preorder on natural numbers is definitionally equal to the standard natural number zero.*)\nDefinition nat0E := nat0E.\nEnd Exports.\nEnd NatDvd.\nHB.export NatDvd.Exports.\n\nModule OrdinalOrder.\nSection OrdinalOrder.\n\n(*This declaration introduces a display token used to select the standard less-than-or-equal-to order and its associated notations for finite ordinal types.*)\nFact ord_display : disp_t. \n\nSection PossiblyTrivial.\nContext (n : nat).\n\n#[export]\n(*This lemma states that for any finite ordinal type, the generic less-than-or-equal-to relation is equivalent to the standard less-than-or-equal-to comparison on the underlying natural numbers.*)\nLemma leEord : (le : rel 'I_n) = leq. \n(*This lemma states that for any finite ordinal type, the generic strict less-than relation is equivalent to the standard strict less-than comparison on the underlying natural numbers.*)\nLemma ltEord : (lt : rel 'I_n) = (fun m n => m < n)%N. \nEnd PossiblyTrivial.\n\nSection NonTrivial.\nContext (n' : nat).\n(*This definition introduces a local positive natural number, which determines the cardinality of a non-trivial finite ordinal type within its scope.*)\nLet n := n'.+1.\n\n#[export] HB.instance Definition _ := @hasBottom.Build _ 'I_n ord0 leq0n.\n(*This lemma states that the bottom element of a non-trivial finite ordinal type is the ordinal corresponding to the number zero.*)\nLemma botEord : \\bot = ord0. \n(*This lemma states that the top element of a non-trivial finite ordinal type is equal to the largest ordinal in that type.*)\nLemma topEord : \\top = ord_max. \n\nEnd NonTrivial.\n\nEnd OrdinalOrder.\n\nModule Exports.\nHB.reexport OrdinalOrder.\n(*This lemma states that the generic less-than-or-equal relation on ordinals is equivalent to the standard less-than-or-equal comparison defined for ordinals.*)\nDefinition leEord := leEord.\n(*This lemma states that the generic strict less-than relation on ordinals is equivalent to the standard strict less-than comparison defined for ordinals.*)\nDefinition ltEord := ltEord.\n(*This lemma states that the generic bottom element of the ordinal type is equivalent to the standard representation of the smallest ordinal, which is zero.*)\nDefinition botEord := botEord.\n(*This lemma states that the generic top element of a finite ordinal type is equivalent to the largest representable ordinal in that type.*)\nDefinition topEord := topEord.\nEnd Exports.\nEnd OrdinalOrder.\nHB.export OrdinalOrder.Exports.\n\nModule BoolOrder.\nSection BoolOrder.\nImplicit Types (x y : bool).\n\n(*This declaration defines a display parameter that links the generic order notations, such as less-than-or-equal, to their specific implementations for the boolean type.*)\nFact bool_display : disp_t. \n\n(*This fact states that for any two booleans, the first is strictly less than the second if and only if the first is less than or equal to the second and the second is not less than or equal to the first.*)\nFact ltn_def x y : (x < y)%N = (x <= y)%N && ~~ (y <= x)%N.\n\n#[export] HB.instance Definition _ := @isPreorder.Build bool_display bool\n _ _ ltn_def leqnn leq_trans.\n#[export] HB.instance Definition _ := @hasBottom.Build _ bool false leq0n.\n(*This lemma states that the generic less-than-or-equal relation for booleans is equivalent to the standard boolean comparison function, where false is less than or equal to both booleans and true is only less than or equal to true.*)\nLemma leEbool : le = (leq : rel bool). \n(*This lemma states that for any two booleans, the generic strict less-than relation between them is equivalent to the result of comparing them using the strict less-than relation for natural numbers, where false is treated as zero and true is treated as one.*)\nLemma ltEbool x y : (x < y) = (x < y)%N. \n\nEnd BoolOrder.\nModule Exports.\nHB.reexport BoolOrder.\n(*This lemma states that the less-than-or-equal relation on booleans holds if and only if the first boolean implies the second.*)\nDefinition leEbool := leEbool.\n(*This lemma states that the strict less-than relation on booleans holds if and only if the first boolean is false and the second boolean is true.*)\nDefinition ltEbool := ltEbool.\nEnd Exports.\nEnd BoolOrder.\nHB.export BoolOrder.Exports.\n\n(*This fact defines a structural placeholder used to construct a product display from two given displays. It takes two dummy arguments of the unit type and returns a value of the unit type.*)\nFact prod_display_unit (_ _ : unit) : unit. \n\n(*This definition creates a new display for a product type by combining the displays associated with its left and right component types.*)\nDefinition prod_display (displ dispr : disp_t) : disp_t :=\n Disp (prod_display_unit (d1 displ) (d1 dispr))\n (prod_display_unit (d2 displ) (d2 dispr)).\n\n(*This definition creates a new display for a sequence type from a given display corresponding to its element type, intended for use with the pointwise product order on sequences.*)\nFact seqprod_display (disp : disp_t) : disp_t. \n\nModule Import ProdSyntax.\n\n(*This notation defines the two-argument function for the component-wise less-than-or-equal comparison on a product type.*)\nNotation \"<=^p%O\" := (@le (prod_display _ _) _) : function_scope.\nNotation \">=^p%O\" := (@ge (prod_display _ _) _) : function_scope.\n(*This notation defines the two-argument function for the component-wise greater-than-or-equal comparison on a product type.*)\nNotation \">=^p%O\" := (@ge (prod_display _ _) _) : function_scope.\n(*This notation defines the two-argument function for the component-wise strict less-than comparison on a product type.*)\nNotation \"<^p%O\" := (@lt (prod_display _ _) _) : function_scope.\n(*This notation defines the two-argument function for the component-wise strict greater-than comparison on a product type.*)\nNotation \">^p%O\" := (@gt (prod_display _ _) _) : function_scope.\n(*This notation defines the boolean-valued function that checks for component-wise less-than-or-equal comparison on a product type, returning true if the relation holds and false otherwise.*)\nNotation \"=<^p%O\" := (@comparable (prod_display _ _) _) : function_scope.\n(*This notation defines the function that checks whether two elements of a product type are incomparable under the component-wise order.*)\nNotation \"><^p%O\" := (fun x y => ~~ (@comparable (prod_display _ _) _ x y)) :\n function_scope.\n\n(*This notation represents the predicate that checks if an element of a product type is less than or equal to a given element under the component-wise order.*)\nNotation \"<=^p y\" := (>=^p%O y) : order_scope.\n(*This notation allows specifying the type of a given element when forming the predicate that checks if an element of a product type is less than or equal to that given element under the component-wise order.*)\nNotation \"<=^p y :> T\" := (<=^p (y : T)) (only parsing) : order_scope.\n(*This notation represents the predicate that checks if an element of a product type is greater than or equal to a given element under the component-wise order.*)\nNotation \">=^p y\" := (<=^p%O y) : order_scope.\n(*This notation allows specifying the type of a given element when forming the predicate that checks if an element of a product type is greater than or equal to that given element under the component-wise order.*)\nNotation \">=^p y :> T\" := (>=^p (y : T)) (only parsing) : order_scope.\n\n(*This notation represents the predicate that checks if an element of a product type is strictly less than a given element under the component-wise order.*)\nNotation \"<^p y\" := (>^p%O y) : order_scope.\n(*This notation allows specifying the type of a given element when forming the predicate that checks if an element of a product type is strictly less than that given element under the component-wise order.*)\nNotation \"<^p y :> T\" := (<^p (y : T)) (only parsing) : order_scope.\n(*This notation represents the predicate that checks if an element of a product type is strictly greater than a given element under the component-wise order.*)\nNotation \">^p y\" := (<^p%O y) : order_scope.\n(*This notation allows specifying the type of a given element when forming the predicate that checks if an element of a product type is strictly greater than that given element under the component-wise order.*)\nNotation \">^p y :> T\" := (>^p (y : T)) (only parsing) : order_scope.\n\n(*This notation represents the component-wise less-than-or-equal comparison between two elements of a product type.*)\nNotation \"x <=^p y\" := (<=^p%O x y) : order_scope.\n(*This notation allows specifying the type of two elements when asserting the component-wise less-than-or-equal comparison between them.*)\nNotation \"x <=^p y :> T\" := ((x : T) <=^p (y : T)) (only parsing) : order_scope.\n(*This notation represents the component-wise greater-than-or-equal comparison between two elements of a product type.*)\nNotation \"x >=^p y\" := (y <=^p x) (only parsing) : order_scope.\n(*This notation allows specifying the type of two elements when asserting the component-wise greater-than-or-equal comparison between them.*)\nNotation \"x >=^p y :> T\" := ((x : T) >=^p (y : T)) (only parsing) : order_scope.\n\n(*This notation represents the component-wise strict less-than comparison between two elements of a product type.*)\nNotation \"x <^p y\" := (<^p%O x y) : order_scope.\n(*This notation allows specifying the type of two elements when asserting the component-wise strict less-than comparison between them.*)\nNotation \"x <^p y :> T\" := ((x : T) <^p (y : T)) (only parsing) : order_scope.\n(*This notation represents the component-wise strict greater-than comparison between two elements of a product type.*)\nNotation \"x >^p y\" := (y <^p x) (only parsing) : order_scope.\n(*This notation allows specifying the type of two elements when asserting the component-wise strict greater-than comparison between them.*)\nNotation \"x >^p y :> T\" := ((x : T) >^p (y : T)) (only parsing) : order_scope.\n\n(*This notation provides a shorthand for asserting that a first element is component-wise less than or equal to a second, and the second is component-wise less than or equal to a third.*)\nNotation \"x <=^p y <=^p z\" := ((x <=^p y) && (y <=^p z)) : order_scope.\n(*This notation provides a shorthand for asserting that a first element is strictly component-wise less than a second, and the second is component-wise less than or equal to a third.*)\nNotation \"x <^p y <=^p z\" := ((x <^p y) && (y <=^p z)) : order_scope.\n(*This notation represents a chained comparison for the component-wise product order, asserting that a first element is less than or equal to a second, and the second element is strictly less than a third.*)\nNotation \"x <=^p y <^p z\" := ((x <=^p y) && (y <^p z)) : order_scope.\n(*This notation represents a chained strict comparison for the component-wise product order, asserting that a first element is strictly less than a second, and the second element is strictly less than a third.*)\nNotation \"x <^p y <^p z\" := ((x <^p y) && (y <^p z)) : order_scope.\n\n(*This notation provides a boolean reflection mechanism for the product order relation, asserting that the proposition stating a first element is less than or equal to a second under the product order is logically equivalent to a given boolean value being true.*)\nNotation \"x <=^p y ?= 'iff' C\" := ( T\" := ((x : T) <=^p (y : T) ?= iff C)\n (only parsing) : order_scope.\n\n(*This notation defines a predicate that is satisfied by any element that is comparable to a given element under the component-wise product order.*)\nNotation \">=<^p y\" := [pred x | >=<^p%O x y] : order_scope.\n(*This notation defines a predicate that is satisfied by any element of a specified type that is comparable to a given element of the same type under the component-wise product order.*)\nNotation \">=<^p y :> T\" := (>=<^p (y : T)) (only parsing) : order_scope.\n(*This notation represents the comparability relation for the component-wise product order, which holds if two elements are related by either less-than-or-equal-to or greater-than-or-equal-to.*)\nNotation \"x >=<^p y\" := (>=<^p%O x y) : order_scope.\n\n(*This notation defines a predicate that is satisfied by any element that is incomparable to a given element under the component-wise product order.*)\nNotation \"><^p y\" := [pred x | ~~ (>=<^p%O x y)] : order_scope.\n(*This notation defines a predicate that is satisfied by any element of a specified type that is incomparable to a given element of the same type under the component-wise product order.*)\nNotation \"><^p y :> T\" := (><^p (y : T)) (only parsing) : order_scope.\n(*This notation represents the incomparability relation for the component-wise product order, which holds if two elements are not related by either less-than-or-equal-to or greater-than-or-equal-to.*)\nNotation \"x ><^p y\" := (~~ (><^p%O x y)) : order_scope.\n\nEnd ProdSyntax.\n\nModule Import SeqProdSyntax.\n\n(*This notation refers to the underlying function for the pointwise less-than-or-equal relation on sequences.*)\nNotation \"<=^sp%O\" := (@le (seqprod_display _) _) : function_scope.\nNotation \">=^sp%O\" := (@ge (seqprod_display _) _) : function_scope.\n(*This notation refers to the underlying function for the pointwise greater-than-or-equal relation on sequences.*)\nNotation \">=^sp%O\" := (@ge (seqprod_display _) _) : function_scope.\n(*This notation refers to the underlying function for the pointwise strict less-than relation on sequences.*)\nNotation \"<^sp%O\" := (@lt (seqprod_display _) _) : function_scope.\n(*This notation refers to the underlying function for the pointwise strict greater-than relation on sequences.*)\nNotation \">^sp%O\" := (@gt (seqprod_display _) _) : function_scope.\n(*This notation refers to the underlying boolean-valued function that checks if one sequence is pointwise less than or equal to another.*)\nNotation \"=<^sp%O\" := (@comparable (seqprod_display _) _) : function_scope.\n(*This notation refers to the underlying function that checks if two sequences are incomparable under the pointwise order.*)\nNotation \"><^sp%O\" := (fun x y => ~~ (@comparable (seqprod_display _) _ x y)) :\n function_scope.\n\n(*This notation defines a predicate that is satisfied by any sequence that is pointwise greater than or equal to a given sequence.*)\nNotation \"<=^sp y\" := (>=^sp%O y) : order_scope.\n(*This notation defines a predicate that is satisfied by any sequence of a specified type that is pointwise greater than or equal to a given sequence of the same type.*)\nNotation \"<=^sp y :> T\" := (<=^sp (y : T)) (only parsing) : order_scope.\n(*This notation defines a predicate that is satisfied by any sequence that is pointwise less than or equal to a given sequence.*)\nNotation \">=^sp y\" := (<=^sp%O y) : order_scope.\n(*This notation defines a predicate that is satisfied by any sequence of a specified type that is pointwise less than or equal to a given sequence of the same type.*)\nNotation \">=^sp y :> T\" := (>=^sp (y : T)) (only parsing) : order_scope.\n\n(*This notation defines a predicate that is satisfied by any sequence that is pointwise strictly less than a given sequence.*)\nNotation \"<^sp y\" := (>^sp%O y) : order_scope.\n(*This notation defines a predicate that is satisfied by any sequence of a specified type that is pointwise strictly less than a given sequence of the same type.*)\nNotation \"<^sp y :> T\" := (<^sp (y : T)) (only parsing) : order_scope.\n(*This notation defines a predicate that is satisfied by any sequence that is pointwise strictly greater than a given sequence.*)\nNotation \">^sp y\" := (<^sp%O y) : order_scope.\n(*This notation defines a predicate that is satisfied by any sequence of a specified type that is pointwise strictly greater than a given sequence of the same type.*)\nNotation \">^sp y :> T\" := (>^sp (y : T)) (only parsing) : order_scope.\n\n(*This notation represents the pointwise less-than-or-equal relation between two sequences.*)\nNotation \"x <=^sp y\" := (<=^sp%O x y) : order_scope.\n(*This notation represents the pointwise less-than-or-equal relation between two sequences of a specified type.*)\nNotation \"x <=^sp y :> T\" := ((x : T) <=^sp (y : T)) (only parsing) : order_scope.\n(*This notation represents the pointwise greater-than-or-equal relation between two sequences, indicating that the first sequence is greater than or equal to the second in the pointwise order.*)\nNotation \"x >=^sp y\" := (y <=^sp x) (only parsing) : order_scope.\n(*This notation represents the pointwise greater-than-or-equal relation between two sequences of a specified type, indicating that the first sequence is greater than or equal to the second in the pointwise order.*)\nNotation \"x >=^sp y :> T\" := ((x : T) >=^sp (y : T)) (only parsing) : order_scope.\n\n(*This notation represents the pointwise strict less-than relation between two sequences.*)\nNotation \"x <^sp y\" := (<^sp%O x y) : order_scope.\n(*A notation for asserting that a sequence `x` is strictly less than a sequence `y` according to the sequence product order, where both sequences are explicitly specified to be of a certain type `T`. This comparison is true if the sequences have the same length and each element of `x` is less than or equal to the corresponding element of `y`, with at least one element of `x` being strictly less than its corresponding element in `y`.*)\nNotation \"x <^sp y :> T\" := ((x : T) <^sp (y : T)) (only parsing) : order_scope.\n(*A notation for asserting that a sequence `x` is strictly greater than a sequence `y` according to the sequence product order. This is defined as `y` being strictly less than `x` in the same order.*)\nNotation \"x >^sp y\" := (y <^sp x) (only parsing) : order_scope.\n(*A notation for asserting that a sequence `x` is strictly greater than a sequence `y` according to the sequence product order, with an explicit type annotation on the sequences.*)\nNotation \"x >^sp y :> T\" := ((x : T) >^sp (y : T)) (only parsing) : order_scope.\n\n(*A chained comparison notation asserting that a sequence `x` is less than or equal to a sequence `y`, and `y` is less than or equal to a sequence `z`, all according to the sequence product order.*)\nNotation \"x <=^sp y <=^sp z\" := ((x <=^sp y) && (y <=^sp z)) : order_scope.\n(*A chained comparison notation asserting that a sequence `x` is strictly less than a sequence `y`, and `y` is less than or equal to a sequence `z`, all according to the sequence product order.*)\nNotation \"x <^sp y <=^sp z\" := ((x <^sp y) && (y <=^sp z)) : order_scope.\n(*A chained comparison notation asserting that a sequence `x` is less than or equal to a sequence `y`, and `y` is strictly less than a sequence `z`, all according to the sequence product order.*)\nNotation \"x <=^sp y <^sp z\" := ((x <=^sp y) && (y <^sp z)) : order_scope.\n(*A chained comparison notation asserting that a sequence `x` is strictly less than a sequence `y`, and `y` is strictly less than a sequence `z`, all according to the sequence product order.*)\nNotation \"x <^sp y <^sp z\" := ((x <^sp y) && (y <^sp z)) : order_scope.\n\n(*A reflection notation which asserts that the boolean statement '`x` is less than or equal to `y`' under the sequence product order is logically equivalent to a given proposition.*)\nNotation \"x <=^sp y ?= 'iff' C\" := ( T\" := ((x : T) <=^sp (y : T) ?= iff C)\n (only parsing) : order_scope.\n\n(*A section notation that represents the predicate testing whether an input sequence is comparable to a given sequence `y` under the sequence product order. Two sequences are comparable if one is less than or equal to the other.*)\nNotation \">=<^sp y\" := [pred x | >=<^sp%O x y] : order_scope.\n(*A section notation that represents the predicate testing whether an input sequence is comparable to a given sequence `y` of a certain type `T` under the sequence product order.*)\nNotation \">=<^sp y :> T\" := (>=<^sp (y : T)) (only parsing) : order_scope.\n(*An infix notation to assert that two sequences, `x` and `y`, are comparable under the sequence product order, meaning one is less than or equal to the other.*)\nNotation \"x >=<^sp y\" := (>=<^sp%O x y) : order_scope.\n\n(*A section notation that represents the predicate testing whether an input sequence is incomparable to a given sequence `y` under the sequence product order.*)\nNotation \"><^sp y\" := [pred x | ~~ (>=<^sp%O x y)] : order_scope.\n(*A section notation that represents the predicate testing whether an input sequence is incomparable to a given sequence `y` of a certain type `T` under the sequence product order.*)\nNotation \"><^sp y :> T\" := (><^sp (y : T)) (only parsing) : order_scope.\n(*An infix notation to assert the stable incomparability of two sequences, `x` and `y`, under the sequence product order. This is true if it is not the case that they are not incomparable.*)\nNotation \"x ><^sp y\" := (~~ (><^sp%O x y)) : order_scope.\n\nEnd SeqProdSyntax.\n\n(*This declaration introduces a display for lexicographic order on product types. It is parameterized by the displays of the component types to properly resolve notations.*)\nFact lexi_display (disp _ : disp_t) : disp_t. \n\n(*This declaration introduces a display for lexicographic order on sequence types. It is parameterized by the display of the sequence element type to properly resolve notations.*)\nFact seqlexi_display (disp : disp_t) : disp_t. \n\nModule Import LexiSyntax.\n\n(*Defines the underlying function for the 'less than or equal to' comparison using the lexicographic order. This is intended for use within other functions and notations.*)\nNotation \"<=^l%O\" := (@le (lexi_display _ _) _) : function_scope.\nNotation \">=^l%O\" := (@ge (lexi_display _ _) _) : function_scope.\n(*Defines the underlying function for the 'greater than or equal to' comparison using the lexicographic order. This is intended for use within other functions and notations.*)\nNotation \">=^l%O\" := (@ge (lexi_display _ _) _) : function_scope.\n(*Defines the underlying function for the 'strictly less than' comparison using the lexicographic order. This is intended for use within other functions and notations.*)\nNotation \"<^l%O\" := (@lt (lexi_display _ _) _) : function_scope.\n(*Defines the underlying function for the 'strictly greater than' comparison using the lexicographic order. This is intended for use within other functions and notations.*)\nNotation \">^l%O\" := (@gt (lexi_display _ _) _) : function_scope.\n(*Defines the underlying function for the reflected 'less than or equal to' comparison using the lexicographic order, which relates the boolean outcome to a proposition.*)\nNotation \"=<^l%O\" := (@comparable (lexi_display _ _) _) : function_scope.\n(*Defines the underlying function that determines if two elements are incomparable under the lexicographic order, which is true if it is not the case that they are comparable.*)\nNotation \"><^l%O\" := (fun x y => ~~ (@comparable (lexi_display _ _) _ x y)) :\n function_scope.\n\n(**)\nNotation \"<=^l y\" := (>=^l%O y) : order_scope.\n(**)\nNotation \"<=^l y :> T\" := (<=^l (y : T)) (only parsing) : order_scope.\n(**)\nNotation \">=^l y\" := (<=^l%O y) : order_scope.\n(**)\nNotation \">=^l y :> T\" := (>=^l (y : T)) (only parsing) : order_scope.\n\n(**)\nNotation \"<^l y\" := (>^l%O y) : order_scope.\n(**)\nNotation \"<^l y :> T\" := (<^l (y : T)) (only parsing) : order_scope.\n(**)\nNotation \">^l y\" := (<^l%O y) : order_scope.\n(**)\nNotation \">^l y :> T\" := (>^l (y : T)) (only parsing) : order_scope.\n\n(**)\nNotation \"x <=^l y\" := (<=^l%O x y) : order_scope.\n(**)\nNotation \"x <=^l y :> T\" := ((x : T) <=^l (y : T)) (only parsing) : order_scope.\n(**)\nNotation \"x >=^l y\" := (y <=^l x) (only parsing) : order_scope.\n(**)\nNotation \"x >=^l y :> T\" := ((x : T) >=^l (y : T)) (only parsing) : order_scope.\n\n(**)\nNotation \"x <^l y\" := (<^l%O x y) : order_scope.\n(**)\nNotation \"x <^l y :> T\" := ((x : T) <^l (y : T)) (only parsing) : order_scope.\n(**)\nNotation \"x >^l y\" := (y <^l x) (only parsing) : order_scope.\n(**)\nNotation \"x >^l y :> T\" := ((x : T) >^l (y : T)) (only parsing) : order_scope.\n\n(**)\nNotation \"x <=^l y <=^l z\" := ((x <=^l y) && (y <=^l z)) : order_scope.\n(**)\nNotation \"x <^l y <=^l z\" := ((x <^l y) && (y <=^l z)) : order_scope.\n(**)\nNotation \"x <=^l y <^l z\" := ((x <=^l y) && (y <^l z)) : order_scope.\n(**)\nNotation \"x <^l y <^l z\" := ((x <^l y) && (y <^l z)) : order_scope.\n\n(**)\nNotation \"x <=^l y ?= 'iff' C\" := ( T\" := ((x : T) <=^l (y : T) ?= iff C)\n (only parsing) : order_scope.\n\n(**)\nNotation \">=<^l y\" := [pred x | >=<^l%O x y] : order_scope.\n(**)\nNotation \">=<^l y :> T\" := (>=<^l (y : T)) (only parsing) : order_scope.\n(**)\nNotation \"x >=<^l y\" := (>=<^l%O x y) : order_scope.\n\n(**)\nNotation \"><^l y\" := [pred x | ~~ (>=<^l%O x y)] : order_scope.\n(**)\nNotation \"><^l y :> T\" := (><^l (y : T)) (only parsing) : order_scope.\n(**)\nNotation \"x ><^l y\" := (~~ (><^l%O x y)) : order_scope.\n\nEnd LexiSyntax.\n\nModule Import SeqLexiSyntax.\n\n(*An operator notation for the binary function that checks if one sequence is less than or equal to another using the sequence lexicographic order.*)\nNotation \"<=^l%O\" := (@le (seqlexi_display _ _) _) : function_scope.\nNotation \">=^l%O\" := (@ge (seqlexi_display _ _) _) : function_scope.\n(*An operator notation for the binary function that checks if one sequence is greater than or equal to another using the sequence lexicographic order.*)\nNotation \">=^l%O\" := (@ge (seqlexi_display _ _) _) : function_scope.\n(*An operator notation for the binary function that checks if one sequence is strictly less than another using the sequence lexicographic order.*)\nNotation \"<^l%O\" := (@lt (seqlexi_display _ _) _) : function_scope.\n(*An operator notation for the binary function that checks if one sequence is strictly greater than another using the sequence lexicographic order.*)\nNotation \">^l%O\" := (@gt (seqlexi_display _ _) _) : function_scope.\n(*An operator notation for the boolean reflection of the 'less than or equal to' relation for the sequence lexicographic order.*)\nNotation \"=<^l%O\" := (@comparable (seqlexi_display _ _) _) : function_scope.\n(*An operator notation for the binary function that checks if two sequences are incomparable under the sequence lexicographic order.*)\nNotation \"><^l%O\" := (fun x y => ~~ (@comparable (seqlexi_display _ _) _ x y)) :\n function_scope.\n\n(*A section notation that represents the predicate testing whether an input element is less than or equal to a given element `y` under the lexicographic order.*)\nNotation \"<=^l y\" := (>=^l%O y) : order_scope.\n(*A section notation representing the predicate that tests whether an input element is less than or equal to a given element `y` of a certain type `T` under the lexicographic order.*)\nNotation \"<=^l y :> T\" := (<=^l (y : T)) (only parsing) : order_scope.\n(*A section notation that represents the predicate testing whether an input element is greater than or equal to a given element `y` under the lexicographic order.*)\nNotation \">=^l y\" := (<=^l%O y) : order_scope.\n(*A section notation representing the predicate that tests whether an input element is greater than or equal to a given element `y` of a certain type `T` under the lexicographic order.*)\nNotation \">=^l y :> T\" := (>=^l (y : T)) (only parsing) : order_scope.\n\n(*A section notation that represents the predicate testing whether an input element is strictly less than a given element `y` under the lexicographic order.*)\nNotation \"<^l y\" := (>^l%O y) : order_scope.\n(*A section notation representing the predicate that tests whether an input element is strictly less than a given element `y` of a certain type `T` under the lexicographic order.*)\nNotation \"<^l y :> T\" := (<^l (y : T)) (only parsing) : order_scope.\n(*A notation for the predicate that holds for any element strictly greater than a given element `y` under the lexicographic order.*)\nNotation \">^l y\" := (<^l%O y) : order_scope.\n(*A parsing-only notation that specifies the type `T` for the element `y` within the predicate for being strictly greater than `y` under the lexicographic order.*)\nNotation \">^l y :> T\" := (>^l (y : T)) (only parsing) : order_scope.\n\n(*A notation for the relation indicating that `x` is less than or equal to `y` under the lexicographic order.*)\nNotation \"x <=^l y\" := (<=^l%O x y) : order_scope.\n(*A parsing-only notation that specifies that `x` and `y` have type `T` for the lexicographic comparison where `x` is less than or equal to `y`.*)\nNotation \"x <=^l y :> T\" := ((x : T) <=^l (y : T)) (only parsing) : order_scope.\n(*A notation for the relation indicating that `x` is greater than or equal to `y` under the lexicographic order.*)\nNotation \"x >=^l y\" := (y <=^l x) (only parsing) : order_scope.\n(*A parsing-only notation that specifies that `x` and `y` have type `T` for the lexicographic comparison where `x` is greater than or equal to `y`.*)\nNotation \"x >=^l y :> T\" := ((x : T) >=^l (y : T)) (only parsing) : order_scope.\n\n(*A notation for the relation indicating that `x` is strictly less than `y` under the lexicographic order.*)\nNotation \"x <^l y\" := (<^l%O x y) : order_scope.\n(*A parsing-only notation that specifies that `x` and `y` have type `T` for the lexicographic comparison where `x` is strictly less than `y`.*)\nNotation \"x <^l y :> T\" := ((x : T) <^l (y : T)) (only parsing) : order_scope.\n(*A notation for the relation indicating that `x` is strictly greater than `y` under the lexicographic order.*)\nNotation \"x >^l y\" := (y <^l x) (only parsing) : order_scope.\n(*A parsing-only notation that specifies that `x` and `y` have type `T` for the lexicographic comparison where `x` is strictly greater than `y`.*)\nNotation \"x >^l y :> T\" := ((x : T) >^l (y : T)) (only parsing) : order_scope.\n\n(*A notation for a chained comparison that checks if `x` is less than or equal to `y` and `y` is less than or equal to `z`, using the lexicographic order.*)\nNotation \"x <=^l y <=^l z\" := ((x <=^l y) && (y <=^l z)) : order_scope.\n(*A notation for a chained comparison that checks if `x` is strictly less than `y` and `y` is less than or equal to `z`, using the lexicographic order.*)\nNotation \"x <^l y <=^l z\" := ((x <^l y) && (y <=^l z)) : order_scope.\n(*A notation for a chained comparison that checks if `x` is less than or equal to `y` and `y` is strictly less than `z`, using the lexicographic order.*)\nNotation \"x <=^l y <^l z\" := ((x <=^l y) && (y <^l z)) : order_scope.\n(*A notation for a chained comparison that checks if `x` is strictly less than `y` and `y` is strictly less than `z`, using the lexicographic order.*)\nNotation \"x <^l y <^l z\" := ((x <^l y) && (y <^l z)) : order_scope.\n\n(*A reflection notation that asserts that the lexicographic relation '`x` is less than or equal to `y`' is logically equivalent to a given boolean `C` being true.*)\nNotation \"x <=^l y ?= 'iff' C\" := ( T\" := ((x : T) <=^l (y : T) ?= iff C)\n (only parsing) : order_scope.\n\n(*A notation for the predicate that holds for any element that is comparable to a given element `y` under the lexicographic order.*)\nNotation \">=<^l y\" := [pred x | >=<^l%O x y] : order_scope.\n(*A parsing-only notation that specifies that `y` has type `T` in the predicate for being comparable to `y` under the lexicographic order.*)\nNotation \">=<^l y :> T\" := (>=<^l (y : T)) (only parsing) : order_scope.\n(*A notation for the relation indicating that `x` and `y` are comparable under the lexicographic order.*)\nNotation \"x >=<^l y\" := (>=<^l%O x y) : order_scope.\n\n(*A notation for the predicate that holds for any element that is incomparable to a given element `y` under the lexicographic order.*)\nNotation \"><^l y\" := [pred x | ~~ (>=<^l%O x y)] : order_scope.\n(*A parsing-only notation that specifies that `y` has type `T` in the predicate for being incomparable to `y` under the lexicographic order.*)\nNotation \"><^l y :> T\" := (><^l (y : T)) (only parsing) : order_scope.\n(*A notation for the relation indicating that `x` and `y` are incomparable under the lexicographic order.*)\nNotation \"x ><^l y\" := (~~ (><^l%O x y)) : order_scope.\n\nEnd SeqLexiSyntax.\n\nModule ProdOrder.\n\nLocal Open Scope type_scope. \n\n(*This definition sets the carrier of a tuple preorder structure to be the type of fixed-length tuples of a given length and underlying element type.*)\nDefinition type (disp : disp_t) (T T' : Type) := T * T'.\n(*This definition constructs the product type of two given preorder types, associating it with a product order display derived from the displays of the input types.*)\nDefinition type_\n (disp1 disp2 : disp_t) (T : preorderType disp1) (T' : preorderType disp2) :=\n type (prod_display disp1 disp2) T T'.\n\nSection Basis.\nContext {disp : disp_t}.\n\n(**)\nLocal Notation \"T * T'\" := (type disp T T') : type_scope.\n\n#[export] HB.instance Definition _ (T T' : eqType) := Equality.on (T * T').\n#[export] HB.instance Definition _ (T T' : choiceType) := Choice.on (T * T').\n#[export] HB.instance Definition _ (T T' : countType) := Countable.on (T * T').\n(*This fact states that for any two pairs of elements, the first pair is strictly less than the second pair if and only if the first pair is less than or equal to the second, while the second pair is not less than or equal to the first.*)\nFact lt_def x y : lt x y = le x y && ~~ le y x.\n\n(*This lemma states the reflexivity property for a preorder on a product-like type, asserting that any pair is less than or equal to itself.*)\nFact refl : reflexive le. \n\n(*This lemma states the transitivity property of a preorder relation on a product-like type.*)\nFact trans : transitive le.\n\nEnd Preorder.\n\nSection Preorder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : preorderType disp1) (T2 : preorderType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\n(*This definition creates a local alias for a type named T1 immediately preceding the definition of sequence-based order structures.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := Preorder.on T1'.\n(*This definition creates a local alias for a type named T2 immediately preceding the definition of sequence-based order structures.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := Preorder.on T2'.\n\n(*This definition establishes the 'less than or equal to' relation for a pair of elements from a product type. A first pair is less than or equal to a second pair if the first component of the first pair is less than or equal to the first component of the second, and the second component of the first pair is less than or equal to the second component of the second.*)\nDefinition le x y := (x.1 <= y.1) && (x.2 <= y.2).\n\n(*This definition establishes the 'strictly less than' relation for a pair of elements from a product type. A first pair is strictly less than a second pair if its first component is strictly less than the first component of the second and its second component is less than or equal to the second component of the second, or if its first component is less than or equal to the first component of the second and its second component is strictly less than the second component of the second.*)\nDefinition lt x y := (x.1 < y.1) && (x.2 <= y.2) || (x.1 <= y.1) && (x.2 < y.2).\n\n#[export]\n(*This lemma states that for two pairs of elements, the first pair is less than or equal to the second pair if and only if the first component of the first pair is less than or equal to the first component of the second, and the second component of the first pair is less than or equal to the second component of the second.*)\nLemma leEprod x y : (x <= y) = (x.1 <= y.1) && (x.2 <= y.2). \n\n(*This lemma states that for two pairs of elements, the first pair is strictly less than the second pair if and only if one of two conditions holds: either the first component of the first pair is strictly less than the first component of the second and the second components are in a 'less than or equal to' relation, or the first components are in a 'less than or equal to' relation and the second component of the first pair is strictly less than the second component of the second.*)\nLemma ltEprod x y :\n (x < y) = (x.1 < y.1) && (x.2 <= y.2) || (x.1 <= y.1) && (x.2 < y.2).\n\n(*This lemma states that comparing two pairs of elements using the 'less than or equal to' relation is equivalent to a boolean conjunction of two separate comparisons: one where the first components of the pairs are compared, and one where the second components are compared, both using their respective 'less than or equal to' relations.*)\nLemma le_pair (x1 y1 : T1) (x2 y2 : T2) :\n (x1, x2) <= (y1, y2) :> T1 * T2 = (x1 <= y1) && (x2 <= y2).\n\n(*This lemma states that comparing two pairs of elements using the 'strictly less than' relation is equivalent to a boolean disjunction. The first condition is that the first component of the first pair is strictly less than that of the second, while the respective second components are in a 'less than or equal to' relation. The second condition is that the first components are in a 'less than or equal to' relation, while the second component of the first pair is strictly less than that of the second.*)\nLemma lt_pair (x1 y1 : T1) (x2 y2 : T2) :\n (x1, x2) < (y1, y2) :> T1 * T2\n = (x1 < y1) && (x2 <= y2) || (x1 <= y1) && (x2 < y2).\n\nEnd Preorder.\n\nSection BPreorder.\nContext (disp1 disp2 : disp_t).\nContext (T1 : bPreorderType disp1) (T2 : bPreorderType disp2).\nLocal Notation \"T1 * T2\" := (type (Disp tt tt) T1 T2) : type_scope.\nImplicit Types (x : T1 * T2).\n\n(*This lemma states that for tuples equipped with a component-wise preorder, the tuple consisting entirely of bottom elements is the minimum element, meaning it is less than or equal to any other tuple of the same length.*)\nFact le0x x : (\\bot, \\bot) <= x :> T1 * T2.\n\nEnd BPreorder.\n\nSection BPreorder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : bPreorderType disp1) (T2 : bPreorderType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\n\n(*This definition creates a local alias for a type named T1 immediately preceding the definition of sequence-based order structures.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := BPreorder.on T1'.\n(*This definition creates a local alias for a type named T2 immediately preceding the definition of sequence-based order structures.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := BPreorder.on T2'.\n\n#[export]\n(*This lemma states that the bottom element of a product of two ordered types, each having a bottom element, is the pair formed by the bottom elements of the two component types.*)\nLemma botEprod : \\bot = (\\bot, \\bot) :> T1 * T2. \n\nEnd BPreorder.\n\nSection TPreorder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : tPreorderType disp1) (T2 : tPreorderType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\n\n#[export]\n(*This lemma states that the greatest element in a product of two ordered types that both have a greatest element is the pair formed by the greatest element of the first type and the greatest element of the second type.*)\nLemma topEprod : \\top = (\\top, \\top) :> T1 * T2. \n\nEnd TPreorder.\n\n#[export]\n(*This notation represents the product of two ordered types, where the resulting product type is equipped with the component-wise order relation. The parameter 'd' is a display that controls how order-related notations are interpreted for this product type.*)\nNotation \"T *prod[ d ] T'\" := (type d T T')\n (at level 70, d at next level, format \"T *prod[ d ] T'\") : type_scope.\n(*This notation serves as a shorthand for the product of two ordered types, equipped with the default component-wise order relation.*)\nNotation \"T *p T'\" := (type_ T T')\n (at level 70, format \"T *p T'\") : type_scope.\n(*This lemma states that a pair of elements is less than or equal to another pair of elements in the product order if and only if the first component of the first pair is less than or equal to the first component of the second pair, and the second component of the first pair is less than or equal to the second component of the second pair.*)\nDefinition leEprod := @leEprod.\n(*This lemma states that a pair of elements is strictly less than another pair of elements in the product order if and only if each component of the first pair is less than or equal to the corresponding component of the second pair, and at least one of these component-wise comparisons is a strict inequality.*)\nDefinition ltEprod := @ltEprod.\n(*This lemma states that if the components of a first pair are respectively less than or equal to the components of a second pair, then the first pair is less than or equal to the second pair under the product order.*)\nDefinition le_pair := @le_pair.\n(*This lemma states that a pair is strictly less than another pair in the product order if one of its components is strictly less than the corresponding component of the other pair, and its other component is less than or equal to the corresponding component of the other pair.*)\nDefinition lt_pair := @lt_pair.\n(*This lemma states that the least element in a product of two ordered types that both have a least element is the pair formed by the least element of the first type and the least element of the second type.*)\nDefinition botEprod := @botEprod.\n(*This lemma states that the top element of a product of two ordered types that both possess a top element is the pair formed by the top elements of each of the component types.*)\nDefinition topEprod := @topEprod.\nEnd Exports.\nEnd ProdOrder.\nHB.export ProdOrder.Exports.\n\nModule DefaultProdOrder.\nSection DefaultProdOrder.\nContext {disp1 disp2 : disp_t}.\n\n(*This definition creates an alias for the product of two preordered types, equipped with the component-wise product order structure, using specified displays to manage notation.*)\nLet prod T1 T2 := T1 *prod[prod_display disp1 disp2] T2.\n\nHB.instance Definition _ (T : preorderType disp1) (T' : preorderType disp2) :=\n Preorder.copy (T * T')%type (T *p T').\nHB.instance Definition _ (T1 : bPreorderType disp1) (T2 : bPreorderType disp2) :=\n BPreorder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _ (T1 : tPreorderType disp1) (T2 : tPreorderType disp2) :=\n TPreorder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _ (T1 : tbPreorderType disp1) (T2 : tbPreorderType disp2) :=\n TBPreorder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finPreorderType disp1) (T2 : finPreorderType disp2) :=\n FinPreorder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finBPreorderType disp1) (T2 : finBPreorderType disp2) :=\n FinBPreorder.copy (T1 * T2)%type (prod T1 T2).\nHB.instance Definition _\n (T1 : finTPreorderType disp1) (T2 : finTPreorderType disp2) :=\n FinTPreorder.copy (T1 * T2)%type (prod T1 T2).\n(*This definition declares the carrier type for a lexicographic order structure as the Cartesian product of two given types, parameterized by a display to handle notation.*)\nDefinition type (disp : disp_t) (T T' : Type) := T * T'.\n(*This definition specializes the product carrier type for two given preordered types, explicitly associating it with the lexicographic order display.*)\nDefinition type_\n (disp1 disp2 : disp_t) (T : preorderType disp1) (T' : preorderType disp2) :=\n type (lexi_display disp1 disp2) T T'.\n\nSection Basis.\nContext {disp : disp_t}.\n\n(*This notation provides a shorthand for the product carrier type, which is parameterized by a display from the context, to simplify type expressions involving lexicographic products.*)\nLocal Notation \"T * T'\" := (type disp T T') : type_scope.\n\n#[export] HB.instance Definition _ (T T' : eqType) := Equality.on (T * T').\n#[export] HB.instance Definition _ (T T' : choiceType) := Choice.on (T * T').\n#[export] HB.instance Definition _ (T T' : countType) := Countable.on (T * T').\n(*This lemma states the reflexivity property for a preorder on a product-like type, asserting that any pair is less than or equal to itself.*)\nFact refl : reflexive le.\n\n(*This lemma states the transitivity property of a preorder relation on a product-like type.*)\nFact trans : transitive le.\n\n(*This fact defines the strict less-than relation based on the non-strict less-than-or-equal-to relation. An element is strictly less than another if and only if the first element is less than or equal to the second, and the second element is not less than or equal to the first.*)\nFact lt_le_def x y : lt x y = le x y && ~~ le y x.\n\nEnd Preorder.\n\nSection Preorder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : preorderType disp1) (T2 : preorderType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\nImplicit Types (x y : T1 * T2).\n\n(*This definition creates a local alias for a type named T1 immediately preceding the definition of sequence-based order structures.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := Preorder.on T1'.\n(*This definition creates a local alias for a type named T2 immediately preceding the definition of sequence-based order structures.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := Preorder.on T2'.\n\n(*This definition specifies the lexicographic less-than-or-equal relation between two pairs. A pair is less than or equal to another if its first component is smaller, or if the first components are equal and its second component is less than or equal to the other's second component.*)\nDefinition le x y := (x.1 <= y.1) && ((x.1 >= y.1) ==> (x.2 <= y.2)).\n(*This definition specifies the strict lexicographic less-than relation between two pairs. A pair is strictly less than another if its first component is smaller, or if the first components are equal and its second component is strictly less than the other's second component.*)\nDefinition lt x y := (x.1 <= y.1) && ((x.1 >= y.1) ==> (x.2 < y.2)).\n\n#[export]\n(*This lemma provides an equational rule for the lexicographic less-than-or-equal relation on pairs, stating that it holds if the first component is less than or equal to the other's first component, and if they are equal, then the second component must be less than or equal to the other's second component.*)\nLemma leEprodlexi x y :\n (x <= y) = (x.1 <= y.1) && ((x.1 >= y.1) ==> (x.2 <= y.2)).\n\n(*This lemma provides an equational rule for the strict lexicographic less-than relation on pairs, stating that it holds if the first component is less than or equal to the other's first component, and if they are equal, then the second component must be strictly less than the other's second component.*)\nLemma ltEprodlexi x y :\n (x < y) = (x.1 <= y.1) && ((x.1 >= y.1) ==> (x.2 < y.2)).\n\n(*This lemma states the Boolean equivalence for the lexicographic less-than-or-equal comparison of two explicitly constructed pairs. The comparison is true if the first element of the first pair is less than or equal to the first element of the second pair, and if these first elements are also equal, then the second element of the first pair must be less than or equal to the second element of the second pair.*)\nLemma lexi_pair (x1 y1 : T1) (x2 y2 : T2) :\n (x1, x2) <= (y1, y2) :> T1 * T2 = (x1 <= y1) && ((x1 >= y1) ==> (x2 <= y2)).\n\n(*This lemma states the Boolean equivalence for the strict lexicographic less-than comparison of two explicitly constructed pairs. The comparison is true if the first element of the first pair is less than or equal to the first element of the second pair, and if these first elements are also equal, then the second element of the first pair must be strictly less than the second element of the second pair.*)\nLemma ltxi_pair (x1 y1 : T1) (x2 y2 : T2) :\n (x1, x2) < (y1, y2) :> T1 * T2 = (x1 <= y1) && ((x1 >= y1) ==> (x2 < y2)).\n\nEnd Preorder.\n\nSection BPreorder.\nContext (disp1 disp2 : disp_t).\nContext (T1 : bPreorderType disp1) (T2 : bPreorderType disp2).\nLocal Notation \"T1 * T2\" := (type (Disp tt tt) T1 T2) : type_scope.\nImplicit Types (x : T1 * T2).\n\n(*This fact establishes that for two preordered types with bottom elements, the pair formed by their respective bottom elements is the minimum element in their lexicographically ordered product.*)\nFact le0x x : (\\bot, \\bot) <= x :> T1 * T2.\n\nEnd BPreorder.\n\nSection BPreorder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : bPreorderType disp1) (T2 : bPreorderType disp2).\n(**)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\n\n(*This definition creates an alias for a type equipped with a preorder and a bottom element, making this structure explicitly available for use in subsequent constructions of ordered types.*)\nLet T1' : Type := T1.\nHB.instance Definition _ := BPreorder.on T1'.\n(*This definition creates an alias for a second type equipped with a preorder and a bottom element, making this structure explicitly available for use in subsequent constructions of ordered types.*)\nLet T2' : Type := T2.\nHB.instance Definition _ := BPreorder.on T2'.\n\n#[export]\n(*This lemma states that for the Cartesian product of two ordered types equipped with a lexicographic order, the bottom element of the product is the pair formed by the bottom elements of the two component types.*)\nLemma botEprodlexi : \\bot = (\\bot, \\bot) :> T1 * T2. \n\nEnd BPreorder.\n\nSection TPreorder.\nContext (disp1 disp2 disp3 : disp_t).\nContext (T1 : tPreorderType disp1) (T2 : tPreorderType disp2).\n(*This notation represents the Cartesian product of two ordered types, where the resulting product type is itself equipped with a specific order structure.*)\nLocal Notation \"T1 * T2\" := (type disp3 T1 T2) : type_scope.\n\n#[export]\n(*This lemma states that the greatest element of a product of two types equipped with the lexicographic order is the pair formed by the greatest element of the first type and the greatest element of the second type.*)\nLemma topEprodlexi : \\top = (\\top, \\top) :> T1 * T2. \n\nEnd TPreorder.\n\n#[export]\n(*This lemma states that if a pair of elements is less than or equal to another pair under the component-wise product order, then it is also less than or equal to that same pair under the lexicographic order.*)\nLemma sub_prod_lexi (disp1 disp2 disp3 disp4 : disp_t)\n (T1 : preorderType disp1) (T2 : preorderType disp2) :\n subrel (<=%O : rel (T1 *prod[disp3] T2)) (<=%O : rel (type disp4 T1 T2)).\n\nSection ProdLexiOrder.\nContext (disp1 disp2 disp3 : disp_t).\n\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (T1 : bPreorderType disp1)\n (T2 : bPreorderType disp2) := Preorder.on (type disp3 T1 T2).\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (T1 : tPreorderType disp1)\n (T2 : tPreorderType disp2) := Preorder.on (type disp3 T1 T2).\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (T1 : tbPreorderType disp1)\n (T2 : tbPreorderType disp2) := Preorder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finPreorderType disp1)\n (T2 : finPreorderType disp2) := Preorder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finBPreorderType disp1)\n (T2 : finBPreorderType disp2) := Preorder.on (type disp3 T1 T2).\n#[export]\nHB.instance Definition _ (T1 : finTPreorderType disp1)\n (T2 : finTPreorderType disp2) := Preorder.on (type disp3 T1 T2).\n#[export]\n(*This notation represents the Cartesian product of two ordered types, endowed with the lexicographic order. A display parameter is included to distinguish this order from other possible orders on the same product type.*)\nNotation \"T *lexi[ d ] T'\" := (type d T T')\n (at level 70, d at next level, format \"T *lexi[ d ] T'\") : type_scope.\n(*This notation is a shorthand for the Cartesian product of two ordered types endowed with the lexicographic order, used when the display parameter for the order can be inferred from the context.*)\nNotation \"T *l T'\" := (type_ T T')\n (at level 70, format \"T *l T'\") : type_scope.\n\n(*This definition provides the characterization of the non-strict lexicographic order relation on pairs. It states that a pair is less than or equal to another pair if and only if the first element of the first pair is strictly less than the first element of the second pair, or if the first elements are equal and the second element of the first pair is less than or equal to the second element of the second pair.*)\nDefinition leEprodlexi := @leEprodlexi.\n(*This definition provides the characterization of the strict lexicographic order relation on pairs. It states that a pair is strictly less than another pair if and only if the first element of the first pair is strictly less than the first element of the second pair, or if the first elements are equal and the second element of the first pair is strictly less than the second element of the second pair.*)\nDefinition ltEprodlexi := @ltEprodlexi.\n(*This definition provides a rule for constructing a proof of non-strict lexicographic comparison. It establishes that a pair is less than or equal to another pair if either the first element of the one pair is strictly less than the first element of the other, or if their first elements are equal and the second element of the one pair is less than or equal to the second element of the other.*)\nDefinition lexi_pair := @lexi_pair.\n(*This definition provides a rule for constructing a proof of strict lexicographic comparison. It establishes that a pair is strictly less than another pair if either the first element of the one pair is strictly less than the first element of the other, or if their first elements are equal and the second element of the one pair is strictly less than the second element of the other.*)\nDefinition ltxi_pair := @ltxi_pair.\n(*This definition states that the greatest element in the lexicographic product order of two types with greatest elements is the pair formed by the greatest element of the first type and the greatest element of the second type.*)\nDefinition topEprodlexi := @topEprodlexi.\n(*This definition states that the least element in the lexicographic product order of two types with least elements is the pair formed by the least element of the first type and the least element of the second type.*)\nDefinition botEprodlexi := @botEprodlexi.\n(*This definition constructs a sub-preorder structure on a subset of a lexicographic product of two preordered types, using the order inherited from the parent product type.*)\nDefinition sub_prod_lexi := @sub_prod_lexi.\n\nEnd Exports.\nEnd ProdLexiOrder.\nHB.export ProdLexiOrder.Exports.\n\nModule DefaultProdLexiOrder.\nSection DefaultProdLexiOrder.\nContext {disp1 disp2 : disp_t}.\n\n(*This definition provides a local alias for the type representing the lexicographic product of two ordered types, parameterized by their respective display settings.*)\nLet prodlexi T1 T2 := T1 *lexi[lexi_display disp1 disp2] T2.\n\nHB.instance Definition _ (T1 : preorderType disp1) (T2 : preorderType disp2) :=\n Preorder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _ (T1 : bPreorderType disp1) (T2 : bPreorderType disp2) :=\n BPreorder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _ (T1 : tPreorderType disp1) (T2 : tPreorderType disp2) :=\n TPreorder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _ (T1 : tbPreorderType disp1) (T2 : tbPreorderType disp2) :=\n TBPreorder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _\n (T1 : finPreorderType disp1) (T2 : finPreorderType disp2) :=\n FinPreorder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _\n (T1 : finBPreorderType disp1) (T2 : finBPreorderType disp2) :=\n FinBPreorder.copy (T1 * T2)%type (prodlexi T1 T2).\nHB.instance Definition _\n (T1 : finTPreorderType disp1) (T2 : finTPreorderType disp2) :=\n FinTPreorder.copy (T1 * T2)%type (prodlexi T1 T2).\n(*This definition sets the carrier of a tuple preorder structure to be the type of fixed-length tuples of a given length and underlying element type.*)\nDefinition type (disp : disp_t) T := seq T.\n(*This definition creates a type alias for a finite sequence over a preordered base type, intended to be used with the sequence product order.*)\nDefinition type_ (disp : disp_t) (T : preorderType disp) :=\n type (seqprod_display disp) T.\n\nContext {disp disp' : disp_t}.\n\n(*This local notation creates an alias named 'seq' for the carrier type of a sequence preorder structure, used to simplify type expressions within its scope.*)\nLocal Notation seq := (type disp').\n\n#[export] HB.instance Definition _ (T : eqType) := Equality.on (seq T).\n#[export] HB.instance Definition _ (T : choiceType) := Choice.on (seq T).\n(*This fixpoint definition specifies a less-than-or-equal-to relation for finite sequences. A sequence is considered less than or equal to another if its length is no greater than the other's, and each of its elements is less than or equal to the corresponding element in the other sequence.*)\nFixpoint le s1 s2 := if s1 isn't x1 :: s1' then true else\n if s2 isn't x2 :: s2' then false else\n (x1 <= x2) && le s1' s2'.\n\n(*This fact establishes that the pullback less-than-or-equal relation is reflexive.*)\nFact refl : reflexive le. \n\n(*This fact establishes that the pullback less-than-or-equal relation is transitive.*)\nFact trans : transitive le.\n\n#[export]\nHB.instance Definition _ := isPreorder.Build disp' (seq T) (rrefl _) refl trans.\n\n(*This lemma provides a computational equivalence for the less-than-or-equal-to relation on finite sequences. It states that the comparison is true if the first sequence is empty, false if the first is non-empty and the second is empty, and otherwise is determined by the logical conjunction of the comparison of the heads and the recursive comparison of the tails.*)\nLemma leEseq s1 s2 : s1 <= s2 = if s1 isn't x1 :: s1' then true else\n if s2 isn't x2 :: s2' then false else\n (x1 <= x2) && (s1' <= s2' :> seq _).\n\n(*This lemma states that the empty sequence is less than or equal to any other finite sequence under the pointwise order.*)\nLemma le0s s : [::] <= s :> seq _. \n\n(*This lemma states that a finite sequence is less than or equal to the empty sequence under the pointwise order if and only if that sequence is itself empty.*)\nLemma les0 s : s <= [::] = (s == [::]). \n\n(*This lemma states that a non-empty finite sequence is less than or equal to another non-empty finite sequence if and only if their first elements are in relation and their tails are also in relation under the pointwise order.*)\nLemma le_cons x1 s1 x2 s2 :\n x1 :: s1 <= x2 :: s2 :> seq _ = (x1 <= x2) && (s1 <= s2).\n\n#[export]\n(*This lemma asserts that the bottom element, which is the least element, in the preorder of finite sequences under the pointwise order is the empty sequence.*)\nLemma botEseq : \\bot = [::] :> seq T.\n\nEnd Preorder.\n\nEnd SeqProdOrder.\n\nModule Exports.\n\nHB.reexport SeqProdOrder.\n\n(*A notation for a finite sequence type built from a base type and an explicit display parameter, used to construct a sequence type with a specified order structure.*)\nNotation seqprod_with := type.\n(*A notation for a finite sequence type that inherits its pointwise product order structure from a preordered base type.*)\nNotation seqprod := type_.\n\n(*This lemma states that the pointwise less-than-or-equal relation on finite sequences holds if and only if the sequences have the same length and their corresponding elements are pairwise less than or equal. Recursively, this means the relation holds if both sequences are empty, or if they are both non-empty, their first elements are less than or equal, and their tails are recursively in relation.*)\nDefinition leEseq := @leEseq.\n(*This lemma specifies the behavior of the pointwise product order when the first sequence is empty, stating that an empty sequence is less than or equal to another sequence if and only if the second sequence is also empty.*)\nDefinition le0s := @le0s.\n(*This lemma specifies the behavior of the pointwise product order when the second sequence is empty, stating that a sequence is less than or equal to an empty sequence if and only if the first sequence is also empty.*)\nDefinition les0 := @les0.\n(*This lemma provides the recursive step for the pointwise product order on non-empty sequences, asserting that a sequence starting with a given element is less than or equal to another such sequence if and only if their initial elements are less than or equal and their remaining tails also satisfy the relation.*)\nDefinition le_cons := @le_cons.\n(*This lemma states that the designated bottom element for the type of sequences under the pointwise product order is the empty sequence.*)\nDefinition botEseq := @botEseq.\n\nEnd Exports.\nEnd SeqProdOrder.\nHB.export SeqProdOrder.Exports.\n\nModule DefaultSeqProdOrder.\nSection DefaultSeqProdOrder.\nContext {disp : disp_t}.\n\n(*This notation provides a shorthand for creating a sequence type that is equipped with the pointwise product order, derived from the order of its elements.*)\nNotation seqprod := (seqprod_with (seqprod_display disp)).\n\nHB.instance Definition _ (T : preorderType disp) :=\n Preorder.copy (seq T) (seqprod T).\n(*This definition introduces a generic alias for the type of finite sequences over a given base type, which will be used as the carrier for the lexicographic order structure.*)\nDefinition type (disp : disp_t) T := seq T.\n(*This definition creates a canonical alias for the type of finite sequences over a given preorder type, specifically for use with the lexicographic order.*)\nDefinition type_ (disp : disp_t) (T : preorderType disp) :=\n type (seqlexi_display disp) T.\n\nContext {disp disp' : disp_t}.\n\n(*This notation provides a local shorthand for the type of finite sequences within the context where the lexicographic order is being defined.*)\nLocal Notation seq := (type disp').\n\n#[export] HB.instance Definition _ (T : eqType) := Equality.on (seq T).\n#[export] HB.instance Definition _ (T : choiceType) := Choice.on (seq T).\n(*This definition establishes the lexicographic less-than-or-equal relation between two finite sequences, defined recursively by comparing elements from left to right.*)\nFixpoint le s1 s2 := if s1 isn't x1 :: s1' then true else\n if s2 isn't x2 :: s2' then false else\n (x1 <= x2) && ((x1 >= x2) ==> le s1' s2').\n(*This definition establishes the strict lexicographic less-than relation between two finite sequences, defined recursively by comparing elements from left to right.*)\nFixpoint lt s1 s2 := if s2 isn't x2 :: s2' then false else\n if s1 isn't x1 :: s1' then true else\n (x1 <= x2) && ((x1 >= x2) ==> lt s1' s2').\n\n(*This fact proves that the lexicographic less-than-or-equal relation on finite sequences is reflexive, meaning any sequence is less than or equal to itself.*)\nFact refl: reflexive le.\n\n(*This fact proves that the lexicographic less-than-or-equal relation on finite sequences is transitive.*)\nFact trans: transitive le.\n\n(*This lemma states that a finite sequence is strictly lexicographically less than another if and only if it is less than or equal to the other, but the other is not less than or equal to it.*)\nLemma lt_le_def s1 s2 : lt s1 s2 = le s1 s2 && ~~ le s2 s1.\n\n#[export]\nHB.instance Definition _ := isPreorder.Build disp' (seq T) lt_le_def refl trans.\n\n(*This lemma provides an equational characterization for the lexicographic less-than-or-equal relation on finite sequences, expanding the relation based on whether the sequences are empty or constructed from an element and a tail.*)\nLemma leEseqlexi s1 s2 :\n s1 <= s2 = if s1 isn't x1 :: s1' then true else\n if s2 isn't x2 :: s2' then false else\n (x1 <= x2) && ((x1 >= x2) ==> (s1' <= s2' :> seq T)).\n\n(*This lemma provides an equational characterization for the strict lexicographic less-than relation on finite sequences, expanding the relation based on whether the sequences are empty or constructed from an element and a tail.*)\nLemma ltEseqlexi s1 s2 :\n s1 < s2 = if s2 isn't x2 :: s2' then false else\n if s1 isn't x1 :: s1' then true else\n (x1 <= x2) && ((x1 >= x2) ==> (s1' < s2' :> seq T)).\n\n(*This lemma states that the empty sequence is lexicographically less than or equal to any other finite sequence, establishing it as the bottom element.*)\nLemma lexi0s s : [::] <= s :> seq T. \n\n(*This lemma states that a finite sequence is lexicographically less than or equal to the empty sequence if and only if that sequence is itself empty.*)\nLemma lexis0 s : s <= [::] = (s == [::]). \n\n(*This lemma states that the empty sequence is strictly lexicographically less than another finite sequence if and only if the other sequence is not empty.*)\nLemma ltxi0s s : ([::] < s :> seq T) = (s != [::]). \n\n(*This lemma states that it is always false for a finite sequence to be strictly lexicographically less than the empty sequence.*)\nLemma ltxis0 s : s < [::] = false. \n\n(*This lemma characterizes the lexicographic less-than-or-equal comparison for two non-empty finite sequences. The relation holds if the first element of the first sequence is strictly less than the first element of the second, or if the first elements are equivalent and the tail of the first sequence is less than or equal to the tail of the second.*)\nLemma lexi_cons x1 s1 x2 s2 :\n x1 :: s1 <= x2 :: s2 :> seq T = (x1 <= x2) && ((x1 >= x2) ==> (s1 <= s2)).\n\n(*This lemma characterizes the strict lexicographic less-than comparison for two non-empty finite sequences. The relation holds if the first element of the first sequence is strictly less than the first element of the second, or if the first elements are equivalent and the tail of the first sequence is strictly less than the tail of the second.*)\nLemma ltxi_cons x1 s1 x2 s2 :\n x1 :: s1 < x2 :: s2 :> seq T = (x1 <= x2) && ((x1 >= x2) ==> (s1 < s2)).\n\n(*This lemma asserts that if a non-empty finite sequence is lexicographically less than or equal to another, then its head element must be less than or equal to the head element of the other sequence.*)\nLemma lexi_lehead x s1 y s2 : x :: s1 <= y :: s2 :> seq T -> x <= y.\n\n(*This lemma asserts that if a non-empty finite sequence is strictly lexicographically less than another, then its head element must be less than or equal to the head element of the other sequence.*)\nLemma ltxi_lehead x s1 y s2 : x :: s1 < y :: s2 :> seq T -> x <= y.\n\n(*This lemma simplifies a lexicographical comparison, stating that if two non-empty finite sequences have the same head element, the less-than-or-equal relation between them is equivalent to the relation between their tails.*)\nLemma eqhead_lexiE (x : T) s1 s2 : (x :: s1 <= x :: s2 :> seq _) = (s1 <= s2).\n\n(*This lemma simplifies a strict lexicographical comparison, stating that if two non-empty finite sequences have the same head element, the strict less-than relation between them is equivalent to the strict relation between their tails.*)\nLemma eqhead_ltxiE (x : T) s1 s2 : (x :: s1 < x :: s2 :> seq _) = (s1 < s2).\n\n#[export]\n(*This lemma states that the pointwise product order on finite sequences is a subrelation of the lexicographic order. In other words, if one sequence is less than or equal to another in the pointwise product order, it is also less than or equal to it in the lexicographic order.*)\nLemma sub_seqprod_lexi d (T : preorderType disp) :\n subrel (<=%O : rel (seqprod_with d T)) (<=%O : rel (seq T)).\n\nEnd SeqLexiOrder.\n\nModule Exports.\n\nHB.reexport SeqLexiOrder.\n\n(*This notation serves as a factory for creating a sequence type equipped with the lexicographic order, taking a display parameter to resolve the order on the sequence elements.*)\nNotation seqlexi_with := type.\n(*This notation provides the canonical way to refer to the type of finite sequences over a given preorder type, implicitly equipped with the lexicographic order.*)\nNotation seqlexi := type_.\n\n(*This lemma states that the non-strict less-than-or-equal relation for sequences under the lexicographic order holds if and only if the corresponding boolean predicate for non-strict lexicographic comparison evaluates to true.*)\nDefinition leEseqlexi := @leEseqlexi.\n(*This lemma states that the empty sequence is lexicographically less than or equal to any non-empty sequence.*)\nDefinition lexi0s := @lexi0s.\n(*This lemma states that a non-empty sequence is never lexicographically less than or equal to the empty sequence.*)\nDefinition lexis0 := @lexis0.\n(*This lemma provides a recursive characterization for the non-strict lexicographic comparison of two non-empty sequences. It asserts that one sequence is less than or equal to another if and only if their first elements are in a strict less-than relationship, or their first elements are equal and the remainder of the first sequence is lexicographically less than or equal to the remainder of the second.*)\nDefinition lexi_cons := @lexi_cons.\n(*This lemma states that if the first element of one non-empty sequence is strictly less than the first element of another, then the first sequence is lexicographically less than or equal to the second, regardless of their tails.*)\nDefinition lexi_lehead := @lexi_lehead.\n(*This lemma provides an equivalence for comparing two non-empty sequences with identical first elements under non-strict lexicographic order. It states that the comparison is equivalent to the non-strict lexicographic comparison of the remaining subsequences.*)\nDefinition eqhead_lexiE := @eqhead_lexiE.\n\n(*This lemma states that the strict less-than relation for sequences under the lexicographic order holds if and only if the corresponding boolean predicate for strict lexicographic comparison evaluates to true.*)\nDefinition ltEseqltxi := @ltEseqlexi.\n(*This lemma states that the empty sequence is strictly lexicographically less than any non-empty sequence.*)\nDefinition ltxi0s := @ltxi0s.\n(*This lemma states that a non-empty sequence is never strictly lexicographically less than the empty sequence.*)\nDefinition ltxis0 := @ltxis0.\n(*This lemma provides a recursive characterization for the strict lexicographic comparison of two non-empty sequences. It asserts that one sequence is strictly less than another if and only if their first elements are in a strict less-than relationship, or their first elements are equal and the remainder of the first sequence is strictly lexicographically less than the remainder of the second.*)\nDefinition ltxi_cons := @ltxi_cons.\n(*This lemma states that if the first element of one non-empty sequence is strictly less than the first element of another, then the first sequence is strictly lexicographically less than the second, regardless of their tails.*)\nDefinition ltxi_lehead := @ltxi_lehead.\n(*This lemma provides an equivalence for strictly comparing two non-empty sequences with identical first elements under lexicographic order. It states that the comparison is equivalent to the strict lexicographic comparison of the remaining subsequences.*)\nDefinition eqhead_ltxiE := @eqhead_ltxiE.\n(*This lemma states that the component-wise product order on sequences is a subrelation of the lexicographic order. Specifically, if one sequence is less than or equal to another in the component-wise ordering, it is also less than or equal to it in the lexicographic ordering.*)\nDefinition sub_seqprod_lexi := @sub_seqprod_lexi.\n\nEnd Exports.\nEnd SeqLexiOrder.\nHB.export SeqLexiOrder.Exports.\n\nModule DefaultSeqLexiOrder.\nSection DefaultSeqLexiOrder.\nContext {disp : disp_t}.\n\n(*This notation defines a type for sequences equipped with the lexicographic order, using a display parameter to manage concrete notations.*)\nNotation seqlexi := (seqlexi_with (seqlexi_display disp)).\n\nHB.instance Definition _ (T : preorderType disp) :=\n Preorder.copy (seq T) (seqlexi T).\n(*This definition sets the carrier of a tuple preorder structure to be the type of fixed-length tuples of a given length and underlying element type.*)\nDefinition type (disp : disp_t) n T := n.-tuple T.\n(*This definition provides a local alias for the type of tuples of a given length, explicitly specifying that they are equipped with the component-wise product order.*)\nDefinition type_ (disp : disp_t) n (T : preorderType disp) :=\n type (seqprod_display disp) n T.\n\nContext {disp disp' : disp_t}.\n(**)\nLocal Notation \"n .-tuple\" := (type disp' n) : type_scope.\n\nSection Basics.\nContext (n : nat).\n#[export] HB.instance Definition _ (T : eqType) := Equality.on (n.-tuple T).\n#[export] HB.instance Definition _ (T : eqType) := SubEquality.on (n.-tuple T).\n#[export] HB.instance Definition _ (T : choiceType) :=\n SubChoice.on (n.-tuple T).\n#[export] HB.instance Definition _ (T : countType) :=\n SubCountable.on (n.-tuple T).\n(*This lemma states that for two tuples under the product order, one tuple is less than or equal to another if and only if every element of the first tuple is less than or equal to its corresponding element in the second tuple.*)\nLemma leEtprod n T (t1 t2 : n.-tuple T) :\n t1 <= t2 = [forall i, tnth t1 i <= tnth t2 i].\n\n(*This lemma states that for two tuples under the product order, one tuple is strictly less than another if and only if all elements of the first tuple are less than or equal to their corresponding elements in the second, and at least one element is strictly smaller.*)\nLemma ltEtprod n T (t1 t2 : n.-tuple T) :\n t1 < t2 = [exists i, tnth t1 i < tnth t2 i] &&\n [forall i, tnth t1 i <= tnth t2 i].\n\nEnd Preorder.\n\nSection BPreorder.\nContext (n : nat) (T : bPreorderType disp).\nImplicit Types (t : n.-tuple T).\n\n(*This lemma states that for tuples equipped with a component-wise preorder, the tuple consisting entirely of bottom elements is the minimum element, meaning it is less than or equal to any other tuple of the same length.*)\nFact le0x t : [tuple \\bot | _ < n] <= t :> n.-tuple T.\n\n#[export]\n(*This lemma states that the bottom element in the product order of tuples is precisely the tuple where every component is the bottom element of the underlying type.*)\nLemma botEtprod : \\bot = [tuple \\bot | _ < n] :> n.-tuple T.\n\nEnd BPreorder.\n\nSection TPreorder.\nContext (n : nat) (T : tPreorderType disp).\nImplicit Types (t : n.-tuple T).\n\n(*This fact asserts that a tuple consisting entirely of top elements is the maximal element in the product order, meaning any other tuple of the same length is less than or equal to it.*)\nFact lex1 t : t <= [tuple \\top | _ < n] :> n.-tuple T.\n\n#[export]\n(*This lemma states that the top element in the product order of tuples is precisely the tuple where every component is the top element of the underlying type.*)\nLemma topEtprod : \\top = [tuple \\top | _ < n] :> n.-tuple T.\n\nEnd TPreorder.\n\n#[export]\nHB.instance Definition _ (n : nat) (T : tbPreorderType disp) :=\n Preorder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finPreorderType disp) :=\n Preorder.on (n.-tuple T).\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (n : nat) (T : finPreorderType disp) :=\n Preorder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finBPreorderType disp) :=\n Preorder.on (n.-tuple T).\n#[export]\nHB.instance Definition _ (n : nat) (T : finTPreorderType disp) :=\n Preorder.on (n.-tuple T).\n#[export]\n(*This notation provides a syntax for the type of tuples of a specified length, equipped with the product order, allowing for an explicit order display parameter to be provided.*)\nNotation \"n .-tupleprod[ disp ]\" := (type disp n)\n (at level 2, disp at next level, format \"n .-tupleprod[ disp ]\") :\n type_scope.\n(*This notation provides a shorthand syntax for the type of tuples of a specified length, equipped with the default component-wise product order.*)\nNotation \"n .-tupleprod\" := (type_ n)\n (at level 2, format \"n .-tupleprod\") : type_scope.\n\n(*This lemma asserts that for two tuples, the first is less than or equal to the second under the product order if and only if each element of the first tuple is less than or equal to the corresponding element of the second tuple.*)\nDefinition leEtprod := @leEtprod.\n(*This lemma asserts that for two tuples, the first is strictly less than the second under the product order if and only if every element of the first tuple is less than or equal to the corresponding element of the second, and at least one element of the first tuple is strictly less than its corresponding element in the second.*)\nDefinition ltEtprod := @ltEtprod.\n(*This lemma states that the bottom element of a tuple type equipped with the product order is the tuple where every entry is the bottom element of the underlying component type.*)\nDefinition botEtprod := @botEtprod.\n(*This lemma states that the top element of a tuple type equipped with the product order is the tuple where every entry is the top element of the underlying component type.*)\nDefinition topEtprod := @topEtprod.\n\nEnd Exports.\nEnd TupleProdOrder.\nHB.export TupleProdOrder.Exports.\n\nModule DefaultTupleProdOrder.\nSection DefaultTupleProdOrder.\nContext {disp : disp_t}.\n\n(*This notation represents the type of fixed-length sequences, or n-tuples, endowed with the product order. Under this order, one tuple is considered less than or equal to another if and only if each element of the first tuple is less than or equal to the corresponding element in the second tuple.*)\nNotation \"n .-tupleprod\" := n.-tupleprod[seqprod_display disp].\n\nHB.instance Definition _ n (T : preorderType disp) :=\n Preorder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : bPreorderType disp) :=\n BPreorder.copy (n.-tuple T) (n.-tupleprod T).\nHB.instance Definition _ n (T : tPreorderType disp) :=\n TPreorder.copy (n.-tuple T) (n.-tupleprod T).\n(*This definition establishes the carrier type for ordered n-tuples, which is the type of finite sequences of a specified length over a base type.*)\nDefinition type (disp : disp_t) n T := n.-tuple T.\n(*This definition specifies the carrier type for n-tuples equipped with the lexicographic order, using a display derived from the component type's display.*)\nDefinition type_ (disp : disp_t) n (T : preorderType disp) :=\n type (seqlexi_display disp) n T.\n\nContext {disp disp' : disp_t}.\n(*This notation represents the type of a finite sequence of a fixed length, also known as an n-tuple. An object of this type is a collection of a specified number of elements, all of which belong to the same underlying base type.*)\nLocal Notation \"n .-tuple\" := (type disp' n) : type_scope.\n\nSection Basics.\nContext (n : nat).\n#[export] HB.instance Definition _ (T : eqType) := Equality.on (n.-tuple T).\n#[export] HB.instance Definition _ (T : choiceType) :=\n SubChoice.on (n.-tuple T).\n#[export] HB.instance Definition _ (T : countType) :=\n SubCountable.on (n.-tuple T).\n(*This lemma states that a tuple composed entirely of bottom elements is less than or equal to any other tuple of the same length under the lexicographic order.*)\nFact le0x t : [tuple \\bot | _ < n] <= t :> n.-tuple T.\n\n(*This lemma asserts that the bottom element for the type of n-tuples under the lexicographic order is precisely the tuple where every component is the bottom element of the base type.*)\nLemma botEtlexi : \\bot = [tuple \\bot | _ < n] :> n.-tuple T. \n\nEnd BPreorder.\n\nSection TPreorder.\nContext (n : nat) (T : tPreorderType disp).\nImplicit Types (t : n.-tuple T).\n\n(*This lemma states that any given tuple is less than or equal to the tuple composed entirely of top elements of the same length under the lexicographic order.*)\nFact lex1 t : t <= [tuple \\top | _ < n].\n\n(*This lemma asserts that the top element for the type of n-tuples under the lexicographic order is precisely the tuple where every component is the top element of the base type.*)\nLemma topEtlexi : \\top = [tuple \\top | _ < n] :> n.-tuple T. \n\nEnd TPreorder.\n\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (n : nat) (T : bPreorderType disp) :=\n Preorder.on (n.-tuple T).\n#[export, warning=\"-HB.no-new-instance\"]\nHB.instance Definition _ (n : nat) (T : tPreorderType disp) :=\n Preorder.on (n.-tuple T).\n#[export]\n(*This lemma states that the component-wise product order on n-tuples is a subrelation of the lexicographic order, meaning that if one tuple is less than or equal to another in the product order, it is also less than or equal in the lexicographic order.*)\nLemma sub_tprod_lexi d n (T : preorderType disp) :\n subrel (<=%O : rel (n.-tupleprod[d] T)) (<=%O : rel (n.-tuple T)).\n\nEnd TupleLexiOrder.\n\nModule Exports.\n\nHB.reexport TupleLexiOrder.\n\n(*This notation refers to the type of fixed-length sequences, or n-tuples, equipped with an order relation that is determined by a provided display parameter. While the name suggests its primary use is for lexicographic orders, it can represent any order structure associated with the given display.*)\nNotation \"n .-tuplelexi[ disp ]\" := (type disp n)\n (at level 2, disp at next level, format \"n .-tuplelexi[ disp ]\") :\n type_scope.\n(*This notation represents the type of fixed-length sequences, or n-tuples, equipped with the lexicographic order. When comparing two tuples, the order is determined by the first pair of corresponding elements that are not equal, similar to how words are ordered in a dictionary.*)\nNotation \"n .-tuplelexi\" := (type_ n)\n (at level 2, format \"n .-tuplelexi\") : type_scope.\n\n(*This lemma states that the greatest element of a tuple type equipped with lexicographic order is the tuple where each component is the greatest element of the base type.*)\nDefinition topEtlexi := @topEtlexi.\n(*This lemma states that the least element of a tuple type equipped with lexicographic order is the tuple where each component is the least element of the base type.*)\nDefinition botEtlexi := @botEtlexi.\n(*This lemma states that if a tuple is less than or equal to another in the component-wise product order, it is also less than or equal to it in the lexicographic order.*)\nDefinition sub_tprod_lexi := @sub_tprod_lexi.\n\nEnd Exports.\nEnd TupleLexiOrder.\nHB.export TupleLexiOrder.Exports.\n\nModule DefaultTupleLexiOrder.\nSection DefaultTupleLexiOrder.\nContext {disp : disp_t}.\n\n(*A notation for the type of fixed-length sequences, or tuples, of a given length, where the tuples are ordered lexicographically. The lexicographic comparison proceeds element by element from left to right, and the first position where elements differ determines the order of the tuples.*)\nNotation \"n .-tuplelexi\" := n.-tuplelexi[seqlexi_display disp].\n\nHB.instance Definition _ n (T : preorderType disp) :=\n Preorder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : bPreorderType disp) :=\n BPreorder.copy (n.-tuple T) (n.-tuplelexi T).\nHB.instance Definition _ n (T : tPreorderType disp) :=\n TPreorder.copy (n.-tuple T) (n.-tuplelexi T).\n(*A constant display parameter used to associate the standard subset relation on finite sets with generic order notations.*)\nFact subset_display : disp_t. \n\n(*This definition establishes the carrier type for an order structure on sets, which is the type of finite sets over a given finite base type. The structure is parameterized by a display.*)\nDefinition type (disp : disp_t) (T : finType) := {set T}.\n\nContext {disp : disp_t} {T : finType}.\n(*A notation for the type of finite sets over a given finite base type, implicitly equipped with the standard subset relation as its order.*)\nLocal Notation \"{ 'subset' T }\" := (type disp T).\nImplicit Type (A B C : {subset T}).\n\n(*This lemma provides an alternative definition for the subset relation between two finite sets, stating that one set is a subset of another if and only if their intersection is equal to the first set.*)\nLemma le_def A B : A \\subset B = (A :&: B == A).\n\n#[export]\nHB.instance Definition _ := Choice.on {subset T}.\n\n#[export]\nHB.instance Definition _ := Le_isPreorder.Build disp {subset T}\n (@subxx _ _) (fun A B => @subset_trans _ B A).\n\n#[export]\nHB.instance Definition _ := hasBottom.Build disp {subset T} (@sub0set _).\n\n#[export]\n(*This lemma states that for finite sets equipped with the subset order, the generic less-than-or-equal relation is equivalent to the subset relation.*)\nLemma leEsubset A B : (A <= B) = (A \\subset B).\n\nEnd SetSubsetOrder.\n\nModule Exports.\nArguments type disp T%_type.\n(*A notation for the type of finite sets over a given finite base type, equipped with an order structure determined by a specified display parameter.*)\nNotation \"{ 'subset' [ d ] T }\" := (type d T)\n (d at next level, format \"{ 'subset' [ d ] T }\") : type_scope.\n(*A notation that represents the type of finite sets whose elements are drawn from a given base type, typically used in contexts involving the subset order.*)\nNotation \"{ 'subset' T }\" := {subset[subset_display] T}\n (format \"{ 'subset' T }\") : type_scope.\n\nHB.reexport.\n\n(*This definition provides an equivalence between the generic 'less-than-or-equal-to' relation and the subset inclusion relation when applied to finite sets.*)\nDefinition leEsubset := @leEsubset.\n\nEnd Exports.\nEnd SetSubsetOrder.\nExport SetSubsetOrder.Exports.\n\nModule DefaultSetSubsetOrder.\n\n(*This lemma states that the cardinality of a set of elements from a finite preordered type is equal to the length of the finite sequence that enumerates its elements in sorted order.*)\nLemma cardE (A : {pred T}) : #|A| = size (enum A).\n\n(*This lemma states that the sorted enumeration of a set of elements from a finite preordered type contains exactly the same elements as the original set.*)\nLemma mem_enum (A : {pred T}) : enum A =i A.\n\n(*This lemma states that the sorted enumeration of a set of elements from a finite preordered type results in a finite sequence containing no duplicate elements.*)\nLemma enum_uniq (A : {pred T}) : uniq (enum A).\n\n(*This lemma states that the cardinality of a finite preordered type is equal to the length of the finite sequence containing all its elements in sorted order.*)\nLemma cardT : #|T| = size (enum T).\n\n(*This lemma states that the sorted enumeration of all elements in a finite preordered type is equivalent to sorting the standard, unsorted enumeration of that type according to its preorder relation.*)\nLemma enumT : enum T = sort <=%O (Finite.enum T).\n\n(*This lemma states that the sorted enumeration of the empty set is an empty finite sequence.*)\nLemma enum0 : enum (pred0 : {pred T}) = [::].\n\n(*This lemma states that the sorted enumeration of a singleton set containing a single element is a finite sequence containing only that element.*)\nLemma enum1 (x : T) : enum (pred1 x) = [:: x].\n\n(*This lemma states that if two sets have the same elements, then their respective sorted enumerations will be identical finite sequences.*)\nLemma eq_enum (A B : {pred T}) : A =i B -> enum A = enum B.\n\n(*This lemma states that if a set contains all the elements of a finite preordered type, its cardinality is equal to the length of the sorted enumeration of the entire type.*)\nLemma eq_cardT (A : {pred T}) : A =i predT -> #|A| = size (enum T).\n\n(*This lemma states that converting the sorted enumeration of a finite set back into a set yields the original finite set.*)\nLemma set_enum (A : {set T}) : [set x in enum A] = A.\n\n(*This lemma states that the sorted enumeration of the empty finite set is an empty finite sequence.*)\nLemma enum_set0 : enum (set0 : {set T}) = [::].\n\n(*This lemma states that the sorted enumeration of the set containing all elements of a finite preordered type is equivalent to sorting the standard enumeration of the type.*)\nLemma enum_setT : enum [set: T] = sort <=%O (Finite.enum T).\n\n(*This lemma states that the sorted enumeration of a singleton finite set is a finite sequence containing only that element.*)\nLemma enum_set1 (a : T) : enum [set a] = [:: a].\n\nEnd Enum.\n\nSection Ordinal.\nImport OrdinalOrder.Exports.\n\n(*This lemma states that the sorted enumeration of the type of ordinals less than a given natural number is identical to its standard, unsorted enumeration.*)\nLemma enum_ord n : enum 'I_n = fintype.enum 'I_n.\n\n(*This lemma states that applying the 'val' operation, which converts an ordinal to its underlying natural number, to each element of the sorted enumeration of ordinals less than a given number `n` yields the sequence of natural numbers from zero to `n-1`.*)\nLemma val_enum_ord n : [seq val i | i <- enum 'I_n] = iota 0 n.\n\n(*This lemma states that the length of the sorted enumeration of the type of ordinals less than a given natural number `n` is equal to `n`.*)\nLemma size_enum_ord n : size (enum 'I_n) = n.\n\n(*This lemma states that for any natural number `m` less than `n`, the underlying natural number value of the `m`-th element in the sorted enumeration of ordinals less than `n` is equal to `m`.*)\nLemma nth_enum_ord (n : nat) (i0 : 'I_n) (m : nat) :\n (m < n)%N -> nth i0 (enum 'I_n) m = m :> nat.\n\n(*This lemma states that for any ordinal `i` less than `n`, the element at the index corresponding to `i` in the sorted enumeration of ordinals less than `n` is `i` itself.*)\nLemma nth_ord_enum (n : nat) (i0 i : 'I_n) : nth i0 (enum 'I_n) i = i.\n\n(*This lemma states that the index of a given ordinal `i` in the sorted enumeration of ordinals less than `n` is equal to the underlying natural number value of `i`.*)\nLemma index_enum_ord (n : nat) (i : 'I_n) : index i (enum 'I_n) = i.\n\nEnd Ordinal.\n\n(*This lemma states that if a function from a totally ordered finite type to a preordered type is monotonic, then the sequence obtained by applying this function to each element of the sorted enumeration of the source type is itself sorted.*)\nLemma mono_sorted_enum d d' (T : finPreorderType d)\n (T' : preorderType d') (f : T -> T') :\n total (<=%O : rel T) -> {mono f : x y / (x <= y)%O} ->\n sorted <=%O [seq f x | x <- enum T].\n\nModule Import EnumVal.\nSection EnumVal.\nImport OrdinalOrder.Exports.\nVariables (d : disp_t) (T : finPreorderType d).\nImplicit Types (x : T) (A : {pred T}).\n\n(*This definition computes the rank of an element within a given subset of a finite preordered type as the ordinal corresponding to its zero-based index in the sorted enumeration of that subset.*)\nDefinition enum_rank_in x0 A (Ax0 : x0 \\in A) x :=\n insubd (Ordinal (@enum_rank_subproof _ x0 A Ax0)) (index x (enum A)).\n\n(*This definition computes the rank of an element within its entire finite preordered type, which is its zero-based index in the sorted enumeration of all elements of the type.*)\nDefinition enum_rank x := @enum_rank_in x T (erefl true) x.\n\n(*This definition retrieves the element at a specific rank from a given subset of a finite preordered type by accessing the element at the corresponding index in the subset's sorted enumeration.*)\nDefinition enum_val A i := nth (@enum_default _ A i) (enum A) i.\nPrenex Implicits enum_val.\n\n(*This lemma states that the element corresponding to a given rank within a subset, as returned by the `enum_val` function, is a member of that subset.*)\nLemma enum_valP A i : @enum_val A i \\in A.\n\n(*This lemma states that retrieving an element by its rank from a subset is equivalent to retrieving the element at the corresponding index from the subset's sorted enumeration sequence, using a specified default element.*)\nLemma enum_val_nth A x i : @enum_val A i = nth x (enum A) i.\n\n(*This lemma states that for any element within a given subset, applying the ranking function `enum_rank_in` and then the value retrieval function `enum_val` returns the original element, confirming they are inverse operations on that subset.*)\nLemma nth_enum_rank_in x00 x0 A Ax0 :\n {in A, cancel (@enum_rank_in x0 A Ax0) (nth x00 (enum A))}.\n\n(*This lemma states that the `enum_rank` and `enum_val` functions are inverse operations when applied over the entire finite preordered type; applying one after the other returns the original element.*)\nLemma nth_enum_rank x0 : cancel enum_rank (nth x0 (enum T)).\n\n(*This lemma states that `enum_rank_in` is a left inverse to `enum_val` for valid ranks. Specifically, taking a valid rank within a subset, retrieving the corresponding element using `enum_val`, and then computing the rank of that element using `enum_rank_in` yields the original rank.*)\nLemma enum_rankK_in x0 A Ax0 :\n {in A, cancel (@enum_rank_in x0 A Ax0) enum_val}.\n\n(*This lemma states that the ranking function is the left inverse of the element enumeration function for the entire type. Applying the rank function to the element at a given index in the ordered enumeration of the type returns the original index.*)\nLemma enum_rankK : cancel enum_rank enum_val.\n\n(*This lemma states that for any element within a given subset of a finite ordered type, applying the ranking function for that subset and then retrieving the element at the resulting rank from the ordered enumeration of the subset will return the original element.*)\nLemma enum_valK_in x0 A Ax0 : cancel enum_val (@enum_rank_in x0 A Ax0).\n\n(*This lemma states that applying the element enumeration function to the rank of any element in the finite ordered type returns the original element, establishing that the enumeration function is a left inverse to the ranking function.*)\nLemma enum_valK : cancel enum_val enum_rank.\n\n(*This lemma states that the function which computes the rank of an element within the entire finite ordered type is injective, meaning that distinct elements are always assigned distinct ranks.*)\nLemma enum_rank_inj : injective enum_rank.\n\n(*This lemma states that for any given subset of a finite ordered type, the function that maps an index to an element in the ordered enumeration of that subset is injective, meaning that distinct indices correspond to distinct elements.*)\nLemma enum_val_inj A : injective (@enum_val A).\n\n(*This lemma asserts that for any inhabited subset of a finite ordered type, the element enumeration function establishes a bijection between the set of valid rank indices and the elements of that subset.*)\nLemma enum_val_bij_in x0 A : x0 \\in A -> {on A, bijective (@enum_val A)}.\n\n(*This lemma states that for a given subset of a finite ordered type, the function that computes the rank of an element within that subset is functionally the same, regardless of which particular element from the subset is used to instantiate the ranking function.*)\nLemma eq_enum_rank_in (x0 y0 : T) A (Ax0 : x0 \\in A) (Ay0 : y0 \\in A) :\n {in A, enum_rank_in Ax0 =1 enum_rank_in Ay0}.\n\n(*This lemma establishes the injectivity of the ranking function for a subset of a finite ordered type. It states that if two elements within the subset have the same rank in the ordered enumeration of that subset, then those two elements must be identical.*)\nLemma enum_rank_in_inj (x0 y0 : T) A (Ax0 : x0 \\in A) (Ay0 : y0 \\in A) :\n {in A &, forall x y, enum_rank_in Ax0 x = enum_rank_in Ay0 y -> x = y}.\n\n(*This lemma states that the ranking function is a bijection, establishing a one-to-one correspondence between the elements of the entire finite ordered type and their rank indices.*)\nLemma enum_rank_bij : bijective enum_rank.\n\n(*This lemma states that the element enumeration function for the entire finite ordered type is a bijection, establishing a one-to-one correspondence between the rank indices and the elements of the type.*)\nLemma enum_val_bij : bijective (@enum_val T).\n\nEnd EnumVal.\nArguments enum_val {d T A}.\nArguments enum_rank {d T}.\nEnd EnumVal.\n\n(*This notation refers to a function that retrieves an element from an ordered enumeration. Given a subset of a finite preordered type and an index, it returns the element at that specific position in the sequence of elements from the subset sorted in non-decreasing order.*)\nNotation enum_val := enum_val.\n(*This notation refers to a function that computes the rank of a given element within a specified subset of a finite preordered type. The rank is the zero-based index of the element in the ordered enumeration of that subset.*)\nNotation enum_rank_in := enum_rank_in.\n(*This notation refers to a function that computes the rank of a given element within its entire finite preordered type. The rank is the zero-based index of the element in the ordered enumeration of all elements of the type.*)\nNotation enum_rank := enum_rank.\n(*This notation refers to a reflective lemma stating that an index is strictly less than the size of a given subset if and only if that index is a valid position within the ordered enumeration of that subset.*)\nNotation enum_valP := enum_valP.\n(*This notation refers to a function that retrieves an element from the ordered enumeration of a subset by its index, using a default value that is returned if the given index is out of bounds.*)\nNotation enum_val_nth := enum_val_nth.\n(*This notation refers to a lemma stating that for any element belonging to a given subset, computing its rank within that subset and then using that rank to retrieve an element from the subset's ordered enumeration recovers the original element.*)\nNotation nth_enum_rank_in := nth_enum_rank_in.\n(*This notation refers to a lemma stating that for any element in the entire finite ordered type, computing its rank and then using that rank to retrieve an element from the full ordered enumeration will recover the original element.*)\nNotation nth_enum_rank := nth_enum_rank.\n(*This notation refers to a lemma stating that the ranking function for a subset is the left inverse of the element enumeration function for that same subset. Applying the rank function to the element at a given index in the ordered enumeration of the subset returns the original index.*)\nNotation enum_rankK_in := enum_rankK_in.\n(*This lemma states that for any valid natural number index, the rank of the element corresponding to that index in an enumeration is equal to the original index.*)\nNotation enum_rankK := enum_rankK.\n(*This lemma states that for any element present in the enumeration of a finite type, retrieving the element at the rank of the given element yields the original element.*)\nNotation enum_valK_in := enum_valK_in.\n(*This lemma states that for any element of a finite type, retrieving the element at the rank of the given element yields the original element.*)\nNotation enum_valK := enum_valK.\n(*This lemma asserts that the rank function for an enumeration is injective, meaning that distinct elements are always assigned distinct ranks.*)\nNotation enum_rank_inj := enum_rank_inj.\n(*This lemma asserts that the value function for an enumeration is injective, meaning that distinct numerical indices always correspond to distinct elements.*)\nNotation enum_val_inj := enum_val_inj.\n(*This lemma establishes that the enumeration value function is a bijection between the set of valid numerical indices and the set of elements present in the enumeration.*)\nNotation enum_val_bij_in := enum_val_bij_in.\n(*This lemma states that two elements present in an enumeration are equal if and only if their ranks are equal.*)\nNotation eq_enum_rank_in := eq_enum_rank_in.\n(*This lemma asserts that the rank function is injective when restricted to the elements that are included in the enumeration, meaning that distinct elements within the enumeration will always have distinct ranks.*)\nNotation enum_rank_in_inj := enum_rank_in_inj.\n(*This lemma establishes that the rank function for an enumeration is a bijection from the elements of a finite type to the set of valid numerical indices.*)\nNotation enum_rank_bij := enum_rank_bij.\n(*This lemma establishes that the value function for an enumeration is a bijection from the set of valid numerical indices to the elements of a finite type.*)\nNotation enum_val_bij := enum_val_bij.\n\nModule Syntax.\nExport PreOSyntax.\nExport DualSyntax.\nExport DvdSyntax.\nEnd Syntax.\n\nModule Theory.\nExport PreorderTheory.\nExport PreOCoercions.\nExport BPreorderTheory.\nExport TPreorderTheory.\nExport DualPreorder. \n\nExport OrderMorphismTheory.\n\nExport SubPreorderTheory.\nEnd Theory.\n\nModule Exports.\nHB.reexport.\nEnd Exports.\n\nEnd Order.\n\nExport Order.Exports.\n\nExport Order.Syntax.\n\nExport Order.Preorder.Exports.\nExport Order.BPreorder.Exports.\nExport Order.TPreorder.Exports.\nExport Order.TBPreorder.Exports.\nExport Order.FinPreorder.Exports.\nExport Order.FinBPreorder.Exports.\nExport Order.FinTPreorder.Exports.\nExport Order.FinTBPreorder.Exports.\n\nModule DefaultProdOrder := Order.DefaultProdOrder.\nModule DefaultSeqProdOrder := Order.DefaultSeqProdOrder.\nModule DefaultTupleProdOrder := Order.DefaultTupleProdOrder.\nModule DefaultProdLexiOrder := Order.DefaultProdLexiOrder.\nModule DefaultSeqLexiOrder := Order.DefaultSeqLexiOrder." -} \ No newline at end of file +version https://git-lfs.github.com/spec/v1 +oid sha256:9dcfddf8140e70876d4e563cbf41a3c2d2608de3c321348b98665838e44e619a +size 6794591