Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  groebnerordering.gi   Sprache: unbekannt

 
# GAP Implementation
# This file was generated from 
# $Id: ordering.gi,v 1.2 2012/02/27 12:26:34 sunnyquiver Exp $

InstallMethod(LessThanByOrdering,
 "for orderings and two paths",
 true,
 [IsQuiverOrdering, IsPath, IsPath], 0,
 function(O,a,b)
     return ComparisonFunction(O)(a,b) < 0;
 end
);

InstallMethod(IsWellOrdering,
 "for an ordering",
 true,
 [IsQuiverOrdering],0,
 function(O)
     return IsWellSubset(O,GeneratorsOfQuiver(O!.quiver));
  end
);


InstallMethod(IsWellReversedOrdering,
 "for an ordering",
 true,
 [IsQuiverOrdering],0,
 function(O)
     return IsWellReversedSubset(O,GeneratorsOfQuiver(O!.quiver));
  end
);


InstallMethod(IsTotalOrdering,
 "for an ordering",
 true,
 [IsQuiverOrdering],0,
 function(O)
     return IsTotalSubset(O,GeneratorsOfQuiver(O!.quiver));
  end
);


InstallMethod(IsAdmissibleOrdering,
 "for an ordering",
 true,
 [IsQuiverOrdering],0,
 function(O)
     #Check IsTotalOrdering() first, because it is often faster
     return IsTotalOrdering(O) and IsWellOrdering(O);
  end
);


DeclareGlobalFunction("CheckQuiverSubsetForCycles");

InstallGlobalFunction(CheckQuiverSubsetForCycles,
 function(Q,L)
     local h,n,a,b,i,r,visit;

     #Possibly a big shortcut
     if HasIsAcyclicQuiver(Q) and IsAcyclicQuiver(Q) then
         return true;
     fi;

     #Identify every arrow in the list, as well as every vertex we
     #can start from
     h:=[];
     for a in L do
         if IsArrow(a) then
             i:=ExtRepOfObj(a)[1];
             h[i]:=a;
             b:=SourceOfPath(a);
             h[ExtRepOfObj(b)[1]]:=b;
         fi;
     od;

     #If we have some arrows
     if Length(h)>0 then
         n:=[];
         i:=1;
         #Visit a vertex
         #v is the vertex
         #j is 3 * the generator position of the vertex
         #c is the label of the source vertex for the last arrow which was in the subset
         #n[j]   = the depth-first search label of the vertex
         #n[j-1] = true: the vertex was visited successfully; false: vertex is being visited
         #n[j-2] = index of the highest vertex reachable from cycles containing this vertex
         visit:=function(v,j,c)
             local adj,k,t,p,m;
             n[j]:=i;      #Label the vertex
             n[j-1]:=true; #Mark us in the process of being visited
             i:=i+1;
             #Check all the arrows 
             adj:=OutgoingArrowsOfVertex(v);
             for p in adj do
                 t:=TargetOfPath(p);
                 k:=ExtRepOfObj(t)[1]*3;
                 #Arrow is inside our subset
                 if IsBound(h[ExtRepOfObj(p)[1]]) then
                     #Arrow points to an unvisited vertex
                     if not IsBound(n[k]) then
                         if not visit(t,k,n[j]) then
                             return false;
                         fi;
                     #The vertex can reach us
                     #Or the vertex is part of a cycle that reaches us
                     elif n[k-1] or (IsBound(n[k-2]) and n[n[k-2]-1]) then
                         return false;
                     fi;
                 #Arrow is outside our subset
                 else
                     #Arrow points to an unvisited vertex
                     if not IsBound(n[k]) then
                         if not visit(t,k,c) then
                             return false;
                         #If it's part of a cycle that reaches us, mark us
                         elif IsBound(n[k-2]) and n[n[k-2]-1] and
                          ((not IsBound(n[j-2])) or n[n[j-2]]>n[n[k-2]]) then
                             n[j-2]:=n[k-2];
                         fi;
                     #The vertex can reach us
                     elif n[k-1] or (IsBound(n[k-2]) and n[n[k-2]-1]) then
                         if IsBound(n[k-2]) then
                             m:=n[k-2];
                         else
                             m:=k;
                         fi;
                         #The cycle contains something from our set
                         if n[m]<=c then
                             return false;
                         #Mark us as belonging to the cycle
                         elif (not IsBound(n[j-2])) or n[n[j-2]]>n[m] then
                             n[j-2]:=m;
                         fi;
                     fi;
                 fi;
             od;
             n[j-1]:=false;
             return true;
         end;
         for b in h do
             if not IsQuiverVertex(b) then
                 break;
             fi;
             r:=ExtRepOfObj(b)[1]*3;
             if not IsBound(n[r]) then
                 if not visit(b,r,0) then
                     return false;
                 fi;
             fi;
         od;
     fi;
     return true;
  end
);


InstallGlobalFunction(LengthOrdering,function(arg)
    local O,fam;

    if not ((Length(arg) = 1 or (Length(arg) = 2 and IsQuiverOrdering(arg[2])))
        and IsQuiver(arg[1])) then
        Error("usage: LengthOrdering(Q) or LengthOrdering(Q,O)",
       " where Q is a quiver and O is an ordering");
    fi;

    fam := NewFamily("FamilyLengthOrdering", IsLengthOrdering);
    O := Objectify(NewType(fam,IsLengthOrdering and IsAttributeStoringRep),
                   rec() );

    SetOrderingName(O, "length");

    # Set quiver in record:
    O!.quiver:=arg[1];

    # We already know that the argument is an ordering
    if Length(arg)=2 then
        SetNextOrdering(O, arg[2]);
        if HasLexicographicTable(arg[2]) then
            SetLexicographicTable(O,LexicographicTable(arg[2]));
            O!.lex:=arg[2]!.lex;
        fi;
    fi;

    SetComparisonFunction(O,function(a,b)
      local lena, lenb;

      if HasWalkOfPath(a) then
          lena := Length(WalkOfPath(a));
      else
          lena := 0;
      fi;

      if HasWalkOfPath(b) then
          lenb := Length(WalkOfPath(b));
      else
          lenb := 0;
      fi;
#Print("lena: ",lena,", lenb: ",lenb,"\n");
      if lena < lenb then
          return -1;
      elif lena = lenb then
          if HasNextOrdering(O) then
              return ComparisonFunction(NextOrdering(O))(a,b);
          else
              return 0;
          fi;
      else
          return 1;
      fi;

      end
    );

    return O;
  end
);


InstallMethod(IsWellReversedOrdering,
 "for a length ordering",
 true,
 [IsLengthOrdering],0,
 function(O)
     return IsFinite(O!.quiver);
  end
);


InstallMethod(IsTotalOrdering,
 "for a length ordering",
 true,
 [IsLengthOrdering],0,
 function(O)
     if Length(VerticesOfQuiver(O!.quiver))<1 then
         return true;
     elif HasNextOrdering(O) then
         return IsTotalOrdering(NextOrdering(O));
     else
         return false;
     fi;
  end
);


InstallMethod(IsWellSubset,
 "for a length ordering and a list of generators",
 true,
 [IsLengthOrdering,IsHomogeneousList],0,
 function(O,L)
     return true;
  end
);


InstallMethod(IsWellReversedSubset,
 "for a length ordering",
 true,
 [IsLengthOrdering,IsHomogeneousList],0,
 function(O,L)
     return CheckQuiverSubsetForCycles(O!.quiver,L);
  end
);


InstallMethod(IsTotalSubset,
 "for a length ordering and a list of generators",
 true,
 [IsLengthOrdering,IsHomogeneousList],0,
 function(O,L)
     if Length(L)<1 then
         return true;
     elif HasNextOrdering(O) then
         return IsTotalSubset(NextOrdering(O),L);
     else
         return false;
     fi;
  end
);


InstallMethod(IsWellOrdering,
 "for a lexicographic ordering and a quiver",
 true,
 [IsLexicographicOrdering],0,
 function(O)
     local i,l,a,v,m,ret;
     if IsFinite(O!.quiver) then
         return true;
     else
         l:=LexicographicTable(O);
         #This must be an arrow, or we wouldn't be infinite
         a:=l[Length(l)];
         v:=SourceOfPath(a);
         i:=ExtRepOfObj(v)[1];
         if i<>ExtRepOfObj(TargetOfPath(a))[1] or InDegreeOfVertex(v)>1 then
             return false;
         fi;
         m:=AdjacencyMatrixOfQuiver(O!.quiver);
         m[i][i]:=0;
         ret:=IsFinite(Quiver(m));
         m[i][i]:=1;
         return ret;
     fi;
  end
);


InstallMethod(IsWellOrdering,
 "for a lexicographic ordering and a quiver",
 true,
 [IsLexicographicOrdering],0,
 function(O)
     local i,l,a,v,m,ret;
     if IsFinite(O!.quiver) then
         return true;
     else
         l:=LexicographicTable(O);
         #This must be an arrow, or we wouldn't be infinite
         a:=l[Length(VerticesOfQuiver(O!.quiver))+1];
         v:=SourceOfPath(a);
         i:=ExtRepOfObj(v)[1];
         if i<>ExtRepOfObj(TargetOfPath(a))[1] or InDegreeOfVertex(v)>1 then
             return false;
         fi;
         m:=AdjacencyMatrixOfQuiver(O!.quiver);
         m[i][i]:=0;
         ret:=IsFinite(Quiver(m));
         m[i][i]:=1;
         return ret;
     fi;
  end
);


InstallMethod(IsWellSubset,
 "for a lexicographic ordering and a list of generators",
 true,
 [IsLexicographicOrdering,IsHomogeneousList],0,
 function(O,L)
     local h,n,a,b,i,r,lgst,lgst_lex,visit;
     #Possibly a big shortcut
     if HasIsAcyclicQuiver(O!.quiver) and IsAcyclicQuiver(O!.quiver) then
         return true;
     fi;
     #Identify every arrow in the list, as well as every vertex we
     #can start from, and the largest arrow
     h:=[];
     for a in L do
         if IsArrow(a) then
             i:=ExtRepOfObj(a)[1];
             h[i]:=a;
             if not IsBound(lgst) or
              lgst_lex<O!.lex[i] then
                 lgst:=a;
                 lgst_lex:=O!.lex[i];
             fi;
             b:=SourceOfPath(a);
             h[ExtRepOfObj(b)[1]]:=b;
         fi;
     od;
     #If we have some arrows
     if IsBound(lgst) then
         #The largest arrow may appear in cycles
         Unbind(h[ExtRepOfObj(lgst)[1]]);
         n:=[];
         i:=1;
         visit:=#Visit a vertex
                #v is the vertex
                #j is 3 * the generator position of the vertex
                #p is the 3 * the generator position of the vertex's parent, or -1
                #c is the label of the source vertex for the last arrow which was a parent
                #n[j]   = the depth-first search label of the vertex
                #n[j-1] = -1: being visited, -2: and has cycle, 1: done being visited, 2: and has cycle
                #n[j-2] = index of the highest vertex reachable from cycles containing this vertex
                function(v,j,c)
                    local adj,k,t,p,m;
                    n[j]:=i;    #Label the vertex
                    n[j-1]:=-1; #Mark us as being visited
                    i:=i+1;
                    #Check all the arrows 
                    adj:=OutgoingArrowsOfVertex(v);
                    for p in adj do
                        t:=TargetOfPath(p);
                        k:=ExtRepOfObj(t)[1]*3;
                        #Arrow is inside our subset, and not the largest
                        if IsBound(h[ExtRepOfObj(p)[1]]) then
                            #Arrow points to an unvisited vertex
                            if not IsBound(n[k]) then
                                if not visit(t,k,n[j]) then
                                    return false;
                                fi;
                            #Arrow points to the largest arrow and largest arrow belongs to a cycle
                            #Or the vertex can reach us
                            #Or the vertex is part of a cycle that reaches us
                            elif (n[k]=1 and n[k-1]=2) or n[k-1]<0 or
                             (IsBound(n[k-2]) and n[n[k-2]-1]<0) then
                                return false;
                            fi;
                        #Arrow is outside our subset, or the largest
                        else
                            #Arrow points to an unvisited vertex
                            if not IsBound(n[k]) then
                                if p=lgst then
                                    if not visit(t,k,-1) then
                                        return false;
                                    fi;
                                else
                                    if not visit(t,k,c) then
                                        return false;
                                    fi;
                                fi;
                                if IsBound(n[k-2]) and (n[n[k-2]-1]<0) and
                                 ((not IsBound(n[j-2])) or n[n[j-2]]>n[n[k-2]]) then
                                    n[j-2]:=n[k-2];
                                fi;
                            #The vertex can possibly reach us
                            elif n[k-1]<0 or
                             (IsBound(n[k-2]) and n[n[k-2]-1]<0) then
                                if IsBound(n[k-2]) then
                                    m:=n[k-2];
                                else
                                    m:=k;
                                fi;
                                #The cycle contains something from our set
                                if n[m]<=c then
                                    return false;
                                #The cycle is outside our set
                                elif (not IsBound(n[j-2])) or n[n[j-2]]>n[m] then
                                    n[j-2]:=m;
                                fi;
                                #The cycle descends directly from the largest arrow
                                if c<0 or p=lgst then
                                    n[m-1]:=-2;
                                fi;
                            fi;
                        fi;
                    od;
                    n[j-1]:=-n[j-1]; #Mark us as done being visited
                    return true;
                end;
         #Visit source of largest arrow first
         b:=SourceOfPath(lgst);
         r:=ExtRepOfObj(b)[1]*3;
         if not visit(b,r,0) then
             return false;
         fi;
         #Visit any unconnected components reachable from our subset
         for b in h do
             if not IsQuiverVertex(b) then
                 break;
             fi;
             r:=ExtRepOfObj(b)[1]*3;
             if not IsBound(n[r]) then
                 if not visit(b,r,0) then
                     return false;
                 fi;
             fi;
         od;
     fi;
     return true;
  end
);


InstallMethod(IsWellReversedSubset,
 "for a lexicographic ordering and a list of generators",
 true,
 [IsLexicographicOrdering,IsHomogeneousList],0,
 function(O,L)
     local h,n,a,b,i,r,lgst,lgst_lex,visit;
     #Possibly a big shortcut
     if HasIsAcyclicQuiver(O!.quiver) and IsAcyclicQuiver(O!.quiver) then
         return true;
     fi;
     #Identify every arrow in the list, as well as every vertex we
     #can start from, and the largest arrow
     h:=[];
     for a in L do
         if IsArrow(a) then
             i:=ExtRepOfObj(a)[1];
             h[i]:=a;
             if not IsBound(lgst) or
              lgst_lex>O!.lex[i] then
                 lgst:=a;
                 lgst_lex:=O!.lex[i];
             fi;
             b:=SourceOfPath(a);
             h[ExtRepOfObj(b)[1]]:=b;
         fi;
     od;
     #If we have some arrows
     if IsBound(lgst) then
         #The largest arrow may appear in cycles
         Unbind(h[ExtRepOfObj(lgst)[1]]);
         n:=[];
         i:=1;
         visit:=#Visit a vertex
                #v is the vertex
                #j is 3 * the generator position of the vertex
                #p is the 3 * the generator position of the vertex's parent, or -1
                #c is the label of the source vertex for the last arrow which was a parent
                #n[j]   = the depth-first search label of the vertex
                #n[j-1] = -1: being visited, -2: and has cycle, 1: done being visited, 2: and has cycle
                #n[j-2] = index of the highest vertex reachable from cycles containing this vertex
                function(v,j,c)
                    local adj,k,t,p,m;
                    n[j]:=i;    #Label the vertex
                    n[j-1]:=-1; #Mark us as being visited
                    i:=i+1;
                    #Check all the arrows 
                    adj:=OutgoingArrowsOfVertex(v);
                    for p in adj do
                        t:=TargetOfPath(p);
                        k:=ExtRepOfObj(t)[1]*3;
                        #Arrow is inside our subset, and not the largest
                        if IsBound(h[ExtRepOfObj(p)[1]]) then
                            #Arrow points to an unvisited vertex
                            if not IsBound(n[k]) then
                                if not visit(t,k,n[j]) then
                                    return false;
                                fi;
                            #Arrow points to the largest arrow and largest arrow belongs to a cycle
                            #Or the vertex can reach us
                            #Or the vertex is part of a cycle that reaches us
                            elif (n[k]=1 and n[k-1]=2) or n[k-1]<0 or
                             (IsBound(n[k-2]) and n[n[k-2]-1]<0) then
                                return false;
                            fi;
                        #Arrow is outside our subset, or the largest
                        else
                            #Arrow points to an unvisited vertex
                            if not IsBound(n[k]) then
                                if p=lgst then
                                    if not visit(t,k,-1) then
                                        return false;
                                    fi;
                                else
                                    if not visit(t,k,c) then
                                        return false;
                                    fi;
                                fi;
                                if IsBound(n[k-2]) and (n[n[k-2]-1]<0) and
                                 ((not IsBound(n[j-2])) or n[n[j-2]]>n[n[k-2]]) then
                                    n[j-2]:=n[k-2];
                                fi;
                            #The vertex can possibly reach us
                            elif n[k-1]<0 or
                             (IsBound(n[k-2]) and n[n[k-2]-1]<0) then
                                if IsBound(n[k-2]) then
                                    m:=n[k-2];
                                else
                                    m:=k;
                                fi;
                                #The cycle contains something from our set
                                if n[m]<=c then
                                    return false;
                                #The cycle is outside our set
                                elif (not IsBound(n[j-2])) or n[n[j-2]]>n[m] then
                                    n[j-2]:=m;
                                fi;
                                #The cycle descends directly from the largest arrow
                                if c<0 or p=lgst then
                                    n[m-1]:=-2;
                                fi;
                            fi;
                        fi;
                    od;
                    n[j-1]:=-n[j-1]; #Mark us as done being visited
                    return true;
                end;
         #Visit source of largest arrow first
         b:=SourceOfPath(lgst);
         r:=ExtRepOfObj(b)[1]*3;
         if not visit(b,r,0) then
             return false;
         fi;
         #Visit any unconnected components reachable from our subset
         for b in h do
             if not IsQuiverVertex(b) then
                 break;
             fi;
             r:=ExtRepOfObj(b)[1]*3;
             if not IsBound(n[r]) then
                 if not visit(b,r,0) then
                     return false;
                 fi;
             fi;
         od;
     fi;
     return true;
  end
);


InstallMethod(IsTotalSubset,
 "for a lexicographic ordering and a list of generators",
 true,
 [IsLexicographicOrdering,IsHomogeneousList],0,
 function(O,L)
     return true;
 end);
InstallGlobalFunction(LeftLexicographicOrdering,function(arg)
    local fam,O,Q,lex,i,j,rep,gens,oldgens;

    if not (Length(arg)=1 or (Length(arg)=2 and IsHomogeneousList(arg[2])) and IsQuiver(arg[1])) then
        Error("usage: LeftLexicographicOrdering(Q,L), Q must be q quiver, L is an optional list of gens");
    fi;

    fam:=NewFamily("FamilyLeftLexicographicOrderings",
                   IsLeftLexicographicOrdering);
    O:=Objectify(NewType(fam,IsLeftLexicographicOrdering and
                             IsAttributeStoringRep),rec());
    Q:=arg[1];
    O!.quiver:=Q;

    oldgens:=GeneratorsOfQuiver(Q);
     lex:=[];
     gens:=[];
     j:=1;
     if Length(arg)>=2 then
         for i in arg[2] do
             if IsQuiverVertex(i) then
                 rep:=ExtRepOfObj(i)[1];
                 if not IsBound(lex[rep]) then
                     lex[rep]:=j;
                     j:=j+1;
                     Add(gens,i);
                 fi;
             fi;
         od;
     fi;
     if Length(VerticesOfQuiver(Q))>=j then
         for i in oldgens do
             if not IsQuiverVertex(i) then
                 break;
             fi;
             rep:=ExtRepOfObj(i)[1];
             if not IsBound(lex[rep]) then
                 lex[rep]:=j;
                 j:=j+1;
                 Add(gens,i);
             fi;
         od;
     fi;
     if Length(arg)>=2 then
         for i in arg[2] do
             if IsArrow(i) then
                 rep:=ExtRepOfObj(i)[1];
                 if not IsBound(lex[rep]) then
                     lex[rep]:=j;
                     j:=j+1;
                     Add(gens,i);
                fi;
             fi;
         od;
     fi;
     if Length(oldgens)>=j then
         for i in [Length(VerticesOfQuiver(Q))+1..Length(oldgens)] do
             rep:=ExtRepOfObj(oldgens[i])[1];
             if not IsBound(lex[rep]) then
                 lex[rep]:=j;
                 j:=j+1;
                 Add(gens,oldgens[i]);
             fi;
         od;
     fi;

    SetOrderingName(O,"left lexicographic");
    SetLexicographicTable(O,gens);
    O!.lex:=lex;
    SetComparisonFunction(O,function(a,b)
        local m,n,l,r,s,j;
        if IsZeroPath(a) then
            if IsZeroPath(b) then
                return 0;
            else
                return -1;
            fi;
        elif IsZeroPath(b) then
            return 1;
        fi;
        r:=ExtRepOfObj(a); # remember, these are paths
        s:=ExtRepOfObj(b);
        m:=Length(r);
        n:=Length(s);
        l:=Minimum(m, n);
        for j in [1..l] do
            if lex[r[j]]<>lex[s[j]] then
                if lex[r[j]]<lex[s[j]] then
                    return -1;
                else
                    return 1;
                fi;
            fi;
        od;
        if m<n then
            return -1;
        elif m=n then
            if HasNextOrdering(O) then
                return ComparisonFunction(NextOrdering(O))(a,b);
            else
                return 0;
            fi;
        else
            return 1;
        fi;
    end);

    return O;

  end
);


InstallGlobalFunction(RightLexicographicOrdering,function(arg)
    local fam,O,Q,lex,i,j,rep,gens,oldgens;

    if not (Length(arg)=1 or (Length(arg)=2 and IsHomogeneousList(arg[2])) and IsQuiver(arg[1])) then
        Error("usage: RightLexicographicOrdering(Q,L), Q must be q quiver, L is an optional list of gens");
    fi;

    fam:=NewFamily("FamilyRightLexicographicOrderings",
                   IsRightLexicographicOrdering);
    O:=Objectify(NewType(fam,IsRightLexicographicOrdering and
                             IsAttributeStoringRep),rec());
    Q:=arg[1];
    O!.quiver:=Q;

    oldgens:=GeneratorsOfQuiver(Q);
     lex:=[];
     gens:=[];
     j:=1;
     if Length(arg)>=2 then
         for i in arg[2] do
             if IsQuiverVertex(i) then
                 rep:=ExtRepOfObj(i)[1];
                 if not IsBound(lex[rep]) then
                     lex[rep]:=j;
                     j:=j+1;
                     Add(gens,i);
                 fi;
             fi;
         od;
     fi;
     if Length(VerticesOfQuiver(Q))>=j then
         for i in oldgens do
             if not IsQuiverVertex(i) then
                 break;
             fi;
             rep:=ExtRepOfObj(i)[1];
             if not IsBound(lex[rep]) then
                 lex[rep]:=j;
                 j:=j+1;
                 Add(gens,i);
             fi;
         od;
     fi;
     if Length(arg)>=2 then
         for i in arg[2] do
             if IsArrow(i) then
                 rep:=ExtRepOfObj(i)[1];
                 if not IsBound(lex[rep]) then
                     lex[rep]:=j;
                     j:=j+1;
                     Add(gens,i);
                fi;
             fi;
         od;
     fi;
     if Length(oldgens)>=j then
         for i in [Length(VerticesOfQuiver(Q))+1..Length(oldgens)] do
             rep:=ExtRepOfObj(oldgens[i])[1];
             if not IsBound(lex[rep]) then
                 lex[rep]:=j;
                 j:=j+1;
                 Add(gens,oldgens[i]);
             fi;
         od;
     fi;

    SetOrderingName(O,"right lexicographic");
    SetLexicographicTable(O,gens);
    O!.lex:=lex;
    SetComparisonFunction(O,function(a,b)
        local m,n,l,r,s,j;

        if IsZeroPath(a) then
            if IsZeroPath(b) then
                return 0;
            else
                return -1;
            fi;
        elif IsZeroPath(b) then
            return 1;
        fi;
        r:=ExtRepOfObj(a); # remember, these are paths
        s:=ExtRepOfObj(b); 
        m:=Length(r);
        n:=Length(s);
        l:=Minimum(m, n);
        for j in [0..l-1] do
            if lex[r[m-j]]<>lex[s[n-j]] then
                if lex[r[m-j]]<lex[s[n-j]] then
                    return -1;
                else
                    return 1;
                fi;
            fi;
        od;
        if m<n then
            return -1;
        elif m=n then
            if HasNextOrdering(O) then
                return ComparisonFunction(NextOrdering(O))(a,b);
            else
                return 0;
            fi;
        else
            return 1;
        fi;
    end);
    SetIsTotal(O,true);

    return O;

  end
);


InstallGlobalFunction(ReverseOrdering,function(arg)
    local fam,O;
    if not (Length(arg)=2 and IsQuiverOrdering(arg[2]) and IsQuiver(arg[1])) then
        Error("Usage: ReverseOrdering(Q,O) where Q is a quiver and O is an ordering");
    fi;

    fam:=NewFamily("FamilyReverseOrderings",IsReverseOrdering);
    O:=Objectify(NewType(fam,IsReverseOrdering and IsAttributeStoringRep),
                 rec());

    O!.quiver:=arg[1];
    SetOrderingName(O,"reverse");
    SetNextOrdering(O,arg[2]);
    if HasLexicographicTable(arg[2]) then
        SetLexicographicTable(O,LexicographicTable(arg[2]));
        O!.lex:=arg[2]!.lex;
    fi;

    SetComparisonFunction(O,function(a,b)
        local ret;
        if IsZeroPath(a) then
            if IsZeroPath(b) then
                return 0;
            else
                return ComparisonFunction(NextOrdering(O))(a,b);
            fi;
        elif IsZeroPath(b) then
            return ComparisonFunction(NextOrdering(O))(a,b);
        fi;
        if IsQuiverVertex(a) then
            if not IsQuiverVertex(b) then
                return ComparisonFunction(NextOrdering(O))(a,b);
            fi;
        elif IsQuiverVertex(b) then
            return ComparisonFunction(NextOrdering(O))(a,b);
        fi;
        return -ComparisonFunction(NextOrdering(O))(a,b);
    end);

    return O;
  end
);


InstallMethod(IsWellOrdering,
 "for a reverse ordering and a quiver",
 true,
 [IsReverseOrdering],0,
 function(O)
     return IsWellReversedOrdering(NextOrdering(O));
  end
);


InstallMethod(IsWellReversedOrdering,
 "for a reverse ordering and a quiver",
 true,
 [IsReverseOrdering],0,
 function(O)
     return IsWellOrdering(NextOrdering(O));
  end
);


InstallMethod(IsTotalOrdering,
 "for a reverse ordering",
 true,
 [IsReverseOrdering],0,
 function(O)
     return IsTotalOrdering(NextOrdering(O));
  end
);


InstallMethod(IsWellSubset,
 "for a reverse ordering and a list of generators",
 true,
 [IsReverseOrdering,IsHomogeneousList],0,
 function(O,L)
     return IsWellReversedSubset(NextOrdering(O),L);
  end
);


InstallMethod(IsWellReversedSubset,
 "for a reverse ordering and a list of generators",
 true,
 [IsReverseOrdering,IsHomogeneousList],0,
 function(O,L)
     return IsWellSubset(NextOrdering(O),L);
  end
);


InstallMethod(IsTotalSubset,
 "for a reverse ordering and a list of generators",
 true,
 [IsReverseOrdering,IsHomogeneousList],0,
 function(O,L)
     return IsTotalSubset(NextOrdering(O),L);
  end
);


InstallMethod(IsWellReversedOrdering,
 "for a vector ordering",
 true,
 [IsVectorOrdering],0,
 function(O)
     return IsFinite(O!.quiver);
  end
);


InstallMethod(IsTotalOrdering,
 "for a vector ordering",
 true,
 [IsVectorOrdering],0,
 function(O)
     if Length(VerticesOfQuiver(O!.quiver))<1 then
         return true;
     elif HasNextOrdering(O) then
         return IsTotalOrdering(NextOrdering(O));
     else
         return false;
     fi;
  end
);


InstallMethod(IsWellSubset,
 "for a vector ordering and a list of generators",
 true,
 [IsVectorOrdering,IsHomogeneousList],0,
 function(O,L)
     return true;
  end
);


InstallMethod(IsWellReversedSubset,
 "for a vector ordering and a list of generators",
 true,
 [IsVectorOrdering,IsHomogeneousList],0,
 function(O,L)
     return CheckQuiverSubsetForCycles(O!.quiver,L);
  end
);


InstallMethod(IsTotalSubset,
 "for a vector ordering and a list of generators",
 true,
 [IsVectorOrdering,IsHomogeneousList],0,
 function(O,L)
     if Length(L)<1 then
         return true;
     elif HasNextOrdering(O) then
         return IsTotalSubset(NextOrdering(O),L);
     else
         return false;
     fi;
  end
);


InstallGlobalFunction(LeftVectorOrdering,function(arg)
    local fam,O,Q,lex,i,j,rep,gens,oldgens;
    if not (Length(arg)=1 or (Length(arg)=2 or (Length(arg)=3 and
     IsQuiverOrdering(arg[3])) and IsHomogeneousList(arg[2])) and IsQuiver(arg[1]))
     then
        Error("usage: LeftVectorOrdering(Q,L,O), the first arg must be a quiver, the second a list of generators, and the optional third argument an ordering");
    fi;
    fam:=NewFamily("FamilyLeftVectorOrderings",IsLeftVectorOrdering);
    O:=Objectify(NewType(fam,IsLeftVectorOrdering and IsAttributeStoringRep),
                 rec());
    Q:=arg[1];
    O!.quiver:=Q;

    if Length(arg)>=3 and HasLexicographicTable(arg[3]) then
        oldgens:=LexicographicTable(arg[3]);
    else
        oldgens:=GeneratorsOfQuiver(Q);
    fi;
     lex:=[];
     gens:=[];
     j:=1;
     if Length(arg)>=2 then
         for i in arg[2] do
             if IsQuiverVertex(i) then
                 rep:=ExtRepOfObj(i)[1];
                 if not IsBound(lex[rep]) then
                     lex[rep]:=j;
                     j:=j+1;
                     Add(gens,i);
                 fi;
             fi;
         od;
     fi;
     if Length(VerticesOfQuiver(Q))>=j then
         for i in oldgens do
             if not IsQuiverVertex(i) then
                 break;
             fi;
             rep:=ExtRepOfObj(i)[1];
             if not IsBound(lex[rep]) then
                 lex[rep]:=j;
                 j:=j+1;
                 Add(gens,i);
             fi;
         od;
     fi;
     if Length(arg)>=2 then
         for i in arg[2] do
             if IsArrow(i) then
                 rep:=ExtRepOfObj(i)[1];
                 if not IsBound(lex[rep]) then
                     lex[rep]:=j;
                     j:=j+1;
                     Add(gens,i);
                fi;
             fi;
         od;
     fi;
     if Length(oldgens)>=j then
         for i in [Length(VerticesOfQuiver(Q))+1..Length(oldgens)] do
             rep:=ExtRepOfObj(oldgens[i])[1];
             if not IsBound(lex[rep]) then
                 lex[rep]:=j;
                 j:=j+1;
                 Add(gens,oldgens[i]);
             fi;
         od;
     fi;

    if Length(arg)>=3 then
        SetNextOrdering(O,arg[3]);
        if HasLexicographicTable(arg[3]) then
            if LexicographicTable(arg[3])<>gens then
                Error("Must use same lexicographic table");
            fi;
            O!.lex:=arg[3]!.lex;
            SetLexicographicTable(O,LexicographicTable(arg[3]));
        else
            O!.lex:=lex;
            SetLexicographicTable(O,gens);
        fi;
    else
        O!.lex:=lex;
        SetLexicographicTable(O,gens);
    fi;
    SetOrderingName(O,"left vector");
    SetComparisonFunction(O,function(a,b)
        local v,w,r,s,i,j,o;
        if IsQuiverVertex(a) or IsZeroPath(a) then
            if IsQuiverVertex(b) or IsZeroPath(b) then
                if HasNextOrdering(O) then
                    return ComparisonFunction(NextOrdering(O))(a,b);
                else
                    return 0;
                fi;
            else
                return -1;
            fi;
        elif IsQuiverVertex(b) or IsZeroPath(b) then
            return 1;
        fi;
        # At this point, both items are paths
        o:=Length(VerticesOfQuiver(O!.quiver));
        v:=ListWithIdenticalEntries(Length(gens)-o,0);
        r:=ExtRepOfObj(a);
        for i in [1..Length(r)] do
            j:=lex[r[i]]-o;
            v[j]:=v[j]+1;
        od;
        w:=ListWithIdenticalEntries(Length(gens)-o,0);
        s:=ExtRepOfObj(b);
        for i in [1..Length(s)] do
            j:=lex[s[i]]-o;
            w[j]:=w[j]+1;
        od;
        for i in [1..Length(v)] do
            if v[i]<w[i] then
                return -1;
            elif v[i]>w[i] then
                return 1;
            fi;
        od;
        if HasNextOrdering(O) then
            return ComparisonFunction(NextOrdering(O))(a,b);
        else
            return 0;
        fi;
    end);

    return O;

  end
);


InstallGlobalFunction(RightVectorOrdering,function(arg)
    local fam,O,Q,lex,i,j,rep,gens,oldgens;
    if not (Length(arg)=1 or (Length(arg)=2 or (Length(arg)=3 and
     IsQuiverOrdering(arg[3])) and IsHomogeneousList(arg[2])) and IsQuiver(arg[1]))
     then
        Error("usage: RightVectorOrdering(Q,L,O), the first arg must be a quiver, the second a list of generators, and the optional third argument an ordering");
    fi;
    fam:=NewFamily("FamilyRightVectorOrderings",IsRightVectorOrdering);
    O:=Objectify(NewType(fam,IsRightVectorOrdering and IsAttributeStoringRep),
                 rec());
    Q:=arg[1];
    O!.quiver:=Q;

    if Length(arg)>=3 and HasLexicographicTable(arg[3]) then
        oldgens:=LexicographicTable(arg[3]);
    else
        oldgens:=GeneratorsOfQuiver(Q);
    fi;
     lex:=[];
     gens:=[];
     j:=1;
     if Length(arg)>=2 then
         for i in arg[2] do
             if IsQuiverVertex(i) then
                 rep:=ExtRepOfObj(i)[1];
                 if not IsBound(lex[rep]) then
                     lex[rep]:=j;
                     j:=j+1;
                     Add(gens,i);
                 fi;
             fi;
         od;
     fi;
     if Length(VerticesOfQuiver(Q))>=j then
         for i in oldgens do
             if not IsQuiverVertex(i) then
                 break;
             fi;
             rep:=ExtRepOfObj(i)[1];
             if not IsBound(lex[rep]) then
                 lex[rep]:=j;
                 j:=j+1;
                 Add(gens,i);
             fi;
         od;
     fi;
     if Length(arg)>=2 then
         for i in arg[2] do
             if IsArrow(i) then
                 rep:=ExtRepOfObj(i)[1];
                 if not IsBound(lex[rep]) then
                     lex[rep]:=j;
                     j:=j+1;
                     Add(gens,i);
                fi;
             fi;
         od;
     fi;
     if Length(oldgens)>=j then
         for i in [Length(VerticesOfQuiver(Q))+1..Length(oldgens)] do
             rep:=ExtRepOfObj(oldgens[i])[1];
             if not IsBound(lex[rep]) then
                 lex[rep]:=j;
                 j:=j+1;
                 Add(gens,oldgens[i]);
             fi;
         od;
     fi;

    if Length(arg)>=3 then
        SetNextOrdering(O,arg[3]);
        if HasLexicographicTable(arg[3]) then
            if LexicographicTable(arg[3])<>gens then
                Error("Must use same lexicographic table");
            fi;
            O!.lex:=arg[3]!.lex;
            SetLexicographicTable(O,LexicographicTable(arg[3]));
        else
            O!.lex:=lex;
            SetLexicographicTable(O,gens);
        fi;
    else
        O!.lex:=lex;
        SetLexicographicTable(O,gens);
    fi;
    SetOrderingName(O,"right vector");
    SetComparisonFunction(O,function(a,b)
        local v,w,r,s,i,j,l,o;
        if IsQuiverVertex(a) or IsZeroPath(a) then
            if IsQuiverVertex(b) or IsZeroPath(b) then
                if HasNextOrdering(O) then
                    return ComparisonFunction(NextOrdering(O))(a,b);
                else
                    return 0;
                fi;
            else
                return -1;
            fi;
        elif IsQuiverVertex(b) or IsZeroPath(b) then
            return 1;
        fi;
        # At this point, both items are paths
        o:=Length(VerticesOfQuiver(O!.quiver));
        v:=ListWithIdenticalEntries(Length(gens)-o,0);
        r:=ExtRepOfObj(a);
        for i in [1..Length(r)] do
            j:=lex[r[i]]-o;
            v[j]:=v[j]+1;
        od;
        w:=ListWithIdenticalEntries(Length(gens)-o,0);
        s:=ExtRepOfObj(b);
        for i in [1..Length(s)] do
            j:=lex[s[i]]-o;
            w[j]:=w[j]+1;
        od;
        l:=Length(v);
        for i in [0..l-1] do
            if v[l-i]<w[l-i] then
                return -1;
            elif v[l-i]>w[l-i] then
                return 1;
            fi;
        od;
        if HasNextOrdering(O) then
            return ComparisonFunction(NextOrdering(O))(a,b);
        else
            return 0;
        fi;
    end);
    return O;
  end
);


InstallGlobalFunction(WeightOrdering,function(arg)
    local fam,O,Q,weight,i,j,rep,gens,p;
    if not (Length(arg)=1 or (Length(arg)=2 or (Length(arg)=3 and
     IsQuiverOrdering(arg[3])) and IsHomogeneousList(arg[2])) and IsQuiver(arg[1]))
     then
        Error("usage: WeightOrdering(Q,L,O), the first arg must be a quiver, the second a list of weights, one for each arrow in the quiver, and the optional third argument an ordering");
    fi;
    fam:=NewFamily("FamilyWeightOrderings",IsWeightOrdering);
    O:=Objectify(NewType(fam,IsWeightOrdering and IsAttributeStoringRep),
                 rec());
    Q:=arg[1];
    O!.quiver:=Q;
    weight:=ListWithIdenticalEntries(Length(ArrowsOfQuiver(Q)),0);
    if Length(arg)>=2 and Length(arg[2])>0 then
        for p in [1..Length(arg[2])] do
            weight[p]:=arg[2][p];
        od;
    fi;
    O!.weight:=weight;

    if Length(arg)>=3 then
        SetNextOrdering(O,arg[3]);
        if HasLexicographicTable(arg[3]) then
            SetLexicographicTable(O,LexicographicTable(arg[3]));
            O!.lex:=arg[3]!.lex;
        fi;
    fi;
    SetOrderingName(O,"weight");
    SetComparisonFunction(O,function(a,b)
        local v,w,r,s,i,o;
        if IsQuiverVertex(a) or IsZeroPath(a) then
            if IsQuiverVertex(b) or IsZeroPath(b) then
                if HasNextOrdering(O) then
                    return ComparisonFunction(NextOrdering(O))(a,b);
                else
                    return 0;
                fi;
            else
                return -1;
            fi;
        elif IsQuiverVertex(b) or IsZeroPath(b) then
            return 1;
        fi;
        # At this point, both items are paths
        o:=Length(VerticesOfQuiver(O!.quiver));
        r:=ExtRepOfObj(a);
        s:=ExtRepOfObj(b);
        w:=0;
        for i in r do
            w:=w+weight[i-o];
        od;
        v:=0;
        for i in s do
            v:=v+weight[i-o];
        od;
        if w=v then
            if HasNextOrdering(O) then
                return ComparisonFunction(NextOrdering(O))(a,b);
            else
                return 0;
            fi;
        else
            return w-v;
        fi;
    end);
    return O;
  end
);


InstallMethod(IsWellReversedOrdering,
 "for a weight ordering",
 true,
 [IsWeightOrdering],0,
 function(O)
     local z,o;
     if IsFinite(O!.quiver) then
         return true;
     fi;
     o:=Length(VerticesOfQuiver(O!.quiver));
     z:=Filtered(ArrowsOfQuiver(O!.quiver),function(a)
         return O!.weight[ExtRepOfObj(a)[1]-o]<>0;
     end);
     if Length(z)>0 and not CheckQuiverSubsetForCycles(O!.quiver,z) then
         return false;
     fi;
     return not HasNextOrdering(O) or
      IsWellReversedSubset(NextOrdering(O),z);
  end
);


InstallMethod(IsTotalOrdering,
 "for a weight ordering",
 true,
 [IsWeightOrdering],0,
 function(O)
     if Length(VerticesOfQuiver(O!.quiver))<1 then
         return true;
     elif HasNextOrdering(O) then
         return IsTotalOrdering(NextOrdering(O));
     else
         return true;
     fi;
  end
);


InstallMethod(IsWellSubset,
 "for a weight ordering and a list of generators",
 true,
 [IsWeightOrdering,IsHomogeneousList],0,
 function(O,L)
     return true;
  end
);


InstallMethod(IsWellReversedSubset,
 "for a weight ordering and a list of generators",
 true,
 [IsWeightOrdering,IsHomogeneousList],0,
 function(O,L)
     local z,o;
     if HasIsAcyclicQuiver(O!.quiver) and IsAcyclicQuiver(O!.quiver) then
         return true;
     fi;
     o:=Length(VerticesOfQuiver(O!.quiver));
     z:=Filtered(L,function(a)
         return IsArrow(a) and O!.weight[ExtRepOfObj(a)[1]-o]<>0;
     end);
     if Length(z)>0 and not CheckQuiverSubsetForCycles(O!.quiver,z) then
         return false;
     fi;
     z:=Filtered(L,function(a)
         return IsArrow(a) and O!.weight[ExtRepOfObj(a)[1]-o]=0;
     end);
     if Length(z)>0 and not CheckQuiverSubsetForCycles(O!.quiver,z) then
         return not HasNextOrdering(O) or
          IsWellReversedSubset(NextOrdering(O),z);
     fi;
     return true;
  end
);


InstallMethod(IsTotalSubset,
 "for a weight ordering and a list of generators",
 true,
 [IsWeightOrdering,IsHomogeneousList],0,
 function(O,L)
     if Length(L)<1 or
      (Length(L)=1 and IsArrow(L[1]) and
       O!.weight[ExtRepOfObj(L[1])[1]-
                 Length(VerticesOfQuiver(O!.quiver))]<>0) then
         return true;
     elif HasNextOrdering(O) then
         return IsTotalSubset(NextOrdering(O,L));
     else
         return true;
     fi;
  end
);


DeclareOperation("PathFromArrowList",[IsQuiver,IsHomogeneousList]);

InstallMethod(PathFromArrowList,
 "for a list of arrows",
 true,
 [IsQuiver,IsHomogeneousList],0,
 function(Q,L)
     local ret;
     if Length(L)<1 then
         return Zero(Q);
     elif Length(L)=1 then
         return L[1]; #This handles vertices, too
     else
         ret:=Objectify(NewType(FamilyObj(Q),
                                IsPath and IsAttributeStoringRep),
                        rec());
         SetSourceOfPath(ret,SourceOfPath(L[1]));
         SetTargetOfPath(ret,TargetOfPath(L[Length(L)]));
         SetLengthOfPath(ret,Length(L));
         SetWalkOfPath(ret,L);
         SetIsZeroPath(ret,false);
         return ret;
     fi;
  end
);


DeclareOperation("CompareArrowLists",[IsQuiverOrdering,IsHomogeneousList,IsHomogeneousList]);

InstallMethod(CompareArrowLists,
 "for an ordering and two lists of arrows",
 true,
 [IsQuiverOrdering,IsHomogeneousList,IsHomogeneousList],0,
 function(O,a,b)
     return ComparisonFunction(O)(PathFromArrowList(O!.quiver,a),
                                  PathFromArrowList(O!.quiver,b));
  end
);


InstallGlobalFunction(BlockOrdering,function(arg)
    local fam,O,Q,L,block,orders,i,j,rep;
    if not (Length(arg)=1 or (Length(arg)=2 or (Length(arg)=3 and
     IsQuiverOrdering(arg[3])) and IsHomogeneousList(arg[2])) and IsQuiver(arg[1]))
     then
        Error("usage: BlockOrdering(Q,L,O), the first arg must be a quiver, the second a list of [ordering,[generator list]] pairs, and the optional third argument an ordering");
    fi;
    L:=arg[2];
    if Length(L)<1 then
        Error("BlockOrdering: Subset list cannot be empty");
    fi;

    fam:=NewFamily("FamilyBlockOrderings",IsBlockOrdering);
    O:=Objectify(NewType(fam,IsBlockOrdering and IsAttributeStoringRep),
                 rec());
    Q:=arg[1];
    O!.quiver:=Q;

    block:=[];
    orders:=[];
    L:=Flat(L);
    i:=1;
    while i<Length(L) do
        if not IsQuiverOrdering(L[i]) then
            Error("Second argument must be a list of [ordering,[generator list]] pairs");
        fi;
        Add(orders,L[i]);
        if HasLexicographicTable(L[i]) then
            if HasLexicographicTable(O) then
                if LexicographicTable(O)<>LexicographicTable(L[i]) then
                    Error("Conflicting lexicographic tables");
                fi;
            else
                SetLexicographicTable(O,LexicographicTable(L[i]));
                O!.lex:=L[i]!.lex;
            fi;
        fi;
        i:=i+1;
        while i<Length(L) do
            if (not IsArrow(L[i])) and (not IsQuiverVertex(L[i])) then
                break;
            fi;
            block[ExtRepOfObj(L[i])[1]]:=Length(orders);
            i:=i+1;
        od;
    od;
    L:=Length(GeneratorsOfQuiver(Q));
    if L>0 then
        for i in [1..L] do
            if not IsBound(block[i]) then
                block[i]:=Length(orders);
            fi;
        od;
    fi;
    O!.block:=block;
    O!.orders:=orders;

    if Length(arg)>=3 then
        SetNextOrdering(O,arg[3]);
        if HasLexicographicTable(arg[3]) then
            if HasLexicographicTable(O) then
                if LexicographicTable(O)<>LexicographicTable(arg[3]) then
                    Error("Conflicting lexicographic tables");
                fi;
            else
                SetLexicographicTable(O,LexicographicTable(arg[3]));
                O!.lex:=arg[3]!.lex;
            fi;
        fi;
    fi;

    SetOrderingName(O,"block");
    SetComparisonFunction(O,function(a,b)
        local ret,e,f,p,q,o,i,g;
        o:=Length(O!.orders);
        p:=[];
        for i in [1..o] do
            Add(p,[]);
        od;
        q:=StructuralCopy(p);
        g:=GeneratorsOfQuiver(O!.quiver);
        if not IsZeroPath(a) then
            e:=ExtRepOfObj(a);
            for i in e do
                Add(p[block[i]],g[i]);
            od;
        fi;
        if not IsZeroPath(b) then
            f:=ExtRepOfObj(b);
            for i in f do
                Add(q[block[i]],g[i]);
            od;
        fi;
        while o>0 do
            ret:=CompareArrowLists(O!.orders[o],p[o],q[o]);
            if ret<>0 then
                return ret;
            fi;
            o:=o-1;
        od;
        if HasNextOrdering(O) then
            return ComparisonFunction(NextOrdering(O))(a,b);
        fi;
        return 0;
    end);
    return O;
  end
);


DeclareGlobalFunction("CheckBlocksForCycles");

InstallGlobalFunction(CheckBlocksForCycles,
 function(O,block)
     local i,r,n,visit;
     #Possibly a big shortcut
     if HasIsAcyclicQuiver(O!.quiver) and IsAcyclicQuiver(O!.quiver) then
         return true;
     fi;
     n:=[];
     i:=1;
     #Visit a vertex
     #v is the vertex
     #j is 4 * the generator position of the vertex
     #c is the label of the source vertex for the last arrow which transitioned blocks
     #b is the current block number, or 0
     #a is the label of the source vertex for highest previous 0 arrow in a row
     #n[j]   = the depth-first search label of the vertex
     #n[j-1] = true: the vertex was visited successfully; false: vertex is being visited
     #n[j-2] = index of the highest vertex reachable from cycles containing this vertex
     #n[j-3] = the block number of any cycle this vertex belongs to, or 0
     visit:=function(v,j,c,b,a)
         local adj,k,t,p,d,e,f,m;
         n[j]:=i;
         n[j-1]:=true;
         n[j-3]:=0;
         i:=i+1;
         #Check all the arrows
         adj:=OutgoingArrowsOfVertex(v);
         for p in adj do
             t:=TargetOfPath(p);
             k:=ExtRepOfObj(t)[1]*4;
             #Look for block transition
             e:=block[ExtRepOfObj(p)[1]];
             if e>0 then
                 if b>0 and e<>b then
                     f:=a;
                 else
                     f:=c;
                 fi;
                 d:=i;
             else
                 e:=b;
                 f:=c;
                 d:=a;
             fi;
             #Arrow points to an unvisited vertex
             if not IsBound(n[k]) then
                 if not visit(t,k,f,e,d) then
                     return false;
                 #If it's part of a cycle that reaches us
                 elif IsBound(n[k-2]) and n[n[k-2]-1] then
                     #Mark how high we can reach
                     if (not IsBound(n[j-2])) or n[n[j-2]]>n[n[k-2]] then
                         n[j-2]:=n[k-2];
                     fi;
                     #Mark what block the cycle is in
                     if n[k-3]<>0 then
                         n[j-3]:=n[k-3];
                     fi;
                 fi;
             #The vertex can reach us
             elif n[k-1] or (IsBound(n[k-2]) and n[n[k-2]-1]) then
                 if IsBound(n[k-2]) then
                     m:=[k-2];
                 else
                     m:=k;
                 fi;
                 #The cycle contains something outside our block
                 if n[m]<f or (n[k-3]>0 and e>0 and n[k-3]<>e) then
                     return false;
                 #Mark us a belonging to the cycle
                 elif (not IsBound(n[j-2])) or n[n[j-2]]>n[m] then
                     n[j-2]:=m;
                 fi;
             fi;
         od;
         n[j-1]:=false;
         return true;
     end;
     for i in [1..Length(VerticesOfQuiver(O!.quiver))] do
         if block[i]>0 then
             r:=i*4;
             if not IsBound(n[r]) then
                 if not visit(VerticesOfQuiver(O!.quiver)[i],r,0,0,0) then
                     return false;
                 fi;
             fi;
         fi;
     od;
     return true;
  end
);


InstallMethod(IsTotalOrdering,
 "for a block ordering",
 true,
 [IsBlockOrdering],0,
 function(O)
     local l,s,i,block;
     l:=GeneratorsOfQuiver(O!.quiver);
     s:=[];
     block:=O!.block;
     for i in [1..Length(O!.orders)] do
         Add(s,[]);
     od;
     for i in l do
         Add(s[block[ExtRepOfObj(i)[1]]],i);
     od;
     for i in [1..Length(O!.orders)] do
         if not IsTotalSubset(O!.orders[i],s[i]) then
             if HasNextOrdering(O) then
                 return IsTotalOrdering(NextOrdering(O));
             else
                 return false;
             fi;
         fi;
     od;
     if Length(block)>0 then
         if not CheckBlocksForCycles(O,block) then
            if HasNextOrdering(O) then
                return IsTotalOrdering(NextOrdering(O));
            else
                return false;
            fi;
         fi;
     fi;
     return true;
  end
);


InstallMethod(IsWellSubset,
 "for a block ordering and a list of generators",
 true,
 [IsBlockOrdering,IsHomogeneousList],0,
 function(O,L)
     local s,i,block;
     s:=[];
     block:=O!.block;
     for i in [1..Length(O!.orders)] do
         Add(s,[]);
     od;
     for i in L do
         Add(s[block[ExtRepOfObj(i)[1]]],i);
     od;
     for i in [1..Length(O!.orders)] do
         if not IsWellSubset(O!.orders[i],s[i]) then
             return false;
         fi;
     od;
     return true;
  end
);


InstallMethod(IsWellReversedSubset,
 "for a block ordering and a list of generators",
 true,
 [IsBlockOrdering,IsHomogeneousList],0,
 function(O,L)
     local s,i,block;
     s:=[];
     block:=O!.block;
     for i in [1..Length(O!.orders)] do
         Add(s,[]);
     od;
     for i in L do
         Add(s[block[ExtRepOfObj(i)[1]]],i);
     od;
     for i in [1..Length(O!.orders)] do
         if not IsWellReversedSubset(O!.orders[i],s[i]) then
             return false;
         fi;
     od;
     return true;
  end
);


InstallMethod(IsTotalSubset,
 "for a block ordering and a list of generators",
 true,
 [IsBlockOrdering,IsHomogeneousList],0,
 function(O,L)
     local l,s,i,j,block;
     s:=[];
     block:=ListWithIdenticalEntries(Length(O!.block),0);
     for i in [1..Length(O!.orders)] do
         Add(s,[]);
     od;
     for i in L do
         if IsArrow(i) then
             j:=ExtRepOfObj(SourceOfPath(i))[1];
             block[j]:=O!.block[j];
         fi;
         j:=ExtRepOfObj(i)[1];
         block[j]:=O!.block[j];
         Add(s[block[j]],i);
     od;
     for i in [1..Length(O!.orders)] do
         if not IsTotalSubset(O!.orders[i],s[i]) then
             if HasNextOrdering(O) then
                 return IsTotalSubset(NextOrdering(O),L);
             else
                 return false;
             fi;
         fi;
     od;
     if Length(block)>0 then
         if not CheckBlocksForCycles(O,block) then
             if HasNextOrdering(O) then
                 return IsTotalOrdering(NextOrdering(O));
             else
                 return false;
             fi;
         fi;
     fi;
     return true;
  end
);


InstallGlobalFunction(WreathOrdering,function(arg)
    local fam,O,Q,L,block,orders,i,j,rep;
    if not (Length(arg)=1 or (Length(arg)=2 or (Length(arg)=3 and
     IsQuiverOrdering(arg[3])) and IsHomogeneousList(arg[2])) and IsQuiver(arg[1]))
     then
        Error("usage: WreathOrdering(Q,L,O), the first arg must be a quiver, the second a list of [ordering,[generator list]] pairs, and the optional third argument an ordering");
    fi;
    L:=arg[2];
    if Length(L)<1 then
        Error("WreathOrdering: Subset list cannot be empty");
    fi;

    fam:=NewFamily("FamilyWreathOrderings",IsWreathOrdering);
    O:=Objectify(NewType(fam,IsWreathOrdering and IsAttributeStoringRep),
                 rec());
    Q:=arg[1];
    O!.quiver:=Q;

    block:=[];
    orders:=[];
    L:=Flat(L);
    i:=1;
    while i<Length(L) do
        if not IsQuiverOrdering(L[i]) then
            Error("Second argument must be a list of [ordering,[generator list]] pairs");
        fi;
        Add(orders,L[i]);
        if HasLexicographicTable(L[i]) then
            if HasLexicographicTable(O) then
                if LexicographicTable(O)<>LexicographicTable(L[i]) then
                    Error("Conflicting lexicographic tables");
                fi;
            else
                SetLexicographicTable(O,LexicographicTable(L[i]));
                O!.lex:=L[i]!.lex;
            fi;
        fi;
        i:=i+1;
        while i<Length(L) do
            if (not IsArrow(L[i])) and (not IsQuiverVertex(L[i])) then
                break;
            fi;
            block[ExtRepOfObj(L[i])[1]]:=Length(orders);
            i:=i+1;
        od;
    od;
    L:=Length(GeneratorsOfQuiver(Q));
    if L>0 then
        for i in [1..L] do
            if not IsBound(block[i]) then
                block[i]:=Length(orders);
            fi;
        od;
    fi;
    O!.block:=block;
    O!.orders:=orders;

    if Length(arg)>=3 then
        SetNextOrdering(O,arg[3]);
        if HasLexicographicTable(arg[3]) then
            if HasLexicographicTable(O) then
                if LexicographicTable(O)<>LexicographicTable(arg[3]) then
                    Error("Conflicting lexicographic tables");
                fi;
            else
                SetLexicographicTable(O,LexicographicTable(arg[3]));
                O!.lex:=arg[3]!.lex;
            fi;
        fi;
    fi;

    SetOrderingName(O,"wreath");
    SetComparisonFunction(O,function(a,b)
        local ret,e,f,o,s,t,i,j,c,d,p,q,m,n,x,y,g;
        if IsZeroPath(a) then
            e:=[];
        else
            e:=ExtRepOfObj(a);
        fi;
        if IsZeroPath(b) then
            f:=[];
        else
            f:=ExtRepOfObj(b);
        fi;
        o:=1;
        i:=Minimum(Length(e),Length(f));
        # Skip equal elements
        while o<=i do
            if e[o]<>f[o] then
                break;
            fi;
            o:=o+1;
        od;
        # If we skipped everything, the paths are identical
        if o>Length(e) and o>Length(f) then
            return 0;
        fi;
        g:=GeneratorsOfQuiver(O!.quiver);
        s:=0;
        m:=0;
        p:=[];
        c:=[];
        x:=[];
        if o<=Length(e) then
            for i in [o..Length(e)] do
                j:=block[e[i]];
                if j>m then
                    s:=s+1;
                    m:=j;
                    Add(c,m);
                    Add(p,[g[e[i]]]);
                elif j=m then
                    Add(p[s],g[e[i]]);
                else
                    Add(x,g[e[i]]);
                fi;
            od;
        fi;
        t:=0;
        n:=0;
        q:=[];
        d:=[];
        y:=[];
        if o<=Length(f) then
            for i in [o..Length(f)] do
                j:=block[f[i]];
                if j>n then
                    t:=t+1;
                    n:=j;
                    Add(d,n);
                    Add(q,[g[f[i]]]);
                elif j=n then
                    Add(q[t],g[f[i]]);
                else
                    Add(y,g[f[i]]);
                fi;
            od;
        fi;
        while s>0 and t>0 do
            if c[s]=d[t] then
                ret:=CompareArrowLists(orders[c[s]],p[s],q[t]);
                s:=s-1;
                t:=t-1;
            elif c[s]>d[t] then
                ret:=CompareArrowLists(orders[c[s]],p[s],[]);
                s:=s-1;
            else
                ret:=CompareArrowLists(orders[d[t]],[],q[t]);
                t:=t-1;
            fi;
            if ret<>0 then
                return ret;
            fi;
        od;
        while s>0 do
            ret:=CompareArrowLists(orders[c[s]],p[s],[]);
            if ret<>0 then
                return ret;
            fi;
            s:=s-1;
        od;
        while t>0 do
            ret:=CompareArrowLists(orders[d[t]],[],q[t]);
            if ret<>0 then
                return ret;
            fi;
            t:=t-1;
        od;
        ret:=CompareArrowLists(O,x,y);
        if ret=0 and HasNextOrdering(O) then
            ret:=ComparisonFunction(NextOrdering(O))(a,b);
        fi;
        return ret;
    end);

    return O;

  end
);


PrintOrdering :=  function(O)
    local done;
    
    done := false;
    Print("<");
    while not done do
        if HasOrderingName(O) then
            Print(OrderingName(O));
        else
            Print("unnamed");
        fi;
        Print(" ");
        if HasNextOrdering(O) then
            O := NextOrdering(O);
        else
            done := true;
        fi;
    od;
    Print("ordering>");
end;


InstallMethod( ViewObj,
    "for orderings",
    true,
    [IsQuiverOrdering], 0,
    PrintOrdering
);


InstallMethod( PrintObj,
    "for orderings",
    true,
    [IsQuiverOrdering], 0,
    PrintOrdering
);

[ Dauer der Verarbeitung: 0.48 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge