BeginPackage["SubQuotient`"]; e::usage = " e[i] is a basis vector in the standard infinite dimensional vector space E. "; SQ::usage = " SQ[zc, emax, bas] represents a subquetient, where zc is the zero criterion (a list of rules representing a linear map into E, so the ambient space is (First /@ zc)), emax is bigger or equal the maximal index of an e[i] in zc, and bas is a generating set for the basis. "; ReduceSQ::usage = " ReduceSQ[sq] reduces the subquotient sq. A subquotient sq=SQ[zc, emax, bas] is called reduced if zc is a surjection on the span of e[1] through e[emax] and bas is a basis of sq. Also works as ReduceSQ[zc, emax, bas]. " SQMorphism::usage = "SQMorphism[sq1, sq2, map] represents a morphism from the subquotient sq1 \ to the subquotient sq2. map is a set of rules mapping the generators of \ the ambient space of sq1 to the ambient space of sq2."; Kernel::usage = " Kernel[sqm] computes the kernel of the SQMorphism sqm. Also works as Kernel[sq1, sq2, map]. Kernel always returns a reduced SQ. " CoKernel::usage = " CoKernel[sqm] computes the kernel of the SQMorphism sqm. Also works as CoKernel[sq1, sq2, map]. CoKernel always returns a reduced SQ. " FreeSpan::usage = " FreeSpan[bas] returns the subquotient object (SQ) freely generated by bas. "; SQDirectSum::usage = " SQDirectSum[{sq1, sq2, ...}, {tag1, tag2, ...}] returns the direct sum of the sqi's tagged with the tagi's. "; Dim::usage = " Dim[sq] returns the dimension of the subquotient sq (assuming it is reduced). "; Begin["`Private`"]; Format[SQ[zc_, emax_, bas_], StandardForm] := StringForm[ "- SQ[-``-, ``, -``-] -", Length[zc], emax, Length[bas] ] ToMatrix[ecombs_List, emax_Integer] := ecombs /. Prepend[ Thread[Rule[Array[e, emax], IdentityMatrix[emax]]], 0 -> Table[0, {emax}] ] FreeSpan[bas_List] := Module[ {l=Length[bas]}, SQ[Thread[Rule[bas, Array[e, l]]], l, bas] ] ReduceSQ[SQ[zc_List, emax_Integer, bas_List]] := ReduceSQ[zc, emax, bas] ReduceSQ[{}, _, _] := SQ[{}, 0, {}] ReduceSQ[zc_List, emax_Integer, bas_List] := Module[ {mat, pos, nemax, nzc, nbas}, mat = ToMatrix[Last /@ zc, emax]; pos = Flatten[Position[#, 1, 1, 1]& /@ RowReduce[mat]]; nemax = Length[pos]; nzc = zc /. Append[Thread[Rule[e/@pos, Array[e,nemax]]], e[_] -> 0]; If[bas==={} || nemax==0, SQ[nzc, nemax, {}], mat = ToMatrix[bas /. nzc, nemax]; mat = NullSpace[Transpose[mat]]; If[mat === {}, SQ[nzc, nemax, bas], pos = Flatten[Position[#, 1, 1, 1]& /@ RowReduce[mat]]; nbas = bas[[Complement[Range[Length[bas]], pos]]]; SQ[nzc, nemax, nbas] ] ] ] Kernel[SQMorphism[sq1_SQ, sq2_SQ, map_List]] := Kernel[sq1, sq2, map] Kernel[SQ[zc1_, emax1_, bas1_], SQ[zc2_, emax2_, _], map_List] := Module[ {mat}, If[emax2==0 || bas1==={}, ReduceSQ[SQ[zc1, emax1, bas1]], mat = ToMatrix[Expand[bas1 /. map] /. zc2, emax2]; mat = NullSpace[Transpose[mat]]; ReduceSQ[SQ[ zc1, emax1, If[mat==={}, {}, mat.bas1] ]] ] ] CoKernel[SQMorphism[sq1_SQ, sq2_SQ, map_List]] := CoKernel[sq1, sq2, map] CoKernel[SQ[_, _, bas1_], SQ[zc2_, emax2_, bas2_], map_List] := Module[ {mat, im, rule, nzc2}, If[emax2==0 || bas1==={}, ReduceSQ[SQ[zc2, emax2, bas2]], mat = ToMatrix[Expand[bas1 /. map] /. zc2, emax2]; im = DeleteCases[RowReduce[mat].Array[e, emax2], 0]; rule = Replace[ #, {v_e :> (v -> 0), v_Plus :> (First[v] -> -Rest[v])} ]& /@ im; nzc2 = Replace[ #, (v1_ -> v2_) :> (v1 -> Expand[v2 /. rule]) ]& /@ zc2; ReduceSQ[SQ[nzc2, emax2, bas2]] ] ] SQDirectSum[sqs_List, tags_List] := Module[ {emax = 0, l, zc, k}, l = Length[sqs]; SQ[ Flatten[Table[ zc = sqs[[k, 1]] /. (a_ -> b_) :> (Expand[tags[[k]]]*a -> (b /. e[i_] :> e[emax+i])); emax += sqs[[k, 2]]; zc, {k, l} ]], emax, Flatten[Table[ Expand[tags[[k]] sqs[[k,3]]], {k, l} ]] ] ] Dim[SQ[_, _, bas_]] := Length[bas] End[]; EndPackage[]