Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/kan/lib/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 23.0.2024 mit Größe 48 kB image not shown  

SSL dcrws.gi   Sprache: unbekannt

 
##############################################################################
##
#W  dcrws.gi                     Kan Package                     Chris Wensley
#W                                                             & Anne Heyworth
#Y  Copyright (C) 1996-2023, Chris Wensley and Anne Heyworth 
##
##  This file contains generic methods for double coset rewriting systems
##
##  Convention:  order is a string, "shortlex" or "wreath",
##                 ord is an ordering,
##             gensord is a numerical list of generators, e.g. [2,1,4,3]

KAN_double_coset_group_alphabet := 
    ["A","a","B","b","C","c","D","d","E","e","F","f","G","g"];
KAN_double_coset_coset_alphabet := 
    ["T","t"];

############################################################################
##
#M  \*                                                  methods for strings
#M  \^                                                   (rather a fudge)
##
InstallOtherMethod( \*, "for strings", true, 
    [ IS_STRING_REP, IS_STRING_REP ], 0, 
function( s1, s2 ) 
  return Concatenation( s1, s2 );
end );

InstallOtherMethod( \^, "for strings", true, [ IS_STRING_REP, IsPosInt ], 0, 
function( s, p ) 
    local  i, w;
    w := s;
    for i in [2..p] do
        w := Concatenation( w, s );
    od;
    return w;
end );

#############################################################################
##
#M  OrderedAlphabet 
#M  WordToString
#M  DisplayAsString
#M  DisplayRwsRules 
##
InstallMethod( OrderedAlphabet, "generic method for a rewriting system", true, 
    [ IsRewritingSystem  ], 0, 
function( rws )

    local  alph, free, gens, ord, pos, oalph; 
    alph := rws!.alphabet; 
    if not HasOrderingOfRewritingSystem( rws ) then 
        return alph; 
    fi; 
    free := FreeMonoidOfRewritingSystem( rws ); 
    gens := GeneratorsOfMonoid( free ); 
    ord := OrderingOnGenerators( OrderingOfRewritingSystem(rws) );
    pos := List( ord, g -> Position( gens, g ) ); 
    oalph := List( [1..Length(alph)], i -> alph[pos[i]] );
    return List( [1..Length(alph)], i -> alph[pos[i]] );
end ); 

InstallMethod( WordToString, "generic method for a rewriting system", true, 
    [ IsWord, IsString ], 0, 
function( r, alph )

    local  alph0, w, lenw, i, j, k, c, s;
    alph0 := List( [1..Length(alph)], i -> WordAlp( alph, i ) );
    w := ExtRepOfObj( r );  
    lenw := QuoInt( Length(w), 2 );
    s := "";
    for i in [1..lenw] do
        j := i+i;
        c := alph0[w[j-1]];
        for k in [1..w[j]] do
            s := Concatenation( s, c );
        od;
    od;
    return s;
end );

InstallMethod( DisplayAsString, "generic method for a rewriting system", true, 
    [ IsWord, IsString ], 0, 
function( r, alph )

    local  alph0, w, lenw, i, j, k, c, s;
    alph0 := List( [1..Length(alph)], i -> WordAlp( alph, i ) );
    w := ExtRepOfObj( r );  
    lenw := QuoInt( Length(w), 2 );
    s := "";
    for i in [1..lenw] do
        j := i+i;
        c := alph0[w[j-1]];
        for k in [1..w[j]] do
            s := Concatenation( s, c );
        od;
    od;
    Print( s );
end );

InstallOtherMethod( DisplayAsString, "generic method for a list of words", 
    true, [ IsHomogeneousList, IsString, IsBool ], 0, 
function( L, alph, b )

    local  alph0, w, lenw, i, j, k, c, q, r, s, len, M;

    alph0 := List( [1..Length(alph)], i -> WordAlp( alph, i ) );
    if ( L = [ ] ) then
        Print( L );
        if ( b = true ) then
            Print( "\n" );
        fi;
    elif IsList( L[1] ) then
        for M in L do
            DisplayAsString( M, alph, b );
        od;
    elif not IsWord( L[1] ) then
        Error( "not a list of words" );
    else
        len := Length( L );
        Print( "[ " );
        for q in [1..len] do
            r := L[q];
            w := ExtRepOfObj( r ); 
            lenw := QuoInt( Length(w), 2 );
            if ( lenw = 0 ) then
                Print( "id" );
            else
                s := "";
                for i in [1..lenw] do
                    j := i+i;
                    c := alph0[w[j-1]];
                    for k in [1..w[j]] do
                        s := Concatenation( s, c );
                    od;
                od;
                Print( s );
            fi;
            if ( q < len ) then
               Print( ", " );
            else
                Print( " ]" );
                if ( b = true ) then
                    Print( "\n" );
                fi;
            fi;
        od;
    fi;
end );

InstallMethod( DisplayRwsRules,
    "generic method for a double coset rewriting system", true, 
    [ IsRewritingSystem ], 0,
function( rws )

    local  numr, t, type, w, k, ok, c, cG, cH, cK, cHK,
           rules, M, num, extended, alph;

    rules := Rules( rws );
    extended := ( HasIsDoubleCosetRewritingSystem( rws ) and
                     IsDoubleCosetRewritingSystem( rws ) );
    M := MonoidOfRewritingSystem( rws );
    num := Length( GeneratorsOfMonoid( M ) );
    if IsBound( rws!.alphabet ) then
        alph := rws!.alphabet;
    else
        alph := KAN_double_coset_group_alphabet{[1..num]};
        if extended then
            alph := Concatenation( "HK", alph );
        fi;
    fi;
    cG:=0;  cH:=0;  cK:=0;  cHK:=0;
    ## (15/8/23) make output same for GAP 4.12 and gapdev
    rules := Set(rules);
    numr := Length( rules );
    type := ListWithIdenticalEntries( numr, 0 ); 
    if extended then
        for k in [1..numr] do
            t := 0;
            w := ExtRepOfObj( rules[k][1] );
            if ( w[1]=1 ) then t:=1; fi;
            if ( w[Length(w)-1]=2 ) then t:=t+2; fi;
            type[k] := t;
            if (t=0) then cG:=cG+1;
            elif (t=1) then cH:=cH+1;
            elif (t=2) then cK:=cK+1;
            else cHK:=cHK+1;
            fi;
        od;
    else
        cG := numr;
    fi;
    c := 0;
    if extended then  Print( "G-rules:\n" );  fi;
    for k in [1..numr] do
        if ( type[k] = 0 ) then
            if (c=0) then Print("[ "); fi;
            c := c+1;
            DisplayAsString( rules[k], alph, false );
            if (c=cG) then Print(" ]\n"); else Print(", "); fi;
        fi;
    od;
    if extended then
        if ( cH > 0 ) then
            c := 0;
            Print( "H-rules:\n" );
            for k in [1..numr] do
                if ( type[k] = 1 ) then
                    if (c=0) then Print("[ "); else Print("  "); fi;
                    c := c+1;
                    DisplayAsString( rules[k], alph, false );        
                if (c=cH) then Print(" ]\n"); else Print(",\n"); fi;
                fi;
            od;
        fi;
        if ( cK > 0 ) then
            c := 0;
            Print( "K-rules:\n" );
            for k in [1..numr] do
                if ( type[k] = 2 ) then
                    if (c=0) then Print("[ "); else Print("  "); fi;
                    c := c+1;
                    DisplayAsString( rules[k], alph, false );   
                if (c=cK) then Print(" ]\n"); else Print(",\n"); fi;
                fi;
            od;
        fi;
        if (cHK > 0 ) then
            c := 0;
            Print( "H-K-rules:\n" );
            for k in [1..numr] do
                if ( type[k] = 3 ) then
                    if (c=0) then Print("[ "); else Print("  "); fi;
                    c := c+1;
                    DisplayAsString( rules[k], alph, false );  
                if (c=cHK) then Print(" ]\n"); else Print(",\n"); fi;
                fi;
            od;
        fi;
    fi;
    return true;
end );

#############################################################################
##
#M  WordAcceptorOfReducedRws
##
InstallMethod( WordAcceptorOfReducedRws, 
    "generic method for an rws", true, [ IsRewritingSystem ], 0,
function( rws )

    local  rules, numr, order, fam, ogens, id, numgens, pf, numpf, 
           i, j, k, l, p, u, v, w, pos, pos2, numstates, sh, row, transmx, 
           rhs, ugens, len, sink, accept, init, alph, alpht, nfa, mfa, dfa, 
           ok, ls, lu, perm, IsSuffix;

    IsSuffix := function( u, s )
        ls := Length( s );  lu := Length( u );
        return ( (lu >= ls) and (Subword(u,lu-ls+1,lu) = s) );
    end;

    rules := Rules( rws );
    numr := Length( rules );
    order := OrderingOfRewritingSystem( rws );
    fam := FamilyForRewritingSystem( rws );
    ogens := OrderingOnGenerators( order );
    ugens := List( ogens, g -> true );
    id := One( ogens[1] );
    numgens := Length( ogens );
    if IsBound( rws!.alphabet ) then
        alph := rws!.alphabet;
        alpht := ShallowCopy( alph );
        perm := rws!.gensperm;
        for i in [1..Length(alph)] do
            alpht[i] := alph[i^perm];
        od;
        Info( InfoKan, 2, "alphabet= ", alph, ", twisted alphabet= ", alpht );
    else
        alph := numgens;
    fi;
    pf := [ id ];
    rhs := [ ];
    for k in [1..numr] do
        w := rules[k][2];
        if not ( w = id ) then
            pos := Position( rhs, w );
            if ( pos = fail ) then
                Add( rhs, w );
            fi;
        fi;
        w := rules[k][1];
        len := Length( w );
        if ( len = 1 ) then
            pos := Position( ogens, Subword( w, 1, 1 ) );
            ugens[pos] := false;
        else
            for i in [1..len-1] do
                p := Subword( w, 1, i );
                pos := Position( pf, p );
                if ( pos = fail ) then
                    Add( pf, p );
                fi;
            od;
        fi;
    od;
    numpf := Length( pf );
    Info( InfoKan, 2, "prefixes = ", pf );
    sink := 1;  sh := 1;
    numstates := numpf + sh;
    row := ListWithIdenticalEntries( numstates, 0 );
    transmx := List( [1..numgens], i -> ShallowCopy( row ) );
    for i in [1..numgens] do
        transmx[i][sink] := [ sink ];
        for j in [sh+1..numstates] do 
            if ( ugens[i] = false ) then
                transmx[i][j] := [ sink ];
            else
                transmx[i][j] := [ ];
            fi;
        od;
    od;
    Info( InfoKan, 2, "ogens, ugens and rhs:" );
    Info( InfoKan, 2, ogens );
    Info( InfoKan, 2, ugens );
    Info( InfoKan, 2, rhs );
    ## transitions ##
    for k in [1..numpf] do
        j := k + sh;
        u := pf[k];
        len := Length(u) + 1;
        for i in [1..numgens] do
            v := u * ogens[i];
            ok := true;
            l := 1;
            while ( ok and ( l <= numr ) ) do
                if IsSuffix( v, rules[l][1] ) then
                    transmx[i][j] := [ sink ];
                    ok := false;
                fi;
                l := l+1;
            od;
            if ok then
                for l in [1..len] do
                    p := Subword( v, l, len );
                    pos := Position( pf, p );
                    if not ( pos = fail ) then
                        pos2 := Position( transmx[i][j], pos );
                        if ( pos2 = fail ) then 
                            Add( transmx[i][j], pos+sh );
                        fi;
                    fi;
                od;
            fi;
            if ( transmx[i][j] = [ ] ) then
                Error( "transmx[i][j] = fail" );
            fi;
        od;
    od;
    Info( InfoKan, 2, "transition matrix of acceptor:" );
    Info( InfoKan, 2, transmx );
    accept := [sink];
    init := [ sh+1 ];
    nfa := Automaton( "nondet", numstates, alpht, transmx, init, accept );
    Info( InfoKan, 2, "initial NFA: ", nfa ); 
    dfa := NFAtoDFA( nfa ); 
    Info( InfoKan, 2, "initial DFA: ", dfa ); 
    mfa := MinimalAutomaton( ComplementDA( dfa ) );
    Info( InfoKan, 2, "minimal DFA: ", mfa ); 
    SetWordAcceptorOfReducedRws( rws, mfa );
    return mfa; 
end );

#############################################################################
##
#M  DoubleCosetRewritingSystem
#M  PartialDoubleCosetRewritingSystem
#M  DCrules
##
InstallMethod( DoubleCosetRewritingSystem,
    "generic method for a group, two subgroups and an rws",  true, 
    [ IsGroup, IsGroup, IsGroup, IsRewritingSystem ], 0,
function( G, H, K, rwsG )
    return PartialDoubleCosetRewritingSystem( G, H, K, rwsG, 0 );
end );

InstallMethod( DCrules, "generic method for a double coset rws", true, 
    [ IsDoubleCosetRewritingSystem ], 0,
function( dcrws )

    local  order, ogens, rules, hrules, krules, hkrules, m1, m2;

    order := OrderingOfRewritingSystem( dcrws );
    ogens := OrderingOnGenerators( order );
    m1 := ogens[1];
    m2 := ogens[2];
    rules := Rules( dcrws );
    hrules := Filtered( rules, r -> Subword(r[1],1,1) = m1 );
    krules := Filtered( rules, 
        r -> Subword(r[1],Length(r[1]),Length(r[1])) = m2 );
    hkrules := Filtered( krules, r -> Subword(r[1],1,1) = m1 );
    hrules := Difference( hrules, hkrules );
    krules := Difference( krules, hkrules );
    SetHrules( dcrws, hrules );
    SetKrules( dcrws, krules );
    SetHKrules( dcrws, hkrules );
    return true;
end );

InstallMethod( PartialDoubleCosetRewritingSystem,
    "generic method for a group, two subgroups, an rws and a limit",  true, 
    [ IsGroup, IsGroup, IsGroup, IsRewritingSystem, IsInt ], 0,
function( G, H, K, rwsG, limit )

    local  genH, genK, gensord, order, fG, rels, genG, genfG, numgenG, numgenfG, 
           genfM, genfH, genfK, alph, alpht, alph2, mhom, M, genM, 
           numgenM, range, fM, ord, perm, rules, numrules, numgensF2, 
           F2, genF2, numH, numK, extrules, printmax, i, j, l, el, r, 
           er, lene, n, e, h, h1, k, k1, fam2, M2, genM2, numgenM2, 
           range2, ord2, rws2, fM2, genfM2, L2, perm2, plus;

    if not ( IsSubgroup( G, H ) and IsSubgroup( G, K ) ) then 
        Error( "H and K must be subgroups of G" ); 
    fi; 
    genH := GeneratorsOfGroup( H ); 
    genK := GeneratorsOfGroup( K ); 
    printmax := 40;
    ord := OrderingOfRewritingSystem( rwsG );
    if ( HasIsShortLexOrdering( ord ) and IsShortLexOrdering( ord ) ) then
        order := "shortlex";
    elif ( HasIsBasicWreathProductOrdering( ord ) and
           IsBasicWreathProductOrdering( ord ) ) then
        order := "wreath";
    fi;
    alph := rwsG!.alphabet;
    gensord := OrderingOnGenerators( ord );
    #?  is the following chunk redundant after adding OrderedAlphabet? 
    ############################## 
    alpht := ShallowCopy( alph );
    if ( HasReducedConfluentRewritingSystem( G ) 
         or HasInitialRewritingSystem( G ) ) then
        perm := rwsG!.gensperm;
    elif HasKBMagWordAcceptor( G ) then
        perm := KBMagWordAcceptor( G )!.gensperm;
    else
        Error( "no gensperm with which to permute the alphabet" );
    fi;
    for i in [1..Length(alph)] do
        alpht[i] := alph[i^perm];
    od; 
    ############################### 
    alpht := OrderedAlphabet( rwsG ); 
    fG := FreeGroupOfFpGroup( G );
    rels := RelatorsOfFpGroup( G );
    genG := GeneratorsOfGroup( G );
    genfG := GeneratorsOfGroup( fG );
    numgenG := Length( genG );
    numgenfG := Length( genfG );
    if ( numgenG <> numgenfG ) then
        Error( "unequal numbers of generators" );
    fi;
    genfH := List( genH, h -> MappedWord( h, genG, genfG ) );
    genfK := List( genK, k -> MappedWord( k, genG, genfG ) );
    mhom := IsomorphismFpMonoid( G );
    M := Image( mhom );
    genM := GeneratorsOfMonoid( M );
    fM := FreeMonoidOfFpMonoid( M );
    genfM := GeneratorsOfMonoid( fM );
    numgenM := Length( genM );
    if ( numgenM = Length( gensord ) ) then
        range := List( gensord, x -> Position( genfM, x ) );
    else
        range := 0 * [1..numgenM];
        for i in [1..numgenG] do
            range[i] := 2*i;
            range[i+numgenG] := 2*i-1;
        od;
    fi;
    Info( InfoKan, 2, "using range = ", range );
    if ( order = "shortlex" ) then
        ord := ShortLexOrdering( fM, range );
    elif ( order = "wreath" ) then
        ord := BasicWreathProductOrdering( fM, range );
    else
        Error( "the given order should be \"shortlex\" or \"wreath\"" );
    fi;
    rules := Rules( rwsG );
    numrules := Length( rules );
    Info( InfoKan, 2, "Rules of ", order, " rewriting system:" );
    if ( InfoLevel( InfoKan ) >= 2 ) then
        if ( numrules <= printmax )  then
            DisplayRwsRules( rwsG );
        else
            Print( "number of rules = ", numrules, "\n" );
        fi;
    fi;
    alph2 := Concatenation( "HK", alph );
    Info( InfoKan, 2, "setting alphabet alph2 = ", alph2 );
    numgensF2 := numgenM + 2;
    F2 := FreeMonoid( numgensF2 );
    genF2 := GeneratorsOfMonoid( F2 );
    numH := Length( genH );
    numK := Length( genK );
    plus := 2*(numH + numK);
    extrules := 0 * [1..(plus+numrules)];
    fam2 := FamilyObj( One( F2 ) );
    for i in [1..numrules] do
        el := ShallowCopy( ExtRepOfObj( rules[i][1] ) );
        lene := QuoInt( Length( el ), 2 );
        for j in [1..lene] do
             el[j+j-1] := el[j+j-1] + 2;
        od;
        l := ObjByExtRep( fam2, el );
        er := ShallowCopy( ExtRepOfObj( rules[i][2] ) );
        lene := QuoInt( Length( er ), 2 );
        for j in [1..lene] do
             er[j+j-1] := er[j+j-1] + 2;
        od; 
        r := ObjByExtRep( fam2, er );
        extrules[plus + i] := [ l, r ];
    od;
    n := 0;
    for h in genH do
        n := n+1;
        e := ShallowCopy( ExtRepOfObj( h ) );
        for i in [1..QuoInt( Length(e), 2 ) ] do
            j := i+i;
            e[j-1] := 2*e[j-1] + 2;
            if ( e[j] < 0 ) then
                e[j] := - e[j];
                e[j-1] := e[j-1] - 1;
            fi;
        od;
        e := Concatenation( [ 1, 1 ], e );
        extrules[n] := [ ObjByExtRep( fam2, e ), genF2[1] ];
        h1 := h^-1;
        n := n+1;
        e := ShallowCopy( ExtRepOfObj( h1 ) );
        for i in [1..QuoInt( Length(e), 2 ) ] do
            j := i+i;
            e[j-1] := 2*e[j-1] + 2;
            if ( e[j] < 0 ) then
                e[j] := - e[j];
                e[j-1] := e[j-1] - 1;
            fi;
        od;
        e := Concatenation( [ 1, 1 ], e );
        extrules[n] := [ ObjByExtRep( fam2, e ), genF2[1] ];
    od;    
    for k in genK do
        n := n+1;
        e := ShallowCopy( ExtRepOfObj( k ) );
        for i in [1..QuoInt( Length(e), 2 ) ] do
            j := i+i;
            e[j-1] := 2*e[j-1] + 2;
            if ( e[j] < 0 ) then
                e[j] := - e[j];
                e[j-1] := e[j-1] - 1;
            fi;
        od;
        e := Concatenation( e, [ 2, 1 ] );
        extrules[n] := [ ObjByExtRep( fam2, e ), genF2[2] ];
        k1 := k^-1;
        n := n+1;
        e := ShallowCopy( ExtRepOfObj( k1 ) );
        for i in [1..QuoInt( Length(e), 2 ) ] do
            j := i+i;
            e[j-1] := 2*e[j-1] + 2;
            if ( e[j] < 0 ) then
                e[j] := - e[j];
                e[j-1] := e[j-1] - 1;
            fi;
        od;
        e := Concatenation( e, [ 2, 1 ] );
        extrules[n] := [ ObjByExtRep( fam2, e ), genF2[2] ];
        k1 := k^-1;
    od;
    if not ( n = plus ) then
        Error( "expecting plus = n" );
    fi; 
    numrules := Length( rules );
    Info( InfoKan, 2, "Rules of ", order, " extended rewriting system:" );
    if ( InfoLevel( InfoKan ) >= 2 ) then
        if ( Length(extrules) <= printmax )  then
            DisplayAsString( extrules, alph2, true );
        else
            Print( "number of rules = ", Length(extrules), "\n" );
        fi;
    fi;

    M2 := F2/extrules;
    genM2 := GeneratorsOfMonoid( M2 );
    numgenM2 := Length( genM2 );
    range2 := Concatenation( [1,2], List( range, j -> j+2 ) );
    if ( order = "shortlex" ) then
        ord2 := ShortLexOrdering( F2, range2 );
    elif ( order = "wreath" ) then
        Info( InfoKan, 2, "using wreath product ordering" );
        ord2 := BasicWreathProductOrdering( F2, range2 );
    else
        Error( "expecting order to be \"shortlex\" or \"wreath\"" );
    fi;
    L2 := Concatenation( [1,2], List( ListPerm(perm), i -> i+2 ) );
    perm2 := PermList( L2 );
    rws2 := ReducedConfluentRewritingSystem( M2, ord2, limit );
    rws2!.alphabet := alph2;
    rws2!.gensperm := perm2;
    if ( InfoLevel( InfoKan ) > 3 ) then   
        DisplayRwsRules( rws2 );
    fi;
    fM2 := FreeMonoidOfFpMonoid( M2 );
    genfM2 := GeneratorsOfMonoid( fM2 );
    SetIsDoubleCosetRewritingSystem( rws2, true );
    return rws2;
end );

#############################################################################
##          need to define  One  for DCRws  as  HK  or  Tt                 ##
#############################################################################

#############################################################################
##
#M  IdentityDoubleCoset
#M  NextWord
##
InstallMethod( IdentityDoubleCoset, "generic method for a double coset rws",
    true, [ IsDoubleCosetRewritingSystem ], 0, 
function( dcrws )

    local  ord, gens, w;
    ord := OrderingOfRewritingSystem( dcrws );
    gens := ShallowCopy( OrderingOnGenerators( ord ) );
    w := gens[1]*gens[2];
    return w;
end );

InstallOtherMethod( NextWord, "generic method for a rws and a word", 
    true, [ IsRewritingSystem, IsWord ], 0,
function( rws, w )
    return NextWord( rws, w, 100000 ); 
end ); 

InstallOtherMethod( NextWord, "generic method for a rws and a word", 
    true, [ IsRewritingSystem, IsWord, IsPosInt ], 0,
function( rws, w, limit )

    local  max_number_of_attempts, ord, fam, famw, gens, ogens, num, id, 
           count, v, lenv, eu, j, lastg, lastp, u, rfu, ok;

    max_number_of_attempts := limit;
    ord := OrderingOfRewritingSystem( rws );
    gens := ShallowCopy( OrderingOnGenerators( ord ) );
    ogens := List( gens, g -> ExtRepOfObj( g )[1] );
    SortParallel( ogens, gens );
    num := Length( gens );
    fam := FamilyObj( gens[1] );
    if not ( fam = FamilyObj( w ) ) then
        Error( "word not in correct family" );
    fi;
    id := One( gens[1] );
    ok := false;
    u := w;
    count := 0; 
    while not ok do
        ok := true;
        v := u;
        lenv := Length(v);
        if ( lenv = 0 ) then 
             u := gens[1]; 
        else
            eu := ShallowCopy( ExtRepOfObj( v ) );
            j := Length( eu );
            lastg := eu[j-1];
            lastp := eu[j];
            if (lastg < num ) then
                if ( lastp = 1 ) then
                    eu[j-1] := lastg + 1;
                else
                    eu[j] := lastp - 1;
                    eu := Concatenation( eu, [ lastg+1, 1 ] );
                fi;
            else  ## lastg = num ##
                if ( j = 2 ) then
                    eu := [ 1, lastp+1 ];
                else
                    j := j-2;
                    if ( eu[j] = 1 ) then
                        eu[j-1] := eu[j-1] + 1;
                        eu[j+1] := 1;
                    else
                        eu[j] := eu[j] - 1;
                        eu[j+1] := eu[j-1] + 1;
                        eu[j+2] := 1;
                        eu := Concatenation( eu, [ 1, lastp ] );
                    fi;
                fi;
            fi;
            u := ObjByExtRep( fam, eu );
        fi;
        rfu :=  ReducedForm( rws, u );
        count := count + 1; 
        ok := ( ( u = rfu ) or ( count > max_number_of_attempts ) );
    od;
    if ( count > max_number_of_attempts ) then 
        return fail;
    else 
        Info( InfoKan, 1, "count = ", count ); 
        return u; 
    fi;
end );

InstallMethod( NextWord, "generic method for double coset rws, word and limit", 
    true, [ IsDoubleCosetRewritingSystem, IsWord, IsPosInt ], 0,
function( rws, w, limit )

    local  ord, fam, famw, gens, ogens, num, id, v, lenv, eu, j, 
           lastg, lastp, u, rfu, ok, max_number_of_attempts, count;

    max_number_of_attempts := limit;
    ord := OrderingOfRewritingSystem( rws );
    gens := ShallowCopy( OrderingOnGenerators( ord ) );
    ogens := List( gens, g -> ExtRepOfObj( g )[1] );
    SortParallel( ogens, gens );
    num := Length( gens );
    ## fam := FamilyObj( gens[1] );
    fam := FamilyObj( w ); 
    if not ( fam = FamilyObj( gens[1] ) ) then
        Error( "word not in correct family" );
    fi;
    id := One( gens[1] );
    ok := false;
    u := w;
    count := 0;
    while not ok do
        ok := true;
        v := u;
        lenv := Length(v);
        if ( lenv = 2 ) then
            u := gens[1] * gens[3] * gens[2];
        else
            eu := ShallowCopy( ExtRepOfObj( v ) );
            j := Length( eu ) - 2;
            lastg := eu[j-1];
            lastp := eu[j];
            if ( lastg < num ) then
                if ( lastp = 1 ) then
                    eu[j-1] := lastg + 1;
                else
                    eu[j] := lastp - 1;
                    eu[j+1] := lastg + 1;
                    eu := Concatenation( eu, [ 2, 1 ] );
                fi;
            else  ## lastg = num ##
                if ( j = 4 ) then
                    eu := [ 1, 1, 3, lastp+1, 2, 1 ];
                else
                    j := j-2;
                    if ( eu[j] = 1 ) then
                        eu[j-1] := eu[j-1] + 1;
                        eu[j+1] := 3;
                    else
                        eu[j] := eu[j] - 1;
                        eu[j+1] := eu[j-1] + 1;
                        eu[j+2] := 1;
                        eu[j+3] := 3;
                        eu[j+4] := lastp;
                        eu := Concatenation( eu, [ 2, 1 ] );
                    fi;
                fi;
            fi;
            u := ObjByExtRep( fam, eu );
        fi;
        rfu := ReducedForm( rws, u );
        count := count + 1;
        ok := ( ( u = rfu ) or ( count > max_number_of_attempts ) );
        ok := ( u = rfu );
if InfoLevel(InfoKan)>0 then
  Print( WordToString(u,rws!.alphabet)," -> ", 
         WordToString(rfu,rws!.alphabet), "\n" );
fi;
    od;
    if ( count > max_number_of_attempts ) then 
        return fail;
    else 
        Info( InfoKan, 1, "count = ", count ); 
        return u; 
    fi;
end );

InstallMethod( NextWords, "for a rws, a word, how many and limit on #tries", 
    true, [ IsRewritingSystem, IsWord, IsPosInt, IsPosInt ], 0,
function( rws, w0, num, limit )

    local  L, i, w, ok; 

    L := ListWithIdenticalEntries( num, 0 ); 
    i := 0; 
    w := w0; 
    ok := true; 
    while ( ( i < num ) and ok ) do 
        i := i+1; 
        w := NextWord( rws, w, limit ); 
        ok := not ( w = fail ); 
        if ok then 
            L[i] := w; 
        else 
            Info( InfoKan, 1, "limit reached in NextWord" ); 
        fi;
    od; 
    if not ok then 
        L := L{[1..i-1]};  
    fi; 
    return L; 
end ); 

#############################################################################
##
#M  WordAcceptorOfDoubleCosetRws
##
InstallMethod( WordAcceptorOfDoubleCosetRws,
    "generic method for a double coset rewriting system",
    true, [ IsDoubleCosetRewritingSystem ], 0,
function( rws )

    local  rules, numr, order, fam, ogens, ugens, numgens, range, type, 
           a, c, g, i, j, k, l, m, n, p, q, s, t, u, v, w, lq, ls, lu, lw, 
           cG, cH, cK, cHK, posG, posH, posK, posHK, id, alph, alpht, perm, 
           ok, pfG, pfH, sfK, pfHK, npfG, npfH, nsfK, npfHK, printmax,
           wG, wH, wK, wHK, numstates, lr, len, sublr, pos, pos2, 
           row, transmx, shG, shH, shK, shHK, accept, nfa, dfa, cdfa, mdfa,
           init, sink, done, stateG, stateH, stateK, stateHK, 
           IsSuffix;

    IsSuffix := function( u, s )
        ls := Length( s );  lu := Length( u );
        return ( (lu >= ls) and (Subword(u,lu-ls+1,lu) = s) );
    end;

    printmax := 30;
    rules := Rules( rws );
    if ( ( InfoLevel(InfoKan) > 1 ) and ( Length(rules) < 51 ) )then
        Print( "rules of double coset rewriting system:\n" );
        DisplayRwsRules( rws );
    else
        Info( InfoKan, 2, "there are ", Length( rules ), " rules" );
    fi;
    numr := Length( rules );
    type := ListWithIdenticalEntries( numr, 0 );;
    order := OrderingOfRewritingSystem( rws );
    fam := FamilyForRewritingSystem( rws );
    ogens := OrderingOnGenerators( order );
    ugens := List( ogens, g -> true );
    id := One( ogens[1] );
    numgens := Length( ogens );
    alph := rws!.alphabet;
    alpht := ShallowCopy( alph );
    perm := rws!.gensperm;
    for i in [3..Length(alph)] do
        alpht[i] := alph[i^perm];
    od;
    Info( InfoKan, 2, "alphabet = ", alph, ", twisted alphabet = ", alpht );
    cG:=0;  cH:=0;  cK:=0;  cHK:=0;
    posG := [ ];  posH := [ ];  posK := [ ];  posHK := [ ];
    for k in [1..numr] do
        t := 0;
        w := ExtRepOfObj( rules[k][1] );
        Info( InfoKan, 3, "w = ", w );
        if ( w[1]=1 ) then t:=1; fi;
        if ( w[Length(w)-1]=2 ) then t:=t+2; fi;
        type[k] := t;
        if (t=0) then cG:=cG+1; Add(posG,k);
        elif (t=1) then cH:=cH+1; Add(posH,k);
        elif (t=2) then cK:=cK+1; Add(posK,k);
        else cHK:=cHK+1; Add(posHK,k);
        fi;
    od;
    Info( InfoKan, 2, "[cG,cH,cK,cHK] = ", [cG,cH,cK,cHK] );
    Info( InfoKan, 2, " posG = ", posG );
    Info( InfoKan, 2, " posH = ", posH );
    Info( InfoKan, 2, " posK = ", posK );
    Info( InfoKan, 2, "posHK = ", posHK );
    if ( numr <= printmax ) then
        Info( InfoKan, 2, "type = ", type );
    fi;
    pfG:=[ id ];  pfH:=[ id ];  sfK:=[ id ];  pfHK:=[ id ];
    wG:=0*[1..cG];  wH:=0*[1..cH];  wK:=0*[1..cK];  wHK:=0*[1..cHK];
    cG:=0;  cH:=0;  cK:=0;  cHK:=0;
    for k in [1..numr] do
        lr := rules[k][1];
        len := Length( lr );
        if ( type[k] = 0 ) then  ## G rule ##
            if ( len = 1 ) then
                pos := Position( ogens, Subword( lr, 1, 1 ) );
                ugens[pos] := false;
            else
                for i in [1..len-1] do
                    sublr := Subword( lr, 1, i );
                    pos := Position( pfG, sublr );
                    if ( pos = fail ) then Add( pfG, sublr); fi;
                od;
            fi;
            cG := cG+1;
            wG[cG] := lr;
        elif ( type[k] = 1 ) then  ## H rule ##
            for i in [2..len-1] do
                sublr := Subword( lr, 2, i );
                pos := Position( pfH, sublr );
                if ( pos = fail ) then Add( pfH, sublr); fi;
            od;
            cH := cH+1;
            wH[cH] := lr;
        elif ( type[k] = 2 ) then  ## K rule ##
            for i in [2..len-1] do
                sublr := Subword( lr, i, len-1 );
                pos := Position( sfK, sublr );
                if ( pos = fail ) then Add( sfK, sublr); fi;
            od;
            cK := cK+1;
            wK[cK] := lr;
        else  ## HK rule ##
            for i in [2..Length(lr)-1] do
                sublr := Subword( lr, 2, i );
                pos := Position( pfHK, sublr );
                if ( pos = fail ) then Add( pfHK, sublr); fi;
            od;
            cHK := cHK+1;
            wHK[cHK] := lr; 
        fi;
    od;
    if ( numr <= printmax ) then
        Info( InfoKan, 2, "[wG, wH, wK, wHK] =" );
        Info( InfoKan, 2, wG );
        Info( InfoKan, 2, wH );
        Info( InfoKan, 2, wK );
        Info( InfoKan, 2, wHK );
        Info( InfoKan, 2, "[pfG, pfH, sfK, pfHK] =" );
        Info( InfoKan, 2, pfG );
        Info( InfoKan, 2, pfH );
        Info( InfoKan, 2, sfK );
        Info( InfoKan, 2, pfHK );
    fi;
    Info( InfoKan, 2, "ogens = ", ogens );
    npfG := Length( pfG );
    npfH := Length( pfH );
    nsfK := Length( sfK );
    npfHK := Length( pfHK );
    init := 1;  done := 2;  sink := 3;  shG := 3;
    stateG := shG+1;  shH := shG+npfG; 
    stateH := shH+1;  shK := shH+npfH;
    stateK := shK+1;  shHK := shK+nsfK;  
    stateHK := shHK+1;
    numstates := shG + npfG + npfH + nsfK + npfHK;
    row := ListWithIdenticalEntries( numstates, 0 );
    transmx := List( [1..numgens], i -> ShallowCopy( row ) );
    for j in [1..shH] do  transmx[1][j] := [sink];  od;
    for j in [shH+1..numstates] do  transmx[1][j] := [ ];  od;
    for j in [1..numstates] do  transmx[2][j] := [ ];  od;
    transmx[2][init] := [sink];  
    transmx[2][done] := [sink];
    transmx[2][sink] := [sink];
    ## identify the identity word states ##
    transmx[1][init] := [ stateG, stateH, stateHK ];  
    for i in [3..numgens] do
        for j in [1..shG] do
            transmx[i][j] := [sink];
        od;
        for j in [shG+1..numstates] do
            if ( ugens[i] = false ) then
                transmx[i][j] := [sink];
            else
                transmx[i][j] := [ ];
            fi;
        od;
        transmx[i][init] := [sink];
        transmx[i][sink] := [sink];
    od;
    ## G transitions ##
    for j in [shG+1..shH] do
        transmx[2][j] := [done];
    od;
    for k in [1..npfG] do
        j := k + shG;
        u := pfG[k];
        len := Length(u) + 1;
        for i in [3..numgens] do
            v := u * ogens[i];
            ok := true;
            l := 1;
            while ( ok and ( l <= cG ) ) do
                if IsSuffix( v, rules[posG[l]][1] ) then
                    transmx[i][j] := [sink];
                    ok := false;
                fi;
                l := l+1;
            od;
            if ok then
                for l in [1..len] do
                    p := Subword( v, l, len );
                    pos := Position( pfG, p );
                    if not ( pos = fail ) then
                        pos2 := Position( transmx[i][j], pos );
                        if ( pos2 = fail ) then
                            Add( transmx[i][j], pos+shG );
                        fi;
                    fi;
                od;
            fi;
            if ( transmx[i][j] = [ ] ) then
                Error( "transmx[i][j] = fail" );
            fi;
        od;
    od;
    ## H transitions ##
    for k in [2..npfH] do
        q := pfH[k];  lq := Length(q);
        a := Subword( q, lq, lq );
        i := Position( ogens, a );
        p := Subword( q, 1, lq-1 );
        pos := Position( pfH, p );
        Add( transmx[i][pos+shH], k+shH );
    od;
    for w in wH do
        lw := Length(w);
        a := Subword( w, lw, lw );
        i := Position( ogens, a );
        p := Subword( w, 2, lw-1 );
        pos := Position( pfH, p );
        transmx[i][pos+shH] := [sink];
    od;
    ## K transitions ##
    for k in [2..nsfK] do
        q := sfK[k];  lq := Length(q);
        a := Subword( q, 1, 1 );
        i := Position( ogens, a );
        p := Subword( q, 2, lq );
        pos := Position( sfK, p );
        Add( transmx[i][k+shK], pos+shK );
    od;
    ##  for i in [1..numgens] do transmx[i][shK+1] := [sink]; od;
    transmx[2][stateK] := [sink];
    ## transitions to K-leaves ##
    for w in wK do
        a := Subword( w, 1, 1 );
        p := Subword( w, 2, Length(w)-1 );
        pos := Position( sfK, p );
        i := Position( ogens, a );
        for k in [1..npfG] do
            j := k + shG;
            if ( transmx[i][j] <> [sink] ) then
                Add( transmx[i][j], pos+shK );
            fi;
        od;
    od;
    ## HK transitions ##
    for k in [2..npfHK] do
        q := pfHK[k];  lq := Length(q);
        a := Subword( q, lq, lq );
        i := Position( ogens, a );
        p := Subword( q, 1, lq-1 );
        pos := Position( pfHK, p );
        Add( transmx[i][pos+shHK], k+shHK );
    od;
    for w in wHK do
        p := Subword( w, 2, Length(w)-1 );
        pos := Position( pfHK, p );
        transmx[2][pos+shHK] := [sink];
    od;
    accept := Difference( [1..numstates], [done] );
    nfa := Automaton( "nondet", numstates, alpht, transmx, [init], accept );
    if ( nfa!.states < 51 ) then 
        Info( InfoKan, 2, "initial NFA: ", nfa );
    else
        Info( InfoKan, 2, "initial NFA has ", nfa!.states, " states" );
    fi;
    #?  (12/11/08)  added fixes while awaiting automata.1.12
    Info( InfoKan, 2, "initial NFA has alphabet ", 
                      AlphabetOfAutomatonAsList( nfa ) ); 
    dfa := NFAtoDFA( nfa );
    Info( InfoKan, 2, "DFA of NFA has alphabet ", 
                      AlphabetOfAutomatonAsList( dfa ) ); 
    if ( dfa!.states < 51 ) then 
        Info( InfoKan, 2, "DFA from NFA:", dfa );
    else
        Info( InfoKan, 2, "DFA from NFA has ", dfa!.states, " states" );
    fi;
    cdfa := ComplementDA( dfa );
    Info( InfoKan, 2, "complement of DFA has alphabet ", 
                      AlphabetOfAutomatonAsList( cdfa ) ); 
    if ( cdfa!.states < 51 ) then 
        Info( InfoKan, 2, "complement of DFA:", cdfa );
    else
        Info( InfoKan, 2, "complement of DFA has ", cdfa!.states, " states" );
    fi;
    mdfa := MinimalAutomaton( cdfa ); 
    Info( InfoKan, 2, "minimalized cdfa has alphabet ", 
                      AlphabetOfAutomatonAsList( mdfa ) ); 
    if ( mdfa!.states < 51 ) then 
        Info( InfoKan, 2, "minimal automaton of complement of DFA", mdfa );
    else
        Info( InfoKan, 2, "minimal automaton of complement of DFA has ", 
            mdfa!.states, " states" );
    fi;
    SetIsWordAcceptorOfDoubleCosetRws( rws, true );
    SetRewritingSystemOfWordAcceptor( mdfa, rws );
    SetWordAcceptorOfDoubleCosetRws( rws, mdfa );
    return mdfa;
end );

###########################################################################
##
#M  WordAcceptorOfPartialDoubleCosetRws
##
##  this method requires G to already have a complete rewrite system,
##  generators for H and K should be supplied, plus a limit on #rules
##
InstallMethod( WordAcceptorOfPartialDoubleCosetRws,
    "generic method for a double coset rewriting system", true, 
    [ IsGroup, IsDoubleCosetRewritingSystem ], 0,
function( G, dcrws )

    local  rwsG, gensord, ord, alph, alpht, alph2, perm, perm2, alpht2, 
           rules, numr, fam, order, ogens, ugens, numgens, range, type, 
           a, c, g, i, j, k, l, m, n, p, q, r, s, t, u, v, w, 
           lq, ls, lu, lw, M, genM, numgenM, fM, genfM, m1, m2, oldinit, 
           accG, transG, numstG, numH, numK, numHK, hrules, krules, hkrules,
           id, ok, printmax, fhrules, fkrules, fhkrules,
           numstates, lr, len, sublr, pos, pos2, shG, shH, shK, shHK, 
           pfH, sfK, pfHK, npfH, nsfK, npfHK, 
           row, transmx, accept, nfa, dfa, cdfa, mdfa, 
           init, nonacc, oldsink, sink, done, 
           stateG, stateH, stateK, stateHK;

    if not HasReducedConfluentRewritingSystem( G ) then
        Error( "make a ReducedConfluentRewritingSystem( G ) first" );
    fi;
    rwsG := ReducedConfluentRewritingSystem( G );
    alph := rwsG!.alphabet;
    alpht := ShallowCopy( alph );
    perm := rwsG!.gensperm;
    for i in [1..Length(alph)] do
        alpht[i] := alph[i^perm];
    od;
    Info( InfoKan, 2, "alphabet = ", alph, ", twisted alphabet = ", alpht );
    gensord := OrderingOfRewritingSystem( rwsG );
    ord := OrderingOnGenerators( gensord );
    accG := WordAcceptorOfReducedRws( rwsG );
    Info( InfoKan, 3, "WordAcceptor of group:", accG );
    ##  dcrws := PartialDoubleCosetRewritingSystem
    ##               ( G, genH, genK, gensord, ord, limit );
    rules := Rules( dcrws );
    numr := Length( rules );
    fam := FamilyForRewritingSystem( dcrws );
    order := OrderingOfRewritingSystem( dcrws );
    ogens := OrderingOnGenerators( order );
    Info( InfoKan, 2, "ogens = ", ogens );
    ugens := List( ogens, g -> true );
    id := One( ogens[1] );
    numgens := Length( ogens );
    alph2 := dcrws!.alphabet;
    alpht2 := ShallowCopy( alph2 );
    perm2 := dcrws!.gensperm;
    for i in [3..Length(alph2)] do
        alpht2[i] := alph2[i^perm2];
    od;
    Info( InfoKan, 2, "alphabet = ", alph2, ", twisted alphabet = ", alpht2 );
    M := MonoidOfRewritingSystem( dcrws );
    genM := GeneratorsOfMonoid( M );
    numgenM := Length( genM );
    id := One( genM[1] );
    fM := FreeMonoidOfFpMonoid( M );
    genfM := GeneratorsOfMonoid( fM );
    m1 := genfM[1];  m2 := genfM[2];
    hrules := Filtered( rules, r -> Subword(r[1],1,1) = m1 );
    krules := Filtered( rules, 
        r -> Subword(r[1],Length(r[1]),Length(r[1])) = m2 );
    hkrules := Filtered( krules, r -> Subword(r[1],1,1) = m1 );
    hrules := Difference( hrules, hkrules );
    krules := Difference( krules, hkrules );
    Info( InfoKan, 2, "H-rules, K-rules, HK-rules =" );
    Info( InfoKan, 2, hrules );
    Info( InfoKan, 2, krules );
    Info( InfoKan, 2, hkrules );

    transG := accG!.transitions;
    numstG := accG!.states;
    oldinit := accG!.initial[1];
    numH := Length( hrules );
    numK := Length( krules );
    numHK := Length( hkrules );
    pfH:=[ m1 ];  sfK:=[ m2 ];  pfHK:=[ m1 ];
    for k in [1..numH] do
        lr := hrules[k][1];
        len := Length( lr );
        for i in [1..len-1] do
            sublr := Subword( lr, 1, i );
            pos := Position( pfH, sublr );
            if ( pos = fail ) then Add( pfH, sublr); fi;
        od;
    od;
    for k in [1..numK] do
        lr := krules[k][1];
        len := Length( lr );
        for i in [1..len-1] do
            sublr := Subword( lr, len-i+1, len );
            pos := Position( sfK, sublr );
            if ( pos = fail ) then Add( sfK, sublr); fi;
        od;
    od;
    for k in [1..numHK] do
        lr := hkrules[k][1];
        len := Length( lr );
        for i in [1..len-1] do
            sublr := Subword( lr, 1, i );
            pos := Position( pfHK, sublr );
            if ( pos = fail ) then Add( pfHK, sublr); fi;
        od;
    od;
    pfH := List( pfH, w -> Subword( w, 2, Length(w) ) );
    sfK := List( sfK, w -> Subword( w, 1, Length(w)-1 ) );
    pfHK := List( pfHK, w -> Subword( w, 2, Length(w) ) );
    npfH := Length( pfH );
    nsfK := Length( sfK );
    npfHK := Length( pfHK );
    Info( InfoKan, 2, "[npfH,nsfK,npfHK] = ", [npfH,nsfK,npfHK] );
    Info( InfoKan, 2, pfH );
    Info( InfoKan, 2, sfK );
    Info( InfoKan, 2, pfHK );
    nonacc := Difference( [1..numstG], accG!.accepting );
    if not ( Length( nonacc ) = 1 ) then
        Error( "more than one non-accepting state" );
    fi;
    oldsink := nonacc[1];
    init := 1;  done := 2;  shG := 2;  sink := shG+oldsink;
    stateG := shG+accG!.initial[1];  shH := shG+numstG; 
    stateH := shH+1;  shK := shH+npfH;
    stateK := shK+1;  shHK := shK+nsfK;  
    stateHK := shHK+1;
    numstates := shG + numstG + npfH + nsfK + npfHK;
    row := ListWithIdenticalEntries( numstates, 0 );
    transmx := List( [1..numgens], i -> ShallowCopy( row ) );
    for j in [1..shH] do  transmx[1][j] := [sink];  od;
    for j in [shH+1..numstates] do  transmx[1][j] := [ ];  od;
    for j in [1..numstates] do  transmx[2][j] := [ ];  od;
    transmx[2][init] := [sink];  
    transmx[2][done] := [sink];
    transmx[2][sink] := [sink];
    ## identify the identity word states ##
    transmx[1][init] := [ stateG, stateH, stateHK ];  
    for i in [3..numgens] do
        ##  if ( transG[i-2][oldinit] = oldsink ) then
        ##      Info( InfoKan, 2, "found dud generator", i );
        ##      ugens[i] := false;
        ##  fi;
        for j in [1..shG] do
            transmx[i][j] := [sink];
        od;
        for j in [shG+1..numstates] do
            if ( ugens[i] = false ) then
                transmx[i][j] := [sink];
            else
                transmx[i][j] := [ ];
            fi;
        od;
        transmx[i][init] := [sink];
        transmx[i][sink] := [sink];
    od;
    Info( InfoKan, 2, "ugens = ", ugens );
    Info( InfoKan, 2, "initial transmx", transmx );
    ## G transitions ##
    for i in [1..numgens-2] do
        for j in [1..numstG] do
            transmx[i+2][j+shG] := [ transG[i][j]+shG ];
        od;
    od;
    for j in [1..numstG] do
        transmx[2][j+shG] := [done];
    od;
    transmx[2][oldsink+shG] := [sink];
    Info( InfoKan, 3, "*** H-transitions:" );
    ## H transitions ##
    for k in [2..npfH] do
        q := pfH[k];  lq := Length(q);
        a := Subword( q, lq, lq );
        i := Position( ogens, a );
        if ( lq = 1 ) then
            pos := 1;
        else
            p := Subword( q, 1, lq-1 );
            pos := Position( pfH, p );
        fi;
        Info( InfoKan, 3, "[q,a,pos,i,pos+shH,k+shH] = ",
            [q,a,pos,i,pos+shH,k+shH] );
        Add( transmx[i][pos+shH], k+shH );
    od;
    Info( InfoKan, 3, "*** H-rules:" );
    for r in hrules do
        w := Subword( r[1], 2, Length(r[1]) );
        lw := Length(w);
        a := Subword( w, lw, lw );
        i := Position( ogens, a );
        if ( lw = 1 ) then
            pos := 1;
        else
            p := Subword( w, 1, lw-1 );
            pos := Position( pfH, p );
        fi;
        transmx[i][pos+shH] := [sink];
    od;
    ## K transitions ##
    Info( InfoKan, 3, "*** K-transitions:" );
    for k in [2..nsfK] do
        q := sfK[k];  lq := Length(q);
        a := Subword( q, 1, 1 );
        i := Position( ogens, a );
        if ( lq = 1 ) then
            pos := 1;
        else
            p := Subword( q, 2, lq );
            pos := Position( sfK, p );
        fi;
        Info( InfoKan, 3, "[q,a,pos,i,k+shK,pos+shK] = ",
            [q,a,pos,i,k+shK,pos+shK] );
        Add( transmx[i][k+shK], pos+shK );
    od;
    ##  for i in [1..numgens] do transmx[i][shK+1] := [sink]; od;
    transmx[2][stateK] := [sink];
    ## transitions to K-leaves ##
    Info( InfoKan, 3, "*** K-rules:" );
    for r in krules do
        w := Subword( r[1], 1, Length(r[1])-1 );
        lw := Length( w );
        a := Subword( w, 1, 1 );
        i := Position( ogens, a );
        if ( lw = 1 ) then
            pos := 1;
        else
            p := Subword( w, 2, lw );
            pos := Position( sfK, p );
        fi;
        for k in [1..numstG] do
            j := k + shG;
            if ( transmx[i][j] <> [sink] ) then
                Info( InfoKan, 3, "adding [i,j,pos+shK] = ", [i,j,pos+shK] );
                Add( transmx[i][j], pos+shK );
            fi;
        od;
    od;
    ## HK transitions ##
    Info( InfoKan, 3, "*** HK-transitions:" );
    for k in [2..npfHK] do
        q := pfHK[k];  lq := Length(q);
        a := Subword( q, lq, lq );
        i := Position( ogens, a );
        if ( lq = 1 ) then
            pos := 1;
        else
            p := Subword( q, 1, lq-1 );
            pos := Position( pfHK, p );
        fi;
        Info( InfoKan, 3, "[q,a,pos,i,pos+shHK,k+shHK] = ",
            [q,a,pos,i,pos+shHK,k+shHK] );
        Add( transmx[i][pos+shHK], k+shHK );
    od;
    Info( InfoKan, 3, "*** HK-rules:" );
    for r in hkrules do
        pos := Position( pfHK, Subword( r[1], 2, Length(r[1])-1 ) );
        transmx[2][pos+shHK] := [sink];
    od;

    accept := Difference( [1..numstates], [done] );
    nfa := Automaton( "nondet", numstates, alpht2, transmx, [init], accept );
    Info( InfoKan, 2, "initial NFA:" );
    Info( InfoKan, 2, nfa );
    #?  (12/11/08)  added fixes while awaiting automata.1.12
    dfa := NFAtoDFA( nfa );
    Info( InfoKan, 2, "DFA from NFA:" );
    Info( InfoKan, 2, dfa );
    cdfa := ComplementDA( dfa );
    mdfa := MinimalAutomaton( cdfa );
    return mdfa;
end );

#############################################################################
##
#M  DoubleCosetsAutomaton
#M  RightCosetsAutomaton 
##
##  should use these to make DoubleCosetsNC and RightCosetsNC: these were 
##  the original names, but changed 04/04/06 to fix a conflict with Gpd
##
InstallMethod( DoubleCosetsAutomaton, "for an fp-group with a rws", true, 
    [ IsFpGroup and HasReducedConfluentRewritingSystem, IsGroup, IsGroup ], 0,
function( G, U, V )
    local rws, dcrws;
    Info( InfoKan, 2, "in first Kan version of DoubleCosetsAutomaton" );
    rws := ReducedConfluentRewritingSystem( G, 0 );
    dcrws := DoubleCosetRewritingSystem( G, U, V, rws );
    return WordAcceptorOfDoubleCosetRws( dcrws );
end );

InstallMethod( DoubleCosetsAutomaton, "for an infinite fp-group", true, 
    [ IsFpGroup, IsGroup, IsGroup ], 0,
function( G, U, V )
    local genG, len, i, L, Aa, alph, genU, genV, rws, dcrws, dcwa;
    if IsFinite( G ) then
        TryNextMethod();
    fi;
    Info( InfoKan, 2, "in second Kan version of DoubleCosetsAutomaton" );
    genG := GeneratorsOfGroup( G );
    len := Length( genG );
    L := [1..2*len];
    for i in [1..len] do
        L[2*i] := 2*i-1;
        L[2*i-1] := 2*i;
    od;
    rws := ReducedConfluentRewritingSystem( G, L, "shortlex", 0 );
    if ( rws = fail ) then
        TryNextMethod();
    fi;
    Aa := "Aa";
    alph := "Aa";
    for i in [2..len] do
        alph := Concatenation( alph, Aa );
    od;
    for i in [3..2*len] do
        alph[i] := CHAR_INT( INT_CHAR(alph[i])+1 );
    od;
    rws := ReducedConfluentRewritingSystem( G );
    rws!.alphabet := alph; 
    genU := GeneratorsOfGroup( U );
    genV := GeneratorsOfGroup( V );
    dcrws := DoubleCosetRewritingSystem( G, U, V, rws );
    dcwa := WordAcceptorOfDoubleCosetRws( dcrws );
    return dcwa;
end );

InstallMethod( RightCosetsAutomaton, "for an fp-group with rewriting system", 
    true, [ IsFpGroup and HasReducedConfluentRewritingSystem, IsGroup ], 0,
function( G, V )
    local U, rws, dcrws, dcwa;
    Info( InfoKan, 2, "in first Kan version of RightCosetsAutomaton" );
    U := TrivialSubgroup( G );
    rws := ReducedConfluentRewritingSystem( G, 0 );
    dcrws := DoubleCosetRewritingSystem( G, U, V, rws );
    dcwa := WordAcceptorOfDoubleCosetRws( dcrws );
    return dcwa;
end );

InstallMethod( RightCosetsAutomaton, "for an infinite fp-group", true, 
    [ IsFpGroup, IsGroup ], 0,
function( G, V )
    local  one;
    if IsFinite( G ) then
        TryNextMethod();
    fi;
    Info( InfoKan, 2, "in second Kan version of RightCosetsAutomaton" );
    one := One( G );
    return DoubleCosetsAutomaton( G, Subgroup(G,[one]), V );
end );

#############################################################################
## 
#E  dcrws.gi . . . .  . . . . . . . . . . . . . . . . . . . . . . . ends here 
## 

[ Verzeichnis aufwärts0.74unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]