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