Section Submodule.
Variable U : 'M[F]_n.
Definition val_submod m : 'M_(m, \rank U) -> 'M_(m, n) := mulmxr (row_base U).
Definition in_submod m : 'M_(m, n) -> 'M_(m, \rank U) :=
mulmxr (invmx (row_ebase U) *m pid_mx (\rank U)).
Canonical val_submod_linear m := [linear of @val_submod m].
Canonical in_submod_linear m := [linear of @in_submod m].
Definition val_factmod m : _ -> 'M_(m, n) :=
mulmxr (row_base (cokermx U) *m row_ebase U).
Definition in_factmod m : 'M_(m, n) -> _ := mulmxr (col_base (cokermx U)).
Canonical val_factmod_linear m := [linear of @val_factmod m].
Canonical in_factmod_linear m := [linear of @in_factmod m].
Definition submod_mx of mxmodule U :=
fun x => in_submod (val_submod 1%:M *m rG x).
Definition factmod_mx of mxmodule U :=
fun x => in_factmod (val_factmod 1%:M *m rG x).
Hypothesis Umod : mxmodule U.
Canonical submod_repr := MxRepresentation submod_mx_repr.
Canonical factmod_repr := MxRepresentation factmod_mx_repr.
End Submodule.
(* Properties of enveloping algebra as a subspace of 'rV_(n ^ 2). *)
(* Module homomorphisms; any square matrix f defines a module homomorphism   *)
(* over some domain, namely, dom_hom_mx f.                                   *)
Definition dom_hom_mx f : 'M_n :=
kermx (lin1_mx (mxvec \o mulmx (cent_mx_fun E_G f) \o lin_mul_row)).
Arguments hom_mxP {m f W}.
(* The subspace fixed by a subgroup H of G; it is a module if H <| G.         *)
(* The definition below is extensionally equivalent to the straightforward    *)
(*    \bigcap_(x in H) kermx (rG x - 1%:M)                                    *)
(* but it avoids the dependency on the choice function; this allows it to     *)
(* commute with ring morphisms.                                               *)
Definition rfix_mx (H : {set gT}) :=
let commrH := \matrix_(i < #|H|) mxvec (rG (enum_val i) - 1%:M) in
kermx (lin1_mx (mxvec \o mulmx commrH \o lin_mul_row)).
Arguments rfix_mxP {m W}.
(* The cyclic module generated by a single vector. *)
Definition cyclic_mx u := <<E_G *m lin_mul_row u>>%MS.
Arguments cyclic_mxP {u v}.
(* The annihilator of a single vector. *)
Definition annihilator_mx u := (E_G :&: kermx (lin_mul_row u))%MS.
(* The subspace of homomorphic images of a row vector.                        *)
Definition row_hom_mx u :=
(\bigcap_j kermx (vec_mx (row j (annihilator_mx u))))%MS.
(* Sub-, isomorphic, simple, semisimple and completely reducible modules.     *)
(* All these predicates are intuitionistic (since, e.g., testing simplicity   *)
(* requires a splitting algorithm fo r the mas field). They are all           *)
(* specialized to square matrices, to avoid spurrious height parameters.      *)
(* Module isomorphism is an intentional property in general, but it can be    *)
(* decided when one of the two modules is known to be simple.                 *)
Variant mx_iso (U V : 'M_n) : Prop :=
MxIso f of f \in unitmx & (U <= dom_hom_mx f)%MS & (U *m f :=: V)%MS.
(* Simple modules (we reserve the term "irreducible" for representations).    *)
Definition mxsimple (V : 'M_n) :=
[/\ mxmodule V, V != 0 &
forall U : 'M_n, mxmodule U -> (U <= V)%MS -> U != 0 -> (V <= U)%MS].
Definition mxnonsimple (U : 'M_n) :=
exists V : 'M_n, [&& mxmodule V, (V <= U)%MS, V != 0 & \rank V < \rank U].
(* A boolean test for module isomorphism that is only valid for simple        *)
(* modules; this is the only case that matters in practice.                   *)
(* For us, "semisimple" means "sum of simple modules"; this is classically,   *)
(* but not intuitionistically, equivalent to the "completely reducible"       *)
(* alternate characterization.                                                *)
Implicit Type I : finType.
Variant mxsemisimple (V : 'M_n) :=
MxSemisimple I U (W := (\sum_(i : I) U i)%MS) of
forall i, mxsimple (U i) & (W :=: V)%MS & mxdirect W.
(* Completely reducible modules, and Maeschke's Theorem. *)
Variant mxsplits (V U : 'M_n) :=
MxSplits (W : 'M_n) of mxmodule W & (U + W :=: V)%MS & mxdirect (U + W).
Definition mx_completely_reducible V :=
forall U, mxmodule U -> (U <= V)%MS -> mxsplits V U.

Lemma hom_mxsemisimple_iso I P U W f :
let V := (\sum_(i : I |  P i) W i)%MS in
mxsimple U -> (forall i, P i -> W i != 0 -> mxsimple (W i)) ->
(V <= dom_hom_mx f)%MS -> (U <= V *m f)%MS ->
{i | P i & mx_iso (W i) U}.