fga/init.g 0000644 0003717 0003717 00000001344 13275267465 014161 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W init.g FGA package Christian Sievers
##
## The init file for the FGA package
##
#Y 2003 - 2012
##
ReadPackage( "FGA", "lib/util.gd" );
ReadPackage( "FGA", "lib/Iterated.gd" );
ReadPackage( "FGA", "lib/Autom.gd" );
ReadPackage( "FGA", "lib/FreeGrps.gd" );
ReadPackage( "FGA", "lib/ReprAct.gd" );
ReadPackage( "FGA", "lib/Normal.gd" );
ReadPackage( "FGA", "lib/ExtAutom.gd" );
ReadPackage( "FGA", "lib/Hom.gd" );
ReadPackage( "FGA", "lib/AutGrp.gd" );
ReadPackage( "FGA", "lib/Intsect.gd" );
ReadPackage( "FGA", "lib/Whitehd.gd" );
#############################################################################
##
#E
fga/read.g 0000644 0003717 0003717 00000001534 13275267465 014132 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W read.g FGA package Christian Sievers
##
## The read file for the FGA package
##
#Y 2003 - 2012
##
ReadPackage( "FGA", "lib/util.gi" );
ReadPackage( "FGA", "lib/Iterated.gi" );
ReadPackage( "FGA", "lib/Autom.gi" );
ReadPackage( "FGA", "lib/FreeGrps.gi" );
ReadPackage( "FGA", "lib/ReprAct.gi" );
ReadPackage( "FGA", "lib/Normal.gi" );
ReadPackage( "FGA", "lib/Central.gi" );
ReadPackage( "FGA", "lib/Index.gi" );
ReadPackage( "FGA", "lib/ExtAutom.gi");
ReadPackage( "FGA", "lib/Hom.gi" );
ReadPackage( "FGA", "lib/AutGrp.gi" );
ReadPackage( "FGA", "lib/Intsect.gi" );
ReadPackage( "FGA", "lib/ReprActT.gi" );
ReadPackage( "FGA", "lib/Whitehd.gi" );
#############################################################################
##
#E
fga/PackageInfo.g 0000664 0003717 0003717 00000011745 13275267465 015375 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W PackageInfo.g FGA package Christian Sievers
##
## The package info file for the FGA package
##
#Y 2003 - 2018
##
SetPackageInfo( rec(
PackageName := "FGA",
Subtitle := "Free Group Algorithms",
Version := "1.4.0",
# dd/mm/yyyy
Date := "23/03/2018",
Persons := [
rec(
LastName := "Sievers",
FirstNames := "Christian",
IsAuthor := true,
IsMaintainer := true,
Email := "c.sievers@tu-bs.de",
# WWWHome := "",
# PostalAddress := Concatenation(
# [ "Christian Sievers\n",
# "Fachbereich Mathematik und Informatik\n",
# "Institut Computational Mathematics\n",
# "Technische Universit\"at Braunschweig\n",
# "Pockelsstr. 14\n",
# "D-38106 Braunschweig,\n",
# "Germany" ]),
# Place := "Braunschweig",
# Institution := "TU Braunschweig"
) ],
Status := "accepted",
CommunicatedBy := "Edmund Robertson (St. Andrews)",
AcceptDate := "05/2005",
## For a central overview of all packages and a collection of all package
## archives it is necessary to have two files accessible which should be
## contained in each package:
## - A README file, containing a short abstract about the package
## content and installation instructions.
## - The file you are currently reading or editing!
## You must specify URLs for these two files, these allow to automate
## the updating of package information on the GAP Website, and inclusion
## and updating of the package in the GAP distribution.
#
PackageWWWHome := "http://www.icm.tu-bs.de/ag_algebra/software/FGA/",
ArchiveFormats := ".tar.gz",
ArchiveURL := Concatenation( ~.PackageWWWHome, "FGA-", ~.Version ),
README_URL := Concatenation( ~.PackageWWWHome, "README" ),
PackageInfoURL := Concatenation( ~.PackageWWWHome, "PackageInfo.g" ),
SourceRepository := rec(
Type := "git",
URL := "https://github.com/chsievers/fga"
),
IssueTrackerURL := Concatenation( ~.SourceRepository.URL, "/issues" ),
## Here you must provide a short abstract explaining the package content
## in HTML format (used on the package overview Web page) and an URL
## for a Webpage with more detailed information about the package
## (not more than a few lines, less is ok):
## Please, use 'GAP' and
## 'MyPKG' for specifing package names.
##
AbstractHTML :=
"The FGA package installs methods for \
computations with finitely generated subgroups of free groups and \
provides a presentation for their automorphism groups.",
## On the GAP Website there is an online version of all manuals in the
## GAP distribution. To handle the documentation of a package it is
## necessary to have:
## - an archive containing the package documentation (in at least one
## of HTML or PDF-format, preferably both formats)
## - the start file of the HTML documentation (if provided), *relative to
## package root*
## - the PDF-file (if provided) *relative to the package root*
## For links to other package manuals or the GAP manuals one can assume
## relative paths as in a standard GAP installation.
## Also, provide the information about autoloadability of the documentation.
##
## Please, don't include unnecessary files (.log, .aux, .dvi, .ps, ...) in
## the provided documentation archive.
##
# in case of several help books give a list of such records here:
PackageDoc := rec(
# use same as in GAP
BookName := "FGA",
# format/extension can be one of .zoo, .tar.gz, .tar.bz2, -win.zip
# Archive := "",
ArchiveURLSubset := ["doc", "htm"],
HTMLStart := "htm/chapters.htm",
PDFFile := "doc/manual.pdf",
# the path to the .six file used by GAP's help system
SixFile := "doc/manual.six",
# a longer title of the book, this together with the book name should
# fit on a single text line (appears with the '?books' command in GAP)
LongTitle := "Free Group Algorithms",
# Should this help book be autoloaded when GAP starts up? This should
# usually be 'true', otherwise say 'false'.
Autoload := true
),
## Are there restrictions on the operating system for this package? Or does
## the package need other packages to be available?
Dependencies := rec(
GAP := ">=4.8",
NeededOtherPackages := [],
SuggestedOtherPackages := [],
ExternalConditions := []
),
AvailabilityTest := ReturnTrue,
#BannerString := ""
Autoload := true,
## *Optional*, but recommended: path relative to package root to a file which
## contains as many tests of the package functionality as sensible.
TestFile := "tst/testall.g",
Keywords := ["free groups", "inverse finite automata",
"basic coset enumeration",
"finite presentation of the automorphism group of a free group"]
));
#############################################################################
##
#E
fga/COPYING 0000644 0003717 0003717 00000043706 13275267465 014111 0 ustar gap-jenkins gap-jenkins The FGA package is free software; you can redistribute and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
Version 2 of the GNU General Public License follows.
=====================================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
fga/README 0000664 0003717 0003717 00000002274 13275267465 013733 0 ustar gap-jenkins gap-jenkins
FGA
Free Group Algorithms
A GAP 4 package
Contents:
---------
The FGA package provides methods for computations with finitely
generated subgroups of free groups.
It allows you to (constructively) test membership and conjugacy,
and to compute free generators, the rank, the index, normalizers,
centralizers, and intersections where the groups involved are finitely
generated subgroups of free groups.
In addition, it provides generators and a finite presentation for the
automorphism group of a finitely generated free group and allows to
write any such automorphism as word in these generators.
Requirements:
-------------
FGA is written for GAP version 4.8 or later.
It does not use external programs and does not depend on
system specifics.
License:
--------
The FGA package is free software and can be redistributed and/or
modified under the terms of the GNU General Public License.
For details see the file COPYING.
Installation:
-------------
The installation follows standard GAP rules.
So the normal way to install is to unpack the archive in the `pkg'
directory, which will create an `fga' subdirectory.
Enjoy!
fga/lib/Normal.gi 0000644 0003717 0003717 00000006115 13275267465 015366 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Normal.gi FGA package Christian Sievers
##
## Method installations for normalizers in free groups
##
#Y 2003 - 2012
##
#############################################################################
##
#M NormalizerInWholeGroup( )
##
## returns the normalizer of in the group of the whole family
##
InstallMethod( NormalizerInWholeGroup,
[ CanComputeWithInverseAutomaton ],
function(G)
local found, A, reducedPos, states, s, u, ur, i, gens, redgenwords, fam,
interesting, conjinvLetterRep, N;
if IsTrivial( G ) then
N := Group( FreeGeneratorsOfWholeGroup( G ) );
SetIsWholeFamily( N, true );
return N;
fi;
found := false;
A := FreeGroupAutomaton(G);
fam := ElementsFamily(FamilyObj(G));
gens := ShallowCopy(FreeGeneratorsOfGroup(G));
redgenwords := List(gens, LetterRepAssocWord);
reducedPos := FGA_reducedPos(A);
conjinvLetterRep := redgenwords[1]{[1..reducedPos-1]};
redgenwords := List(redgenwords,
w -> w{[reducedPos .. Length(w)-reducedPos+1]});
states := FGA_States(FreeGroupAutomaton(G));
interesting := ReturnTrue;
for i in [reducedPos+1 .. Length(states)] do
s := states[i];
u := FGA_repr(s);
ur := u{[reducedPos..Length(u)]};
if interesting(ur) and
ForAll(redgenwords,w->FGA_Check(s,w)) then
# generator found
if found then # this was not the first extra generator
# Print("inserting\n");
else
# Print("inserting first\n");
A := FGA_FromGeneratorsLetterRep(redgenwords, G);
interesting := w -> not FGA_Check(A!.initial,w);
found := true;
fi;
FGA_AutomInsertGeneratorLetterRep(A, ur);
# Add(gens, AssocWordByLetterRep(fam, u));
fi;
od;
if found then
s := FGA_newstate();
FGA_coincidence(Iterated(conjinvLetterRep,
FGA_define,
s ),
A!.initial );
A!.initial := FGA_find(s);
A!.terminal := A!.initial;
MakeImmutable(A);
N := AsGroup(A);
else
N := G;
fi;
return N;
end );
#############################################################################
##
#M NormalizerOp( , )
##
InstallMethod( NormalizerOp,
"for a subgroup of a free group",
IsIdenticalObj,
[ CanComputeWithInverseAutomaton, CanComputeWithInverseAutomaton ],
function(F,G)
return Intersection( F, NormalizerInWholeGroup( G ) );
end );
#############################################################################
##
#M NormalizerOp( , )
##
InstallMethod( NormalizerOp,
"for an element in a free group",
IsCollsElms,
[ IsFreeGroup, IsElementOfFreeGroup ],
CentralizerOp );
#############################################################################
##
#E
fga/lib/Normal.gd 0000644 0003717 0003717 00000001132 13275267465 015353 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Normal.gd FGA package Christian Sievers
##
## The declaration file for the computation of normalizers in free groups
##
#Y 2003 - 2012
##
#############################################################################
##
#A NormalizerInWholeGroup( )
##
## returns the normalizer of in the group of the whole family
##
DeclareAttribute( "NormalizerInWholeGroup", IsFreeGroup );
#############################################################################
##
#E
fga/lib/ExtAutom.gi 0000644 0003717 0003717 00000016064 13275267465 015710 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W ExtAutom.gi FGA package Christian Sievers
##
## Methods to create and compute with extended inverse automata
##
#Y 2003 - 2016
##
InstallValue( FGA_FreeGroupForGenerators, FreeGroup(infinity) );
InstallValue( FGA_One, One(FGA_FreeGroupForGenerators) );
InstallGlobalFunction( FGA_newstateX,
function()
return (rec (delta:=[], deltainv:=[], sndsig:=[], sndsiginv:=[]));
end );
InstallGlobalFunction( FGA_connectposX,
function(s1, s2, g, sndsig, sndsiginv)
s1.delta[g] := s2;
s2.deltainv[g] := s1;
s1.sndsig[g] := sndsig;
s2.sndsiginv[g] := sndsiginv;
end );
InstallGlobalFunction( FGA_connectX,
function(s1, s2, g, sndsig)
if g>0 then
FGA_connectposX(s1, s2, g, sndsig, sndsig^-1);
else
FGA_connectposX(s2, s1, -g, sndsig^-1, sndsig);
fi;
end );
InstallGlobalFunction( FGA_defineX,
function(state, gen)
local nstate;
nstate := FGA_newstateX();
FGA_connectX(state, nstate, gen, FGA_One);
# nstate.W := state.W * gen
return nstate;
end );
# active
InstallGlobalFunction( FGA_findX,
function(s)
local sndsig;
sndsig := FGA_One;
while IsBound(s.isnow) do
sndsig := sndsig * s.sndcoinc;
s := s.isnow;
od;
return rec(state:=s, sndcoinc:=sndsig);
# todo: path compression
end );
InstallGlobalFunction( FGA_mergeX,
function(s1, A, s2, B, Q)
local s, C;
s1 := FGA_findX(s1);
s2 := FGA_findX(s2);
if IsNotIdenticalObj(s1.state,s2.state) then
if IsBound(s2.state.isinitial) then
# don't mess with the initial state
s := s1; s1 := s2; s2 := s;
C := A; A := B; B := C;
fi;
s2.state.isnow := s1.state;
s2.state.sndcoinc := (B*s2.sndcoinc)^-1*A*s1.sndcoinc;
Add(Q,s2.state);
fi;
end );
InstallGlobalFunction( FGA_coincidenceX,
function(s1, A, s2, B)
local Q, s, g, s0, s01, delta, deltainv;
Q := [];
FGA_mergeX(s1, A, s2, B, Q);
for s in Q do
delta := ShallowCopy(s.delta);
for g in BoundPositions(delta) do
Unbind(delta[g].deltainv[g]);
od;
deltainv := ShallowCopy(s.deltainv);
for g in BoundPositions(deltainv) do
Unbind(deltainv[g].delta[g]);
od;
for g in BoundPositions(delta) do
s0 := FGA_findX(s);
s01 := FGA_findX(delta[g]);
if IsBound(s0.state.delta[g]) then
FGA_mergeX(s01.state, s.sndsig[g]*s01.sndcoinc,
s0.state.delta[g], s0.sndcoinc*s0.state.sndsig[g], Q);
elif IsBound(s01.state.deltainv[g]) then
FGA_mergeX(s0.state, s.sndsig[g]^-1*s0.sndcoinc,
s01.state.deltainv[g],
s01.sndcoinc*s01.state.sndsiginv[g], Q);
else
FGA_connectX(s0.state, s01.state, g,
s0.sndcoinc^-1*s.sndsig[g]*s01.sndcoinc);
fi;
od;
for g in BoundPositions(deltainv) do
s0 := FGA_findX(s);
s01 := FGA_findX(deltainv[g]);
if IsBound(s0.state.deltainv[g]) then
FGA_mergeX(s01.state, s.sndsiginv[g]*s01.sndcoinc,
s0.state.deltainv[g], s0.sndcoinc*s0.state.sndsiginv[g], Q);
elif IsBound(s01.state.delta[g]) then
FGA_mergeX(s0.state, s.sndsiginv[g]^-1*s0.sndcoinc,
s01.state.delta[g], s01.sndcoinc*s01.state.sndsig[g], Q);
else
FGA_connectX(s01.state, s0.state, g,
s01.sndcoinc^-1*s.sndsiginv[g]^-1*s0.sndcoinc);
fi;
od;
od;
end );
InstallGlobalFunction( FGA_atfX,
function(l, lx, p)
if IsBound(l[p]) then
return rec(state:=l[p], sndsig:=lx[p]);
else
return fail;
fi;
end );
InstallGlobalFunction( FGA_deltaX,
function(state, gen)
if gen>0 then
return FGA_atfX(state.delta, state.sndsig, gen);
else
return FGA_atfX(state.deltainv, state.sndsiginv, -gen);
fi;
end );
InstallGlobalFunction( FGA_stepX,
function(r, gen)
local res;
res := FGA_deltaX(r.state, gen);
if res <> fail then
res.sndsig := r.sndsig * res.sndsig;
fi;
return res;
end );
InstallGlobalFunction( FGA_deltasX,
function(state, genlist)
return IteratedF(genlist, FGA_stepX, rec(state:=state, sndsig:=FGA_One));
end );
InstallGlobalFunction( FGA_traceX,
function(s,w)
local i, s1;
s := rec(state := s, sndsig := FGA_One);
s1 := s;
i := 1;
while i <= Length(w) and s1 <> fail do
s := s1;
s1 := FGA_stepX(s, w[i]);
i := i+1;
od;
if s1 = fail then
return rec(state:=s.state, index:=i-1, sndsig:=s.sndsig);
else
return rec(state:=s1.state, index:=i, sndsig:=s1.sndsig);
fi;
end );
InstallGlobalFunction( FGA_backtraceX,
function(s,w,j)
local i, s1;
s := rec(state:=s, sndsig := FGA_One);
s1 := s;
i := Length(w);
while i >= j and s1 <> fail do
s := s1;
s1 := FGA_stepX(s, -w[i]);
i := i-1;
od;
if s1 = fail then
return rec(state:=s.state, index:=i+1, sndsig:=s.sndsig );
else
return rec(state:=s1.state, index:=i, sndsig:=s1.sndsig);
fi;
end );
InstallGlobalFunction( FGA_insertgeneratorX,
function(s, g, sndgen)
local i, t, bt, s1, s2;
t := FGA_traceX(s, g);
bt := FGA_backtraceX(s, g, t.index);
s1 := t.state;
s2 := bt.state;
if t.index > bt.index then # trace complete
FGA_coincidenceX(s1, sndgen^-1*t.sndsig, s2, bt.sndsig);
else
if IsIdenticalObj(s1, s2) then
while g[t.index] = -g[bt.index] do
s1 := FGA_defineX(s1, g[t.index]);
t.index := t.index+1;
bt.index := bt.index - 1;
od;
s2 := s1;
fi;
for i in [t.index .. bt.index-1] do
s1 := FGA_defineX(s1, g[i]);
od;
FGA_connectX(s1, s2, g[bt.index], t.sndsig^-1*sndgen*bt.sndsig);
fi;
return FGA_find(s);
end );
InstallGlobalFunction( FGA_fromgeneratorsX,
function(gens)
local gen, i, autom;
i := 1;
autom := FGA_newstateX();
autom.isinitial := true;
for gen in gens do
autom := FGA_insertgeneratorX(autom, gen,
FGA_FreeGroupForGenerators.(i) );
i := i+1;
od;
return autom;
end );
InstallGlobalFunction( FGA_FromGroupWithGeneratorsX,
function( G )
return FGA_fromgeneratorsX( List ( GeneratorsOfGroup ( G ),
LetterRepAssocWord ));
end );
InstallGlobalFunction( FGA_AsWordLetterRepInGenerators,
function( w, A)
local res;
res := FGA_deltasX( A, w );
if res = fail or IsNotIdenticalObj( res.state, A ) then
return fail;
else
return LetterRepAssocWord( res.sndsig );
fi;
end );
#############################################################################
##
#E
fga/lib/Autom.gd 0000664 0003717 0003717 00000003316 13275267465 015220 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Autom.gd FGA package Christian Sievers
##
## Declarations for methods to create and compute with inverse automata
##
#Y 2003 - 2018
##
DeclareCategory( "IsInvAutomatonCategory", IsObject);
DeclareOperation( "TrivialInvAutomaton", [ IsFreeGroup ]);
DeclareOperation( "InvAutomatonInsertGenerator",
[ IsInvAutomatonCategory and IsMutable, IsElementOfFreeGroup ] );
DeclareGlobalFunction( "FGA_newstate" );
DeclareGlobalFunction( "FGA_connectpos" );
DeclareGlobalFunction( "FGA_connect" );
DeclareGlobalFunction( "FGA_define" );
DeclareGlobalFunction( "FGA_find" );
DeclareGlobalFunction( "FGA_merge" );
DeclareGlobalFunction( "FGA_coincidence" );
DeclareGlobalFunction( "FGA_delta" );
DeclareGlobalFunction( "FGA_deltas" );
DeclareGlobalFunction( "FGA_TmpState" );
DeclareGlobalFunction( "FGA_trace" );
DeclareGlobalFunction( "FGA_backtrace" );
DeclareGlobalFunction( "FGA_InsertGenerator" );
DeclareGlobalFunction( "FGA_AutomInsertGeneratorLetterRep" );
DeclareGlobalFunction( "FGA_InsertGeneratorLetterRep" );
DeclareGlobalFunction( "FGA_FromGroupWithGenerators" );
DeclareGlobalFunction( "FGA_FromGeneratorsLetterRep");
DeclareGlobalFunction( "FGA_Check" );
DeclareGlobalFunction( "FGA_FindGeneratorsAndStates" );
DeclareGlobalFunction( "FGA_repr" );
DeclareGlobalFunction( "FGA_initial" );
DeclareGlobalFunction( "FGA_reducedPos" );
DeclareGlobalFunction( "FGA_Index" );
DeclareGlobalFunction( "FGA_AsWordLetterRepInFreeGenerators" );
DeclareGlobalFunction( "FGA_States" );
DeclareGlobalFunction( "FGA_GeneratorsLetterRep" );
#############################################################################
##
#E
fga/lib/Central.gi 0000644 0003717 0003717 00000004140 13275267465 015522 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Central.gi FGA package Christian Sievers
##
## Method installations for centralizers in free groups
##
#Y 2003 - 2012
##
#############################################################################
##
#M CentralizersOp( , )
##
InstallMethod( CentralizerOp,
"for an element in a free group",
IsCollsElms,
[ IsFreeGroup, IsElementOfFreeGroup ],
function(G,g)
local i, l, len, div, w, f, p, pp, c;
if g=One(G) then
return G;
fi;
w := LetterRepAssocWord(g);
i := 1;
l := Length(w);
while w[i] = -w[l] do
i := i+1;
l := l-1;
od;
len := l-i+1;
pp := PrimePowersInt(len);
f := 1;
while f 0 and
w{[i..i+len-(len/div)-1]} = w{[i+len/div..i+len-1]} do
len := len/div;
p := p-1;
od;
f := f+2;
od;
# return Group(AssocWordByLetterRep(FamilyObj(g), w{[i..i+len-1]})^
# AssocWordByLetterRep(FamilyObj(g), w{[l+1..Length(w)]}) );
c := FindPowLetterRep(G, w{[1..i-1]}, w{[i..i+len-1]},
w{[l+1..Length(w)]} );
if c = fail then
return TrivialSubgroup(G);
else
return Group(c);
fi;
end );
#############################################################################
##
#M CentralizerOp( , )
##
InstallMethod( CentralizerOp,
"for a subgroup of a free group",
IsIdenticalObj,
[ IsFreeGroup, IsFreeGroup ],
function(F,G)
local r;
r := RankOfFreeGroup(G);
if r >= 2 then
return TrivialSubgroup(F);
elif r = 1 then
return Centralizer(F, FreeGeneratorsOfGroup(G)[1]);
else # (r = 0)
return F;
fi;
end );
#############################################################################
##
#E
fga/lib/AutGrp.gi 0000644 0003717 0003717 00000032637 13275267465 015350 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W AutGrp.gi FGA package Christian Sievers
##
## Methods for automorphism groups of free groups
##
#Y 2003 - 2012
##
#############################################################################
##
#M AutomorphismGroup( )
##
InstallMethod( AutomorphismGroup,
"for free groups",
[ CanComputeWithInverseAutomaton ],
function( G )
local n, aut;
n := RankOfFreeGroup( G );
if n = 0 then
aut := AsGroup( [ IdentityMapping ( G ) ] );
elif n = 1 then
aut := Group( FreeGroupAutomorphismsGeneratorO( G ) );
SetSize( aut, 2 );
elif n = 2 then
aut := Group( FreeGroupAutomorphismsGeneratorO( G ),
FreeGroupAutomorphismsGeneratorP( G ),
FreeGroupAutomorphismsGeneratorU( G ) );
elif n = 3 then
aut := Group( FreeGroupAutomorphismsGeneratorS( G ),
FreeGroupAutomorphismsGeneratorT( G ),
FreeGroupAutomorphismsGeneratorU( G ) );
elif IsEvenInt( n ) then
aut := Group( FreeGroupAutomorphismsGeneratorQ( G ),
FreeGroupAutomorphismsGeneratorR( G ) );
else # n > 3, odd
aut := Group( FreeGroupAutomorphismsGeneratorS( G ),
FreeGroupAutomorphismsGeneratorR( G ) );
fi;
SetIsFinite( aut, n <= 1 );
SetFilterObj( aut, IsAutomorphismGroupOfFreeGroup );
return aut;
end );
#############################################################################
##
#M \in( , )
##
## tests whether is in .
##
## Code contributed by Max Horn.
InstallMethod( \in,
"for automorphism groups of free groups",
[ IsGroupGeneralMapping, IsAutomorphismGroupOfFreeGroup ],
function( hom, aut )
local G;
G := AutomorphismDomain( aut );
return Source( hom ) = G and Range( hom ) = G and IsBijective( hom );
end );
#############################################################################
##
#M IsomorphismFpGroup( )
##
## returns an isomorphism from an automorphism group of a free group
## to a finitely presented group.
##
## The presentation follows Bernhard Neumann (see ../doc/manual.bib)
## Numbers in the comments refer to the equation numbers in that paper.
##
InstallMethod( IsomorphismFpGroup,
"for automorphism groups of free groups",
[ IsAutomorphismGroupOfFreeGroup ],
function( aut )
local n, f, fp, O, P, U, S, T, Q, R, rels, moreRels,
o, p, u, s, t, q, r, iso, isoinv;
n := RankOfFreeGroup( AutomorphismDomain ( aut ));
if n = 0 then
fp := FreeGroup( 0 );
iso := aut -> One( fp );
elif n = 1 then
f := FreeGroup( "O" );
O := f.1;
rels := [ O^2 ]; # 6a
fp := f / rels;
o := fp.1;
iso := aut -> o ^ (Order(aut) - 1);
elif n = 2 then
f := FreeGroup( "O", "P", "U" );
O := f.1; P := f.2; U := f.3;
rels := [ P^2 # 5a
, O^2 # 6a
, (O*P)^4 # 8a
, Comm( U, O*U*O ) # 7e
, (P*O*P*U)^2 # 7i
, (U*P*O)^3 # 8b
];
fp := f / rels;
o := fp.1; p := fp.2; u := fp.3;
iso := FGA_CurryAutToPQOU( p, p, o, u); # Q=P
elif n = 3 then
f := FreeGroup( "S", "T", "U" );
S := f.1; T := f.2; U := f.3;
rels := [ (S^5*T^-1)^2 # 19a
, T^-1*S*T^2*S^8*T^-1*S*T^2*S^-4 # 19b
, (S^4*T^-1*S*T^-1)^2 # 19c
, T^4 # 19d
, Comm( U, S^2*T^-1*S*T^-1*S^2 ) # 19e
, Comm( U, S^-2*T^-1*S*T^-1*U*S^-2*T^-1*S*T^-1) # 19f
# wrong: Comm( U, S^2*T^-1*S*T*S*T^-1*U*T*S^-1*T^-1*S^-1*T*S^2 ) # 19g
, Comm( U, S^-2*T^-1*S*T*S*T^-1*U*
T*S^-1*T^-1*S^-1*T*S^2 ) # 19g corrected
, Comm( U, T^-1*S*T^2*U*T^-1*S*T^2 ) # 19h
, S^-2*T^-1*S*T^2*S^2*U*S^2*T^-1*S*T^2*S^2*
U*S^-2*U*S^2*U^-1*S^-2*U^-1 # 19i
, (S^-2*T^-1*S*T*U)^2 # 19j
, (U*T)^3 # 19k
];
fp := f / rels;
s := fp.1; t := fp.2; u := fp.3;
iso := FGA_CurryAutToPQOU( t*s^3*(s*t^-1)^2 # 16c
, s^4 # 16a
, s^3*(s*t^-1)^2 # 16b
, u
);
elif IsEvenInt(n) then
f := FreeGroup( "Q", "R" );
Q := f.1; R := f.2;
rels := [ (R^3*(Q*R^3)^(n-1))^2 # 22a
, (Q*R^3)^(2*(n-1)) # 22d
, Q^n # 22e
, Comm( (Q*R^3)^(n-1),
Q^-1*R^3*(Q*R^3)^(n-1)*Q ) # 22f
, Comm( Q^-2*R^4*Q^2*R^-3,
Q*R^-3*Q^-1*R^-3*Q ) # 22h
, Comm( R^4, (Q*R^3)^(n-1) ) # 22j
, Comm( R^4, Q^-2*R^4*Q^2 ) # 22k
, Comm( Q^-2*R^4*Q^2*R^-3,
(Q*R^3)^(n-1)*Q^-2*R^4*Q^2*R^-3*(Q*R^3)^(n-1) ) # 22l
, Comm( Q^-2*R^4*Q^2*R^-3,
R^-3*Q^-1*Q^-2*R^4*Q^2*R^-3*Q*R^3 ) # 22m
, Comm( Q^-2*R^4*Q^2*R^-3,
R^-3*Q^-1*R^-3*(Q*R^3)^n*Q^-2*R^4*
Q^2*R^-3*(Q*R^3)^-n*R^3*Q*R^3 ) # 22n
, (Q*R^3)^-n*Q^-2*R^4*Q^2*R^-3*(Q*R^3)^n*
Q^-3*R^4*Q^2*R^-3*Q^-1*R^4*Q^2*R^-3*
Q^-1*R^3*Q^-2*R^-4*Q^3*R^3*Q^-2*R^-4*Q^2 # 22o
, (R^3*(Q*R^3)^(n-1)*Q^-2*R^4*Q^2)^2 # 22p
, R^12 # 22q
];
# finally the relations 22c:
moreRels := List( [ 2 .. n/2 ],
i -> Comm( R^3*(Q*R^3)^(n-1),
Q^-i*R^3*(Q*R^3)^(n-1)*Q^i ) );
fp := f / Concatenation(rels, moreRels);
q := fp.1; r := fp.2;
iso := FGA_CurryAutToPQOU( r^3*(q*r^3)^(n-1) # 21b
, q
, (q*r^3)^(n-1) # 21a
, q^-2*r^4*q^2*r^-3 # 21c
);
else # n > 3, odd
f := FreeGroup( "S", "R" );
S := f.1; R := f.2;
rels := [ (R^3*S^n*(S*R^-3)^(n-1))^2 # 25a
, (S^(n+1)*R^3*S^n*(S*R^-3)^(n-1))^(n-1)*
S^((-n)*(n-1)) # 25b
, ((S^n)*(S*R^-3)^(n-1))^2 # 25d
, Comm( S^n*(S*R^-3)^(n-1),
S^-(n+1)*R^3*S^n*
(S*R^-3)^(n-1)*S^(n+1) ) # 25e
, Comm( S^-2*R^4*S^2*R^3,
S*R^-3*S^(n-1)*R^-3*S ) # 25f
, Comm( R^4, S^n*(S*R^-3)^(n-1) ) # 25g
, Comm( R^4, S^-2*R^4*S^2 ) # 25h
, Comm( S^-2*R^4*S^2*R^-3,
S^n*(S*R^-3)^(n-1)*S^-2*R^4*S^2*
R^-3*S^n*(S*R^-3)^(n-1) ) # 25i
, Comm( S^-2*R^4*S^2*R^-3,
R^-3*S^-(n+1)*S^-2*R^4*S^2*
R^-3*S^(n+1)*R^3 ) # 25j
# wrong: , Comm( S^-2*R^4*S^2*R^-3,
# R^-3*S^-1*R^-3*S*R^3*S^n*
# (S*R^-3)^(n-1)*S^-2*R^4*S^2*R^3*
# (S*R^-3)^(n-1)*S^n*R^-3*S^-1*
# R^3*S*R^3 ) # 25k
, Comm( S^-2*R^4*S^2*R^-3,
R^-3*S^-1*R^-3*S*R^3*S^n*
(S*R^-3)^(n-1)*S^-2*R^4*S^2*R^-3*
(S*R^-3)^(n-1)*S^n*R^-3*S^-1*
R^3*S*R^3 ) # 25k corrected
, R^3*(S*R^-3)^(n-1)*S^-3*R^4*S^2*R^-3*S*
R^3*(S*R^-3)^(n-1)*S^(n-3)*R^4*S^2*R^-3*
S^(n-1)*R^4*S^2*R^-3*S^(n-1)*R^3*S^-2*
R^-4*S^(n+3)*R^3*S^-2*R^-4*S^2 # 25l
, (R^3*(S*R^-3)^(n-1)*S^(n-2)*R^4*S^2)^2 # 25m
, R^12 # 22q
] ;
# and finally the relations 25c:
moreRels := List( [ 2 .. (n-1)/2 ],
i -> Comm( R^3*S^n*(S*R^-3)^(n-1),
S^(-i*(n+1))*R^3*S^n*
(S*R^-3)^(n-1)*S^(i*(n+1)) ) );
fp := f / Concatenation( rels, moreRels );
s := fp.1; r := fp.2;
iso := FGA_CurryAutToPQOU( r^3*s^n*(s*r^-3)^(n-1) # 24c
, s^(n+1) # 24a
, s^n*(s*r^-3)^(n-1) # 24b
, s^(-2*(n+1))*r^4*s^(2*(n+1))*r^-3 # 24d
);
fi;
isoinv := GroupHomomorphismByImagesNC( fp, aut,
GeneratorsOfGroup( fp ),
GeneratorsOfGroup( aut ) );
return GroupHomomorphismByFunction( aut, fp, iso,
x -> x ^ isoinv );
end );
#############################################################################
##
#F FreeGroupEndomorphismByImages( , )
##
## returns the endomorphism of that maps the generators of
## to .
##
InstallGlobalFunction( FreeGroupEndomorphismByImages,
function(g,l)
return GroupHomomorphismByImages(g,g,FreeGeneratorsOfGroup(g),l);
end );
#############################################################################
##
#F FreeGroupAutomorphismsGeneratorO( )
#F FreeGroupAutomorphismsGeneratorP( )
#F FreeGroupAutomorphismsGeneratorU( )
#F FreeGroupAutomorphismsGeneratorS( )
#F FreeGroupAutomorphismsGeneratorT( )
#F FreeGroupAutomorphismsGeneratorQ( )
#F FreeGroupAutomorphismsGeneratorR( )
##
## These functions return the automorphism of which maps the
## generators [, , ..., ] to
## O : [^-1 , , ..., ] (n>=1)
## P : [ , , , ..., ] (n>=2)
## U : [, , , ..., ] (n>=2)
## S : [^-1, ^-1, ..., ^-1, ^-1 ] (n>=1)
## T : [ , ^-1, , ..., ] (n>=2)
## Q : [, , ..., , ] (n>=2)
## R : [^-1, , , , ...,
## , ^-1, ^-1] (n>=4)
##
InstallGlobalFunction( FreeGroupAutomorphismsGeneratorO,
function( g )
local imgs;
FGA_CheckRank( g, 1 );
imgs := ShallowCopy( FreeGeneratorsOfGroup( g ) );
imgs[1] := imgs[1]^-1;
return FreeGroupEndomorphismByImages( g, imgs );
end );
InstallGlobalFunction( FreeGroupAutomorphismsGeneratorP,
function( g )
local imgs;
FGA_CheckRank( g, 2 );
imgs := ShallowCopy( FreeGeneratorsOfGroup( g ) );
imgs{[1,2]} := [ imgs[2], imgs[1] ];
return FreeGroupEndomorphismByImages( g, imgs );
end );
InstallGlobalFunction( FreeGroupAutomorphismsGeneratorU,
function( g )
local imgs;
imgs := ShallowCopy( FreeGeneratorsOfGroup( g ) );
FGA_CheckRank( g, 2 );
imgs[1] := imgs[1] * imgs[2];
return FreeGroupEndomorphismByImages( g, imgs );
end );
InstallGlobalFunction( FreeGroupAutomorphismsGeneratorS,
function( g )
local imgs;
FGA_CheckRank( g, 1 );
imgs := FreeGeneratorsOfGroup(g){[2..Rank(g)]};
Add( imgs, FreeGeneratorsOfGroup(g)[1] );
return FreeGroupEndomorphismByImages( g, List(imgs, g -> g^-1) );
end );
InstallGlobalFunction( FreeGroupAutomorphismsGeneratorT,
function( g )
local imgs;
FGA_CheckRank( g, 2 );
imgs := ShallowCopy( FreeGeneratorsOfGroup( g ) );
imgs{[1..2]} := [ imgs[2], imgs[1]^-1 ];
return FreeGroupEndomorphismByImages( g, imgs );
end );
InstallGlobalFunction( FreeGroupAutomorphismsGeneratorQ,
function( g )
local imgs;
FGA_CheckRank( g, 2 ); # we could allow 1
imgs := FreeGeneratorsOfGroup(g){[2..Rank(g)]};
Add( imgs, FreeGeneratorsOfGroup(g)[1] );
return FreeGroupEndomorphismByImages( g, imgs );
end );
InstallGlobalFunction( FreeGroupAutomorphismsGeneratorR,
function( g )
local imgs, n;
FGA_CheckRank( g, 4 );
n := RankOfFreeGroup( g );
imgs := ShallowCopy( FreeGeneratorsOfGroup( g ) );
imgs{[1,2,n-1,n]} := [ imgs[2]^-1, imgs[1],
imgs[n]*imgs[n-1]^-1, imgs[n-1]^-1 ];
return FreeGroupEndomorphismByImages( g, imgs );
end );
#############################################################################
##
#F FGA_CheckRank( , )
##
## Checks whether has rank at least , and signals an
## error otherwise (helper function for FreeGroupAutomorphismsGenerator*)
##
InstallGlobalFunction( FGA_CheckRank,
function( g, r )
if RankOfFreeGroup( g ) < r then
Error( "the rank of the group should be at least ", r );
fi;
return;
end );
#############################################################################
##
#E
fga/lib/Autom.gi 0000664 0003717 0003717 00000025421 13275267465 015226 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Autom.gi FGA package Christian Sievers
##
## Methods to create and compute with inverse automata
##
#Y 2003 - 2018
##
DeclareRepresentation( "IsSimpleInvAutomatonRep",
IsComponentObjectRep and IsInvAutomatonCategory and
IsAttributeStoringRep and IsCollection,
# [ "initial", "terminal", "states", "group" ] );
[ "states", "group" ] );
InstallMethod( TrivialInvAutomaton,
[ IsFreeGroup ],
function(G)
local state;
state := FGA_newstate();
return Objectify( NewType( FamilyObj( G ),
IsSimpleInvAutomatonRep and IsMutable),
rec(initial:=state, terminal:=state, group:=G) );
end );
InstallMethod( InvAutomatonInsertGenerator,
IsCollsElms,
[ IsSimpleInvAutomatonRep and IsMutable, IsElementOfFreeGroup ],
function(A,gen)
FGA_AutomInsertGeneratorLetterRep( A, LetterRepAssocWord( gen ) );
end );
InstallMethod( \in,
"for a simple inverse automaton",
IsElmsColls,
[ IsElementOfFreeGroup, IsSimpleInvAutomatonRep ],
function(g,A)
return IsIdenticalObj(FGA_deltas( A!.initial,
LetterRepAssocWord(g)),
A!.terminal);
end );
InstallMethod( PrintObj,
[ IsSimpleInvAutomatonRep ],
function(A)
Print("");
end );
InstallMethod( AsGroup,
"for a simple inverse Automaton",
[ IsSimpleInvAutomatonRep ],
function(A)
local G;
if IsMutable(A) then
TryNextMethod();
fi;
G := rec ();
ObjectifyWithAttributes( G,
NewType( FamilyObj( A ),
IsFreeGroup and IsAttributeStoringRep and
HasOneImmutable and HasFreeGroupAutomaton ),
OneImmutable, One( A!.group ),
FreeGroupAutomaton, A );
return G;
end );
InstallGlobalFunction( FGA_newstate,
function()
return (rec (delta:=[], deltainv:=[]));
end );
InstallGlobalFunction( FGA_connectpos,
function(s1, s2, g)
s1.delta[g] := s2;
s2.deltainv[g] := s1;
end );
InstallGlobalFunction( FGA_connect,
function(s1, s2, g)
if g>0 then
FGA_connectpos(s1, s2, g);
else
FGA_connectpos(s2, s1, -g);
fi;
end );
InstallGlobalFunction( FGA_define,
function(state, gen)
local nstate;
nstate := FGA_newstate();
FGA_connect(state, nstate, gen);
return nstate; # !!!
end );
# "active"
InstallGlobalFunction( FGA_find,
function(s)
while IsBound(s.isnow) do
s := s.isnow;
od;
return s;
# todo: path compression
end );
InstallGlobalFunction( FGA_merge,
function(s1, s2, Q)
s1 := FGA_find(s1);
s2 := FGA_find(s2);
if IsNotIdenticalObj(s1,s2) then
s2.isnow := s1;
Add(Q,s2);
fi;
end );
InstallGlobalFunction( FGA_coincidence,
function(s1,s2)
local Q, s, g, s0, s01, delta, deltainv;
Q := [];
FGA_merge(s1, s2, Q);
for s in Q do
delta := ShallowCopy(s.delta);
for g in BoundPositions(delta) do
Unbind(delta[g].deltainv[g]);
od;
deltainv := ShallowCopy(s.deltainv);
for g in BoundPositions(deltainv) do
Unbind(deltainv[g].delta[g]);
od;
for g in BoundPositions(delta) do
s0 := FGA_find(s);
s01 := FGA_find(delta[g]);
if IsBound(s0.delta[g]) then
FGA_merge(s01, s0.delta[g], Q);
elif IsBound(s01.deltainv[g]) then
FGA_merge(s0, s01.deltainv[g], Q);
else
FGA_connectpos(s0, s01, g);
fi;
od;
for g in BoundPositions(deltainv) do
s0 := FGA_find(s);
s01 := FGA_find(deltainv[g]);
if IsBound(s0.deltainv[g]) then
FGA_merge(s01, s0.deltainv[g], Q);
elif IsBound(s01.delta[g]) then
FGA_merge(s0, s01.delta[g], Q);
else
FGA_connectpos(s01, s0, g);
fi;
od;
od;
end );
InstallGlobalFunction( FGA_delta,
function(state, gen)
if gen>0 then
return ATf(state.delta, gen);
else
return ATf(state.deltainv, -gen);
fi;
end );
InstallGlobalFunction( FGA_deltas,
function(state, genlist)
return IteratedF(genlist, FGA_delta, state);
end );
InstallGlobalFunction( FGA_TmpState,
function(state, genlist)
local undo, oldstate, i;
i := 1;
while state <> fail and i <= Size(genlist) do
oldstate := state;
state := FGA_delta( oldstate, genlist[i] );
i := i+1;
od;
if state = fail then
i := i-1;
if genlist[i] > 0 then
undo := function() Unbind(oldstate.delta[genlist[i]]); end;
else
undo := function() Unbind(oldstate.deltainv[-genlist[i]]); end;
fi;
state := Iterated( genlist{[i..Size(genlist)]}, FGA_define, oldstate );
else
undo := ReturnTrue;
fi;
return rec( state:=state, undo:=undo);
end );
InstallGlobalFunction( FGA_trace,
function(s,w)
local i, s1;
s1 := s;
i := 1;
while i <= Length(w) and s1 <> fail do
s := s1;
s1 := FGA_delta(s, w[i]);
i := i+1;
od;
if s1 = fail then
return rec(state:=s, index:=i-1);
else
return rec(state:=s1, index:=i);
fi;
end );
InstallGlobalFunction( FGA_backtrace,
function(s,w,j)
local i, s1;
s1 := s;
i := Length(w);
while i >= j and s1 <> fail do
s := s1;
s1 := FGA_delta(s, -w[i]);
i := i-1;
od;
if s1 = fail then
return rec(state:=s, index:=i+1);
else
return rec(state:=s1, index:=i);
fi;
end );
InstallGlobalFunction( FGA_InsertGenerator,
function(s, gen)
return FGA_InsertGeneratorLetterRep(s, LetterRepAssocWord(gen));
end );
InstallGlobalFunction( FGA_AutomInsertGeneratorLetterRep,
function(A, w)
A!.initial := FGA_InsertGeneratorLetterRep( A!.initial, w);
A!.terminal := A!.initial;
end );
InstallGlobalFunction( FGA_InsertGeneratorLetterRep,
function(s, w)
local i, t, bt, s1, s2;
t := FGA_trace(s, w);
bt := FGA_backtrace(s, w, t.index);
s1 := t.state;
s2 := bt.state;
if t.index > bt.index then # trace complete
FGA_coincidence(s1, s2);
else
if IsIdenticalObj(s1, s2) then
while w[t.index] = -w[bt.index] do
s1 := FGA_define(s1, w[t.index]);
t.index := t.index + 1;
bt.index := bt.index - 1;
od;
s2 := s1;
fi;
for i in [t.index .. bt.index-1] do
s1 := FGA_define(s1, w[i]);
od;
FGA_connect(s1, s2, w[bt.index]);
fi;
return FGA_find(s);
end );
InstallGlobalFunction( FGA_FromGroupWithGenerators,
# gens -> Iterated(gens, FGA_InsertGenerator, FGA_newstate()) );
function(G)
local s;
s := Iterated(GeneratorsOfGroup(G), FGA_InsertGenerator, FGA_newstate());
return Objectify( NewType( FamilyObj( G ),IsSimpleInvAutomatonRep),
rec(initial:=s, terminal:=s, group:=G) );
end );
InstallGlobalFunction( FGA_FromGeneratorsLetterRep,
function(gens,G)
local s;
s := Iterated(gens, FGA_InsertGeneratorLetterRep, FGA_newstate());
return Objectify( NewType( FamilyObj( G ),
IsSimpleInvAutomatonRep and IsMutable),
rec(initial:=s, terminal:=s, group:=G) );
end );
InstallGlobalFunction( FGA_Check,
function(s, w)
return IsIdenticalObj(FGA_deltas(s, w), s);
end );
InstallGlobalFunction( FGA_FindGeneratorsAndStates,
function(A)
local Q, Gens, nq, q, i, nr, freegens;
q := A!.initial;
nr := 0;
Gens := [];
q.repr := [];
Q := [q];
for nq in Q do
freegens := [];
nr := nr + 1;
nq.nr := nr;
for i in BoundPositions(nq.delta) do
q := nq.delta[i];
if IsBound(q.repr) then
if nq.repr = [] or nq.repr[Length(nq.repr)] <> -i then
Add(Gens, Concatenation(nq.repr, [i], -Reversed(q.repr)));
freegens[i] := Length(Gens);
fi;
else
q.repr := ShallowCopy(nq.repr);
Add(q.repr, i);
Add(Q, q);
fi;
od;
for i in BoundPositions(nq.deltainv) do
q := nq.deltainv[i];
if not(IsBound(q.repr)) then
q.repr := ShallowCopy(nq.repr);
Add(q.repr, -i);
Add(Q, q);
fi;
od;
if freegens <> [] then
nq.freegens := freegens;
fi;
od;
###
A!.states := Q;
A!.genslr := Gens;
end );
InstallGlobalFunction( FGA_initial,
A -> A!.initial );
InstallGlobalFunction( FGA_repr,
state -> state.repr );
InstallGlobalFunction( FGA_GeneratorsLetterRep,
function(A)
if not IsBound( A!.genslr ) then
FGA_FindGeneratorsAndStates(A);
fi;
return A!.genslr;
end );
InstallGlobalFunction( FGA_States,
function(A)
if not IsBound( A!.states ) then
FGA_FindGeneratorsAndStates(A);
fi;
return A!.states;
end );
InstallGlobalFunction( FGA_reducedPos,
function(A)
local i, states, n;
i := 0;
states := FGA_States(A);
repeat
i := i+1;
n := Size(BoundPositions(states[i].delta)) +
Size(BoundPositions(states[i].deltainv));
until n > 2 or ( n=2 and i=1);
return i;
end );
InstallGlobalFunction( FGA_Index,
function(A)
local states, r;
states := FGA_States(A);
r := Size(FreeGeneratorsOfWholeGroup(A!.group));
if ForAny( List( states, s -> s.delta),
delta -> not IsDenseList(delta) or Size(delta) <> r ) then
return infinity;
fi;
return Size(states);
end );
InstallGlobalFunction( FGA_AsWordLetterRepInFreeGenerators,
function(g,A)
local s,x,f,w;
FGA_States(A); # do work in the automaton if needed
w := [];
s := A!.initial;
for x in g do
if x > 0 then
if IsBound(s.freegens) and IsBound(s.freegens[x]) then
Add(w, s.freegens[x]);
fi;
s := ATf(s.delta, x);
if s = fail then
return fail;
fi;
else
s := ATf(s.deltainv, -x);
if s=fail then
return fail;
fi;
if IsBound(s.freegens) and IsBound(s.freegens[-x]) then
Add(w, -s.freegens[-x]);
fi;
fi;
od;
if IsNotIdenticalObj( s, A!.terminal ) then
return fail;
fi;
return w;
end );
#############################################################################
##
#E
fga/lib/FreeGrps.gi 0000644 0003717 0003717 00000015512 13275267465 015654 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W FreeGroups.gi FGA package Christian Sievers
##
## Main installation file for the FGA package
##
#Y 2003 - 2012
##
#############################################################################
##
#M FreeGroupAutomaton( )
##
## returns the automaton representing .
##
InstallMethod( FreeGroupAutomaton,
"for a subgroup of a free group",
[ CanComputeWithInverseAutomaton ],
function(G)
return FGA_FromGroupWithGenerators(G);
end );
#############################################################################
##
#M FreeGroupExtendedAutomaton( )
##
## return the extended automaton representing .
InstallMethod( FreeGroupExtendedAutomaton,
"for a subgroup of a free group",
[ CanComputeWithInverseAutomaton ],
function(G)
return FGA_FromGroupWithGeneratorsX(G);
end );
#############################################################################
##
#M \in( , )
##
## tests whether is in the finitely generated free group .
##
InstallMethod( \in,
"for a subgroup of a free group",
IsElmsColls,
[ IsElementOfFreeGroup, CanComputeWithInverseAutomaton ],
function( g, G )
return g in FreeGroupAutomaton(G);
end );
#############################################################################
##
#M FreeGeneratorsOfGroup( )
##
## returns a list of free generators of the group .
## This is a minimal generating set, but is also guarantied to
## be N-reduced.
##
InstallMethod( FreeGeneratorsOfGroup,
"for a subgroup of a free group",
[ CanComputeWithInverseAutomaton ],
function(G)
return List(FGA_GeneratorsLetterRep(FreeGroupAutomaton(G)),
l -> AssocWordByLetterRep
(ElementsFamily(FamilyObj(G)), l) );
end );
#############################################################################
##
#M GeneratorsOfGroup( )
##
InstallMethod( GeneratorsOfGroup,
"for a subgroup of a free group having a FreeGroupAutomaton",
[ HasFreeGroupAutomaton ],
FreeGeneratorsOfGroup );
##
## FreeGeneratorsOfGroup are GeneratorsOfGroup
##
InstallImmediateMethod( GeneratorsOfGroup,
HasFreeGeneratorsOfGroup,
0,
FreeGeneratorsOfGroup);
#############################################################################
##
#M MinimalGeneratingSet( )
##
## returns 's FreeGeneratorsOfGroup
##
InstallMethod( MinimalGeneratingSet,
"for a subgroup of a free group",
[ CanComputeWithInverseAutomaton ],
FreeGeneratorsOfGroup );
#############################################################################
##
#M SmallGeneratingSet( )
##
## returns 's FreeGeneratorsOfGroup
##
InstallMethod( SmallGeneratingSet,
"for a subgroup of a free group",
[ CanComputeWithInverseAutomaton ],
FreeGeneratorsOfGroup );
#############################################################################
##
#M IsWholeFamily( )
##
InstallMethod( IsWholeFamily,
"for a finitely generated free group",
[ CanComputeWithInverseAutomaton ],
G -> ForAll( FreeGeneratorsOfWholeGroup( G ), gen -> gen in G) );
#############################################################################
##
#M RankOfFreeGroup( )
##
## returns the rank of a free group.
##
InstallMethod( RankOfFreeGroup,
"for a subgroup of a free group",
[ CanComputeWithInverseAutomaton ],
G -> Size(MinimalGeneratingSet(G)) );
InstallMethod( RankOfFreeGroup,
"for a whole free group",
[ IsFreeGroup and IsWholeFamily ],
G -> Size(FreeGeneratorsOfWholeGroup(G)) );
#############################################################################
##
#M Rank( )
##
## a convenient name for RankOfFreeGroup
##
InstallMethod( Rank,
"for a subgroup of a free group",
[ IsFreeGroup ],
RankOfFreeGroup );
#############################################################################
##
#M IsSubset( , )
##
InstallMethod( IsSubset,
"for subgroups of free groups",
IsIdenticalObj,
[ CanComputeWithInverseAutomaton, CanComputeWithInverseAutomaton ],
function(G,U)
local gens;
if HasFreeGeneratorsOfGroup(U) then
gens := FreeGeneratorsOfGroup(U);
else
gens := GeneratorsOfGroup(U);
fi;
return ForAll(gens, u -> u in G);
end );
#############################################################################
##
#M \=( , )
##
InstallMethod( \=,
"for subgroups of free groups",
IsIdenticalObj,
[ CanComputeWithInverseAutomaton, CanComputeWithInverseAutomaton ],
function( G, H )
return IsSubset(G,H) and IsSubset(H,G);
end );
#############################################################################
##
#M AsWordLetterRepInFreeGenerators( , )
##
## returns the unique list representing a word in letter representation
## such that
## = Product( ,
## x -> FreeGeneratorsOfGroup()[AbsInt(x)]^(SignInt(x)),
## One() )
## or fail, if is not in .
##
InstallMethod( AsWordLetterRepInFreeGenerators,
"for an element in a free group",
IsElmsColls,
[ IsElementOfFreeGroup, CanComputeWithInverseAutomaton ],
function( g, G )
return FGA_AsWordLetterRepInFreeGenerators(
LetterRepAssocWord(g), FreeGroupAutomaton(G) );
end );
#############################################################################
##
#M AsWordLetterRepInGenerators( , )
##
## returns a list representing a word in letter representation such that
## = Product( ,
## x -> GeneratorsOfGroup()[AbsInt(x)]^(SignInt(x)),
## One() )
## or fail, if is not in .
##
InstallMethod( AsWordLetterRepInGenerators,
"for an element in a free group",
IsElmsColls,
[ IsElementOfFreeGroup,
CanComputeWithInverseAutomaton and HasGeneratorsOfGroup ],
function( g, G )
return FGA_AsWordLetterRepInGenerators(
LetterRepAssocWord( g ),
FreeGroupExtendedAutomaton( G ) );
end );
#############################################################################
##
#O CyclicallyReducedWord( )
##
## returns the the cyclically reduced form of
##
InstallMethod( CyclicallyReducedWord,
"for an element in a free group",
[ IsElementOfFreeGroup ],
function( g )
local rep, len, i;
if IsOne( g ) then
return g;
fi;
rep := LetterRepAssocWord( g );
len := Length( rep );
i := 1;
while rep[i] = -rep[len-i+1] do
i := i+1;
od;
return AssocWordByLetterRep( FamilyObj( g ), rep{[i..len-i+1]} );
end );
#############################################################################
##
#E
fga/lib/ExtAutom.gd 0000644 0003717 0003717 00000002244 13275267465 015676 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W ExtAutom.gd FGA package Christian Sievers
##
## Declarations for methods to create and compute with
## extended inverse automata
##
#Y 2003 - 2012
##
DeclareGlobalVariable( "FGA_FreeGroupForGenerators" );
DeclareGlobalVariable( "FGA_One" );
DeclareGlobalFunction( "FGA_newstateX" );
DeclareGlobalFunction( "FGA_connectposX" );
DeclareGlobalFunction( "FGA_connectX" );
DeclareGlobalFunction( "FGA_defineX" );
DeclareGlobalFunction( "FGA_findX" );
DeclareGlobalFunction( "FGA_mergeX" );
DeclareGlobalFunction( "FGA_coincidenceX" );
DeclareGlobalFunction( "FGA_atfX" );
DeclareGlobalFunction( "FGA_deltaX" );
DeclareGlobalFunction( "FGA_stepX" );
DeclareGlobalFunction( "FGA_deltasX" );
DeclareGlobalFunction( "FGA_traceX" );
DeclareGlobalFunction( "FGA_backtraceX" );
DeclareGlobalFunction( "FGA_insertgeneratorX" );
DeclareGlobalFunction( "FGA_fromgeneratorsX" );
DeclareGlobalFunction( "FGA_FromGroupWithGeneratorsX" );
DeclareGlobalFunction( "FGA_AsWordLetterRepInGenerators" );
#############################################################################
##
#E
fga/lib/Iterated.gi 0000644 0003717 0003717 00000003625 13275267465 015702 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Iterated.gi FGA package Christian Sievers
##
## Method installations for variants of Iterated
##
## Maybe this should move to the GAP library
##
#Y 2003 - 2012
##
#############################################################################
##
#M Iterated( , , )
##
## applies to iteratively as Iterated does, but uses
## as initial value.
##
InstallOtherMethod( Iterated,
[ IsList, IsFunction, IsObject ],
function (list, f, init)
local x;
for x in list do
init := f(init, x);
od;
return init;
end );
#############################################################################
##
#M IteratedF( , )
##
## applies to iteratively as Iterated does, but stops
## and returns fail when returns fail.
InstallMethod( IteratedF,
[ IsList, IsFunction ],
function (list, f)
local res, i;
if IsEmpty( list ) then
Error( "IteratedF: must contain at least one element" );
fi;
res := list[1];
for i in [ 2 .. Length( list ) ] do
if res = fail then
break;
fi;
res := f( res, list[i] );
od;
return res;
end );
#############################################################################
##
#M IteratedF( , , )
##
## applies to iteratively as Iterated does, but stops
## and returns fail when returns fail, and uses as
## initial value.
InstallOtherMethod( IteratedF,
[ IsList, IsFunction, IsObject ],
function (list, f, init)
local x;
for x in list do
init := f(init, x);
if init=fail then
break;
fi;
od;
return init;
end );
#############################################################################
##
#E
fga/lib/FreeGrps.gd 0000644 0003717 0003717 00000006526 13275267465 015654 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W FreeGroups.gd FGA package Christian Sievers
##
## Main declaration file for the FGA package
##
#Y 2003 - 2012
##
#############################################################################
##
#A FreeGeneratorsOfGroup( )
##
## returns a list of free generators of the group .
## This is a minimal generating set, but is also guarantied to
## be N-reduced.
##
DeclareAttribute( "FreeGeneratorsOfGroup", IsFreeGroup );
#############################################################################
##
#A RankOfFreeGroup( )
##
## returns the rank of a free group.
##
DeclareAttribute( "RankOfFreeGroup", IsFreeGroup );
#############################################################################
##
#A FreeGroupAutomaton( )
##
## returns the automaton representing .
##
DeclareAttribute( "FreeGroupAutomaton",
IsFreeGroup,
"mutable" );
#############################################################################
##
#A FreeGroupExtendedAutomaton( )
##
## return the extended automaton representing .
## The extra information is enough for a constructive membership test
## with respect to the given generators of .
##
DeclareAttribute( "FreeGroupExtendedAutomaton", IsFreeGroup );
#############################################################################
##
#O AsWordLetterRepInFreeGenerators( , )
##
## returns the unique list representing a word in letter representation
## such that
## = Product( ,
## x -> FreeGeneratorsOfGroup()[AbsInt(x)]^(SignInt(x)),
## One() )
## or fail, if is not in .
##
DeclareOperation( "AsWordLetterRepInFreeGenerators",
[ IsElementOfFreeGroup, IsFreeGroup ] );
#############################################################################
##
#O AsWordLetterRepInGenerators( , )
##
## returns a list representing a word in letter representation such that
## = Product( ,
## x -> GeneratorsOfGroup()[AbsInt(x)]^(SignInt(x)),
## One() )
## or fail, if is not in .
##
DeclareOperation( "AsWordLetterRepInGenerators",
[ IsElementOfFreeGroup, IsFreeGroup ] );
#############################################################################
##
#O CyclicallyReducedWord( )
##
## returns the the cyclically reduced form of
##
DeclareOperation( "CyclicallyReducedWord",
[ IsElementOfFreeGroup ] );
#############################################################################
##
#F CanComputeWithInverseAutomaton( )
##
## indicates whether we can use inverse automata to compute with .
## We assume this is possible if is a finitely generated free group,
## hoping that we actually can get a generating set when needed.
## This is not always true, but generally then there is also no other way.
##
DeclareSynonym( "CanComputeWithInverseAutomaton",
IsFreeGroup and IsFinitelyGeneratedGroup );
InstallTrueMethod( CanComputeWithInverseAutomaton, HasFreeGroupAutomaton );
InstallTrueMethod( CanEasilyTestMembership, HasFreeGroupAutomaton );
InstallTrueMethod( CanComputeSizeAnySubgroup, IsFreeGroup );
#############################################################################
##
#E
fga/lib/Hom.gd 0000644 0003717 0003717 00000001475 13275267465 014660 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Hom.gd FGA package Christian Sievers
##
## Declaration file for the computation with homomorphisms of free groups
##
#Y 2012
##
#############################################################################
##
#A FGA_Source( )
##
## returns the source of as group with special generators
##
DeclareAttribute( "FGA_Source", IsFromFpGroupGeneralMappingByImages );
#############################################################################
##
#A FGA_Image( )
##
## returns the image of as group with special generators
##
DeclareAttribute( "FGA_Image", IsToFpGroupGeneralMappingByImages );
#############################################################################
##
#E
fga/lib/Hom.gi 0000644 0003717 0003717 00000005372 13275267465 014665 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Hom.gi FGA package Christian Sievers
##
## Methods for homomorphisms of free groups
##
#Y 2003 - 2016
##
InstallMethod( PreImagesRepresentative,
"for homomorphisms of free groups",
FamRangeEqFamElm,
[ IsToFpGroupGeneralMappingByImages, IsElementOfFreeGroup ],
function( hom, x )
local w, mgi;
mgi := MappingGeneratorsImages( hom );
w := AsWordLetterRepInGenerators( x, FGA_Image( hom ));
if w = fail then
return fail;
fi;
return Product( w, i -> mgi[1][AbsInt(i)]^SignInt(i),
One(Source(hom)));
end );
InstallMethod( ImagesRepresentative,
"for homomorphisms of free groups",
FamSourceEqFamElm,
[ IsFromFpGroupGeneralMappingByImages, IsElementOfFreeGroup ],
23,
function( hom, x )
local w, mgi;
mgi := MappingGeneratorsImages( hom );
if mgi[1]=[] then return One(Range(hom)); fi;
w := AsWordLetterRepInGenerators( x, FGA_Source( hom ));
if w = fail then
return fail;
fi;
return Product( w, i -> mgi[2][AbsInt(i)]^SignInt(i),
One(Range(hom)));
end );
InstallMethod( FGA_Source,
[ IsFromFpGroupGeneralMappingByImages and HasMappingGeneratorsImages ],
hom -> SubgroupNC( Source(hom), MappingGeneratorsImages(hom)[1] )
);
InstallMethod( FGA_Image,
[ IsToFpGroupGeneralMappingByImages and HasMappingGeneratorsImages ],
hom -> SubgroupNC( Range(hom), MappingGeneratorsImages(hom)[2] )
);
InstallMethod( IsSingleValued,
"for group general mappings of free groups",
[ IsFromFpGroupGeneralMappingByImages and HasMappingGeneratorsImages ],
function( hom )
local mgi, g, imgs;
mgi := MappingGeneratorsImages( hom );
if mgi[1]=[] then return true; fi; # map on trivial group
g := SubgroupNC( Source(hom), mgi[1] );
if not IsFreeGroup( g ) then
TryNextMethod();
fi;
if Size( mgi[1] ) = RankOfFreeGroup( g ) then
return true;
fi;
# write free generators in given generators and
# compute corresponding images:
imgs := List( FreeGeneratorsOfGroup( g ), fgen ->
Product( AsWordLetterRepInGenerators( fgen, g ),
i -> mgi[2][AbsInt(i)]^SignInt(i),
One(Range(hom)) ));
# check if all given generator/image pairs agree with the
# map given by free generators and computed images:
return ForAll( [ 1 .. Size( mgi[1] ) ], n ->
mgi[2][n] =
Product(
AsWordLetterRepInFreeGenerators( mgi[1][n], g ),
i -> imgs[AbsInt(i)]^SignInt(i),
One(Range(hom)) ));
end );
#############################################################################
##
#E
fga/lib/ReprAct.gi 0000644 0003717 0003717 00000012745 13275267465 015504 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W ReprAct.gi FGA package Christian Sievers
##
## Methods for computing RepresentativeAction
##
#Y 2003 - 2016
##
InstallOtherMethod( RepresentativeActionOp,
"for conjugation of elements in a free group",
IsCollsElmsElmsX,
[ IsFreeGroup, IsElementOfFreeGroup, IsElementOfFreeGroup, IsFunction ],
function(F, d, e, act)
local wd, we, le, ld, id, ie, wecr, w, pos, pos2, conj;
if act <> OnPoints then
TryNextMethod();
fi;
if IsOne(d) and IsOne(e) then
return One(F);
fi;
if IsOne(d) or IsOne(e) then
return fail;
fi;
wd := LetterRepAssocWord(d);
ld := Length(wd);
id := 1;
while wd[id] = -wd[ld-id+1] do
id := id+1;
od;
we := LetterRepAssocWord(e);
le := Length(we);
ie := 1;
while we[ie] = -we[le-ie+1] do
ie := ie+1;
od;
if ld-2*id <> le-2*ie then
return fail;
fi;
w := wd{[id..ld-id+1]}; # wd cyclically reduced
w := Concatenation(w,w); # ... and doubled
wecr := we{[ie..le-ie+1]}; # we cyclically reduced
pos := PositionSublist(w,wecr);
if pos=fail then
return fail;
fi;
conj := AssocWordByLetterRep(FamilyObj(d), wd{[1..id+pos-2]}) *
AssocWordByLetterRep(FamilyObj(d), we{[le-ie+2..le]});
if conj in F then
return conj;
fi;
pos2 := PositionSublist(w, wecr, pos);
if pos2=fail then
pos2 := pos+ld-2*ie+2;
fi;
return FindPowLetterRep(F, wd{[1..id+pos-2]},w{[pos..pos2-1]},
we{[le-ie+2..le]});
end );
InstallMethod( FindPowLetterRep,
[ CanComputeWithInverseAutomaton, IsList, IsList, IsList ],
function(f, wi, wp, wt)
local init, initstate, final, finalstate, state, n, fam;
state := FGA_initial(FreeGroupAutomaton(f));
init := FGA_TmpState(state, wi);
initstate := init.state;
final := FGA_TmpState(state, -Reversed(wt));
finalstate := final.state;
state := initstate;
n := 0;
repeat
state := FGA_deltas(state, wp);
n := n+1;
until state=fail or IsIdenticalObj(state, initstate) or
IsIdenticalObj(state, finalstate);
if state = fail then
state := initstate;
n := 0;
wp := -Reversed(wp);
repeat
state := FGA_deltas(state, wp);
n := n+1;
until state=fail or IsIdenticalObj(state, finalstate);
fi;
final.undo();
init.undo();
if IsIdenticalObj(state, finalstate) then
fam := ElementsFamily(FamilyObj(f));
return AssocWordByLetterRep(fam, wi) *
AssocWordByLetterRep(fam, wp)^n *
AssocWordByLetterRep(fam, wt);
else
return fail;
fi;
end );
InstallOtherMethod( RepresentativeActionOp,
"for subgroups of a free group",
IsFamFamFamX,
[ CanComputeWithInverseAutomaton,
CanComputeWithInverseAutomaton,
CanComputeWithInverseAutomaton,
IsFunction ],1,
function(F, G, H, act)
local AG, AH, AF, rdG, rdH, statesH, redgens, i, AN, tmp, conj;
if act <> OnPoints then
TryNextMethod();
fi;
if RankOfFreeGroup(G) <> RankOfFreeGroup(H) then
return fail;
fi;
AG := FreeGroupAutomaton(G);
rdG := FGA_reducedPos(AG);
AH := FreeGroupAutomaton(H);
rdH := FGA_reducedPos( AH );
statesH := FGA_States(AH);
if Size(statesH)-rdH <> Size(FGA_States(AG))-rdG then
return fail;
fi;
redgens := List( List(FreeGeneratorsOfGroup(G), LetterRepAssocWord),
w -> w{[rdG .. Length(w)-rdG+1]} );
for i in [rdH .. Size(statesH)] do
if ForAll(redgens, w -> FGA_Check(statesH[i], w)) then
# We now know that G is a subgroup of a conjugate of H.
# More ugly low level computation could check for equality.
# Instead we postpone the check to a time where we can work
# at a higher level.
# So if the result is fail, we get it a little slower.
AN := FreeGroupAutomaton( NormalizerInWholeGroup( G ) );
tmp := FGA_TmpState(
AN!.initial,
Concatenation(
FGA_States( AG )[ rdG ].repr,
-Reversed(FGA_repr(statesH[i])) ));
AF := FreeGroupAutomaton( F );
conj := FGA_FindRepInIntersection(
AF, AF!.terminal,
AN, tmp.state );
tmp.undo();
if conj = fail then
return fail;
fi;
conj := AssocWordByLetterRep(
ElementsFamily(FamilyObj(F)), conj );
# Now check if we really have a conjugating element:
if IsSubset( G, List( FreeGeneratorsOfGroup(H),
h -> h^(conj^-1) )) then
return conj;
else
return fail;
fi;
fi;
od;
return fail;
end );
#############################################################################
##
#E
fga/lib/Index.gi 0000644 0003717 0003717 00000005734 13275267465 015213 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Index.gi FGA package Christian Sievers
##
## Method installations for index computations in free groups
##
#Y 2003 - 2012
##
#############################################################################
##
#M IndexInWholeGroup( )
##
InstallMethod( IndexInWholeGroup,
"for a free group",
[ CanComputeWithInverseAutomaton ],
function(G)
if HasIsWholeFamily(G) and IsWholeFamily(G) then
return 1;
fi;
# let the gap lib handle this case:
if IsSubgroupOfWholeGroupByQuotientRep(G) then
TryNextMethod();
fi;
return FGA_Index(FreeGroupAutomaton(G));
end );
#############################################################################
##
#M IndexOp( , , )
##
## computes the index of in .
## If is true, checks whether the subgroup relation really holds
## and returns fail otherwise.
## Some of the checks will even be performed when is false.
##
InstallOtherMethod( IndexOp,
"for free groups",
IsFamFamX,
[ CanComputeWithInverseAutomaton,
CanComputeWithInverseAutomaton,
IsBool ],
function( G, U, check )
local indexG, indexU, index, rankG, gensU, gen, w, genwords;
indexG := IndexInWholeGroup( G );
indexU := IndexInWholeGroup( U );
if indexG <> infinity then
if check and not IsSubset( G, U ) then
return fail;
fi;
if indexU = infinity then
return infinity;
else
index := indexU / indexG;
if IsInt( index ) then
return index;
else
return fail;
fi;
fi;
fi;
# one more cheap test:
if indexU <> infinity then
return fail;
fi;
# now we must work harder
rankG := RankOfFreeGroup( G );
gensU := FreeGeneratorsOfGroup( U );
genwords := [];
for gen in gensU do
w := AsWordLetterRepInFreeGenerators( gen, G );
if w = fail then
return fail;
fi;
Add( genwords, w );
od;
return FGA_Index(
FGA_FromGeneratorsLetterRep( genwords, FreeGroup(rankG) ) );
end );
#############################################################################
##
#M IndexOp( , )
##
InstallMethod( IndexOp,
"for free groups",
IsIdenticalObj,
[ CanComputeWithInverseAutomaton, CanComputeWithInverseAutomaton ],
function( G, H )
return IndexOp( G, H, true);
end );
#############################################################################
##
#M IndexNC( , )
##
InstallMethod( IndexNC,
"for free groups",
IsIdenticalObj,
[ CanComputeWithInverseAutomaton, CanComputeWithInverseAutomaton ],
function( G, H )
return IndexOp( G, H, false);
end );
#############################################################################
##
#E
fga/lib/ReprActT.gi 0000644 0003717 0003717 00000001647 13275267465 015627 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W ReprActT.gi FGA package Christian Sievers
##
## Trivial cases for RepresentativeAction
##
## This is generally applicable and not needed for the FGA package,
## so maybe it should move to the GAP library.
##
#Y 2003 - 2012
##
InstallOtherMethod( RepresentativeActionOp,
"trivial general cases",
IsCollsElmsElmsX,
[ IsGroup, IsObject, IsObject, IsFunction ],
function( G, d, e, act)
local result;
if act=OnRight then
result := LeftQuotient( d, e );
elif act=OnLeftInverse then
result := d / e;
else
TryNextMethod();
fi;
if result in G then
return result;
else
return fail;
fi;
end );
#############################################################################
##
#E
fga/lib/Iterated.gd 0000644 0003717 0003717 00000001215 13275267465 015666 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Iterated.gd FGA package Christian Sievers
##
## Declarations for variants of Iterated
##
## Maybe this should move to the GAP library
##
#Y 2003 - 2012
##
#############################################################################
##
#O IteratedF( , )
##
## applies to iteratively as Iterated does, but stops
## and returns fail when returns fail.
##
DeclareOperation( "IteratedF", [ IsList, IsFunction ] );
#############################################################################
##
#E
fga/lib/util.gi 0000644 0003717 0003717 00000001022 13275267465 015103 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W util.gi FGA package Christian Sievers
##
## Utility functions
##
#Y 2003 - 2012
##
InstallGlobalFunction( BoundPositions,
l -> Filtered([1..Length(l)], i -> IsBound(l[i])) );
InstallGlobalFunction( ATf,
function(l, p)
if IsBound(l[p]) then
return l[p];
else
return fail;
fi;
end );
#############################################################################
##
#E
fga/lib/ReprAct.gd 0000644 0003717 0003717 00000000634 13275267465 015471 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W ReprAct.gd FGA package Christian Sievers
##
## Declarations used for computing RepresentativeAction
##
#Y 2003 - 2012
##
DeclareOperation( "FindPowLetterRep",
[ IsFreeGroup, IsList, IsList, IsList ]);
#############################################################################
##
#E
fga/lib/Intsect.gi 0000644 0003717 0003717 00000013403 13275267465 015545 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W Intsect.gi FGA package Christian Sievers
##
## Installations for the computation of intersections of free groups
##
#Y 2003 - 2012
##
#############################################################################
##
#F FGA_StateTable( , , )
##
InstallGlobalFunction( FGA_StateTable,
function( t, i, j )
if not IsBound( t[i] ) then
t[i] := [];
fi;
if not IsBound( t[i][j] ) then
t[i][j] := FGA_newstate();
fi;
return t[i][j];
end );
#############################################################################
##
#M Intersection2( , )
##
InstallMethod( Intersection2,
"for subgroups of free groups",
IsIdenticalObj,
[ CanComputeWithInverseAutomaton, CanComputeWithInverseAutomaton ],
function( G1, G2 )
local A, t, sl1, sl2, i, nr1, nr2, Q, pair, g, q, q1, q2, bpd, bpdi;
# let the gap lib handle this case:
if IsSubgroupOfWholeGroupByQuotientRep( G1 ) and
IsSubgroupOfWholeGroupByQuotientRep( G2 ) then
TryNextMethod();
fi;
t := [];
i := FGA_StateTable( t, 1, 1 );
sl1 := FGA_States( FreeGroupAutomaton( G1 ) );
sl2 := FGA_States( FreeGroupAutomaton( G2 ) );
Q := [ [1,1] ];
for pair in Q do
q1 := sl1[ pair[1] ];
q2 := sl2[ pair[2] ];
q := FGA_StateTable( t, pair[1], pair[2] );
for g in Difference(
Intersection( BoundPositions( q1.delta ),
BoundPositions( q2.delta ) ),
BoundPositions( q.delta ) ) do
nr1 := q1.delta[g].nr;
nr2 := q2.delta[g].nr;
FGA_connectpos( q, FGA_StateTable( t, nr1, nr2 ), g );
Add( Q, [ nr1, nr2 ] );
od;
for g in Difference(
Intersection( BoundPositions( q1.deltainv ),
BoundPositions( q2.deltainv ) ),
BoundPositions( q.deltainv ) ) do
nr1 := q1.deltainv[g].nr;
nr2 := q2.deltainv[g].nr;
FGA_connectpos( FGA_StateTable( t, nr1, nr2 ), q, g );
Add( Q, [ nr1, nr2 ] );
od;
bpd := BoundPositions( q.delta );
bpdi := BoundPositions( q.deltainv );
while Size( bpd ) + Size( bpdi ) = 1 and
IsNotIdenticalObj( q, i ) do
if Size( bpd ) = 1 then
g := bpd[ 1 ];
q := q.delta[ g ];
Unbind( q.deltainv[ g ] );
else
g := bpdi[ 1 ];
q := q.deltainv[ g ];
Unbind( q.delta[ g ] );
fi;
bpd := BoundPositions( q.delta );
bpdi := BoundPositions( q.deltainv );
od;
od;
A := Objectify( NewType( FamilyObj( G1 ), IsSimpleInvAutomatonRep ),
rec( initial:=i, terminal:=i,
group := TrivialSubgroup( G1 ) ) );
return AsGroup( A );
end );
#############################################################################
##
#F FGA_TrySetRepTable( , , , , )
##
InstallGlobalFunction( FGA_TrySetRepTable,
function( t, i, j, r, g )
local rx;
if not IsBound( t[i] ) then
t[i] := [];
fi;
if not IsBound( t[i][j] ) then
rx := ShallowCopy( r );
Add( rx, g );
t[i][j] := rx;
return rx;
else
return fail;
fi;
end );
#############################################################################
##
#F FGA_GetNr ( , )
##
InstallGlobalFunction( FGA_GetNr,
function( q, sl )
if not IsBound( q.nr ) then
Add( sl, q );
q.nr := Size( sl );
elif not IsBound( sl[ q.nr ] ) then
sl[ q.nr ] := q;
fi;
return q.nr;
end );
#############################################################################
##
#F FGA_FindRepInIntersection ( , , , )
##
InstallGlobalFunction( FGA_FindRepInIntersection,
function( A1, t1, A2, t2 )
local tab, sl1, sl2, Q, pair, g, q1, nr1, q2, nr2, r, rx;
sl1 := [];
sl2 := [];
q1 := A1!.initial;
q2 := A2!.initial;
if IsIdenticalObj( q1, t1) and
IsIdenticalObj( q2, t2) then
return [];
fi;
nr1 := FGA_GetNr( q1, sl1 );
nr2 := FGA_GetNr( q2, sl2 );
tab := [];
tab [ nr1 ] := [];
tab [ nr1 ][ nr2 ] := []; # empty word at initial state
Q := [ [ nr1, nr2 ] ];
for pair in Q do
q1 := sl1[ pair[1] ];
q2 := sl2[ pair[2] ];
r := tab [ pair[1] ] [ pair[2] ];
for g in Intersection( BoundPositions( q1.delta ),
BoundPositions( q2.delta ) ) do
nr1 := FGA_GetNr(q1.delta[g], sl1);
nr2 := FGA_GetNr(q2.delta[g], sl2);
rx := FGA_TrySetRepTable( tab, nr1, nr2, r, g );
if rx <> fail then
if IsIdenticalObj(sl1[ nr1 ], t1) and
IsIdenticalObj(sl2[ nr2 ], t2) then
return rx;
fi;
Add( Q, [ nr1, nr2 ] );
fi;
od;
for g in Intersection( BoundPositions( q1.deltainv ),
BoundPositions( q2.deltainv ) ) do
nr1 := FGA_GetNr(q1.deltainv[g], sl1);
nr2 := FGA_GetNr(q2.deltainv[g], sl2);
rx := FGA_TrySetRepTable( tab, nr1, nr2, r, -g );
if rx <> fail then
if IsIdenticalObj(sl1[ nr1 ], t1) and
IsIdenticalObj(sl2[ nr2 ], t2) then
return rx;
fi;
Add( Q, [ nr1, nr2 ] );
fi;
od;
od;
return fail;
end );
#############################################################################
##
#E
fga/lib/util.gd 0000644 0003717 0003717 00000000576 13275267465 015113 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W util.gd FGA package Christian Sievers
##
## Declarations of utility functions
##
#Y 2003 - 2012
##
DeclareGlobalFunction( "BoundPositions" );
DeclareGlobalFunction( "ATf" );
#############################################################################
##
#E
fga/lib/AutGrp.gd 0000644 0003717 0003717 00000005206 13275267465 015333 0 ustar gap-jenkins gap-jenkins #############################################################################
##
#W AutGrp.gd FGA package Christian Sievers
##
## Methods for automorphism groups of free groups
##
#Y 2003 - 2012
##
#############################################################################
##
#F IsAutomorphismGroupOfFreeGroup( )
##
## returns true if is the automorphism group of a free group.
##
DeclareFilter( "IsAutomorphismGroupOfFreeGroup" );
InstallTrueMethod( IsAutomorphismGroup,
IsAutomorphismGroupOfFreeGroup );
#############################################################################
##
#F FreeGroupEndomorphismByImages( , )
##
## returns the endomorphism of that maps the generators of
## to .
##
DeclareGlobalFunction( "FreeGroupEndomorphismByImages" );
#############################################################################
##
#F FreeGroupAutomorphismsGeneratorO( )
#F FreeGroupAutomorphismsGeneratorP( )
#F FreeGroupAutomorphismsGeneratorU( )
#F FreeGroupAutomorphismsGeneratorS( )
#F FreeGroupAutomorphismsGeneratorT( )
#F FreeGroupAutomorphismsGeneratorQ( )
#F FreeGroupAutomorphismsGeneratorR( )
##
## These functions return the automorphism of which maps the
## generators [, , ..., ] to
## O : [^-1 , , ..., ] (n>=1)
## P : [ , , , ..., ] (n>=2)
## U : [, , , ..., ] (n>=2)
## S : [^-1, ^-1, ..., ^-1, ^-1 ] (n>=1)
## T : [ , ^-1, , ..., ] (n>=2)
## Q : [, , ..., , ] (n>=2)
## R : [^-1, , , , ...,
## , ^-1,