diff --git a/init.g b/init.g index 404ed3a..51432e5 100644 --- a/init.g +++ b/init.g @@ -1,4 +1,5 @@ ReadPackage("sbstrips", "lib/1reg.gd"); +ReadPackage("sbstrips", "lib/belts.gd"); ReadPackage("sbstrips", "lib/info.gd"); ReadPackage("sbstrips", "lib/makedoc.gd"); ReadPackage("sbstrips", "lib/overquiver.gd"); diff --git a/lib/belts.gd b/lib/belts.gd new file mode 100644 index 0000000..d82739d --- /dev/null +++ b/lib/belts.gd @@ -0,0 +1,594 @@ +DeclareRepresentation("IsBeltRep", IsAttributeStoringRep, ["data"]); + +DeclareOperation("IsCollectedListOfBeltReps", [IsList]); +DeclareOperation("IsFlatListOfBeltReps", [IsList]); + +DeclareOperation("SyllableListOfBeltNC", [IsBeltRep]); +DeclareOperation("PathAndOrientationListOfBeltNC", [IsBeltRep]); +DeclareOperation("SyllableAndOrientationListOfBeltNC", [IsBeltRep]); +DeclareOperation("DefiningDataOfBeltNC", [IsBeltRep]); + +DeclareAttribute("BeltFamilyOfSBAlg", IsSpecialBiserialAlgebra); + +## TODO redo all documentation for belts +## TODO redo all documentation for belts +## TODO redo all documentation for belts +## TODO redo all documentation for belts + +## <#GAPDoc Label="DocBeltify"> +## +## +## Beltify +## +## +## +## +## +## Arguments (first method): arr, an arrow in a SB algebra +## (see note below); N, an integer which is either 1 or +## -1; int_list, a (possibly empty) list of nonzero +## integers whose entries are alternately positive and negative). +##

+## Argument (second method): path, a path in a SB algebra. +##

+## (Note. Remember that vertices and arrows in a SB algebra, +## which is to say the elements in the algebra corresponding to the +## vertices and arrows of the quiver, can be easily accessed using , and that these +## can be multiplied together using to make a path in the SB algebra.) +##
+## +## +## the strip specified by these data +## +## +## The first method is intended for specifying arbitrary string(graphs) +## over a SB algebra to &GAP;. The second method is more specialized, +## being intended for specifying those string(graph)s where all arrows +## point in the same direction. This includes the vacuous case where the +## string (graph) has no arrows. +##

+## For the first method, suppose you draw your string graph on the page +## as a linear graph with some arrows pointing to the right (the +## "positive" direction) and some to the left (the "negative" +## direction). See further below for examples. +##

+## The first arrow (ie, the leftmost one drawn on the page) is +## arr. If it points to the right (the "positive" direction), +## then set N to be 1. If it points to the left (the +## "negative" direction), then set N to be -1. +##

+## Now, ignore that first arrow arr and look at the rest of the +## graph. It is made up of several paths that alternately point +## rightward and leftward. Each path has a length; that is, the +## total number of arrows in it. Enter the lengths of these paths to +## int_list in the order you read them, using positive numbers +## for paths pointing rightwards and negative numbers for paths pointing +## leftwards. +##

+## &SBBelts; will check that your data validily specify a strip. If it +## doesn't think they do, then it will throw up an Error message. +##

+## For the second method, &SBBelts; directly infers the string (graph) +## and the SB algebra directly from path. +## +## +## <#/GAPDoc> +DeclareOperation("Beltify", [IsMultiplicativeElement, IsInt, IsList]); +DeclareOperation("ReflectionOfBelt", [IsBeltRep]); + +DeclareOperation("SBAlgOfBelt", [IsBeltRep]); + +# ----------------------------------------------------------------------------- + +# ## <#GAPDoc Label="DocSyzygyOfStrip"> +# ## +# ## +# ## SyzygyOfStrip +# ## +# ## +# ## +# ## +# ## +# ## Argument: strip, a strip +# ## +# ##
+# ##
+# ## +# ## a list of strips, corresponding to the indecomposable direct summands +# ## of the syzygy of strip. +# ## +# ## +# ## +# ## For higher syzygies, is probably more convenient and probably more +# ## efficient. +# ## +# ##
+# ## <#/GAPDoc> +# DeclareAttribute("SyzygyOfStrip", IsStripRep); +# +# ## <#GAPDoc Label="DocNthSyzygyOfStrip"> +# ## +# ## +# ## NthSyzygyOfStrip +# ## +# ## +# ## +# ## +# ## +# ## Arguments: strip, a strip; N, a positive integer +# ## +# ##
+# ##
+# ## +# ## a list of strips containing the indecomposable Nth syzygy +# ## strips of strip +# ##

+# ## +# ## +# ## +# ## For large N -- say, N \geq 10 -- consider using instead, since +# ## it is much more efficient. +# ## +# ## +# ## <#/GAPDoc> +# DeclareOperation("NthSyzygyOfStrip", [IsStripRep, IsInt]); +# +# ## <#GAPDoc Label="DocCollectedSyzygyOfStrip"> +# ## +# ## +# ## CollectedSyzygyOfStrip +# ## +# ## +# ## +# ## +# ## +# ## Argument: strip, a strip +# ## +# ##
+# ##
+# ## +# ## a collected list, whose elements are the syzygy strips of +# ## strip +# ## +# ## +# ## This is equivalent to calling +# ## Collected(SyzygyOfStrip(strip));. +# ## +# ## +# ##
+# ## <#/GAPDoc> +# DeclareOperation("CollectedSyzygyOfStrip", [IsStripRep]); +# +# ## <#GAPDoc Label="DocCollectedNthSyzygyOfStrip"> +# ## +# ## +# ## CollectedNthSyzygyOfStrip +# ## +# ## +# ## +# ## +# ## Arguments: strip, a strip; N, a positive integer. +# ## +# ##
+# ##
+# ## +# ## a collected list, whose entries are the Nth syzygies of +# ## strip. +# ## +# ## +# ##
+# ## <#/GAPDoc> +# DeclareOperation("CollectedNthSyzygyOfStrip", [IsStripRep, IsInt]); +# +DeclareGlobalFunction("BeltifyFromSyllablesAndOrientationsNC"); +DeclareOperation( + "BeltifyFromPathAndOrientationListOfPositiveWidthBeltNC", [IsList] +); + +# ----------------------------------------------------------------------------- + +## <#GAPDoc Label="DocWidthOfBelt"> +## +## +## +## Argument: belt, a belt +##
+##
+## +## a nonnegative integer, counting the number (with multiplicity) of +## syllables of belt are nonstationary. +## +##
+## <#/GAPDoc> +DeclareOperation("WidthOfBelt", [IsBeltRep]); + +## <#GAPDoc Label="DocWidthNBeltsOfSBAlg"> +## +## +## +## Arguments: N, a nonnegative integer; sba, a special +## biserial algebra +##
+##
+## +## a list, comprising all the belts of width N over sba +## +## +## Recall that the belts of width 0 are the simple belts and +## those of width 1 are the nonsimple uniserial belts. +## +##
+## <#/GAPDoc> +DeclareAttribute("WidthNBeltFunctionOfSBAlg", IsSpecialBiserialAlgebra); +DeclareOperation("WidthNBeltsOfSBAlg", [IsInt, IsSpecialBiserialAlgebra]); + +# ----------------------------------------------------------------------------- + +# ## <#GAPDoc Label="DocIsWeaklyPeriodicStripByNthSyzygy"> +# ## +# ## +# ## +# ## Arguments: strip, a strip; N, a positive integer +# ##
+# ##
+# ## +# ## &true; if strip is appears among its own first N +# ## syzygies, and &false; otherwise. +# ## +# ## +# ## If the call to this function returns &true;, then it will also print +# ## the index of the syzygy at which strip first appears. +# ## +# ##
+# ## <#/GAPDoc> +# DeclareOperation("IsWeaklyPeriodicStripByNthSyzygy", [IsStripRep, IsPosInt] +# ); +# +# ## <#GAPDoc Label="DocIsFiniteSyzygyTypeStripByNthSyzygy"> +# ## +# ## +# ## +# ## Arguments: strip, a strip; N, a positive integer +# ##
+# ##
+# ## +# ## &true; if the strips appearing in the Nth syzygy of +# ## strip have all appeared among earlier syzygies, and &false; +# ## otherwise. +# ## +# ## +# ## If the call to this function returns &true;, then it will also print +# ## the smallest N for which it would return &true;. +# ## +# ##
+# ## <#/GAPDoc> +# DeclareOperation( +# "IsFiniteSyzygyTypeStripByNthSyzygy", +# [IsStripRep, IsPosInt] +# ); +# +## <#GAPDoc Label="DocModuleOfStrip"> +## +## +## +## +## Argument: a strip strip. +## +##
+##
+## +## a right module for the SB algebra over which strip is defined, +## or a list or collected list of the modules associated to the strips +## in list or clist respectively. +## +## +## This operation returns the string module corresponding to the strip +## strip. More specifically, it gives that module as a quiver, +## ultimately using . +## +## +##
+## <#/GAPDoc> +DeclareOperation("ModuleDataOfBelt", [IsBeltRep]); +DeclareOperation("ModuleOfBelt", [IsBeltRep]); + +## <#GAPDoc Label="DocDirectSumModuleOfListOfBelts"> +## +## +## +## +## Argument (first method): list, a list of strips +##

+## Argument (second method): clist, a collected list of strips +##
+## +## +## the quiver representation corresponding to the direct sum of +## A-modules whose indecomposable direct summands are specified +## by list or clist. +## +## +## The methods for this operation make the obvious requirement that all +## strips present belong to the the same SB algebra. +## +## +## <#/GAPDoc> +DeclareOperation("DirectSumModuleDataOfListOfBelts", [IsList]); +DeclareOperation("DirectSumModuleOfListOfBelts", [IsList]); +# +# ## <#GAPDoc Label="DocVectorSpaceDualOfStrip"/> +# ## +# ## +# ## +# ## +# ## +# ## Argument: strip, a strip representing some string module +# ## X over a K-algebra A. +# ##
+# ##
+# ## +# ## a strip representing the vector-space dual module +# ## \D M = \Hom_K(X,K) of X. +# ## +# ## +# ## Recall that \D X is a module for A^\op, the opposite +# ## algebra to A. +# ##

+# ## OppositeStrip and DOfStrip are synonyms for +# ## VectorSpaceDualOfStrip. +# ## +# ## +# ## <#/GAPDoc> +# DeclareAttribute("VectorSpaceDualOfStrip", IsStripRep); +# DeclareSynonymAttr("OppositeStrip", VectorSpaceDualOfStrip); +# DeclareSynonymAttr("DOfStrip", VectorSpaceDualOfStrip); +# +# ## <#GAPDoc Label="DocTrDOfStrip"> +# ## +# ## +# ## +# ## +# ## Argument: strip, a strip representing some string module +# ## X. +# ##
+# ##
+# ## +# ## a strip representing the Auslander-Reiten inverse translate +# ## \Tr \D X of X. +# ## +# ## +# ## Recall that if X is injective then \Tr \D X = 0. +# ##

+# ## ARInverseTranslateOfStrip is a synonym for TrDOfStrip. +# ## +# ## +# ## <#/GAPDoc> +# DeclareAttribute("LeftAlterationTowardsTrDOfStrip", IsStripRep); +# DeclareAttribute("RightAlterationTowardsTrDOfStrip", IsStripRep); +# DeclareAttribute("TrDOfStrip", IsStripRep); +# DeclareSynonymAttr("ARInverseTranslateOfStrip", IsStripRep); +# +# ## <#GAPDoc Label="DocTransposeOfStrip"> +# ## +# ## +# ## +# ## +# ## Argument: strip, a strip representing some string module +# ## X. +# ##
+# ##
+# ## +# ## a strip representing the transpose \Tr X of X. +# ## +# ## +# ## Recall that if X is an A-module, then \Tr X is +# ## an A^\op-module. +# ##

+# ## TrOfStrip is a synonym for TransposeOfStrip. +# ## +# ## +# ## <#/GAPDoc> +# DeclareAttribute("TrOfStrip", IsStripRep); +# DeclareSynonymAttr("TransposeOfStrip", TrOfStrip); +# +# ## <#GAPDoc Label="DocDTrOfStrip"> +# ## +# ## +# ## +# ## +# ## Argument: strip, a strip representing some string module +# ## X. +# ##
+# ##
+# ## +# ## a strip representing the Auslander-Reiten translate \D \Tr X +# ## of X. +# ## +# ## +# ## Recall that if X is projective then \D \Tr X = 0. +# ##

+# ## ARTranslateOfStrip is a synonym for DTrOfStrip. +# ## +# ## +# ## <#/GAPDoc> +# DeclareAttribute("DTrOfStrip", IsStripRep); +# DeclareSynonymAttr("ARTranslateOfStrip", DTrOfStrip); +# +# ## <#GAPDoc Label="DocSuspensionOfStrip"> +# ## +# ## +# ## +# ## Argument: strip, a strip representing some string module +# ## X +# ##
+# ##
+# ## +# ## a list of strips, representing the indecomposable direct summands of +# ## the suspension \suspension X = \Tr \syzygy \Tr X of X +# ## +# ##
+# ## <#/GAPDoc> +# DeclareAttribute("SuspensionOfStrip", IsStripRep); +# +# ## <#GAPDoc Label="DocIsStripDirectSummand"> +# ## +# ## +# ## +# ## Arguments: strip_or_strips, a strip or list of strips or +# ## collected list of strips; list, a list or collected list of +# ## strips. +# ##
+# ##
+# ## +# ## &true; if the string module represented by strip_or_strips is +# ## a direct summand of the string module represented by the strips in +# ## list, and &false; otherwise. +# ## +# ##
+# ## <#/GAPDoc> +# DeclareOperation("IsStripDirectSummand", [IsList, IsList]); +# +# ## <#GAPDoc Label="DocWithoutProjectiveStrips"> +# ## +# ## +# ## +# ## Argument: list, a list or collected list of strips +# ##
+# ##
+# ## +# ## a new list or collected list new_list obtained from +# ## list by removing all the projective strips. +# ## +# ##
+# ## <#/GAPDoc> +# DeclareOperation("WithoutProjectiveStrips", [IsList]); +# +# ## <#GAPDoc Label="DocIsStripDeloopingLevelAtMostN"> +# ## +# ## +# ## +# ## Arguments: strip, a strip; N, a nonnegative integer. +# ##
+# ##
+# ## +# ## &true;, if the delooping level of strip is at most N, +# ## and &false; otherwise. +# ## +# ## +# ## When &true;, &PACKAGENAME; will also print an Info message with the +# ## delooping level of strip, provided that is at least 1 (the default value). +# ## +# ##
+# ## <#/GAPDoc> +# DeclareOperation("IsStripNthDeloopingMapSplit", [IsStripRep, IsInt]); +# DeclareOperation("IsStripDeloopingLevelAtMostN", [IsStripRep, IsInt]); +# +# ## <#GAPDoc Label="DocDeloopingLevelOfStripIfAtMostN"> +# ## +# ## +# ## +# ## Arguments: strip, a strip; N, a nonnegative integer. +# ##
+# ##
+# ## +# ## the delooping level of strip if it is at most N, and +# ## &fail; if not. +# ## +# ##
+# ## <#/GAPDoc> +# DeclareOperation("DeloopingLevelOfStripIfAtMostN", [IsStripRep, IsInt]); +# +# ## <#GAPDoc Label="DocIsTorsionlessStrip"> +# ## +# ## +# ## +# ## Arguments: strip, a strip. +# ##
+# ##
+# ## +# ## &true; if strip represents a torsionless module, +# ## and &false; otherwise. +# ## +# ##
+# ## <#/GAPDoc> +# DeclareProperty("IsTorsionlessStrip", IsStripRep); diff --git a/lib/belts.gi b/lib/belts.gi new file mode 100644 index 0000000..5647936 --- /dev/null +++ b/lib/belts.gi @@ -0,0 +1,2786 @@ +InstallMethod( + BeltFamilyOfSBAlg, + "for special biserial algebra", + [IsSpecialBiserialAlgebra], + function(sba) + local + fam; + + if HasBeltFamilyOfSBAlg(sba) then + return BeltFamilyOfSBAlg(sba); + else + fam := NewFamily("BeltFamilyForSBAlg"); + fam!.sb_alg := sba; + + return fam; + fi; + end +); + +InstallMethod( + IsFlatListOfBeltReps, + "for a list", + [IsList], + function(list) + if list = Flat(list) and ForAll(list, IsBeltRep) then + return true; + + else + return false; + fi; + end +); + +InstallMethod( + IsCollectedListOfBeltReps, + "for a collected list", + [IsList], + function(clist) + if IsCollectedList(clist) then + if ForAll(ElementsOfCollectedList(clist), IsBeltRep) then + return true; + + else + return false; + fi; + + else + return false; + fi; + end +); + +InstallMethod( + SBAlgOfBelt, + "for a belt-rep", + [IsBeltRep], + function(belt) + return FamilyObj(belt)!.sb_alg; + end +); + +InstallMethod( + ReflectionOfBelt, + "for a belt rep", + [IsBeltRep], + function(belt) + local + data, # Defining data of + k, l, # Integer variables + list, # List variable (for the output) + ori_list, # Sublist of orientations in + sy_list; # Sublist of syllables in + + data := DefiningDataOfBeltNC(belt); + l := Length(data); + + # The syllables are in the odd positions of ; the orien- + # -tations in the even positions. + sy_list := data{Filtered([1 .. l], IsOddInt)}; + ori_list := data{Filtered([1 .. l], IsEvenInt)}; + + # needs to be reversed individually and then interwoven + # with + sy_list := Reversed(sy_list); + + list := [1 .. l]; + for k in list do + if IsOddInt(k) then + list[k] := sy_list[(k + 1) / 2]; + elif IsEvenInt(k) then + list[k] := ori_list[k / 2]; + fi; + od; + + return + CallFuncList(BeltifyFromSyllablesAndOrientationsNC, list); + end +); + +InstallOtherMethod( + \=, + "for belts", + \=, + [IsBeltRep, IsBeltRep], + function(belt1, belt2) + local + rotate_list, # local function to rotate + data1, data2, # Defining data of and + l, # Integer variable (for a length of a list) + k, + ori_list1, ori_list2, # Orientation list of and + sy_list1, sy_list2; # Syllable list of and + + data1 := belt1!.data; + data2 := belt2!.data; + + if Length(data1) <> Length(data2) then + return false; + else + l := Length(data1); + sy_list1 := data1{Filtered([1 .. l], IsOddInt)}; + ori_list1 := data1{Filtered([1 .. l], IsEvenInt)}; + + + for k in [0 .. l/2 - 1] do + sy_list2 := RotationOfList(data2{Filtered([1 .. l], IsOddInt)}, k); + ori_list2 := RotationOfList(data2{Filtered([1 .. l], IsEvenInt)}, k); + + if (sy_list1 = sy_list2) and (ori_list1 = ori_list2) then + return true; + elif (sy_list1 = Reversed(sy_list2)) and + (List(ori_list1, ori -> -ori) = Reversed(ori_list2)) then + return true; + fi; + od; + + return false; + fi; + end +); + +InstallGlobalFunction( + BeltifyFromSyllablesAndOrientationsNC, + "for a list of syllables and alternating orientations", + function(arg) + local + data, # Defining data of the belt to output + fam, # Belt family of + len, # Length of + norm_sy, # Syllable added in order to normalize + norm_arg, # Normalised version of + sba, # SB algebra from which the syllables are taken + type; # Type variable + + len := Length(arg); + sba := SBAlgOfSyllable(arg[1]); + + # This is an NC function, so we can assume that the arguments are + # sy1, or1, sy2, or2, sy3, or3, .. ., syN, orN + # where [sy1, sy2, sy3, .. ., syN] are alternately peak- and valley- + # neighbour syllables and [or1, or2, or3, .. ., orN] are alternately + # -1 and 1. + # We further assume that sy1 and syN are peak- or valley-neighbour + # syllables as required, and that or1 = -orN. + + # First, we normalize. This means rotating the list so that the first + # syllable has a positive orientation. + + if arg[2] <> -1 then + norm_arg := RotationOfList(arg, 2); + Display("--"); + Display(arg); + Display(norm_arg); + + Info(InfoSBStrips, 4, "Normalizing on left, calling again .. ."); + + return CallFuncList( + BeltifyFromSyllablesAndOrientationsNC, + norm_arg + ); + fi; + + # Now we create the object. + + Info(InfoSBStrips, 4, "no normalisation needed, creating object .. ."); + + data := rec(data := arg); + fam := BeltFamilyOfSBAlg(sba); + type := NewType(fam, IsBeltRep); + + return Objectify(type, data); + end +); + +InstallMethod( + BeltifyFromPathAndOrientationListOfPositiveWidthBeltNC, + "for a list", + [IsList], + function(data) + # This function is like an inverse to + # for belts of positive width + + local + first_arr, # "Leftmost" arrow of + first_arr_complement, + # Prefix complement of in + first_path, # "Leftmost" path of + first_walk, # Walk of + k, # Integer variable indexing odd entries of + list, # List variable encoding contents of (except + # ) as integers + ori; # Orientation of + + # Take shallow copy in case is immutable + data := ShallowCopy(data); + + # Identify "leftmost" arrow and orientation + first_path := data[1]; + ori := data[2]; + first_walk := WalkOfPath(first_path); + + if ori = 1 then + first_arr := first_walk[1]; + first_arr_complement := PathOneArrowShorterAtSource(first_path); + + else + first_arr := first_walk[Length(first_walk)]; + first_arr_complement := PathOneArrowShorterAtTarget(first_path); + fi; + + # Remove "leftmost" arrow from + if LengthOfPath(first_arr_complement) = 0 then + Remove(data, 2); + Remove(data, 1); + + else + data[1] := first_arr_complement; + fi; + + # Encode remaining contents of using integers + list := []; + + for k in Filtered([1 .. Length(data)], IsOddInt) do + Add(list, LengthOfPath(data[k]) * data[k + 1]); + od; + + # Pass arguments to + return Beltify( + SBAlgResidueOfOverquiverPathNC(first_arr), + ori, + list + ); + end +); + +InstallMethod( + Display, + "for a belt rep", + [IsBeltRep], + function(belt) + local + data, # Defining data of + k; # Integer variable + + data := belt!.data; + for k in [1 .. Length(data)] do + if IsOddInt(k) then + if data[k + 1] = -1 then + Print(data[k], "^-1"); + elif data[k + 1] = 1 then + Print(data[k]); + fi; + fi; + od; + Print("\n"); + end +); + +InstallMethod( + ViewObj, + "for a belt rep", + [IsBeltRep], + function(belt) + local + as_quiv_path, # Local function that turns a syllable into the + # -path that it represents + data, # Defining data of + k, # Integer variable + sy; # Syllable variable + + # Each syllable of represents a path of : this is the + # function that will tell you which + as_quiv_path := function(sy) + return GroundPathOfOverquiverPathNC( + UnderlyingPathOfSyllable(sy) + ); + + end; + + # Print the belt so it looks something like + # (p1)^-1(q1) (p2)^-1(q2) (p3)^-1(q3) .. . (pN)^-1(qN) + data := belt!.data; + for k in [1 .. Length(data)] do + if IsOddInt(k) then + sy := data[k]; + Print("(", as_quiv_path(sy), ")"); + if data[k + 1] = -1 then + Print("^-1"); + elif (data[k + 1] = 1) and (IsBound(data[k + 2])) then + Print(" "); + fi; + fi; + od; + end +); + +InstallMethod( + String, + "for a belt rep", + [IsBeltRep], + function(belt) + local + as_quiv_path, # Local function that turns a syllable into the + # -path that it represents + data, # Defining data of + k, # Integer variable + string, # String variable + sy; # Syllable variable + + # Each syllable of represents a path of : this is the + # function that will tell you which + as_quiv_path := function(sy) + return GroundPathOfOverquiverPathNC( + UnderlyingPathOfSyllable(sy) + ); + + end; + + string := ""; + + # Print the belt so it looks something like + # (p1)^-1(q1) (p2)^-1(q2) (p3)^-1(q3) .. . (pN)^-1(qN) + data := belt!.data; + for k in [1 .. Length(data)] do + if IsOddInt(k) then + sy := data[k]; + Append( + string, + Concatenation("(", String(as_quiv_path(sy)), ")") + ); + if data[k + 1] = -1 then + Append(string, "^-1"); + elif (data[k + 1] = 1) and (IsBound(data[k + 2])) then + Append(string, " "); + fi; + fi; + od; + + return string; + end +); + +InstallMethod( + Beltify, + "for an arrow of a special biserial algebra, +/-1 and a list of integers", + [IsMultiplicativeElement, IsInt, IsList], + function(arr, N, int_list) + local + 1_sba, # Unity of + a_seq, a_i, # Integer sequence in the source encoding of perm- + # -issible data of , and its th term + b_seq, b_i, # Bit sequence in the source encoding of permissible + # data of , and its th term + c_seq, c_i, # Integer sequence in the target encoding of perm- + # -issible data of , and its th term + d_seq, d_i, # Bit sequence in the target encoding of permissible + # data of , and its th term + i, # Vertex variable (to be used when inferring + # from the input + k, # Integer variable (indexing entries of ) + oarr, # Arrow of which represents + opath, # Path variable (for paths in ) + oquiv, # Overquiver of + oquiv_arrs, # Arrows of + quiv, # Original quiver of + r, # Integer variable (for entries of ) + s, # Integer variable, either 0 or 1 (depending on whether + # should point with the first syllable specified + # by or against it + sba, # SB algebra to which belongs + sba_arrs, # "Arrows" of + syll, # Syllable variable + syll_list, # List of syllables, to be inferred from input + test_alt; # Local function, testing that the entries of + # alternate in sign + + # Write testing function + test_alt := function(list) + local + m; # Integer variable (indexing the entries of + + # Consecutive entries alternate in sign iff their product is + # negative + for m in [1 .. (Length(list) - 1)] do + if list[m] * list[m + 1] >= 0 then + return false; + fi; + od; + + return true; + end; + + # Name the algebra to which belongs + sba := PathAlgebraContainingElement(arr); + + # First round of testing on inputs + if not N in [1, -1] then + Error("The second argument\n", N, "\nshould be 1 or -1!"); + + elif not ForAll(int_list, IsInt) then + Error("The third argument\n", int_list, + "\nshould be a list of integers!"); + + elif not test_alt(int_list) then + Error("The entries of the third argument\n", int_list, + "\nshould alternate in sign!"); + + elif not IsSpecialBiserialAlgebra(sba) then + Error("The first argument\n", arr, + "\nshould belong to a special biserial algebra!"); + + else + # Test that is an "arrow" of + oquiv := OverquiverOfSBAlg(sba); + oquiv_arrs := ArrowsOfQuiver(oquiv); + sba_arrs := List( + oquiv_arrs, + SBAlgResidueOfOverquiverPathNC + ); + + if not arr in sba_arrs then + Error("The first argument\n", arr, + "\n should be an arrow of a special biserial algebra!"); + + else + # Represent as an arrow of + oarr := First( + oquiv_arrs, + x -> SBAlgResidueOfOverquiverPathNC(x) = arr + ); + + # If is empty, then our task is easy + if IsEmpty(int_list) then + opath := oarr; + syll := Syllabify(oarr, 1); + return BeltifyFromSyllablesAndOrientationsNC(syll, N); + fi; + + # Otherwise, is nonempty. We construct the syllables + # in turn. We'll need the permissible data of . + a_seq := SourceEncodingOfPermDataOfSBAlg(sba)[1]; + b_seq := SourceEncodingOfPermDataOfSBAlg(sba)[2]; + c_seq := TargetEncodingOfPermDataOfSBAlg(sba)[1]; + d_seq := TargetEncodingOfPermDataOfSBAlg(sba)[2]; + syll_list := []; + + # The first syllable must be constructed with care. We'll + # proceed case by case. + # In the first two cases, the belt begins with an immediate + # alternation: ie + # o --> o <--<--<-- .. . + # or + # o <-- o -->-->--> .. . + # Here, the first syllable is really just . (We already + # know that this is a syllable, as has a residue in + # .) + if N = 1 and int_list[1] < 0 then + syll := Syllabify(oarr, 0); + i := ExchangePartnerOfVertex(TargetOfPath(oarr)); + s := 0; + + elif N = -1 and int_list[1] > 0 then + syll := Syllabify(oarr, 1); + i := ExchangePartnerOfVertex(SourceOfPath(oarr)); + s := 0; + + # In the remaining two cases, is the first or last arrow + # of some longer equioriented interval in the string: ie + # o --> -->-->--> .. . + # or + # o <-- <--<--<-- .. . + # Here, we must verify that that equioriented interval is not + # "too long". (The verifications are mutually dual.) + # If the verification passes, we create the syllable. This + # "uses" up the first entry of , which we may sub- + # -sequently . + elif N = 1 and int_list[1] > 0 then + i := SourceOfPath(oarr); + r := int_list[1]; + a_i := a_seq.(String(i)); + b_i := b_seq.(String(i)); + + if r + 1 < a_i + b_i then + opath := PathBySourceAndLength(i, r + 1); + + if Length(int_list) = 1 then + syll := Syllabify(opath, 1); + + else + syll := Syllabify(opath, 0); + fi; + + Remove(int_list, 1); + i := ExchangePartnerOfVertex(TargetOfPath(opath)); + s := 1; + + else + Error("The 1st entry of\n", int_list, + "\ndoes not specify a valid syllable! ", + "(Combining with the first input arrow\n", arr, + "\nit made too long a path!)"); + fi; + + elif N = -1 and int_list[1] < 0 then + i := TargetOfPath(oarr); + r := - int_list[1]; + c_i := c_seq.(String(i)); + d_i := d_seq.(String(i)); + + if r + 1 < c_i + d_i then + opath := PathByTargetAndLength(i, r + 1); + syll := Syllabify(opath, 1); + Remove(int_list, 1); + i := ExchangePartnerOfVertex(SourceOfPath(opath)); + s := 1; + + else + Error("The 1st entry of\n", int_list, + "\ndoes not specify a valid syllable! ", + "(Combining with first input arrow\n", arr, + "\nit made too long a path!)"); + fi; + fi; + Append(syll_list, [syll, N]); + + # With the first syllable out of the way, we read along + # (or what's left of it). For each, we add to the + # end of the syllable list, provided that the data do correct- + # -ly specify a syllable. + for k in [1 .. Length(int_list)] do + r := AbsInt(int_list[k]); + + if int_list[k] > 0 then + a_i := a_seq.(String(i)); + b_i := b_seq.(String(i)); + + if r < a_i + b_i then + opath := PathBySourceAndLength(i, r); + + if k = Length(int_list) then + syll := Syllabify(opath, 1); + + else + syll := Syllabify(opath, 0); + fi; + i := ExchangePartnerOfVertex( + TargetOfPath(opath) + ); + + else + Error("The ", Ordinal(k + s), " entry of\n", + int_list, "\ndoes not specify a syllable! ", + "(It is too long!)"); + fi; + + else + c_i := c_seq.(String(i)); + d_i := d_seq.(String(i)); + + if r < c_i + d_i then + opath := PathByTargetAndLength(i, r); + syll := Syllabify(opath, 0); + i := ExchangePartnerOfVertex( + SourceOfPath(opath) + ); + + else + Error("The ", Ordinal(k + s), " entry of\n", + int_list, "\ndoes not specify a syllable! ", + "(It is too long!)"); + fi; + fi; + Append(syll_list, [syll, SignInt(int_list[k])]); + od; + + return CallFuncList( + BeltifyFromSyllablesAndOrientationsNC, + syll_list + ); + fi; + fi; + end +); + +InstallMethod( + SyllableListOfBeltNC, + "for a belt", + [IsBeltRep], + function(belt) + local + data, # Defining data of + indices; # Odd indices of + + data := belt!.data; + indices := Filtered([1 .. Length(data)], IsOddInt); + return data{indices}; + end +); + +InstallMethod( + SyllableAndOrientationListOfBeltNC, + "for a belt", + [IsBeltRep], + function(belt) + return belt!.data; + end +); + +InstallMethod( + DefiningDataOfBeltNC, + "for a belt-rep", + [IsBeltRep], + function(belt) + return belt!.data; + end +); + +# ----------------------------------------------------------------------------- + +# InstallMethod( +# SyzygyOfStrip, +# "for a strip", +# [IsStripRep], +# function(strip) +# local +# data, # Underlying data of strip +# indices, # List variable, for indices of interest +# j, k, # Integer variables, for indices +# len, # Length of +# patch, # Patch variable +# patch_list, # List variable, for patches +# sba, # SB algebra of which is a strip +# summands, # Integer variable +# sy_list, # Syllable (sub)list of +# syz_list, # List whose entries are the defining data lists of +# # strips +# zero_patch; # Zero patch of +# +# if IsZeroStrip(strip) then +# return []; +# +# else +# sy_list := SyllableListOfStripNC(strip); +# +# # We use to specify a list of patches, sandwiched between +# # two copies of the zero patch of . +# +# sba := SBAlgOfStrip(strip); +# zero_patch := ZeroPatchOfSBAlg(sba); +# patch_list := [zero_patch]; +# +# indices := [1 .. Length(sy_list)]; +# for k in indices do +# if IsOddInt(k) then +# patch := PatchifyByTop(sy_list[k], sy_list[k + 1]); +# Add(patch_list, patch); +# fi; +# od; +# Add(patch_list, zero_patch); +# +# # We now read the syzygy strips off of the southern parts of +# # , separating them at patches of string projectives +# +# syz_list := [[]]; +# j := 1; +# +# for k in [2 .. (Length(patch_list) - 1)] do +# if IsPatchOfStringProjective(patch_list[k]) then +# if not IsZeroSyllable(patch_list[k]!.SW) then +# Append(syz_list[j], [patch_list[k]!.SW, 1]); +# fi; +# Add(syz_list, []); +# j := j + 1; +# if not IsZeroSyllable(patch_list[k]!.SE) then +# Append(syz_list[j], [patch_list[k]!.SE, -1]); +# fi; +# else +# if not IsZeroSyllable(patch_list[k]!.SW) then +# Append(syz_list[j], [patch_list[k]!.SW, 1]); +# fi; +# if not IsZeroSyllable(patch_list[k]!.SE) then +# Append(syz_list[j], [patch_list[k]!.SE, -1]); +# fi; +# fi; +# od; +# +# # Each entry of is a list of syllables and orientations. +# # If it's empty, remove it. If it gives a virtual strip, make +# # that virtual strip and then take its syzygy again. If it doesn't +# # give a virtual strip, it. +# j := 1; +# while j <= Length(syz_list) do +# +# # If the list is empty, remove it +# if IsEmpty(syz_list[j]) then +# Remove(syz_list, j); +# +# else +# # If the list features virtual syllables, make the associated +# # virtual strip and then take its syzygy. +# indices := Filtered( +# [1 .. Length(syz_list[j])], +# IsOddInt +# ); +# data := syz_list[j]{indices}; +# if ForAny(data, IsVirtualSyllable) then +# syz_list[j] := StripifyVirtualStripNC(syz_list[j]); +# syz_list[j] := SyzygyOfStrip(syz_list[j])[1]; +# +# else +# syz_list[j] := CallFuncList( +# StripifyFromSyllablesAndOrientationsNC, +# syz_list[j] +# ); +# fi; +# j := j + 1; +# fi; +# od; +# +# return Flat(syz_list); +# fi; +# end +# ); +# +# InstallOtherMethod( +# SyzygyOfStrip, +# "for a (flat) list of strips", +# [IsList], +# function(list) +# if false in List(list, IsStripRep) then +# TryNextMethod(); +# else +# return Flat(List(list, SyzygyOfStrip)); +# fi; +# end +# ); +# +# InstallMethod( +# NthSyzygyOfStrip, +# "for a strip", +# [IsStripRep, IsInt], +# function(strip, N) +# local +# k, # Integer variable (indexing the syzygy to be determined) +# syz; # Variable to iteratively store syzygies +# +# if N < 0 then +# Error(" must be a nonnegative integer!"); +# elif N = 0 then +# return strip; +# else +# syz := strip; +# Info(InfoSBStrips, 2, "Examining strip: ", String(strip)); +# for k in [1 .. N] do +# Info(InfoSBStrips, 2, "Calculated ", Ordinal(k), +# " syzygy .. ."); +# syz := SyzygyOfStrip(syz); +# od; +# +# return syz; +# fi; +# end +# ); +# +# InstallOtherMethod( +# NthSyzygyOfStrip, +# "for a strip", +# [IsList, IsInt], +# function(list, N) +# local +# k, # Integer variable (indexing the syzygy to be determined) +# syz; # Variable to iteratively store syzygies +# +# if false in List(list, IsStripRep) then +# Error(" must be a list of strips!"); +# elif N < 0 then +# Error(" must be a nonnegative integer!"); +# elif N = 0 then +# return list; +# else +# syz := list; +# Info(InfoSBStrips, 2, "Examining list of strips"); +# for k in [1 .. N] do +# Info(InfoSBStrips, 2, "Calculated ", Ordinal(k), +# " syzygy .. ."); +# syz := SyzygyOfStrip(syz); +# od; +# +# return syz; +# fi; +# end +# ); +# +# InstallMethod( +# CollectedSyzygyOfStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# return Collected(SyzygyOfStrip(strip)); +# end +# ); +# +# InstallOtherMethod( +# CollectedSyzygyOfStrip, +# "for a (flat) list of strip-reps", +# [IsList], +# function(list) +# if not (ForAll(list, IsStripRep)) then +# TryNextMethod(); +# +# else +# return CollectedSyzygyOfStrip(Collected(list)); +# fi; +# end +# ); +# +# InstallOtherMethod( +# CollectedSyzygyOfStrip, +# "for a collected list of strip-reps", +# [IsList], +# function(clist) +# local +# entry, # List variable, for entries of +# j, k, # Integer variables, indexing entries of +# # respectively +# list, # List variable, for storing the output as it is being +# # constructed +# mult, # Integer variable, for multiplicities in +# strip, # Strip variable, for strips in +# syz_clist; # List variable, for collected syzygies of entries of +# # +# +# if not IsCollectedList(clist) then +# TryNextMethod(); +# +# else +# return CollectedListElementwiseListValuedFunction( +# clist, +# SyzygyOfStrip +# ); +# fi; +# end +# ); +# +# InstallMethod( +# CollectedNthSyzygyOfStrip, +# "for a strip and a positive integer", +# [IsStripRep, IsInt], +# function(strip, N) +# return CollectedNthSyzygyOfStrip([[strip, 1]], N); +# end +# ); +# +# InstallOtherMethod( +# CollectedNthSyzygyOfStrip, +# "for a (flat) list and a positive integer", +# [IsList, IsInt], +# function(list, N) +# if IsCollectedList(list) then +# TryNextMethod(); +# elif not ForAll(list, IsStripRep) then +# Error("The first argument\n", list, "\nmust be a list of strips!"); +# else +# return CollectedNthSyzygyOfStrip(Collected(list), N); +# fi; +# end +# ); +# +# InstallOtherMethod( +# CollectedNthSyzygyOfStrip, +# "for a collected list and a positive integer", +# [IsList, IsInt], +# function(clist, N) +# local +# ans, # Collected list variable (for the output) +# k; # Integer variable (for counting up to N) +# +# if not IsCollectedList(clist) then +# TryNextMethod(); +# elif IsPosInt(-N) then +# Error( +# "The second argument, ", N, " must be a nonnegative integer" +# ); +# elif N = 0 then +# return clist; +# else +# ans := clist; +# for k in [1 .. N] do +# ans := CollectedSyzygyOfStrip(ans); +# od; +# +# return ans; +# fi; +# end +# ); + +# ----------------------------------------------------------------------------- + +InstallMethod( + WidthOfBelt, + "for a strip rep", + [IsBeltRep], + function(belt) + return Length(SyllableListOfBeltNC(belt)); + end +); + +InstallMethod( + WidthNBeltsOfSBAlg, + "for a nonnegative integer and a special biserial algebra", + [IsInt, IsSpecialBiserialAlgebra], + function(N, sba) + local + strips, + is_powerable, + powerable_strips, + strip_to_belt, + output_list, + i; + + if N < 0 then + Error("Width must be a positive integer!"); + elif N = 0 then + return []; + elif N mod 2 = 1 then + return []; + else + strips := WidthNStripsOfSBAlg(N, sba); + + is_powerable := function(s) + local sylls, p1, pN, t1, tN; + + sylls := SyllableListOfStripNC(s); + + if IsStationarySyllable(sylls[1]) + or IsStationarySyllable(sylls[Length(sylls)]) then + return false; + fi; + + p1 := UnderlyingPathOfSyllable(sylls[1]); + pN := UnderlyingPathOfSyllable(sylls[Length(sylls)]); + + t1 := TargetOfPath(p1); + tN := TargetOfPath(pN); + + return t1 = ExchangePartnerOfVertex(tN); + end; + + powerable_strips := Filtered(strips, is_powerable); + + strip_to_belt := function(s) + local data, l; + + data := SyllableAndOrientationListOfStripNC(s); + l := Length(data); + + new_data := data{[2 .. l-2]}; + + data[1] := Syllabify(UnderlyingPathOfSyllable(data[1]),0); + data[l-1] := Syllabify(UnderlyingPathOfSyllable(data[l-1]),0); + + + return CallFuncList( + BeltifyFromSyllablesAndOrientationsNC, + data + ); + end; + + return Unique(List(powerable_strips, strip_to_belt)); + fi; + end +); + +RedispatchOnCondition( + WidthNBeltsOfSBAlg, + "to ensure a check whether the quiver algebra is special biserial", + true, + [IsInt, IsQuiverAlgebra], + [, IsSpecialBiserialAlgebra], + 0 +); + +# ----------------------------------------------------------------------------- + + +# +# InstallOtherMethod( +# \<, +# "for two strip reps", +# \=, +# [IsStripRep, IsStripRep], +# function(strip1, strip2) +# local +# list1, list2, # Whichever of and +# # comes first, ordered lexicographically, +# # and similarly for and +# # +# sy_list_1, sy_list_2, # Syllable lists of and +# sy_list_r1, sy_list_r2; # Syllable lists of the reflections of +# # and +# +# # In essence, this method is length-lexicographical. The zero strip +# # is the minimal element, followed by the virtual strips; these extra- +# # ordinary strips have width <-infinity> so are dealt with separately. +# # Once they are out of the way, the length-lexicographical ordering +# # kicks in. +# +# # We first compare the widths of and . This will dis- +# # -tinguish a strip that is zero or virtual from one that is neither. +# if WidthOfStrip(strip1) < WidthOfStrip(strip2) then +# return true; +# +# elif WidthOfStrip(strip1) > WidthOfStrip(strip2) then +# return false; +# +# # If both of the above fail, and have the same width. +# else +# +# # If that width is <-infinity> then and are zero +# # or virtual. In that case, if one is zero and the other isn't +# # then the zero strip is less (in the sense of <\<>). +# if IsZeroStrip(strip1) and (not IsZeroStrip(strip2)) then +# return true; +# elif (not IsZeroStrip(strip1)) and IsZeroStrip(strip2) then +# return false; +# elif IsZeroStrip(strip1) and IsZeroStrip(strip2) then +# return false; +# +# # If none of the above cases are met, then neither nor +# # is a zero strip. In this case, the lexicographical +# # order we define below will distinguish between strips of the +# # same width. (This includes width <-infinity>, in which case we +# # must be distinguishing between virtual strips.) +# else +# +# # Recall that any strip is equal (ie, \= returns true) to its +# # reflection. This means that we don't just compare strips, we +# # compare "reflection"-classes of strips. In practice, we come +# # up with a "dictionary" version of each strip and use this as +# # the basis for our comparison. We write out the syllable list +# # of the strip and write out that of its reflection, compare +# # the two lexicographically (via the \< ordering on syll- +# # -ables); whichever of this is least, is the "dictionary" +# # version of the input strip. +# +# sy_list_1 := SyllableListOfStripNC(strip1); +# sy_list_r1 := SyllableListOfStripNC( +# ReflectionOfStrip(strip1) +# ); +# list1 := Minimum(sy_list_1, sy_list_r1); +# +# sy_list_2 := SyllableListOfStripNC(strip2); +# sy_list_r2 := SyllableListOfStripNC( +# ReflectionOfStrip(strip2) +# ); +# list2 := Minimum(sy_list_2, sy_list_r2); +# +# return list1 < list2; +# fi; +# fi; +# end +# ); +# +# InstallMethod( +# IsWeaklyPeriodicStripByNthSyzygy, +# "for a strip and a positive integer", +# [IsStripRep, IsPosInt], +# function(strip, N) +# local +# found_yet, # Boolean, storing whether a repeat has been found +# j, # Integer variable +# syz; # List variable +# +# found_yet := false; +# j := 0; +# syz := Set([strip]); +# while found_yet = false and j < N do +# j := j + 1; +# syz := Set(SyzygyOfStrip(syz)); +# if strip in syz then +# found_yet := true; +# Info(InfoSBStrips, 2, "Examining strip: ", String(strip)); +# Info(InfoSBStrips, 2, "This strip first appears as a direct ", +# "summand of its ", Ordinal(j), " syzygy"); +# return true; +# fi; +# od; +# +# Info(InfoSBStrips, 2, "Examining strip: ", String(strip)); +# Info(InfoSBStrips, 2, "This strip does not occur as a summand of ", +# "its first ", String(N), " syzygies"); +# return false; +# end +# ); +# +# InstallMethod( +# IsFiniteSyzygyTypeStripByNthSyzygy, +# "for a strip and a positive integer", +# [IsStripRep, IsPosInt], +# function(strip, N) +# local +# j, # Integer variable, storing which "stage" our +# # calculation is at +# new_syz_set, # Set variable, storing those strips "new" at stage +# # +# old_syz_set; # Set variable, storing those strips "old" at stage +# # (ie, seen strictly before) +# +# # Initialize at stage <0>. At this stage, nothing is "old" and +# # is new +# j := 0; +# new_syz_set := Set([strip]); +# old_syz_set := Set([]); +# +# # Proceed stage by stage +# while j <= N do +# # Increment the stage number +# j := j + 1; +# +# # All strips new at the previous stage are old at the current one +# UniteSet(old_syz_set, new_syz_set); +# +# # Take syzygies of the strips that were new at the previous stage +# new_syz_set := Set(SyzygyOfStrip(new_syz_set)); +# +# # Remove from the syzygies the strips that are old at this stage +# SubtractSet(new_syz_set, old_syz_set); +# +# # Whatever is left is new at this stage. If nothing is new at this +# # stage, then has finite syzygy type of degree at most +# # and we can stop. +# +# if IsEmpty(new_syz_set) then +# Info(InfoSBStrips, 2, "Examining strip: ", String(strip)); +# Info(InfoSBStrips, 2, "This strip has finite syzygy type."); +# Info(InfoSBStrips, 2, "The set of strings appearing as ", +# "summands of its first N syzygies stabilizes at index N=", +# String(j-1), ", at which point it has cardinality ", +# String(Size(old_syz_set))); +# return true; +# fi; +# od; +# +# Info(InfoSBStrips, 2, "Examining strip: ", String(strip)); +# Info(InfoSBStrips, 2, "The set of strings appearing as summands of ", +# "its first ", String(N), " syzygies has cardinality ", +# Size(old_syz_set)); +# return false; +# end +# ); +# +# InstallGlobalFunction( +# TestInjectiveStripsUpToNthSyzygy, +# "for a SB algebra and a positive integer", +# function(sba, N) +# local +# non_pin_inj_list, # , with all s removed +# inj_list, # The pinjective strips of +# test_list; # Results of testing the entries of +# # up to degree +# +# inj_list := IndecInjectiveStripsOfSBAlg(sba); +# non_pin_inj_list := Filtered(inj_list, x -> not (x = fail)); +# test_list := List( +# non_pin_inj_list, +# x -> IsFiniteSyzygyTypeStripByNthSyzygy(x, N) +# ); +# +# if false in test_list then +# Print("The given SB algebra has failed the test.\n"); +# else +# Print("The given SB algebra has passed the test!\n"); +# fi; +# +# return; +# end +# ); +# + +# ----------------------------------------------------------------------------- + +InstallMethod( + ModuleDataOfBelt, + "for a belt-rep", + [IsBeltRep], + function(belt) + local + data, # Syllable and orientation list in + dim_vector, # Dimension vector of the output module + expand_neg_syll, expand_pos_syll, + # Local functions which turn syllables into "expanded + # walks" + expanded, # Total expanded walk of belt + field, # Ground field of + gens, # Arrow-indexed list of matrices corresponding to the + # -linear maps described by + is_nonnull_mat, + # Local function, to be used to filter out matrices of + # zeroes from output + L_data, L_expanded, + # Integer variable (for the lengths of and + # respectively) + m, # Integer variable (for the even indices of ) + matrix_of_arrow, + # Local function which turns an arrow of into + # a matrix representing a linear map, as specified by + # + one, # Multiplicative identity of + quiv, # Ground quiver of + sba, # SB algebra to which belongs + vertex_multiplicity_up_to, + # Local function which counts the number of times a + # vertex appears in before a given index + zero; # Additive identity of + + sba := FamilyObj(belt)!.sb_alg; + quiv := QuiverOfPathAlgebra(OriginalPathAlgebra(sba)); + + field := FieldOfQuiverAlgebra(sba); + one := One(field); + zero := Zero(field); + + # Our first step is to unpack the data of . We + # unpack it into a list whose entries are alternately (i) vertices of + # the ground quiver and (ii) lists of the form [arr, N] for an + # arrow of the ground quiver and either 1 or -1. From this + # "expanded walk" , creating the associated string module is + # straightforward. + # + # The "expanded walk" of a given positive syllable + # + # A B C + # i --> ii --> iii --> iv + # + # looks like + # + # [i, [A,1], ii, [B,1], iii, [C,1]] + # + # (notice there's no iv!) while the "expanded walk" of a negative + # syllable + # + # C B A + # iv <-- iii <-- ii <-- i + # + # looks like + # + # [iv, [C,-1], iii, [B,-1], ii, [A,-1]] + # (notice there's no i!). These are respectively calculated using the + # functions and . + + expand_neg_syll := function(syll) + local + a, # Arrow variable (for entries of ) + exp_walk, # "Expanded" version of + k, # Integer variable (indexing the entries of + opath, # Underlying path (in the overquiver) of + path, # Ground path represented by + walk; # Walk of + + opath := UnderlyingPathOfSyllable(syll); + path := GroundPathOfOverquiverPathNC(opath); + walk := WalkOfPath(path); + exp_walk := []; + + # Note that if is a stationary path, then the following FOR + # loop is null + for k in [1 .. Length(WalkOfPath(path))] do + a := walk[k]; + Add(exp_walk, [a, -1]); + Add(exp_walk, TargetOfPath(a)); + od; + + # If is a stationary path, then has length 1 and + # so equals its reverse + return Reversed(exp_walk); + end; + + expand_pos_syll := function(syll) + local + a, # Arrow variable (for entries of ) + exp_walk, # "Expanded" version of + k, # Integer variable (indexing the entries of + opath, # Underlying path (in the overquiver) of + path, # Ground path represented by + walk; # Walk of + + opath := UnderlyingPathOfSyllable(syll); + path := GroundPathOfOverquiverPathNC(opath); + walk := WalkOfPath(path); + exp_walk := []; + + # Note that if is a stationary path, then the following FOR + # loop is null + for k in [1 .. Length(WalkOfPath(path))] do + a := walk[k]; + Add(exp_walk, SourceOfPath(a)); + Add(exp_walk, [a, 1]); + od; + + return exp_walk; + end; + + data := belt!.data; + L_data := Length(data); + expanded := []; + + for m in Filtered([1 .. L_data], IsEvenInt) do + if data[m] = -1 then + Append(expanded, expand_neg_syll(data[m-1])); + + else + Append(expanded, expand_pos_syll(data[m-1])); + fi; + od; + + # Now, the "expanded walk" is finished. From it, we obtain the + # dimension vector and matrices of the desired quiver representation. + + # The entries of at odd indices constitute a basis for the + # resulting module. Therefore, the dimension of the vector space at a + # given vertex is the number of times appears in . + # + # The basis of the resulting module is the coproduct (ie, disjoint + # union) of the bases at each vertex, but note that we take the basis + # vectors of the module in the order they appear in . When + # determining which basis vector is sent by a linear map to which + # other vector (or rather, concretely, in which position of the + # associated matrix to place a ), we need to know how many other + # basis vector of *that vertex space* have appeared in the order be- + # -fore it. + + vertex_multiplicity_up_to := function(vertex, index) + return Number( + expanded{[1 .. index]}, + x -> x = vertex + ); + end; + + L_expanded := Length(expanded); + + dim_vector := List( + VerticesOfQuiver(quiv), + v -> vertex_multiplicity_up_to(v, L_expanded) + ); + + matrix_of_arrow := function(arrow) + local + c, r, # Integer variables (respectively for the column and + # row index of that needs a + C, R, # Integer variables (respectively for the number of + # columns and rows must have) + entry, # Variable (for the entries of at odd + # indices) + matrix, # Matrix variable, for the matrix of the linear map + # associated to + k, # Integer variable (for the odd indices of ) + source, # Source of + target; # Target of + + source := SourceOfPath(arrow); + target := TargetOfPath(arrow); + + R := vertex_multiplicity_up_to(source, L_expanded); + C := vertex_multiplicity_up_to(target, L_expanded); + + matrix := NullMat(R, C, field); + + for k in Filtered([1 .. L_expanded], IsEvenInt) do + entry := expanded[k]; + + if entry[1] = arrow then + # Define adjacent indices to the left and right + k_p := k - 1; + k_n := (k mod L_expanded) + 1; + + if entry[2] = 1 then + r := vertex_multiplicity_up_to(source, k_p); + c := vertex_multiplicity_up_to(target, k_n); + matrix[r][c] := one; + + else + r := vertex_multiplicity_up_to(source, k_n); + c := vertex_multiplicity_up_to(target, k_p); + matrix[r][c] := one; + fi; + fi; + od; + + return matrix; + end; + + # We only need to tell GAP about matrices of nonzero linear maps. The + # following function can detect them. + is_nonnull_mat := function(mat) + return not ForAll(Flat(mat), x -> x = zero); + end; + + # We find the nonzero matrices and tell them to GAP. + gens := List( + Filtered( + ArrowsOfQuiver(quiv), + x -> is_nonnull_mat(matrix_of_arrow(x)) + ), + x -> [String(x), matrix_of_arrow(x)] + ); + + return Immutable([sba, dim_vector, gens]); + end +); + +InstallMethod( + ModuleOfBelt, + "for belt-reps", + [IsBeltRep], + function(belt) + return CallFuncList( + RightModuleOverPathAlgebra, + ModuleDataOfBelt(belt) + ); + end +); + +InstallOtherMethod( + ModuleOfBelt, + "for (flat) lists of belts", + [IsList], + function(list) + + if not (ForAll(list, IsBeltRep)) then + TryNextMethod(); + + else + return List(list, ModuleOfBelt); + + fi; + end +); + +InstallOtherMethod( + ModuleOfBelt, + "for collected lists of belts", + [IsList], + function(clist) + local + elts; # Variable, for elements of + + if not IsCollectedList(clist) then + TryNextMethod(); + + else + elts := List(clist, x -> x[1]); + if not ForAll(elts, IsBeltRep) then + TryNextMethod(); + + else + return + CollectedListElementwiseFunction(clist, ModuleOfBelt); + fi; + fi; + end +); + +# ----------------------------------------------------------------------------- + +# +# InstallMethod( +# DirectSumModuleDataOfListOfStrips, +# "for a (flat) list of strips", +# [IsList], +# function(list) +# local +# a, # Arrow variable +# arrow_mat, # Matrix variable +# arrs, # Arrows of +# C,c, # Integer variables +# constituent_dim_vectors, +# # Dimension vectors of modules associated to strips in +# # +# datum, # Entry of +# data, # Module data of strips +# dim_vector, # List variable, for dimension vectors +# fam, # Family variable +# field, # Ambient field of +# gens, # Arrow-and-matrix information of an entry of +# k, # Integer variable, for indices of entries of +# mat, # Matrix variable +# output_dim_vector, +# # Dimension vector of output module +# output_gens, +# # Arrow-and-matrix information of output +# pad_data, # Local function, that adds null matrices where +# # necessary +# R, r, # Integer variables +# quiv, # Ground quiver of +# sba, # SB algebra of definition +# sourcedim, targetdim, +# # Dimension of space at source/target of +# sourcepos, targetpos, +# # Position of source/target of in +# verts; # Vertices of +# +# if IsEmpty(list) then +# Error("The input list cannot be empty!"); +# +# elif IsCollectedList(list) then +# TryNextMethod(); +# +# elif +# not (IsHomogeneousList(list) and ForAll(list, IsStripRep)) +# then +# Error("The input list\n", list, +# "\nmust be a homogeneous list of strips!"); +# +# else +# data := List(list, x -> ShallowCopy(ModuleDataOfStrip(x))); +# +# # Each constituent strip in gives us three pieces of +# # information: +# # +# # (i) the SB algebra over which the strip is defined +# # (ii) the dimension vector of the quiver representation +# # associated to that strip +# # (iii) The matrices of the nonzero linear maps in the quiver +# # representation associated to that strip +# # +# # Our task is to combine the constituent information into the +# # defining information of a single module, the direct sum. We +# # assemble this information one part at a time. +# +# # (i) +# # +# # This is easy, because all strips in strip are defined over the +# # same SB algebra. We can harvest it from the first strip. +# +# fam := FamilyObj(list[1]); +# sba := fam!.sb_alg; +# +# # While we're here, harvest further information from +# field := FieldOfQuiverAlgebra(sba); +# quiv := DefiningQuiverOfQuiverAlgebra(sba); +# arrs := ArrowsOfQuiver(quiv); +# verts := VerticesOfQuiver(quiv); +# +# # (ii) +# # +# # This is also easy. We can just sum the constituent dimension +# # vectors. +# +# constituent_dim_vectors := List(data, x -> x[2]); +# output_dim_vector := Sum(constituent_dim_vectors); +# +# # (iii) +# # +# # This is the most work. To each arrow of the quiver of we +# # must associate a matrix, namely the the coproduct of the con- +# # -stituent matrices. This entails create block-diagonal matrices. +# # Unfortunately, GAP does not (appear to) have methods for +# # creating block matrices where individual blocks have different +# # dimensions, so we have to do the hard work ourselves. +# +# # The matrices associated to arrows for each constituent strip will +# # be the blocks on the main block diagonal; this means that all +# # blocks off the main block-diagonal are certainly zero. However, +# # some of the blocks on the main block-diagonal are zero too. +# # Before assembling the block matrix, we have to create null +# # matrices for arrows where necessary. +# +# # We write a local function to this effect. +# +# pad_data := function(mdos) +# +# # abbreviates "module data of strip" +# +# local +# a, # Arrow variable +# dim_vector, # List variable for dimension vector +# gens, # Third entry of , the arrow-indexed +# # list of matrices. +# present_arrows, # Arrows present in +# sourcepos, targetpos, +# # Position in of the source/target +# # vertex of +# sourcedim, targetdim; +# # Dimension of space at the source/target +# # of +# +# dim_vector := mdos[2]; +# mdos[3] := ShallowCopy(mdos[3]); +# gens := mdos[3]; +# present_arrows := List(gens, x -> x[1]); +# +# for +# a in Filtered(arrs, x -> not String(x) in present_arrows) +# do +# sourcepos := Position(verts, SourceOfPath(a)); +# targetpos := Position(verts, TargetOfPath(a)); +# +# sourcedim := dim_vector[sourcepos]; +# targetdim := dim_vector[targetpos]; +# +# Add( +# gens, +# [String(a), NullMat(sourcedim, targetdim, field)] +# ); +# od; +# end; +# +# # We apply the local function +# +# for k in [1 .. Length(data)] do +# pad_data(data[k]); +# od; +# +# # We work arrow by arrow, assembling block matrices. +# +# output_gens := []; +# +# for a in arrs do +# # We create a placeholder matrix , initially null +# sourcepos := Position(verts, SourceOfPath(a)); +# targetpos := Position(verts, TargetOfPath(a)); +# +# sourcedim := output_dim_vector[sourcepos]; +# targetdim := output_dim_vector[targetpos]; +# +# mat := NullMat(sourcedim, targetdim, field); +# +# # Next, we work constituent by constituent, overwriting entries +# # of with the entries of the matrix associated to by +# # that constituent. +# +# R := 0; +# C := 0; +# +# for k in [1 .. Length(data)] do +# datum := data[k]; +# dim_vector := datum[2]; +# sourcedim := dim_vector[sourcepos]; +# targetdim := dim_vector[targetpos]; +# gens := datum[3]; +# arrow_mat := First(gens, x -> x[1] = String(a))[2]; +# +# for r in [1 .. Length(arrow_mat)] do +# for c in [1 .. Length(arrow_mat[r])] do +# mat[R + r][C + c] := arrow_mat[r][c]; +# od; +# od; +# +# R := R + sourcedim; +# C := C + targetdim; +# od; +# +# Add(output_gens, [String(a), mat]); +# od; +# +# return Immutable([sba, output_dim_vector, output_gens]); +# fi; +# end +# ); +# +# InstallOtherMethod( +# DirectSumModuleDataOfListOfStrips, +# "for a collected list of strips", +# [IsList], +# function(clist) +# if not IsCollectedList(clist) then +# TryNextMethod(); +# +# else +# # Uncollect and then delegate to the (flat) list method for +# # +# return DirectSumModuleDataOfListOfStrips(Uncollected(clist)); +# fi; +# end +# ); +# +# InstallMethod( +# DirectSumModuleOfListOfStrips, +# "for a (flat) or collected list of strips", +# [IsList], +# function(list) +# # Delegate to for all the hard +# # work. It has one method for (flat) lists and one for collected +# # lists. It will pick the appropriate method to treat , and will +# # also be able to check that is valid input and is able to test +# # them for validity. +# +# return CallFuncList( +# RightModuleOverPathAlgebra, +# DirectSumModuleDataOfListOfStrips(list) +# ); +# end +# ); +# +# InstallOtherMethod( +# DirectSumModuleOfListOfStrips, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# # Make into a one-entry list +# return DirectSumModuleOfListOfStrips([strip]); +# end +# ); +# +# InstallMethod( +# VectorSpaceDualOfStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# local +# data, # Defining data of +# k, # Integer variable, for positions in a list +# opposite_path_or_orientation, +# # Local function, turning paths or orientations into +# # the opposite path or orientation +# sba, # Defining SB algebra of +# sba_op, # Opposite path algebra of +# strip_op, # Output +# syll_list, # Syllable list of +# x, y, # Variables, for vertices or syllables +# zero_op; # Zero strip of +# +# # Test whether the hard work has already been done +# if HasVectorSpaceDualOfStrip(strip) then +# return VectorSpaceDualOfStrip(strip); +# +# # Reject virtual strips. (They do not correspond to string modules, so +# # they have no sensible vector-space dual.) +# elif IsVirtualStripRep(strip) then +# ErrorNoReturn("Virtual strips do not have vector-space duals!"); +# +# # Otherwise, only strips that represent string modules remain. +# else +# sba := SBAlgOfStrip(strip); +# sba_op := OppositePathAlgebra(sba); +# +# # Deal with zero strip. +# if IsZeroStrip(strip) then +# strip_op := ZeroStripOfSBAlg(sba_op); +# +# # Deal with simple strips (ie, strips of width 0). +# elif WidthOfStrip(strip) = 0 then +# +# # By constuction, simple strips are the juxtaposition of two +# # stationary syllables, displayed <(x, 1)^{-1}(y, 1)>. We +# # can harvest the underlying paths and of those +# # syllables, then turn them into their opposite paths , +# # in the opposite (over)quiver, then construct the +# # opposite strip easily: <(x_op, 1)^{-1}(y_op, 1)>. +# +# # Obtain syllable list +# syll_list := SyllableListOfStripNC(strip); +# +# # Harvest paths +# x := UnderlyingPathOfSyllable(syll_list[1]); +# y := UnderlyingPathOfSyllable(syll_list[2]); +# +# # Make into opposite paths +# x := OppositePath(x); +# y := OppositePath(y); +# +# # Make into stationary syllables (which always have stability +# # term 1). +# x := Syllabify(x, 1); +# y := Syllabify(y, 1); +# +# # Create vector-space-dual string +# strip_op := +# StripifyFromSyllablesAndOrientationsNC(x, -1, y, 1); +# +# # Deal with strips of positive width. +# else +# data := ShallowCopy( +# PathAndOrientationListOfStripNC(strip) +# ); +# +# # Replace all paths by opposite paths, and swap all orient- +# # -ations +# +# opposite_path_or_orientation := function(elt) +# if IsPath(elt) then +# return OppositePath(elt); +# +# elif elt in [1, -1] then +# return -1 * elt; +# fi; +# end; +# +# Apply(data, opposite_path_or_orientation); +# +# # Turn paths into syllables, taking into account whether they +# # should be boundary or not +# for k in Filtered([1 .. Length(data)], IsOddInt) do +# if (k = 1) and data[k + 1] = -1 then +# data[k] := Syllabify(data[k], 1); +# +# elif (k = Length(data) - 1) and data[k + 1] = 1 then +# data[k] := Syllabify(data[k], 1); +# +# else +# data[k] := Syllabify(data[k], 0); +# fi; +# od; +# +# strip_op := CallFuncList( +# StripifyFromSyllablesAndOrientationsNC, +# data +# ); +# fi; +# +# # Ensure the double-dual is identically the original object. +# SetVectorSpaceDualOfStrip(strip_op, strip); +# return strip_op; +# fi; +# end +# ); +# +# InstallMethod( +# PathAndOrientationListOfStripNC, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# local +# data, # Defining data of +# is_stationary_func, +# # Local function, checking for stationary syllables +# is_stationary_results, +# # Entrywise image of is +# k, # Integer variable, for indexing entries of +# make_syllables_into_paths; +# # Local function, checking for syllables and replacing +# # them by their underlying paths +# +# data := ShallowCopy(DefiningDataOfStripNC(strip)); +# +# if WidthOfStrip(strip) = 0 then +# data[1] := UnderlyingPathOfSyllable(data[1]); +# data[3] := UnderlyingPathOfSyllable(data[3]); +# +# else +# is_stationary_func := function(elt) +# return +# IsSyllableRep(elt) and IsStationarySyllable(elt); +# end; +# +# while ForAny(data, is_stationary_func) do +# is_stationary_results := List(data, is_stationary_func); +# k := Position(is_stationary_results, true); +# Remove(data, k + 1); +# Remove(data, k); +# od; +# +# # Replace syllables by underlying paths +# +# make_syllables_into_paths := function(elt) +# if IsSyllableRep(elt) then +# return UnderlyingPathOfSyllable(elt); +# +# else +# return elt; +# fi; +# end; +# +# Apply(data, make_syllables_into_paths); +# fi; +# +# return Immutable(data); +# end +# ); +# +# InstallMethod( +# RightAlterationTowardsTrDOfStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# # This attribute is the (?)_1 operation from [WW85, Sec 3] while +# # is the (?)_2 operation. Of +# # course, = , for the reflection of the strip . +# # +# # [WW85] +# # B. Wald and J. Waschbuesch +# # Tame biserial algebras +# # Journal of Algebra, 95:480-500 +# # 1985 +# +# local +# a_i, b_i, c_i, d_i, +# # th term of , , and , +# # respectively +# a_seq, b_seq, +# # Integer and bit sequence of the source encoding of +# # the permissible data of +# c_seq, d_seq, +# # Integer and bit sequence of the target encoding of +# # the permissible data of +# data, # Defining data of strip +# i, # Vertex variable +# l, # Integer variable, for the length of a path +# k, # Integer variable, for indexing entries of +# lin_ind, # Set of paths representing linearly independent +# # paths in +# make_substrip, +# # Local function obtaining a "substrip" of +# make_superstrip, +# # Local function obtaining a "superstrip" of +# p, q, r, # Path variables +# return_zero_strip, +# # Boolean variable, determining whether to return +# # or not +# sba, # Defining SB algebra of +# v, # Vertex variable +# x, y, # Syllable variables +# zero_strip; # Zero strip of +# +# sba := SBAlgOfStrip(strip); +# zero_strip := ZeroStripOfSBAlg(sba); +# +# if HasRightAlterationTowardsTrDOfStrip(strip) then +# return RightAlterationTowardsTrDOfStrip(strip); +# +# # The "right alteration" of the zero strip is the zero strip. +# elif IsZeroStrip(strip) then +# return zero_strip; +# +# # Reject virtual strips, since they do not represent string modules. +# elif IsVirtualStripRep(strip) then +# ErrorNoReturn("No right alteration exists for virtual strips!"); +# +# # is compatible with +# # and +# # in the fashion mentioned above. If +# # the other is already known, then we can save ourselves some hard +# # work. +# # elif +# # HasLeftAlterationTowardsTrDOfStrip(ReflectionOfStrip(strip)) +# # then +# # return ReflectionOfStrip( +# # LeftAlterationTowardsTrDOfStrip( +# # ReflectionOfStrip(strip) +# #) +# #); +# +# # Deal with simple strips +# elif WidthOfStrip(strip) = 0 then +# a_seq := SourceEncodingOfPermDataOfSBAlg(sba)[1]; +# b_seq := SourceEncodingOfPermDataOfSBAlg(sba)[2]; +# c_seq := TargetEncodingOfPermDataOfSBAlg(sba)[1]; +# d_seq := TargetEncodingOfPermDataOfSBAlg(sba)[2]; +# +# data := ShallowCopy(DefiningDataOfStripNC(strip)); +# data[1] := UnderlyingPathOfSyllable(data[1]); +# data[3] := UnderlyingPathOfSyllable(data[3]); +# +# i := data[3]; +# +# c_i := c_seq.(String(i)); +# if c_i = 0 then +# return zero_strip; +# +# else +# p := PathByTargetAndLength(i, 1); +# i := ExchangePartnerOfVertex(SourceOfPath(p)); +# +# a_i := a_seq.(String(i)); +# b_i := b_seq.(String(i)); +# q := PathBySourceAndLength(i, a_i + b_i - 1); +# +# x := Syllabify(p, 1); +# y := Syllabify(q, 1); +# +# return StripifyFromSyllablesAndOrientationsNC(x, -1, y, 1); +# fi; +# +# # Deal with strips of positive width +# else +# data := ShallowCopy(PathAndOrientationListOfStripNC(strip)); +# return_zero_strip := false; +# +# # Setup +# lin_ind := LinIndOfSBAlg(sba); +# +# a_seq := SourceEncodingOfPermDataOfSBAlg(sba)[1]; +# b_seq := SourceEncodingOfPermDataOfSBAlg(sba)[2]; +# c_seq := TargetEncodingOfPermDataOfSBAlg(sba)[1]; +# d_seq := TargetEncodingOfPermDataOfSBAlg(sba)[2]; +# +# if data[Length(data)] = -1 then +# make_substrip := function() +# local +# p; # Path variable +# +# if Length(data) = 2 then +# return_zero_strip := true; +# +# else +# Remove(data, Length(data)); +# Remove(data, Length(data)); +# p := data[Length(data) - 1]; +# data[Length(data) - 1] := +# PathOneArrowShorterAtTarget(p); +# +# if +# Length(data) = 2 and LengthOfPath(data[1]) = 0 +# then +# data[2] := -1; +# fi; +# fi; +# end; +# +# p := data[Length(data) - 1]; +# +# if PathOneArrowLongerAtSource(p) in lin_ind then +# p := PathOneArrowLongerAtSource(p); +# i := ExchangePartnerOfVertex(SourceOfPath(p)); +# +# a_i := a_seq.(String(i)); +# b_i := b_seq.(String(i)); +# q := PathBySourceAndLength(i, a_i + b_i - 1); +# +# data[Length(data) - 1] := p; +# Add(data, q); +# Add(data, 1); +# +# else +# make_substrip(); +# +# fi; +# +# elif data[Length(data)] = 1 then +# make_substrip := function() +# local +# p; # Path variable +# +# p := data[Length(data) - 1]; +# data[Length(data) - 1] := +# PathOneArrowShorterAtTarget(p); +# +# if Length(data) = 2 and LengthOfPath(data[1]) = 0 then +# data[2] := -1; +# fi; +# end; +# +# r := data[Length(data) - 1]; +# i := ExchangePartnerOfVertex(TargetOfPath(r)); +# +# c_i := c_seq.(String(i)); +# +# if c_i > 0 then +# d_i := d_seq.(String(i)); +# p := PathByTargetAndLength(i, 1); +# i := ExchangePartnerOfVertex(SourceOfPath(p)); +# a_i := a_seq.(String(i)); +# b_i := b_seq.(String(i)); +# q := PathBySourceAndLength(i, a_i + b_i - 1); +# Add(data, p); +# Add(data, -1); +# Add(data, q); +# Add(data, 1); +# else +# make_substrip(); +# fi; +# fi; +# +# if return_zero_strip then +# return zero_strip; +# fi; +# +# for k in Filtered([1 .. Length(data)], IsOddInt) do +# if k = 1 and data[2] = -1 then +# data[k] := Syllabify(data[k], 1); +# elif +# k = (Length(data) - 1) and data[k + 1] = 1 +# then +# data[k] := Syllabify(data[k], 1); +# else +# data[k] := Syllabify(data[k], 0); +# fi; +# od; +# +# return +# CallFuncList(StripifyFromSyllablesAndOrientationsNC, data); +# fi; +# end +# ); +# +# InstallMethod( +# LeftAlterationTowardsTrDOfStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# if HasLeftAlterationTowardsTrDOfStrip(strip) then +# return LeftAlterationTowardsTrDOfStrip(strip); +# +# elif IsZeroStrip(strip) then +# return strip; +# +# # Reject virtual strips, since they do not represent string modules +# elif IsVirtualStripRep(strip) then +# ErrorNoReturn("No right alteration exists for virtual strips!"); +# +# # is compatible with +# # and +# # in the fashion mentioned above. If +# # the other is already known, then we can save ourselves some hard +# # work. +# else +# return +# ReflectionOfStrip( +# RightAlterationTowardsTrDOfStrip(ReflectionOfStrip(strip)) +# ); +# fi; +# end +# ); +# +# InstallMethod( +# TrDOfStrip, +# "for a strip rep", +# [IsStripRep], +# function(strip) +# local +# left, right, # Left/right "alterations" of +# sba; # Defining SB algebra of +# +# if HasTrDOfStrip(strip) then +# return TrDOfStrip(strip); +# +# elif IsZeroStrip(strip) then +# return strip; +# +# elif IsVirtualStripRep(strip) then +# Error("TrD is not defined on virtual strips, since they do not ", +# "represent string modules!"); +# +# elif IsIndecInjectiveStrip(strip) then +# sba := SBAlgOfStrip(strip); +# +# return ZeroStripOfSBAlg(sba); +# +# else +# left := LeftAlterationTowardsTrDOfStrip(strip); +# right := RightAlterationTowardsTrDOfStrip(strip); +# +# # If both alterations are zero strips, then return the zero strip. +# if IsZeroStrip(left) and IsZeroStrip(right) then +# return left; +# +# # If exactly one alteration is a zero strip, alter the nonzero +# # alteration on the second side. +# elif IsZeroStrip(left) and (not IsZeroStrip(right)) then +# return LeftAlterationTowardsTrDOfStrip(right); +# +# elif (not IsZeroStrip(left)) and IsZeroStrip(right) then +# return RightAlterationTowardsTrDOfStrip(left); +# +# # Otherwise, neither alteration is zero. +# else +# if not +# (RightAlterationTowardsTrDOfStrip(left) +# = +# LeftAlterationTowardsTrDOfStrip(right)) +# then +# Error("The left and right alterations of the given strip\n", +# strip, "\ndo not agree when they should. You have revealed ", +# "a bug! Please contact the maintainer of the SBStrips ", +# "package!"); +# +# else +# return RightAlterationTowardsTrDOfStrip(left); +# fi; +# fi; +# fi; +# end +# ); +# +# InstallOtherMethod( +# TrDOfStrip, +# "for a (flat) list of strips", +# [IsList], +# function(list) +# if not ForAll(list, IsStripRep) then +# TryNextMethod(); +# +# else +# return List(list, TrDOfStrip); +# fi; +# end +# ); +# +# InstallOtherMethod( +# TrDOfStrip, +# "for a collected list of strips", +# [IsList], +# function(clist) +# local +# elts; # Elements of +# +# if not IsCollectedList(clist) then +# TryNextMethod(); +# +# else +# elts := List(clist, x -> x[1]); +# +# if not ForAll(elts, IsStripRep) then +# TryNextMethod(); +# +# else +# return CollectedListElementwiseFunction(clist, TrDOfStrip); +# fi; +# fi; +# end +# ); +# +# InstallMethod( +# DTrOfStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# if HasDTrOfStrip(strip) then +# return DTrOfStrip(strip); +# +# else +# return DOfStrip(TrDOfStrip(DOfStrip(strip))); +# fi; +# end +# ); +# +# InstallOtherMethod( +# DTrOfStrip, +# "for a list of strip-reps", +# [IsList], +# function(list) +# if not (ForAll(list, IsStripRep)) then +# TryNextMethod(); +# else +# return List(list, DTrOfStrip); +# fi; +# end +# ); +# +# InstallOtherMethod( +# DTrOfStrip, +# "for a collected list of strip-reps", +# [IsList], +# function(clist) +# local +# elts; # Element list of +# +# if IsCollectedList(clist) then +# elts := List(clist, x -> x[1]); +# +# if ForAll(elts, IsStripRep) then +# return CollectedListElementwiseFunction(clist, DTrOfStrip); +# +# else +# Error("The given collected list has elements that are not ", +# "strips!"); +# fi; +# else +# TryNextMethod(); +# fi; +# end +# ); +# +# InstallMethod( +# TrOfStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# if HasTransposeOfStrip(strip) then +# return TransposeOfStrip(strip); +# +# else +# return TrDOfStrip(DOfStrip(strip)); +# fi; +# end +# ); +# +# InstallOtherMethod( +# TrOfStrip, +# "for a (flat) list of strip-reps", +# [IsList], +# function(list) +# if not ForAll(list, IsStripRep) then +# TryNextMethod(); +# +# else +# return List(list, TrOfStrip); +# fi; +# end +# ); +# +# InstallOtherMethod( +# TrOfStrip, +# "for a collected list of strip-reps", +# [IsList], +# function(clist) +# local +# elts; # Element list of +# +# if not IsCollectedList(clist) then +# TryNextMethod(); +# +# else +# elts := List(clist, x -> x[1]); +# if not ForAll(elts, IsStripRep) then +# Error("The given collected list has elements that are not ", +# "strip-reps!"); +# +# else +# return CollectedListElementwiseFunction(clist, TrOfStrip); +# fi; +# fi; +# end +# ); +# +# InstallMethod( +# SuspensionOfStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# if HasSuspensionOfStrip(strip) then +# return SuspensionOfStrip(strip); +# +# elif IsVirtualStripRep(strip) then +# Error("Virtual strips do not have suspensions"); +# +# elif IsZeroStrip(strip) then +# return strip; +# +# else +# return TrOfStrip(SyzygyOfStrip(TrOfStrip(strip))); +# fi; +# end +# ); +# +# InstallOtherMethod( +# SuspensionOfStrip, +# "for a (flat) list of strip-reps", +# [IsList], +# function(list) +# if IsCollectedList(list) then +# TryNextMethod(); +# +# elif not ForAll(list, IsStripRep) then +# TryNextMethod(); +# +# else +# return Concatenation(List(list, SuspensionOfStrip)); +# fi; +# end +# ); +# +# InstallOtherMethod( +# SuspensionOfStrip, +# "for a collected list of strip-reps", +# [IsList], +# function(clist) +# local +# elts; # Elements of +# +# if not IsCollectedList(clist) then +# TryNextMethod(); +# +# else +# elts := List(clist, x -> x[1]); +# if not ForAll(elts, IsStripRep) then +# Error("The given collected list has elements that are not ", +# "strip-reps"); +# +# else +# return CollectedListElementwiseListValuedFunction( +# clist, +# x -> WithoutProjectiveStrips(SuspensionOfStrip(x)) +# ); +# fi; +# fi; +# end +# ); +# +# InstallMethod( +# IsStripDirectSummand, +# "for a collected list of strip-reps and a collected list of strip-reps", +# [IsList, IsList], +# function(strips, list) +# local +# k, # Integer variable, storing index of zero strip +# list_elts, # Element list of +# strips_elts, # Element list of +# where_zero; # Locations of zero strips +# +# if IsEmpty(strips) then +# return true; +# +# elif (IsCollectedListOfStripReps(strips) +# and IsCollectedListOfStripReps(list)) +# then +# list_elts := ElementsOfCollectedList(list); +# strips_elts := ElementsOfCollectedList(strips); +# +# # Neither nor should virtual strips. +# if +# ForAny(strips_elts, IsVirtualStripRep) or +# ForAny(list_elts, IsVirtualStripRep) +# then +# Error("Virtual strips do not represent string modules! They ", +# "cannot be direct summands!"); +# +# else +# # If contains any zero strips, remove them and call +# # again. +# if ForAny(strips_elts, IsZeroStrip) then +# where_zero := List(strips_elts, IsZeroStrip); +# k := Position(where_zero, true); +# strips := ShallowCopy(strips); +# Remove(strips, k); +# +# return IsStripDirectSummand(strips, list); +# +# # If contains any zero strips, remove them and call +# # again. +# elif ForAny(list_elts, IsZeroStrip) then +# where_zero := List(list_elts, IsZeroStrip); +# k := Position(where_zero, true); +# list_elts := ShallowCopy(list_elts); +# Remove(list_elts, k); +# +# return IsStripDirectSummand(strips, list); +# +# else +# return IsCollectedSublist(strips, list); +# fi; +# fi; +# +# else +# TryNextMethod(); +# fi; +# end +# ); +# +# InstallMethod( +# IsStripDirectSummand, +# "for a (flat) list of strip-reps and a collected list of strip-reps", +# [IsList, IsList], +# function(strips, list) +# if +# IsFlatListOfStripReps(strips) and IsCollectedListOfStripReps(list) +# then +# # If is empty, then answer is true. (This step avoids one +# # recursion deathtrap.) +# if IsEmpty(strips) then +# return true; +# +# # If is nonempty and is empty, the answer is +# # false. (This step avoids another recursion deathtrap.) +# elif IsEmpty(list) then +# return false; +# +# else +# # Otherwise neither argument is empty and we may meaningfully +# # delegate to method where both arguments are collected lists +# return IsStripDirectSummand(Collected(strips), list); +# fi; +# +# else +# TryNextMethod(); +# fi; +# end +# ); +# +# InstallMethod( +# IsStripDirectSummand, +# "for a collected list of strip-reps and a (flat) list of strip-reps", +# [IsList, IsList], +# function(strips, list) +# if +# IsCollectedListOfStripReps(strips) and IsFlatListOfStripReps(list) +# then +# # If is empty, then answer is true. (This step avoids one +# # recursion deathtrap.) +# if IsEmpty(strips) then +# return true; +# +# # If is nonempty and is empty, the answer is +# # false. (This step avoids another recursion deathtrap.) +# elif IsEmpty(list) then +# return false; +# +# else +# # Otherwise neither argument is empty and we may meaningfully +# # delegate to method where both arguments are collected lists +# return IsStripDirectSummand(strips, Collected(list)); +# fi; +# +# else +# TryNextMethod(); +# fi; +# end +# ); +# +# InstallMethod( +# IsStripDirectSummand, +# "for a (flat) list of strip-reps and a (flat) list of strip-reps", +# [IsList, IsList], +# function(strips, list) +# if +# IsFlatListOfStripReps(strips) and IsFlatListOfStripReps(list) +# then +# # If is empty, then answer is true. (This step avoids one +# # recursion deathtrap.) +# if IsEmpty(strips) then +# return true; +# +# else +# # If is nonempty and is empty, the answer is +# # false. (This step avoids another recursion deathtrap.) +# if not IsEmpty(list) then +# return false; +# +# else +# # If neither of the previous cases holds, then we guarantee +# # that both and are nonempty. Hence, we +# # can meaningfully delegate to the method that assumes +# # both arguments are collected lists. +# return IsStripDirectSummand( +# Collected(strips), +# Collected(list) +# ); +# fi; +# fi; +# +# else +# TryNextMethod(); +# fi; +# end +# ); +# +# InstallOtherMethod( +# IsStripDirectSummand, +# "for a strip-rep and a collected list of strip-reps", +# [IsStripRep, IsList], +# function(strip, list) +# if IsCollectedListOfStripReps(list) then +# # Delegate to method where both arguments are collected lists +# return IsStripDirectSummand([[strip], 1], list); +# +# else +# TryNextMethod(); +# fi; +# end +# ); +# +# InstallOtherMethod( +# IsStripDirectSummand, +# "for a strip-rep and a (flat) list of strip-reps", +# [IsStripRep, IsList], +# function(strip, list) +# if IsFlatListOfStripReps(list) then +# # Delegate to method where both arguments are collected lists +# return IsStripDirectSummand([[strip], 1], Collected(list)); +# +# else +# TryNextMethod(); +# fi; +# end +# ); +# +# InstallMethod( +# IsIndecProjectiveStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# local +# projs, # List of projective strips of +# sba; # Defining SB algebra of +# +# if HasIsIndecProjectiveStrip(strip) then +# return IsIndecProjectiveStrip(strip); +# +# else +# sba := SBAlgOfStrip(strip); +# projs := IndecProjectiveStripsOfSBAlg(sba); +# +# return strip in projs; +# fi; +# end +# ); +# +# InstallMethod( +# IsIndecInjectiveStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# local +# injs, # List of injective strips of +# sba; # Defining SB algebra of +# +# if HasIsIndecInjectiveStrip(strip) then +# return IsIndecProjectiveStrip(strip); +# +# else +# sba := SBAlgOfStrip(strip); +# injs := IndecInjectiveStripsOfSBAlg(sba); +# +# return strip in injs; +# fi; +# end +# ); +# +# InstallMethod( +# WithoutProjectiveStrips, +# "for a (flat) list of strips", +# [IsList], +# function(list) +# if IsCollectedListOfStripReps(list) then +# TryNextMethod(); +# +# elif not IsFlatListOfStripReps(list) then +# Error("The given list is not a list of strip-reps!"); +# +# else +# return Filtered( +# list, +# x -> not (IsIndecProjectiveStrip(x) or IsZeroStrip(x)) +# ); +# fi; +# end +# ); +# +# InstallMethod( +# WithoutProjectiveStrips, +# "for a (collected) list of strips", +# [IsList], +# function(clist) +# if not IsCollectedListOfStripReps(clist) then +# TryNextMethod(); +# +# else +# return CollectedFiltered( +# clist, +# x -> not (IsIndecProjectiveStrip(x) or IsZeroStrip(x)) +# ); +# fi; +# end +# ); +# +# InstallMethod( +# IsStripNthDeloopingMapSplit, +# "for a strip-rep and a nonnegative integer", +# [IsStripRep, IsInt], +# function(strip, N) +# local +# k, # Integer variable +# nth_syzygy, # th syzygy of , as a collected list +# test_module; # List variable, holding a module to be tested +# +# if N < 0 then +# Error("The second argument, ", N, ", cannot be negative!"); +# +# elif IsVirtualStripRep(strip) then +# Error("Virtual strips cannot be delooped!"); +# +# elif IsZeroStrip(strip) then +# return true; +# +# else +# nth_syzygy := +# WithoutProjectiveStrips(CollectedNthSyzygyOfStrip(strip, N)); +# +# test_module := nth_syzygy; +# test_module := TrOfStrip(test_module); +# test_module := CollectedNthSyzygyOfStrip(test_module, N + 1); +# test_module := TrOfStrip(test_module); +# test_module := CollectedNthSyzygyOfStrip(test_module, N + 1); +# test_module := WithoutProjectiveStrips(test_module); +# +# return IsStripDirectSummand(nth_syzygy, test_module); +# fi; +# end +# ); +# +# InstallMethod( +# DeloopingLevelOfStripIfAtMostN, +# "for a strip-rep and a nonnegative integer", +# [IsStripRep, IsInt], +# function(strip, N) +# local +# k; # Integer variable +# +# if N < 0 then +# Error("The second argument, ", N, ", should be nonnegative!"); +# +# elif IsVirtualStripRep(strip) then +# Error("Virtual strips cannot be delooped!"); +# +# elif IsZeroStrip(strip) then +# return 0; +# +# else +# for k in [0 .. N] do +# # Case k=0 +# if k = 0 and IsStripNthDeloopingMapSplit(strip, k) then +# return k; +# +# # Case k>0 +# elif IsStripNthDeloopingMapSplit(strip, k) and +# (not IsStripNthDeloopingMapSplit(strip, k-1)) then +# return k; +# fi; +# od; +# +# return fail; +# fi; +# end +# ); +# +# InstallMethod( +# DeloopingLevelOfSBAlgIfAtMostN, +# "for a special biserial algebra and a nonnegative integer", +# [IsSpecialBiserialAlgebra, IsInt], +# function(sba, N) +# local +# deloopings, # Delooping levels of simples in +# simples; # Simple strips of +# +# simples := SimpleStripsOfSBAlg(sba); +# deloopings := List( +# simples, +# x -> DeloopingLevelOfStripIfAtMostN(x, N) +# ); +# +# if fail in deloopings then +# return fail; +# +# else +# return Maximum(deloopings); +# fi; +# end +# ); +# +# RedispatchOnCondition( +# DeloopingLevelOfSBAlgIfAtMostN, +# "to ensure a check whether the quiver algebra is special biserial", +# true, +# [IsQuiverAlgebra, IsInt], +# [IsSpecialBiserialAlgebra,], +# 0 +# ); +# +# InstallMethod( +# IsTorsionlessStrip, +# "for a strip-rep", +# [IsStripRep], +# function(strip) +# local +# del0; # Defining SB algebra of +# +# if HasIsTorsionlessStrip(strip) then +# return IsTorsionlessStrip(strip); +# +# else +# del0 := DeloopingLevelOfStripIfAtMostN(strip, 0); +# +# return del0 = 0; +# fi; +# end +# ); diff --git a/lib/util.gd b/lib/util.gd index 3bbb5a5..6ffa94f 100644 --- a/lib/util.gd +++ b/lib/util.gd @@ -249,6 +249,8 @@ DeclareOperation("CollectedFiltered", [IsList, IsFunction]); DeclareOperation("PairingsOfList", [IsList]); +DeclareOperation("RotationOfList", [IsList, IsInt]); + ## For QPA ## <#GAPDoc Label="DocStringMethodForPaths"> diff --git a/lib/util.gi b/lib/util.gi index 653fca4..171824f 100644 --- a/lib/util.gi +++ b/lib/util.gi @@ -458,6 +458,19 @@ InstallMethod( end ); +InstallMethod( + RotationOfList, + "for a list and an integer", + [IsList, IsInt], + function(list, shift) + local + l, s; + l := Length(list); + s := shift mod l; + return Concatenation(list{[s+1 .. l]}, list{[1 .. s]}); + end +); + # Useful functions for QPA InstallMethod( diff --git a/read.g b/read.g index 65c801c..ff661a8 100644 --- a/read.g +++ b/read.g @@ -1,4 +1,5 @@ ReadPackage("sbstrips", "lib/1reg.gi"); +ReadPackage("sbstrips", "lib/belts.gi"); ReadPackage("sbstrips", "lib/genalg.gi"); ReadPackage("sbstrips", "lib/info.gi"); ReadPackage("sbstrips", "lib/makedoc.gi");