polenta-1.3.11/000755 000766 000024 00000000000 14775712162 013542 5ustar00mhornstaff000000 000000 polenta-1.3.11/PackageInfo.g000644 000766 000024 00000007550 14775712140 016064 0ustar00mhornstaff000000 000000 ############################################################################# ## ## PackageInfo.g GAP4 Package `Polenta' Bjoern Assmann ## SetPackageInfo( rec( PackageName := "Polenta", Subtitle := "Polycyclic presentations for matrix groups", Version := "1.3.11", Date := "10/04/2025", # dd/mm/yyyy format License := "GPL-2.0-or-later", Persons := [ rec( LastName := "Assmann", FirstNames := "Björn", IsAuthor := true, IsMaintainer := false, ), rec( LastName := "Horn", FirstNames := "Max", IsAuthor := false, IsMaintainer := true, Email := "mhorn@rptu.de", WWWHome := "https://www.quendi.de/math", PostalAddress := Concatenation( "Fachbereich Mathematik\n", "RPTU Kaiserslautern-Landau\n", "Gottlieb-Daimler-Straße 48\n", "67663 Kaiserslautern\n", "Germany" ), Place := "Kaiserslautern, Germany", Institution := "RPTU Kaiserslautern-Landau" ), ], Status := "accepted", CommunicatedBy := "Charles Wright (Eugene)", AcceptDate := "08/2005", PackageWWWHome := "https://gap-packages.github.io/polenta/", README_URL := Concatenation(~.PackageWWWHome, "README.md"), PackageInfoURL := Concatenation(~.PackageWWWHome, "PackageInfo.g"), ArchiveURL := Concatenation("https://github.com/gap-packages/polenta/", "releases/download/v", ~.Version, "/polenta-", ~.Version), ArchiveFormats := ".tar.gz .tar.bz2", SourceRepository := rec( Type := "git", URL := "https://github.com/gap-packages/polenta" ), IssueTrackerURL := Concatenation( ~.SourceRepository.URL, "/issues" ), AbstractHTML := "The Polenta package provides methods to compute polycyclic presentations of matrix groups (finite or infinite). As a by-product, this package gives some functionality to compute certain module series for modules of solvable groups. For example, if G is a rational polycyclic matrix group, then we can compute the radical series of the natural Q[G]-module Q^d.", PackageDoc := rec( BookName := "Polenta", ArchiveURLSubset := [ "doc" ], HTMLStart := "doc/chap0_mj.html", PDFFile := "doc/manual.pdf", SixFile := "doc/manual.six", LongTitle := "Polycyclic presentations for matrix groups", ), Dependencies := rec( GAP := ">= 4.7", NeededOtherPackages := [[ "polycyclic", "2.10.1" ], [ "alnuth" , "2.2.3"], [ "radiroot", "2.4" ], ], SuggestedOtherPackages := [ ["aclib", "1.0"]], ), AvailabilityTest := ReturnTrue, TestFile := "tst/testall.g", Keywords := [ "polycyclic presentations", "matrix groups", "test solvability", "triangularizable subgroup", "unipotent subgroup", "radical series", "composition series of triangularizable groups" ], AutoDoc := rec( TitlePage := rec( Copyright := "\ License\ ©right; 2003-2007 by Björn Assmann

\ The &Polenta; package is free software; \ you can redistribute it and/or modify it under the terms of the \ https://www.fsf.org/licenses/gpl.html \ as published by the Free Software Foundation; either version 2 of the License, \ or (at your option) any later version.", Acknowledgements := "\ We appreciate very much all past and future comments, suggestions and \ contributions to this package and its documentation provided by &GAP; \ users and developers.", ), ), )); ############################################################################# ## #E polenta-1.3.11/LICENSE000644 000766 000024 00000036466 14775712140 014562 0ustar00mhornstaff000000 000000 The polenta 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 opinion) any later version. The polenta package 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. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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 polenta-1.3.11/CHANGES000644 000766 000024 00000006125 14775712140 014535 0ustar00mhornstaff000000 000000 =========================================================================== This file describes changes in 'Polenta'. This file was added after the 1.2.7 release. Any information pertaining older Polenta versions may not be complete accurate, as it was re-created from old records. If you notice anything amiss, please let us know. =========================================================================== 1.3.11 (2025-04-10) - Updated Max Horn's contact details once again ... - Janitorial changes 1.3.10 (2022-03-29) - Updated Max Horn's contact details - Janitorial changes 1.3.9 (2019-10-01) - Janitorial changes 1.3.8 (2017-11-29) - Internal changes (use TestDirectory() to run tests in tst/testall.g) 1.3.7 (2016-11-09) - Disabled some unused code for multiplicative Jordan decomposition and for simultaneously diagonalizing commuting matrices - Avoid using polycyclic's NaturalHomomorphism operation, instead use NaturalHomomorphismByNormalSubgroup 1.3.6 (2016-03-08) - Internal changes (refactor ClosureBasePcgs_word, fix a URL) 1.3.5 (2016-02-14) - Fix a bug in IsomorphismPcpGroup for finite matrix groups 1.3.4 (2016-01-07) - Move website to https://gap-packages.github.io/recogbase/ 1.3.3 (2014-11-28) o Fixed a bug in ExponentVector_AbelianSS which could lead to IsomorphismPcpGroup running into an error. 1.3.2 (2014-04-01) o Moved the homepage o Updated Max Horn's contact details o Changed how the manual is built (now AutoDoc is used to automatically generate the title page from PackageInfo.g) 1.3.1 (2012-06-01) o Fixed warning when loading without aclib o Some minor tweaks and cleanups 1.3 (2011-09-23) o Updated README o Added GPL license text o Added this CHANGES file o Fixed bug in POL_KroneckerProduct (used by the examples) o Added Max Horn as addition package maintainer; removed outdated email address for Bjoern Assmann and removed his maintainer flag (at least for the time being, due to lack of time on his part) o Removed references to KANT / KASH -- which is a dependency of (old versions of) Alnuth, so we should not have to worry about it here. o Fixed handling of matrix groups over finite fields that are not prime fields. o Changed IsSolvableGroup method installation so that calling them on matrix groups not defined over a field does not cause weird errors anymore. o Changed the IsPolycyclicMatGroup methods to IsPolycyclicGroup methods, so that more code can automatically benefit from this functionality. The only remaining IsPolycyclicMatGroup method simply invokes IsPolycyclicGroup. It will be removed in a future version. o Converted documentation to GAPDoc format. o Turn IsTriangularizableMatGroup into a property. o Fixed bug that could cause an error while building an isomorphism from a matrix group to a pcp group. 1.2.7 (2007-06-17) o TODO 1.2.6 (2007-06-11) o TODO 1.2.5 (2007-06-10) o TODO 1.2.4 (2007-06-07) o TODO 1.2.3 (2006-07-17) o TODO 1.2.2 (2006-01-10) o TODO 1.2.1 (2005-08-09) o TODO 1.2 (2004-02-04) o TODO 1.1 (2003-11-02) o TODO 1.0 (2003-11-02) o TODO polenta-1.3.11/TODO000644 000766 000024 00000000624 14775712140 014230 0ustar00mhornstaff000000 000000 * update documentation to match latest reality * check copyright data * add GPL headers to files as appropriate * Consider removing "documentation" for methods like ImageElm, IsSolvableGroup or at least rewrite it to make clear that what Polenta does is providing a new *method* for these, but that the functions themselves are part of GAP... * Implement IsTriangularizableMatGroup for FFE groups? polenta-1.3.11/README.md000644 000766 000024 00000006410 14775712140 015016 0ustar00mhornstaff000000 000000 [![Build Status](https://github.com/gap-packages/polenta/workflows/CI/badge.svg?branch=master)](https://github.com/gap-packages/polenta/actions?query=workflow%3ACI+branch%3Amaster) [![Code Coverage](https://codecov.io/github/gap-packages/polenta/coverage.svg?branch=master&token=)](https://codecov.io/gh/gap-packages/polenta) The GAP 4 package `Polenta` =========================== This package provides functions for computation with matrix groups. Let $G$ be a subgroup of $GL(d,R)$ where the ring $R$ is either equal to $\Q,\Z$ or a finite field $\F_q$. Then: - We can test whether $G$ is solvable. - We can test whether $G$ is polycyclic. - If $G$ is polycyclic, then we can determine a polycyclic presentation for $G$. A group $G$ which is given by a polycyclic presentations can be largely investigated by algorithms implemented in the GAP-package Polycyclic. For example we can determine if $G$ is torsion-free and calculate the torsion subgroup. Further we can compute the derived series and the Hirschlength of the group $G$. Also various methods for computations with subgroups, factorsgroups and extensions are available. As a by-product, the Polenta package provides some functionality to compute certain module series for modules of solvable groups. For example, if $G$ is a rational polycyclic matrix group, then we can compute the radical series of the natural $\Q[G]$-module $\Q^d$. Installing this package ======================= The Polenta package is part of the standard distribution of GAP and so normally there should be no need to install it separately. If by any chance it is not part of your GAP distribution, then this package is available at in form of a gzipped tar-archive. The standard method is to unpack the package into the `pkg` directory of your GAP distribution. This will create a `polenta` subdirectory. For other non-standard options please refer to the GAP Reference Manual. Note that the GAP-Packages Alnuth and Polycyclic are needed for this package. Normally they should be contained in your distribution. If not they can be obtained at . Loading the Polenta package ========================== If the Package is not already loaded then you have to request it explicitly. This can be done by `LoadPackage("polenta")`. The `LoadPackage` command is described in the GAP Reference Manual. Running the test suite ====================== Once the package is installed, it is possible to check the correct installation by running the test suite of the package. gap> ReadPackage( "Polenta", "tst/testall.g" ); For more details on Test Files see Section 7.9 of the GAP Reference Manual. If the test suite runs into an error, even though the packages Polycyclic and Alnuth and their depdendencies have been correctly installed, then please send a message to including the error message. Author / Maintainer =================== The Polenta package was originally written by Bjoern Assmann, who remains his principal author. It is currently being maintained by Max Horn . To submit bug reports, feature requests and suggestions, please go to . polenta-1.3.11/makedoc.g000644 000766 000024 00000000613 14775712140 015311 0ustar00mhornstaff000000 000000 # # Generate the manual using AutoDoc # if fail = LoadPackage("AutoDoc", ">= 2016.01.21") then Error("AutoDoc 2016.01.21 or newer is required"); fi; AutoDoc(rec( scaffold := rec( bib := "polentabib.xml", includes := [ "intro.xml", "methods.xml", "example.xml", "install.xml", "info.xml", ], ) )); polenta-1.3.11/lib/000755 000766 000024 00000000000 14775712140 014304 5ustar00mhornstaff000000 000000 polenta-1.3.11/doc/000755 000766 000024 00000000000 14775712162 014307 5ustar00mhornstaff000000 000000 polenta-1.3.11/exam/000755 000766 000024 00000000000 14775712140 014470 5ustar00mhornstaff000000 000000 polenta-1.3.11/tst/000755 000766 000024 00000000000 14775712140 014350 5ustar00mhornstaff000000 000000 polenta-1.3.11/init.g000644 000766 000024 00000001434 14775712140 014653 0ustar00mhornstaff000000 000000 ############################################################################# ## #W init.g POLENTA package Bjoern Assmann ## ## #Y 2003 ## ############################################################################# #R read .gd files ## ReadPackage( "polenta", "lib/finite.gd" ); ReadPackage( "polenta", "lib/info.gd" ); ReadPackage( "polenta", "lib/basic.gd" ); ReadPackage( "polenta", "exam/test.gd" ); ReadPackage( "polenta", "lib/cpcs.gd" ); ReadPackage( "polenta", "lib/present.gd" ); ReadPackage( "polenta", "lib/solvable.gd" ); ReadPackage( "polenta", "lib/series.gd" ); ReadPackage( "polenta", "lib/subgroups.gd" ); ReadPackage( "polenta", "lib/ispolyz.gd" ); ############################################################################# ## #E polenta-1.3.11/read.g000644 000766 000024 00000001754 14775712140 014630 0ustar00mhornstaff000000 000000 ############################################################################# ## #W read.g POLENTA package Bjoern Assmann ## ## #Y 2003 ## ############################################################################# ## #R read files ## ReadPackage( "polenta", "lib/finite.gi" ); ReadPackage( "polenta", "lib/basic.gi" ); ReadPackage( "polenta", "lib/unipo.gi" ); ReadPackage( "polenta", "lib/series.gi" ); ReadPackage( "polenta", "lib/semi.gi" ); ReadPackage( "polenta", "lib/ispoly.gi" ); ReadPackage( "polenta", "lib/cpcs.gi" ); ReadPackage( "polenta", "lib/present.gi" ); ReadPackage( "polenta", "lib/isom.gi" ); ReadPackage( "polenta", "lib/solvable.gi" ); ReadPackage( "polenta", "exam/exam.gi" ); ReadPackage( "polenta", "exam/test.gi" ); ReadPackage( "polenta", "lib/subgroups.gi" ); ReadPackage( "polenta", "lib/ispolyz.gi" ); #ReadPackage( "polenta", "lib/jordan.gi" ); ############################################################################# ## #E polenta-1.3.11/tst/POLENTA.tst000644 000766 000024 00000002357 14775712140 016215 0ustar00mhornstaff000000 000000 gap> START_TEST("Test of POLENTA package"); # gap> mats := [ [ [ 1, 0, 0, 3/2, 0 ], [ 0, 1, 0, 0, 1 ], [ 0, 0, 1, 0, 0 ],[ 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1 ] ], [ [ 1, 0, 0, 1, 0 ], [ 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 1 ], [ 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1 ] ], [ [ 1, -3/2, -1, 0, 0 ], [ 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 1 ], [ 0, 0, 0, 0, 1 ] ], [ [ 1, 0, 0, 0, 1 ], [ 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1 ] ], [ [ 1, 1, -1, -2, 2 ], [ 0, -1, 0, 0, 0 ], [ 0, 0, -1, 0, 0 ],[ 0, 0, 0, -1, 0 ], [ 0, 0, 0, 0, 1 ] ] ];; gap> G := Group( mats );; gap> nat := IsomorphismPcpGroup( G );; gap> H := Image( nat );; gap> h := GeneratorsOfGroup( H );; gap> mats2 := List( h, x -> PreImage( nat, x ) );; gap> exp := [ 1, 1, 1, 1, 1 ];; gap> g := MappedVector( exp, mats2 );; gap> i := ImageElm( nat, g );; gap> Exponents( i ); [ 1, 1, 1, 1, 1 ] gap> PreImagesRepresentative( nat, i );; gap> last = g; true gap> IsPolycyclicMatGroup( G ); true gap> IsTriangularizableMatGroup( G ); true gap> IsSolvable( G ); true gap> mats_f := mats* One( GF(3 ) );; gap> G_f := Group( mats_f );; gap> IsSolvable( G_f ); true gap> IsPolycyclicMatGroup( G_f ); true gap> Size( G_f ); 162 # gap> STOP_TEST( "POLENTA.tst", 100000); polenta-1.3.11/tst/bugfix.tst000644 000766 000024 00000012674 14775712140 016402 0ustar00mhornstaff000000 000000 gap> START_TEST("bugfix.tst"); # gap> m := > [ [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, -1 ] ], > [ [ 1, 0, 0 ], [ 0, -1, 0 ], [ 0, 0, 1 ] ], > [ [ -1, 0, 0 ], [ 0, -1, 0 ], [ 0, 0, 1 ] ], > [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, -1 ] ], > [ [ -1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] ];; gap> M := Group(m); gap> matrix := [ [ -1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]; [ [ -1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] gap> IsomorphismPcpGroup(M); [ [ [ -1, 0, 0 ], [ 0, -1, 0 ], [ 0, 0, 1 ] ], [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, -1 ] ], [ [ -1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] ] -> [ g1, g2, g3 ] # GitHub issue #2: an error in IsomorphismPcpGroup gap> G := Group(Z(7)^0 * > [ [ [ Z(7), 0, 0, 0, 0, 0, 0, 0 ], > [ 0, Z(7), 0, 0, 0, 0, 0, 0 ], > [ 0, 0, Z(7), 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7), 0, 0, 0, 0 ], > [ 0, 0, 0, 0, Z(7), 0, 0, 0 ], > [ 0, 0, 0, 0, 0, Z(7), 0, 0 ], > [ 0, 0, 0, 0, 0, 0, Z(7), 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7) ] ], > [ [ 0, 0, 0, 0, Z(7)^5, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, Z(7)^5, 0, 0 ], > [ 0, 0, 0, 0, 0, 0, Z(7)^5, 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7)^5 ], > [ Z(7)^2, 0, 0, 0, 0, 0, 0, 0 ], > [ 0, Z(7)^2, 0, 0, 0, 0, 0, 0 ], > [ 0, 0, Z(7)^2, 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7)^2, 0, 0, 0, 0 ] ], > [ [ 0, 0, 0, 0, Z(7)^4, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, Z(7)^4, 0, 0 ], > [ 0, 0, 0, 0, 0, 0, Z(7)^4, 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7)^4 ], > [ Z(7), 0, 0, 0, 0, 0, 0, 0 ], > [ 0, Z(7), 0, 0, 0, 0, 0, 0 ], > [ 0, 0, Z(7), 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7), 0, 0, 0, 0 ] ], > [ [ 0, 0, 0, 0, 0, 0, 0, Z(7)^5 ], > [ 0, 0, 0, 0, 0, 0, Z(7)^2, 0 ], > [ 0, 0, 0, 0, 0, Z(7)^5, 0, 0 ], > [ 0, 0, 0, 0, Z(7)^2, 0, 0, 0 ], > [ 0, 0, 0, Z(7)^2, 0, 0, 0, 0 ], > [ 0, 0, Z(7)^5, 0, 0, 0, 0, 0 ], > [ 0, Z(7)^2, 0, 0, 0, 0, 0, 0 ], > [ Z(7)^5, 0, 0, 0, 0, 0, 0, 0 ] ], > [ [ 0, Z(7), 0, 0, 0, 0, 0, 0 ], > [ Z(7)^4, 0, 0, 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7)^4, 0, 0, 0, 0 ], > [ 0, 0, Z(7), 0, 0, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, Z(7), 0, 0 ], > [ 0, 0, 0, 0, Z(7)^4, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7)^4 ], > [ 0, 0, 0, 0, 0, 0, Z(7), 0 ] ], > [ [ 0, 1, 0, 0, 0, 0, 0, 0 ], > [ Z(7)^3, 0, 0, 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7)^3, 0, 0, 0, 0 ], > [ 0, 0, 1, 0, 0, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, 1, 0, 0 ], > [ 0, 0, 0, 0, Z(7)^3, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7)^3 ], > [ 0, 0, 0, 0, 0, 0, 1, 0 ] ], > [ [ 0, 0, 0, 0, Z(7)^4, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, Z(7)^4, 0, 0 ], > [ 0, 0, 0, 0, 0, 0, Z(7)^4, 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7)^4 ], > [ Z(7)^4, 0, 0, 0, 0, 0, 0, 0 ], > [ 0, Z(7)^4, 0, 0, 0, 0, 0, 0 ], > [ 0, 0, Z(7)^4, 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7)^4, 0, 0, 0, 0 ] ], > [ [ Z(7)^4, 0, 0, 0, 0, 0, 0, 0 ], > [ 0, Z(7)^4, 0, 0, 0, 0, 0, 0 ], > [ 0, 0, Z(7), 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7), 0, 0, 0, 0 ], > [ 0, 0, 0, 0, Z(7)^4, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, Z(7)^4, 0, 0 ], > [ 0, 0, 0, 0, 0, 0, Z(7), 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7) ] ], > [ [ Z(7)^2, 0, 0, 0, 0, 0, 0, 0 ], > [ 0, Z(7)^5, 0, 0, 0, 0, 0, 0 ], > [ 0, 0, Z(7)^2, 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7)^5, 0, 0, 0, 0 ], > [ 0, 0, 0, 0, Z(7)^2, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, Z(7)^5, 0, 0 ], > [ 0, 0, 0, 0, 0, 0, Z(7)^2, 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7)^5 ] ], > [ [ Z(7)^2, 0, 0, 0, 0, 0, 0, 0 ], > [ 0, Z(7)^2, 0, 0, 0, 0, 0, 0 ], > [ 0, 0, Z(7)^2, 0, 0, 0, 0, 0 ], > [ 0, 0, 0, Z(7)^2, 0, 0, 0, 0 ], > [ 0, 0, 0, 0, Z(7)^2, 0, 0, 0 ], > [ 0, 0, 0, 0, 0, Z(7)^2, 0, 0 ], > [ 0, 0, 0, 0, 0, 0, Z(7)^2, 0 ], > [ 0, 0, 0, 0, 0, 0, 0, Z(7)^2 ] ], > [ [ 0, Z(7), 0, Z(7)^4, 0, Z(7), 0, Z(7)^4 ], > [ Z(7), 0, Z(7), 0, Z(7), 0, Z(7), 0 ], > [ 0, Z(7)^4, 0, Z(7), 0, Z(7), 0, Z(7)^4 ], > [ Z(7)^4, 0, Z(7)^4, 0, Z(7), 0, Z(7), 0 ], > [ Z(7)^4, 0, Z(7), 0, Z(7), 0, Z(7)^4, 0 ], > [ 0, Z(7), 0, Z(7), 0, Z(7)^4, 0, Z(7)^4 ], > [ Z(7), 0, Z(7)^4, 0, Z(7), 0, Z(7)^4, 0 ], > [ 0, Z(7)^4, 0, Z(7)^4, 0, Z(7)^4, 0, Z(7)^4 ] ], > [ [ 1, Z(7)^3, Z(7)^3, 1, Z(7)^3, 1, 1, Z(7)^3 ], > [ Z(7)^3, 1, Z(7)^3, 1, 1, Z(7)^3, 1, Z(7)^3 ], > [ Z(7)^3, Z(7)^3, Z(7)^3, Z(7)^3, Z(7)^3, Z(7)^3, Z(7)^3, Z(7)^3 ], > [ 1, 1, Z(7)^3, Z(7)^3, 1, 1, Z(7)^3, Z(7)^3 ], > [ Z(7)^3, 1, Z(7)^3, 1, Z(7)^3, 1, Z(7)^3, 1 ], > [ 1, Z(7)^3, Z(7)^3, 1, 1, Z(7)^3, Z(7)^3, 1 ], > [ 1, 1, Z(7)^3, Z(7)^3, Z(7)^3, Z(7)^3, 1, 1 ], > [ Z(7)^3, Z(7)^3, Z(7)^3, Z(7)^3, 1, 1, 1, 1 ] ], > [ [ 0, Z(7)^4, 0, Z(7), Z(7)^4, 0, Z(7), 0 ], > [ Z(7)^4, 0, Z(7)^4, 0, 0, Z(7), 0, Z(7) ], > [ 0, Z(7)^4, 0, Z(7), Z(7), 0, Z(7)^4, 0 ], > [ Z(7)^4, 0, Z(7)^4, 0, 0, Z(7)^4, 0, Z(7)^4 ], > [ Z(7), 0, Z(7)^4, 0, 0, Z(7)^4, 0, Z(7) ], > [ 0, Z(7), 0, Z(7), Z(7), 0, Z(7), 0 ], > [ Z(7)^4, 0, Z(7), 0, 0, Z(7)^4, 0, Z(7) ], > [ 0, Z(7)^4, 0, Z(7)^4, Z(7), 0, Z(7), 0 ] ] ]); gap> iso := IsomorphismPcpGroup(G);; # this gap> Size(Image(iso)); 16128 gap> Image(iso); Pcp-group with orders [ 3, 2, 3, 7, 2, 2, 2, 2, 2, 2, 2 ] # gap> STOP_TEST( "bugfix.tst", 100000); polenta-1.3.11/tst/POLENTA3.tst000644 000766 000024 00000004507 14775712140 016277 0ustar00mhornstaff000000 000000 gap> START_TEST("Test 3 of POLENTA package"); # gap> SetInfoLevel( InfoPolenta, 0 );; # gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 5 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 6 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 7 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 8 ) ); # gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -16 ) ); # gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 46 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 47 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 48 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 49 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 50 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 51 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 52 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 53 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 54 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 55 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 56 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 57 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 58 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( 59 ) ); # gap> POL_Test_AllFunctions_PolExamples( 20,31 ); Test of group 20 Test of group 21 The input group is not triangularizable. The input group is not triangularizable. Test of group 22 Test of group 23 The input group is not triangularizable. The input group is not triangularizable. Test of group 24 The input group is not triangularizable. The input group is not triangularizable. Test of group 25 # gap> STOP_TEST( "POLENTA3.tst", 100000); polenta-1.3.11/tst/POLENTA2.tst000644 000766 000024 00000004703 14775712140 016274 0ustar00mhornstaff000000 000000 gap> START_TEST("Test 2 of POLENTA package"); # gap> SetInfoLevel( InfoPolenta, 0 );; # gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -18 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -17 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -15 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -14 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -13 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -12 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -11 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -10 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -9 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -8 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -7 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -6 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -5 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -4 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -3 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -2 ) ); gap> POL_Test_AllFunctions_PRMGroup( POL_PolExamples2( -1 ) ); # gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 1 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 2 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 3 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 4 ) ); # gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 9 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 10 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 11 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 12 ) ); The input group is not triangularizable. The input group is not triangularizable. gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 13 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 14 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 15 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 16 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 17 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 18 ) ); gap> POL_Test_AllFunctions_PRMGroup( PolExamples( 19 ) ); # gap> STOP_TEST( "POLENTA2.tst", 100000); polenta-1.3.11/tst/polenta_finite.tst000644 000766 000024 00000002411 14775712140 020102 0ustar00mhornstaff000000 000000 # A test case involving a maximal unipotent subgroup of SU(6,5). # This group is given here by matrices over GF(25), not GF(5). # This triggered a bug in polenta versions up to and including 1.2.7. gap> START_TEST("Test of POLENTA package with finite field matrices"); gap> z:=Z(5^2);; gap> mats := [ [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 0, 0, z^3, 1, 0, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 1 ] ], [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, z^12, 1, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 1, 0 ], [ 0, 0, 0, 0, 0, 1 ] ], [ [ 1, 0, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0, 0 ], [ 0, z^17, 1, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, z, 1, 0 ], [ 0, 0, 0, 0, 0, 1 ] ] ] * One(z);; gap> G := Group( mats );; gap> nat := IsomorphismPcpGroup( G );; gap> H := Image( nat ); Pcp-group with orders [ 5, 5, 5, 5, 5, 5 ] gap> h := GeneratorsOfGroup( H );; gap> mats2 := List( h, x -> PreImage( nat, x ) );; gap> exp := [ 1, 1, 1, 1, 1, 1 ];; gap> g := MappedVector( exp, mats2 );; gap> i := ImageElm( nat, g );; gap> Exponents( i ); [ 1, 1, 1, 1, 1, 1 ] gap> PreImagesRepresentative( nat, i );; gap> last = g; true gap> IsPolycyclicMatGroup( G ); true gap> IsSolvable( G ); true gap> Size( H ); 15625 gap> STOP_TEST( "polenta_finite.tst", 100000); polenta-1.3.11/tst/testall.g000644 000766 000024 00000000647 14775712140 016177 0ustar00mhornstaff000000 000000 LoadPackage( "polenta" ); dirs := DirectoriesPackageLibrary( "polenta", "tst" ); tests := [ "bugfix.tst", "polenta_finite.tst", "POLENTA.tst", #"POLENTA2.tst", # slow; requires aclibe #"POLENTA3.tst", # VERY slow ]; if IsPackageMarkedForLoading( "aclib" , "1.0" ) then Add(tests, "POLENTA2.tst"); # slow fi; tests := List(tests, f -> Filename(dirs,f)); TestDirectory(tests, rec(exitGAP := true)); polenta-1.3.11/exam/exam.gi000644 000766 000024 00000204543 14775712140 015753 0ustar00mhornstaff000000 000000 ############################################################################# ## #W exam.gi POLENTA package Bjoern Assmann ## ## examples for polycyclic rational matrix groups ## #Y 2003 ## ############################################################################# ## #F POL_KroneckerProduct ## ## Examples built with the Kroneckerproduct. ## POL_KroneckerProduct := function( G, e ) local newGens, gens; gens := GeneratorsOfGroup( G ); if e = 0 then e := RandomList( [1,-1] ); fi; newGens := List( gens, x->KroneckerProduct(x,x^e) ); return Group( newGens ); end; ############################################################################# ## #F POL_AlmostCrystallographicGroup ## ## Examples coming from aclib ## if not IsPackageMarkedForLoading( "aclib" , "1.0" ) then POL_AlmostCrystallographicGroup := false; else POL_AlmostCrystallographicGroup := function( a,b,c ) local G, mats; G := AlmostCrystallographicGroup(a,b,c); mats := GeneratorsOfGroup( G ); G := Group( mats ); return G; end; fi; ############################################################################# ## #F PolExamples( n ) .............. .. Examples for polycyc rat. matrix groups ## # FIXME: This function is documented and should be turned into a GlobalFunction PolExamples := function( n ) local i,M,P, nat, G, gens, d, l,r,s; # check if aclib is needed l := Concatenation( [9..19],[21..24]); if POL_AlmostCrystallographicGroup = false then if n in l then Print( "package 'aclib' is needed for this example.\n" ); return fail; fi; fi; # some unipotent groups if n=1 then return Group( [ [ [ 1, -4, 1, 2 ], [ 0, 1, 5, 1 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ] , [ [ 1, -1, -2, 4 ], [ 0, 1, -1, 1 ], [ 0, 0, 1, 1 ], [ 0, 0, 0, 1 ] ] , [ [ 1, -4, -2, 1 ], [ 0, 1, -2, -3 ], [ 0, 0, 1, 2 ], [ 0, 0, 0, 1 ] ] ]); fi; if n=2 then return Group( [ [ [ 1, 5, -3, 1, -3 ], [ 0, 1, 2, 0, 1 ], [ 0, 0, 1, 2, -2 ], [ 0, 0, 0, 1, -2 ], [ 0, 0, 0, 0, 1 ] ] , [ [ 1, 3, -3, -1, 1 ], [ 0, 1, 0, -2, 2 ], [ 0, 0, 1, 4, 1 ], [ 0, 0, 0, 1, -1 ], [ 0, 0, 0, 0, 1 ] ] ]); fi; if n=3 then return Group( [ [ [ 73/10, -35/2, 42/5, 63/2 ], [ 27/20, -11/4, 9/5, 27/4 ], [ -3/5, 1, -4/5, -9 ], [ -11/20, 7/4, -2/5, 1/4 ] ] , [ [ -42/5, 423/10, 27/5, 479/10 ], [ -23/10, 227/20, 13/10, 231/20 ], [ 14/5, -63/5, -4/5, -79/5 ], [ -1/10, 9/20, 1/10, 37/20 ] ] ]); fi; if n=4 then return Group( [ [ [ 5, 2, -8, 17, -1 ], [ -69/4, -15/4, 449/20, -163/5, 53/20 ], [ -2, 4, 9/5, 63/5, 3/5 ], [ 13/4, 3/4, -121/20, 57/5, -17/20 ], [ 241/4, 7/4, -1477/20, 319/5, -189/20 ] ] , [ [ 19/2, 0, -3, -19/2, -1/2 ], [ -74/5, 129/20, 7/4, 159/4, 9/10 ], [ 53/10, 4/5, -4, 9/2, -9/10 ], [ 37/10, -41/20, -7/4, -29/4, -3/5 ], [ 137/5, -457/20, 37/4, -559/4, 3/10 ] ] ]); fi; if n in [5..8] then return MatExamples( n-4 ); fi; if n=9 then return POL_AlmostCrystallographicGroup( 3, 17, [1,0,-3,7] ); fi; if n=10 then return POL_AlmostCrystallographicGroup( 3, 16, [3,4,-1,0] ); fi; if n=11 then return POL_AlmostCrystallographicGroup( 3, 15, [-1,1,0,0] ); fi; if n=12 then return POL_AlmostCrystallographicGroup( 3, 14, [-2,-1,2,-1] ); fi; if n=13 then return POL_AlmostCrystallographicGroup( 4, 2, [0,-3,-2,1,-1,-2,4] ); fi; if n=14 then return POL_AlmostCrystallographicGroup( 4, 13, [-2,0,-2,-2,-1,-1] ); fi; if n=15 then return POL_AlmostCrystallographicGroup( 4, 37, [ 1,2,0,-3,-4] ); fi; if n=16 then return POL_AlmostCrystallographicGroup( 4, 86,[0,-2,-1,-2,-1] ); fi; if n=17 then return POL_AlmostCrystallographicGroup( 4, 10,[-2,-2,-1] ); fi; if n=18 then return POL_AlmostCrystallographicGroup( 4, 11,[-4,-2,-1] ); fi; if n=19 then return POL_AlmostCrystallographicGroup( 4, 12,[0,1,3,-1] ); fi; if n=20 then return POL_KroneckerProduct( MatExamples(4), -1 ); fi; if n in [21..24] then return POL_KroneckerProduct( PolExamples( n-12 ), 1 ); fi; if n = 25 then #Marco Costantini example r := [ [ 1, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0, 0, 1 ], [ 0, 1, 0, 0, 0, 0, 0, 0 ] ]; s := [ [ 1, 0, 0, 0, 0, 0, 0, 1 ], [ 0, E(7)^6, 0, 0, 0, 0, 0, 0 ], [ 0, 0, E(7), 0, 0, 0, 0, 0 ], [ 0, 0, 0, 1, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 1, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 0, 0, 1 ] ]; return Group( [r,s^7] ); fi; if n = 26 then # subgroup of a group which is conjugate to a direct product # of PolExamples(1) and PolExamples(6); gens := [ [ [ -403, 2500, 32, -633, -1638, 800, 2073, 406 ], [ 3, 37, 20, -9, 5, -11, 29, 7 ], [ -65, -16, 5, 3, -73, 129, -43, 59 ] , [ -37, -2936, 80, 735, 1366, 54, -2676, 28 ], [ 2, -788, 0, 197, 364, -4, -707, -12 ], [ -207, 20, 16, -9, -263, 411, -71, 191 ], [ -13, -1276, 0, 319, 567, 26, -1152, -6 ], [ 8, 972, 0, -243, -434, -16, 877, 7 ] ], [ [ -615, 40, -64, -12, -850, 1248, -241, 515 ], [ -9, 37, -4, -9, -31, 19, 29, 7 ], [ -39, 347, -7, -87, -205, 80, 293, 41 ], [ 437, 3676, -16, -918, -1054, -870, 3495, -290 ], [ 106, 748, 0, -187, -189, -212, 719, -72 ], [ -149, 1184, -32, -297, -727, 307, 995, 151 ], [ 187, 1376, 0, -344, -359, -374, 1319, -126 ], [ -106, -816, 0, 204, 217, 212, -779, 70 ] ], [ [ -352, -632, -64, 150, -246, 722, -699, 251 ], [ 17, -107, -8, 27, 63, -32, -87, -21 ], [ -59, -16, -7, 3, -73, 120, -37, 51 ], [ -58, 84, -32, -20, -93, 124, 64, 87 ], [ -2, 220, 0, -55, -90, 4, 199, 18 ], [ -188, -16, -32, 0, -256, 385, -82, 160 ], [ -36, 260, 0, -65, -144, 72, 221, 57 ], [ 3, -228, 0, 57, 94, -6, -206, -20 ] ], [ [ 893, 7836, 0, -1959, -2319, -1784, 7446, -585 ], [ 0, 1, 0, 0, 0, 0, 0, 0 ], [ 76, 456, 1, -114, -102, -152, 444, -54 ], [ -210, -4128, 0, 1033, 1567, 420, -3805, 87 ], [ -158, -1776, 0, 444, 587, 316, -1668, 96 ], [ 228, 1368, 0, -342, -306, -455, 1332, -162 ], [ -142, -2088, 0, 522, 746, 284, -1940, 75 ], [ 190, 2100, 0, -525, -690, -380, 1974, -116 ] ], [ [ -1656, -60, 0, 15, -1925, 3314, -920, 1473 ], [ 0, 1, 0, 0, 0, 0, 0, 0 ], [ -46, 0, 1, 0, -50, 92, -26, 42 ], [ 1626, 236, 0, -58, 1847, -3252, 1043, -1434 ], [ 468, 20, 0, -5, 551, -936, 259, -414 ], [ -138, 0, 0, 0, -150, 277, -78, 126 ], [ 700, 76, 0, -19, 805, -1400, 428, -618 ], [ -519, 0, 0, 0, -621, 1038, -267, 460 ] ], [ [ -427, -4608, 0, 1152, 1464, 856, -4359, 207 ], [ 0, 1, 0, 0, 0, 0, 0, 0 ], [ -104, -360, 1, 90, 36, 208, -372, 90 ], [ -525, 2300, 0, -574, -1560, 1050, 1845, 660 ], [ -48, 876, 0, -219, -421, 96, 771, 96 ], [ -312, -1080, 0, 270, 108, 625, -1116, 270 ], [ -171, 1104, 0, -276, -657, 342, 923, 234 ], [ 58, -936, 0, 234, 457, -116, -821, -110 ] ], [ [ -479, 2668, -64, -669, -1882, 976, 2189, 434 ], [ -9, 37, -4, -9, -31, 19, 29, 7 ], [ -71, -13, -7, 3, -91, 144, -43, 59 ], [ -85, -2936, -16, 735, 1222, 174, -2676, 28 ], [ 2, -788, 0, 197, 364, -4, -707, -12 ], [ -245, 104, -32, -27, -385, 499, -13, 205 ], [ -13, -1276, 0, 319, 567, 26, -1152, -6 ], [ 8, 972, 0, -243, -434, -16, 877, 7 ] ], [ [ -539, -128, 32, 24, -606, 1072, -357, 487 ], [ 3, 37, 20, -9, 5, -11, 29, 7 ], [ -33, 344, 5, -87, -187, 65, 293, 41 ], [ 485, 3676, 80, -918, -910, -990, 3495, -290 ], [ 106, 748, 0, -187, -189, -212, 719, -72 ], [ -111, 1100, 16, -279, -605, 219, 937, 137 ], [ 187, 1376, 0, -344, -359, -374, 1319, -126 ], [ -106, -816, 0, 204, 217, 212, -779, 70 ] ], [ [ -352, -632, -64, 150, -246, 722, -699, 251 ], [ 17, -107, -8, 27, 63, -32, -87, -21 ], [ -59, -16, -7, 3, -73, 120, -37, 51 ], [ -58, 84, -32, -20, -93, 124, 64, 87 ], [ -2, 220, 0, -55, -90, 4, 199, 18 ], [ -188, -16, -32, 0, -256, 385, -82, 160 ], [ -36, 260, 0, -65, -144, 72, 221, 57 ], [ 3, -228, 0, 57, 94, -6, -206, -20 ] ] ]; return Group( gens ); fi; if n = 27 then # subgroup of a group which is conjugate to a direct product # of PolExamples(3) and PolExamples(5); gens := [ [ [ -396/5, 49, -4/5, 0, 147, -292, -2611/5, 1799/10, 6, -2/5, 2, -373/2, 882, 0, 0, 16/5, -2, -2, 389/2, -59 ], [ 539/10, -97/2, 78/5, 2, -283/2, 283, 3619/10, -2541/20, 15, 44/5, 2, 623/4, -849, 2, -5, -132/5, 0, 20, -623/4, 91/2 ], [ -9, 1, -10, 1, 8, -17, -51, 17, -2, -4, 2, -16, 51, 1, 1, 12, -1, -5, 15, -5 ], [ -117/10, 5/2, -49/5, 1, 19/2, -18, -737/10, 503/20, 1, -22/5, 2, -81/4, 55, 1, 0, 66/5, -1, -1, 85/4, -13/2 ], [ 32, -2, 18, -2, -10, 16, 192, -64, -11, 8, -4, 49, -52, -2, 3, -26, 2, -10, -51, 17 ], [ -30, 2, 6, 2, 10, -25, -162, 54, 11, 4, 4, -55, 73, 2, -2, -10, -2, 6, 48, -16 ], [ 169/10, -19/2, 18/5, 0, -57/2, 55, 1159/10, -791/20, -4, 9/5, -1, 141/4, -169, 0, 0, -32/5, 2, 1, -161/4, 25/2 ], [ 547/10, -57/2, 94/5, 0, -171/2, 166, 3657/10, -2493/20, -9, 47/5, -2, 463/4, -507, 0, 0, -151/5, 5, 2, -507/4, 79/2 ], [ 653/5, -41, 117/5, -1, -125, 248, 3958/5, -1326/5, -2, 56/5, -3, 257, -746, -2, 0, -173/5, 2, 2, -259, 85 ], [ -87/5, 11, -28/5, 1, 23, -35, -652/5, 219/5, 1, -24/5, -1, -32, 111, -2, -2, 72/5, 2, 10, 43, -14 ], [ 10, 0, 0, 0, 0, 1, 57, -19, 0, 0, 0, 16, -2, -1, 0, 0, 0, 0, -15, 5 ] , [ -2, 0, -8, 0, 0, 1, -12, 4, -3, -4, -1, -4, -4, 0, 0, 11, 1, 1, 3, -1 ], [ -15, 1, -1, 1, 5, -11, -84, 28, 5, 0, 2, -26, 33, 1, -1, 1, -1, 3, 24, -8 ], [ -66, 5, -5, 6, 24, -48, -396, 132, 15, 0, 7, -107, 144, 5, -5, 0, 0, 20, 107, -36 ], [ 2139/5, -124, 236/5, -3, -381, 751, 13014/5, -4358/5, -20, 108/5, -13, 814, -2267, -11, 1, -359/5, 10, 6, -832, 273 ], [ -3, 1, -8, 1, 3, -3, -24, 8, -1, -4, 1, -3, 11, 0, 0, 12, 0, 0, 6, -2 ], [ 1241/5, -81, 234/5, -1, -248, 491, 7556/5, -2532/5, -3, 112/5, -3, 492, -1477, -3, 1, -341/5, 2, -2, -497, 163 ], [ 6, 0, -8, 0, 0, -1, 39, -13, -3, -4, -1, 6, 1, -1, 0, 11, 1, 1, -9, 3 ], [ -639/10, 97/2, -158/5, -2, 283/2, -281, -4249/10, 2961/20, -8, -84/5, -3, -683/4, 843, -2, 2, 247/5, 0, -7, 683/4, -101/2 ], [ -243/10, 97/2, -191/5, -5, 271/2, -268, -2003/10, 1487/20, -12, -108/5, -5, -433/4, 807, -5, 5, 324/5, -3, -20, 445/4, -59/2 ] ], [ [ -1561/10, -2/5, -134/5, 0, -26/5, 72/5, -852, 2699/10, 2, -67/5, 2, -2431/10, -196/5, 0, 0, 211/5, -2, -2, 2451/10, -489/5 ], [ 3529/20, -21/5, 53/5, 0, -63/5, 151/5, 981, -6261/20, 0, 53/10, 2, 5589/20, -428/5, -3, 0, -109/10, 0, -2, -5589/20, 1071/10 ], [ -22, 0, 0, 0, 0, -2, -129, 43, 0, 0, 1, -32, 5, 2, 0, -1, 0, -2, 33, -11 ], [ 113/20, -7/5, 1/5, 0, -21/5, 47/5, 33, -217/20, 0, 1/10, 1, 233/20, -136/5, 0, 0, 7/10, 0, -1, -213/20, 37/10 ], [ -10, 0, 0, 0, 0, -1, -66, 22, 0, 0, -2, -15, 2, 1, 0, -3, 0, 2, 15, -5 ], [ 0, 0, 0, 0, -3, 6, 6, -2, 0, 0, 2, 0, -18, 0, 0, 2, 0, -2, 0, 0 ], [ 519/20, 19/5, 48/5, 1, 77/5, -164/5, 130, -791/20, 2, 53/10, -1, 719/20, 482/5, 1, -1, -179/10, 1, 6, -739/20, 171/10 ], [ 1517/20, 42/5, 104/5, 3, 176/5, -372/5, 378, -2293/20, 7, 119/10, -2, 2177/20, 1096/5, 3, -3, -407/10, 2, 17, -2217/20, 503/10 ], [ 1004/5, -64/5, 72/5, 0, -192/5, 374/5, 1101, -1751/5, 2, 36/5, -2, 1639/5, -1132/5, 0, -1, -118/5, 1, 6, -1644/5, 632/5 ], [ -31/5, 1/5, -128/5, 0, 3/5, 29/5, -18, 9/5, -3, -64/5, 1, -76/5, -77/5, -4, 0, 202/5, 0, 4, 66/5, -48/5 ], [ 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 2, 0, 0, -1, 0, 0, 0, 0 ], [ 2, 2, 8, 0, 8, -18, 12, -4, -1, 4, -1, 0, 52, 0, 0, -13, 1, 1, -1, 1 ], [ 0, 0, 0, 0, -1, 2, 3, -1, 0, 0, 1, 0, -6, 0, 0, 1, 0, -1, 0, 0 ], [ -3, 0, 0, 1, -1, 7, -3, 1, 0, 0, 6, -5, -16, 0, 0, 5, 0, -5, 5, -2 ], [ 3062/5, -157/5, 376/5, 0, -436/5, 737/5, 3384, -5388/5, 2, 188/5, -10, 4877/5, -2346/5, 0, -3, -639/5, 7, 23, -4972/5, 1921/5 ], [ 0, -1, -8, 0, -3, 7, 0, 0, -1, -4, 1, 1, -21, 0, 0, 12, 0, 0, -1, 0 ] , [ 2008/5, -133/5, 104/5, 0, -409/5, 803/5, 2202, -3502/5, 2, 52/5, -2, 3288/5, -2424/5, 0, -1, -171/5, 1, 7, -3293/5, 1264/5 ], [ 2, 2, 8, 0, 8, -21, 18, -6, -1, 4, -1, -3, 58, 0, 0, -14, 1, 1, -1, 1 ], [ -2629/20, 26/5, -8/5, -1, 78/5, -176/5, -708, 4441/20, -4, -13/10, -3, -4269/20, 508/5, -1, 1, 19/10, 1, -2, 4249/20, -841/10 ], [ -1923/20, -8/5, -36/5, -3, -54/5, 83/5, -501, 3067/20, -9, -51/10, -5, -3003/20, -274/5, -3, 3, 133/10, 0, -10, 3003/20, -637/10 ] ], [ [ -59, 10, -12, 0, 66, -154, -312, 104, 2, 0, 0, -120, 446, 6, -2, -8, 2, 4, 100, -30 ], [ -114, 9, -3, 0, 31, -65, -648, 216, 5, 0, 7, -186, 195, 10, 5, 7, -10, -30, 179, -57 ], [ 27, -3, -6, 1, -14, 33, 150, -50, 2, -4, 1, 46, -97, -3, -3, 11, 3, 15, -43, 13 ], [ -9, 0, -1, 0, 3, -7, -48, 16, 3, 0, 1, -15, 20, 1, -1, 0, 0, 3, 13, -4 ], [ 26, 0, 15, 0, 4, -15, 162, -54, -3, 8, -3, 34, 39, -2, -1, -27, 4, 6, -39, 13 ], [ -70, 4, -17, 0, 12, -25, -396, 132, 5, -8, 5, -115, 75, 6, 3, 29, -8, -18, 109, -35 ], [ 42, -4, 13, 0, -26, 59, 232, -77, -1, 4, -2, 74, -172, -4, 0, -10, 1, 3, -67, 21 ], [ 96, -7, 33, 0, -45, 100, 537, -178, -2, 12, -6, 162, -293, -9, -1, -34, 4, 11, -151, 48 ], [ 31, 0, 0, 1, 1, -3, 177, -59, -2, 0, -3, 47, 8, -3, -1, -2, 3, 7, -46, 15 ], [ -45, 3, 14, -5, 22, -57, -246, 82, -10, 9, -5, -74, 164, 6, 6, -28, -3, -30, 68, -20 ], [ 22, -2, 2, 0, -11, 25, 120, -40, -2, 0, -1, 39, -73, -2, 0, 0, 1, 2, -35, 11 ], [ 42, -5, 5, 0, -29, 68, 228, -76, -2, 0, -1, 78, -197, -4, 0, 2, 1, 3, -68, 21 ], [ -24, 1, -8, 0, 2, -3, -138, 46, 2, -4, 2, -38, 10, 2, 1, 14, -3, -6, 37, -12 ], [ -110, 5, -1, 0, 13, -28, -612, 204, 6, 0, 10, -182, 82, 10, 4, 9, -9, -26, 170, -55 ], [ 276, -25, 24, 2, -139, 318, 1506, -502, -16, 0, -19, 489, -926, -26, -3, 1, 14, 38, -438, 137 ], [ 3, -1, 0, -1, -2, 3, 18, -6, -2, 0, -1, 6, -10, 0, 0, -1, 1, 0, -6, 2 ], [ 43, 1, -9, 1, 8, -20, 249, -83, -4, -4, -5, 62, 56, -4, -1, 8, 4, 8, -63, 21 ], [ 42, -6, 6, 0, -35, 81, 222, -74, -2, 0, -2, 81, -235, -4, 0, 2, 1, 4, -69, 21 ], [ 78, -8, -2, 0, -40, 94, 423, -141, -4, -4, -3, 141, -272, -7, -1, 12, 3, 10, -124, 39 ], [ 84, -8, -21, 0, -31, 74, 450, -150, -5, -12, -4, 153, -213, -7, -2, 32, 4, 15, -134, 43 ] ], [ [ -15, 0, -36, 0, 8, -14, -90, 30, 2, -16, 2, -28, 42, 2, 2, 48, -6, -6, 24, -8 ], [ 37, 1, 2, 5, 2, 2, 201, -67, 9, 0, -3, 54, -5, -5, -5, -6, 3, 28, -53, 16 ], [ -4, 0, 8, 0, -2, 5, -27, 9, 4, 4, 2, -2, -12, 0, -1, -9, 0, 2, 6, -2 ], [ 10, -1, -1, 1, 0, 0, 57, -19, 4, 0, 0, 16, 0, -1, -2, -1, 1, 9, -16, 5 ], [ -63, 2, -2, -3, 9, -26, -345, 115, -5, 0, 3, -104, 73, 7, 5, 4, -5, -26, 95, -30 ], [ 45, -2, -19, 5, -19, 58, 222, -74, 7, -12, 1, 83, -162, -6, -4, 34, 1, 23, -67, 20 ], [ 11, -1, 11, -1, -11, 24, 61, -20, -3, 4, 0, 22, -70, -1, 0, -10, 2, -1, -18, 6 ], [ 25, -3, 15, -3, -29, 65, 135, -44, -8, 4, 1, 52, -189, -2, 1, -6, 3, -6, -42, 14 ], [ -14, -1, -7, -2, -7, 13, -78, 26, -7, -4, 0, -20, -40, 2, 3, 14, -1, -13, 19, -6 ], [ 44, -3, -17, 0, 4, -13, 261, -87, -5, -7, -7, 61, 33, -3, -1, 12, 3, 11, -69, 22 ], [ 0, 1, 7, 0, 6, -14, 0, 0, 0, 4, -1, -1, 41, 0, -1, -13, 2, 4, 1, 0 ], [ 1, 0, 17, -1, -2, 1, 12, -4, -2, 8, -1, 2, -4, 0, 0, -23, 2, -2, -2, 1 ], [ 24, -1, -6, 2, -8, 24, 123, -41, 3, -4, 0, 43, -67, -3, -2, 11, 1, 11, -36, 11 ], [ 57, -3, -1, 5, -25, 72, 294, -98, 14, -4, 0, 103, -201, -7, -5, 13, 0, 27, -86, 26 ], [ 31, -8, 44, -7, -60, 121, 177, -59, -36, 16, -3, 74, -359, -1, 7, -40, 11, -32, -58, 19 ], [ 12, -1, -1, 0, 0, -1, 69, -23, 1, 0, -1, 19, 3, -1, -1, -1, 1, 5, -19, 6 ], [ -14, -2, -30, -2, -14, 34, -90, 30, -10, -16, 1, -14, -99, 2, 4, 51, -2, -16, 18, -6 ], [ 20, -1, 18, 0, -8, 16, 114, -38, -3, 8, -1, 35, -47, -2, -1, -24, 4, 4, -31, 10 ], [ -12, 1, 22, -2, 9, -30, -51, 17, -6, 12, -2, -25, 83, 2, 1, -37, 3, -8, 19, -5 ], [ -34, 3, 16, -2, 31, -86, -165, 55, -9, 12, -3, -69, 242, 5, 2, -42, 3, -13, 53, -15 ] ], [ [ -71, 0, 58, -8, 20, -72, -348, 116, 4, 32, -2, -134, 194, 10, 0, -96, 2, -8, 104, -32 ], [ -2, 9, 27, 2, 45, -103, 9, -3, 2, 16, -2, -23, 298, 0, -2, -50, 4, 7, 12, -2 ], [ -43, -1, 15, 1, -5, 1, -237, 79, 5, 8, 2, -73, -9, 4, -1, -24, 0, 4, 64, -22 ], [ -15, -1, 15, 0, -1, -5, -75, 25, 3, 8, 0, -28, 10, 2, -1, -24, 1, 4, 21, -7 ], [ 52, -8, -9, -4, -42, 97, 285, -95, -10, -8, -2, 101, -282, -4, 4, 26, -2, -15, -88, 28 ], [ -37, 6, 13, 1, 26, -61, -198, 66, -2, 8, 2, -71, 175, 4, 2, -23, -1, -11, 62, -19 ], [ 51, -2, -28, 3, -18, 53, 259, -86, -4, -16, 0, 94, -147, -6, 0, 47, 0, 5, -77, 24 ], [ 117, -6, -55, 5, -44, 123, 600, -199, -10, -32, -1, 215, -344, -13, 0, 93, 1, 11, -179, 56 ], [ 37, -4, -37, -3, -18, 48, 192, -64, -9, -20, -2, 75, -135, -3, 3, 59, -2, -12, -61, 20 ], [ 77, -1, -4, 1, -2, 19, 429, -143, 5, -3, -1, 128, -45, -8, -4, 12, 3, 19, -116, 38 ], [ -9, 0, -8, -1, 0, 0, -54, 18, -3, -4, -1, -12, 1, 1, 2, 12, -2, -9, 13, -4 ], [ 29, -1, -22, 3, -10, 32, 141, -47, 0, -12, 0, 55, -87, -4, -1, 35, 0, 8, -43, 13 ], [ -21, 3, 6, 1, 14, -33, -114, 38, 1, 4, 1, -40, 95, 2, 0, -12, 0, -1, 35, -11 ], [ -10, 3, 84, 4, 20, -66, -24, 8, 5, 44, -4, -41, 178, 2, -4, -135, 9, 20, 20, -7 ], [ 157, -13, -258, 1, -104, 309, 735, -245, -42, -140, 6, 347, -850, -19, 20, 427, -25, -78, -248, 78 ], [ -3, -1, 8, 1, -4, 7, -15, 5, 5, 4, 1, -6, -21, 0, -2, -11, 1, 9, 4, -2 ], [ 39, -7, -58, -7, -34, 87, 192, -64, -18, -32, -3, 91, -246, -2, 8, 97, -6, -34, -69, 23 ], [ 15, 0, -37, 3, -11, 38, 60, -20, -3, -20, 3, 35, -102, -3, 2, 62, -4, -7, -21, 6 ], [ 16, -1, -53, 2, -14, 49, 57, -19, 0, -28, 3, 41, -131, -3, 1, 86, -5, -3, -23, 7 ], [ -40, 1, -78, -2, -6, 34, -252, 84, 1, -40, 8, -46, -85, 3, 5, 128, -13, -28, 60, -18 ] ], [ [ -456/5, 43, -164/5, 0, 125, -246, -2911/5, 1999/10, 2, -82/5, 2, -409/2, 742, 0, 0, 256/5, -2, -2, 413/2, -65 ], [ 1159/10, -101/2, 88/5, 0, -303/2, 308, 7399/10, -5061/20, 0, 44/5, 2, 1007/4, -919, -3, 0, -107/5, 0, -2, -1007/4, 155/2 ], [ -22, 0, 0, 0, 0, -2, -129, 43, 0, 0, 1, -32, 5, 2, 0, -1, 0, -2, 33, -11 ], [ 13/10, 3/2, -4/5, 0, 9/2, -8, 43/10, -17/20, 0, -2/5, 1, 3/4, 25, 0, 0, 11/5, 0, -1, 1/4, 1/2 ], [ -10, 0, 0, 0, 0, -1, -66, 22, 0, 0, -2, -15, 2, 1, 0, -3, 0, 2, 15, -5 ], [ 0, 0, 0, 0, -3, 6, 6, -2, 0, 0, 2, 0, -18, 0, 0, 2, 0, -2, 0, 0 ], [ 79/10, -11/2, 53/5, 1, -25/2, 23, 499/10, -351/20, 2, 29/5, -1, 85/4, -71, 1, -1, -97/5, 1, 6, -89/4, 15/2 ], [ 217/10, -39/2, 119/5, 3, -97/2, 93, 1377/10, -973/20, 7, 67/5, -2, 259/4, -283, 3, -3, -226/5, 2, 17, -267/4, 43/2 ], [ 528/5, -40, 72/5, 0, -120, 238, 3193/5, -1071/5, 2, 36/5, -2, 219, -716, 0, -1, -118/5, 1, 6, -220, 72 ], [ 88/5, 7, -128/5, 0, 21, -35, 488/5, -161/5, -3, -64/5, 1, 12, 107, -4, 0, 202/5, 0, 4, -14, 4 ], [ 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 2, 0, 0, -1, 0, 0, 0, 0 ], [ 2, 2, 8, 0, 8, -18, 12, -4, -1, 4, -1, 0, 52, 0, 0, -13, 1, 1, -1, 1 ], [ 0, 0, 0, 0, -1, 2, 3, -1, 0, 0, 1, 0, -6, 0, 0, 1, 0, -1, 0, 0 ], [ -3, 0, 0, 1, -1, 7, -3, 1, 0, 0, 6, -5, -16, 0, 0, 5, 0, -5, 5, -2 ], [ 1634/5, -113, 376/5, 0, -332, 637, 9984/5, -3348/5, 2, 188/5, -10, 649, -1938, 0, -3, -639/5, 7, 23, -668, 221 ], [ 0, -1, -8, 0, -3, 7, 0, 0, -1, -4, 1, 1, -21, 0, 0, 12, 0, 0, -1, 0 ] , [ 1056/5, -81, 104/5, 0, -245, 487, 6386/5, -2142/5, 2, 52/5, -2, 440, -1464, 0, -1, -171/5, 1, 7, -441, 144 ], [ 2, 2, 8, 0, 8, -21, 18, -6, -1, 4, -1, -3, 58, 0, 0, -14, 1, 1, -1, 1 ], [ -709/10, 103/2, -43/5, -1, 309/2, -313, -4669/10, 3241/20, -4, -24/5, -3, -743/4, 935, -1, 1, 62/5, 1, -2, 739/4, -109/2 ], [ -443/10, 101/2, -81/5, -3, 291/2, -296, -3173/10, 2267/20, -9, -48/5, -5, -577/4, 883, -3, 3, 134/5, 0, -10, 577/4, -81/2 ] ], [ [ -2121/10, 78/5, -114/5, 0, 414/5, -938/5, -1146, 3679/10, 2, -27/5, 0, -3651/10, 2734/5, 6, -2, 41/5, 2, 4, 3451/10, -629/5 ], [ 729/20, 19/5, 38/5, 0, 77/5, -169/5, 171, -861/20, 5, 53/10, 7, 1089/20, 507/5, 10, 5, -89/10, -10, -30, -1229/20, 371/10 ], [ 27, -3, -6, 1, -14, 33, 150, -50, 2, -4, 1, 46, -97, -3, -3, 11, 3, 15, -43, 13 ], [ -127/20, -2/5, -4/5, 0, 9/5, -23/5, -33, 223/20, 3, 1/10, 1, -207/20, 64/5, 1, -1, -3/10, 0, 3, 167/20, -23/10 ], [ 26, 0, 15, 0, 4, -15, 162, -54, -3, 8, -3, 34, 39, -2, -1, -27, 4, 6, -39, 13 ], [ -70, 4, -17, 0, 12, -25, -396, 132, 5, -8, 5, -115, 75, 6, 3, 29, -8, -18, 109, -35 ], [ 1579/20, -26/5, 78/5, 0, -148/5, 331/5, 433, -2811/20, -1, 53/10, -2, 2659/20, -968/5, -4, 0, -139/10, 1, 3, -2519/20, 441/10 ], [ 4137/20, -53/5, 204/5, 0, -279/5, 608/5, 1140, -7373/20, -2, 159/10, -6, 6777/20, -1789/5, -9, -1, -457/10, 4, 11, -6557/20, 1173/10 ], [ 1159/5, -64/5, 72/5, 1, -187/5, 369/5, 1281, -2051/5, -2, 36/5, -3, 1879/5, -1112/5, -3, -1, -118/5, 3, 7, -1874/5, 707/5 ], [ -476/5, 31/5, 52/5, -5, 158/5, -381/5, -522, 849/5, -10, 36/5, -5, -781/5, 1108/5, 6, 6, -113/5, -3, -30, 751/5, -258/5 ], [ 22, -2, 2, 0, -11, 25, 120, -40, -2, 0, -1, 39, -73, -2, 0, 0, 1, 2, -35, 11 ], [ 42, -5, 5, 0, -29, 68, 228, -76, -2, 0, -1, 78, -197, -4, 0, 2, 1, 3, -68, 21 ], [ -24, 1, -8, 0, 2, -3, -138, 46, 2, -4, 2, -38, 10, 2, 1, 14, -3, -6, 37, -12 ], [ -110, 5, -1, 0, 13, -28, -612, 204, 6, 0, 10, -182, 82, 10, 4, 9, -9, -26, 170, -55 ], [ 4392/5, -317/5, 336/5, 2, -1271/5, 2742/5, 4818, -7778/5, -16, 108/5, -19, 7377/5, -8086/5, -26, -3, -319/5, 14, 38, -7122/5, 2581/5 ], [ 3, -1, 0, -1, -2, 3, 18, -6, -2, 0, -1, 6, -10, 0, 0, -1, 1, 0, -6, 2 ], [ 2223/5, -123/5, 99/5, 1, -344/5, 668/5, 2457, -3927/5, -4, 52/5, -5, 3598/5, -2024/5, -4, -1, -176/5, 4, 8, -3603/5, 1369/5 ], [ 42, -6, 6, 0, -35, 81, 222, -74, -2, 0, -2, 81, -235, -4, 0, 2, 1, 4, -69, 21 ], [ -1449/20, -14/5, -63/5, 0, -122/5, 314/5, -396, 2361/20, -4, -93/10, -3, -1989/20, -892/5, -7, -1, 279/10, 3, 10, 2329/20, -551/10 ], [ -1223/20, -18/5, -156/5, 0, -89/5, 238/5, -339, 1987/20, -5, -171/10, -4, -1563/20, -669/5, -7, -2, 473/10, 4, 15, 1943/20, -477/10 ] ], [ [ 97, -18, -62, -12, -64, 138, 546, -182, -32, -32, -2, 184, -408, -6, 4, 104, 6, -12, -168, 54 ], [ 66, -3, 66, -8, -32, 64, 387, -129, -16, 28, -7, 123, -186, -6, 3, -76, 7, -20, -107, 37 ], [ -57, 5, -18, 3, 22, -47, -330, 110, 0, -8, 1, -102, 133, 5, 0, 19, -1, 4, 92, -30 ], [ 6, -1, 1, -1, -5, 10, 36, -12, -7, 0, -1, 11, -32, 0, 1, 0, 2, -3, -11, 4 ], [ 0, -2, -12, 2, 1, 2, -15, 5, 10, -4, 3, 5, -2, 0, -3, 12, -1, 14, -1, -1 ], [ 9, 1, 29, -3, -8, 18, 45, -15, -9, 12, -2, 27, -48, -1, 2, -32, 3, -14, -14, 6 ], [ -46, 9, 21, 6, 36, -76, -263, 88, 18, 12, 1, -90, 225, 3, -3, -40, -3, 12, 81, -26 ], [ -90, 18, 32, 12, 76, -159, -519, 174, 38, 20, 2, -178, 471, 6, -7, -68, -6, 30, 159, -51 ], [ 1, -2, -20, 1, 3, -6, 3, -1, 14, -8, 2, 3, 21, 0, -3, 24, -3, 12, -3, 0 ], [ 120, -10, 14, -6, -47, 103, 696, -232, -18, 5, -2, 207, -299, -10, 3, -8, 5, -14, -193, 63 ], [ -26, 2, -10, 2, 12, -23, -153, 51, 9, -4, 1, -44, 70, 2, -2, 11, -2, 8, 42, -14 ], [ -43, 7, 14, 5, 28, -60, -240, 80, 14, 8, 1, -84, 176, 3, -2, -28, -3, 8, 74, -24 ], [ -1, 1, 10, -1, -1, 2, -6, 2, -4, 4, -1, 1, -5, 0, 1, -11, 1, -6, 2, 0 ], [ -13, 5, 81, -5, -3, 8, -81, 27, -13, 36, -9, -11, -24, 1, 0, -103, 11, -4, 22, -4 ], [ -244, 26, -58, 32, 145, -301, -1407, 469, 113, -16, 20, -445, 904, 17, -18, 29, -30, 68, 408, -138 ], [ 2, 0, -8, 0, -1, 3, 12, -4, -6, -4, 0, 1, -11, 0, 1, 11, 1, -2, -3, 1 ], [ 5, -4, -47, 1, 3, 0, 15, -5, 20, -20, 5, 18, 10, 0, -5, 62, -4, 19, -11, 2 ], [ -59, 8, 5, 7, 33, -70, -336, 112, 17, 4, 3, -110, 207, 4, -2, -17, -5, 7, 100, -33 ], [ -39, 5, -12, 7, 26, -57, -213, 71, 16, -4, 5, -81, 167, 3, -1, 6, -7, 4, 68, -23 ], [ 9, -5, -60, 5, -7, 11, 63, -21, 4, -28, 10, 9, -33, 0, 3, 79, -10, -13, -16, 3 ] ], [ [ -446/5, 47, -254/5, 2, 141, -276, -2941/5, 2019/10, -2, -122/5, 6, -401/2, 836, 0, 2, 376/5, -4, -8, 417/2, -65 ], [ 1009/10, -95/2, 73/5, 5, -267/2, 267, 6379/10, -4381/20, 3, 44/5, 0, 883/4, -804, -2, -3, -157/5, 3, 17, -895/4, 135/2 ], [ 11, -2, -6, -1, -12, 24, 60, -20, -6, -4, 0, 22, -70, -1, 3, 12, -2, -13, -19, 6 ], [ 133/10, 1/2, -4/5, 0, 3/2, -6, 793/10, -517/20, -3, -2/5, 0, 67/4, 16, -1, 1, 1/5, 0, -4, -75/4, 13/2 ], [ -17, -1, 1, -3, -6, 14, -96, 32, 3, 0, 0, -22, -39, 2, 1, 5, -3, -7, 23, -7 ], [ 18, -3, -24, 2, -9, 25, 84, -28, 2, -12, 0, 35, -71, -2, -3, 32, 2, 17, -29, 8 ], [ 329/10, -21/2, 108/5, -2, -69/2, 68, 2059/10, -1391/20, 1, 49/5, -3, 261/4, -206, -1, -1, -147/5, 2, 4, -265/4, 43/2 ], [ 977/10, -65/2, 239/5, -5, -213/2, 213, 6027/10, -4073/20, 2, 107/5, -6, 795/4, -641, -3, -2, -316/5, 4, 8, -791/4, 127/2 ], [ 473/5, -40, 32/5, -1, -120, 246, 2848/5, -956/5, 6, 16/5, 0, 209, -733, 1, -2, -33/5, 0, 7, -204, 67 ], [ -92/5, 14, 52/5, 2, 54, -117, -457/5, 154/5, 3, 36/5, 0, -60, 341, -1, -3, -123/5, 4, 14, 48, -15 ], [ -12, 1, -1, 0, 6, -12, -72, 24, 3, 0, 0, -18, 37, 1, -1, 0, 0, 3, 19, -6 ], [ 1, 1, 17, -1, 2, -7, 15, -5, 0, 8, -2, -2, 18, 0, 0, -24, 1, -1, -1, 1 ], [ 9, -1, -8, 1, -3, 8, 45, -15, 0, -4, 0, 16, -23, -1, -1, 10, 1, 6, -14, 4 ], [ 65, -2, -7, 5, -9, 20, 366, -122, -1, -4, 0, 100, -58, -7, 0, 7, 0, 6, -97, 30 ], [ 1404/5, -118, 241/5, -8, -357, 731, 8499/5, -2853/5, 19, 108/5, -11, 622, -2183, 3, -10, -289/5, 7, 36, -608, 202 ], [ 10, 0, 0, 0, 0, -3, 63, -21, -3, 0, 0, 13, 7, -1, 1, -1, 0, -4, -15, 5 ], [ 1006/5, -82, 24/5, -2, -246, 503, 6041/5, -2027/5, 11, 12/5, 0, 438, -1499, 1, -4, -11/5, 0, 15, -428, 140 ], [ -1, 1, 9, -1, 3, -7, -3, 1, 0, 4, -3, -3, 19, 0, -1, -13, 2, 4, 2, 0 ], [ -1159/10, 107/2, -8/5, -2, 325/2, -330, -7129/10, 4881/20, 0, -4/5, -2, -1039/4, 985, 3, 0, 17/5, 1, -3, 1015/4, -153/2 ], [ -1673/10, 119/2, -111/5, -2, 375/2, -381, -10163/10, 6927/20, 0, -48/5, 0, -1389/4, 1137, 8, 0, 154/5, 0, -5, 1353/4, -205/2 ] ], [ [ -1481/10, 28/5, 26/5, 0, 84/5, -198/5, -810, 2559/10, 2, 13/5, 0, -2371/10, 574/5, 0, 0, -39/5, 0, 0, 2391/10, -469/5 ], [ 3189/20, -36/5, 53/5, -3, -108/5, 201/5, 873, -5541/20, 0, 53/10, 2, 5169/20, -603/5, 0, 0, -159/10, 0, 0, -5169/20, 1001/10 ], [ -5, 2, -1, 3, 8, -14, -33, 11, 3, 0, 1, -11, 42, 0, -1, -1, 0, 5, 11, -4 ], [ 153/20, -12/5, 1/5, 0, -36/5, 72/5, 45, -297/20, 0, 1/10, 1, 293/20, -216/5, 0, 0, -3/10, 0, 0, -293/20, 47/10 ], [ -7, 3, 0, 1, 11, -21, -42, 14, 0, 0, -2, -14, 63, 0, 0, 0, 0, 0, 14, -4 ], [ 4, -2, 0, 0, -8, 13, 33, -11, 0, 0, 2, 5, -42, 0, 0, 0, 0, 0, -8, 2 ] , [ 599/20, 4/5, -27/5, 1, 12/5, -9/5, 160, -991/20, -1, -27/10, 0, 899/20, 37/5, 0, 0, 81/10, 0, 0, -919/20, 191/10 ], [ 1837/20, 12/5, -41/5, 3, 36/5, -42/5, 489, -3033/20, -2, -41/10, 0, 2777/20, 146/5, 0, 0, 123/10, 0, 0, -2817/20, 583/10 ], [ 984/5, -59/5, 32/5, 0, -172/5, 334/5, 1086, -1726/5, 0, 16/5, -2, 1594/5, -1012/5, 0, 0, -48/5, 0, 0, -1609/5, 622/5 ], [ -171/5, -4/5, 122/5, -6, -32/5, 29/5, -174, 269/5, -9, 56/5, -2, -256/5, -102/5, 0, 2, -158/5, 3, -10, 256/5, -103/5 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ -2, 0, -8, 0, 0, 3, -12, 4, -1, -4, 0, -3, -7, 0, 0, 12, 0, 0, 3, -1 ], [ 2, -1, 0, 0, -4, 7, 15, -5, 0, 0, 1, 3, -22, 0, 0, 0, 0, 0, -4, 1 ], [ -3, 1, -1, 1, 5, -10, -18, 6, 3, 0, 6, -6, 30, 1, -1, 0, 0, 4, 6, -2 ], [ 2902/5, -177/5, 96/5, 0, -516/5, 1042/5, 3213, -5103/5, 4, 48/5, -10, 4687/5, -3136/5, 0, -4, -139/5, 4, 15, -4752/5, 1841/5 ], [ 2, 0, 8, 0, 0, -1, 12, -4, -1, 4, 0, 3, 2, 0, 0, -12, 1, 0, -3, 1 ], [ 1978/5, -123/5, 64/5, 0, -364/5, 713/5, 2181, -3467/5, 0, 32/5, -3, 3218/5, -2154/5, 0, 0, -91/5, 0, 0, -3238/5, 1249/5 ], [ -2, 0, 0, 0, 0, 2, -9, 3, 1, 0, -1, -4, -5, 0, -1, 0, 1, 4, 3, -1 ], [ -2949/20, 16/5, -93/5, -1, 48/5, -81/5, -801, 5061/20, -1, -93/10, -2, -4689/20, 253/5, 0, 0, 279/10, 0, 0, 4689/20, -921/10 ], [ -2603/20, -8/5, -51/5, -3, -24/5, 48/5, -699, 4387/20, 0, -51/10, -5, -4023/20, -144/5, 0, 0, 153/10, 0, 0, 4023/20, -807/10 ] ], [ [ -19, -4, -50, 0, -8, 16, -114, 38, -2, -24, 0, -30, -52, 2, 0, 68, -2, 4, 26, -10 ], [ -69, 11, -5, 5, 48, -102, -405, 135, 12, 0, 0, -122, 303, 5, -2, -5, -3, 8, 116, -37 ], [ 14, -3, 1, -2, -12, 27, 81, -27, -1, 0, 0, 29, -79, -1, -1, 2, 2, 3, -25, 8 ], [ -7, 0, -1, 0, 3, -6, -42, 14, 3, 0, 0, -10, 18, 1, -1, 0, 0, 4, 10, -3 ], [ 37, -4, 3, -1, -21, 44, 219, -73, -8, 0, 0, 60, -133, -3, 2, 1, 1, -6, -60, 19 ], [ -24, 2, -2, 0, 15, -36, -126, 42, 6, 0, 0, -45, 104, 2, -2, -3, 0, 6, 38, -12 ], [ 22, 2, 25, 0, 4, -8, 130, -43, -1, 12, 0, 32, 25, -2, 0, -34, 2, -1, -31, 11 ], [ 56, 4, 50, 0, 8, -16, 330, -109, -4, 24, 0, 81, 49, -5, 0, -68, 5, -1, -80, 28 ], [ 25, -3, -6, -1, -15, 29, 150, -50, -8, -4, 0, 40, -89, -2, 2, 12, 1, -7, -41, 13 ], [ -58, 6, -3, 4, 30, -66, -342, 114, 11, 1, 0, -103, 194, 5, -1, -7, -4, 6, 95, -31 ], [ 1, -1, 1, -1, -6, 12, 9, -3, -3, 0, 0, 3, -36, 0, 1, 1, 0, -5, -3, 1 ], [ 10, 1, 17, 0, 0, 2, 54, -18, 0, 8, 0, 18, -3, -1, 0, -22, 1, -1, -14, 5 ], [ -12, 1, -1, 0, 7, -16, -66, 22, 3, 0, 0, -21, 47, 1, -1, -1, 0, 3, 19, -6 ], [ -65, 10, -6, 5, 48, -97, -390, 130, 16, 0, -1, -111, 290, 5, -6, -6, 1, 25, 110, -35 ], [ 132, -11, 51, -8, -65, 127, 792, -264, -26, 20, -1, 217, -380, -11, 6, -52, 8, -28, -213, 70 ], [ -10, 0, -1, 0, 2, -4, -60, 20, 3, 0, 0, -15, 12, 1, -1, 0, 0, 4, 15, -5 ], [ 38, -5, -13, -2, -23, 42, 234, -78, -13, -8, -1, 58, -132, -3, 3, 23, 2, -10, -63, 20 ], [ 11, 0, 17, -1, -3, 6, 66, -22, 0, 8, 0, 19, -16, -1, 0, -22, 1, -2, -17, 6 ], [ 28, -3, 19, -2, -18, 38, 162, -54, -4, 8, 0, 50, -110, -2, 2, -20, 0, -10, -45, 15 ], [ 39, -10, 5, -5, -45, 90, 234, -78, -9, 0, 0, 74, -267, -2, 5, 5, -3, -23, -71, 23 ] ] ]; return Group( gens ); fi; if n = 30 then # subgroup of a group which is conjugate to a direct product # of PolExamples(1) and PolExamples(6); gens := [ [ [ -402, -128, 32, 24, -452, 798, -293, 349 ], [ 3, 37, 20, -9, 5, -11, 29, 7 ], [ -67, 56, 5, -15, -105, 133, 21, 65 ], [ -114, 660, 80, -164, -325, 208, 528, 199 ], [ -2, 220, 0, -55, -90, 4, 199, 18 ], [ -213, 236, 16, -63, -359, 423, 121, 209 ], [ -36, 260, 0, -65, -144, 72, 221, 57 ], [ 3, -228, 0, 57, 94, -6, -206, -20 ] ], [ [ -446, 1144, -64, -288, -1114, 910, 833, 407 ], [ -9, 37, -4, -9, -31, 19, 29, 7 ], [ -125, 155, -7, -39, -223, 252, 77, 113 ], [ -510, 428, -16, -106, -779, 1024, 104, 457 ], [ -108, 28, 0, -7, -134, 216, -35, 96 ], [ -407, 608, -32, -153, -781, 823, 347, 367 ], [ -190, 92, 0, -23, -254, 380, -23, 171 ], [ 159, 12, 0, -3, 176, -318, 98, -140 ] ], [ [ -621, 2704, -64, -684, -1991, 1260, 2143, 599 ], [ 17, -107, -8, 27, 63, -32, -87, -21 ], [ -1, 248, -7, -63, -117, 4, 225, 3 ], [ 856, -1252, -32, 314, 1560, -1704, -694, -819 ], [ 194, -408, 0, 102, 411, -388, -268, -186 ], [ -14, 776, -32, -198, -388, 37, 704, 16 ], [ 322, -444, 0, 111, 581, -644, -237, -303 ], [ -222, 480, 0, -120, -476, 444, 319, 214 ] ], [ [ 751, 1404, 0, -351, 316, -1500, 1588, -669 ], [ 0, 1, 0, 0, 0, 0, 0, 0 ], [ 36, 48, 1, -12, 28, -72, 58, -30 ], [ -609, -1316, 0, 330, -135, 1218, -1457, 564 ], [ -184, -380, 0, 95, -53, 368, -423, 168 ], [ 108, 144, 0, -36, 84, -215, 174, -90 ], [ -267, -568, 0, 142, -66, 534, -629, 246 ], [ 200, 420, 0, -105, 55, -400, 466, -182 ] ], [ [ -127, 2424, 0, -606, -1351, 256, 2117, 75 ], [ 0, 1, 0, 0, 0, 0, 0, 0 ], [ 4, 0, 1, 0, 2, -8, 2, -6 ], [ 208, -2844, 0, 712, 1634, -416, -2456, -159 ], [ 50, -808, 0, 202, 455, -100, -702, -36 ], [ 12, 0, 0, 0, 6, -23, 6, -18 ], [ 84, -1220, 0, 305, 695, -168, -1055, -63 ], [ -54, 936, 0, -234, -520, 108, 815, 40 ] ], [ [ -402, -128, 32, 24, -452, 798, -293, 349 ], [ 3, 37, 20, -9, 5, -11, 29, 7 ], [ -67, 56, 5, -15, -105, 133, 21, 65 ], [ -114, 660, 80, -164, -325, 208, 528, 199 ], [ -2, 220, 0, -55, -90, 4, 199, 18 ], [ -213, 236, 16, -63, -359, 423, 121, 209 ], [ -36, 260, 0, -65, -144, 72, 221, 57 ], [ 3, -228, 0, 57, 94, -6, -206, -20 ] ], [ [ -611, 600, 0, -150, -979, 1224, 257, 615 ], [ 0, 1, 0, 0, 0, 0, 0, 0 ], [ -276, -1536, 1, 384, 338, 552, -1510, 210 ], [ -1604, -13100, 0, 3276, 3766, 3208, -12532, 1065 ], [ -302, -3016, 0, 754, 947, 604, -2854, 180 ], [ -828, -4608, 0, 1152, 1014, 1657, -4530, 630 ], [ -608, -5252, 0, 1313, 1551, 1216, -5007, 393 ], [ 422, 3960, 0, -990, -1212, -844, 3759, -260 ] ], [ [ 7, 2628, -992, -657, -2051, 236, 2575, -430 ], [ -21, 37, -28, -9, -67, 49, 29, 7 ], [ -131, 324, -123, -81, -435, 293, 261, 57 ], [ -1520, -540, -112, 136, -1868, 3068, -1127, 1264 ], [ -316, -168, 0, 42, -347, 632, -288, 270 ], [ -483, 1116, -496, -279, -1591, 1091, 899, 199 ], [ -566, -276, 0, 69, -630, 1132, -494, 486 ], [ 342, 60, 0, -15, 441, -684, 201, -287 ] ], [ [ -562, 440, -64, -120, -996, 1142, 171, 461 ], [ 22, -143, -12, 36, 82, -41, -116, -28 ], [ -87, 127, -7, -33, -173, 176, 79, 79 ], [ -38, -60, -48, 16, -17, 88, -52, 59 ], [ -2, 220, 0, -55, -90, 4, 199, 18 ], [ -293, 520, -32, -135, -631, 595, 353, 265 ], [ -36, 260, 0, -65, -144, 72, 221, 57 ], [ 3, -228, 0, 57, 94, -6, -206, -20 ] ] ]; return Group( gens ); fi; if n= 31 then gens := GeneratorsOfGroup( MatExamples(4) ); return Group( gens{[1,2]} ); fi; return fail; end; ############################################################################# ## #F POL_RandomRationalTriangularGroup( dim, numberOfGens ) ## POL_RandomRationalTriangularGroup := function( dim, numberOfGens ) local gens, i, g, j, k, range, kk,ll; range := 7; ll := [-range..range]; kk := [-range..range]; ll := Filtered( ll, (x->x<>0) ); kk := Filtered( kk, (x->x<>0) ); gens:=[]; for i in [1..numberOfGens] do g:=IdentityMat(dim,Rationals); for j in [1..dim] do for k in [j..dim] do if j<=k then g[j][k] := RandomList( ll )/RandomList( kk ); else g[j][k] := 0; fi; od; od; Add(gens,g); od; return gens; end; ############################################################################# ## #F POL_RandomRationalUnipotentGroup( dim, numberOfGens ) ## POL_RandomRationalUnipotentGroup := function( dim, numberOfGens ) local G, x; G := POL_RandomRationalTriangularGroup( dim, numberOfGens ); x := RandomInvertibleMat( dim, Rationals ); return G^x; end; ############################################################################# ## #F POL_RandomSubgroup( G, numberOfgens ) ## ## POL_RandomSubgroup := function( G, numberOfNewGens ) local gens,newGens, i; gens := GeneratorsOfGroup( G ); newGens := []; for i in [1..numberOfNewGens] do Add( newGens, POL_RandomGroupElement( gens ) ); od; return Group( newGens ); end; ############################################################################# ## #F POL_DirectProduct( G1, G2 ) ## ## POL_DirectProduct:= function( G1, G2 ) local n1, n2, gens, k, i, j, matrix, x, G, gens1, gens2; gens1 := GeneratorsOfGroup( G1 ); gens2 := GeneratorsOfGroup( G2 ); n1 := Length( gens1[1] ); n2 := Length( gens2[2] ); gens := []; for k in [1..Length( gens1 )] do matrix := IdentityMat( n1+n2 ); for i in [1..n1] do for j in [1..n1] do matrix[i][j] := gens1[k][i][j]; od; od; Add( gens, matrix ); od; for k in [1..Length( gens2 )] do matrix := IdentityMat( n1+n2 ); for i in [1..n2] do for j in [1..n2] do matrix[i+n1][j+n1] := gens2[k][i][j]; od; od; Add( gens, matrix ); od; return Group( gens ); end; ############################################################################# ## #F POL_SemidirectProductVectorSpace( G ) ## POL_SemidirectProductVectorSpace := function( G ) local gens, n, newGens, g, h, i, v; gens := GeneratorsOfGroup( G ); n := Length( gens[1] ); newGens := []; for g in gens do h := POL_CopyVectorList( g ); for i in [1..n] do Add( h[i], 0 ); od; v := List( [1..n+1], x->0 ); v[n+1] := 1; Add( h, v ); Add( newGens, h ); od; for i in [1..n] do h := IdentityMat( n+1 ); h[i][n+1] := 1; Add( newGens, h ); od; return Group( newGens ); end; POL_IrredPol := function( n ) local x,p; x := Indeterminate(Rationals,"x":old); if n = 1 then p := x^2 + 6*x + 3; return p; fi; if n = 2 then p := x^3 + 14*x^2 - 49*x + 7; return p; fi; if n = 3 then p := x^2+1; return p; fi; if n = 4 then p := x^3+2*x+2; return p; fi; if n = 5 then p := x^3+2*x+2; return p; fi; if n = 6 then p := -4*x^2-2*x+1; return p; fi; end; POL_AbelianIrreducibleGens := function( n ) local k,l,ll,range,pol,mat,n_gens,gens,i,exps,l_comb,g; pol := POL_IrredPol( n ); mat := CompanionMat( pol ); range := 3; l := [-range..range]; l := Filtered( l, (x -> x<>0) ); # k := [-range..range]; k := [1]; k := Filtered( k, (x -> x<>0) ); exps := [0,1,2]; n_gens := 3; gens := []; for i in [1..n_gens] do l_comb := 2; ll := List( [1..l_comb], x-> RandomList(l)/RandomList(k) ); g := List( [1..l_comb] , x-> ll[x]*mat^RandomList(exps) ); Add( gens, Sum( g ) ); od; return gens; end; POL_RandomUnitGroupGens := function( n ) local F, U, u_gens, n_gens, gens; F := ExampleMatField( n ); U := UnitGroup( F ); u_gens := GeneratorsOfGroup( U ); n_gens := 3; gens := List( [1..n_gens], x->POL_RandomGroupElement( u_gens )); return gens; end; POL_TriangularizableGens := function( n_blocks, n_gens ) local n_fields,a_gens,i,ll,dim,j,k,start,rr,gens,g,start1,start2, rr1,rr2, u_entries, mat; n_fields := 6; a_gens := []; for i in [1..n_blocks] do Add( a_gens, POL_RandomUnitGroupGens( RandomList( [1..n_fields] )) ); od; #get dimension of composed matrix ll := List( [1..n_blocks], x-> Length( a_gens[x][1] )); dim := Sum( ll ); #get final generators gens := []; for i in [1..n_gens] do g := NullMat( dim,dim ); #write blocks for j in [1..n_blocks] do for k in [j..n_blocks] do if j = k then #place block on diagonal # set starting point start := Sum( ll{[1..(j-1)]} ); # get range rr := [1..ll[j]]+start; g{rr}{rr} := RandomList( a_gens[j] ); elif j <= k then # write upper part #set starting points start1 := Sum( ll{[1..(j-1)]} ); start2 := Sum( ll{[1..(k-1)]} ); #get range rr1 := [1..ll[j]]+start1; rr2 := [1..ll[k]]+start2; u_entries := [0,0,0,1/2,0]; mat := RandomMat( ll[j], ll[k], u_entries ); g{rr1}{rr2} := mat; fi; od; od; Add( gens, g ); od; return gens; end; ############################################################################# ## #F POL_PolExamples2( n ) .............Examples for polycyc rat. matrix groups ## POL_PolExamples2 := function( n ) local i,M,P, nat, G, gens, d, l, l1, l2, l3,h1,h2,H,g,h; # check if aclib is needed l1 := Concatenation( [9..16],[21..28],[37..40]); l2 := l1 + 40; l3 := [82..100]; l := Concatenation( l1, l2 ,l3); l1 := l+100; l := Concatenation( l, l1 ); l1 := l+300; l := Concatenation( l, l1 ); l1 := l+400; l := Concatenation( l, l1 ); if POL_AlmostCrystallographicGroup = false then if n in l then Print( "package 'aclib' is needed for this example.\n" ); return fail; fi; fi; # some unipotent groups if n=1 then return Group( [ [ [ 1, -4, 1, 2 ], [ 0, 1, 5, 1 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ] , [ [ 1, -1, -2, 4 ], [ 0, 1, -1, 1 ], [ 0, 0, 1, 1 ], [ 0, 0, 0, 1 ] ] , [ [ 1, -4, -2, 1 ], [ 0, 1, -2, -3 ], [ 0, 0, 1, 2 ], [ 0, 0, 0, 1 ] ] ]); fi; if n=2 then return Group( [ [ [ 1, 5, -3, 1, -3 ], [ 0, 1, 2, 0, 1 ], [ 0, 0, 1, 2, -2 ], [ 0, 0, 0, 1, -2 ], [ 0, 0, 0, 0, 1 ] ] , [ [ 1, 3, -3, -1, 1 ], [ 0, 1, 0, -2, 2 ], [ 0, 0, 1, 4, 1 ], [ 0, 0, 0, 1, -1 ], [ 0, 0, 0, 0, 1 ] ] ]); fi; if n=3 then return Group( [ [ [ 73/10, -35/2, 42/5, 63/2 ], [ 27/20, -11/4, 9/5, 27/4 ], [ -3/5, 1, -4/5, -9 ], [ -11/20, 7/4, -2/5, 1/4 ] ] , [ [ -42/5, 423/10, 27/5, 479/10 ], [ -23/10, 227/20, 13/10, 231/20 ], [ 14/5, -63/5, -4/5, -79/5 ], [ -1/10, 9/20, 1/10, 37/20 ] ] ]); fi; if n=4 then return Group( [ [ [ 5, 2, -8, 17, -1 ], [ -69/4, -15/4, 449/20, -163/5, 53/20 ], [ -2, 4, 9/5, 63/5, 3/5 ], [ 13/4, 3/4, -121/20, 57/5, -17/20 ], [ 241/4, 7/4, -1477/20, 319/5, -189/20 ] ] , [ [ 19/2, 0, -3, -19/2, -1/2 ], [ -74/5, 129/20, 7/4, 159/4, 9/10 ], [ 53/10, 4/5, -4, 9/2, -9/10 ], [ 37/10, -41/20, -7/4, -29/4, -3/5 ], [ 137/5, -457/20, 37/4, -559/4, 3/10 ] ] ]); fi; if n in [5..8] then return MatExamples( n-4 ); fi; if n=9 then return POL_AlmostCrystallographicGroup( 3, 17, [1,0,-3,7] ); fi; if n=10 then return POL_AlmostCrystallographicGroup( 3, 16, [3,4,-1,0] ); fi; if n=11 then return POL_AlmostCrystallographicGroup( 3, 15, [-1,1,0,0] ); fi; if n=12 then return POL_AlmostCrystallographicGroup( 3, 14, [-2,-1,2,-1] ); fi; if n=13 then return POL_AlmostCrystallographicGroup( 4, 2, [0,-3,-2,1,-1,-2,4] ); fi; if n=14 then return POL_AlmostCrystallographicGroup( 4, 13, [-2,0,-2,-2,-1,-1] ); fi; if n=15 then return POL_AlmostCrystallographicGroup( 4, 37, [ 1,2,0,-3,-4] ); fi; if n=16 then return POL_AlmostCrystallographicGroup( 4, 86,[0,-2,-1,-2,-1] ); fi; if n in [17..20] then return POL_KroneckerProduct( MatExamples( n-16), -1 ); fi; if n in [21..28] then return POL_KroneckerProduct( PolExamples( n-12 ), 1 ); fi; if n=29 then return POL_DirectProduct( PolExamples( 1 ), PolExamples( 2 ) ); fi; if n=30 then return POL_DirectProduct( PolExamples( 1 ), PolExamples( 4 ) ); fi; if n=31 then return POL_DirectProduct( PolExamples( 2 ), PolExamples( 8 ) ); fi; if n=32 then return POL_DirectProduct( PolExamples( 6 ), PolExamples( 7 ) ); fi; if n=33 then return POL_DirectProduct( PolExamples( 1 ), PolExamples( 2 ) ); fi; if n=34 then return POL_DirectProduct( PolExamples( 1 ), PolExamples( 4 ) ); fi; if n=35 then return POL_DirectProduct( PolExamples( 2 ), PolExamples( 8 ) ); fi; if n=36 then return POL_DirectProduct( PolExamples( 6 ), PolExamples( 7 ) ); fi; if n=37 then return POL_DirectProduct( PolExamples( 1 ), PolExamples( 9 ) ); fi; if n=38 then return POL_DirectProduct( PolExamples( 10 ), PolExamples( 11 ) ); fi; if n=39 then return POL_DirectProduct( PolExamples( 17 ), PolExamples( 21 ) ); fi; if n=40 then return POL_DirectProduct( PolExamples( 2 ), PolExamples( 27 ) ); fi; if n in [41..81] then return POL_SemidirectProductVectorSpace( PolExamples( n-40 ) ); fi; if n in [82..100] then return POL_AlmostCrystallographicGroup( 4, n-5, false ); fi; if n in [101..200] then P := SymmetricGroup( 3 ); M := POL_PolExamples2( n-100 ); return WreathProductOfMatrixGroup( M, P ); fi; if n in [201..300] then P := SmallGroup( 8, 3 ); nat := RegularActionHomomorphism( P ); P := Image( nat ); M := POL_PolExamples2( n-200 ); return WreathProductOfMatrixGroup( M, P ); fi; if n in [301..600] then G := POL_PolExamples2( n-300 ); gens := GeneratorsOfGroup( G ); d := Length( gens[1] ); M := RandomInvertibleMat( Integers, d ); return G^M; fi; if n in [601..1200] then return POL_RandomSubgroup( POL_PolExamples2( n-600), 2 ); fi; # examples which can be nonpolycyclic or nonsolvable if n = 1201 then h1 := [[2,0],[0,1]]; h2 := [[1,1],[0,1]]; H := Group( [h1,h2] ); return H; fi; if n = 1202 then gens := [ [ [ -1/4, 5/4, -4/3 ], [ 1, 0, 1 ], [ 0, -5/3, -1 ] ], [ [ 2, 3/5, 4 ], [ 2/3, 0, 1 ], [ 5/3, 0, 1/2 ] ] ]; return Group( gens ); fi; if n = 1203 then gens := [ [ [ 2, 4/3, 1/2, 1/2 ], [ -2, -1/2, -1/4, 1 ], [ -1/2, 0, 0, 3/2 ], [ 0, 1/3, 0, 3/2 ] ], [ [ 2, 2, 1, 2 ], [ -2/5, 3/2, 0, -1/2 ], [ -3/2, 0, 1/3, 4 ], [ -1/4, 0, -3, 0 ] ] ]; return Group( gens ); fi; if n = 1204 then gens := [ [ [ 3, 1, 3, -1 ], [ 2, -1, 1, 1 ], [ -1, 0, 1, 3 ], [ 1, 1, -1, 0 ] ], [ [ 0, -3, -1, 2 ], [ -3, -3, 0, -1 ], [ -1, -2, -1, 0 ], [ 1, -1, 2, -5 ] ] ]; return Group( gens ); fi; if n= 1205 then gens := [ [ [ -7/3, 77/3, 0, 0, 1, 0 ], [ -77/3, 994/3, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, -28/3 ], [ 0, 0, 2/3, 0, 0, 22/3 ], [ 0, 0, 0, 2/3, 0, -10/3 ], [ 0, 0, 0, 0, 2/3, -2 ] ], [ [ 1/3, 8/3, 0, 0, 0, 0 ], [ -8/3, 35, 0, 1, 0, 0 ], [ 0, 0, 0, 0, 0, -28/3 ], [ 0, 0, 2/3, 0, 0, 22/3 ], [ 0, 0, 0, 2/3, 0, -10/3 ], [ 0, 0, 0, 0, 2/3, -2 ]] ]; return Group( gens ); fi; if n = 1206 then gens := [ [ [ -6, -1/2, 3/4, -5/3 ], [ 0, -3, 3, -3/2 ], [ 0, 0, 1/3, -4/7 ], [ 0, 0, 0, 1 ] ], [ [ 7/4, 2, 1/2, -5/3 ], [ 0, 5/6, -6, 1 ], [ 0, 0, 3, 2/7 ], [ 0, 0, 0, 2/3 ] ] ]; return Group( gens ); fi; if n = 1207 then gens := [ [ [ 1, 5/7, 3/4, -5, 2/5 ], [ 0, -1, 3/2, 2, 4/7 ], [ 0, 0, 2/3, 1, -7/5 ], [ 0, 0, 0, 1/5, 4/7 ], [ 0, 0, 0, 0, 2/5 ] ], [ [ 2, -2/7, -4/7, 1, 3/7 ], [ 0, -1/5, -1/3, 1, 1/2 ], [ 0, 0, -4/3, -3, 2 ], [ 0, 0, 0, 7, -1/6 ], [ 0, 0, 0, 0, -2 ] ] ]; return Group( gens ); fi; if n = 1208 then gens := [ [ [ 3/2, -3, -4/5, 1/3, -3, -5/6, 4, 5/3 ], [ 0, -1, 5/7, -1/2, 3/7, -1/3, -4/5, 1/2 ], [ 0, 0, -1/4, 3/5, 5/2, -1/6, -1, 1 ], [ 0, 0, 0, 1/5, 7/4, -2, -7/4, -1 ], [ 0, 0, 0, 0, 5/3, -5/2, -1, -1/6 ], [ 0, 0, 0, 0, 0, -1, 5/2, -1 ], [ 0, 0, 0, 0, 0, 0, 3, 1 ], [ 0, 0, 0, 0, 0, 0, 0, -2/7 ] ], [ [ 3/2, 1, -3/2, 1, -1, -2/5, 1/5, -1 ], [ 0, 1, 4/7, 1, -3/5, -5/7, 5/2, 3 ], [ 0, 0, -1/3, 1, 3/2, -4/3, 3/2, 2/3 ], [ 0, 0, 0, 3, -3, -7/5, 5/2, 1/2 ], [ 0, 0, 0, 0, 3/5, -2, 4/3, 1 ], [ 0, 0, 0, 0, 0, -2, 3, 3 ], [ 0, 0, 0, 0, 0, 0, -1/2, -1/2 ], [ 0, 0, 0, 0, 0, 0, 0, 5/3 ] ] ]; return Group( gens ); fi; if n = 1209 then gens := [ [ [ 5/6, -2, 1, 4, -1, 2 ], [ 2/3, -19/6, -1, 4, -3, 0 ], [ 0, 0, 5/6, -2, -1, -2 ], [ 0, 0, 2/3, -19/6, 0, -3 ], [ 0, 0, 0, 0, 5/6, -2 ], [ 0, 0, 0, 0, 2/3, -19/6 ] ], [ [ -1/2, -12/5, 3, -1, 1, -2 ], [ 4/5, -53/10, -2, -4, -2, 1 ], [ 0, 0, -1/2, -12/5, -2, -4 ], [ 0, 0, 4/5, -53/10, 2, 3 ], [ 0, 0, 0, 0, -1/2, -12/5 ], [ 0, 0, 0, 0, 4/5, -53/10 ] ], [ [ 4733/600, -2037/50, -2, -1, 4, -2 ], [ 679/50, -8831/120, 0, 0, -3, -2 ], [ 0, 0, 4733/600, -2037/50, 0, 2 ], [ 0, 0, 679/50, -8831/120, 4, 1 ], [ 0, 0, 0, 0, 4733/600, -2037/50 ], [ 0, 0, 0, 0, 679/50, -8831/120 ] ], [ [ 1, 0, -3, -2, -2, -4 ], [ 0, 1, 3, 2, 1, 3 ], [ 0, 0, 1, 0, -2, 1 ], [ 0, 0, 0, 1, 2, 0 ], [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 1 ] ] ]; return Group( gens ); fi; if n = 1210 then # takes 6 minutes to test polycyclicity gens := [ [ [ 63/20, -5/2, 121/2, -1475, -5, 1, 1, 1 ], [ 0, -237/20, 721/2, -17579/2, 1, -3, 2, -2 ], [ 2/5, -15/2, 3393/20, -8129/2, 1, -1, 1, -1 ], [ 1/2, -121/10, 295, -144107/20, -3, -1, 0, 0 ], [ 0, 0, 0, 0, 63/20, -5/2, 121/2, -1475 ], [ 0, 0, 0, 0, 0, -237/20, 721/2, -17579/2 ], [ 0, 0, 0, 0, 2/5, -15/2, 3393/20, -8129/2 ], [ 0, 0, 0, 0, 1/2, -121/10, 295, -144107/20 ] ], [ [ -281351/400, 34831/2, -8511437/20, 20798633/2, 3, 0, -2, 0 ], [ -85011/20, 41515849/400, -12680078/5, 1239406543/20, -1, 0, -1, 1 ], [ -196313/100, 959919/20, -469170371/400, 286619339/10, -1, -4, 1, 1 ], [ -34831/10, 8511437/100, -20798633/10, 20329462629/400, 1, -2, 4, -2 ], [ 0, 0, 0, 0, -281351/400, 34831/2, -8511437/20, 20798633/2 ], [ 0, 0, 0, 0, -85011/20, 41515849/400, -12680078/5, 1239406543/20 ], [ 0, 0, 0, 0, -196313/100, 959919/20, -469170371/400, 286619339/10 ], [ 0, 0, 0, 0, -34831/10, 8511437/100, -20798633/10, 20329462629/400 ] ], [ [ -5, -3, 75, -3665/2, 1, 0, -1, -2 ], [ 1/2, -23, 447, -10920, 0, -3, 1, 2 ], [ 0, -17/2, 202, -10101/2, -3, -1, 0, 1 ], [ 3/5, -15, 733/2, -17921/2, 0, 1, 2, 3 ], [ 0, 0, 0, 0, -5, -3, 75, -3665/2 ], [ 0, 0, 0, 0, 1/2, -23, 447, -10920 ], [ 0, 0, 0, 0, 0, -17/2, 202, -10101/2 ], [ 0, 0, 0, 0, 3/5, -15, 733/2, -17921/2 ] ], [ [ -50, -30, 750, -18325, 3, -2, 0, 2 ], [ 5, -230, 4470, -109200, 0, 1, 5, 3 ], [ 0, -85, 2020, -50505, 3, 0, 1, 4 ], [ 6, -150, 3665, -89605, 2, -3, 1, -1 ] , [ 0, 0, 0, 0, -50, -30, 750, -18325 ], [ 0, 0, 0, 0, 5, -230, 4470, -109200 ], [ 0, 0, 0, 0, 0, -85, 2020, -50505 ], [ 0, 0, 0, 0, 6, -150, 3665, -89605 ] ] ]; return Group( gens ); fi; ############################################################### # some easy examples if n = -1 then g := 2*IdentityMat( 2, 1 ); gens := [g]; return Group( gens ); fi; if n = -2 then g := 2*IdentityMat( 3, 1 ); gens := [g]; return Group( gens ); fi; if n = -3 then g := 1345*IdentityMat( 5, 1 ); gens := [g]; return Group( gens ); fi; if n = -4 then g := 23* IdentityMat( 5, 1 ); h := 12* IdentityMat( 5, 1 ); gens := [g,h]; return Group( gens ); fi; if n = -5 then g := IdentityMat( 3,1 ); g[3][3] := 34; h := IdentityMat( 3,1 ); h[1][1] := 23; gens := [g,h]; return Group( gens ); fi; if n = -6 then g := IdentityMat(4,1 ); gens := [g]; return Group( gens ); fi; if n = -7 then g := [[2]]; h := [[3]]; gens := [g,h]; return Group( gens ); fi; if n = -8 then g := [[1]]; gens := [g]; return Group( gens ); fi; ################################################################## # some abelian irrdeucible examples if n = - 9 then gens := [ [ [ -21/5, 0, 56, -168 ], [ 0, -21/5, -44, 188 ], [ -4, 0, 79/5, -104 ], [ 0, -4, 12, -101/5 ] ], [ [ -1/2, 0, 434/5, -1302/5 ], [ 0, -1/2, -341/5, 1457/5 ], [ -31/5, 0, 61/2, -806/5 ], [ 0, -31/5, 93/5, -253/10 ] ], [ [ -5/6, 0, 14/5, -77/5 ], [ 1/2, -5/6, -11/5, 149/10 ], [ -1/5, 1/2, 1/6, -77/10 ], [ 0, -1/5, 11/10, -47/15 ] ] ]; return Group( gens ); fi; if n = - 10 then gens := [ [ [ -37/20, 0, 0, -70/3 ], [ 5/3, -37/20, 0, 55/3 ], [ 0, 5/3, -37/20, -25/3 ], [ 0, 0, 5/3, -137/20 ] ], [ [ 3/4, 0, 0, -56 ], [ 4, 3/4, 0, 44 ], [ 0, 4, 3/4, -20 ], [ 0, 0, 4, -45/4 ] ], [ [ 7/2, 0, 28, -84 ], [ 0, 7/2, -22, 94 ], [ -2, 0, 27/2, -52 ], [ 0, -2, 6, -9/2 ] ] ]; return Group( gens ); fi; if n = -11 then gens := [ [ [ -1, 185/12 ], [ -185/12, 2393/12 ] ], [ [ -1/2, -24 ], [ 24, -625/2 ] ] , [ [ 1/3, -1/2 ], [ 1/2, -37/6 ] ] ]; return( Group(gens ) ); fi; if n = -12 then gens := [ [ [ 0, 0, 0, 0, 0, 119/6 ], [ -17/12, 0, 0, 0, 0, -187/12 ], [ 0, -17/12, 0, 0, 0, 0 ], [ 0, 0, -17/12, 0, 0, -17 ], [ 0, 0, 0, -17/12, 0, 0 ], [ 0, 0, 0, 0, -17/12, 85/12 ] ], [ [ 0, 0, 0, 0, 196/15, -238/3 ], [ 1, 0, 0, 0, -154/15, 377/5 ], [ -14/15, 1, 0, 0, 0, -154/15 ], [ 0, -14/15, 1, 0, -56/5, 68 ], [ 0, 0, -14/15, 1, 0, -56/5 ], [ 0, 0, 0, -14/15, 17/3, -85/3 ] ], [ [ 2, 0, 0, 0, -84/5, 98 ], [ -1, 2, 0, 0, 66/5, -469/5 ], [ 6/5, -1, 2, 0, 0, 66/5 ], [ 0, 6/5, -1, 2, 72/5, -84 ], [ 0, 0, 6/5, -1, 2, 72/5 ], [ 0, 0, 0, 6/5, -7, 37 ] ] ]; return Group( gens ); fi; ################################################################## # some triangularizable examples if n = -13 then gens := [ [ [ 9/10, 39/10, 0, 0 ], [ -39/10, 258/5, 0, 0 ], [ 0, 0, 4, -39 ], [ 0, 0, 39, -503 ] ], [ [ 9/10, 39/10, 0, 0 ], [ -39/10, 258/5, 0, 0 ], [ 0, 0, 4, -39 ], [ 0, 0, 39, -503 ] ] ]; return Group( gens ); fi; if n = -14 then gens := [ [ [ 7, 6, 0, 0 ], [ -6, 85, 0, 0 ], [ 0, 0, 0, 5 ], [ 0, 0, -5, 65 ] ], [ [ -7, 78, 0, 0 ], [ -78, 1007, 0, 0 ], [ 0, 0, -6, 81 ], [ 0, 0, -81, 1047 ] ] ]; return Group( gens ); fi; if n = -15 then gens := [ [ [ -9, 36, 0, 0, 0 ], [ -12, 63, 0, 0, 0 ], [ 0, 0, -1, 6, 0 ], [ 0, 0, 0, 5, 6 ], [ 0, 0, -3, 0, 5 ] ], [ [ -6, 24, 0, 0, 0 ], [ -8, 42, 0, 0, 0 ], [ 0, 0, -1, 6, 0 ], [ 0, 0, 0, 5, 6 ], [ 0, 0, -3, 0, 5 ] ] ]; return Group( gens ); fi; # takes some more time, example form referee if n = -16 then gens := [ [ [ 1, -3, 8, -2, 0, 2 ], [ 5, -14, 37, -3, -2, -2 ], [ -3, 8, -22, 0, -5, 2 ], [ 0, 0, 0, 0, 1, -1 ], [ 0, 0, 0, 0, 5, -4 ], [ 0, 0, 0, 1, -1, 6 ] ], [ [ 1, 0, 0, -1, 1, -2 ], [ 0, 1, 0, -3, 0, 5 ], [ 0, 0, 1, -1, 2, 1 ], [ 0, 0, 0, 2, -1, -1 ], [ 0, 0, 0, -2, -3, -6 ], [ 0, 0, 0, -1, -1, -2 ] ] ]; return Group( gens ); fi; # finite examples if n = -17 then return ImfMatrixGroup( 4,1,1 ); fi; if n = -18 then return ImfMatrixGroup(6,2,1); fi; ################################################################ #difficult examples ??? if n = -100 then gens := [ [ [ -100, 51, 70, -231, 1, 0, 0, 1 ], [ -169, 82, 112, -385, 0, 0, 0, 0 ], [ -59, 27, 37, -132, 0, 0, 0, 0 ], [ -80, 38, 52, -181, 0, 1, 0, 0 ], [ 0, 0, 0, 0, -19, 96, 70, -231 ], [ 0, 0, 0, 0, -34, 163, 112, -385 ], [ 0, 0, 0, 0, 31, -153, -107, 363 ], [ 0, 0, 0, 0, 10, -52, -38, 125 ] ], [ [ -1, 0, -1, 0, 0, 0, 0, 0 ], [ -2, 3, 5, -11, 0, 0, 1, 0 ], [ -1, 0, 0, 0, 0, 0, 1, 0 ], [ -1, 1, 2, -4, 1, 0, 1, 0 ], [ 0, 0, 0, 0, -19, 96, 70, -231 ], [ 0, 0, 0, 0, -34, 163, 112, -385 ], [ 0, 0, 0, 0, 31, -153, -107, 363 ], [ 0, 0, 0, 0, 10, -52, -38, 125 ] ] ]; return Group( gens ); fi; if n = -101 then gens:= [[[1,-3,8,-2,0,2], [5,-14,37,-3,-2,-2], [-3,8,-22,0,-5,2], [0,0,0,0,1,-1], [0,0,0,0,5,-4], [0,0,0,1,-1,6]], [[1,0,0,-1,1,-2], [0,1,0,-3,0,5], [0,0,1,-1,2,1], [0,0,0,2,-1,-1], [0,0,0,-2,-3,-6], [0,0,0,-1,-1,-2]]]; return Group( gens ); fi; if n = -102 then gens :=[[[-984,113,11,19,0,-2,-2,5,1,1,-1], [1160,146,223,201,0,1,0,-2,-3,2,3], [124,30,36,33,2,0,2,-2,1,-5,0], [113,11,19,17,3,0,4,-1,1,1,-1], [0,0,0,0, 619,1178,2242, 2,-2,-1,-2], [0,0,0,0, 3420, 6509,12388, 2,-2,-2,-4], [0,0,0,0, 1178, 2242, 4267, 2,0,1,-3], [0,0,0,0, 0,0,0, 5274, 4861, 4561, 4272], [0,0,0,0, 0,0,0, 57443, 53884,50471,47281], [0,0,0,0, 0,0,0, 9422,8833,8274,7751], [0,0,0,0, 0,0,0, 4861,4561,4272,4002]], [[4272,4002,3749,3512, -1,-2,2,-1,1,1,2], [47281,44292,41492,38869, 4,-1,-1,3,-2,3,1], [7751,7261,6802,6372, 2,-2,5,4,-1,-1,-3], [4002,3749,3512,3290, -1,1,0,-2,0,1,-3], [0,0,0,0, 0,0,1, -1,-1,-2,2], [0,0,0,0, 1,0,5, 3,-1,2,2], [0,0,0,0, 0,1,-1, -1,2,-1,0], [0,0,0,0, 0,0,0, 4272,4002,3749,3512 ], [0,0,0,0, 0,0,0, 47281,44292,41492,38869], [0,0,0,0, 0,0,0, 7751,7261,6802,6372], [0,0,0,0, 0,0,0, 4002,3749,3512,3290]] ]; return Group( gens ); fi; if n = -103 then gens := [ [ [ -12, -3, -18, 22, 0, 1/2, 0, 0, 0, 0, 0, 0 ], [ -1, 16, 46, -88, 1/2, 0, 1/2, 0, 0, 0, 0, 0 ], [ -2, -10, -23, 33, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 4, 14, -29, 0, 0, 0, 1/2, 1/2, 1/2, 0, 0 ], [ 0, 0, 0, 0, -1, -1, -1, 0, 0, 1/2, 0, 0 ], [ 0, 0, 0, 0, -5, 3, 5, -11, 1/2, 0, 0, 0 ], [ 0, 0, 0, 0, -3, 4, 5, -11, 0, 0, 1/2, 0 ], [ 0, 0, 0, 0, -3, 3, 4, -9, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0, 0, -15, 48, 36 -121 ], [ 0, 0, 0, 0, 0, 0, 0, 0, -26, 83, 62, -209 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 11, -71, -49, 165 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, -22, -14, 47 ] ], [ [ -12, -3, -18, 22, 0, 0, 0, 0, 0, 0, 0, 0 ], [ -1, 16, 46, -88, 0, 0, 0, 0, 1/2, 0, 0, 0 ], [ -2, -10, -23, 33, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 4, 14, -29, 1/2, 1/2, 0, 1/2, 0, 0, 0, 1/2 ], [ 0, 0, 0, 0, -3, 4, 6, -11, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 2, -5, -8, 11, 0, 1/2, 0, 1/2 ], [ 0, 0, 0, 0, 3, -5, -7, 11, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 2, -4, -6, 9, 0, 0, 1/2, 0 ], [ 0, 0, 0, 0, 0, 0, 0, 0, -15, 48, 36, -121 ], [ 0, 0, 0, 0, 0, 0, 0, 0, -26, 83, 62, -209 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 11, -71, -49, 165 ], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, -22, -14, 47 ] ] ]; return Group( gens ); fi; return fail; end; ############################################################################# # # examples groups used for the paper "testing polycyclicity" # SolvableMatGroupExams := function( n ) local gens,mat1,mat2; if n=1 then return PolExamples( 3 ); fi; if n=2 then return PolExamples( 4 ); fi; if n=3 then return PolExamples( 13 ); fi; if n=4 then return PolExamples( 16 ); fi; if n=5 then return PolExamples( 24 ); fi; if n=6 then return PolExamples( 27 ); fi; if n=7 then return POL_PolExamples2( 1201 ); fi; if n = 8 then return POL_PolExamples2( 1209 ); fi; if n = 9 then return POL_PolExamples2( 1210 ); fi; if n = 10 then # examples used during the talk in oxford and st andrews mat1 := [ [ 5/6, -2, 1, 4 ], [ 2/3, -19/6, -1, 4 ], [ 0, 0, 5/6, -2 ], [ 0, 0, 2/3, -19/6 ] ]; mat2 := [ [ -1/2, -12/5, 3, -1 ], [ 4/5, -53/10, -2, -4 ], [ 0, 0, -1/2, -12/5 ], [ 0, 0, 4/5, -53/10 ] ]; return Group( mat1, mat2 ); fi; return 0; end; # ideas for the construction of further examples # - semidirect product # - wreath product for example with S_4 # - extensions # - use library for finite integral matrix groups # - subdirect product # - use galois group of the arrising number fields # - direct product with finite group # - subdirect products S_4 \times G # S_4 \times G # | | # |alpha | beta # V V # S_3 or C_2 # # H = { (\sigma,g) : \sigma \alpha = g \beta} # K < G \times H polenta-1.3.11/exam/test.gi000644 000766 000024 00000027024 14775712140 015775 0ustar00mhornstaff000000 000000 ############################################################################# ## #W test.gi POLENTA package Bjoern Assmann ## ## examples for polycyclic rational matrix groups ## #Y 2003 ## ############################################################################# ## #F POL_RandomGroupElement( gens ) ## InstallGlobalFunction( POL_RandomGroupElement , function( gens ) local d,k,g,i,length,x,n; k:=Length(gens); g := gens[1]^0; length:=Random(2,10); for i in [1..length] do x:=Random(1,k); n:=Random( List( [-3..3] ) ); g:=g*(gens[x]^n); od; return g; end) ; ############################################################################# ## #F POL_Test_CPCS_PRMGroup( G ) ## ## G is a rational polycyclic matrix group ## POL_Test_CPCS_PRMGroup := function( G ) local numberOfTests, pcgs, gens, i, g, exp, a_level; a_level := AssertionLevel(); SetAssertionLevel( 2 ); Print( "Start testing\n" ); numberOfTests := 10; pcgs := CPCS_PRMGroup( G ); if pcgs = fail then return 0;fi; gens := GeneratorsOfGroup( G ); for i in [1..numberOfTests] do Print(i); g := POL_RandomGroupElement( gens ); Info( InfoPolenta, 3, "g is equal to ", g ); exp := ExponentVector_CPCS_PRMGroup( g, pcgs); if not Exp2Groupelement( pcgs.pcs, exp ) = g then Error( "Wrong exponent vector!\n" ); fi; od; SetAssertionLevel( a_level ); Print( "\n" ); end; ############################################################################# ## #F POL_Test_Series_PRMGroup( G ) ## ## G is a rational polycyclic matrix group ## POL_Test_Series_PRMGroup := function( G ) local radSer, homSer, comSer, a_level; a_level := AssertionLevel(); SetAssertionLevel( 2 ); radSer :=RadicalSeriesSolvableMatGroup( G ); if IsAbelian( G ) then homSer := HomogeneousSeriesAbelianMatGroup( G ); comSer := CompositionSeriesAbelianMatGroup( G ); fi; homSer := HomogeneousSeriesTriangularizableMatGroup( G ); comSer := CompositionSeriesTriangularizableMatGroup( G ); SetAssertionLevel( a_level ); end; ############################################################################# ## #F POL_Test_SubgroupComp_PRMGroup( G ) ## ## G is a rational polycyclic matrix group ## POL_Test_SubgroupComp_PRMGroup := function( G ) local T, reco, a_level; a_level := AssertionLevel(); SetAssertionLevel( 2 ); reco := SubgroupsUnipotentByAbelianByFinite( G ); SetAssertionLevel( a_level ); end; ############################################################################# ## #F POL_Test_Properties_PRMGroup( G ) ## ## G is a rational polycyclic matrix group ## POL_Test_Properties_PRMGroup := function( G ) local t,a_level; a_level := AssertionLevel(); SetAssertionLevel( 2 ); t := IsSolvableGroup( G ); t := IsTriangularizableMatGroup(G ); t := IsPolycyclicMatGroup( G ); SetAssertionLevel( a_level ); end; ############################################################################# ## #F POL_Test_Isom_PRMGroup( G ) ## ## G is a rational polycyclic matrix group ## POL_Test_Isom_PRMGroup := function( G ) local iso, src,mats,n,numberOfTests,i, exp1,mat1,img1,mat2, a_level; a_level := AssertionLevel(); SetAssertionLevel( 2 ); iso := IsomorphismPcpGroup( G ); if iso = fail then return 0;fi; mats := GeneratorsOfGroup( G ); n := Length( mats ); numberOfTests := 2; for i in [1..numberOfTests] do Info( InfoPolenta, 1, i ); #exp1 := List( [1..n], x-> Random( Integers ) ); #mat1 := MappedVector( exp1, mats ); mat1 := POL_RandomGroupElement( mats ); img1 := ImageElm( iso, mat1 ); mat2 := PreImage( iso, img1 ); if not mat1 = mat2 then Error( "Isomorphism calculated wrong preimage\n" ); fi; od; SetAssertionLevel( a_level ); Info( InfoPolenta, 1, "\n" ); end; ############################################################################# ## #F POL_Test_AllFunctions_PRMGroup( G ) ## ## G is a rational polycyclic matrix group ## POL_Test_AllFunctions_PRMGroup := function( G ) local a_level; a_level := AssertionLevel(); SetAssertionLevel( 2 ); Info( InfoPolenta, 2, "POL_Test_Isom_PRMGroup" ); POL_Test_Isom_PRMGroup( G ); Info( InfoPolenta, 2, "POL_Test_Properties_PRMGroup" ); POL_Test_Properties_PRMGroup( G ); Info( InfoPolenta, 2, "POL_Test_SubgroupComp_PRMGroup" ); POL_Test_SubgroupComp_PRMGroup( G ); Info( InfoPolenta, 2, "POL_Test_Series_PRMGroup" ); POL_Test_Series_PRMGroup( G ); SetAssertionLevel( a_level ); end; ############################################################################# ## #F POL_Test_AllFunctions_PolExamples( anfang, ende ) ## ## G is a rational polycyclic matrix group ## POL_Test_AllFunctions_PolExamples := function( anfang, ende ) local i, G, a_level; a_level := AssertionLevel(); SetAssertionLevel( 2 ); for i in [anfang..ende] do Print( "Test of group ", i, "\n" ); G := PolExamples( i ); POL_Test_AllFunctions_PRMGroup( G ); od; SetAssertionLevel( a_level ); end; ############################################################################# ## #F POL_Test_AllFunctions_PolExamples2( anfang, ende ) ## ## G is a rational polycyclic matrix group ## POL_Test_AllFunctions_PolExamples2 := function( anfang, ende ) local i, G, a_level; a_level := AssertionLevel(); SetAssertionLevel( 2 ); for i in [anfang..ende] do Print( "Test of group ", i, "\n" ); G := POL_PolExamples2( i ); POL_Test_AllFunctions_PRMGroup( G ); od; SetAssertionLevel( a_level ); end; POL_Test_AllFunctions_FeasibleExamples2 := function() local l1,l2,l3,l4,l5,ll,a_level,i,G; l1 := [-18..-1]; l2 := [1..16]; l3 := [18]; l4 := [29..44]; l5 := [46..59]; ll := Concatenation( l1, l2, l3, l4, l5 ); a_level := AssertionLevel(); SetAssertionLevel( 2 ); for i in ll do Print( "Test of group ", i, "\n" ); G := POL_PolExamples2( i ); POL_Test_AllFunctions_PRMGroup( G ); od; SetAssertionLevel( a_level ); end; ############################################################################# ## #F POL_Test_CPCS_PRMGroupExams( anfang, ende ) ## ## G is a rational polycyclic matrix group ## POL_Test_CPCS_PRMGroupExams := function( anfang, ende ) local i,G; #SetInfoLevel( InfoPolenta, 3 ); for i in [anfang..ende] do Print( "Test of PolExamples( ", i, " )\n" ); G := PolExamples( i ); POL_Test_CPCS_PRMGroup( G ); od; end; ############################################################################# ## #F POL_Test_CPCS_PRMGroupRuntime( anfang, ende ) ## ## G is a rational polycyclic matrix group ## POL_Test_CPCS_PRMGroupRuntime := function( anfang, ende ) local i,G, pcs; ProfileFunctions([CPCS_PRMGroup]); ClearProfile(); SetInfoLevel( InfoPolenta,0 ); SetAssertionLevel( 0 ); for i in [anfang..ende] do G := PolExamples( i ); pcs := CPCS_PRMGroup( G ); Print( "PolExamples ", i, "\n" ); DisplayProfile(); ClearProfile(); Print( "\n" ); od; return 0; end; POL_AbelianTestGroup := function( i ) local G,p, d, gens_p, bound_derivedLength, pcgs_I_p, gens_K_p, homSeries, gens_K_p_m, gens, gens_K_p_mutableCopy, pcgs, gensOfBlockAction; G := PolExamples( i ); gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an admissible prime p := DetermineAdmissiblePrime(gens); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; # finite part Info( InfoPolenta, 1,"determine a constructive polycyclic sequence\n", " for the image under the p-congruence homomorph."); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); Info( InfoPolenta, 1, "finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ) ); if pcgs_I_p = fail then return fail; fi; gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); gens_K_p := Filtered( gens_K_p, x -> not x = IdentityMat(d) ); # compositions series Info( InfoPolenta, 1, "compute the composition series "); gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); homSeries := POL_CompositionSeriesNormalGens( gens, gens_K_p_mutableCopy, d ); if homSeries=fail then return fail; fi; Info( InfoPolenta, 2, "composition series has length ", Length( homSeries ) ); # induce K_p to the factors of the composition series gensOfBlockAction := POL_InducedActionToSeries(gens_K_p, homSeries); return gensOfBlockAction; end; POL_CompleteRuntime:= function( func, input ) local rec1,rec2, user_time, user_time_child, system_time, system_time_child, sum; rec1 := Runtimes(); func( input ); rec2 := Runtimes(); user_time := rec2.user_time -rec1.user_time; user_time_child := rec2.user_time_children -rec1.user_time_children; system_time := rec2.system_time - rec1.system_time; system_time_child := rec2.system_time_children - rec1.system_time_children; sum := user_time + user_time_child + system_time + system_time_child; return StringTime( sum); end; POL_CompleteRuntime2:= function( func, input ) local rec1,rec2, user_time, user_time_child, system_time, system_time_child, sum, result; rec1 := Runtimes(); result := func( input ); rec2 := Runtimes(); user_time := rec2.user_time -rec1.user_time; user_time_child := rec2.user_time_children -rec1.user_time_children; system_time := rec2.system_time - rec1.system_time; system_time_child := rec2.system_time_children - rec1.system_time_children; sum := user_time + user_time_child + system_time + system_time_child; return rec( time := sum, result := result ); end; POL_CompleteRuntime_FullInfo:= function( func, input ) local rec1,rec2, rec3; rec1 := Runtimes(); func( input ); rec2 := Runtimes(); rec3 := rec( user_time := StringTime( rec2.user_time -rec1.user_time), user_time_child := StringTime( rec2.user_time_children -rec1.user_time_children ), system_time := StringTime( rec2.system_time - rec1.system_time ), system_time_child := StringTime( rec2.system_time_children - rec1.system_time_children ), ); return rec3; end; POL_Runtime := function( rec1, rec2 ) local user_time, user_time_child, system_time, system_time_child, sum; user_time := rec2.user_time -rec1.user_time; user_time_child := rec2.user_time_children -rec1.user_time_children; system_time := rec2.system_time - rec1.system_time; system_time_child := rec2.system_time_children - rec1.system_time_children; sum := user_time + user_time_child + system_time + system_time_child; return sum; end; POL_GroupData := function( G ) local gens, noGens, degree,ring; gens := GeneratorsOfGroup( G ); noGens := Length( gens ); degree := Length( gens[1] ); ring := "Q"; if IsIntegerMatrixGroup( G ) then ring := "Z"; fi; return [ degree, noGens, ring ]; end; ############################################################################# ## #E polenta-1.3.11/exam/test.gd000644 000766 000024 00000000614 14775712140 015764 0ustar00mhornstaff000000 000000 ############################################################################# ## #W test.gd POLENTA package Bjoern Assmann ## ## examples for polycyclic rational matrix groups ## #Y 2003 ## ############################################################################# ## #F POL_RandomGroupElement( gens ) ## DeclareGlobalFunction( "POL_RandomGroupElement" ); polenta-1.3.11/doc/info.xml000644 000766 000024 00000017101 14775712140 015760 0ustar00mhornstaff000000 000000 Information Messages It is possible to get informations about the status of the computation of the functions of Chapter of this manual.

Info Class is the Info class of the &Polenta; package (for more details on the Info mechanism see Section of the &GAP; Reference Manual). With the help of the function SetInfoLevel(InfoPolenta,level) you can change the info level of InfoPolenta. If InfoLevel( InfoPolenta ) is equal to 0 then no information messages are displayed. If InfoLevel( InfoPolenta ) is equal to 1 then basic informations about the process are provided. For further background on the displayed informations we refer to (publicly available via the Internet address http://www.icm.tu-bs.de/ag_algebra/software/assmann/diploma.pdf). If InfoLevel( InfoPolenta ) is equal to 2 then, in addition to the basic information, the generators of computed subgroups and module series are displayed.
Example SetInfoLevel( InfoPolenta, 1 ); gap> PcpGroupByMatGroup( PolExamples(11) ); #I Determine a constructive polycyclic sequence for the input group ... #I #I Chosen admissible prime: 3 #I #I Determine a constructive polycyclic sequence for the image under the p-congruence homomorphism ... #I finished. #I Finite image has relative orders [ 3, 2, 3, 3, 3 ]. #I #I Compute normal subgroup generators for the kernel of the p-congruence homomorphism ... #I finished. #I #I Compute the radical series ... #I finished. #I The radical series has length 4. #I #I Compute the composition series ... #I finished. #I The composition series has length 5. #I #I Compute a constructive polycyclic sequence for the induced action of the kernel to the composition series ... #I finished. #I This polycyclic sequence has relative orders [ ]. #I #I Calculate normal subgroup generators for the unipotent part ... #I finished. #I #I Determine a constructive polycyclic sequence for the unipotent part ... #I finished. #I The unipotent part has relative orders #I [ 0, 0, 0 ]. #I #I ... computation of a constructive polycyclic sequence for the whole group finished. #I #I Compute the relations of the polycyclic presentation of the group ... #I Compute power relations ... #I ... finished. #I Compute conjugation relations ... #I ... finished. #I Update polycyclic collector ... #I ... finished. #I finished. #I #I Construct the polycyclic presented group ... #I finished. #I Pcp-group with orders [ 3, 2, 3, 3, 3, 0, 0, 0 ] gap> SetInfoLevel( InfoPolenta, 2 ); gap> PcpGroupByMatGroup( PolExamples(11) ); #I Determine a constructive polycyclic sequence for the input group ... #I #I Chosen admissible prime: 3 #I #I Determine a constructive polycyclic sequence for the image under the p-congruence homomorphism ... #I finished. #I Finite image has relative orders [ 3, 2, 3, 3, 3 ]. #I #I Compute normal subgroup generators for the kernel of the p-congruence homomorphism ... #I finished. #I The normal subgroup generators are #I [ [ [ 1, -3/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ], [ [ 1, 0, 0, 24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3, 3, 15 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3, 3, 9 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3/2, 3/2, 3/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3/2, 9/2, -69/2 ], [ 0, 1, 0, 9 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ] , [ [ 1, 0, 0, -24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, -3, -15 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3/2, -3/2, -9/2 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, -3, -12 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3, -3/2, -21 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3/2, 3/2, 9/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ] ] #I #I Compute the radical series ... #I finished. #I The radical series has length 4. #I The radical series is #I [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 0, 1 ] ], [ ] ] #I #I Compute the composition series ... #I finished. #I The composition series has length 5. #I The composition series is #I [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 0, 1 ] ], [ ] ] #I #I Compute a constructive polycyclic sequence for the induced action of the kernel to the composition series ... #I finished. #I This polycyclic sequence has relative orders [ ]. #I #I Calculate normal subgroup generators for the unipotent part ... #I finished. #I The normal subgroup generators for the unipotent part are #I [ [ [ 1, -3/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ], [ [ 1, 0, 0, 24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3, 3, 15 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3, 3, 9 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3/2, 3/2, 3/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3/2, 9/2, -69/2 ], [ 0, 1, 0, 9 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ] , [ [ 1, 0, 0, -24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, -3, -15 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3/2, -3/2, -9/2 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ], [ [ 1, -3, -3, -12 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3, -3/2, -21 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ], [ [ 1, 3/2, 3/2, 9/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ] ] #I #I Determine a constructive polycyclic sequence for the unipotent part ... #I finished. #I The unipotent part has relative orders #I [ 0, 0, 0 ]. #I #I ... computation of a constructive polycyclic sequence for the whole group finished. #I #I Compute the relations of the polycyclic presentation of the group ... #I Compute power relations ... ..... #I ... finished. #I Compute conjugation relations ... .............................................. #I ... finished. #I Update polycyclic collector ... #I ... finished. #I finished. #I #I Construct the polycyclic presented group ... #I finished. #I Pcp-group with orders [ 3, 2, 3, 3, 3, 0, 0, 0 ] ]]>
polenta-1.3.11/doc/manual.six000644 000766 000024 00000014321 14775712162 016312 0ustar00mhornstaff000000 000000 #SIXFORMAT GapDocGAP HELPBOOKINFOSIXTMP := rec( encoding := "UTF-8", bookname := "Polenta", entries := [ [ "Title page", "0.0", [ 0, 0, 0 ], 1, 1, "title page", "X7D2C85EC87DD46E5" ], [ "Copyright", "0.0-1", [ 0, 0, 1 ], 21, 2, "copyright", "X81488B807F2A1CF1" ], [ "Acknowledgements", "0.0-2", [ 0, 0, 2 ], 32, 2, "acknowledgements", "X82A988D47DFAFCFA" ], [ "Table of Contents", "0.0-3", [ 0, 0, 3 ], 39, 3, "table of contents", "X8537FEB07AF2BEC8" ], [ "\033[1X\033[33X\033[0;-2YIntroduction\033[133X\033[101X", "1", [ 1, 0, 0 ], 1, 4, "introduction", "X7DFB63A97E67C0A1" ], [ "\033[1X\033[33X\033[0;-2YThe package\033[133X\033[101X", "1.1", [ 1, 1, 0 ], 4, 4, "the package", "X79DE59997FDCF767" ], [ "\033[1X\033[33X\033[0;-2YPolycyclic groups\033[133X\033[101X", "1.2", [ 1, 2, 0 ], 30, 4, "polycyclic groups", "X86007B0083F60470" ], [ "\033[1X\033[33X\033[0;-2YMethods for matrix groups\033[133X\033[101X", "2", [ 2, 0, 0 ], 1, 5, "methods for matrix groups", "X829BA50B82FEC109" ], [ "\033[1X\033[33X\033[0;-2YPolycyclic presentations of matrix groups\033[133\ X\033[101X", "2.1", [ 2, 1, 0 ], 4, 5, "polycyclic presentations of matrix groups", "X826C51B3825A2789" ], [ "\033[1X\033[33X\033[0;-2YModule series\033[133X\033[101X", "2.2", [ 2, 2, 0 ], 70, 6, "module series", "X80D1E9E07DB87F97" ], [ "\033[1X\033[33X\033[0;-2YSubgroups\033[133X\033[101X", "2.3", [ 2, 3, 0 ], 133, 7, "subgroups", "X7BA181CA81D785BB" ], [ "\033[1X\033[33X\033[0;-2YExamples\033[133X\033[101X", "2.4", [ 2, 4, 0 ], 146, 8, "examples", "X7A489A5D79DA9E5C" ], [ "\033[1X\033[33X\033[0;-2YAn example application\033[133X\033[101X", "3", [ 3, 0, 0 ], 1, 9, "an example application", "X81CAD2F27B2066C4" ], [ "\033[1X\033[33X\033[0;-2YPresentation for rational matrix groups\033[133X\\ 033[101X", "3.1", [ 3, 1, 0 ], 7, 9, "presentation for rational matrix groups" , "X7DAC33E37B977087" ], [ "\033[1X\033[33X\033[0;-2YModules series\033[133X\033[101X", "3.2", [ 3, 2, 0 ], 61, 10, "modules series", "X79CF643081B3FB26" ], [ "\033[1X\033[33X\033[0;-2YTriangularizable subgroups\033[133X\033[101X", "3.3", [ 3, 3, 0 ], 86, 10, "triangularizable subgroups", "X7BA34CD28059D6CD" ], [ "\033[1X\033[33X\033[0;-2YInstallation\033[133X\033[101X", "4", [ 4, 0, 0 ], 1, 12, "installation", "X8360C04082558A12" ], [ "\033[1X\033[33X\033[0;-2YInstalling this package\033[133X\033[101X", "4.1", [ 4, 1, 0 ], 4, 12, "installing this package", "X81746D7285808409" ], [ "\033[1X\033[33X\033[0;-2YLoading the \033[5XPolenta\033[105X\033[101X\027\\ 033[1X\027 package\033[133X\033[101X", "4.2", [ 4, 2, 0 ], 19, 12, "loading the polenta package", "X802ED64A87AA11DC" ], [ "\033[1X\033[33X\033[0;-2YRunning the test suite\033[133X\033[101X", "4.3", [ 4, 3, 0 ], 26, 12, "running the test suite", "X796DF52483B61C74" ], [ "\033[1X\033[33X\033[0;-2YInformation Messages\033[133X\033[101X", "5", [ 5, 0, 0 ], 1, 13, "information messages", "X85677704855596EB" ], [ "\033[1X\033[33X\033[0;-2YInfo Class\033[133X\033[101X", "5.1", [ 5, 1, 0 ], 7, 13, "info class", "X7EBFC26F83EB9F72" ], [ "\033[1X\033[33X\033[0;-2YExample\033[133X\033[101X", "5.2", [ 5, 2, 0 ], 32, 13, "example", "X85861B017AEEC50B" ], [ "Bibliography", "bib", [ "Bib", 0, 0 ], 1, 17, "bibliography", "X7A6F98FD85F02BFE" ], [ "References", "bib", [ "Bib", 0, 0 ], 1, 17, "references", "X7A6F98FD85F02BFE" ], [ "Index", "ind", [ "Ind", 0, 0 ], 1, 18, "index", "X83A0356F839C696F" ], [ "License", "0.0-1", [ 0, 0, 1 ], 21, 2, "license", "X81488B807F2A1CF1" ], [ "Polenta", "1.0", [ 1, 0, 0 ], 1, 4, "polenta", "X7DFB63A97E67C0A1" ], [ "Polycyclic", "1.0", [ 1, 0, 0 ], 1, 4, "polycyclic", "X7DFB63A97E67C0A1" ], [ "\033[2XPcpGroupByMatGroup\033[102X", "2.1-1", [ 2, 1, 1 ], 15, 5, "pcpgroupbymatgroup", "X7A1BC4437FD92201" ], [ "\033[2XIsomorphismPcpGroup\033[102X", "2.1-2", [ 2, 1, 2 ], 23, 5, "isomorphismpcpgroup", "X8771540F7A235763" ], [ "\033[2XImagesRepresentative\033[102X", "2.1-3", [ 2, 1, 3 ], 36, 5, "imagesrepresentative", "X85ADB89B7C8DD7D0" ], [ "\033[2XImageElm\033[102X", "2.1-3", [ 2, 1, 3 ], 36, 5, "imageelm", "X85ADB89B7C8DD7D0" ], [ "\033[2XImagesSet\033[102X", "2.1-3", [ 2, 1, 3 ], 36, 5, "imagesset", "X85ADB89B7C8DD7D0" ], [ "\033[2XIsSolvableGroup\033[102X", "2.1-4", [ 2, 1, 4 ], 49, 6, "issolvablegroup", "X809C78D5877D31DF" ], [ "\033[2XIsTriangularizableMatGroup\033[102X", "2.1-5", [ 2, 1, 5 ], 56, 6, "istriangularizablematgroup", "X7EE01C207C214C1F" ], [ "\033[2XIsPolycyclicGroup\033[102X", "2.1-6", [ 2, 1, 6 ], 63, 6, "ispolycyclicgroup", "X7D7456077D3D1B86" ], [ "\033[2XRadicalSeriesSolvableMatGroup\033[102X", "2.2-1", [ 2, 2, 1 ], 86, 6, "radicalseriessolvablematgroup", "X84472FDC863322BD" ], [ "\033[2XHomogeneousSeriesAbelianMatGroup\033[102X", "2.2-2", [ 2, 2, 2 ], 95, 7, "homogeneousseriesabelianmatgroup", "X8524F992828B6A71" ], [ "\033[2XHomogeneousSeriesTriangularizableMatGroup\033[102X", "2.2-3", [ 2, 2, 3 ], 105, 7, "homogeneousseriestriangularizablematgroup", "X87D9F67C7CBB1499" ], [ "\033[2XCompositionSeriesAbelianMatGroup\033[102X", "2.2-4", [ 2, 2, 4 ], 117, 7, "compositionseriesabelianmatgroup", "X86FB6E9B801A37D4" ], [ "\033[2XCompositionSeriesTriangularizableMatGroup\033[102X", "2.2-5", [ 2, 2, 5 ], 125, 7, "compositionseriestriangularizablematgroup", "X78DE110C7E2A493C" ], [ "\033[2XSubgroupsUnipotentByAbelianByFinite\033[102X", "2.3-1", [ 2, 3, 1 ], 136, 7, "subgroupsunipotentbyabelianbyfinite", "X79273B8581D15356" ], [ "\033[2XPolExamples\033[102X", "2.4-1", [ 2, 4, 1 ], 149, 8, "polexamples", "X7C7C3EFA7E49F932" ], [ "Installation", "4.0", [ 4, 0, 0 ], 1, 12, "installation", "X8360C04082558A12" ], [ "Loading the \033[5XPolenta\033[105X package", "4.2", [ 4, 2, 0 ], 19, 12, "loading the polenta package", "X802ED64A87AA11DC" ], [ "\033[2XInfoPolenta\033[102X", "5.1-1", [ 5, 1, 1 ], 10, 13, "infopolenta", "X809F2CFB87393CE0" ] ] ); polenta-1.3.11/doc/chapBib_mj.html000644 000766 000024 00000010705 14775712162 017216 0ustar00mhornstaff000000 000000 GAP (Polenta) - References
Goto Chapter: Top 1 2 3 4 5 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

References

[AE05] Assmann, B. and Eick, B., Computing polycyclic presentations for polycyclic rational matrix groups, J. Symbolic Comput., 40 (6) (2005), 1269--1284.

[Ass03] Assmann, B., Polycyclic presentations for matrix groups, Diplomarbeit, TU Braunschweig (2003)
(http://www.icm.tu-bs.de/ag_algebra/software/assmann).

[Eic01] Eick, B., Algorithms for Polycyclic Groups, Habilitationsschrift, Gesamthochschule Kassel (2001).

[EN00] Eick, B. and Nickel, W., Polycyclic (2000)
(GAP package).

[Ost96] Ostheimer, G., Algorithms for Polycyclic-by-finite groups, Ph.D. thesis, Rutgers University (1996).

[Sim94] Sims, C. C., Computation with finitely presented groups, Cambridge University Press (1994).

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/_entities.xml000644 000766 000024 00000000057 14775712156 017021 0ustar00mhornstaff000000 000000 Polenta'> polenta-1.3.11/doc/chap0_mj.html000644 000766 000024 00000021453 14775712162 016663 0ustar00mhornstaff000000 000000 GAP (Polenta) - Contents
Goto Chapter: Top 1 2 3 4 5 Bib Ind
 [Top of Book]  [Contents]   [Next Chapter] 

Polenta

Polycyclic presentations for matrix groups

1.3.11

10 April 2025

Björn Assmann

Copyright

© 2003-2007 by Björn Assmann

The Polenta package 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.

Acknowledgements

We appreciate very much all past and future comments, suggestions and contributions to this package and its documentation provided by GAP users and developers.

Contents

1 Introduction
2 Methods for matrix groups
3 An example application
4 Installation
5 Information Messages
References
Index

 [Top of Book]  [Contents]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/chap2.html000644 000766 000024 00000046430 14775712162 016201 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 2: Methods for matrix groups
Goto Chapter: Top 1 2 3 4 5 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

2 Methods for matrix groups
 2.1 Polycyclic presentations of matrix groups
 2.2 Module series
 2.3 Subgroups
 2.4 Examples

2 Methods for matrix groups

2.1 Polycyclic presentations of matrix groups

Groups defined by polycyclic presentations are called PcpGroups in GAP. We refer to the Polycyclic manual [EN00] for further background.

Suppose that a collection X of matrices of GL(d,R) is given, where the ring R is either ℚ,ℤ or a finite field. Let G= ⟨ X ⟩. If the group G is polycyclic, then the following functions determine a PcpGroup isomorphic to G.

2.1-1 PcpGroupByMatGroup
‣ PcpGroupByMatGroup( G )( operation )

G is a subgroup of GL(d,R) where R=ℚ,ℤ or F_q. If G is polycyclic, then this function determines a PcpGroup isomorphic to G. If G is not polycyclic, then this function returns fail.

2.1-2 IsomorphismPcpGroup
‣ IsomorphismPcpGroup( G )( method )

G is a subgroup of GL(d,R) where R=ℚ,ℤ or F_q. If G is polycyclic, then this function determines an isomorphism onto a PcpGroup. If G is not polycyclic, then this function returns fail.

Note that the method IsomorphismPcpGroup, installed in this package, cannot be applied directly to a group given by the function AlmostCrystallographicGroup. Please use POL_AlmostCrystallographicGroup (with the same parameters as AlmostCrystallographicGroup) instead.

2.1-3 ImagesRepresentative
‣ ImagesRepresentative( map, elm )( method )
‣ ImageElm( map, elm )( method )
‣ ImagesSet( map, elms )( method )

Here map is an isomorphism from a polycyclic matrix group G onto a PcpGroup H calculated by IsomorphismPcpGroup (2.1-2). These methods can be used to compute with such an isomorphism. If the input elm is an element of G, then the function ImageElm can be used to compute the image of elm under map. If elm is not contained in G then the function ImageElm returns fail. The input pcpelm is an element of H.

2.1-4 IsSolvableGroup
‣ IsSolvableGroup( G )( method )

G is a subgroup of GL(d,R) where R=ℚ,ℤ or F_q. This function tests if G is solvable and returns true or false.

2.1-5 IsTriangularizableMatGroup
‣ IsTriangularizableMatGroup( G )( property )

G is a subgroup of GL(d,ℚ). This function tests if G is triangularizable (possibly over a finite field extension) and returns true or false.

2.1-6 IsPolycyclicGroup
‣ IsPolycyclicGroup( G )( method )

G is a subgroup of GL(d,R) where R=ℚ,ℤ or F_q. This function tests if G is polycyclic and returns true or false.

2.2 Module series

Let G be a finitely generated solvable subgroup of GL(d,ℚ). The vector space ℚ^d is a module for the algebra ℚ[G]. The following functions provide the possibility to compute certain module series of ℚ^d. Recall that the radical Rad_G(ℚ^d) is defined to be the intersection of maximal ℚ[G]-submodules of ℚ^d. Also recall that the radical series

0=R_n < R_{n-1} < \dots < R_1 < R_0=ℚ^d

is defined by R_i+1:= Rad_G(R_i).

2.2-1 RadicalSeriesSolvableMatGroup
‣ RadicalSeriesSolvableMatGroup( G )( operation )

This function returns a radical series for the ℚ[G]-module ℚ^d, where G is a solvable subgroup of GL(d,ℚ).

A radical series of ℚ^d can be refined to a homogeneous series.

2.2-2 HomogeneousSeriesAbelianMatGroup
‣ HomogeneousSeriesAbelianMatGroup( G )( function )

A module is said to be homogeneous if it is the direct sum of pairwise irreducible isomorphic submodules. A homogeneous series of a module is a submodule series such that the factors are homogeneous. This function returns a homogeneous series for the ℚ[G]-module ℚ^d, where G is an abelian subgroup of GL(d,ℚ).

2.2-3 HomogeneousSeriesTriangularizableMatGroup
‣ HomogeneousSeriesTriangularizableMatGroup( G )( function )

A module is said to be homogeneous if it is the direct sum of pairwise irreducible isomorphic submodules. A homogeneous series of a module is a submodule series such that the factors are homogeneous. This function returns a homogeneous series for the ℚ[G]-module ℚ^d, where G is a triangularizable subgroup of GL(d,ℚ).

A homogeneous series can be refined to a composition series.

2.2-4 CompositionSeriesAbelianMatGroup
‣ CompositionSeriesAbelianMatGroup( G )( function )

A composition series of a module is a submodule series such that the factors are irreducible. This function returns a composition series for the ℚ[G]-module ℚ^d, where G is an abelian subgroup of GL(d,ℚ).

2.2-5 CompositionSeriesTriangularizableMatGroup
‣ CompositionSeriesTriangularizableMatGroup( G )( function )

A composition series of a module is a submodule series such that the factors are irreducible. This function returns a composition series for the ℚ[G]-module ℚ^d, where G is a triangularizable subgroup of GL(d,ℚ).

2.3 Subgroups

2.3-1 SubgroupsUnipotentByAbelianByFinite
‣ SubgroupsUnipotentByAbelianByFinite( G )( operation )

G is a subgroup of GL(d,R) where R=ℚ or . If G is polycyclic, then this function returns a record containing two normal subgroups T and U of G. The group T is unipotent-by-abelian (and thus triangularizable) and of finite index in G. The group U is unipotent and is such that T/U is abelian. If G is not polycyclic, then the algorithm returns fail.

2.4 Examples

2.4-1 PolExamples
‣ PolExamples( l )( function )

Returns some examples for polycyclic rational matrix groups, where l is an integer between 1 and 24. These can be used to test the functions in this package. Some of the properties of the examples are summarised in the following table.

PolExamples      number generators      subgroup of      Hirsch length
          1                      3           GL(4,Z)                 6
          2                      2           GL(5,Z)                 6
          3                      2           GL(4,Q)                 4
          4                      2           GL(5,Q)                 6
          5                      9          GL(16,Z)                 3
          6                      6           GL(4,Z)                 3
          7                      6           GL(4,Z)                 3
          8                      7           GL(4,Z)                 3
          9                      5           GL(4,Q)                 3
         10                      4           GL(4,Q)                 3
         11                      5           GL(4,Q)                 3
         12                      5           GL(4,Q)                 3
         13                      5           GL(5,Q)                 4
         14                      6           GL(5,Q)                 4
         15                      6           GL(5,Q)                 4
         16                      5           GL(5,Q)                 4
         17                      5           GL(5,Q)                 4
         18                      5           GL(5,Q)                 4
         19                      5           GL(5,Q)                 4
         20                      7          GL(16,Z)                 3
         21                      5          GL(16,Q)                 3
         22                      4          GL(16,Q)                 3
         23                      5          GL(16,Q)                 3
         24                      5          GL(16,Q)                 3

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/install.xml000644 000766 000024 00000004411 14775712140 016473 0ustar00mhornstaff000000 000000 Installation Installation
Installing this package The &Polenta; package is part of the standard distribution of &GAP; and so normally there should be no need to install it separately. If by any chance it is not part of your &GAP; distribution, then the standard method is to unpack the package into the pkg directory of your &GAP; distribution. This will create a polenta subdirectory. For other non-standard options please see Chapter of the &GAP; Reference Manual.

Note that the GAP-Packages Alnuth and Polycyclic are needed for this package. Normally they should be contained in your distribution. If not, they can be obtained at https://www.gap-system.org/Packages/packages.html.

Loading the &Polenta; package Loading the &Polenta; package If the &Polenta; package is not already loaded then you have to request it explicitly. This can be done via the command.
Running the test suite Once the package is installed, it is possible to check the correct installation by running the test suite of the package. ReadPackage( "Polenta", "tst/testall.g" ); ]]> For more details on Test Files see Section of the &GAP; Reference Manual.

If the test suite runs into an error, even though the packages Polycyclic and Alnuth and their depdendencies have been correctly installed, then please send a message to mhorn@rptu.de including the error message.

polenta-1.3.11/doc/chap3.html000644 000766 000024 00000016627 14775712162 016207 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 3: An example application
Goto Chapter: Top 1 2 3 4 5 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

3 An example application
 3.1 Presentation for rational matrix groups
 3.2 Modules series
 3.3 Triangularizable subgroups

3 An example application

In this section we outline three example computations with functions from the previous chapter.

3.1 Presentation for rational matrix groups

gap> mats :=
[ [ [ 1, 0, -1/2, 0 ], [ 0, 1, 0, 1 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 1/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 1 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 0, 0, 1 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -1/2, -3, 7/6 ], [ 0, 1, -1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ -1, 3, 3, 0 ], [ 0, 0, 1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ] ];

gap> G := Group( mats );
<matrix group with 5 generators>

# calculate an isomorphism from G to a pcp-group
gap> nat := IsomorphismPcpGroup( G );;

gap> H := Image( nat );
Pcp-group with orders [ 2, 2, 3, 5, 5, 5, 0, 0, 0 ]

gap> h := GeneratorsOfGroup( H );
[ g1, g2, g3, g4, g5, g6, g7, g8, g9]

gap> mats2 := List( h, x -> PreImage( nat, x ) );;

# take a random element of G
gap> exp :=  [ 1, 1, 1, 1, 0, 0, 0, 0, 1 ];;
gap> g := MappedVector( exp, mats2 );
[ [ -1, 17/2, -1, 233/6 ],
  [ 0, 1, 0, -2 ],
  [ 0, 1, -1, 2 ],
  [ 0, 0, 0, 1 ] ]

# map g into the image of nat
gap> i := ImageElm( nat, g );
g1*g2*g3*g4*g9

# exponent vector
gap> Exponents( i );
[ 1, 1, 1, 1, 0, 0, 0, 0, 1 ]

# compare the preimage with g
gap> PreImagesRepresentative( nat, i );
[ [ -1, 17/2, -1, 233/6 ],
  [ 0, 1, 0, -2 ],
  [ 0, 1, -1, 2 ],
  [ 0, 0, 0, 1 ] ]


gap> last = g;
true

3.2 Modules series

gap> gens :=
[ [ [ 1746/1405, 524/7025, 418/1405, -77/2810 ],
    [ 815/843, 899/843, -1675/843, 415/281 ],
    [ -3358/4215, -3512/21075, 4631/4215, -629/1405 ],
    [ 258/1405, 792/7025, 1404/1405, 832/1405 ] ],
  [ [ -2389/2810, 3664/21075, 8942/4215, -35851/16860 ],
    [ 395/281, 2498/2529, -5105/5058, 3260/2529 ],
    [ 3539/2810, -13832/63225, -12001/12645, 87053/50580 ],
    [ 5359/1405, -3128/21075, -13984/4215, 40561/8430 ] ] ];

gap> H := Group( gens );
<matrix group with 2 generators>

gap> RadicalSeriesSolvableMatGroup( H );
[ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 0, 0, 79/138 ], [ 0, 1, 0, -275/828 ], [ 0, 0, 1, -197/414 ] ],
  [ [ 1, 0, -3, 2 ], [ 0, 1, 55/4, -55/8 ] ],
  [ [ 1, 4/15, 2/3, 1/6 ] ],
  [  ] ]

3.3 Triangularizable subgroups

gap> G := PolExamples(3);
<matrix group with 2 generators>

gap> GeneratorsOfGroup( G );
[ [ [ 73/10, -35/2, 42/5, 63/2 ],
    [ 27/20, -11/4, 9/5, 27/4 ],
    [ -3/5, 1, -4/5, -9 ],
    [ -11/20, 7/4, -2/5, 1/4 ] ],
  [ [ -42/5, 423/10, 27/5, 479/10 ],
    [ -23/10, 227/20, 13/10, 231/20 ],
    [ 14/5, -63/5, -4/5, -79/5 ],
    [ -1/10, 9/20, 1/10, 37/20 ] ] ]

gap> subgroups := SubgroupsUnipotentByAbelianByFinite( G );
rec( T := <matrix group with 2 generators>,
  U := <matrix group with 4 generators> )

gap> GeneratorsOfGroup( subgroups.T );
[ [ [ 73/10, -35/2, 42/5, 63/2 ],
    [ 27/20, -11/4, 9/5, 27/4 ],
    [ -3/5, 1, -4/5, -9 ],
    [ -11/20, 7/4, -2/5, 1/4 ] ],
  [ [ -42/5, 423/10, 27/5, 479/10 ],
    [ -23/10, 227/20, 13/10, 231/20 ],
    [ 14/5, -63/5, -4/5, -79/5 ],
    [ -1/10, 9/20, 1/10, 37/20 ] ] ]

# so G is triangularizable!
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/chap1_mj.html000644 000766 000024 00000013327 14775712162 016665 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 1: Introduction
Goto Chapter: Top 1 2 3 4 5 Bib Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

1 Introduction
 1.1 The package
 1.2 Polycyclic groups

1 Introduction

1.1 The package

This package provides functions for computation with matrix groups. Let \(G\) be a subgroup of \(GL(d,R)\) where the ring \(R\) is either equal to \(ℚ,ℤ\) or a finite field \(\mathbb{F}_q\). Then:

A group \(G\) which is given by a polycyclic presentation can be largely investigated by algorithms implemented in the GAP-package Polycyclic [EN00]. For example we can determine if \(G\) is torsion-free and calculate the torsion subgroup. Further we can compute the derived series and the Hirsch length of the group \(G\). Also various methods for computations with subgroups, factor groups and extensions are available.

As a by-product, the Polenta package provides some functionality to compute certain module series for modules of solvable groups. For example, if \(G\) is a rational polycyclic matrix group, then we can compute the radical series of the natural \(ℚ[G]\)-module \(ℚ^d\).

1.2 Polycyclic groups

A group \(G\) is called polycyclic if it has a finite subnormal series with cyclic factors. It is a well-known fact that every polycyclic group is finitely presented by a so-called polycyclic presentation (see for example Chapter 9 in [Sim94] or Chapter 2 in [EN00] ). In GAP, groups which are defined by polycyclic presentations are called polycyclically presented groups, abbreviated PcpGroups.

The overall idea of the algorithm implemented in this package was first introduced by Ostheimer in 1996 [Ost96]. In 2001 Eick presented a more detailed version [Eic01]. This package contains an implementation of Eick's algorithm. A description of this implementation together with some refinements and extensions can be found in [AE05] and [Ass03].

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/title.xml000644 000766 000024 00000002114 14775712156 016153 0ustar00mhornstaff000000 000000 Polenta Polycyclic presentations for matrix groups 1.3.11 Björn Assmann
10 April 2025 License ©right; 2003-2007 by Björn Assmann

The &Polenta; package is free software; you can redistribute it and/or modify it under the terms of the https://www.fsf.org/licenses/gpl.html as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. We appreciate very much all past and future comments, suggestions and contributions to this package and its documentation provided by &GAP; users and developers. polenta-1.3.11/doc/manual.js000644 000766 000024 00000010113 14775712162 016116 0ustar00mhornstaff000000 000000 /* manual.js Frank Lübeck */ /* This file contains a few javascript functions which allow to switch between display styles for GAPDoc HTML manuals. If javascript is switched off in a browser or this file in not available in a manual directory, this is no problem. Users just cannot switch between several styles and don't see the corresponding button. A style with name mystyle can be added by providing two files (or only one of them). mystyle.js: Additional javascript code for the style, it is read in the HTML pages after this current file. The additional code may adjust the preprocessing function jscontent() with is called onload of a file. This is done by appending functions to jscontentfuncs (jscontentfuncs.push(newfunc);). Make sure, that your style is still usable without javascript. mystyle.css: CSS configuration, read after manual.css (so it can just reconfigure a few details, or overwrite everything). Then adjust chooser.html such that users can switch on and off mystyle. A user can change the preferred style permanently by using the [Style] link and choosing one. Or one can append '?GAPDocStyle=mystyle' to the URL when loading any file of the manual (so the style can be configured in the GAP user preferences). */ /* generic helper function */ function deleteCookie(nam) { document.cookie = nam+"=;Path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT"; } /* read a value from a "nam1=val1;nam2=val2;..." string (e.g., the search part of an URL or a cookie */ function valueString(str,nam) { var cs = str.split(";"); for (var i=0; i < cs.length; i++) { var pos = cs[i].search(nam+"="); if (pos > -1) { pos = cs[i].indexOf("="); return cs[i].slice(pos+1); } } return 0; } /* when a non-default style is chosen via URL or a cookie, then the cookie is reset and the styles .js and .css files are read */ function overwriteStyle() { /* style in URL? */ var style = valueString(window.location.search, "GAPDocStyle"); /* otherwise check cookie */ if (style == 0) style = valueString(document.cookie, "GAPDocStyle"); if (style == 0) return; if (style == "default") deleteCookie("GAPDocStyle"); else { /* ok, we set the cookie for path "/" */ var path = "/"; /* or better like this ??? var here = window.location.pathname.split("/"); for (var i=0; i+3 < here.length; i++) path = path+"/"+here[i]; */ document.cookie = "GAPDocStyle="+style+";Path="+path; /* split into names of style files */ var stlist = style.split(","); /* read style's css and js files */ for (var i=0; i < stlist.length; i++) { document.writeln(''); document.writeln(''); } } } /* this adds a "[Style]" link next to the MathJax switcher */ function addStyleLink() { var line = document.getElementById("mathjaxlink"); var el = document.createElement("a"); var oncl = document.createAttribute("href"); var back = window.location.protocol+"//" if (window.location.protocol == "http:" || window.location.protocol == "https:") { back = back+window.location.host; if (window.location.port != "") { back = back+":"+window.location.port; } } back = back+window.location.pathname; oncl.nodeValue = "chooser.html?BACK="+back; el.setAttributeNode(oncl); var cont = document.createTextNode(" [Style]"); el.appendChild(cont); line.appendChild(el); } var jscontentfuncs = new Array(); jscontentfuncs.push(addStyleLink); /* the default jscontent() only adds the [Style] link to the page */ function jscontent () { for (var i=0; i < jscontentfuncs.length; i++) jscontentfuncs[i](); } polenta-1.3.11/doc/chapInd.html000644 000766 000024 00000007741 14775712162 016554 0ustar00mhornstaff000000 000000 GAP (Polenta) - Index

Goto Chapter: Top 1 2 3 4 5 Bib Ind

Index

CompositionSeriesAbelianMatGroup 2.2-4
CompositionSeriesTriangularizableMatGroup 2.2-5
HomogeneousSeriesAbelianMatGroup 2.2-2
HomogeneousSeriesTriangularizableMatGroup 2.2-3
ImageElm 2.1-3
ImagesRepresentative 2.1-3
ImagesSet 2.1-3
InfoPolenta 5.1-1
Installation 4.
IsomorphismPcpGroup 2.1-2
IsPolycyclicGroup 2.1-6
IsSolvableGroup 2.1-4
IsTriangularizableMatGroup 2.1-5
License .-1
Loading the Polenta package 4.2
PcpGroupByMatGroup 2.1-1
Polenta 1.
PolExamples 2.4-1
Polycyclic 1.
RadicalSeriesSolvableMatGroup 2.2-1
SubgroupsUnipotentByAbelianByFinite 2.3-1

Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/chap3_mj.html000644 000766 000024 00000017152 14775712162 016667 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 3: An example application
Goto Chapter: Top 1 2 3 4 5 Bib Ind

3 An example application

In this section we outline three example computations with functions from the previous chapter.

3.1 Presentation for rational matrix groups

gap> mats :=
[ [ [ 1, 0, -1/2, 0 ], [ 0, 1, 0, 1 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 1/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 1 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 0, 0, 1 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -1/2, -3, 7/6 ], [ 0, 1, -1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ -1, 3, 3, 0 ], [ 0, 0, 1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ] ];

gap> G := Group( mats );
<matrix group with 5 generators>

# calculate an isomorphism from G to a pcp-group
gap> nat := IsomorphismPcpGroup( G );;

gap> H := Image( nat );
Pcp-group with orders [ 2, 2, 3, 5, 5, 5, 0, 0, 0 ]

gap> h := GeneratorsOfGroup( H );
[ g1, g2, g3, g4, g5, g6, g7, g8, g9]

gap> mats2 := List( h, x -> PreImage( nat, x ) );;

# take a random element of G
gap> exp :=  [ 1, 1, 1, 1, 0, 0, 0, 0, 1 ];;
gap> g := MappedVector( exp, mats2 );
[ [ -1, 17/2, -1, 233/6 ],
  [ 0, 1, 0, -2 ],
  [ 0, 1, -1, 2 ],
  [ 0, 0, 0, 1 ] ]

# map g into the image of nat
gap> i := ImageElm( nat, g );
g1*g2*g3*g4*g9

# exponent vector
gap> Exponents( i );
[ 1, 1, 1, 1, 0, 0, 0, 0, 1 ]

# compare the preimage with g
gap> PreImagesRepresentative( nat, i );
[ [ -1, 17/2, -1, 233/6 ],
  [ 0, 1, 0, -2 ],
  [ 0, 1, -1, 2 ],
  [ 0, 0, 0, 1 ] ]


gap> last = g;
true

3.2 Modules series

gap> gens :=
[ [ [ 1746/1405, 524/7025, 418/1405, -77/2810 ],
    [ 815/843, 899/843, -1675/843, 415/281 ],
    [ -3358/4215, -3512/21075, 4631/4215, -629/1405 ],
    [ 258/1405, 792/7025, 1404/1405, 832/1405 ] ],
  [ [ -2389/2810, 3664/21075, 8942/4215, -35851/16860 ],
    [ 395/281, 2498/2529, -5105/5058, 3260/2529 ],
    [ 3539/2810, -13832/63225, -12001/12645, 87053/50580 ],
    [ 5359/1405, -3128/21075, -13984/4215, 40561/8430 ] ] ];

gap> H := Group( gens );
<matrix group with 2 generators>

gap> RadicalSeriesSolvableMatGroup( H );
[ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 0, 0, 79/138 ], [ 0, 1, 0, -275/828 ], [ 0, 0, 1, -197/414 ] ],
  [ [ 1, 0, -3, 2 ], [ 0, 1, 55/4, -55/8 ] ],
  [ [ 1, 4/15, 2/3, 1/6 ] ],
  [  ] ]

3.3 Triangularizable subgroups

gap> G := PolExamples(3);
<matrix group with 2 generators>

gap> GeneratorsOfGroup( G );
[ [ [ 73/10, -35/2, 42/5, 63/2 ],
    [ 27/20, -11/4, 9/5, 27/4 ],
    [ -3/5, 1, -4/5, -9 ],
    [ -11/20, 7/4, -2/5, 1/4 ] ],
  [ [ -42/5, 423/10, 27/5, 479/10 ],
    [ -23/10, 227/20, 13/10, 231/20 ],
    [ 14/5, -63/5, -4/5, -79/5 ],
    [ -1/10, 9/20, 1/10, 37/20 ] ] ]

gap> subgroups := SubgroupsUnipotentByAbelianByFinite( G );
rec( T := <matrix group with 2 generators>,
  U := <matrix group with 4 generators> )

gap> GeneratorsOfGroup( subgroups.T );
[ [ [ 73/10, -35/2, 42/5, 63/2 ],
    [ 27/20, -11/4, 9/5, 27/4 ],
    [ -3/5, 1, -4/5, -9 ],
    [ -11/20, 7/4, -2/5, 1/4 ] ],
  [ [ -42/5, 423/10, 27/5, 479/10 ],
    [ -23/10, 227/20, 13/10, 231/20 ],
    [ 14/5, -63/5, -4/5, -79/5 ],
    [ -1/10, 9/20, 1/10, 37/20 ] ] ]

# so G is triangularizable!
Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/chapInd.txt000644 000766 000024 00000001572 14775712156 016426 0ustar00mhornstaff000000 000000 Index CompositionSeriesAbelianMatGroup 2.2-4 CompositionSeriesTriangularizableMatGroup 2.2-5 HomogeneousSeriesAbelianMatGroup 2.2-2 HomogeneousSeriesTriangularizableMatGroup 2.2-3 ImageElm 2.1-3 ImagesRepresentative 2.1-3 ImagesSet 2.1-3 InfoPolenta 5.1-1 Installation 4.0 IsomorphismPcpGroup 2.1-2 IsPolycyclicGroup 2.1-6 IsSolvableGroup 2.1-4 IsTriangularizableMatGroup 2.1-5 License 0.0-1 Loading the Polenta package 4.2 PcpGroupByMatGroup 2.1-1 Polenta 1.0 PolExamples 2.4-1 Polycyclic 1.0 RadicalSeriesSolvableMatGroup 2.2-1 SubgroupsUnipotentByAbelianByFinite 2.3-1 ------------------------------------------------------- polenta-1.3.11/doc/chap4.html000644 000766 000024 00000012355 14775712162 016202 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 4: Installation
Goto Chapter: Top 1 2 3 4 5 Bib Ind

4 Installation

4.1 Installing this package

The Polenta package is part of the standard distribution of GAP and so normally there should be no need to install it separately. If by any chance it is not part of your GAP distribution, then the standard method is to unpack the package into the pkg directory of your GAP distribution. This will create a polenta subdirectory. For other non-standard options please see Chapter Reference: Installing a GAP Package of the GAP Reference Manual.

Note that the GAP-Packages Alnuth and Polycyclic are needed for this package. Normally they should be contained in your distribution. If not, they can be obtained at https://www.gap-system.org/Packages/packages.html.

4.2 Loading the Polenta package

If the Polenta package is not already loaded then you have to request it explicitly. This can be done via the LoadPackage (Reference: LoadPackage) command.

4.3 Running the test suite

Once the package is installed, it is possible to check the correct installation by running the test suite of the package.

    gap> ReadPackage( "Polenta", "tst/testall.g" );

For more details on Test Files see Section Reference: Test Files of the GAP Reference Manual.

If the test suite runs into an error, even though the packages Polycyclic and Alnuth and their depdendencies have been correctly installed, then please send a message to mhorn@rptu.de including the error message.

Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/nocolorprompt.css000644 000766 000024 00000000313 14775712162 017733 0ustar00mhornstaff000000 000000 /* colors for ColorPrompt like examples */ span.GAPprompt { color: #000000; font-weight: normal; } span.GAPbrkprompt { color: #000000; font-weight: normal; } span.GAPinput { color: #000000; } polenta-1.3.11/doc/lefttoc.css000644 000766 000024 00000000474 14775712162 016466 0ustar00mhornstaff000000 000000 /* leftmenu.css Frank Lübeck */ /* Change default CSS to show section menu on left side */ body { padding-left: 28%; } body.chap0 { padding-left: 2%; } div.ChapSects div.ContSect:hover div.ContSSBlock { left: 15%; } div.ChapSects { left: 1%; width: 25%; } polenta-1.3.11/doc/intro.xml000644 000766 000024 00000004774 14775712140 016174 0ustar00mhornstaff000000 000000 Introduction Polenta Polycyclic
The package This package provides functions for computation with matrix groups. Let G be a subgroup of GL(d,R) where the ring R is either equal to &QQ;,&ZZ; or a finite field \mathbb{F}_q. Then: We can test whether G is solvable. We can test whether G is polycyclic. If G is polycyclic, then we can determine a polycyclic presentation for G. A group G which is given by a polycyclic presentation can be largely investigated by algorithms implemented in the &GAP;-package Polycyclic . For example we can determine if G is torsion-free and calculate the torsion subgroup. Further we can compute the derived series and the Hirsch length of the group G. Also various methods for computations with subgroups, factor groups and extensions are available.

As a by-product, the &Polenta; package provides some functionality to compute certain module series for modules of solvable groups. For example, if G is a rational polycyclic matrix group, then we can compute the radical series of the natural &QQ;[G]-module &QQ;^d.

Polycyclic groups A group G is called polycyclic if it has a finite subnormal series with cyclic factors. It is a well-known fact that every polycyclic group is finitely presented by a so-called polycyclic presentation (see for example Chapter 9 in or Chapter 2 in ). In &GAP;, groups which are defined by polycyclic presentations are called polycyclically presented groups, abbreviated PcpGroups.

The overall idea of the algorithm implemented in this package was first introduced by Ostheimer in 1996 . In 2001 Eick presented a more detailed version . This package contains an implementation of Eick's algorithm. A description of this implementation together with some refinements and extensions can be found in and .

polenta-1.3.11/doc/chap2_mj.html000644 000766 000024 00000047450 14775712162 016672 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 2: Methods for matrix groups
Goto Chapter: Top 1 2 3 4 5 Bib Ind

2 Methods for matrix groups

2.1 Polycyclic presentations of matrix groups

Groups defined by polycyclic presentations are called PcpGroups in GAP. We refer to the Polycyclic manual [EN00] for further background.

Suppose that a collection \(X\) of matrices of \(GL(d,R)\) is given, where the ring \(R\) is either \(ℚ,ℤ\) or a finite field. Let \(G= \langle X \rangle\). If the group \(G\) is polycyclic, then the following functions determine a PcpGroup isomorphic to \(G\).

2.1-1 PcpGroupByMatGroup
‣ PcpGroupByMatGroup( G )( operation )

G is a subgroup of \(GL(d,R)\) where \(R=ℚ,ℤ \) or \(\mathbb{F}_q\). If G is polycyclic, then this function determines a PcpGroup isomorphic to G. If G is not polycyclic, then this function returns fail.

2.1-2 IsomorphismPcpGroup
‣ IsomorphismPcpGroup( G )( method )

G is a subgroup of \(GL(d,R)\) where \(R=ℚ,ℤ \) or \(\mathbb{F}_q\). If G is polycyclic, then this function determines an isomorphism onto a PcpGroup. If G is not polycyclic, then this function returns fail.

Note that the method IsomorphismPcpGroup, installed in this package, cannot be applied directly to a group given by the function AlmostCrystallographicGroup. Please use POL_AlmostCrystallographicGroup (with the same parameters as AlmostCrystallographicGroup) instead.

2.1-3 ImagesRepresentative
‣ ImagesRepresentative( map, elm )( method )
‣ ImageElm( map, elm )( method )
‣ ImagesSet( map, elms )( method )

Here map is an isomorphism from a polycyclic matrix group G onto a PcpGroup H calculated by IsomorphismPcpGroup (2.1-2). These methods can be used to compute with such an isomorphism. If the input elm is an element of G, then the function ImageElm can be used to compute the image of elm under map. If elm is not contained in G then the function ImageElm returns fail. The input pcpelm is an element of H.

2.1-4 IsSolvableGroup
‣ IsSolvableGroup( G )( method )

G is a subgroup of \(GL(d,R)\) where \(R=ℚ,ℤ \) or \(\mathbb{F}_q\). This function tests if G is solvable and returns true or false.

2.1-5 IsTriangularizableMatGroup
‣ IsTriangularizableMatGroup( G )( property )

G is a subgroup of \(GL(d,ℚ)\). This function tests if G is triangularizable (possibly over a finite field extension) and returns true or false.

2.1-6 IsPolycyclicGroup
‣ IsPolycyclicGroup( G )( method )

G is a subgroup of \(GL(d,R)\) where \(R=ℚ,ℤ \) or \(\mathbb{F}_q\). This function tests if G is polycyclic and returns true or false.

2.2 Module series

Let \(G\) be a finitely generated solvable subgroup of \(GL(d,ℚ)\). The vector space \(ℚ^d\) is a module for the algebra \(ℚ[G]\). The following functions provide the possibility to compute certain module series of \(ℚ^d\). Recall that the radical \(Rad_G(ℚ^d)\) is defined to be the intersection of maximal \(ℚ[G]\)-submodules of \(ℚ^d\). Also recall that the radical series

\[ 0=R_n < R_{n-1} < \dots < R_1 < R_0=ℚ^d \]

is defined by \(R_{i+1}:= Rad_G(R_i)\).

2.2-1 RadicalSeriesSolvableMatGroup
‣ RadicalSeriesSolvableMatGroup( G )( operation )

This function returns a radical series for the \(ℚ[G]\)-module \(ℚ^d\), where G is a solvable subgroup of \(GL(d,ℚ)\).

A radical series of \(ℚ^d\) can be refined to a homogeneous series.

2.2-2 HomogeneousSeriesAbelianMatGroup
‣ HomogeneousSeriesAbelianMatGroup( G )( function )

A module is said to be homogeneous if it is the direct sum of pairwise irreducible isomorphic submodules. A homogeneous series of a module is a submodule series such that the factors are homogeneous. This function returns a homogeneous series for the \(ℚ[G]\)-module \(ℚ^d\), where G is an abelian subgroup of \(GL(d,ℚ)\).

2.2-3 HomogeneousSeriesTriangularizableMatGroup
‣ HomogeneousSeriesTriangularizableMatGroup( G )( function )

A module is said to be homogeneous if it is the direct sum of pairwise irreducible isomorphic submodules. A homogeneous series of a module is a submodule series such that the factors are homogeneous. This function returns a homogeneous series for the \(ℚ[G]\)-module \(ℚ^d\), where G is a triangularizable subgroup of \(GL(d,ℚ)\).

A homogeneous series can be refined to a composition series.

2.2-4 CompositionSeriesAbelianMatGroup
‣ CompositionSeriesAbelianMatGroup( G )( function )

A composition series of a module is a submodule series such that the factors are irreducible. This function returns a composition series for the \(ℚ[G]\)-module \(ℚ^d\), where G is an abelian subgroup of \(GL(d,ℚ)\).

2.2-5 CompositionSeriesTriangularizableMatGroup
‣ CompositionSeriesTriangularizableMatGroup( G )( function )

A composition series of a module is a submodule series such that the factors are irreducible. This function returns a composition series for the \(ℚ[G]\)-module \(ℚ^d\), where G is a triangularizable subgroup of \(GL(d,ℚ)\).

2.3 Subgroups

2.3-1 SubgroupsUnipotentByAbelianByFinite
‣ SubgroupsUnipotentByAbelianByFinite( G )( operation )

G is a subgroup of \(GL(d,R)\) where \(R=ℚ\) or \(ℤ\). If G is polycyclic, then this function returns a record containing two normal subgroups \(T\) and \(U\) of \(G\). The group \(T\) is unipotent-by-abelian (and thus triangularizable) and of finite index in G. The group \(U\) is unipotent and is such that \(T/U\) is abelian. If G is not polycyclic, then the algorithm returns fail.

2.4 Examples

2.4-1 PolExamples
‣ PolExamples( l )( function )

Returns some examples for polycyclic rational matrix groups, where l is an integer between 1 and 24. These can be used to test the functions in this package. Some of the properties of the examples are summarised in the following table.

PolExamples      number generators      subgroup of      Hirsch length
          1                      3           GL(4,Z)                 6
          2                      2           GL(5,Z)                 6
          3                      2           GL(4,Q)                 4
          4                      2           GL(5,Q)                 6
          5                      9          GL(16,Z)                 3
          6                      6           GL(4,Z)                 3
          7                      6           GL(4,Z)                 3
          8                      7           GL(4,Z)                 3
          9                      5           GL(4,Q)                 3
         10                      4           GL(4,Q)                 3
         11                      5           GL(4,Q)                 3
         12                      5           GL(4,Q)                 3
         13                      5           GL(5,Q)                 4
         14                      6           GL(5,Q)                 4
         15                      6           GL(5,Q)                 4
         16                      5           GL(5,Q)                 4
         17                      5           GL(5,Q)                 4
         18                      5           GL(5,Q)                 4
         19                      5           GL(5,Q)                 4
         20                      7          GL(16,Z)                 3
         21                      5          GL(16,Q)                 3
         22                      4          GL(16,Q)                 3
         23                      5          GL(16,Q)                 3
         24                      5          GL(16,Q)                 3

Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/chap5.html000644 000766 000024 00000025655 14775712162 016212 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 5: Information Messages
Goto Chapter: Top 1 2 3 4 5 Bib Ind

5 Information Messages

It is possible to get informations about the status of the computation of the functions of Chapter 2 of this manual.

5.1 Info Class

5.1-1 InfoPolenta
‣ InfoPolenta( info class )

is the Info class of the Polenta package (for more details on the Info mechanism see Section Reference: Info Functions of the GAP Reference Manual). With the help of the function SetInfoLevel(InfoPolenta,level) you can change the info level of InfoPolenta.

5.2 Example

gap> SetInfoLevel( InfoPolenta, 1 );

gap> PcpGroupByMatGroup( PolExamples(11) );
#I  Determine a constructive polycyclic sequence
    for the input group ...
#I
#I  Chosen admissible prime: 3
#I
#I  Determine a constructive polycyclic sequence
    for the image under the p-congruence homomorphism ...
#I  finished.
#I  Finite image has relative orders [ 3, 2, 3, 3, 3 ].
#I
#I  Compute normal subgroup generators for the kernel
    of the p-congruence homomorphism ...
#I  finished.
#I
#I  Compute the radical series ...
#I  finished.
#I  The radical series has length 4.
#I
#I  Compute the composition series ...
#I  finished.
#I  The composition series has length 5.
#I
#I  Compute a constructive polycyclic sequence
    for the induced action of the kernel to the composition series ...
#I  finished.
#I  This polycyclic sequence has relative orders [  ].
#I
#I  Calculate normal subgroup generators for the
    unipotent part ...
#I  finished.
#I
#I  Determine a constructive polycyclic  sequence
    for the unipotent part ...
#I  finished.
#I  The unipotent part has relative orders
#I  [ 0, 0, 0 ].
#I
#I  ... computation of a constructive
    polycyclic sequence for the whole group finished.
#I
#I  Compute the relations of the polycyclic
    presentation of the group ...
#I  Compute power relations ...
#I  ... finished.
#I  Compute conjugation relations ...
#I  ... finished.
#I  Update polycyclic collector ...
#I  ... finished.
#I  finished.
#I
#I  Construct the polycyclic presented group ...
#I  finished.
#I
Pcp-group with orders [ 3, 2, 3, 3, 3, 0, 0, 0 ]


gap> SetInfoLevel( InfoPolenta, 2 );

gap> PcpGroupByMatGroup( PolExamples(11) );
#I  Determine a constructive polycyclic sequence
    for the input group ...
#I
#I  Chosen admissible prime: 3
#I
#I  Determine a constructive polycyclic sequence
    for the image under the p-congruence homomorphism ...
#I  finished.
#I  Finite image has relative orders [ 3, 2, 3, 3, 3 ].
#I
#I  Compute normal subgroup generators for the kernel
    of the p-congruence homomorphism ...
#I  finished.
#I  The normal subgroup generators are
#I  [ [ [ 1, -3/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 0, 0, 24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, 3, 15 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, 3, 9 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3/2, 3/2, 3/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3/2, 9/2, -69/2 ], [ 0, 1, 0, 9 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ]
    , [ [ 1, 0, 0, -24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -15 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3/2, -3/2, -9/2 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ]
     ],
  [ [ 1, -3, -3, -12 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, -3/2, -21 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3/2, 3/2, 9/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ] ]
#I
#I  Compute the radical series ...
#I  finished.
#I  The radical series has length 4.
#I  The radical series is
#I  [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 0, 1 ] ],
  [  ] ]
#I
#I  Compute the composition series ...
#I  finished.
#I  The composition series has length 5.
#I  The composition series is
#I  [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 0, 1 ] ], [  ] ]
#I
#I  Compute a constructive polycyclic sequence
    for the induced action of the kernel to the composition series ...
#I  finished.
#I  This polycyclic sequence has relative orders [  ].
#I
#I  Calculate normal subgroup generators for the
    unipotent part ...
#I  finished.
#I  The normal subgroup generators for the unipotent part are
#I  [ [ [ 1, -3/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 0, 0, 24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, 3, 15 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, 3, 9 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3/2, 3/2, 3/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3/2, 9/2, -69/2 ], [ 0, 1, 0, 9 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ]
    , [ [ 1, 0, 0, -24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -15 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3/2, -3/2, -9/2 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ]
     ],
  [ [ 1, -3, -3, -12 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, -3/2, -21 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3/2, 3/2, 9/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ] ]
#I
#I  Determine a constructive polycyclic  sequence
    for the unipotent part ...
#I  finished.
#I  The unipotent part has relative orders
#I  [ 0, 0, 0 ].
#I
#I  ... computation of a constructive
    polycyclic sequence for the whole group finished.
#I
#I  Compute the relations of the polycyclic
    presentation of the group ...
#I  Compute power relations ...
.....
#I  ... finished.
#I  Compute conjugation relations ...
..............................................
#I  ... finished.
#I  Update polycyclic collector ...
#I  ... finished.
#I  finished.
#I
#I  Construct the polycyclic presented group ...
#I  finished.
#I
Pcp-group with orders [ 3, 2, 3, 3, 3, 0, 0, 0 ]
Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/manual.lab000644 000766 000024 00000005674 14775712162 016260 0ustar00mhornstaff000000 000000 \GAPDocLabFile{polenta} \makelabel{polenta:Title page}{}{X7D2C85EC87DD46E5} \makelabel{polenta:Copyright}{}{X81488B807F2A1CF1} \makelabel{polenta:Acknowledgements}{}{X82A988D47DFAFCFA} \makelabel{polenta:Table of Contents}{}{X8537FEB07AF2BEC8} \makelabel{polenta:Introduction}{1}{X7DFB63A97E67C0A1} \makelabel{polenta:The package}{1.1}{X79DE59997FDCF767} \makelabel{polenta:Polycyclic groups}{1.2}{X86007B0083F60470} \makelabel{polenta:Methods for matrix groups}{2}{X829BA50B82FEC109} \makelabel{polenta:Polycyclic presentations of matrix groups}{2.1}{X826C51B3825A2789} \makelabel{polenta:Module series}{2.2}{X80D1E9E07DB87F97} \makelabel{polenta:Subgroups}{2.3}{X7BA181CA81D785BB} \makelabel{polenta:Examples}{2.4}{X7A489A5D79DA9E5C} \makelabel{polenta:An example application}{3}{X81CAD2F27B2066C4} \makelabel{polenta:Presentation for rational matrix groups}{3.1}{X7DAC33E37B977087} \makelabel{polenta:Modules series}{3.2}{X79CF643081B3FB26} \makelabel{polenta:Triangularizable subgroups}{3.3}{X7BA34CD28059D6CD} \makelabel{polenta:Installation}{4}{X8360C04082558A12} \makelabel{polenta:Installing this package}{4.1}{X81746D7285808409} \makelabel{polenta:Loading the Polenta package}{4.2}{X802ED64A87AA11DC} \makelabel{polenta:Running the test suite}{4.3}{X796DF52483B61C74} \makelabel{polenta:Information Messages}{5}{X85677704855596EB} \makelabel{polenta:Info Class}{5.1}{X7EBFC26F83EB9F72} \makelabel{polenta:Example}{5.2}{X85861B017AEEC50B} \makelabel{polenta:Bibliography}{Bib}{X7A6F98FD85F02BFE} \makelabel{polenta:References}{Bib}{X7A6F98FD85F02BFE} \makelabel{polenta:Index}{Ind}{X83A0356F839C696F} \makelabel{polenta:License}{}{X81488B807F2A1CF1} \makelabel{polenta:Polenta}{1}{X7DFB63A97E67C0A1} \makelabel{polenta:Polycyclic}{1}{X7DFB63A97E67C0A1} \makelabel{polenta:PcpGroupByMatGroup}{2.1.1}{X7A1BC4437FD92201} \makelabel{polenta:IsomorphismPcpGroup}{2.1.2}{X8771540F7A235763} \makelabel{polenta:ImagesRepresentative}{2.1.3}{X85ADB89B7C8DD7D0} \makelabel{polenta:ImageElm}{2.1.3}{X85ADB89B7C8DD7D0} \makelabel{polenta:ImagesSet}{2.1.3}{X85ADB89B7C8DD7D0} \makelabel{polenta:IsSolvableGroup}{2.1.4}{X809C78D5877D31DF} \makelabel{polenta:IsTriangularizableMatGroup}{2.1.5}{X7EE01C207C214C1F} \makelabel{polenta:IsPolycyclicGroup}{2.1.6}{X7D7456077D3D1B86} \makelabel{polenta:RadicalSeriesSolvableMatGroup}{2.2.1}{X84472FDC863322BD} \makelabel{polenta:HomogeneousSeriesAbelianMatGroup}{2.2.2}{X8524F992828B6A71} \makelabel{polenta:HomogeneousSeriesTriangularizableMatGroup}{2.2.3}{X87D9F67C7CBB1499} \makelabel{polenta:CompositionSeriesAbelianMatGroup}{2.2.4}{X86FB6E9B801A37D4} \makelabel{polenta:CompositionSeriesTriangularizableMatGroup}{2.2.5}{X78DE110C7E2A493C} \makelabel{polenta:SubgroupsUnipotentByAbelianByFinite}{2.3.1}{X79273B8581D15356} \makelabel{polenta:PolExamples}{2.4.1}{X7C7C3EFA7E49F932} \makelabel{polenta:Installation}{4}{X8360C04082558A12} \makelabel{polenta:Loading the Polenta package}{4.2}{X802ED64A87AA11DC} \makelabel{polenta:InfoPolenta}{5.1.1}{X809F2CFB87393CE0} polenta-1.3.11/doc/chapBib.txt000644 000766 000024 00000002062 14775712156 016403 0ustar00mhornstaff000000 000000 References [AE05] Assmann, B. and Eick, B., Computing polycyclic presentations for polycyclic rational matrix groups, J. Symbolic Comput., 40, 6 (2005), 1269--1284. [Ass03] Assmann, B., Polycyclic presentations for matrix groups, Diplomarbeit, TU Braunschweig (2003), (http://www.icm.tu-bs.de/ag_algebra/software/assmann). [Eic01] Eick, B., Algorithms for Polycyclic Groups, Habilitationsschrift, Gesamthochschule Kassel (2001). [EN00] Eick, B. and Nickel, W., Polycyclic (2000), (GAP package). [Ost96] Ostheimer, G., Algorithms for Polycyclic-by-finite groups, Ph.D. thesis, Rutgers University (1996). [Sim94] Sims, C. C., Computation with finitely presented groups, Cambridge University Press (1994).  polenta-1.3.11/doc/rainbow.js000644 000766 000024 00000005336 14775712162 016315 0ustar00mhornstaff000000 000000 function randchar(str) { var i = Math.floor(Math.random() * str.length); while (i == str.length) i = Math.floor(Math.random() * str.length); return str[i]; } hexdigits = "0123456789abcdef"; function randlight() { return randchar("cdef")+randchar(hexdigits)+ randchar("cdef")+randchar(hexdigits)+ randchar("cdef")+randchar(hexdigits) } function randdark() { return randchar("012345789")+randchar(hexdigits)+ randchar("012345789")+randchar(hexdigits)+ randchar("102345789")+randchar(hexdigits) } document.write('\n'); polenta-1.3.11/doc/Polenta.xml000644 000766 000024 00000000732 14775712156 016440 0ustar00mhornstaff000000 000000 ] > <#Include SYSTEM "title.xml"> <#Include SYSTEM "intro.xml"> <#Include SYSTEM "methods.xml"> <#Include SYSTEM "example.xml"> <#Include SYSTEM "install.xml"> <#Include SYSTEM "info.xml"> polenta-1.3.11/doc/manual.pdf000644 000766 000024 00000722416 14775712162 016273 0ustar00mhornstaff000000 000000 %PDF-1.5 % 89 0 obj << /Length 251 /Filter /FlateDecode >> stream xu?O@ | cT$&lJ&Q$ |g޳Lp*{t@J:CX@K!z^5yNjdb2P/uݷ;(P>0-)RckF%82aڲY Jѹ-=B0 ľ2`aJ)iSHmm֨F6:Vh`w~Sƌ&64][.Peߖc endstream endobj 98 0 obj << /Length 676 /Filter /FlateDecode >> stream xuTKo0 Wh*˖ة0[T[q:!-'r !!%~|}HK٬v{VKnOxJTȽL2kCսgIX4)/|b! d4ru Y@Oz<=sV95BH5,⌥ϽZK5w" yu.=PyL x(uRR^zw(/Rx ;3}{<;Y rWQgAިpc޽ QUF'=*F5u{9&0H*Fԏ!n:eUGþW2?!2bZr}}"O$`ō}NmQjj|@0I <nA#ȹxPg@q^OM2R5x2[cR*K(?I `rjˎ n!Gc2ҩ(=zZ>A σf_{մy~ +.Y"hTI! Oǩ>\ߣ2J@aj?Z""Dvj[eu,N޶t. crϙ𔊬]O42: =t ,OanݾCPɂ2Q1_ףЫ^/Mr endstream endobj 129 0 obj << /Length 802 /Filter /FlateDecode >> stream xo0+|=:RV&$Estk7lC"~L?At1!trr.1U(.8 )$"F9 NN OL&T.QE3$%XH ̉nF/!AftQBHpeH㠘guZA\bl-Gv## Ec] xp(@}FY&F\y9nf;.;]sz7g^,<Ͳt]zUFUKщ0)PdM@K9HUR󪁺EF64C6RF!|-|9Ļ9s]z~Bq T_-k:TcA_w1u7;IUw?۫EON}T}}1:|+ hqEp#Iq<0yH'i{4Y/At,7$uVibh{gQ> stream xXKoϯ[4oI f dA¨^I=^T((4rACdUXW_]ͻ>jY+~ZfYY#fMP[oX;jj>,RDjs E>5CYNۡjer{fJ[(ۍ'7%I},ߊ}䔮g9G)AL< K]&^JԸSöζ=OC>V:CWA}מ=AnEc)1P'ɮiI()@2 ,٩ F ?dP]i"|+,ɇr+LAe z)qG %=V,eFiuYx'ڮmv JRﻲ6! FVQ4hS],CJDq#i:;u> g>d8B~1᳐u37&܃DӖW]|uxx@]m9^2!.;D.ޏ3 l8"_'rX8L?3E] Ok'+u wEDVq |vYIlfD{,`.`.4@%Ȼ F]A*e¹~OpӋ_yx8G$(vvS_ld7Z-}X6^ MרsigZ <+WU5bΫ_TTSA #L^9c+ư@'+ .c¼v9|*]r]{>=-.h<ऋMšt2`! p'ϯ =uyFi1^ 46GOr.~Þ "uZYAvULʅ"O.^qZ|n-jYB1IO iۮ:oǹ@mAˍ(1.#wA7Er|9+ M$2b\B﹊g0ь)_3= #wq endstream endobj 161 0 obj << /Length 1861 /Filter /FlateDecode >> stream xY[6~ϯ Y/(44hZ,46m %$';~/E<m݇;l3ó8^_޽53T3%`b&Aj!fZ[T 7aMtʑҊ8xi‚lVMSU>o?DgЄc7qIo`"rE 1nga0k[TeZ?'D5#loj801-*tBazچߖn]# B# DB6XqS0lP\,[u Unol(2aHv|0Z9!xv_;o1dZk'v\! 0B1<U`6oC+e /+ÇX"֢C)< A6r~}B-mzpw»emawm~Oy∲>U`Xs>x?>B]YgTo ]pb*Wulh0"LGo8AX)4rI/gRæ!Bt.%9E' p37Bx ](ô物? ˇ%L}tH7NuC QBaKS0wCIB@#LMҙA,5S>`k/aĂicT!liIRBKs ޴(01WH FJE)!KRhbb0 蓣i`$9ǡ)_/hIZ(rݯ~ƧtعWO,y`j=N1D$}DHvvz=6; :BR=9!1bD Hx j #\'ڶǺl& Ev:/v>>LRD{J/0iC RiELRA?E*4WkH'.r1PuBtB]oH}<)K%J"wBʒ#w{ԔfdXwݪT`Af;9pR2F(6v]pw|c2/={3iby٪=.[~=C{xb?z|_ V>~:sS箎9Yb9Gg;C.͎ IFnȇvMX#P!>N"8.&xЁ$_PAFs;!碼.D\" l:zTA{HMO]YcGD1AV *h\Be4չyp,8nF{8L 0RPT2,/FA<G۞GA6g(L^ Ur'obo;uE>)CRW&TpM u]I</I*9/T+J4v*#J!]92-d5L;S?驮ﺏC!5PquH5A)Rhehܻ_ u3cR ru.)P ļ`ܿa ݋u0 endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 820 /Length 2170 /Filter /FlateDecode >> stream xڽZ]o:}c"@no[Hyp]51؁=*r۲ $$S3% 8Sd)ͨ8Hʛ*̀Hŀ+CAe9!V9g%7#ʄ2)K&*gQr8<=ʔ Y9@ ƣQ $h^M YE#J*^HVᏢ q*^rFIe J\J(}P XД29tϲa xX9PENX` >ɂ3Y\ĂBP'ʋ Ի$pq x ,zIND}:ppR$'O&sJ +Hџs*p;` 0H!n! " F-ݐ8(t,CGM D/"_l9)$vx֡dT"'l :UL%?9 '/ZTJJYĻRû''8Wg3U^rKo8OƘwra)fr";9_ͯӗk,rJ)p$˔QUAlWe]Hy.=p9h,.C1,3}^fx8=9Z(N+?vgb2E(n'zy3y Y97U9k-E{K,oclQ5X 65z0krlTX\A6^%?DK.S]_5uie[۳=[۳=Qmj{Tۣ(tZefl}2:.gm0l2NU&C/(2%h$kfw!z᭮vr 2{PhIy2q9NPlX>֬\P^3N2N1eRufظ GtQ!(r9i#c/$md59ȴ]!0c#Dv:5z2؁ EX$K䂏QG t",BpA&@B0$9L >ܻ68j) Cw28dFmJ=N2>h@.ky!iδG`GXbb^O$hGM(tvV1 ԩ?o ӻϝl#PZ孏Xw`EFK(,3`fWG*(%`BXaw-0r̨]컗ٵaY YYYYY Y ò IW^%x%d !% 0!>Dbm0e*6eS # Wa/d"4[68ڋ/Ut=FB endstream endobj 176 0 obj << /Length 2151 /Filter /FlateDecode >> stream xZKsDQ)08@%ADUd$vv5===_P~Wׯټ쵐+d[ј -JIVeMr^s"i|F ٙy՚3 5(MzswfECj<ʊñq 1/q+O H΢įr9ί[܃k 2ZSC Sҧ-N0cK0PH;oBH$@$BDig@qm P cD`/R"$4;C90fgbTis:$GD%Y4 zj]*^t 9A Qb.qToF%O@"e'7مp!IQ l6L;&bNFMH ʠǰCZL.ȻcPb8vx*_Kum9n=x4 WYYu7]qOVMZ7vYtTQ\Ҡ’[9)vHB>6٦:A2'vB$`XaQ3 өt96=tsʒ'U1ЏI>]@VKu8(~9R Cr:T!dzhBPgE>,tpg0p5۹9i eIw4$ %^HH$OXI^Jo(qgۏEFo[ mOp==4A4QALOJ_$>j6["`+S4]7!\bmLdșuhS O?:b{5sw7``xR['QߧURZ`$>iŽ=y|xP! ŽCl eؔUlҠϬ<ښFP[,2twfgͣStep I5{w'&\+c?o*II^%M;J]JvLiwIv݈BBqA("Sפpl9VqW\Fr` oӑdMZi[T8hf[NbfЏ9:g+;|מ:4?ȶpD\А!5$S!dO91"42rZ`6lnC :H1E"SYUDCFy$SMP{ޓh1ɾzgy@PH =n?G] 'P3.8n߃B>91|r~C#W'r>TўN*yA| ~9f Oz? ʒǒ?[~~hMFvNL'd J'M3\* (}gUagUw槦0>"ғScG6:M T?[|fxp^3FNɇ}7!#g~=^bRWS{:W 1:_mܶi86>MܗRh̠?;s endstream endobj 189 0 obj << /Length 1843 /Filter /FlateDecode >> stream xZo6_GY~`C[ن Zem[8R 貿~G(f l "u;*8Ipryzy򭐉BFa, 2$J•dN>~+YQ˟_*!l|F 53sx,b j'/8H ,@Z EC8iMv]^$c<-o"+YgWW6O_=+w5}ְ",(s!gl/,UF>a4aɻR ɺeIF<`yu0 _UED蛁#0ČF;*6-mf|ܽ]].UAF~PDO*[,Swi^}w*[W?u&_YJ-CgnL!xske|)e`T;׶]5| ^~qzmOy8AQe(lg|mE Ż%b W#@~39{-Y^ƑgpeUYt3xD* $9kgEip: C* '@wκ% i$&C\tK4Sz컘+bk~Sx@V SYU6RovrC@$)QՒ?>R:JJ\.Fb!lRn0RHOJ#%HCJN%uʂ Ǒ3* %HvFL5qKJ1EJ|*1-ZO/o]ަ8K`5fI|ӿ(ބ+)("n+W<Ca1c/h ㊙!;…2 % .R{ h;|60ERAN:$k3XCka &1P 4$o|=qŹH C0 Y<&ϯyn:Th lkLΟyOœmՀv;͞@Qsq:8)۝KAlHm>xD<sP\Pdh>3Ρ;BLDE~}o"'>@KQ:fH 'g,\eU:A#-LmT.ŅRPNЋo6;O_U.QlPMua1}D_f`>B19&hj11Pά?6Q xYjT΅]_͉ݯK 7\oډA=Fc&N1lUV0؂S@/6(](tm\p [HZ/,&|֞:B /  H, ʜa|Q > stream xڭMs8 MUP$>[563BB-`ֆ̿߶%*>P6z~ #?F7JCa<a9u%yx&],_7ΨcηNAֵm ᱱ"\RZ'45 (j*SypXtY͉Z눑PT@yFwcjyo߸BOcmiݾwAOiC}y*-07MFem:>p#'ӈh(s!_^7(ZsU|vW^ڟlY{lk0]XnOg^WMs~1kY'#=cG= kziAS}+pm`LԢT8$OAZ6]\1p®)ٶ Dzن74b/•tt^z|a]mz(7٩Oq;j5^b^]K\VczMe7 F_F8!Ն*PDcl5z3nqYֵ\ U}nICBw4iT3Nvt}$tqlYu.#$3"sR~A-jajn~/K8*KWwvn(NuSv̋ *^m|vuwċno_SkbNҜX,PFJ #P Zzes%Mb,nnK(la)Q_/K 3FD4q>+%ӀSs ״_xthpM^3hR6ũà)I ɏ\kR2pT(9  ڲȣq}0"-[Y ++AQko:3[+\dr3}ٲl v ߘճf.dIǩa|NQm.3U Z rJ DZ,n99pBle)a bt㼯qR6v6(W8.[Y ''n48>,וZ (*d/e+K@ †0W}ᲕpP#rDta,|-'MΙpR8|1Y0~R ,9;Js/\LN )ofK:R:J> stream xڽZ[o6~9/Z`ņe](|dgߑHږi{ %G|N 'EvH(FRR?%J"D"A1yHzU^ GT ?`dӭ#ʑҊDq2i,T5^de9d1op<- 6`[Jdig|ܐh.8ڋt2*w|HDx1+_V ޗΞ^Ob eH,^ܢCNR5 &ban0"|nvl,A6WlUMyl^ LqB)pc<q>/KrPiwkW&Ie-(U1&F++;}A͌D9-Uþ˓h"M@A']Hx&4CZAFGbtd[VPtd5a\d[gTYm߰%xLzwov+{g^!| cA08J nu=_nzkf!V^o |h 4v!`Ї4  IJwރ䏯E ca .4=|`$~@u3ӡgIzG583bnnI?@ N,|ĺ' I_f5m@bgőoGF/TJs(8g4HPR[9ݮ˦Fa4yKi N/PGi A*}Q \HXPl?UY>ϡOYT˷9PP̹ φTH+8_*hgs{{\U ]ްѮ -4C9.GVq-L ~fB uyj; wro|gG*M7@óA54B:gavh|Fk-CK$Za(pn} z̫e,mT<zw#u-eЋv+pplPCP2@DDsyYߞv#h c}8QlZD+:k/|Qp?_H?Q~w!Aj$d]hx6^%FԘ.Gԙ>Ior1g>WaG7ګk7^8H T:l@ טLhZ5*;ߪ|yZeG_|]_<F YWsu!ϠqvvM-7)`nܽ=C4bR!P!ᝩ23C!x);qa5eGyJ,els EѤO-[҆=AhB C~$@µO0PBIcI#)p*;GćŌ1DTt` Gx #4僢Kn 5|4kua.CGs M2YP<> MUE c> stream xڽZMoFWEwP q h؊*@\INR$%je+n}(7334g[3Ü]~839mv5O4pیG˔s$ :7gHf "kҽg{9Ώ+ͳgUZbӨ[$5m^XM~<,IٷsMn֋eVK !!˖Ӭ}Eh2ZJ)p ̮JFT{h.J1a4QHJ$I6PQ<^ j hl VHeShcMxY=ddvWL3WvjV#BYkЈSCrghiB_+?Kg&ul}|7u38!k)VWq&kjB亊iVXf8g2rr&hsD{ V/DH˱EHPp&D8&{ V/DHkՉlHjIs!m,9GWhCd:a+b)=H!2j5{@Y1`^f&iC9J1+ÙUĬ JQ=N(A+?Ehdǧ8Y)J%HGޙVIZ+cC"+2b- h]0sQvڿidu>FGrFu\20e{|Q,.Vě ڝht:fxIP:A;uNWIW)fx!}PaS̀uW֕A$WU@KANEp}*nPVlϟqThŬVKG*iv?z *RTHsD΅1h;@pz!t%(2i+6x B(KưB4#./\ @ȁ% RZm󣲻oqaƮ{ $*MB ;8QXWz74Z<:-F rV|(9-Tȶ N)l ] ZW4-G+皒DwLv_@(QAݻnOtc@eמJqhQv%! +mGtеV>h[@8+wFkWo/$P `CdjPQ0ٺkҿö5B U`͞fowz9QALlHvӱe,֋u?Gk Y"VCP]# <՟?b]9+'oK,D$ ~9gJj^;z@jOn"ur;hBS$o΋_x숖mhMԆF$}': W>>y6* ]|\+;]d)Z<'@U&EY= RCdj]LL_5꓿0hL'_ꍋF<3!TLhdێ&sHb^'#Zx%0okw$X5K endstream endobj 224 0 obj << /Length 894 /Filter /FlateDecode >> stream xڽWKO1W%H]>T"qpJ9,H!!_6Yz@vfy 6b:GN|Yֿf:.dwY ftOcme9X^`K $ k#Mgp.=;a+6Mi{@)H|+s,2\h=8Pb7*Еo>SK2+x9Pv8Πc "^wʱu1kc5Ƒ)lI_!9'B)[9U,C {aX͍nDp:0ql>b?zkrd1!6@Ї` A&h>u:͏ϦقrdN(bS`P:6Fk3TBcU0d}l Vyχ%_tḾ~0^ )_ y7^@A+ +Y9VuJ^P àbHOA ΉW-%-"m~ۑGu7S}Ni% XE)+_0aeQ%7^NR0\Z%/m\r@} l4Zc$C [t`JvIZDR'zj9˅BmNX%ZVpnTĥ#`YL&!Y#4ю˜pcckE3CYM*25Z窀S UXcuh*}l0Ҹ6:< L?c ;^8'|7 lpvckhj.--_:{wق֒Kmh endstream endobj 229 0 obj << /Length 1797 /Filter /FlateDecode >> stream xڭX]o6}ϯI ?E]t]tiަ}PljK$7ͿC^J; $E{hl|$,&Llƌ2IfSHлvzn8n맏Qf6 R,}Ww}ە}$- ͔dg,}/P|^ 7dx:/Ɲ`25i߆շL>]$ VHa%iŃ KiE P=Gz۸]ۺzXHCM\2QV~uҰȆE6v`>V]渋ܰk@sˌR(f IM;QC8AifRX*^=o`B&W۲^Bbc1 1ƒ^ \1]?Uct}uq4J ɤ(T:G+7GQ~=hL2*z >CojD/!>׺Uߴ$90BkY~fLy-8x-2d EOU@ Z|lyC@&gҨyXsTKf/aP~k|9,b0KaװLQ)!9(tseCM3fG ffEYf(r!!c_ &D $C)[_PER&h[M*4J% 2;sQCXy E" ?4:&0QUΏL'yB.lG}}0bXi}Ts}֏Wϫ]hb:;6zk~N G /?`ukq6sXINۿ Ï}R&zb4Sմ"0P#?QQxs[TЗ'E^O~3Ckۧ'MyXv]i7w>~Pqٱm߽H$ca,?h $o4E,5}F}ff0)u|^u˕sqhXi!^<\DƀACY RФc.&,zt]YggՏT;G$5, m_BkP ӏ ocĽ1zTaQ)Ru (Gk[ ௥oj5 …ٞ8yHgQ{? 6^U^$̯;]UN_s!A"BN#Dže΅_| :Zx\ F,M[=GOa# z;\לh| fmwֹ,c9[?;41 endstream endobj 241 0 obj << /Length 1762 /Filter /FlateDecode >> stream xڽY[o6~ϯ%vۂ+b˶0*wIɒ$uEa<\`߷WgKpJ*Z&J@+F72$u69W4TWQBƏ/p޲ŕeYRȳʩxb Br0+"1Sd/dvA޸jFHZ p8?&"y=vWm}$``VXr wĔGCF0=eCu҅ ۧ/Γt Sq~ (ag"#h4X5b'X`:i_O'Kr#/\F߈1UaT}Ht ݛlhAZY@_\|:`JsCЖ/[}L$ Ӻ6O=Q?èC)RyޣH>C)%SX j> stream xڽZKoFWE;(C8Hi\XJBQq;IX4WZA@\~߼vf4G48yw;y{td3E7p#qLFnXy_~~{#M(q5%9m7zЄ|0I#S#Td8'R(YMi4w#Jn +-ZdyY+6%;4G(39(j0aP'{LnI^]+.*~"4?tWqQH/x\*7O$*`*F&J? M j peV4X\F_خye\P͋j*0`aIL s%:i=2-o<鬾Xr6 !F֜hFZnYf(\Y&J^=~{+Y1-t3bYFMIy 30T^3]Z;. ˼Z4mo̘6MQ DB|ϼDTm)'g <-6Yy_}rck9Q֜g~0m UAXJ8cn\MMso蘽R1!,fy/AKkIŝ囪&Ja],d%MINS  pQ I Dw gl dtrQ&Md*z/_4|xTBMA1Ø 7 ̄uwj*bUnƭݯ4*n֡؟t riB*]GAM "TeJ(K+}L('G Y`AI $ԫ=ٺҼju\V#"4rD0ՂP30# ^%1j6j}VigJnDK ȧE0s*KhD^!bZ0zfpvy@Ls< L \SEȉx8\vI1ykaA(#>mi{vO_?Yv ㈐#İaa2T2upؗ*?d6) seay9B]F#X?܇!&۞ ӱPJ+G6lUN (;Nw::f{Ѳ7^(VUiY\]?FLJH (>5TxL<$'4LۆCQfG0JAvd}Ֆ0Qi 4$auq?ֳJ_>|J2Mn֝7PUJHY9^N$*S{ffa|F =kԜ&M-f zMz\ܨYc|cloHiHèRB9?a`&VB6P_A%1h! "~S%Y_?3Ǭ>8}HyH7;, M: q i!`D{KFe]TΣ0(I ZxSYv>Fw;V'`5~ly %-&,i.!P`)i"!|Cλ_Aq9Tx^!cC+_\t? endstream endobj 255 0 obj << /Length 1789 /Filter /FlateDecode >> stream x[KoF Wbfޏآ{j܂ #+;-ߗMKI"CrF2r2 gGPZeId7vz˻Ϥ(b%iϒ.Do.>_H<G6Jq*./nD6k3:gNG6[d\^k)5|'*j~Ka|bu)G*;TzٖOmW}q22]o3䟟4q7hO @g e@L벂ӶP@@v(B/T?&U;8teBmGc8_oUelYl6ŧEe̿uL7L8Ǥj;.s7_{JxI† ac9y+hOY~|q<gz,>ʆKFvp_<;!aA` J&A|@$Peh>T'e\ꋷuHwu4QIl\V/cR1E |XKWr9YT<}*/'u$3/W 6BE$Ѻ$aFjF\ߟSmHז1mP`S@8eM pZ}wRd[XX'l8l۽j_c}Z+\, ZW=frH`4y.!gbyCL U$eƜfSjvl(Z% ڀz[C4P-ub}ދv.guq5ٕ %C̎9bs%_xP.!_5{g,{A1I]nh pv])FW.W}7,3H%.o W'A{ޜDV{e>q{48 &Y|-쳩&&|+{|197٬QFG~+1%_iA!_yz6kxT"ͽ1XßYovSPcy>J|]%haPcSGK)M9?UqߘJ,3Gr6۱Ґ.I 閜R&+\ViLyF\uOUT3V%|(NuItdYWǤjk7Dm@5 )ߚصDi9 ѬfHKwݟ^q룋'k!?|Ĕ4epaT@䛊:TM+b):н{g*/ߨTѬ6ŭ` endstream endobj 259 0 obj << /Length 1688 /Filter /FlateDecode >> stream x[KoFWE>R4uOL*dIHXk E|*\}!GWU}ƈkJ4u]>$E&If^)0NeͭL!{|ޭ_?k+U!:vFE@Xu3}R>Ҁ5{"_v1-qnb/WtQ7v]zȗy1-WVTt?1!"6e/O{}kzUU8b_2cF7" }82i1C͠Hg->ArW MU1NEQz(*M覂SD_(gUwJVӯWu~ԭD! `pրa=ϴXiQRj˴w&b }DD;3JKCQ]טuղhw,'xgFy4%D8fvL1=l(l,oȿBzTr~sX?6yLL B[c[s8= VG6{DK.InApG:P䓮IF3.W}SoQgc`Ώ"+Lx[ktAx/i'|/̳[ "z1 43⹬Qލy61A 9J$ks鹬Qe9RelLY4y6ozA t`h%J`kvn-hixE(QmӤ&8 9JחoHX{ F$r}o WlxK  F0&80N&Ϟf&$f[ ׼̋1zVMYlgKbZ|}-ݷ&7m"h V$)FGlY?Ha* 6$:+ҿLo IH Jڮ3юsM;~ևE6kƫ./6=ٖ:F\9QQhP6|Ir:H7 L"0C(OjK"9erVOm.ZV;b*/=qo2ETM7a4,j̾ZiCRӲAPp 6 m-=Oj6NU!%m4@?}RUD7=߲wgNMKOZK\yϺ7uC􀂃5>F '悌, s$z/܏m$) &2 N5O-gwK,WQGmUsk P𻓿]b׃m"Eii4eCopiI':E[,Y٤0ڱ X$%h)4bQX CVZ͠HDIy>edwIav~!@(EB{zA˓tiJ)e!LvS C2}mfIԔؤl|'5 .Б΀l>֓/zG:{i긠;6;>:J`ÙQaI oc(a\ endstream endobj 272 0 obj << /Length 921 /Filter /FlateDecode >> stream xڽVn8}W*WQ[ҦY@H]!-LDu1$^}G$Xbl23$93cnH{YcHQoT%^(BE6z4[S4BHL[#(ΝxX8{"M콧@)0m]qQI\l`ؽwrћ2[ng_fħ&ZejS4qcˢvK۲n_uqfyTQc){JZ};-ΟRD%ANt=1EMLBr|%E_SlrXk`w `CY$!;v0GJU7]xx!iBHj8Js0,i8_ׄ??=Ê L-/YKVYn<zkYئ}h9U񡨓URh.9a xfz8p7lk18'RڝxQWgůE c^J+BRad/HdBOu8Ҳ.H~FgsWWv;`8oveCf@de G? C), t0k6ԗ6%d % ,BLː_!Eptk8-mg/uLZZhAR afft2L䘮i|6N׾ 7@N> stream xY[o9~ϯ#<౏}|YUH]] QVݪZt(m%S~g&@.p.x<͞Q6+ ^&(,ڨlYhBk3YYe7yU5bR` Oq'CNRӯ@;ȅ kC`QLt,\s!ɋbse: ypʰAa &qL~QُEL#f[-X B5 9uncoaB>X a|8:6_l; Zs q( ;6n;b)d v>iP{r{MޜL kڈ!N=SsMAP-djq4" M:U+^}imv|P=̮Y~^VA!F$˝_NGOqm%oӓvtLy{i_A_OM}'k>"t7w!ﲝu$,]{/:-:{LgN-nD;EOh/V]= Wm;i=lwˀ:F$;m=Wկ7<Nz!1U NŔI8`Fpt!qt>[%~:u#8kA C9Nft'oo뷳a5k`jI]]Lo'wC=z\)N.ޔ'_kc%X"<:4\[X l!gAw>m?dy3+l~so$> stream x͖Oo0>&pm}\$JQq)jgHClCDx<]ܡv `.!1-x[>v|n. $SXC$4"L≅+2Qŏ^Ȓ}Tpv*9DJ|*cBмg˦hzZRG3#/ yH!vl(\[.Hiy36d,[q`\F@2ih萕[ߗʮprX,n$ŰO2ͤNz.+7*؆L px J6Eh*&L,Hg ǵ!W`QmcEK?|j@5w#~o@Z7 DrB$s*3U) օJ Uia`wG-. b2~чۆq01Gʿ(oþu{9*+Yfryu*0Twn1|zڌX#]ל{4=w[*=?LN[r"hvvVMYfӤP%rz/ڷ A&kTUm%6pԳ7 endstream endobj 319 0 obj << /Length1 1477 /Length2 6294 /Length3 0 /Length 7297 /Filter /FlateDecode >> stream xڍwT6 M"H zB{.R $$;HM"һ4Jt"MPzzZ߷Vg=白ް{# AXAN>^@^SSxA ~bVV}7NjEa'`ȣ` ScDM@O',P @(1hNP41<鎂a`>u``'&cuh v!aP?BKa0H1 ՕEl80@\U-#OiĬ};Aaq,:.O P;@OU:&k&p_x_9r[[#`'w-h+ib0v@#`0l%J Pm!1h^4FU1+:AP' *? j=wwNl`N2 O@'S"7f @"DPgx;wckD"lPo C@S"@`DXj{? 0a]}dUo p)_F99G/E : W9 3+](J7 _|gr*H驃/;oc;0}&; NM5]M(񿭪0vdl ah%-߸9hˆ2k8AcFcGWk(v5r5}B0 v'6xaun 5{l(F v_ap߀67D;vB@W[ WjKc:^5P75Z<о2\ޕgeP'1?`9!Sqb1N/3cJXiOܾUK8kӞrs!Қ-Uᵱx#d8/ Q8#ۈ!zd^Uwe.RzԤV^A jE`գ"OWKaZi%ZN\{{f(:E|g P(0((3yygvf2&K)5}#C^K۔sYSeBՌWZދ>jԊHyWC2E3nGD&Go (#bWQaL/u0@pr^ t!p]"O7=7qZjG GZm_vJMr_jLUt N4pRxpi\X =]LX֖!桚fOM'uFLHK!uYx<NTgx4W+|O6)$ƽtBZ9̄8#(=nwtF];]V+|Q lAЏG6 FX-YSEx:rV}Μ=Gu)',z u]FňCҡ ;]5Fw4goy`V hw`sF:Q,r]OwqJ t5}yb@#9ksƠO(`NI+yG hr䫧T8e sW2P}ȭ 0 bbX2Cߩ{$K 7SHmf}'񥵡*]90Jq&0[of / ]J0RߺOٙsSQ2lJUsWs3W#Eț8_Ny}apS5-zw +~oжa9B60.\..a[5nn.T޾J<,ӭxtt0Uݷ;2$ZtoF ORf.e9-mGBt+* 4`GZ ȈBٔL#_ :9)BKij/ A1bMh4w( h(6 +e+: 0RtR3ȯg^IՖ,~~{)1xoǝm1-/c ӗ!* =N#P˟ 3 A/3f@Y*G߬V)[q>`^(x굍!%_@u\ӧJ )h$u\_j_<^,K Gұ5ݽwKW4a;7oQt d=SaCd-ewk7^R|ox)xqg$5UƤvϴ4kTGj&q>6xIܱ;q|ŠǍ/\:doBvs݁IZm3ގA QkGN}jјi|#m[wd*U[`yɁ#L|a{|#BF^#{K߽j17 ASmj>M&-5.9H'TQq!W*cZjzJ~8!zY˷Vi8ٍ84ÌOR,䊷07 e"Bn ); ?4"et+';TNMdLf_EoO6E|9E1)+9:PќUO0’/WL *V/GsL52Td#OJkg̞/d_.WyCozېՕ_?{T1+3g'꧶'m,P"17QmQHH˞8zL|͸iCK0WԂo:L]O'\p7^cvytǼ8@ƶ0yXrΓ羗jVb%z7VE uc`Es<ⱬcfξ5L Ħ1*7vzOR +D0hi*^ċ2s!ǠPBg)\ O/,Bj8%(G;sy%yX ~\>UWt [oưo%o)Kv/KoXˠ)_mj=ض/[R֟ixpWwmP·Z}Fҿ:FN|^;[cMf.B.q(XiY͸mW F=8ˀfrI3eOdDԇ31~oǵ+f>K2{)Fy\Y‘ϛe$A͡j~eE15A\Rz%ш{)Sx~.ḍ쯻 ăy#[}mZ.k̟"zKY=MzGaO~UX~TUX6;T tmQl՘xO/2y~h.z-V1Yzjxt79kI)5L;Nd9;SeKk`&:s2걃=y/]Z#/(pSOgdGVxb-f*A͕ՕԔ8A s7x0|џwݱV33'}br}1|\VjY铵O7ģ,P>ؿ*ea@O5aWmRN>ЋIѽI˒Y'{pc";@ -_;b[9R),-G Ic^'!@~Ӻn6?a1wvܾ^{z(yp Oܖy˝1Bd흪dw@ahY }q[[:,]郛!S/6:Mʓ㬟7bo$5aZ?1ld_ptinpfH&QHGb!gn2+ґ~{ OV;4} 90r ?NSf/pOzB2!x}yGo ?elmr^wuO(J٥r9kԒaˤ] 7fZPLPt/yT-|.%g/OV٪rQ,D,&"nH//Jk8q-sPWG$o D;1H4)MCx^nlSV\PpMd75^]JD*ff (ZSgKu[~Cmg.n=ÍHhwʮa F$׺]Z>Rp_u;w %q A?}ڽv_QPQe;VMݹg%4k#y-AuUi?tFo,fzp\^'Nq1VK1K?N|=ܺnw8ui,k8i"4@MFْwqc17ELkV' ׈iC%o_W~C \?XY")HkOCuoU)"2\J hfwB!J͕toďbS2+lD[t%Xֻ)ɢ9EoͿ& Z6 '$z]!aQŃ8e+ٛvB7e# ʰ42$ mKBc$pp>Q8֑اsAk6_ %COT+ p#gwnE7} ?ˍ=Sˆx8`? 'K4Ғl#^]@ J+Z~4 /ce`Ӭw5K :Y/"uK| `xA(` 8쵸kWK㙴;BǬńgHRxʭ5ȯW_顠͸8p,2דlȊ zBN~?E|[uejmP= ľGQ>X7Qd֟]B;藴 6v5Č;RcKy5Ȱ\7eMD^e{}`@zcyL׊ul Y盲&.|sۇ#H;ǮB}^"v( vNu2IB)HVP]N*w:r&9,J]gyH0^6ʼ0`.ПZs H(i)=Ytsbv)zf35w"G)kޱIiA^LT-V.]h=S۵] ;gXB.'C㯩$!a vYfl/gޓk筳< ' VAʁ{L}B#T=T,doЍ}QIRHcJ LC'y\-Wg Q<|Bzҋ._^aS:],.$)y w50s(W-'NaGNq䱉[A'[HOg҈cُ!w:7 3IY5<XyVK b|\jEܖ ~64RrCsu$r)'+!07_&<:yxjZJkG8>M [lU@׍Ua*Ml~ڤnfea.-R#V7YaG4W}OAjVrƙ9;yх'\e\4x_o'Ou6'YL]s*ԍ12>3hƳlX{S *=W+ @L7l=igpvrߒ9=Oi /^)WQwI}}I{>yRFY8Bj.nGXmaąt\dc!~;BMGO5A+xQ1j`)BP3eҦ |81ALi.A 7(h\ք>uXc[zShD"FFꫵ]k  6Axk_R[>|kyS"2`rz^q)IwkKŷ?M gb7TƫniN)x?q ͞ ~%F9qA5e&VO7 endstream endobj 321 0 obj << /Length1 1478 /Length2 6403 /Length3 0 /Length 7390 /Filter /FlateDecode >> stream xڍtT>H( R3tww30 /!ҭ04ҡtҠt|ck}ߚ~sγgVc~E'D GRe]# B&P &0 =8(#!`S0~8@  @bR q)  J@JTP'@ xs(#PW昿nGHRRW8@ :]09 #?Rp˸PR>>>`7OEE 7 0@L` #Q>`$`PGw ƚ:}wo>@J'g"(W0A.g( W@`OG0{0W`!!#~Rs˪p'e$Y  q\>#|6PON^pDS "7AD@0: Loe1 g H#{C($(? @'# q‰C1GB}V@@߿V6y9!0ꯠ!o))!|"@()2q"i ?eG&]- B5PRS, 5/엙1ݠ0?z0]!Vro& E _TB (Gj21@xB>+~Lkˆ-LJ#_&fry*sĄD`$Gi2f' af KA8 `H`LJi bQ#e c? uyy F_/ q$G8J? o WnW)Iv! 4 l?"͸5#cm]SocXˬ`֯E:jҢq8DN։吴Y+ySŪiƊ.VO]&a +c^z<9KBlu<YKlhoDkbϳ}s %wbWϲX'uh+n_. asxLq;kYf2!e߈@X55_6ūAśZxSZXZ(4g{8S ⻡f-ccwc?TpaS}oX~0XxAB2dL&3XHz-mt2cuo>'|kau۷)4$v}9xVϛ%| dD@cL'XdbuAHm/W4Se, }Z֦%W4SJ0Wb Z7y;k3 kDASKSԠߍn2h =}Egg5`a}aN9ﰜSbG$i0dkYm8{^X1x30Ƃ{ȟ޴mv?U=Jwx=+J_I'[*+i^qw_z %ub9Qղٍdj lٺ/{_CIa5C; Y /C/ޝ)C9=`ު!bDCB/N= 5;/.Wnվf~?oeD⵻A+Y&SdbdgRI/vjxr2vR{\$5P/j4V-vΈt~˷dX7>da+l/NWoηJo],kz|2JRZ=LY>kbSoaZ! civX0;iېp㱁xO(l.Rf-޳­ϑjXH3l"8D|(a$kB滔>s][l)?S|e3 }fm=,Ԅf?~VpdkViaN^[<(u| Y~crX1HZ{SĄ'jD ~6#oJ_$dzO7jbԞ=&[8)V][E?v>1 шȡF`~Q%=T4U&ܘa}RL4~T`ǘȯ09v.A>Ae{@ o2z.MXebjE[U_7lIB']7g/JxͲ#R{;9z=bqf:ATf4>|Dz\4(.UpuTQkJR꫐󇒚ߓ3p?_RNPzrG֖v{Z37[- 7v̐1qO)nhEk .]i`by3te:/E^˧c}::n? Vu2S]~~Uh+X[QՎ{I>pb1"-={CwRAncD^/m3AC1=]&==$t7^'=3Ƌai>;hSsSzv4D:%@ź1רصaKLCi߻OXYnopԢ >_d0!C}m7,fVۄ2OqDͷsդoqqQBc+ [54FțHm+LҮ][+d4.68שԸ&L3ck7 #WJ=Ē$R6z'8lM~}ueE>V]ok|iV`,ERuwT-1Mk# ^3rc$ihF& wM{V2q "~,}Q}-A´0̇lυ2ǨԢӃuѮ$2:$bmue@kUA:cUƔ1R!1m» {$BVj&/2g028nMӅ\B5? u+#bZʮY">?74Eax켌i#yG# mY%cQȓw,w.&_Vl; g+|ߜlP%/GR"K- e #9i/4 F?`[]dh0槟3/4^5/SDsut̞ѾS0o-g޶\1T+mRjYt;&Ui9]W '+wb;#{|UqPv_h6.~/V IRwu:4P4lתjs^&\?u?F,RnѕPKJ Hħ>ÑGj؀ϣ}_O*F!|=]/b:t9M9hN64c'˅i^qKGcJnhT [Q5fB<b]iIM3A9]쁱Â5c{,m_^s[D.7[*\xcܒPrDC3_U/q_j;v4?Ī7|<l佷X=p7m0e_}2)wb\;ǦZ+-iChg@fi/snNN0cl'2*_ wtGrc M.FRF83T7.Ney,Ay RpJR9l0Grԥ +Vv4I@opw:-e.ҝgρʥX{օX6&ǝCZUFe> stream xڍxT6"]z" K R W#H/һR7R _xZ߷Vy=癝1Ƀ`8 '/( P20 㱱BPv<6cIC lDٔl(x$%‚n%x xlpo7ߏN @HBB;@Z6H3jG `BH|DH xzz8#n2\OF< 6?   @ @@`7jw&@ pBB W 췳 wvyC`; QGz!y60/ Gx@6(m*zTC .H?U0cV`+?%:wo?u=a 0ݯ2@.F0;X]e J A.o3_ UbF}"l<;?  C`x2Z 'דJa 8 o +j+)_ ', EkE){36\0B*(*D _QWwF*Po/8C(#QSG쿩&FW ;7AM<h>C*/0H:F uȯ%(_jȀN[o AMXT `f㍇5j% BM%[~rj~5V F݆v_?b5oP #~ 5 @Pסt|ưֻ#E/|4T]A# Ss~tG^O#є7 3Q$_19M{D_}.Bl?8JΉ萱y]͘YבfOH3 Ս&nПC.:bh{oe.g?]PF:1sH Ebfbyj Ms8]k3퉃"ڊAt6EzVO譶 P$E9֦*Հ·3Ԉ@{1(X]˷Z3Ҳ 3Mg!"'/c-R?TӅ2ؙ,]?JѲfv\we?Ҕ)vc'z@1`ڙ߷ج.zĘ[Y Y1ϋ mRz"'0o,BT`H2ok&&8CLHtTjJltpt@g˓w6|ǴLu;Ʊz`] Ҵp`6t,>(|q߶G>FtOlZe|2Gf򠷓#uKvXUr%Z/ڦa"|FǭgԮ;ԃ ˝F/.?*\D a"ZJL6 𶠲K[IT]{? <^-VyCWd壀;oyxwѳm W:`VHk-$f񳣅ǚ7›V­[jxBT^4C{4~p+m&,唓)P&[ʧ$BUlTOD@ /-%=8v Cz ,={52@Es{HiFt3lS'i11.y=ZJ6sEoz6"TʠwSNzaTaM#Lz7ꙗW'( ӗ=d{SRrGVdxC6K+T~oJ͢?WL](Sr!!t"n˫_ZWgz.fԇ|8"!^? t|5aGcf5o' Z,0hg'>Z{rd9#qwTK~_v=م{.T܃pJzYWῩJ,W$jy,e][8[$"U+JP|4an*~UKS]߈IK%G[ #{sWovޫVf^Y&h]9Bh>ш~#MuRnT W~J }&78]%f񅝙`yfO'$[͈Vз \Y̆mN׫'): X wR- EO2I =`˙8ՙu,aSdXc|SCr3i< wnʁ6.͆h_+vhE[Cmʳ,vdgyOl b[HR,z]Cf= ܷ tnbo럤tly,0J8{Q6%yH* oir&%C->d*ʲ?{2ԥŎ~nn|5|aQ 0]?kb7] HX͓kھBM‡oc#pElMm+gMy\߰]x旁fީcwȬFcnIn8r&&ˑeCED ud!f!a}N&foU(ק:/br.NX / _8ŌBC3}j-%K_`",(/E$ys}Bk5pVbî6?~v~EP #W31K ܇1n 5Fd^mXcK+n(K.5$d[dуltTa vt>q~ְ#73aYs|]K%Hٍyɱ$QJpWU+lXEC\u/ocPgzDut{vY_K>%s1ػs%Q 6%1}8W@nuD0 B w& |ޚsv99zoH :ޓ)УV`4>{z,\F(BPYcE$*rQrd?] W!sg+@tڛթьE GBtV狝mv`ҿp+*5O#~GcݏX U| ~{)eT+]*c)ں`ivTwG:+=q-.>!tj;}x)c9uXnJIhr2msl"#mw~/HHk'yu.*K&ϷfiFX,Y2n8Dk5{ߣ.)Z۽  au`ӣgGFA.V]zK߶8JUcfqh <.]T: ־ i #`u5aY|Ƚkh̩[}q:-v;k9L](ϹYcͶ[AG\ܡǘ# ȎXj=V䩚u{Ey9rj^G>V%kirڏ9{ 9 Hm,,}/mnq"z搛K'MM -qw$0 L=TP|…Qu3NJ)n*V^c}({S'm&'zOC]wDJDGDnsu*ߌ.uY5y*;ͺd8]f[RN3uoGRֳ۟'q$^X7ScJnhWm Է4ʢ!{R>MMiĘV{*\wME=gp@!|@UcAסvy ^d"α!6;PBs9:n?Zbc/<- $v+9? k8X> X6њY-:.iB#ENFi!UjJϯ.%lX ׌<{nd*$Iz4罛$ц7сnZHop [Ż], :tnuP;O.5C tőH"swU) KSR\,RW+i=#v?iHRa3B?YЛ a]= ?X`q:R!KC6_' a_--GMti# c^UwQMf9#xCl?qS\8N<,|IFHm"2ê,9 ۀw'J9Q7}%oJ۷mi=<G]"j ѹ1GqgR z:"߻ԇ6[`Zc`}f'A'WI'vpho#]nܛJ=GSci<HZ󉜺H?uشՃWw % X!Oi[l7zOU(Eoy? Hإ7'/DMm%~, ώ)f4H)Nk?`%=E;C hlnE,`:k}"6I̻:`g4cjڋa鲭OO6 (K5ݭP^(ehfUOS]J)pJHg;"gG6quݷ&)uImY+SRLӸQ+YL]2l)EͳJ O܏]% a*-٘XBe1=~]2-,ѣYTӍhc*B^ DJ'V A,/my[,@k>rylV$V`yai/iaWb9cl?FH.%GNt }|߶_KWMjv[Vv)WK*c}k)Zg a? fe T/-g_Psf6ķ] 4ya9TL1iffHe{>U|;V椅,%fB$5;4tȵ#?xZ/C$zӷX(}rAC^Z-mkڳZ(ic9 ۃx5p?Sm J=lM4/1pc4ѢT̐Pdn=!:7ߦph:S*دV&IS̨3/ʋ†TSrdG3 ,l ۯ S cM҆ӴYvUw^Ux>h{!8xVs{zv<ƼғgX.1@RUZ;]=iB;DbKfOAz̸¿4 Ťy}7izTokrYĻvC(>thJжz~.Jt`d%4IPb$]5τ|etVÿoC,0[G7Fg'Up*Jbl+hPhgQ0+9~涕őʦRj<㔲V)Ch/|nzDhCIoy`hȞme>o yD>մQ4$D5UIILPuL?Um+w'HgIn@.h6x&%:Ӽx/ $iXk#\fEbƢ2|7鸾N8I'Pe`k˸Oxot:~N;^d%rdt{Ŕ^*&ѻ~ ^2q pUü7?؏& %hɏ'pEpSPH1: <l_Wx^9Y!R.!b_Zo endstream endobj 325 0 obj << /Length1 1334 /Length2 2739 /Length3 0 /Length 3614 /Filter /FlateDecode >> stream xڍS 8{4e IDo!1c7YBƾ&$1^3/cfb߷BBDE!! %E8Kw~~?뺒\@4HG(9 JpB&)i O=LP!>ИcDL UQH5("?$ 8\s8`B"T>Gpx 2RCCMn)C14<̈$,~ !(8Ɠ 'Qp2rD6 xZˀl lupFP@ @XHeЉ `fd6ppk 3%y1D? X4_!1*@ ^:@ZfQL©aG01]I Fw X6A$~Jnm W:Y61Lo*%"z/֏ kjfAdpcAn @xBi]!+. "Tn2s8` ~^ s% ~W`oae6lQO ȫʊL*)+Gq0f5&rsY&7D=\NAt_wXº]zOශ0@ʿVcyD *] Au=dD,uLUT !\Pd.,ɼ'WwH1]2(!j]RG ֿ$ q]-%N0/g}z~g =^YtGWGѡ%v^ p}ͯsJ>'ߔbJAǙ8`j71N>oST3i]'ʦgh9YƫJKIMH]]i'[dnNM^nwOюdQMm*oXLȦ93&TM;nw BˉՑa.ZM>駿5cU( Hߞ5pvCs@k窴'>.׸>fϝ{uW3ۊ3=vmI9RSv¨Ϗ~ 㫑VO,-NDp]Ş3e⋄|-E*0,VzAU~R0I\|yH]C6,*)"͕[Ħ_!d#ZZ\|Vt; XfáGG=.Cpf"S5<[tڴw_^ b_/K_|RN9P*]X1DT)Jyy#xn:5jx=~ HUI v2KWkø !~\NI.S96J1"rP(^Le ]h/s <# (䏱ftTt4M {8DH_}79~gKN<v~}GYb/j̣ל:un:-)*g߫g;!l&9I=f : ӕ9\3oŧ[Kߣ1J/+#Tt>pLtq>(o0y)t7>W/Ue[mtb؇Ky+;lh]#^juoL؏n^[S^Vx):8Q:?m+*T?O]UqЁdVC7mLKW4 iuP٠*υ[ e5\gݖ@C1WuH[4yV5b9ƷܕXz|V`v~^"ܝس8pIUl -H޾.-Y^|ݺM-1tT;Ж9{+w_Y=8dQyK5IWXXo)Z:نk^ᾣ|^P^SDB##J^3KPA7daB%j3.O%UgDo{\Q|F7ܚ)`TCic=.gp=v W8/^C endstream endobj 327 0 obj << /Length1 736 /Length2 10526 /Length3 0 /Length 11113 /Filter /FlateDecode >> stream xmweT\ݲm޸w 4XC#58Aw݃^9w7fU5kVB``ehkrr!HBf +PhNvv$$q[0hۛY@6BDXiW dH+e@G fn(,.@X-Ao@_bV@IZS\FEY -ɦ) 0s(-wtu ;f-{Zxc"qp,As5_;ZnN % Kl7{{e3 ^ @#_Ȼm?f {od.hWEnVvp h r+ gNJ@K?gw–`G{o[MI[AEK ﰴh pêf __k]2, 7  bZA @G+ h Mk +..cn\3׉e_h([啑Hd >6%XZV4/c'bE\gh>2j ^S 9l-A>߿ 7^.hHADGRci`Rz#CX?gut3B";'`>րcY#7MjqmMˀ?*bxyUSD_%3%Z@]^9 $9 vU%/6b\6D|/DJTŔ tSf`+ a J.,ơml;~O ȖAzAydfhT4qֲ )/ܧf NB\nPDsyklP|3ORZ7#r6 2xxYæ6Ru_I'lHÂN2?``2#, DVõ>):Ep*͊~”)R.ީp)d[']#r  ع)nShd]>w{T\4VHql!Pv4(ùו *73# 9d鯈78h/K>/zGrNjg=GiqmZ2%Պy`uC~*J =mf|gEXgMt 'Ŋ2Y:2Fb$ Em9i5HmmQ)NCL>`QnS%<u}3rv}Y; Ih&/&A;IJĖcke)^Hpd1Ѯ&W`V)$Hm@K.%O>{GLJwkgĎ%d4KxXϽ .I7z,eg'sb@g6վ(;jˤ8#t͐L2CS|q>*d,V˪5?tqCU>T9Aǂ38dUf781m#=G>A)Rt-v[e[^mڣE\Bĸ.d묘stgJ~dqCEtftW;(}`u>qk1X[kUsLz֣ ;s4) O\<#p-3:ٴ!\"#p'8 ͳ>h3"˴G   OK{L ;SEOڕ1&`2Ϋ=$f !^aT~9{4ʥ!* @Qu8ፒD3SVK!Y^A.%RӂQzM_v+0 2,QNp0vTw,mYF!\-kf@|~WžOou!)2c*rҸ&aT^#F62hTgWjwŚ W"߳k[>Ы| ϭƼiI"Q))jH?Ĩ#2B@_JgVsF}Ihc?HZEagSanNUblׇT1L+S-Ѹ1K?5> .9fE.9+gB]uGpb|{t=:>tEt6I u=q0FQXfxMbZۥ<=F@[1~3w])}$:k1sYet6P^}P 9cLkNm -! uL3cMr"}>R}z1cZnwp ޞp0Ҭi?1TO.>xqVlg] Ga-*B?,w r<֢Z,yQ?cb`-skesS S].)V(Iq$NbV^ ѯ_gFϚPrC&iXg(-Ns%rx$>ܩ "Ny*ACBƘzOCJ*~%%vD&sÚ:̶Iq|R"A0tκ7םc~XlX/aSt8f64ŋpe鞐`s?"Y/u+heţ+ #%[ۊ49aK< Œ_prA|昌d  E䪒'k6D_OSN;^"UgdPgtȿB,frRQVɬ,0dr+Ty}D[Q:y:%tAubH!Qf2owz bs|3G(&]lFQ dFs B k::&#Seoໂ_Q{LTaܨy85RAU3{*`&7!EQ0.ҏ{Ansk#m;qO%$tGl8/qQwг-##[iJr' O+a}{r03#\?lrkD1^tScLRּfXN7 h*]0?McŴ&Lq|ɰgz;k7 Y~@-(:dl*oO8ə-w0.NnԏEGi)1ӳ\" v RRώ[nJ69P ƧJxWte(a]j[&6z_r\lo:x+#)Y,2llT JtҾ RRWn3WwwqǚՔ[ cn#C#bNm~6ȽKރz|A]?g 8xG҂r$"뱈I9hՂ}Zk^4Y2q<v(!%NO4#ӗEF:sH]5 r[Hx*CS!R(#%CȤ)_wv}+3dsz_}.({?wML߱\'_Zi xYD궠b`rVή!#A@_mɲ{PbsÅZU7&-k\l$O5ӥuy) Of$se8S״Gb[ǎ&c3Ehfń}6g3g?}d.ڶvfBGݴK6gTu)¥Z3 }#Q'Ϳe_)S>uQS;3:3} >~;_V1_Iё14$30 ;~ t1n 䙅,Z~?=pRf 2#tͺno` {DHܳOmnp'*/63&’n:3p9+R1X#c f~[Y6I$&Ngaqtƃ6x~iU=?*`#|c1>我9YYdW'ͧ/n,[TN&9 oI&5&˫E8*QfIE8j#h^v{q\oZ{oGWVs T&eJܴh18`} FXsYNGi0<}OQrPZ8#s9RqDT<|&CV\#n#sdYY.bXG΃]ؓQt1_Zo,|t> q\;`0ܝס_4m:|&&H~£D{3"dm&2=2BJJ,=͝M}6Z;%nu9MwؑV[hQL9I/p9溏6>&ؾZqsp-)#IنuںS \ڗEEĿoi$1Yڟ 98p!DV ߙU"~f1ڈ)jPtDaWGfӃL COARyȵlK(] E^2FL9op|}ڬMQ*yUP7=^oA6!COᯄψ=8vv <_\2~yسK,҈a"P+W}f'xSC7zCi:E*6)|P&iI%"PiN[t!M[}62rcdZ'#$ơ/['aL^1[<)wZCJ uDG ~2o<&9IktEŘr Nȡcv<3ض0h|vvRv5Re2&v6Eui-=ffOC\aGB^aQ)уUQ, C'o "ߎ8ؤ}瞞L&X' ] |=`d) MK Hwj%1 gA%ܞPKFd]ŁoK-lm¦+AJoyP/4|[ FhfbL+~H @^ǃcq4& ES}|U( %"ZZ %znO=K0>fh+/;nϭ db%٘_]|*Q)o:PUxy/z")KugJ 'S9 3t.LscgA@pAa) .!f5ttk¸ e/ Om>[icOKf;WOפ&x(laTOwYZ!1=IfCpLi汭Ǫp$N6GS:9bsWESuw>?!y=9l^|F|cmsӔ҉~ 2̙8T3hr"V,0 V-ih%Tz7ޤ>tl>ȷwkV[clܾAjjpZR{++6 H0ctkqO Hq us] eJ$)$,09GԿYkѕcq+ ~ ~ӎ݃/C#30' *,℞;#c51s j/3j$=kQr`9Uk^3ؼ۰ճ)vB/N~5c8~D[Fw~N^t5Mfg~<ضaK`1mFn=^8BKH N̉u%0gx%;/tЅ(rb1]R_ YzE# . /|DYWQ?O!#XYQ0O3%EnD?18tv8F?bNp2bH3ptZ:Ṅ㓫+:B)!7JƤS? ʰLfHDjU@qkx e#hR j''"Kvh4^oeSI,ը24BދP!cI]8BmTVPG)%~E%BHmyqjIuJ4bJH_HW5'm.?e:'uz1TYKBù L}_o十A 4y_Xgy}ey|Qil^6uoӕ_&9, TP|\7##inqDEt+h>,:i- fC¨ݞ;-)˿Pp{۟#_P f@;JJkeZPFӵA R~4-guYOx9EؓgP4=s}sJv}M+/$hu#u1BX j'Dڭ8hSju/v[&jK1!J݊iՌf=P|-Nv1Nf3&J =! ["?\Ү䩏Fh* 0lO=C.Dv%qBƻt1K)|Nmg˽N{+WP~'<>}6MxG'_֏dNVv!̛B-NH;%hMsV.fwH6gB@ɽ"P%YKC"gIII?L֊U՚y/.~eQ6X=bnCh dišh[[~.<19S9?[a:V f#ٌj qT!܂2꘩3>NyfӉq(>c 4?/a(/tb 996. ,a3ISx;iwܷ(oAP磇4!ICU9Eݏ̈myE*MOغzKbtHwsYKnoF;F5-xim~w97tL77\Fœ؜ܗqxĥ=M9jR7bgMjHUjR4A:V;'i>)^vaȵv=tFܫm-͐*\upvZP5BH@` i  &צ,-ջa+txFmhj)0/CfTwpOlt ̺vu)5CViшd.X KzxG}# %6޺ vpa;'a+2|$IsK BH_^p> %[ik.K${E\{Ro,"𝰡Y9%0v,>ZTUj]O'3 Tocpv/+!LpOg}jᲊ9\_Q βe~t8!+սg~$JVILk|5$B0ȻS}Uw._}(y9[QtKYu3>&¦Kju@ so?"=NB#Hl )ǥĭ,h5Xi喭E.e27=]Kgo 1Xןdޕ%1A+N_- K guLxL40N22#NžΌ*i`y|Z:~?\CB|N" 2r`B: 3?pn|+tVF/f4]O8F`?ܫ*EzS%z\t{|'[Us2> stream xlc&ݲ64mN۶5mmִm۶i۶{g8_ԟ+3ʼVVTVE1=#@YLYH LFɘ P601¶vfNJ#5+@ "LGO1`bne WАP˩čm ΆVFs#cGc*? h?8ZdEUT * @Fp'GU-鿒%J:Gcb͍Ʀ6p Ml?r'??R&x;[YX(m휝@cwu0le`O%b`mn<$ !E8Y;̝?o1?K?' rSֿdPVoC,jcd 41(;í &.ouY's7#څ_H:%$dI`5rvp0qSn,cc7c#%[# 2тrHjP!ӖX.8P&m*pMY`"kXoXe]Wb_)0v#ӎ2'HRI>s-"y,nvBA~wOWҕH\{"|cIQdrUE}"DLN5Q7.A !{rz ¾&!D8klU#n3#6[Dgق<Qw+ m,TsX\Ub{S:-Wq[o2 ,Oy}j#ԗ'AE?ߖreڍţ.h "am[DJi0#jJ >*CM&YC$ V08-pr-iвh#9q(jtK'}>O{c3Q4,ym+6Y,@}lT[e-apO9RМ %Z f+LU']S WTXK^sYM90=& ?e:KSa)';FX_YÔIC"Io 3 C27kyDoB.]QC8J2W_fJ[OZN#p)k'u} t=UȣLʌNGa.JH\@eK'UWX?Z}bF"Lv˹;u{We@ZHGD Ý-;8 ~Sjꒈ(Tэ:),zguӾ{\wRLqk2BMHH ?c@ctGuP2.zkKЫMꆩ)WΥl+҆O- "%ВFEg~N`,+g]Bf<mqkܚi2PT-Hi#~̾3mN\Ab;)_j"R0(mQD1vf[dKY;+ >HrYHI,N̯S/,ƙX)o~45ojڷ{ 7Ƥ:5ݺunєU. #S1n8{@=33_R"6m:yE 9!63Ձ$\LY7=x >Y&q.hDKo \]ٟ%VpÞԔ/ep|$qj-3'NӅ4<͒GaGNU f=W B8+a {]dyLڃH- BfYXǀZ, +~h ̒`򵙀/7!N(w@9HG4+[C=rl3ǜb#2d_ Gp. J$,IcϬvkEЬ Jm5F?Aﮞu`jTo*#/Yz;|ȱ`OHpIn c N ouYO~Rӵ< z^?o"eDzN]> W%bzn4Ӥo=˩V_9[[ 猦[ih7ڼ B i a1)ax/pnx :8"P:\=nj&b8JM4SX 7M׫ zs{ E{0Lx/4~FS<{BaKv^.ٵ*﫭ϙ|=tV,g+x%FJbC*]~De3 WG1?yڦp\lY,oDO,!"D6(=`!J5sKl2VV z. ŮN'xak`F?UTӻd#*dy2p '3u|O)ޖ9pmz$kHU'~9_ [(I/1:Ad"kGKX2Q.gK-o,pOT^d"aޕgte"7>U8SW (%bʁ \BuNzyU4w+Ժ 3~D'8&@{qsj/R5q!X+#mU,Xu6C"&6Z+:)85|ܖœFDШIdk>u}"PS.\k0THlCF#@X֝B.~1z>أjy;|dN5vI&= s:rp\04 oxodL[R~܏>]*C+i?F=5QPڟy)ǡx-)5K46Pdk2TI>K 8ӗ0˹`gYA{hp0MlrO0 hcrk"2:#٨G\5Adb`#B4֯ ꢄo#MaOŰi%q86m!W >XJHɃksIBtj+sͦx2OG̘֩@Dc?XI0m#qLmO qp^  l>JվHn4Nj)bxazMGBS<4 |h$nuJ:D nH@w~iWF |&Yb=faxAFK~r@8 P35R߭vgYBMfOxe F,+Xa8^XW9|xD\u yq' OHTc(EU&4zx +v`|Ez]d[֥?JRVw(f]DѾ==0~{B5"_Ni aga3R*蛜4MhPKuRq[A&.bexR&iP\ޛݖHAgL\!03RؕNNʡINw(rȝms6ϤUyM\#2cx۸V9 9ƢJխ-jKNn3쬉$>:ZXr"0f^H6@M`Xx Yz _&F5v-! L|BOs:ʵgR)2M:xj[{7,e9Ȇ[J ,o0vK jGs-@QY M.A"vR2ڠ%9%L>BñMkf-a 3iغMLghu-6pluݾY=b 'SQ'!gѨiW̆U,RVA"=Ȟ=]ꬻ4<{R]ik:9o .+_n [tMՕևɓn[LqظlSJlYG bC] obnX;rp[5/Am,`m`3]Џ?ԩ)!'ˇqv Vro;udEeDAe\ m ׇg穵xS.fLZY|zm,&k9酉IHo ,_zP5S)ߞI4-AfJ75Yǵ"odi d^啞H?bHxRyHW""-dgHlһ:?e:A)~tDpUdN,T_P#@eqsfJb?wF AhE4Ft"nQ *lʭ6VL :$RWx-gSJb2eI,.4{TL8ѯ^Y੸AtVqP_)qyiL,t݊~M=".gyxL2&/rܞ;.LaSRUvn1z"Ek@jz^XuWj,ZqgwHp&ms!#,"!nMfM/=V]T{)R!Œs13yo'(uɠxց82_O&G0T'=&O7}{AjOr>n kI83 | YZҋјHń4Be]韍2JS6(g`40e^35 }mKh]f jkK&tfM1\ A[No~l#Ou*E0Zg%y#<}5ՎM ,7]AG{2pOKAciކ̎5w\9%GFA&^X9˗DIa"L鹁Sq'N1 t-(=h+_ nVxjF6Qט <ƼOŭaNA,`py VA1\ ƌS]/W!^OpYEàP@I9\ $v~c6BM n_Fr?U/Hk"r}u"JQs%NOڴw %'#4{e &[ؑ8 eppyFO~1qɰ/,jԋɨrD)ʱQ:zl|ŋ!I3&_JK۟tAQD&qCFʟRL*]]-V' MIG2E1XQ ށ*{ OӣO :@M?O;ZA B+$ЎE;mש$QkYX_G1hNVˍ135H&sT>d§ٝ9 ߣHȗ~}=j}`mtY !NQ ruKI(& jlcʪpjz@lrYSF$)O>9d y?=z,Oz(Ӷ/ J) [ ?6o =W֐yF ̗6Zц; )%1oq BsIgj+j(Ji/~aYoCdi|g=nΦ98(' /@'x5zoNvi`ƅ MV~gy&jY}rRn识tz ~Gih±n n(hNB|r=ۭ9?m[3\*Awà K&6.dUѾ.fzXA32*KSXJQ~-v:3qb5/ǃƸwB'Dԩ_符x?tL>b^OFX\Ғn&R M(FU~Vt$) /:dľd+QƋ7F0r;40k 552y.|:K),yZMwRyVZ"Eg[ bw-:Uw'@5%#Ѐs>]^E+j1\rB>[>Y!^x.zՁH,մ_QYm&s&c_.&=q2Xtk›tkF#V8.ތcjE-z8$-dtXej5s SVPLM,wDSĺEWdv8h;3^*Hr)Hy>dYoHUaWr1w v;w%-RbR,5M6uMycbQ?e瘧Jꡇ5H9xq,U달܂ճg܆LYÌH&fQGF L L,ESKCT JP䫖 =hLES0JB)zTFjIPN?J #uBQ;W,˒cCnD93p|J$$́cޅ^)7:#c{F!3 oM%*ޢ|?b[( jR2܅# RrPio+"7f{t<'5-ՄOq!$A4oVyzNA'4%ip" HrlE.Gi' yv^1oS50M9V{pIJV~(|ue7 JdzTۧix7h N)=e!1f2ePl:s]ew]Fְ($(f;!3K=\HsNπ;47M /Y{_[%;!8z3f3+lFd[^^4ٺΗXԾ (%C?w#JrɐmKF{$=^Sk RX_ɄWes)P?ܪ,`- |ttZs,6^.2-Z0`1$r$ Btw5K4}q#wXuF/39C7N2z'fDCIa|5pOwq;4^"ΤBȍ Ր@4*4|Ye~J$?1JR׬lzjph(]>I}8g 9*_Z(Q‰YJG^rUVSҰ "A-܀OQ ucvw?]Zyyw~ZIBoCxqXQz5A AWY~\X+|z=呱R{{ļwڔ\*~zBg< xz7Þ'>'Ot<&|R&Ȩ57!ƨ{moph2L`UCt]o]dB j4<+M92ZaG(WKՕ(R t9!m?Mbnǰq2efηj ;.=dQC>xn[^[ݩ LgR&l:o~~gI3r[hl;=kҖ Q+9Mk8sH6ֽqƗq3wu-s/_PCT/&sܰ\d/F6/nP\MN3nVVĮ)AOyQыKm ld-/pWUVY>1]`ȩ] Y? :A 3y!-S cD Ơ0cpĔ)! ۯC/0 c'Me Bpv:; !;i/)]1U7_)D,e[*կLS}iGv{9FZƿ# Bp jQzSx"3JT":ڇḆ#Kl*]Ym6|N)Y7icnkٟD&=Aõ9(>)OW'"XMCHэcwųm\'FIh~ ߍ IwD-\UDށ#- >_OWU8Y [_[YC|ߑD RsIBM٦?.`#C%yKn}=Y)<L$W'݄hhܻ )'KkދsU|wԽxr]A_}"VÀFO}G7ՅJ՞_iڵ ێDWA ;={nS{Y IMTȄrV] <,\Xɛ^5};~$޷:YSDǦ\.gu$r{o9ܔZ`DvO"UBTz khb1fp(2ڊ]9|"_s4g$;߃0!p!\5d0&/ɶ4abe$SECPGX!F,_("qZx*>4[­r_{'j%Vٔ"{cy m:gZnuonXLkXr*ߝf.Ek6<_Y+|bi=AۀduCz_cB+>9Un=~gϚ`M67 FJh'yZ&1uB# ocg#c.mS=¼|`xPmDa7ZK Y|I&疺w>]Ȥ3IѨVIx_dH9qv Eם pCBY >ON(('xQۂݘ'՛E)̺q26݀mW贏 RD.e 8Xg ^`Z3CJ[/Lm٩## TN4zn7g`u6 _86#SpĬY\e&9W.2GV|XNK᳂29=] &s?5*~F8!4U<̙^ <nOq5}1.vÛx~>N>KϺDͷ-ZbsdӺPk̋v$VGf=D('&.AkHJV%Y0T]9TUo0A{2OmM/xSuI fh薫7 )nCsbVԴtK c6A ZS60NFғ tټpi]bh..ϖ 8lۦ6i5Q!~PΧoG8س+Ғ%9~yF s]0ȿe>-;>A頵%QELrI]:}P!a#ip5Sl9]w[U?ÿtF߲T>)l-p3Rk-(5Ya|T^~gнaxfzT"vvyy-d<͕JdJI]qZڋ)Q &kuݏ0ْal9G]o|[+Mr?~T=LX>~1?ͧeV̹Cgcܤ^hUyO)AhذAB;ʡN6 “ʶ7jMָ7$?ї|ܾw"NL{!v'{͍avZ(E H8m͵i5R.,GTBT3hHor Ȩ;[gC.S/w1SUr%b 6]Ot "Y*|l_zf;Y~+eĩ?`!j ~Gɗ #E.. iV&\J|84SK/u :Erqlt0eEOP?+>|Pq|RrI>د2@ӬU6(3{|b:B_WUF.Hvϼ=eZ~%-{`vOnʵݩp@Fp:$sz'?Cq?G,Wys[Dz" ˁMhKۼb,N08M)~R1G6\Ӵ.21"ZTl쮌lDžlJѰ;䯊1 QnME mik3'. 0wC^w"\Mgu\Q&Q&H9'vѷH۝;بe2ޕ~i[KK 1{3ax-܊ s,^ygl_gY6'Z\dВr_unO\ +,c-*ϩ鍂poɬ5̅{ sp+-Rcaᡶ~~4k<䓍-*Z̞l2'S8i)'a=]TO`.7#6"b4{FJM cu8 <$ȺE#~Av?I:f׃BZu檞6OWm%U+SFO7jG ҖSR-Fę ]IT3CfʋcR\+L>!\ SR!^aUV=ʼn4.NޫQ(Ź;|m_(yD0PBxY6ZP592~7jNZ,`Ե ]?uS&<L{m~TqHm&e[txKLE۠f ;oXf&$ x$:|.[xAl}E].iRkBHGr찕d1Pҭsq m]яg%y/%;աuB)T'|XJa/D<<v$Kˏ,O‘RG)gTMoFު:wz絊z Ň!8, MJ~7~7$I2"Ibsͭ-T:Z,19 Bm{ܪscf|t^ |T''6*/phGUDֈWHp83 余Ȝka/& loilR' e7k쏼2?Z:3U&@EJOKylyiRl&aL=Twi2aPD U1B&pe'2⌥G"XV uySK?kQt~l9nmƓf>U e#Oa o0aN ˑh,ۓxG >[0#/t^}L۳}hVkWk3ԛPJIr]B$=)CbӁq+7:ۀ\&sx"1D)emCEpPRǒm, bi IbLR|e0'JF}m xc֭괲].>Ɔ^Dt,0'_'4 1^E/35:-GS̭C;5F%u]/U@ Z)>ZFy6UK0p5L%ʽ\{Œ̭:F:Eڪ5.~9t/Iܧ_H#e{uef(KQױsdR] pk"PHd oBXMA|hf~d({+֎1nirɍvOT㑖aJ,#t2*\>CpOIgE?@r-O*)40C}sQ+gk޼̲!;AQQ ޽٘jw7Nm Hcg &i"H_~&zTECUW~$i ̶/Q[t$GfěZ4~A51Zgf-DH%~Ƿ;S  ev>ľF^'`)-@tl?#Jz>Vݕ&^Q{T62`Y!׉^mfuo=P fš=-5٘7~AAÊC`EsvT+Ƭi6a׎nn^zTTu"JӉQ*|(ᧂUM?rRGeE}k|곽ƨgE:s]TUCBKqT1bkG\lNusoq/4W+I@w1P̩e_d#\Q,TDrm⮭J#jj (hwLZT_oQLV]T ~+ g) #h*}S Eގͣ1HlnܝZ8FR2\'DL\.rB{_]4=LBTC|[ i\%&":]OoQ+9.Q7@(uҖ)1ܚtPk]Բ$ߊh5v2f z QNaKfk(LAHAro}RP1pA!k8ÜA g)\j\.&mp":6bh_bL yC󋢡NpYE).&-yX0(98.gHWklq&MA^N_;}U2:t "A! OŠO N;&ƿ3\c3̞0t qtox:85c} |_f޽ LP@gdVF[!~-6ڎј8T R a> s͕R>4! y.1 I/?<L'E֒-Pل42G,ѢUĽ=}A,lw 8mq{}` CH)q`2\0@*J+DΎ4u8jJUzylne^z5@hV?=Wh[aPqtmn[פ1&xg+kb3;G(>%7mcb$yG[$C O=|]û+k-%/Vïŏ7sq 9QS|sRuM sm#ޞ?'cN;ޔze sqVi.Cs_-ѯ҅HXcMDw#7RJ\nNdswPSĘ*8^%]U= J+~ň6[B=:a_ F0OWG( MR' !C њDl4uK@Pg3 ? Y\ɐmx@< r&j-}19(uTh9IZWuJ3DwMzX-^#&(Fx2"g{#J7=$"B.: 4X2 M&L"PֽK L (K1'< M23z1'4xdlRf@EN]F_74JMV}yؙ]tF: l$+c Ӛ;O endstream endobj 331 0 obj << /Length1 725 /Length2 36935 /Length3 0 /Length 37408 /Filter /FlateDecode >> stream xlc.ܶm۶mkg۶m۶g{m۶{Zg3߸T*#+u'JK:yxT%ԘXaEFΖvbF"M)*H™ʄL" #SߖDv6v&D|BN. . tR-Df6"QE_ DT D[ @MdfHdlrbG 3sM$/&,F$.ʨ&JddkJ$'Ow[g'&R6FK/RGP 0D&DsK[&mkfG1`oo{g#)і_ػ9ZUߖ6GC0m?,K' Kw?x;;gm.&{ ˻eTD|I>΍\AI%]G hT:q{g6j[oᓞe}5p\(<`J>D=:O΅ai~y D%Qr]O?n}WMCrBBѱZ0xS@㵏g.×D(S`+ݯre@_Xsd7߿/eߌ?=9Qquh{ø*B/rq"akttVKPYyj̃bQD F11?IzP=$D+uɋҖu?z OLcF)?\x6f%Ѹ8\+N#3XT.C-Qb4- 8Paa#1@y]ϱzY ^8G_j-tDsCuP,bwT?hNAbprt,Ț[ð#ǟz}IF+5ĒNow)Rܾ6J!$#,q=3~$)4r$+Xv- "ë,O_G jCkkڊ@W7fwG'4gq!t9x<5UpV8 e;|Mdj.w]HvTC怳}Ȋ=]eyd a#n_;:c'6K uZgc4 &`d)LX&72#HP%]eoM=oxuW2.,VA_'Rj+>W1i_{ᣆnj+s.w{)"`$7`jU nyL7c= Woc ! ة g,z쾄)L]2oS 5d:L,X#eQ\LkGRĭP8Aj"NZEj ڞ\Up:N1ޢiNJLl29O{  FDQ2YlYNb$"Ť(Ye}J>Y]'CD ]a5m3' Z:BZ$l0bʭJM<{|nL, *6$pu..XXNЮ;`:;q-o%xr(Q{|Z @Y3"9khm9 #5~/tPe'g\(ZW> ,NNXez`Io.05$^H|&Y"\5+&nP)ʑ¾k?-#]8{\>hE[I@«klj-N2>ޱAY0{XI' uQ\?߯y⅖,H`2h1Jyĭ(JdQV?=iRur.ng(΅Wmj )K /y "3I#cX^i|ۏJf0%;%E9sN8"Uadkdoϛ13/BF1jǤ#̬{-y(3pD&y?ѕm&h!;9$ISaa<8?>c750-85YIqRAD[88(,mTvQpu5--46^_TJmeR?NˏRz}#R΍~8j“s[ \_'>tʃUq]؎lb魞 xxYq+vu0sEuɿejaop*XO#ko21Dywanb*ϺAVaXN}f<5Ky5!1m{gkM!㗹)u1.GW?6K(O?ޘg|->‹ȸ ##FwTSMk8@KtKK"n6[ Y}j6|0l}_N~P2Z3 YO+;ȗOqf-y c%PcSr쯭×}zĖD.a;j`Stb.AnP /4x8tU vBəTrzM1>BO~$A(m]g8o =PB_>`l-гz1pbW5 ?69vf0b(Ƿ[KxهbKƠ=AmؓXTݘB%|̵X?Kuc BX{;'Mv Q_`7F[ OLViF')K ~Qݬ*P\ Xζȶ0'dh|>e|8bQZtpFiie@bC7Z^,1u Dk|}WZ:luR!e/ ѰAU*]s m 93A1 ևkբi۶ xϵ ;oa,[iI awX_׀g.r:I0Sl +m[p{3h)Nѵt ¥̊] ;h;eaTsi8x}%}JQ%{ZW|C|C61bi־ %N-~Z[8N3EM^I ڢ}h]$)Cu6Kw(\զaQRsiu ~p{&^ (dό5,y?S"#r6|)'ED̳ /@^3.2A>}vIQ*b̹u!Q%[l,Irvҭvdm ^\ 2嶿np9zAY~OF66c;sکK#ZDh?B;@}k/r8`Y)Әe cs/z:j uG&CR#uu /a5c9vzlw.>YkYxo@8,+i}O>Q^82EHDXf2UE3"O%,EeJ]aݙD*C$W62F/BzT&QbpZ-RKSlst&A ; o| R XhHoy1EBbX6z ya|c.L4mX?54nsl `wh>瘕FGkqbj6q MʔzoEK^O8M^/y_xemhL3wx\{mс?""H\}G4(+QkP, ӘG&kJ^JYgUMZ6ƞzRd:\sS0\NjW,7KΪ+׶ іoӎS&*6 j 5Ϥs~xYoWV? D`k*%'Q(^x>p?SO5]rLnkjn}qrP|A-ϑS>4,'6|X&xV7\+~p`z>MW3%DdzL0wS}}Q#E]+vW]Xbiw(spWu%WNԺG)"M=e#&(!`Dܘ?efQ!-ai ໧PElNBH%RgJ'.BȨjVI֔rUғ>6U&CibcG?/@/:TE֛+h \ _Rx_21,|qKwc2s'.f璍&bՂ nոW1h̛-- /%7DLpc9CZoV?|Z^qYfCLu_  5W}50_E 9b3M/0V2 i :AgVF!uBRxwgnla6IJ\M&vD yτ 6.r@b1P#M5ҌpG8f%҄Jּ\dRƯӋ}:.A$37zPzW3R>[GnClꨭQ$3ӷDZ#/뎐»s)>,7tBJK #,v\aL)WհOfKݳGRj\j,^& pVӭJpRDsH>p hJlhl?B)QI)Uw-l^~^'^cCF]-랄D5:~z~-Fǐ@T->1&c\tHg?`cj~/ ImfNLI9䓾e# +ῑ/B{.zf6!B-޻Lfax|-tRr!ֆ;v&JZvE'8.K'E pW~8.Hmvb`_SE81!,UQhN/\H# A;b >`$JbG/~0ýey,RZ'`PL֖Gr7`uOM@V&5=#JWzZNNv]aϘH mzl֙LzE'LiߙlէO+` ;i ٍa$`h?\( |H1`Q(f.wrD -8a&ɛ,f_~ӄu$Ia~|B =4)JlVaicFŽZc%U;V(o6۰OX[|RM?%. ZLMc;5;ctuFȣX9'WCAWϩ81fBU{hre]30kzslW(DFR2 N'LL󃊒(@]$#7jbS=DXr CڐDq*uPH4b:[zլ,&Z5o9Z'n2fv u)_'V3EjUK֌`KNGC]}lUL5y Q|2eHd|Q$ylovJU6ek)P,?rC(>Oc/RCZo2@x5MB.if\"'{˃ut{oy/aZ^ v­.jN8JܮSigUp3 +uti?;9SBCXUaRtn0575EaRrk]R.C V2_N|% /VOAޅ0W[t|\JaСFwÍZ] ;Hage_`0vp4|6gٸjz#i^)cm]cR$ 0 }P`u0rPnq=vy3A$*ȺJӉӒR og-qBqc/aZP3J㺿̈́nwb:o=T! u:S ɲK$x bM]1?xT P/Ql:Π S=1mF^cߛvO' ‹e'{N7~;"%@̊\fNVծS|H%e[mS~7,ұIFQk%}Z~>p$4JReg5>j蜭9w .E+HBVeCW([6}&&jXħsĦM KcHW]_rBW;IG7)„}k,W %wDzFG@sA/.ëq9%~ 9Df_8f[*wɲ/F96ț*,h Q/4|nd݁uaUۅ,Ub/UAӠ7O8X$)#X"%Oezˎ`=P󂪴3] ׈zePCxY&f}!8l54}*1vllEFD-b[wڿyv4lT5Mg?Ra+ 9q`=nwd$DK˂-~%`ֽCC9֩ :GGuf:Qe N~=R kCLTa"o" ҘW+&WW=vS1eѷhHOCaŪ|{DWm4!VCY?ͥ\gV]^FYS2Hv;ڣ+p!L.Mb9c@ny dSTprDf:|QI}l08&Rރ|8]D%䭑,U]RIuu"1fKO1Gּ!oOl '{˦J8c`4'`+Ese(#@ݩv31mکƷR1hJ͏=m2j\l6V&,p|#~H^>3G"BK/T;a/ja$|7!TR&"/A}&k{zmuU7.f],ZrB?)>Xm!u:}>Sp[ C;脀0ڞu71VSɔl%Ȩi‘j*^VN7gduTDnB' (Sgф#Zj`Q |gkIHEdeBL5ܘp7:EQK,2glFmu!\+6Ս9ˈ[wjht~/MRMzIaaLx}LRȈnf)H_JxKOing`L"ղQ3 XNuŎ^g e-r2W+H\3(9%Qn ˈ]%m’ (*7H`qF̖'.-YU M*m˯h|a;Zmyl7ǁv{Ulw˟aÐZvGu} q¦wnyQ8|gPL Ԧh;3%3;$v蟔泑CG[Cqת)`O ~QECpP~͹>W߱!{F0/[薄-XId!iqGB/Hn4ٺggTXzGI zԲ7Dۿ7~j| Ǫ)Tn-]* q}kWTDxVxb }Qz#c|?V.:cCF֡\A&@%?E%8c $)O9/==1uJxnP=hNU +׶質>Pf#2y(Fs˚BTCmnZQ"ÆKRON}8 rY2OVjScHxҨ6] V#6tA3`_-s<HPa@W_Cp%y`a/8 W[g(~BFJg##B^RbxLϛֻ?plPIϭ{ =(=ʈIJ(Fg_n NFY;?Ԣ*m8m3yԱĺj pI{JI{F~V>6_zeA0יw/`t4vw:鴔][6=K0`VUǃ1<\0DQG{BҶNn qsԒ|0:['? GТ C~6HZBYa7SJ€mt<əȊReA_o < UiT,ep"zRl R"E10o,dd.. 0*4[;Ҷ P@{P%FcuiҎuoN>쨙n}He~#T}vd.]ݿ<* h,#*CH -HlOB"B rX~; ɗ)V qd>)8w+a(:Hpon;Ae rez=\֑2\,H2a@EB^!.z!Ń?(X6wp9hi԰f彀2o)M`X \!v%m)SGzPuN8.s=تbdžߞ*ϧ*osz>pBF{U9Tt\ uba V7H8`gc ‘I7_4 )le^s; Y\6c#c>x`j'CO`ɃuQY&G~֢!/Mi.Gj;{~soKfL9+55 sG3.34oF>J/eJ6Žu_ t"D/7ҽ>mOByR? Ҵ*A(o'c>vu#G?1Fg a7OtimnrRzxXѽkĆp!2 bceMW$Jl> .3 HkLJDOh([YSuZ:EMIt;둕)T]m:KLAQk=>S-A'?eT0+c1LDهO՝!A̧ybTؚ8M!)j엥Q }3#Lۋ֣̉lM e}{>9~ ֱmxZadq~o0UZ  qkKr % UCLpB<zl608YEדK3-H Z߾q-js@hٶʶm۶m۶m۶m۶5gV N]6ƣ?QQl&JNRj !va2,tNC]4䓈?yAX u lּ7AWRG0/~ jB^;W‰X /kzXRpՒ_U^Qx#+x}\<. 6.ҜlqХ8X؄z;)_uĥL.3%̊[ͣ'{˭9M3ĩF"O5KmݡCuk [~R͙95xYsϊљ>Tur/pGtpG ╼0z92b S<$ݶDeq(<4ՙYQg/d09}kL(v%BЗJ|n3=tHN2 4>ejyK*vqK$&(ay ;5wc3&_9At"6 .E2x;SxvRc2F # J;&(-feO2;<3{oTX2;&IG#:]'#dTǢ>-ZJyn#B} l]txoÚ;vX2qf,TzLyFmnRHقj6qo!Zm\![1`S}o L%14QwS`O :&cr^[WsL2Dt=&dh]͗諱vֿwHz,?\#˳<ӼVhO>eYhC(d(t˨86 _ tE {UT;$ `Cn =W%IX ĀjPhPmo)\?/ E0_ UHOEgۓue/qqtrq+?Y1K͘dU5 kjkPh`Qq?[zr:mpw@ *e o @V84u0M7`%ur߰[j5y|c}G_e%Lp|Ɍ8Ÿ́)lƣl„+]ڹN}gֶ|Vk+6qƑ]M VH^EbTU^"Jf>¬L`/Oa+df' *̝J3-#p&̓ eN^dd JhP&£03 ~;L`$պqM4,Ps+j)ʰ(~R7cTyVx6lڤZf9bx98;.91FrrZ̽#"w!!畳)#' vI3 6.;U'-@@Ҿ孆P~t^)∉m~hGUeԩssJijdHN55~E`@dܠpqȳkTMUn'5Px Tz(uZ`ʱԛֆƶI^Ik/#lTqQč9 t ͙ n`1{zN6S Lb%TAkN,x <AY,ȸL41 AHmN7atT"hU%Z(` u{ܸ~w1#׵"LeWcV_۹v!81~0ۜ5xi"(9 EOWZn"I\'.8{۸p; C ^5bJC?4TE孕w,| ^sҖk|Eߏm*$/Yؙi3Hsܸg /&w,!y)(giZX'!C8v*RxAcϫb Ԉ:b֦T_y`t)n(|OE 0bѺTtY;XG߶HixXvHNZ5*MvmQ8zJG`ҫהvedECrQ Tɮ|ebf~2 Z1BT#h =u9/V͒Ju8n˴N?/Y4O'Ypt+ 2#>q)lz<6GъdECB굡e#>lt-x|!vS&Cb58rogVkQqɚrwy'|bqU?l.M4Y.TGTx`ed/(7b B+OiIыD }?/,KlĠ|* }q]>s ^@%_OU&An;  >D۴'.)SVzy~]ۮ6Q9m+ i@+ir6{a™0-:c]/-$ň߆o"n ޒ|_D!'ˋ~G5X ١xR Gזu>ot3T] x=#\_dwNLL| "S`_xR n ,fQMNV}ETf#]=qKbSHVo7.CH=/25XNXS*U ]:)-C sjp>]48 Vi^,O>iuttmSDh@f-Sh@M-SCX>NMM/HK=.-1meZVY{wP1.W䛦\ih)rܿ nb};A^|d|,ՀLmeo/6sdfeC% WD36_ԯVE|x4T^b.)cDŽ0*R?V)9S; WW~Lh.5.Ӡ.^O8?E'sv:a*;hAİM~,$g~ Ԯ]yon{3_O&৲pvf2 &GCjV<ܱ^| $Z vCm%W^_SO>;,I B rvPcDjWd]JfwƮ;>CfA$Үm?-eO.mRzEI) tɸYWb^2祖+*i_5 '%HpsWF~E=Tq{osA[uޗQaG*wD ё:G:I mxw*Ge&uUF!h0:D@M4o~QVA 髗SX׸pal|tj+H[Zh++D ֻ$,X1Ycl}֠K·cK8zoT"eJ[گFTvj0b Q #c ɡEGMhFRwתi 螄[`*@n-<_e'Qz9I>YV&ijafez,9YR2,[p'ʎ<=Lq*$2 ϲq#(B7&r"%/ VX{19QvYlh@R%P@AUsXJ`lR捶H.Y'}&A}bM-q Aٖ쓝-QJ?(E3uǽ,Tx)q&^ݡ3 POaK&(i4WB፠p=+w>S;0'!lՑLX+@0 BΆB.%EVhmK݁pQ7Ț JH~ns1 D^'G)BD| j>G/[iq-jz3%qG᪋ ߁ ZUxS1F!S u%*VyZt~h1zZ'5>J`2)5kDnYl!2F:nqQm~|CHC ɨPG$6lOs%Y("_/k@Mta3HO@f;^;E8[ zM~B3ghS[XȾRNWd\ғ@̳9,`ƥ2>^4!'QRmY> [c\!X@ ?4.l0 q.@V +;NOcw6} Q(6ِ@6i8<I@ E>Ak̑CVHR8p@gOh..m GU궊]b\cQ\Ğ(p0+tnYΒة=*,b"EBYrR<4um [_#t6'fdVCCVGWęOtv3E{+ LMgsPKcvd7e*$C㍆ڂMoGyi}BxXgqM0̷##];Z6K\X,T}q/DYI2 ˆX]٬k<9>q95 g^V[Nʌ+]䰀X-R""nL*NԷAqCz:\*:ҕoIɂN[-sPA[Q*&` s篗ÓZGɋСk ?64oNu'߳_ KqYS(CL^xßgҶF=Xfх^s-s=]U״Aͼٸ)xB{l_kfcR,Q,|͘HrȲs7)vmqKob\gMZA P6.t|Af@ĎP|Gw^q<Plܷ7=4A(Zcސޮ䉰˒C13ePRYjْk-[EVEn^;][˫8xN+{BUXHD]4;a)O)[5kl"y8`YER,TɘpԈ8s ܛe 8Ө'0eMd'V~g;T&yPhV-,7|(lɧ׼<ۻ>5wFu”ay؊5H,ri@Ll)Xx*ZQᑬ^r^X0qD0;Rɫ#DHGcn ~ *l2t *54" Bh)j=ɠ>{Z Vڴ}ݜ}"VZS ӣb1VB.cf_<3 "\@=p7+,W%smeGx18xXd{?,KCBIq\WBε+dC- S51i~Y.;@>#|b9g0 Yq^# `hչ$u,|wqѽ]6&Efv&}Eȑ*OnOqLMۚC9Q}dc[hFQ>B?WnR*N.%Aug1c3+䚋ßSfp;sP0w~X=X[*^uGyRB Bs wRTgq$$9j$@X0F3J33L |LU<FPރpB2z-UQ?DQClbM߹ /b 1;\<}Ќ3$ A!~~YFYC"\Eeaã(G }ӿ -M\ς8bEpў4}uRb.m.,`eteҶԶ=c>%s򨂱仚 yB a4blRRbM%^hJ_$XCڀEL QVęOZpv޲ 3D:Z.~F/Z- ?ϐY < @"^@GI MP$zQ{VNbCtA=rD5-z{CR@ A59C޸_迖d*LB!9dW‡{Ta-[SHyᄐlIZ8"S.{^Bv99ba![<4*vK5*o~Z:"cRq[Ϭ@Cj74àV }%v7[xXRim׬;_ οZpDl3l.'îX&; 1sR,(q6[85<(1^׎mAjtR `o&WϏnB)JhPaYPЗ0=/?O1 tMtM߄S zQvk\ DHf{A*=x=>ĢSl^*-O̭ :ٺ''X78m0"A]:`Fs'J<2P*d=NPwUEO3eiLX^⮼^6qB] Wvd )Cj#k`rC8 punaJ.xyچkoݪÔ<) x)r6PʞZOқP5% M$ A/gݯe"ʌ.x{EWIl5"w6/ΜR.k'ƞ7)=$6| PT[0+HOS0Fg.i6R-a 4< H;$U5鳫ԋP>d٘4daA̼.2}l"$o&iD3-rƼFR>Vtq74%ۛqy{5P~>XF"E]eVlOMyUSUQ !%.bvӸ|Sq?t''!o3# 4œdl3)Sb$)"ՊR孫?t=-&$vDNLb-OB&ca-;QL2OM'+]+a/K$i;+JSygudԇ LwvPIrA!jO沺Lcdn/@LbF(G@:Kb(X=M@ˌʫ՜QNyڜt % &sN+4|NGҙ{^!+YI?Y Z '0;4ńΕj=&P"9zx5" l. Tr5cRglqI„U3 w=WR޹iAQ]G(W@J:~w AW{~)4RE (n_saz nm#XnQlI ܳ9`hXޠ`7dEi3IGF~mFp [1xW}x){[Ԅp\f+n\!ܒ zhCvaRL~Rl҈M][?;Xɝ`94tenF.VrjA8a naguҁĽ$w^tD\[i1 |/أxoE{3\2^YY- =|:\պ`%JG0sI{&}6P:{ J?AMyh 9>5v6^WJT)6/+c\ {貑uGa/ {o+7V>Z8.m&-|(r#m]oM`jtU>#۠4;|X`8khSޭsgG+8Fk.Ǎ @т~/ A-͛aD[& w: " OX5\̱l/aD^ |qE=8Wg,~ʨhI6!I_Ù \Ȼb O&c-agw dKcŖٛ(unb6G~:)<p)!Vw0Zs c;?E;=c%wXfr&hPNf]E"`CQM{ߪx/Awxh{cODеaYSJؖnKkyDIs^tL[t`%g'l{$to9yeWXJxM`@`qX{*GꠝF8$n]N16-|X[~fQͤPtX 'UXcۋSw$Bj  -<gOfaVYx[UyE;lʵ:^zmM>AtD\5ߩ`oDIv*eg& _3~Dc@zJtG$`\%C)3H 3?%{2>AVheN#M|Hd_@1LREם-Z;`P\Uѱ{0+4rtAΝL*Y/h5oI[ۀ*L~ND9{{$ck1:(5Nmx}Og(Tȝ)=l??r,j^vSP# 2w>Z|.ъ@uj'=2A:t&h(& X8%Ax{fw- 39Wi[*lEeZ>?%0`]OeK hd2o ϖK2/.E,Q!Y찂lB%RB{fЌ!9}` ,8 7r&sUg6\YȻJBl8@kE?/neڭQRefJsN{":U |dx-xN "꭯Z)_i_PD'۝+jwN_v0[4D<Р"q_ض$d{3˱Vu*1|<ؾp ҷ3L?"0 *]#+o R=2CncnR`;{2W\E跓2?YNR hW@/dI˳D{WG+b" \/`La]Б\S1}D4OS2"NWoW'Z`jрHkK>.*݆ޙT5-QXR'숓^=;*Z(!SJ{{c#ꦚT)XZ嗋ѣͥ nK6'Ij$ol˒ $45UJw,{>b2!L69ıXȗ~]. !*N#W9PF0\F jX:9' vC?'Ƀl 9)rI4nu1 EI~b[\ U Mh^)\eF[clf"n|'oTog_>Lut;gHǧof(}9-O"zJ;[Pޠ]1狁<0Ԡktx|"BY YHœ$i&D̖kO MDs"cܘ73C,skU0ÛHF2Y'3F{ZX!lL x83ToOg︣sRUoDE 9K卢;yUa'gXzҘ%,zEu}a@>4YIggCywGҷ|լjJ.z?MY/Ru^K,b5{Os m21. Sn6QGNAkKp91@hA@:ᣇ57ǩu/IJ9s\]68R;JVe!^!b,%}Ib#~hfo%r}K.\ސ&ޗ:L<2_'ѢgRFgVIrUU Tj*5z%m-PN4L$) U\ep ih5N,< _m>|kgR>.طtJ? Zf/7#%U,"^"¹p.̳g)}ԣr\4%A4a5=VW5a13}HlNJ.*O? qKhM("j0Zp_Gb7Um%y^zA `٤˙FLNЄI2JV?E >cXG:cu վF76{F镉V{JZaz9a5X1PMa`W5EgN=i\Bz#b>< SZx=Z+ɮ۩`4TDoTynf-= 0 ^O?EPjj|Oj= P,<:&l>$zVJ33flHq\;Xء4^_ώvtUE!Ÿdai05b r d'Y^ڡ3~<+փ^Оn':H'x[ 3_7a?j_n kƴj[{12?#gұ|c Ua n^)W\A#ĔXa<2rXlQq5ߺ(-_,Ke:e))5x6b+&;y *ATRp I.\{ɜo(H}O ̌,7փ6C;7~B+~duS{Nz>~=Cܭ(%3\iUґVIG)n=k=c4vţ{ ~1]|GCj#ǧg{NOn6v4\~C~> l;w3TB" ՈRqt60R9e@VEzZ,g;PlYfq ;w_4 tt"dCfیwaoDYi]L? ~:&E) %ZZ$G@]؛vVYx]n]aWRu~5!D3&yt)&ҐbK?WE%noDW)ŌΨS%z.(;((|$ 2!ꘃB8DƽhX ~ߍg8#E*jn;5ʝRBO0;Kj*דK8J2K%1z 3a._a;Yp"Ft+4զ"h;|dxvhެdkOjС@ؐ]Sp0|Y9li.`dw/`thM}.${ZZ^g(rP[niVqv3ƒR+JlS޼])s91 r\3%|~ڭ-8u«1=Fc! whtRQi*\hxz0 f,V7WGw۸GUpqr{gVZ 31wŹϐ0OI,7Y@^2;/|*:GCSweq,ԳH ^Wf?^7ѱe{>イ! 2L˵q? $bf"rVe S>P#b(z_,eTF_?;sʭɗdzl[]5 Su^EcW[@kp%+GF6jJ^:O7nߦ\t,; jR'AC#~"PQV 7h.j^ og-[-*l0'<(ɠgV tWZGBWi5r6V겫tuR0kZmM7̩5AZ!^  S`O@_b @CXOVLOI_A$ą =CP_"%DS( DN$&َSϸ2t%=HP@h;Φ7|\5g>*mP a|CPzzۂN{| `MDOb{O["%9W|4tjQ1I;U~?23ε* ^4ֆ=5YNNĭs o˫>.3G _5ao.= <4<8(Zth&Qe@HSo# ;lYVU;\kMZAe;7wfP-ԥ TM ?su/=rjt:<]iJ?>OOD({#7(лc.v)^Ju>T\.+uίqt 1L\o1`奈7Ƌ+\:/=6Nîl7Y৬6_ 3Uozȹ$3d_S1JsIiַemSNg̉C/ F/ÁFBsM^y帎m* x܃_t֥ď'@b-"؇4%:UWPAL8}WV쨚Ld\=vThm\ÖoH IÈ⊕lʷbdmG7p د]/=;{24lr~ VVꏭ^Q ڜAؾY8fȗKA6#i$F53$h=2p9J`E57t}O٩\ǣ&3* o x"&(mQ*$hS:_ǀ:+lM7ڇkZ9cqr=Kھ,ig٢FAgEN㶡-ۅVߤ2 _z~Uۦ2CPagoSN%~8̙_)_|˘NϏHwEAQݑH⭜| }w!dH}-W5_X}ˠʙ x'tܙ߽Jz͙sghW*!>V.!V@ |C,a9Ug/#6R:+TMZNIT.7s(2J=TF_J}kyU"y8ͣQj9U=xTBvWaga>|xWP;F'^4i4E5PsNqYL ## K,5ܞ gpX(K5Tڜg#0Lx6?umg?at i!YÕ ]JN. ]rHÎT7E\J}d M ֦g6 ڏk', bϙ9ίu,.TA Uܿ̈́LUN\ 3UQÂbXѬ2|)e׺}&Rf7"'w^,?XwLW/}ӕ7aAuNEAO;z AS9IPԽ,{[\p$]V/`>D(_ꙹ=t{ڢuKT0 !Ȋ&"AGw:8<#MWQ%P-WY{3jě%}K9tÈNobҡ.r$#?JKp9 G0"aiFU ~!rsJ5ƅp[=:> {zj&0Wa _Z.h<7nv(`3lWLڣ/%l-R01__p;:eN{QZB04[ kU*gz6؄=pb  C::^8E#:C 3xh4sjKw({]0|TV m Z\#Ncb4Sѽ|"K7kV^ZHo {IP'̲#26/\$\հt[:VkNI卸h]qu.NUi?=zw^d~o٘NJ}2: [ 9Xq5 =lUGtz/o#`R泥NJsteD8P(5`i.>֌s|^IX`a bn`2yO8?_[ FC_o+B=r`t<~sڐ[^P`g몁De'n6.qq#l><\N6(1 AEuK2^LyC8~0, FL!W(}s79oD(a)!Ȟb! 54:[VrOyMxTcD(_6ke  ;_K0|e~j l+~f`L[yqZw\lV>Jr(|H6/4po<5K $yo ZzE_Nܿ1h6z)$T *n*.tkЈ.;3'OΚP*vl\M5l^=7X*,;&T}a? i~w_` ;vh @T ӕn>Xj)tmK|RBIf,^:D^֧ii]\H5.{n [la&|H ~z'Yn0qcsyN?#b1hG9[nfg)T4qׅ \+\XJr; b0y dkg 3X||SDp=}eK pg?+c2bOpߟss|jnx$ T7NfHԾsJ )9JZ S$PtK<4Y%i`Qw =3T qO^rHQ5b"Nc8f  g|۴mY{R=L^ևe$jDGҾ4D1k輢Ě !1<)²gҦ)|YiVw#qs!~qOΚ  uC1$>]Q;"T1imb>u&u{U|.}C<|FIQb@0 ˒Ja,N}p׃_^RqвMRXApm%2fߢkkQb endstream endobj 333 0 obj << /Length1 725 /Length2 32247 /Length3 0 /Length 32739 /Filter /FlateDecode >> stream xlc.]-\.l۶m)kme۶m۶]ݷύs31f1ǚV$)=@YLET`dag+b"P( aH ,̝()$P64p Ps06'qqqpqtspH p2ZX4% (T Ckg#k c c#΁?ſ89 bv6*br**&2:9r;9; 2n` L,f0MԎ?ag!?4$0v3P;;dL6t2G A[cOQ ``N΀YhϮZiK K*P;-jklgbakF􏞆&wZ?_.(:9Xh3kD(!!;7OZ&Zf6FFfVFfE`o pì-sY6̖S 5.t \.nұH%Eؒ5IXr 5W79^ѣy3.ua>?:*Hzf"듸0&d?^kNQ9(QEΥ/9}E &Wue4Rd'&bVu Gނ6wiSMB ӛѯg`oB4z1-Hi 2 ,Oyyl#27 FFؑrc܋MnS`(:}b([7^MKoW;-<<+;bᶪ9xha:@qFKҰeɾGri8zx[;c!Og+I,Wv+:ITDx9Ҽ]I` wmK+8oGu3ttuVxѸ=o}o=JRlc4-V [x^t}n4Rem#c 9&*'j4h&(#޻ڏlC~Hkr k)-C?g I 0~iqccWGȤї4 }m\cW*&yCD]]Gwl=$tt0!`dAێacj@ @aUjx!5ֻǜCOT@V&13+̱O:4K3.Ym6L11NVۦֲ&#)*" ):,E~ jݾcwDtIPařW]ZwLc3؃ɨwNQA4^#;.Ux]pbnu>K 1( 5d*$f.*5w0Ľs*'4k `({˜qar'e 'ue1P4 jSE-qڋN2ZnOHvn7I&[`[IT|٥3_ܬ{^ag-!έe^aZK,q 2b#nLaEeƉ8$lQsSR:O@n |UOCy4Nӝ!GfiFĂq[|d%Om?L{_A܂GsjDT>QrdjC\#ćk<_P)2p o}ыA#ci=s|O^j $ڨ8MmK$5}ԭz+J a,Vt3m%SL`6F@=u+Kۡ> H;=wqTrP<s6MXr7{S|f,z.DtJ/Do% zz_V `Cx1IiA'$zbܦe q5xN"(43&RErQsSsώ*X& 08O۴cw}7X%ۧSk:{7UpNת3OCg4.B; /ॶ4l@V,/nnL@ׂq[Mdže܆5Cߒkl(@cdDaFSB sFyㄻ@ .ϟ&ߔq F*$Joݙ*'DKT0:z-#(dWB,Jo9Q\=w׭4NT˶޻me6j=v(( EյK =zi9Ľ+lsTwa*hxfs0د8J>ףW4s*Gz[bKT/_0N@nqL#pMUwGҸz lTQi$&aC)T'撈e&TV' z w C%}ոq cMDV6OɝG:<;qIQ@DDYe^*\;sKF*}&?Q4v_ IZ-(1(ȳ_[pFA dg S\CzTᣫ[[md2"|QQu>ȅnc3AtLi˴_ċ!{fb ׇJ1J(qFlB$(JM~53Gup-}=E?4_*Tr:t%>Aգsk)lX.kLɁ\x֦g%Za`>nHf{ߊ.dW@ ڍk6Un ظ|!kVtwx6W7lܰnZ[=1K8@ZBI5޻Cy~@\`RVks\b4x)En-7ڸ̔ d>=T&$vwcwqu^p?dɅJ!C5[ 8W,3B%EsC #t(Ӓ] >uHY%#R J露8XXbzBn%=qrmR_9ȧrΰ輓R1 F4+#U~PGZ,e.DHRwnjL%=^G+0oiϯΊ\/DKQj{="^?ǔ.=$D_ #+Eex- qR5EQbC3v؆% *d!i̹ ۏ?O%|wUx*H1B-MP(>vׇӾr이*c]MgHYotP/nlbb'VJT΋bI2=<)Б?&kn7_xn{s-h7^x 2'U$D60&)0IGqY6Ee}oK,m` ҵiƞK=%h~Y)χoBxCƺjl⊺yI?TXF9H PѡYTXJ6=2G*{?#HXV)wiB5䍣&}RVduifie+$CƠ6wW 627,c_.=S,!9~0`Y&ң9B wB/}`i3-ݴpR- BBf}fD,Um:Xl{kUFQ uНW"ʰyn2;&s7䊩GnsIr }zF~dsxY )de̤jԅ"$.JN&|rQgJFtӎƠ4 NCNb6OO;k>z u2TX'\ xXJjVp]Ecz6,v$lxO Οi#a3[+>iYhJ,96T^@'T)==3I,xH A*R0vxc>XJTgH8RxE6\Pd(̩lQCa5#! <2XK./nz0:S%nGA c?/`! /BlxkSs99RLl4PWA֪5,X&ti-ѿ롨[b^aA"MPDȂD刱dﶉ;kʴG#+ wɨ(7fR xLuTsKa!JA+14 z'e2yz |,vFt d}"%#|6S\Jς'+َr;]$ Hz+7(,,`ܱvʊΜBg^ӵxK! qOvõ(EC9)Z cq_)9Z (uND },.92T,ƆdᏔ{+'.2Ukooe?#(劦Yxq=v?Wf&v(07$QcD MFZ0'ҲKR4LrN%ZWf}F̖o-c6RMiCcNPAH)3\ Qx {[+i#GilY=ȧejDR“BrI=ue];w ')hX~:mˋA)Y,Hk(~Լ[ v9zXEhy89@yBmGVTKwr`Sen9fٝ.>9Fg\uSΒACb:H.:ɲ}=zi.CF~q4O/W8t"V>%L8=!HQZoN-Ygc ~\DQ)Y\>+r|5i߿oCжm.\)!N.U4I9MӮa5'1NZ,囇Fܹ_MVc&:JʖH{2mwnp ̗!u:uGvr6e1php FCٸ*]T]qj=Z ׶dW?( ,eY0*+(ǟT- [mR*f''VP0d\V:!}>Mlh>jј5؇5#pg×oq=G1Rj ˫P;BnEE;S>G9S-10VӍhYL&J,lnuߢӠ:E>]zOECKK ڲYڅSp%npN:]y$(Wolgh@@gwS!YnCBgkS B2o4#ozQ!6sr[=Σ' V|"2vAKǣ& S9 My[`a,^ƴLxhHIpbi> [6w\{ʪg%4jEH!ߞʫT#_nM؉To#?aɍh5ܡ߼L 7_ xe~ΩΣO t:ӲțkkfoA2~n[$!)mhs#wPL+y{$a ii ˝˰ml/9%W}̝R^/fW)ȿ&s-+4,Y={A0jTGbB\{c@GoAk"],@BAAٰlQ^r,ۈOV{V.73W:p9v 1 y/>Ҭs=尸pXʭts":بkVHKJ?>!pHU1E>sdڏ;&:gj12`%ױK-/qq(6+tž@lIUF:{fg"} fMaqw&+5žnr, QQSs#:I6mW L)vT^Ml ή$􎬞I,ܿC?YQju9ˁ`uQR ~j_km݄VЊ5˥|G ld7ן  r %mOݐ.: =g/ρǣs fB >p- q`\?Mנ+pH?)['Rkp``xA 2V=VbܽKXk{H5#KpG@R4-Lڈ7U%\چJl} Z)y ;d?&NvlJ|X D~-Y|3>R"toC~Q w6ƦC,kLck TRNȢkBVfaj\P٪?g0Q5~՚ f$<%~GD SY :`Q%]~?:'Z2kH% ece<<ʘ8z ; $@* ?UZ }6vvl' k̖ wM_ Bvl~'4!٢G*sW;'rDfȞn ѣ>|Pu֕ẫb7VO:,';e"v)]f$[(QyȰXdmz%ز)4ܖnN]kF=`8zC/X 8clcZۘpt,w3ywrɝ$gN#\|_#c UliDM_w$U7o=iź]4- pkأ!Μ[ 9Y#+[lbdD)NT5P=} }RT3:V=g3s&i08izQ/ [ ̅x0Bߍ%b*n;rzlx1.Ty CHJVQB*ů9zI*' .,d'z3G.Qro4u{_M 0`P̬uEjMlA*`*e~#}I3;418(n16!->Ū\eȦmi%Bć%-F ͓(4-Y$06֚zz1aj:Udf6]dq||Ys 1^iw"v//Y8Lymm/u:+~F՝T׉CRgT1'* O_v4"\X8r}؜62r  ~Jkh(^\yn)4Ӵp_"L%ڿR}J6̣ v$ mROnrXAv{fX `Š{_9c8Oӛ@ϭqG=9_`v ҷN>泋&ީ0% S_Hb]$ Go'IS^6-'hF!틹WѮvFLYW6,-BZu G˴t!& ]:UuĿh}cuDbnEIEaG FRW!u(TX+2Uč$hPuF9v .`YqW.,zW۴ pbVeH?mD=vđ%G @p4TBۺatW/i:&c o/).Nxb]2D HnZbSs>laS7NU&[A?Jg~xu1"d42a_wA4Jbq\Uh70e\5@jNu:(`kK}赌}i+^иl2`2#I @h$sNcc3x-ɕ~׼z7O2eX;My\9] 8OA)*!eYE;„{3Yvt@,BKMUJmIjk \]ۧ+ƁJh8z`D:t*`']VMꂍB,5\R^_ڲOL0*%鱝U3ˠńv 1a>.l/ M<ҐN?d)DNtn"OwbQ8cjnͥ5ƥv9nR77 ,qcdMPFI/jgY0c YHA{I3"[HXaLS^V伙\2S[Eл0Z9s37{#p~ W2LYztRa =T߰ku=*:Z}1!khc/joԿn;]s# ~ Xw".~35B3uF(*J[Qw_-D: MxXDx{MYS@ UUm(}n'vڢ VL A7:,48'rY gץq3'=c/V1k\rVtR|Fbh rǦcM|"&,Jt.`2 o9c\^SSUbdU2AdO}1WtumU9?G"ocpOڪ#{6/5ԙ*qէ\ԜZct_idsk۔AָFu$c.uC'36,-Զ?cU̞ Ǒx@>& )X*' du]^^JN%ow/dcۻtV716+wo AYЍ0.gnOzE;jSUج32w{ ~ҎQb w)D8w4ُ=;~ZN|9^X%/EB蟈6iz yLh3%m;=N[H,߹P䩒Uߢ.E&omv&S":'J4w+k'`ܳgpC&Lw{P,&"@yThFF*3>8釉z! 1p Q`yF7vtB{jd0U}=4٤^f[u.@ u O#Ͽ+J'NsܧWp\!n)W<6*K_ղrIpFbI;»V6:P_YGYŜiნA^/0ҌvCzGV~@6Fz4?y *ڑ I׍*1ahf 5Y<FꢍVi2u okRxFU8;ֽ}Ġ_`oD"6QZaĻׂF! xlss$ŕ IKY a$G e?d؎srzJIBf|I4ebaXzC 1D:)<)83ߋFS't:E6m ! Е6/̣RImzx60-KF>Mh#(vPYNDaj(6 %͸pKO˳).8ƉR.zJ *q% ׳zoBL>^I@Nra/ڋ %U5gve]ץylšW[hXUKjDR#%J;[/s*%M^8Y 5'@0LTDWJ"t1]]!چ61(E|ċy0%jmsU8fbgN^a~Nq=rY ^kiъ-@礸QSu9|pdbSIo9ONh $iGo2yt9m-6dMul$Va̋;Ļ[dX;:5#I#-iq@kFĺ;zq9e\(AN!gsbW6X+RP$%<ր3,}Ouߞܺ v{>$dQY'X9Px2T~_lӠ<26OmFZְohfɨS<0FdCQS=c dqrX/5,ټ!_ijDV.YB/{o(2\B@:!L&A aSOEo%ّ$? K1pUj*$ak^TɜV;m_Δ]&(; eǙ7puW|@ĄPw))Y8Dc8ǐcaP/RꭠIQvqO^Okyl05%idza3h?PƙCg>1ƵO ,ğ H6/k6b7B;LZ1r8Scצp}rS0IpֻgnG?cxVЙj ܢ 4S;MZ4Y Ś-J\jSPı>\Bn?C廑Cf=$L\V:ٽ1orvStqt4zt,$][[[.!NYTW.>C>Zgmn9PR>s~lYIk7{;ZȻKs`BQ ׭fl rOX_v/5D+*Wr#`?U6%m&ϘTZӞ׭mV[S9uʏYWs714%6oSgǾBxKqA?QYuBGD>}iw-wzY QPDdq5D#@BnF=zn/ɑS+& EuQQ=9mYh6]i۶Ӷm۶m۶mvm["F5g^`-yL1Q K*0*+$ڒqLn_7>J''籂I#=O$ #i\`]x8nLX<9P8Q^|2؝okk2•egwA2létl8Ȳ`^y-Zf7x=E,sX> ҝh%z[SJRf*\.D.g:4jWS߸H۬)e N"-ɮn7s{7<{Z W=t=+]%M_A#QJӦRdC&-zӧq5M^Bt7S2]|Da,A$ ~/=̋JN(pړ#uGbxʺVIɪ)ۇ?fQ3x)ټ\J%҄$]dc"05BS/2 7IrּDQz)kۀRW] ]1"#L̑e 0cx:<ls*#Ӛx" ]2Zf yƵK/ը!b"Ǣ}ҩ+дErq9ux^L86)̬O6'У I-}velklMc8͓Ukmu7c!ūlm|pj9@"gk0UdKwojp{Vod^ Kt@4S[?i+%-[=Of6;%˾o-3PVg: sbC_dp$~OuΊ΃п<)"pRBXAGl:ͩ!@ܻƇny"@yNV .)Жk ?L7/0dribP2.0`gwSj87dֵ3sk£4mM`WgFKoMf',]4aޡd%ÿZ0yE78wfnZ4ϿcIUьِ[od-%7*~5B!}[ӚXOHh3H߷~h4Ýir:wߟ )I?vI,s$ڬ!qCCa4\yg3b9؎!ߛ'Q*p d~n),. ɠŅr +(+ɯFT_[ ),73K ⃙Jt3 )0!I[]8oeBFckI`o*+kvjTR;^a3xX8dDi0y5)jH~ mܧnbWϬ2ػzR̐ċ Fs:G>O(z$*?gׅQ(#¸7qy"búIrNˎh%-qc!ns Bn8u_l{'1M#KJ'YYd$xox&Ch/'SZK*B.$—yx*l޷bAJ4o2K.-rIxr- oD{>8_: bOfͫ7jX Iv~FbUi h"霈գt>&H;v5 T?c0mͺ?l?hOSQ5+?9H Ks;3kF@݉82ʓhjjakubJ2t.p ޙh˂|mr{$<40eOsөVu]=ȟ}"5Y#k9U2N탯낋kCDEϚm8yWdh@t!ΦSB eG xUS$J_wf#/{5zĥC).bjx}ĢTx(y`L5|mpY_J^?1rWcBTV>3֔ k펅NA(z%5`_>Ljz`;AJAPa[fg+სƈT< =: v%dzj(N9C"0 lnS_gOW} =_7]EВo0籄 {tTծ7];۩ďlBtJ19']a:=LԔ< 6b~ud_^CAb7O?d4r~]hةk0eҜNIe!뷕ek߫rq?ÉۍMNߋV$bW]wX G:C ˆ ^_Q03U=( *ٷsOgn+u.6#醘[Pu8\0L=rH*&C8?𹧏04f½EPx iyI``(%@GJb.&J|NɎǢ$ĖB"L/T4z6eE9 {@2V(7S)ATt<$z'W.Bc`12.Cq]+P5{]u=!a}Ct?aC𤓸=Pl|{iLjud~8{a=^(qfD$aAKEYEfQR]H=OxYA|1ڙvSܧ֟.B0GX?.\m@3qJ qݍ;>D8Ωoz`iq;'"ђ1LWmm'g:cg֕B# \*a^(\Z|nSV2x%cE964wn,j~<03Ty`'Z6sS"nRSk#T 5Ɋ^TN~t5"z-g$4zDІ,\qcY^ft`?0K=aD-tY~[,B&c3*n-{ 1ʮs^ϱ̓N2~),{W&o- /+u7yғK:T5o cїAwN*\xɍF-ft \ꞓm/J!1 m\^Bo]WޗsE]mӨCw+V福|%9O#Ow|?$ ; '"ڐ:M>!2w| tDtfj:pw@gLe4(+rwq٢>õmٝ:,kA:@jX(r+Q]15]b8g#1m*l&d.4LAShe tzH X/oi;H𜈌.8;xyKoTFf"MR;f0WueXH]jL5u,H@xd4vw>݊ צpݣn[W~13a,>n;:<_Vqczρ W:ćj]}㝒hJ4M7nAXIӤk l_yvqJyl_h/Kud !"^jHZr?T[sBaϼ2|+og$R_~ԭ|1m*x"Ⱦb8T`$՞),.be4[i1^{W'83*jgO$nLItu(w"fXϼe, U]4%Mr K&.Nb.ljl3jp%fk$:SCO9kLLA:V#eOH.64բazɠP:LGXcEC5~>"F!o'@rkNx|U@"/VMc; 4,`LblV'˨W}J(K.)GKM]tQ]1={?rS|cX4[kܰ;_Cy_d ^H^~=fu@yt3g |&nhZ e^{3q"H2pwʈ'đ"<سLs+:?Zʣ.lS IsRbP]4!Vڰ')q-*bvWAقKAZ픭؛m[UB“}!8o_* ͐PӇ֬Mɪ>␹Z7E%dK@Po# 0<sl%R/-Gd~ۧ+%0Y>!"LR(މ<s_ۧςbiBt[&[%|Z­h{28%-]%粦yRrrF. S?*rj`% 8,KjG3p2['2 8 ZձZXG0t@hGV ;Ĝ(ic^K>d2dGHy,{$1t$``uÍ:2JAn*00N IzݢmbJbO.c5e5iQ*%I%ٶZvvd J!~'\TV;e<#H!&6(*(~nkըѕhXPf>P쀕.<#ci!gkVu,+/Y?9#P]'2RN/Dc|4zfM^ pz^MgZf!![Kq7 @K>R%JAxj>ą Yl]c ij;Q$ԜdJX@.KyT?b.ҿ$W뿝y ΦS+Yˋo:!1 rr>(6> i3trD:1:. %/s1(%6Ƕ^TfC.Ǒk_Ի{ 3hЬ{J{i6nժZ YaŦ[28RDki+ntUyk%L(eX-HxlbGv߂yy#TNjTt~R| "7ϖ1U_t3zOlq]]P+/yy_Ǯp򯏠> ; ٓq]Sg~ ,Mf6@%}Jd9Χ9 ҷWқX]m#aqf HT,FI>7R:2M3%&ϗ @)[ $H"$wJ&|L̿*jm"r䴫臀1_NgYlu**ڗL;C{ᬘP A ^4< Bsb`'5}^XDS9 SfG)߁X`t0mv%gAI?h[nJY~V ߅WuK36ES\%pS`[H?SԌMO{X`:͸1NI^$ ^-M͒^u٬: ?Qʭ\Z SmYrSwI曩K}󨼇UZ/ ͿyG32~_M 6~s҂.>!> ~\EHds)I|;Rk:sH줇*A>"-޿{F7 ?v#k{ ľ1V[ֵ$ƉLԬy#,ޅ4++'f[/9o _(PGNp͸ K0|ېn~,46GNae& \. J8#W.jG&ka|y!0O7áoKH0ubQBkHd[rRkjqmHŇRdB#-d/D4::Sۆ'=fHsvr 39l[C"0X8c]uc4Cyj#kޏ5Nu"&l5~/Q|>)Nmt˼q$* {kɰ+YO>y$ xK ̇s:MU& z!ntDwsY֒8D 2DV7 n&rk =?HCjC\s"/(`Z-$]kMpr?O R?цf4 K_ƘȘس4'1NZuJR.?g;FǨ6+Iʏ9vF`/dJϒpoTvQ>:*jyd!b]hUgA ˗5blN~g*yl]e&;Se˶iF'ӶDJ 6;Ď%\I$@%MzUo4+%O0Ձoz!;IG7$ b*mr?0.3EAEڃ84]"?ba'hYedLkXj=Y|1UU\ubN,[nS .?0:YšeLҟK|eD͇XU~2 udm}H%[AjJOic;=LvW"9ܳ7b,[E'\ }e# ](WFD`D*D5}>\7Yif]U {Rd80_z1/k)DHʯ#[KPPD t|t% 8Ж/e]Pc&upi=`>j>Ӱ>~ E $k /+i]+v\\ NMOЌI 8氛mfUe˧pO/\URHflb)zӲQ [3>(dYf{~,𱬽2-(r1t~TiigbVZP<*[n:Kis74Y\4t5,y1s=ϡolʍbg7O#< Ly= P$s0zud~v˒!X AikF˦{Yѧ\X  Ez*[ɻ*g ٖٗ4T#ܔzO@NlȲoAHciVY.<:$Q"~23IF` 4ˤT_92jvgAyC8؄/Pi~)x.yj=2ٹ&.ShN3/k=Ζo`xn{h-apcbxJ3OlH@ R1QwA&2Zm=B0H j@-F@#h!Axw eK/:?_3kU(A'\8EX0B|y{!a?翸 sY1|fض:6˥95Q,-zA,w30hVYoCƃ؄ԮʿٱWD2Vhܫ oc;/MhkCfT7ZόaNB?.{7Y&#VG6bPeR& 1|.D g%>1nH*hUXv,@iq+." J幏PD*wj/)ðmv47`DD=dYdd')\?9MtrRsۄAEje?ˇ mm?ӓϚ569NQkvyg&/Ư:ڸ$nӡ32Up4V&ztZ]ȷCs~VPxz r4RGT c3C@%RւЁ:10H-GUzg5E uqVjdi"p 1?ߢ&[ oVs'ICI/*>'H_wVBsCmC `=?` ~.AH4you -g_#[ ,gjlMhc%<] zN))q(>M߂g: e_k=ɯ>{\bpڡ`/^RClGw6`RobXza:=8 Bȣrq.$B7P(zfZBG2XGT A&G0M0zR:AO9M{ؚ|w tބ(@$F>i*pf!%4+ m`u\\}iͤ7e'gL 0X~W1p(V p7m{6̤D;ځ6u+gpmRTޥ\ФYfdۣ.GE[X18j_Y#I('OЏgWU &(v>,pxR1ccĠ;6B6hs j++,oڙF:Μt(Rg@r9|ޚgji0Y˜l J8 VL#h[FTh G*{ގ|S"l>9ܧ\nC[F|_UA긣=I9 Q6hؚc _3Eː{U| 8_*7[6`!f3ƥ+&ɅZ%P#9K`x"jg-wK*)_=ʵT%qTB ,נ&t*WoiA!@Rw r_[SWۤi.Hc}> ތ0eNL(YU2V9|ʊ=VqNY<"V8y`$wy8҆bũw2"f&RS&%PygtH_ LI&nA;<.'K 7)xЯ&8y.n1 z_v˜k0ߟu)БfʥǃW Di-OZ,zo>p#fH1&]2ɆGB=[{esЖjU J dL%XCyvJbib.&b{I貌1uȯ1Fя`E_<9w8N"p+be84+ ]-³xYDrwY$[*1\t&2ʪv[xWgs.zTImOLwGcsfBɺC-mYIOh/Ŀ ]/6P Wa1~qͻ4CCl>llE H^Ŧǰ0-~ o جͼ[TDž&%Y>r+S'6ŽzN\U 3/Zn vBiHvs#W7t=.p< u )FȞy"%(X6͡`[@ |Q̻`M \Ɇmx|7z[d^88d|b 7"ǝz8m9Bg}Ot1.Lf`L}Ҟ2jh ch(좽-jC+?,yHj)HD4Yh2~*ןv9h]~Cbd׃ݏC2G/XFG zf=ei23=h_bDb e͌P{ }f"!0؛/}/M}=dۯr؉mfߵ:+fl_DލN-!<jP9'ٜudl;7qɠf GBB**2@鐳yAO_ %x!pIӘ)'.H}Z#CzbUV-ugPwU}ě"Wr{ҚGiC"șIn CuU4>,.UӲ[9[bdi&QR(psN>^d6vUnm+dKZdqx.MkȚF3>aZ=Iu oDE\ vt;bx} jZ %깈\Ƥ-S90 z{1Kڲbٿ9[ɢI83D}57׭G+.v:eS3w.FkbÊY 2?)ɧCrB5]Ƅ5۞uK49y*:=Ew&#KJӺ\Zrxv_tSIhǕjgiV:v% J/D![?æS]Ӌ=Q%OHiN|oKxg(N|&nBzjJI/)#ExK/|_o:M_CY;LTvWzOhp4ی`6D[RʚϒJap-)rE,d]?gc?wc8 L_X-vEB?wˍO]1q _ v>{OB17p%\AWe,|I~/)$ %ieMɲhIХE%9 c$%na'"b #=2^.;AH=ѹwDZ7n 5{A{^AIAz'BL88ВX^xEu䤶(O;Tl\mӏ*k_mvL.>to>;U Y'Ie?#.ēnO6{95gS@gEZjjӰHo0,T'mqe,QohnF4VpK ݋O7n.Ƅӕ*bלDLpJ0"%-ˍ2U0G rQCʢ 풻E'؇H,׫]7, DB>_}j'l|4IOhIZH"oAJ=zڍR2 lP\喇\vHE4wNU%*-kX]O@`OW*n|ꭔX{-[[t)`%9@Q | +rL =D$B,-5~̒JɼtGzv󟄉IjlЧI|X]iIqb+,NE)6(yW XJp\*ΞXgK]_܍' ĭ m`Q_ǃ0b!SJ</kLԏا@ov2W}(#YӸȟJOa~FB`64W ͦ`9b4YE5ESV=B;o0* o3pin|J%Kt4 4K<:Q 9O䈬zt&h)S_[S/5G,L&<ѧA@p ҇Sȑ2 P2컃w倏hddc@ÁUTi^NdKUOD+Y3׆܂Ǟh,}b9O,CGصP1KΞ`0UdN᜙ケmyc[#r/)ٳͽ|2p8uIMi<Ӥ#4ث'\?UswsplNaue ~zVR@hG Xѝ 'ٙ#˂>MއE(x#?7RU{[dET 2|`+zM^MꚥwNt4\6H?@+6 {" Mcy$R\{d>SmDMi;S %qxٌ_-d9mC: %(6a3MT  s%L$]c7 ;H7@ȞO7bVoMdnF[`GV̍.n](ZLz,w~Ӗ<`#kԑE'N2|Xc|(,p=t+7dmǔ5=?56Ł 󨛿x9Sf-=\hPYoRHDL < |fkF,A_,IKنL֕36 zٜ=d/hzIFJ/A'MI6i ^(tX3]8GCL.tq( 69"jkmhFOYW8s8&AoіE˘&s+ %SYGzߑ&RY}Sbi;@D-{,Cޖj6{r?3Rέ։R_5O;?J endstream endobj 335 0 obj << /Length1 1608 /Length2 4180 /Length3 0 /Length 4963 /Filter /FlateDecode >> stream xڭTy8m" eʾEBX˘13 Y'KReS !K%%ox{<\}^u} L$58.KFhg k( SAPP86P$F0UVVfpxwщ\7K9LOюX@H, _4C"@1H@JH3!H 8`p GbHQ#? "ЇXDH8| GCIpFM 0,<@c!;"'G$4h#&a"g"ppÖbdrCc F:h"s'& #.D4/# 0H" C>_}= ǸeDDbPR `rM8\e>\}, G" G9Q2 Ÿ$AG"D;9y7q?.zu``/ 0ߘ sFc&D(OǠu$K!#%ME!&h @0cHE<# )[ =QEΜ,oi=S]_ӣ,$sw<ؿC8ĹJr^SH/*D@6edZeC EWߎ0܅@ +zt-i-9醄3 ߊ@*Hil׶in g+ *u}7l;E.O=5"T$>/}#)ak8Fc(c1]:J9MQ_T_xfox\#*RӅisBg67߷45~]-^",(nOY߻+8oh`{/ӑ+ ~mS  h Ҿi'ߨz?/SAPBZ{f [hf/tL]NK|_ VT;Km݇f;\nM[sCcETeI{o:υUv+R˫o8?ȣ){V3SL8+ UF*K V6w ~ak*5kݡD;t9onW!%ٙuZ{2d>8)Q=% ϵڞy )LF"ڼ# 5C]kptVM.]0Zh BwhI.𫗃/u s)oĂ_LZJ'Wtk_9 +JXT0oýYIp8̌_/hI촫!r(+EM\+V\`2%84ާdޏ?>|`+z2~)'O^Z@LD_vQf|n 5F!te`lelIMZ#Cd$simW' ;+\Hcڂ{9ps+"kp286/R,(uI%vA^\kӷ4NU&MNgϊW9SZ̼ۛ;m>ixbZ7U> U{ 67UZC-#kku`2AiGb3]Jf%cHM\H\nT})TVMeSbCYT&v  u xzN5E< ddƿ`((N^w1$ *Yo0b_c8>g0j6l|kzg&×~% y~Y2@eH2:Reǩ: F^ّ>v_6!-sYmꬡ]}Aǽn)*)-X 3SS^VfgaDnY90*@3'NhmWQ([S-^< _2²8,bIT9]WvǗo%|N8*ai9Rg!FTcD1Nv1 x(35ޗ`8}~؝;DEK͘:UΫ Q ~Z/mM2x<;@+Z[龷AQ.o絭ŝY .ݐh[qD)Ԅ -zq8w{lu/ɇo SoD,p~ln8~|Bސғ2FnGE;|{oJKOkd_`T}jCEvy X%;\GL zWgzÜI~-EEX8"l#!}?DZ2Qm~M?c0J_4ƋQq.eRx|QGWh#鐸o`+#j8Gd2en͌Sy_ZuX”,.'RwX\z"xh olז->ZPYC+4~=ťND"{TF5(oz&@v稶K0rt"'րcdꘜEN}B!7˪' يˢyMDŽS?n<Ց8jPHwYھpSwciSڧQEa6.{SA"#\3 JTR ):ɡhȇQDqچJ#@*QNhsR;b|u>!DC;l3e#介t KO6Uu5nsӰ5T^ѩ1Zp]> stream xuTygs-ڸ}MtEQaӴPީz 2vMK4;қ,Yn4+ë:({łkǪ-oE8)ԸO,i3Q`[x$CsqbcZ M!@a1$`3ɬK'RTajk"q]2w+ev]zHlUI3-}/bS/E"=vr.K{&=NȦ܋`P;kdO^NWqS#7xJj3Ks;K}6-;e-BŰ%X#60#YFO%EjIRrYL5 U$AAJIgjKq7-tb6Y)HL{|M&CINV7Ɖte} olmcU.6u$[6zZ"oUQ]ew3uJ٘'WEIRdҙ I!;d2lMgWw$.|u7;)g'U~־5l}f򀒵0i .op&bq7z/ i:'S,SmM|ʷTGwutϾj52g7uؘ22Zk]44$N~UGYfcY[)ȞKC -L=%̅2\(DC:l"hgG8j}C|WC TK1My/bir?G|m5C]%J)?5%6(M=0SKV-T6YdHKhp d֊\{!žn}W<`W=qC}M6zxrt*JLnwkDubbT.iˁ{lY+wV#dd(x67U"S̿ŦfS6Qy ǥ^H#>=}+s8ՓY(a0RMI,UFsfQ$yױ WfVݥ,PgW''Y9Tx.m .r\W'mE". ݺ M8; 4hhY~opM蠑&ϵz,dDwi?(]-lĂ 8>OX4тA`|M~04` AbG\a %a'[g3$y[F>"GGJםﴭվ;?+}e~hf((7PL7^=h&U|[dCۊbnlyG^dž*bAlb\U61&+k ]ٞDgNGNvQ*p]s]Z' ,\u-vq~FM͙, NV|~NApS\ N9wylbW$?9}d^S`.MU#h-ݻk]ۥJ߾>^؂@L\RgZJzM%<qr} 5nEKH/&+؀&(#Ak3 ҩJDaOWH&ٓd[%GK'7ho,gʹm{ܣ:[rE~q3vAqEHѱ%mE.fK1jH3"l0` /6zv'7`֏sa\ytx M OgIriF-҉oe5rTߔ ى tF М_mE.x]I+ ^/vܜ AS5$^}6Iٴp8A{ $嗬Np#Hd|DqIK_-{W# fcBJ_ i;Ƿk9vƜ&R,j%z)Ia4jNVqQph.꽪&n*u0<:(2R= <<fE\O}kz'S?加6;O7ãSCޱ&`f^l1^(L~*I&nLfȊ!>Ta?.!w̟pO&ʾ8Љi-_:͔>l^,oA3=y6eMhj{'m_tzb`Su׋+NTgɯ}J:>V=axaT[:Ey㏨;I |Ŵu,x5 "$w-k.P"Ou_bMm[C";,m3E31Iܡcs)Hd.&,uDp)8R_ۓϘ\[Le3 v)i9Vc2mWխZdb_{B6*Sݗ+Rzɥ;WfnSƸl|~Jxӵ^͸&秇,(_0z7\eA yܶ9};WmW\xW%A> stream xڭxeT\.A;4ww .{!wNpw}gΜY3w~[T=V$J ¦@ {;gFf^ HVGAhj sSP:-ČM)@ h`eSD<,-*4tte0dinxq;?BU@`fi**iK+H%@; @ giifN&vb% @@7 /=dk },As'#;8,Ll\L!7#=dd Ȫ$&FY~f&.#̇p;09y|d7 FN6@#G쿺:z#O #< GNvL͊=rS\N7adjog03);PXf#W#9/>{h #ۏǎ|,#;ǞZ4.߭5@+boc:igۙ%Hhdlb03ru;S׿[ ``af7_pC3wT IFZTXMY*} (E?wx1prY> Nf&߁Xu7rvt|woaLMUg#;ӏIO_j'U@{/Vi5عCtzX BJՊ 6y _C&xZ=^weh`Pu |hz P(۹2 kFym@}dKYEp Ɵ̵$.sZM1e`%t.>]N'/FؾG$IN7&oO\`._eEM2*h2*櫫m5DlŔ]fj% 2HJzOq1s0@˰UԴP1CuggH, 5Px0 = 9\A1YUwI-о3N--W.gœb}x8 2 FK|ͨVL1/;—\^O+ Sn+p OѝIY n 쑔hyW9:ph0SEy5P*P`A$i͵q6^(1WI$n~~NZZô&7bovUtOuVq_`Xj |f~4͸Ǚm!;)/|ƫK<=8S$f>";TJ=ץ=L%FyĸusnM' jx9I'9Xm78?p]; 'Isʫ'&J?7_lYd|2 o:ݪ?/uU=$tF~%0N92UCL0M\AX)"-Mp& տ_ӺX}IZs؅eh6}K|Jage4=*mu-DGX^l㙣g_^L-iajfwYAB_9DąާB4b&w9 j]:yh4Hi7"պH>qq~Wӵ!kr[Oo~p4%;kl1{MEt.|e'o9b;݆nɞ9Sȕ-oٗER";6js~IY3n9IV\i.p ׿&3߀y2`.h:<)sB$[R*p8ɼ 8sr ~F67yzs$)Df }Js `](nWӕI.q3|n 9 MzmD5b ?X5/}~89Q2s9Tbmrv |X8r hvwrY)4EP[F[KHO3)Ov\&JTp *xSEf>hHw0nwMQ,[y"dv2'YpX޼<˛>#ƩJ{If92Bn>Ng jԍ,Ġ]n=2iisG|٥IQe>3}s <!w. Vq{_݇*,pe_u׳%Is2$`qnZHSHщydr`l<R'&/A c y $UìwN2)m>`V5l0\V8r!#\2\ -]7@ M(xbQmO\ 5- <ؘU(_?&i&n3.d?bYie ͓U)1یϞ;1;x  &$=fVDȲ8_&Y1/Dof[ .cĉ~>vNt8l-db%>y4G5r(=jgNCH@O7)K*>W:qV:%Jrیүj!uy*`7 pZh1, %@ԫbl^" $^m3 /מvVhk hdoR~*yZ\4j .q}ӧ;C"yaH2+0יP6$`ص2]޽J LoD> 5A<M BuS" ̤]Tc`"k{r&hb<^$f"u_s ɟzke:VGȝOxY\?0</{2y)p]—fnZ?v<};ΒSDt0X<ԙ1UƨW5bΕ,$N qnϜaܟ -?ͷT 5,)H{d4~aw&>[\ǢzQx@ƫ|dL3%4xEdGMC V+򸩡n7Ty3b9Ə}h[533΂?4vIZlibu()Jh6 ަ~TYSzTX\zݚaKNzjS8Sgh9Eŋ'%Έ&ü*)ek 6]yɛHQ(HR-rRAw:['Csd T*<uv rǁV޶0Bun&S 0|ک3ZݎrϺcڸmS|XH^|)RUl +wR ǣ5Ϫ԰UB*$,^b;#kZ{ihF"wPޤi i"S8cZ=S|20@90űο6v8ܺi?p(LX-xv;-' r+D teg 4$g%m0;A~g4w2bvޔ]Ǡ1l nyd h7蠘TMb @G9 RLF -m(<dR.(9'#gIA^{ Q3\tU@& g`Z"4yۧa')ÂC0L?M@Vg|ýTӴ>EMŅy3C[z=$_:+  5V=Po5s %Ps;S*T#}kh %JN J.Cs3Z'{PHv&f&AO[-_Fk(Ph~Qvf(.g52y.1Y vH:9R CaJ]u9?EFݙjQSͪ_o]i{:G1%U!ت&Qn~3ڿi_r"?񺒐A!Izsf s3 fa5d.HS_U_mQE: Ɔsɶ/Ĭ\s̅q8^ 3*SOҴ־=D4]+>KvR)WQlJ 3I~SYg 9 8H Y0c 0Д;_/X&+⦇Bx26S]CN 1^ \Dq"=Rp0ÏiH{Ϩ2N͐;; 2g}0gD[@ e᭛zXir)nssA"x+F4+.x0.c?m [g]9opu9~/{TO{/Nu1ǘЄS^0VSv.gbq LCz k\z2s-6_TS1P|oHJ+B6B՛E\ 5ЃCMo臕>|}!9e\ݞWzH3ZGTI';R_)84Z\&r稾 k͖d ЦwH \׻QE3Rke^A2#k:odY87&%Mڙpa$} A6X柏G2K~m@oޝ1ߢy:?1oQnSs }\ȺٰX(y(skHqj|ͺ:<*NP_Q0k5*l֠Bʛhjk#(vD_߇kL Bn47/` E=.c)fίW,*3 K-I;1 vY~ci0F:^M9.Qf{||?:Xz`Oo)$F{;,E:0$lf1fZ^[kP勣/@(f-ϱ\xcG ꄣ%ɉYCIy}٨LRKjJ8_'1AH<U][?MB8KZ=kPÁѷV!qFf5t-nuFsWヤyjgI0EZh(e7zXY 1PKucpޑ 0x 7X %oq#WPΉWs&3/ nkΣ[,J =X7JTp:CQLJ-~JWe 7FG?ڟI]ge$xcS.GT)Ԝ y`87"WqJyPCV&U׽EZJjm mk)o¼Oo,=ZH}.b~oǩ1Zk쨣4A+mvgᢶH^/~'-7>0 jv`ۥyHqej\@G$qx^!}trҗJ#~ieK~bUO |6*굮@6/K(Z;?A9`; 6{ap4==4y Q_X ?S% y!Z/)qgղ'JbI>;@P_\+Rpy pKgd_g~<47v+Gxg97b=Nw[A(AP:y8I "쳗t2 I k1zoh2pV."WJGoseIm9!Խ E < g}lpvE.fw[ln>O4 QAOhA?G:;]%EuV;,ZǍ$u.m0!R,o"eZBwe!_RaA`,w@jp9fs=yDk,:޷汃4=1ښ7֍m=:xOzuv>Tg`!0懏!&jྵ)@+cf[O8-5ɹ9+!@uefH6tasLֆ񖛕ܗ^}.ܸ\"!f#^9nޥ݀]0nt<* bT:/YSCآO;vw>C#;nB+"߅4+ra}o0ƥ]\ǔiF@Y=YSϤ8pMhEhx1/N[Pl69L]鱪5@.b0}d;.Ϧk"(OJʛIt9LK|lD>Ͷߺ(, mB"_Ra%r/Mp6Ph U^;W ϴPv3I c(h ;#ja h$.262bCXG:}QEDEޫRo-e3  fAҥL'ף]P< ;x:n{q$^{ᠲIڱ q`-ͧ|T.c%+|ڬy >VX7<32v2Fa9fT%W??|<V)/c,!7ECZ[w[x lپSh3RqA$yg$lȭe6pf9ifqөQ0e1y9_\S8<ZeQ~,y.2.Hhʼnq2(71 ?R-M|ـ.Hڐr^E[HP1f/υĈCT2UF~KJ@$a3OsW'yEP4~-C+Zѥo 41{ 훥f{d,Cު4V$′\w EkXx:VMtM/ޭK%䛙ʶTE-M=:T_d6xG}qO] n$z5s-- 7=b&&stG[dw lцXB ;srFB3 *u8G$qVaK|h^$fk5xn_YNg昵tKZ 8],DL=C;GC1<ÂZƒ8l@QIbI}7^Jxx$\({OUw)k*L_CwHxzLQu3>μeaj)B"?38̿ `O\nqF6]UG*r*J3z=9#юv  7x^~>Vd *g OIDt8W戩.1| )6P"HdIy%͖AUQ娣J#xʈTqeRjunqGkpgy#Fjru-edcAT7 a%^r~D,8aq7CyUKc(dNS͙98hX 5ںkt{ĮHOoJz03|c/%Y wdz֬J2"I/"Iy|j4ՁPâ"l6 awZ7FW՛^(Dk~nmTǫge<qd>:qG(r"毰OD$zn^|_}ņ<2g-=Je@hU7>.p.|lh#(<2|LF躲?=!:v %[/a{0hDo|_d-BKa@X~zB?F&$3ұ u5 Oɓ$,Y/F ;V~Hw&W_F D\bIEd8o7 dqʿt9-y bgScDR$<#ݶ E4Q[/>I?#PMR*.m  {d58I>/6XbXo8y4$h}Kwyqf }{ri y:q6t ^Y=Q-̭0&2KdNQ9gj<^\HOfz争d KRPBbh`[JۓH^X|5%vءS}KmK7ծ}"C9OxyA [eLYƄi{h.e5F湃f@YiarKYl kSUZ{xjr϶%2)*Ur=s#,F+!8B!"DZ,U" I =#^ھyE Ŝnt[µHbRBp?_+'PKaJ#?izO!dXXG{3Zcy|ʎtMr~vM ?cM>Q |ouW^8&ap9xaCa,/7xx>3?Kj_5//3qeq }]q^E@ؔMwיF 6RTRXJGw+[@B-S͈E=bi08f PmW{K@#'{5~wvlhc>u(}hrF @ 6Dm\34  S 11c,aVj7mR\#P`aJ];UoerQI&CO*"ҽ Wnܻ XBA$|f~ kX@Ybx"ά rcZcB3Z ry*%u!"{2Eqq\=Ǵ%eB=^rES3yYqòV!4oxrJ,hE>4z\g1VBe ꂖ7V%e+bk[#衢Y'BB+|K mC fo"o-Xƣ4{ 7suÌcy*x1+I ᒕ3v觬aLont0h?XN)ŻyI(kbm$u8S#t]&v7^GrSEێ Z /qD^Љ.C7%17!^Xunkn}7A?q:XC^Eo8rgIAeO">3w1yPыYwnWw n3&vCJm )?Ysk_]!(;,Td;O@u}>XtRK?yFicחՔ޺ F.q e\?[@ }E"!@agCϑNbÅ vl6=G|4q,i\HnUy$kL)Ij0<A kXi* m|` l' J]+|S!kZjr.{Bh4KG[^uƣ;G̚&4BNmi%D|,^l|Qh;JrżӁ Ӻ+jл گA;ۂDekӀ Q i'Pp`ȏݏ߯;,@[*QnI|#yм Cq;yItr0);?n[.0+g3-}ډWOCdabl>3%%zh)]#3}Lm7/vػǽ6Q r{lrT.X醐C_y2eRao)^;MK )N7& h#YF AK^3Zl.H(gK$ CgdE`k"VGs!E!f߇ZKJUkZTti(ːlKJ!r/`)K Ey`YV_O/t(3)Z;WBDyK\6 w[͜#<[Gat/w-5LN:џ(d!,^."J6/(K 0o r 8b h+Jʘv;y=to- endstream endobj 341 0 obj << /Length1 1630 /Length2 16753 /Length3 0 /Length 17598 /Filter /FlateDecode >> stream xڬct]%v$۶mwlbb[N6z޷O}~\c\{a.̵&'QR6s0J8ػ330L\TUnrv8rrQg+ 4M,,fnnn8r+J]E?%LC@hhw  \-s+[ @TQI[ZA@%mJn&V9+S ` ``ofOi. ]G_7)lg`p6wW? ;+!Ggvu\\]L]*I;OWKcbXUZ9Sҿtaj]]@ObfV.^cstWn.Vhalf tq gzcGG[y;`5gcfol +{8fEo܁j?3C7 c3{[/QoH }$7PB oWKz+]2{ g;|lO^Zt`Ү"lo& \$X֨V\P]i^k@p˖;u_!&E'aAbƙfՂ6A;Vg'2oH~i (M huEg'Oc#C=7}~$)^F.U-5oKnvЙ3.X,ALe=.XEd ;V8xmV$Ɋٷ>Q5tͤ4P259~ t~'VK9Se>wcҶ9y~U`ل%sʺjnxZ09 Cr7UjӮ'F:.ՠG;]=q^hItƫqX[\V N!ߏ-UivN7Do?]GVO^ /a k]P8bg |P!-oN4ysAXʮ?XJF~c4>{bB~^5&~G[oO*(lccƴ;TbQBjS]2yj6[r@9r^Y_ڞjI3J!jv;rPz Gw`G B%Va%/{-1;bjRt(V+P3Ð=e!(0|5?ڋ$EK6{VC{O+,au >kZXsbc݅q{jH|1?rzwbG{y+a: mԢH2z\ X?x1߂_s%)Z'[|:ux<ԛcVARX/ΗԸ偋A DdL6aCZ]" o*S,̜BgŸ́S.2" fpVYgimV9ӴfEy{*uNK8dppN`d4Lŗ>(]v{(or5*"|<(ƳT^Qm|8fb"pUkm Q 'i2+ zQI|Dzߘ*Q[ÿ9No@ԓI >ZrWZ؟@&Z9S*,#2yu T5Ǵ_}0D e2^z R3| ba-:ϊ<-cC\G{kj 㒁7qHMIo+;[6l) F9jϚhc\:faW^<V<䘏vB*}lVwR(}O0\u~,{.Gqql0U+QU{$‰4'HiȒh7CT0̆$ˮo03y ll%vy^$h-:`؛8[6AQ믴n338جcΔp:e0|!g ?ì,eAg+g[iZb1>|?7~P|B)ޘE 3^/ޫuvjhL/) =(fKG BnkuzD$tN-@sUbNpHVBGM!+)tQpOw`O(5#^ VOZ vK=墫U"dѠJ;(ئU.;f)ytcOHT4x%lFrAE˥PTU3A˅5dur*.EcsD&/\_T`O0۵*}"?alɢ=SR9n\ 6 }`ƍgt23э8{с'IB&T W/{8,.vi$n: *ɔ IYWΜeP@9\c&Q#K pg2D:MAp9ɼwXSYy@ʈ1ęxF,Q?Ҿ?s'& T&'RiuQ;-w89&4Fnjmp~h)&EcQWJAzM 4@D,їeq -3c: ŸLԟ0h1/=6O{EiG%-wwRMZ r˖xh&B%y ͉ߦfQA>M*jJ:Q=<^j>Cy.mֽڭ2MOk+W Y=C݊&?eq,@Ewy9f\62Z!ަH%ت>im5&fawTu$+:ꪸh; jҲ!E!~ݪIα\GU-ty@hM2{"Ѳ¥Ɠ>fwV&a2<*7 G;Q< {4|MO|Hdv7wSL66' @Ҭ/7GP,BTψ qPNq׉:NCTO`-kK !IŔ >bY$wDD MPYڣmO򵥯6$^Bj_q-4>x0|re~O$F;|\z—_\ckzcusZjmBQyGcjt$¥s:J$z_ s7T;ٺ(֪O?S7|d)tNz nuF>~ 6,4HbžMC܏ukoα:6Wq` ؒ hCJ(qC@S:ѬZ'~6UtKs i}`R Kض KX |M( 3ij+5^6jY̝1.wj)&S9M? S GÖ\(Pv|x>=ƒ.RɆu{/ ڐ}6]@y]z:W4+ Xv5Wn[ 3핼u I i>IM mAQOUH ;qIz1A6v/#|2hQ&xXze '(W'"fk(SmpIXXQ*2̓GBx:y5݃$^Zo3V6^iojTTNgnl(H.ĽX&ch2l;AUl Y8x rEzFA;?,ZG˥'j"1E4l?.$)ETڵS-Z"PC׹Sq׹i|y_-cK{b֓яB]e۬ & Qr\!7γߦ#<Ρ2uR^iF3M+bYD#6>]N jc:~=sa{tbjҽRtb Sd[>'.rI(wWz\!p!<]bguiK@mU0^pFX]g%-^FV4 P֪^$v Qq6ê)0XH\i$,sy#3ᇀcU˺ӈ̺g^_ہXD^Me55GWʣOW~޻\`FM~{3Md{H<[S{ |I~Fj idk~}c^"]fP]@&w1E&yrp= ']Ngd/ua-9j-oooYRTm 3rr8Y_QZeO.碆A2|B3N(p7d&A`*]O$l`\ϳ[2 [6O0KÐցU/&Ď*A!)yddGLDa&XMFM0xF7{eK)ynwJYZlGSL;{=7\Bfd}VUQ2x0pz,@Q\+B+*9 TֽĶozъzig%N~h-\9;Yj٤4* *}.Sfm$x(Ҥ$]Y67d}Eznκꥹ\u,'+{Ɗo5l*THۨ =]!h[s7HFi4GY=XTW|c?_|Y|<6Wx#I,bjptպӥ3RWS$"`lyo(UfTfͫt^"B/o!|b6fnFF{ru(m)ΛY^/ۓ/WɎ]<\1.v_IVNڴT8MTA3W`T N-& {<Pqdĥa'$3?@GjϽH->Cs8QuTSzΪ;\qZGb:]m'R,Bo̅2ID)7x%Ff̔ WQ)׭t){rt>\e#92\^e"(f䁢h;{hdjpu˧Ny2h0R y*im]Ob%ܓʫ6L7M }IEt{B*Yfm'1¤dVS7tg.tee\Y^|rAWrIh31 $B׋ZT_Ci?GV+} d}@ܭ0HRLkxC+S@1Q{R9!+݊J1υA*}YCrul[C rxEjq ht#B&Magu:Z6ʻyZa'z?ZJP I7*P 2ӝ}*Ř")uY3K4~18P xL3<7ֹ]G):p.2vߤX| 7!¢'ݤ4:)Bkĺ̄ jL ܆he(@t|J}W$⩼ 4Av:)xQ|ؼ3!H}&wbfw?(+EˑҴ'r!bWY sݙX2r(Yȗ^(te#oPZ>\٢Fms}(  /w2`̞H:J: ? ٫X=yeH>;[4s``oq|f8'$7f oIɃ%^'kX3B1D.G%%?7̮\vr>xٚ(ĺNڇք`}U!<ʟ;1{g֥;-ИLD wRRU8)WyĹd?Bʆ6vI1t(v4Y@՝IsUy( }^X5a&1WɥൈU0CZE?jv9%b R.KDT=@o=Iҏ[+;D77eȈ:Wm44ant_X}xZU%g젍cXPq/Ҥ*;#aZ!>PK0漾EAei[v]x7kh̴+62oR@696}g]d2sM$WVfo3^Ju—=%Fbpp~8_+y`Ȁ[Qu֖Q-9E2e=SaTN>.te}}SB$\oe%w["S[K婩/Ok xǨ+WwGR2O%tϊ%Q~j_|'Cn9Mwm1ieȦ {Fۭ7 ص!]dR cNziP&yjdkI2u 3 #ل{W06d=jQ 'S 8eV.g^ ?fA15)&)YQoh9B^ޕzc T!@p!`J[{P^3JVYyJ 'ޤ4W Z#16bNYDȰ/w!2 2,0Qi0Yωhr 䢠i0m0gF#TPژ/]ˀy[ d JTP$E,$ncaUih5$`B Ӈc'7~c?Fg5x ]$.ɃگG?$H$tQÜ An:6?5&,x-8.~C!\#I{)ΰND:M;75fyd ,ș. Fn+‹\p}rMj9XɎ9yXL=X;et||LJO"uᔔsMK9edS$rh el:b t'R98kZ 1hq V?n~Hu{؅AL3O'P_}8NT h U+"1aTVzz2N{1}]Uϛ-ռϴᣞ31xAO*϶E|J$a`tAr+ ᵐ=k"ENOm̛Pk=86/Rc#Zg?GmODKCWɰhjdUPCxNox[)'TU;ˮb0 1ʖ׏n\1<_CE~5bn9􍐙?\jT﷖OkݯAw:]Wo`TFj!ei1-53N !|uM3Ԝn D0huG\>MVpҎ]\,ε]-l,GY .Jعu=Cyn5H t?gf1pW8)?O|HfMfޯ)s&,T5 5Щ/3WKʫJXg % F/286Ln$r}ZȔ}#{֍_,Gi@^{!R3rXavQ;TCZ Ш.*ǶxvPF_I8 '%U71B&tquT/֋;\SlB`ݤw%-;ɢ[2&fS]1_~ v"` 7w-` H$7)X̛8gH%<_vk爫=JZZyH֟\B^OҠ3[Y:i[0pː>(ghI!f{FR}@Owƕ݄}`a+r 5ֆy!ڂ-fZ{~Ga*F{6ɮ tOԠM`PhrǼI%tra&63|} Ĩsy"rUK6>'-V^CPc$2}&=S/=*M;U$U+x9h{kX(05JUV_ ɪ}q/7!srzZ5y6GgU3~2:B)\jaDB^fA@y)d ^@AskmEHpy AF`܆f̈́f5PܳX*`+,bMQN6WCdy s}T`z~%պCaaYWmf+ju.oR;kTJ@u %%0xh@Yn^:DBpnOuc}ޔ`_Ь,6x IRDMgLlE[Mx?&yܳ2 hO/AS(KX7 d싻#tU^T7ouŕiuP2˼WFs~$iL{ y7]{D0&,4_K*5`P\HƎ8gI:g߲gvF{A5YW: Ȼ(VC(Px>%xOb&z]~!zÂ9؂5=4]H2r]Yd+(4eP8GTH9A%Zq 9>$O+fFUrE݃>*j$ycF){Ou"U =K%[e)NS.-DZ'lRAϖVf`&q;TƟ]rkIхGM8 =l8Od")QX=!8- k&'֙aGJ%B`’YȺpЎ&]M`'q{)7_/YpbnzEbK4RPI9vmpciǷo{@MjZPYp&;js;0܏es`cSH"OԯF?jW>~G0Q\ P@L _ ^|k^o/[ܐӞf:EYzz +*]*/%[Iu0@@ڋshw=ֱ%lA-qk+kՇrUS-81xOww^A褾NLLx7T fjv?ÙF ?ER٤ƾˠf|ca;2A]Mp y0үnsV~Yckۉ!D"hcGɀJg2[2F:!~7\:eȏc `dLn:sj0ٖ-q4ԈL|2C$oԙʘ3z+= shO@Zn*>V. nDž[E]uDTB[MNTXO:‰E.>&57ktNml%o5c,;zR@ ~Y;{LjmԮ.?#=bE5(du)ߖ.`~dLUCT.TWڠ|EGV$duç 4p+~敏g#ňAa.䨔CZH[ ɐzk"9 {gb ^]IDx1jmxsS#lQ3;*7B!@"qOG@'mjʣyr'IwCik)9 1ܘDYV#=MȬ[؇M&~Рz{=/q T('ˌ.XMZ]Y&K1һHsB DcKMN9ұdGLd %*d1F[I<ME}49ℂpF9 hn`#"5(${:f,d)ug+k2*pt `=2{vWwbz3 D(Z pqNi#,XHt4ӏʗ2+o2>N31&h8Eb}n U$!lOG*ˮB\I?/-%3WgYHiԙt$u ]9$.1P.2^'>`԰:|zmuw Zbw!A+D_2cRtڑJe4oFL^6u?X[*? W6V4 ~k&JYKP8G>dNa:է\a-@(콡}KWI YV%L6gIN;)ܓgqR(99s*/6.]ݦ;SGm&~"0YJU,%~ȴY1%l* Im[3d-;g$X#Wsf" O2}m01%"E4gq0@KLqsZ'`6H=}:l3XڍVEⓡe-)d \Xi:xXZ 4@!iC"dbIPnX\RWgEyk:NVh\h G\! |?JW9U8OlF yUY/U}s.RZsjx 9xXB톍`W"w'=|)U._֠ZtFɻҘ,.%a. GA(%K[N/5|Q=V*~ډx: ytªɤC$41.Q5*OFvQ߬5 Gh7y(^0;S/ 90 =rX| 0:n@5r6.nD`)<;>*KF' < z-,, EZ7wpoͅVH-zg1Am?SCj1+!:.ix~_YTZ<ǸS} Zz)(e+Tt6]?l9ks1[4ZGd}?TI%bF$wK'6tzb^/FZmц4|\|UJ! DR$6)7sC<В%$d]c -ߧ؇H9ZIb˦Hx5II@ufx~;h+__8NҒ͊\sW5G%KbMW,[j[ϏT}y4Ʋe[ XEKV()TRPw{eΗ+,n`Xg #X ߧCTEݘGUS+y/ _e) .iւ3۬3ޥ y'Sm"'VxAv=IJ  u[v0&7a"f^coHкl tڭVPu4f, v rCB<Gh!2_U%g2_'B&5P2ǂNRpJ֍SYbޣ̦IdĺvꇒW.6dcYyh4 ڳp=Ά:֕KC/E)g,Hjߥ5G*泜kyߏrJN*KskTl'0=\C򗋄ku ZHAt>ږ~ӥ- ұX >I|A93MSRϻTqz¾d}t&w,omï+5yIutފ8d{)<g"IoeW='Tprb˼9&+$D#dÀyN&b6/`HJfP€a' 9쌎<;NLӀy@`6aiG1Э3hO3L#ۘDe -1,X;W!+rS@yPϵ>v>̎PYjk)q/E.vH4}aoO.8A 9TbNobS'j )U3nͤmn #E@K"/5T12̾ׯGDod!/ՃtJHʀ $fkMܴ! <*uӂ7V==e˧6Wf05ogJ {m:1<^ Վ\ =^5ngmrەBBJ?C;/E?9Uc Z5z3 /ǁ[kj_>AWLђBMwƐ;C\y W7R6n; ۆJn>hlȦC3쯄<O /4(~ ߘI$F1p.38A:Q2.TK+\vx<$M.4mLR4ac%6d`Pt)li>+,C~U|Ry"BS߱`KU|OܤX0yzAf)De9wN+1U6&)O,e|,ٔQn#Έ0o')?#\-땋0>:r-dբ endstream endobj 343 0 obj << /Length1 1644 /Length2 6176 /Length3 0 /Length 7019 /Filter /FlateDecode >> stream xڭTu\m$AZj莡KAbfEC%) Di$v?_s>׉܇I׀OfVAQ|@~A) sсIjh( BA`Pe ,0!!PRR {! QΧF\<<DBv;wCQh @=!`] 5S Fn6[6 E0. ɏR@@$l A=m/F@H?8 @P(uvnCpAch2]E@(:_yPc#!hGߴٺ.A(߱l; BF?i!!Pe @@;g0AsοApo؟[B B蘶(tl@h@a_v;7?0w0O8 :  P> [G}Vusv@/3mE B7 m#_/d(- P4|"*l A>؃}c #!P0Z?>:A ! dj0V2QR6K=lV@1\tc21߄0OPL'$DFtjB"~C?DP'L_P&hT0߃dAгOo @Kg+=0[`ǤdT%UfﰲYg;N+ü尶U뫊WR7^3믚mt~,\9ٛy6,%E|^6|6oYpK?,~=9)6:#I-ƃ=7g}=m?p:dIvޢ578ҙzr7O=iͺ1Dn0gmb<BCey 5->j͉-|JrJnF̪%.ߐ>WN5 S&(Ag,јHC96Yo,Q~ xZ1 tzAE7=]eMC"O^D}ys-bcd<]-Zl—4]j"52َ|,ZZTDǶ:k jzM[1 euELm*zjky"WKhӚߥ}y+M 8.B]iAp''V;fj3pJ`-XjG}Sgb2(X[f?$`RLkKcib8ۖ$3mI[i|7kEJk򴕩ٱWk+ZB>#9u| ' +`$I)1 C03be,c7T?*Pz FZA=!"k ^?cd;yeHoצ;Ue8:;گ̏h67C~)ʜ 1iR"JiO4,vIKv쀬KSs;ߗ5:_~Vٚ:kOfjT*:5Q* <ڗy"o\N|^'v~I7°2{q%/&:RL)P\L:pZ2Cm/&m;RWrk#8ùJQQ7I qz]o^1]ZLu?696h,{r-,1\Fٕ|CgXn8wp^WǗ-sy6\QUB/҄8ۅ1/]̒1mވ2!%;B(R;*hsT[w^skD;t[? Gn0vtz*K\7lk~݁ooװW|N??Ε~'Cs5Z\gW ,dc1vd,} Uy̱_Xӑ˷~jOas_[WY'k,tXK5IO?=Cjxv/Nڍ<讄ACs')(%xlM~-0pyn].&n5i_6E&z&j%Lt2*Q]U0iBK{ҶٿI3^ )A7/R *LIiM)<f uzҗ,*zޤ1!᣶/1<7S MLk4;2B~LzMDz{W YԔ*H[+m2u(Diu\`)u>.&bۺ:^搪9 l#\f]Uڌ!e (u2b̯^eE切S̔k tEa݇fLjU3e oƾ%U=|Nvϗ \2~&7u"j›JU4lkr Y B= ź5f|k/;>4 &5MlEp{E Iܼ8Cv]b߀&.u&_2Sr6T.s!@\ŢMRH|fMSp=. !&Vrʦ1c?yQar%TÒK%!TsΗ19s7έ|;taȧZ uY ;*1aů PDzJIKIqHhM  (77*c鈚vˏRX1ez7*E2HTSU)jm`:Hmm> K 2.ִ~|3ěμq ^]߈ǧ~^D׷ι$]Ib gK 鹖KQTz_^K??Z0JZ .Tx`B%~H3B`qkʺ0M;Sv৮A7J{tӏF[|nŤa>8hv||loNeQ,j1kF^bഎyRN^/­Dn1r w~u0Tx4a۽nlngum. \$-ҸvP BjF\Wa;w'7%pyž[ƩnܑCP9߸V-ʟx$}U1ܼ3iTgTr{2RO$!;gir8zsԚ0/D:TsP܉3~HY,'e: Rg'x!sj{[e[s^uu-M^~LV眞O#e"U׀K8<폫ڃ͓uܲӆ%$6RM8ÖyL~0g% $SD>U/ܟp+=^仼;Wu0*:2U͸Y$WόSS#T)Gӝ2%FKm rNIJ2{Xꊤ˟8|Y VϥE;;ZD(͙èb/bv>8oM)."r>˷E#^ I)hLZ#TVsh(p&#*ˬg'+9 {~yX,\ڡh!_sANg`񛼣C/N_ȕN,Oj pda:Q [=̵J_M2o҉D5׶}cM>*ڻD6Bӿ˖4f\pyf=O*fĪt'֤n 2|?zvX{-nXM_lCFo9Uߴ!JWS=gVNZ; `H/'BmUأܗE7{eE;_kLՉk3Onw1ƛ.n tQ/b^VވT"l,k?c  #mF9*g@Gj5U`|7QRDP?~E ddbtǏ}U"M6sgkѬP~Cp-5ђtS#xkkW`o\PtzdK?^P#뻝\ǩDQjɈGأR4p־09<6 f[?SՉgWeQroM !Uw[ (iڲ"Y> vS"ԧ˷_uI_l 4J`}sZ*sHg((N_ĕ.*h7P9>l5N.8)u -@0m+G^iRts-I1;ríRw䈚5ǔ2"E7*DawgM?ep4dY&B`8ḞmaO,UX}i!}yp.~_ r& IЙˈ-Fp؟̥H @'ճVSi:$%5xaͭmp s`x=fuE3@|eiA캴\m*.⵬z*{GEs zȜ aAmS:(rVj%[>$3@/yW_u'Nvi w> * ?t`Xԧ0)0/t}>oJA2B 6I͗o!chPwS5"i_BtZQ/fIivكJkIy )-gM'  r$حE(9*?Mdza!e5OO̐ :GT]vV&LL_09{oϒ1SKGD$ʭK 1:-.ZHfi.U-yiI3Ͽם6;4R A\+f]f> stream xڭyUXܒ-]C54 4Ҹ  8w/̙;/s]jU^i)1ښmN,lE-<*YqJ8 PIc'@ l v~~~TZ ÿ,LF:B̡.`k[;0,35 - IQ ;6lb ! 0`fBj͑K` p a`7/`qt| 8Nwd @AΦj7 ;WWLsfUGNNv[WOS[_-ҼN# W.0hgmwΎ*p;Z_i^ /Ymqr[s96@QYY-vSgb.`/ᯙyZ-` 6CeUuzM `'+'k_{wjigkkEcǞ.c(u-kc_ Bm ]{kQp;bPWٹYa8JC'k@M(U50u  PU;`I[ٶ;+NlM_#?#D:+;9@l,ll~u7)(9Rs2A ^;GA?mA)N5D=]vyU>)!FՁ, vw;'^pVZyvX 1R"~*]C s#xF$~1 4+gڑ-\MK hj*>q NoP)8uB}/ cȜ8UXj؊-FxWś2蕭2pzX'irKb4kg2$>KQ!Qr7VTYU& @/SfR,U葅@Yؤ~bZ=YܔQ!$"ThM,Ռ%,i ~xn1:]䓰JY q'SV0@HKw3#º~bU, * aMn $:1]Lj_:W?{2]5@pF`SNYO9$|1>Yb톐/}PyU -st Q "4kp>87xpb3HҚ}RA#u'M K_Q JǨna{|tU85`dH+oׇ5`2Աa;q9/+0;GDƾW2 FB{)0VLGiӟU@66܅p9Ϯ;G,T?HB~I'FH!~A"Tm/K.>m H j۷#U-цD; P>NI A k'xp_<ӝ4K '<_ozLI1IsO8nř{$'JK~ǒ17@Z/zH_ϪiwԜ3}<׫(ZG35ٟMť0]QBy1'xu!Yp9,!ꆞ=%-zM"MG3p޻Ϡ9 ,>Ohƺ107fWF{VT+ZWXK/ƋIa)^+ $2Xjգ7go0n~z/cǐ_) mܼi(}?.0fMڕ@deؿ4o5}#S&}QM/r V B`eMhb[~SdD ZXHH5$"D'Smԩ^~[ <r#)![k{}|4EJF%~nMx4H[W? 0bp~IJnf8>wuY+[ņEvԐscG<Qˍ6t]cnpY|StPSQv8[+0Y&-pj{x+ܽ>oSJx"Tsh˰YԊ- HJB!YA|{Vk tN-,/iC̳֘֔DΥN390,wqדM#OWY_cV#͈--sjDnBNRpYUBr"P4PQJEd}_9l.sɢ2Ǡ偖w _?>w4p6bHY(ۃUn7Ls@Jdeِ(X>8r}OBzr|R|~ú*\37ouSw ʍ0, 'T'I,YPzhyo}]Df|{S>j ,;) T]Jj.=%=!!I&lg8UǷ2[{5E<3:Gu!}I,{D Aذ';}oJ(yG C\."ALE]BҼAh3AԺG 5HϤ6xn;y /O'IZ-$;¼O3ִ_z &_Fvښ?vl07} JyXec(5+_F$|֋Jb%#hh$HZ驥VI9]__D"I~u1QȮx3y3OaŶ;RNrTjW7¹D7bi47Iiي[. ǣ]q(_qF8:ؾp#9—ZQZGpꆷ~?P1= %{)>e)JQ]n uÎ Z" _kIO>ͩbVlֺA_H$&'xY/ 5r SS:#'!뿼TME~ݭs;đn۵xCgٛjRamѹ e-?>C2b'UcYQ UscIX\qU"`R.,7z]ϸyU7%,;$koes9γ]ϯ{V^3{E[)"[^j?mւa#@`֩&" jlP۰iۦ4N9Uȅ-]1o&M-T~>y{v{MӁAyӃƤZ}/=#¡9݌.<\١AY1LD. qmoWWVcZZXpGoZF>d% *K z} 89mU4h]}̿B~%׾z+RsT'O=?h%EqDP 0*}E4Y9&u͂Y$Txڽ$ЅX1l_k:]3xf5*rR@sİSµ =PßCe`vs抹p[jr[lOޚp[ [{%CvCi:)e^XUS-|*̵9Y=M`1] Ocp_e<ׂ#%}l = R}q[,VzQ)dQ7e7ӨGY>z{#5&)s6ūJv\'CB.}?=;q@ᅓF5/)~QJ*QU֍ȥ;㕔AMmmY=B[Q+8:J hhK1)RJtPqLPF-d Jjz2"ZM,YLucvAVJhxOJܮV&9=MC#\ R©/'}S;i h5_@ErJo~vaZ?K܆J5D݆1aH-"ژN3HuOZ3Z=wI>q UW~t]@ϋ"|7t#wUJ[@oԨ/lXVE86~G;>});>uE#ȵ3:(FGD$ѳOGd2SU<™+8xUpjj$Q)VY 0&!-8椦B%t:Dj{ӑqI>;[ 4 +ڹ0k?Nu&O;!m f7hm2l4Hx,Vso~5n{,rG:)d1ky.Ϳk"Հ˲ ! wtr+J bq"mD /.:<A1GPT=1I4rwKpƒMHyrz>鹺']Me"V3D ˜V`f5Ϻ~.' |FEv\(⟰<lݑ GoZtړyCy}4?n dqYefܩ1a$۬:kEZ`H:m&#hYT6ӕ} #CeJDkމXHI/U_xY3N!њ9DR<(h ^PJ;uڗÔ!ԝ+xcAqڋ Nΐ"9rmSc$zATqivN6c ;pپi'T"x}0J+3_: >\*iyF4ꐞ)9z<}1T"^g"O\t}'WfP]R+4aWo=jF̍TrgެVh8ڐ%i0R!fTBvVSD)"Z*8Pyܟf>FSqL v|4yYj; ZRl dˇzfQ" ŅqPj:ycw{!F^ivN0T)2|ܽ$TEk,ݚ;SEOcf E4RkG+JFTR-Cn6hlᡰ'U2rnQ|$RwЏd q UTa;uweGb. q7L0MW殐~E/;J c0yڔ<o~2sܸlҫBgIl6_$]T2 Z$FD PhឧyjXFPOoRInQ"@RƜ*>KI#?rq;bYU4_f &w^4kZ-Ͳ wp8)pI?DAX/^ܚL6= u{ܡw].³yŗc? {kҠW \2!Y7TOS1$ۣycfy_w%SOὬgiA^9j#9_eQɹSywح韡'\ze-[z1Ij,~.Az(P@1<> ÁxIEA2|#aI䇼(KTf`%fV/MRF\pԧvˇ̷gh]u]zOPyx:uU~^kاbh6na~W{PtvBjhi=+mȌB*v5xi 4=֧ ީhU{LągyV~k]ڞuÌI/ܭ^#utף!S%ѿ5b`sO=:}_t[.h:a?FbR+@e%MS}kC+P{kChR%KaH,q aqxVl"?XɜBG(v~4}:)JQ\Mz(0 !9: r,wx=տ`=GrHXkӊnE[vY G ,]%?K>rǛk粻QG <CvDO<ކ-zU ȬrR*1mQ1?"0^M"脵<(t3'e&n'[Jv\M{B.m.뎾 :w {FL2H_@:hS7V7,r:(:ef@-v׆!r[nPk)L^|=㊡ѥfw5T˒2c jJSNDfǏRP2˗^5iܐ +5I=ۖ>Q\#8얊>@o̒JݾH&@KRrB'kmMPB:FK2SkCqKz&8?\ ㋳$P?N(Y jݵ\ ʝmm/hʒwv50 (ed5Nz5rL$>"ksEXa]TnT: dR62Q]NO=0/ڻ-_qX"*O\"S;3.gyEAe^DOW~98aw%uaɏg1lM|״~7wg߷뻻(Z 6F !>LOQ 7S\\_ޝ䑢]doh43n]|s8ߦ_' QS=i nC[Sew~QDg^yϐ16';~/d2dTkGÉ6I(6/\cϊZvie@.,g6n*|WpubZy߰zr@Q1洪-,GDgwmc㞂uWAۖl 吿I/RXQuz3˕ݓOZyٍ~0KC "0]\VC^.`\ZPdA!6.ZP{4%}Zˌݏ` L1+,SJ ~C`|_Lwg|9 ,ݔ&;F>K Rx⯍3M mkYQ( G_)zgo{4o6*'/pgjIUzoş3&eE` /U?3;d|]p8?Y}Y Ս8WYѩ+x@ 鼺%f`qىv35\!(K]Ǟ~ڀ΢Ơ \ utk~lI[AGIGpԲ~JcpQq%3'XlC9k'VI2=ŀ'?C|h űa,MNuD2<ñGeܚQ~O}-f泉ʆY횮j|~&4V0-,, N{38+ KW{4?9PĿXLCHGռކߦy[Ս8ni9V0%.j?mk)AERAw`o:}A9C'pLGPr|m%ylf.xh vԆ!Gp{Ld$BI朓pdб 1B W蝽vݞ.7jNJ|1#8d+Pގ6;K&*vhxӳB#/V, "Ywm)[?&@A`nn$S~4 VŪ.AlCO JϙQRVC/Ԃz@E6䘋[g43 G84b Y9=6r OW'$i_׺)NI{`uec }s[Ug.JL?ҳW~r _P)ԙoIA)?(G* YJp.HDȴ=l)XE,E71>ufgc4n9YTNq dEc!J\$ߺJJ:G"b4\XK="t] 87V1 #3 7JVf:j-y lxMFةK{Op endstream endobj 347 0 obj << /Length 696 /Filter /FlateDecode >> stream xmTMo0Wx$ ! 8l[jWHL7IPV=M̼ su;Uٛ=w]yil;<[[j<=?׾+v`&ߴț<^*;~&Q>MS >_P{=s@dkx;`VY`s4JaQܡn.Uu9\Y6><ٴ.Z.4>Dӗ}~r:-d0VWk,8yLһʮӮђ[*mLr?q 5F8@=@)& 8Rx uD\j2HV0CzL] bctI g$`htы0\F0s jd< I6zg W qȐ+#k .bsrbmXK7ǵH7Gnb>&jؐu1VljOu$՟qWS/%1{\xB!K(hHTЖ枃Jρϯv=k2UKς_:~$/ ~E+7ˢ/ l(/} -+ZXukoԝE?ZKq endstream endobj 348 0 obj << /Length 739 /Filter /FlateDecode >> stream xmUMo0WxvHUdCmU^!1H#x?gx]OTm$|͜s_Iss :L;<Sz==׾f`*_`ɫڟk3'iѴ}=M;7rfnj-eSӵOLg~8 )ok A8 $`I\3`Af<Z]! xNky"7 _㓧q H`nḱRONH=CpB:# =%888QA~!*zƜАT?!~> tw8y*sύ }nFE>7*QύR>7G];~<6OIyktg>O:yұϓN|I/|yIg>O:y҅ϓ.}2 L> stream xmUMo:W5?$R. d9M eCkmCp;;w~>|3E_?O]5߶w]Occ]=~?}Oyh9%?۹׬B|Ɯ>);vw%g43>\ 6 EJ78 1{~`W(-;]%=xe_,b+-O;q\L}UI--=BKE1p[! Mߊyu>.N5K)Wb٬8i[_uʕMzQ)V(Txޢjy!Z2P="Zd0\ÃGR\).2*Шa!U,H`+j.5Nα@VK-x%3%AYӀzΚ>kP#5m0Woþj.ZT$X/)n)#Wo(oRZ $Kp4Z-b\1ܰJ P"GXQi/8k^Zq:Zs9dB )sL-7xJ`aɽ)f$1 dъcCZC<73JgznHȰYɚTa,_-O87}KԴܗLloK+gJ.GZyVc48Wt]:P~`rZq.n1] S/Pu7Ue:?&?!d&1yHn5)yғBx#1ޞ]Go׏M?X endstream endobj 350 0 obj << /Length 866 /Filter /FlateDecode >> stream x}UMo0+J! ᫊"Rj.R!W3njNylܬ;WWМ~8׺2{SlݤMƓ7}zn݅9p/]A:YsG7&3HyWOlJQnReT\`YQqJƚXQh)5HK Kw{7E^ kCXq pD zAet 8alSM3?rN%NbQDa 8>#h0\?I`\~KWc ]i/nTvc-+>c_ZZ~Z83z3[:ޭ ߬Lg3t3-g B|B|\3gg|2?z)BXIAup*^+&#sU-'H8qɼy5A78޽_V,z薻\&?U endstream endobj 351 0 obj << /Length 866 /Filter /FlateDecode >> stream x}UMo0+J! ᫊"Rjn" W3nj<4nV~ߝoGM?k]{7[7rSmtɛy=TCA:fYsfi<WOlJQn}w̭][G46sCP=Co`BIFn!$o7ݾK54ޛ`~?n8t/3=NbV+պ};:5wɩƆ56}Ӯqî{qRZ*p]ߜ8y=W(_KdR$| 4hd52HHNsL FU*q8cMMh QEk%RWp |q"/!\,Ѹ8"\ 2:x0)ljsn l9ux\רi"EܰpJM}4$x0.?1Yſpc.\X7ьO*ezl,d mY50ymȋ,aYʘ8 xAf_14g%cxU>ob쉬f 9돱ncsO{(g1?\֟g Yg 9LsQ.(ug^/u ?L[ V|FV|oV|3[: 3 ~!>CO!>S 33>Y^ ?a!SMW,:?8ÇqG湪N$ոd< }ν_V,z薻\ endstream endobj 352 0 obj << /Length 866 /Filter /FlateDecode >> stream x}UMo0+J! ᫊"Rjn"B73W3njehܬ;WWU\8׺v=ߩonTtƓ7]ziTCA:fzg 4R㫧~R~J}6O7}w̭uזSIе(TPfw۷莛n˥?8ޛ`~?n8t/3NbV+պ};:5wɩƆ56}Χ]]₥+U9q~=W(_KdR$| 4hd52HHNsL FU*q8cMMh QEk%RWp gn~ȋCam `42W0A/c9^'-pʹ)pq[[i])9^W5js7 Gb_#xb~ ' ˏ1}cLu'No ޅ0&1Ie76Z cx-~`& y%Q?K'!/h],KV0d 1էM=Ռ3g1Y ~i?'?!>L9g)q:#eNC?lыѣc`83ֲ3#>w+>Cӊ݊͊T_|~+>Cg!>cB|/g)g{!>_|&~'a9K!B>,TGbPq> stream x}UMo0+J! ᫊"Rjn"B73W3njehܬ;WWU\8׺v=ߩonTtƓ7]ziTCA:fYs/'7F3Hy:K)ٔ?p>ݝ2ZkXwm985];B U{hFѻ9z};}\< CC? F`RޗS/~g> ilXcӷ|5nu/.XjR˺^k3<'su_U4H6!L@@B@q\s *Tg ]i/nTvc-+>c_ZZ~Z83z3[:ޭ ߬Lg3t3-g B|B|\3gg|2?z)BXIAup*^+&#sU-'H8qɼe5A78{N Y-7] endstream endobj 354 0 obj << /Length 833 /Filter /FlateDecode >> stream xmUMo0Wx8T·~h[ ۍT~3r#_)9۞c$_{t]P܂~ݣP_(&w(R|vp#P)->g_B?q8SG AC۽[ia߿{2ZE_cf/1/{/4G+)bUUwkuTO4[@ 0@`%! #P .w)úp%KcJe Rͤ(*1:bDDR@ ȓ2UR*N)KIΡԀ0CS,km:5Bͦ&[Y{Ł@꒩)NMvSpJs}irphS ᐙ2L9ΙV}yXi8'z Ԛxq1GyלNZ1fXt:s0>wpVR.խr)>1qҾKvHX1iS5rM yR6FBlH>]6b 5&5&0a'evb_dfQTtQ]zK/WБ^Zz&孯ӷrW.&_rUOz䢓n9)C]!􁠧r7dE?_;~T?m endstream endobj 355 0 obj << /Length 700 /Filter /FlateDecode >> stream xmTn0+Jb'$8B 8l[jWHL$Q;o.Z ̼7/o~:W{xPCWQb6;J^ǩv'-[~Gݾߣ#i6ڿRV_n84]֚̽e[sYͮi P[ L:?=v8|`4nh7u{QE sU5Y7{C]_?{B^QSu; 3jV՞d;&xD\20-0b# !ڇ\)&q)% 1ON"ۂ%480`rH%Dd#C K .%"l %RQ NLHI($ux-LJ@J!^H :ggM597F7FN|[{}&Ff*pdk_ΜN0VG9ʱwDK4X=CaCɁg2)4X(rb0/s4lƵ.b]ʌ[r> stream xmTn0CƆ@LE"jD;oƤjgy_xN{qV'wC&]\]]u>t\qxں7ŦmN7isƬ'k~G]?ߓ` 4;RV_n86]{̭֚u[sfߴ L:?v>4|`0nhWu}QE KU=5Yw߇l?N6jwwv Z/բ,ko{&PaffIq XMJ0LfhrdĥP> stream xmTn0CƆ@LE"j.RC~8iZ)Ayo7?nkNy$냛G׎ծU[7|SlfM[kwʽ5g x=i6;RV׵_n85]֚̽u[OsE͡i P{ LՑ @4=tb/yVvL MnݞArjwf4P׏ީFT]Nrî}sBZ2pmmR?\rs<, X#.KIɌCH'hjmJIQ09da"2rG~\5hגQv]`n @v)(A'b}qHI($ux-JBJ!^I :ggM597F7FN}Y{}&Ff.pdk_ ΜN0VG9ʱwDK4X=CaCɁg2)4X(rb0/s4lƵǮb]ˌ[r> stream xmTn0CƆ@LE"h.RC~8iZ)Ayo7?^$ŝPIs77EW]}==硫nTشxGɛz?{k۝=` 4vN߷u8NM>(s&`ywS0jzQshz+&TuS~Hxqq`P<+ OC톦}SWUn}@`T;P3qtj}w*5UWSܰo\ze \[3. 9ff ؤdF@!i @F\ ` H sn4ȶ` $(Ng 2R0zd9#Cb.k(@.0[Czr aà8SuX$Q:\CAfpGR~m%^!N%$h&՚R #ƿp'XϾ>AI }3Nh25gNE'bkkؿs %|V !3?fc91ӊ9|u 6ZcWCab d1׮eF-9Ag깐3Z=I= 6-7p?)pegT> stream xmTn0CƆ@LE"j.RC~8M])A̼7W?^$PIsWWEW]}~{SCWmݨMi7mv9I+ڴg{ҏÄ~F )P ǦkZn;@1zz5= 7m=x Fgu P}?i]X<;k C톦}UYoO} A`TS7~wpjmS!詺]]ꂅK(ew&97\=̒5⒁yAa>:M1ȈK,x΍t,@F*&" C,zdWXPv-hakH/]d"btv"gg?|2JB^G5kdwt,uVT Jb9;kBX!00a0bw3W M";\88̿9Earʱs ށ?c>+q p~PrL  hi˜c>:q-+01~k2#Ϡ3\OLqRυ>¹M \)s9O \Y!O>\\/Au*[ӺkzT%C0t endstream endobj 360 0 obj << /Length 700 /Filter /FlateDecode >> stream xmTn0CƆ@LE"j.RC~8M])A̼7W?^$PIsWWEW]}~{SCWmݨMi7mv9I+ڴg{ҏÄ~F )P ǦkZn;@1zz5= 7m=x Fgu P}?i]X<;k C톦}UYoO} A`TS7~wpjmS!詺]]ꂅK(ew&97\=̒5⒁yAa>:M1ȈK,x΍t,@F*&" C,zdWXPv-hakH/]d"btv"gg?|2JB^G5kdwt,uVT Jb9;kBX!00a0bw3W M";\88̿9Earʱs ށ?c>+q p~PrL  hi˜c>:q-+01~k2#Ϡ3\OLqRυ>¹M \)s9O \Y!O>\\/Au*[ӺkzT%C2t endstream endobj 276 0 obj << /Type /ObjStm /N 100 /First 918 /Length 4328 /Filter /FlateDecode >> stream x[ko8_D$0XMN;dtzCp&jmbgl?KQ2%_bg9A+ȗX*V2i5J5/e*XzfM@ IX}h;tbXtC鵔 IWbwmFt%q V"n<:HĕœJ'Vic43\v$FUJtDC0e4,eiàc4 tKIAV ;؇i#^♶%)5: #X u<3RJ̪; @@E(f=XfN)E$1g,u,#ziYD,Y`AC$A̎$90` PDVeQ4fI NiaT[R2#   ]טvtJ<aIqH N%A+h@ϐNi+̎֓Z-\''Hk*(`Cjf@ ؆N*$ul4N8Eb<-7tF>vuCs,s d4 М?+F?0ŸO">t>mPCcDJy?3~'o׃g,Z*M .m!F>jXX+БBCѴyUTP +4 [sQBWaD!-BVFoU+Rpb}2G(x]:6w! M;L"Ɠ8=jSC(QS5”ԭHLJNIMm</$x}2RMBjx'c#e 3L_x$VB~ItLa<ˆ  (4\0V&.A *< 1%r7䔂#cX!3J!":ҧ¢U-F X)0((O]AP!wgQ͐(AfFH*yS@O#ⳤAQCPy8+CƀjCm-eNX^Ts doTskïqq0PTʊAp Ŗ.0 yhF|^T $5p*)Ra AU(' WWF=k*=xtn%ØSYDIp]>L]ոI%(gm AөN g ?$< LROe/(5P@GGTPfJ6. tf]M&a44%oZ1 վ';TΡpi6f88)R!BA$x-͡>]4G-6KЬ;IرosŽ#^mr%tml|o>M?Cw K#8w;\t= ^ψ"=C_k2&"$ MAD!hw[ñt0CH6"K, 鵣EeD4{Vpv@Aȕe%*(r n$){N}AU!Mn,q<7ܸjsRlre>p25!*WvDA}OXG-jI0dΓ]j}_>i^ƶ>X4% ƜGڣisښwim>y ŕN2 6+s*\6IhmI$.i3G&ʨIVv HW%Կu&ϭ^18YknM[q[L[⥢75aEW_+Wc/<6*0-vm"<F%n~3]$6t2?lS[E&fFp"*7CGw3eJ&_AuՒ,h[q7c qZ"oDѿiB LJV]w)4_Y\yEawM8+%lzi(N B6Ķ8 28Mnalm5́P$%\lFEe"L_kgMln2 ^w.kl•] buٵ h&Fj%fNjj%/BQ+ԓlldt N׳>}=7o&ТVx=^MћUBwe3 6dp]V_fM?ȫo~_^fa0ݣOGVq@l*UfnJ@95WQ^?W5R+bg׶'0\!V]Z67otX,)HzsZrC =CQRz#2'E52MGkh7D?ET؀g>U_k>ߺdnw}%<>P$2dP?{  | oc? ~w^[QVe~z9_᷊L9?TI#>*>\M1W:\Ϫϗ|Maٴ=MD᳋IUc~ÿ?w;V[޾y~JeI"^s#d\"/R&H %ٞX|oFgxRyeVًç/~z=|3=^>_B9Y #Fι\ns6%s6W}x8:YE!~  Fe.KZA7RuY$d^@.[O^] -HZ,%OϺ =).JvtrÙ[uEZ/v6&t8mYf8Z៺*}|œ(~!]ZwXm:NJ K[ѯۯ;] ǢuWF=1b:i}{?z~ޓwK{t9GXdzs])}}CeI3ϐ|ϑWĢtQ6'wA4_: fpKhp2+MӦLvUum 52}fvyɒdI̧k3dy-i|WR,u~R^N^\ Gw4+#'Trʸ+mhVZ-$sWS8mX+{<]ض,6~Bj,F/Sl_9J1 endstream endobj 387 0 obj << /Producer (pdfTeX-1.40.26) /Author(\376\377\000B\000j\000\366\000r\000n\000\040\000A\000s\000s\000m\000a\000n\000n)/Title(\376\377\000P\000o\000l\000e\000n\000t\000a)/Subject()/Creator(\376\377\000L\000a\000T\000e\000X\000\040\000w\000i\000t\000h\000\040\000h\000y\000p\000e\000r\000r\000e\000f\000\040\000p\000a\000c\000k\000a\000g\000e\000\040\000/\000\040\000G\000A\000P\000D\000o\000c)/Keywords() /CreationDate (D:19700101000000Z) /ModDate (D:19700101000000Z) /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024) kpathsea version 6.4.0) >> endobj 363 0 obj << /Type /ObjStm /N 36 /First 293 /Length 1578 /Filter /FlateDecode >> stream xڅXM6 1 (e4 (P0A ;%=lk'I|ViHsTN+ (,)@Y<8e l4A*DHhEd9ةyAŃʠ6|U|51*@]g8X,ȵgTV傳[/.,'D\Q2)9(#(=c,W P mY.+Ox+ 7y7iP~t 4ܤ \{sT̅E;G)ҞJG4Y8E3:\|Yl M#I >.8djj+GGo#vM0 =/Lgw;, c,9ʢ9E aOe+G bʽ5;me/go]2b1|]T1K pI0AUغER7.t>hSm4Uh눨&۫TۀIW"bۺK6tm;.mI,c%IgmWV1D|]"N:&ncOl1;[-CmL[ /袴!=S#.4hhr: xySbmuId6$ϭOW)Jm+k]J<BNs O]l_|yOc 1pY5ǯ|(X[7"K&.FKPtKb}@n1GZbt`jmj)f*XcFK?d k 5iS6Ne;aŃH,9um\_/Fom+{PO]?ڮxc`nvnd0q*oʗP^KuݡڝRns/搙q'q@pcc{ۊ%܂g~ ^|%3^:9bbn12}n, S si !Cf̋%y҆YY伛X4<)1/((eCnbf;SrZS$ڌ|{-[hN'FFK+#ḴI)Bi[<9+3۫uF\Ykǥs lA'/\ǥÂ5K# cx A0K2ĢkFG*I]ëj <BѡL4EPt rB!j}]1Zp:[=ME}8 /',/?J{ ƯX8iN%F㴅]a|Y? ?Sk|StM@NF>o+ _nw< ?}B>|{y﫡:J7 endstream endobj 388 0 obj << /Type /XRef /Index [0 389] /Size 389 /W [1 3 1] /Root 386 0 R /Info 387 0 R /ID [ ] /Length 945 /Filter /FlateDecode >> stream xMle)OZ mR Bi B 41y5`P &W*+X@BHnb!&K,Itg\4EVmM_֢ :Q4=zmԊ& Sh[A; um`;y5ڝh_t`n֬{8.t>R ap `(88')0 N)nup灶v\vW7VTyyHow  GkTM+@(2WC]pkGy uQGƃ) n?_ŭ3({J;edQE)6>-Pbi(3N2ʤBHb;Rt\ aAb?6ةSz}XĀ%fAr)#nU%9A^Ĉd 91<M+&16%>AT) R,EbTfbޭHVy\s{oi|!i`2>|Xۢ[zA#87ҘzjP5`-hzlflaYl@#@퇺o,=@k7L֢0O ͈p0T`=-ǟUv{v{UQuԽFՈ{ Uߴ:YHըgKNxÒ1~jǪ&M ČHL 2e˄ /^&Lx2e˄ /^&2uxӍr/k?ˢ endstream endobj startxref 237661 %%EOF polenta-1.3.11/doc/times.css000644 000766 000024 00000000261 14775712162 016141 0ustar00mhornstaff000000 000000 /* times.css Frank Lübeck */ /* Change default CSS to use Times font. */ body { font-family: Times,Times New Roman,serif; } polenta-1.3.11/doc/toggless.css000644 000766 000024 00000001672 14775712162 016656 0ustar00mhornstaff000000 000000 /* toggless.css Frank Lübeck */ /* Using javascript we change all div.ContSect to div.ContSectOpen or div.ContSectClosed. This way the config for div.ContSect in manual.css is no longer relevant. Here we add the CSS for the new elements. */ /* This layout is based on an idea by Burkhard Höfling. */ div.ContSectClosed { text-align: left; margin-left: 1em; } div.ContSectOpen { text-align: left; margin-left: 1em; } div.ContSectOpen div.ContSSBlock { display: block; text-align: left; margin-left: 1em; } div.ContSectOpen div.ContSSBlock a { display: block; width: 100%; margin-left: 1em; } span.tocline a:hover { display: inline; background: #eeeeee; } span.ContSS a:hover { display: inline; background: #eeeeee; } span.toctoggle { font-size: 80%; display: inline-block; width: 1.2em; } span.toctoggle:hover { background-color: #aaaaaa; } polenta-1.3.11/doc/chap2.txt000644 000766 000024 00000025051 14775712156 016053 0ustar00mhornstaff000000 000000 2 Methods for matrix groups 2.1 Polycyclic presentations of matrix groups Groups defined by polycyclic presentations are called PcpGroups in GAP. We refer to the Polycyclic manual [EN00] for further background. Suppose that a collection X of matrices of GL(d,R) is given, where the ring R is either ℚ,ℤ or a finite field. Let G= ⟨ X ⟩. If the group G is polycyclic, then the following functions determine a PcpGroup isomorphic to G. 2.1-1 PcpGroupByMatGroup PcpGroupByMatGroup( G )  operation G is a subgroup of GL(d,R) where R=ℚ,ℤ or F_q. If G is polycyclic, then this function determines a PcpGroup isomorphic to G. If G is not polycyclic, then this function returns fail. 2.1-2 IsomorphismPcpGroup IsomorphismPcpGroup( G )  method G is a subgroup of GL(d,R) where R=ℚ,ℤ or F_q. If G is polycyclic, then this function determines an isomorphism onto a PcpGroup. If G is not polycyclic, then this function returns fail. Note that the method IsomorphismPcpGroup, installed in this package, cannot be applied directly to a group given by the function AlmostCrystallographicGroup. Please use POL_AlmostCrystallographicGroup (with the same parameters as AlmostCrystallographicGroup) instead. 2.1-3 ImagesRepresentative ImagesRepresentative( map, elm )  method ImageElm( map, elm )  method ImagesSet( map, elms )  method Here map is an isomorphism from a polycyclic matrix group G onto a PcpGroup H calculated by IsomorphismPcpGroup (2.1-2). These methods can be used to compute with such an isomorphism. If the input elm is an element of G, then the function ImageElm can be used to compute the image of elm under map. If elm is not contained in G then the function ImageElm returns fail. The input pcpelm is an element of H. 2.1-4 IsSolvableGroup IsSolvableGroup( G )  method G is a subgroup of GL(d,R) where R=ℚ,ℤ or F_q. This function tests if G is solvable and returns true or false. 2.1-5 IsTriangularizableMatGroup IsTriangularizableMatGroup( G )  property G is a subgroup of GL(d,ℚ). This function tests if G is triangularizable (possibly over a finite field extension) and returns true or false. 2.1-6 IsPolycyclicGroup IsPolycyclicGroup( G )  method G is a subgroup of GL(d,R) where R=ℚ,ℤ or F_q. This function tests if G is polycyclic and returns true or false. 2.2 Module series Let G be a finitely generated solvable subgroup of GL(d,ℚ). The vector space ℚ^d is a module for the algebra ℚ[G]. The following functions provide the possibility to compute certain module series of ℚ^d. Recall that the radical Rad_G(ℚ^d) is defined to be the intersection of maximal ℚ[G]-submodules of ℚ^d. Also recall that the radical series 0=R_n < R_{n-1} < \dots < R_1 < R_0=ℚ^d  is defined by R_i+1:= Rad_G(R_i). 2.2-1 RadicalSeriesSolvableMatGroup RadicalSeriesSolvableMatGroup( G )  operation This function returns a radical series for the ℚ[G]-module ℚ^d, where G is a solvable subgroup of GL(d,ℚ). A radical series of ℚ^d can be refined to a homogeneous series. 2.2-2 HomogeneousSeriesAbelianMatGroup HomogeneousSeriesAbelianMatGroup( G )  function A module is said to be homogeneous if it is the direct sum of pairwise irreducible isomorphic submodules. A homogeneous series of a module is a submodule series such that the factors are homogeneous. This function returns a homogeneous series for the ℚ[G]-module ℚ^d, where G is an abelian subgroup of GL(d,ℚ). 2.2-3 HomogeneousSeriesTriangularizableMatGroup HomogeneousSeriesTriangularizableMatGroup( G )  function A module is said to be homogeneous if it is the direct sum of pairwise irreducible isomorphic submodules. A homogeneous series of a module is a submodule series such that the factors are homogeneous. This function returns a homogeneous series for the ℚ[G]-module ℚ^d, where G is a triangularizable subgroup of GL(d,ℚ). A homogeneous series can be refined to a composition series. 2.2-4 CompositionSeriesAbelianMatGroup CompositionSeriesAbelianMatGroup( G )  function A composition series of a module is a submodule series such that the factors are irreducible. This function returns a composition series for the ℚ[G]-module ℚ^d, where G is an abelian subgroup of GL(d,ℚ). 2.2-5 CompositionSeriesTriangularizableMatGroup CompositionSeriesTriangularizableMatGroup( G )  function A composition series of a module is a submodule series such that the factors are irreducible. This function returns a composition series for the ℚ[G]-module ℚ^d, where G is a triangularizable subgroup of GL(d,ℚ). 2.3 Subgroups 2.3-1 SubgroupsUnipotentByAbelianByFinite SubgroupsUnipotentByAbelianByFinite( G )  operation G is a subgroup of GL(d,R) where R=ℚ or ℤ. If G is polycyclic, then this function returns a record containing two normal subgroups T and U of G. The group T is unipotent-by-abelian (and thus triangularizable) and of finite index in G. The group U is unipotent and is such that T/U is abelian. If G is not polycyclic, then the algorithm returns fail. 2.4 Examples 2.4-1 PolExamples PolExamples( l )  function Returns some examples for polycyclic rational matrix groups, where l is an integer between 1 and 24. These can be used to test the functions in this package. Some of the properties of the examples are summarised in the following table.  Example  PolExamples number generators subgroup of Hirsch length  1 3 GL(4,Z) 6  2 2 GL(5,Z) 6  3 2 GL(4,Q) 4  4 2 GL(5,Q) 6  5 9 GL(16,Z) 3  6 6 GL(4,Z) 3  7 6 GL(4,Z) 3  8 7 GL(4,Z) 3  9 5 GL(4,Q) 3  10 4 GL(4,Q) 3  11 5 GL(4,Q) 3  12 5 GL(4,Q) 3  13 5 GL(5,Q) 4  14 6 GL(5,Q) 4  15 6 GL(5,Q) 4  16 5 GL(5,Q) 4  17 5 GL(5,Q) 4  18 5 GL(5,Q) 4  19 5 GL(5,Q) 4  20 7 GL(16,Z) 3  21 5 GL(16,Q) 3  22 4 GL(16,Q) 3  23 5 GL(16,Q) 3  24 5 GL(16,Q) 3   polenta-1.3.11/doc/methods.xml000644 000766 000024 00000030253 14775712140 016473 0ustar00mhornstaff000000 000000 Methods for matrix groups
Polycyclic presentations of matrix groups Groups defined by polycyclic presentations are called PcpGroups in &GAP;. We refer to the Polycyclic manual for further background.

Suppose that a collection X of matrices of GL(d,R) is given, where the ring R is either &QQ;,&ZZ; or a finite field. Let G= \langle X \rangle. If the group G is polycyclic, then the following functions determine a PcpGroup isomorphic to G. G is a subgroup of GL(d,R) where R=&QQ;,&ZZ; or \mathbb{F}_q. If G is polycyclic, then this function determines a PcpGroup isomorphic to G. If G is not polycyclic, then this function returns fail. G is a subgroup of GL(d,R) where R=&QQ;,&ZZ; or \mathbb{F}_q. If G is polycyclic, then this function determines an isomorphism onto a PcpGroup. If G is not polycyclic, then this function returns fail.

Note that the method IsomorphismPcpGroup, installed in this package, cannot be applied directly to a group given by the function AlmostCrystallographicGroup. Please use POL_AlmostCrystallographicGroup (with the same parameters as AlmostCrystallographicGroup) instead. Here map is an isomorphism from a polycyclic matrix group G onto a PcpGroup H calculated by . These methods can be used to compute with such an isomorphism. If the input elm is an element of G, then the function ImageElm can be used to compute the image of elm under map. If elm is not contained in G then the function ImageElm returns fail. The input pcpelm is an element of H. G is a subgroup of GL(d,R) where R=&QQ;,&ZZ; or \mathbb{F}_q. This function tests if G is solvable and returns true or false. G is a subgroup of GL(d,&QQ;). This function tests if G is triangularizable (possibly over a finite field extension) and returns true or false. G is a subgroup of GL(d,R) where R=&QQ;,&ZZ; or \mathbb{F}_q. This function tests if G is polycyclic and returns true or false.

Module series Let G be a finitely generated solvable subgroup of GL(d,&QQ;). The vector space &QQ;^d is a module for the algebra &QQ;[G]. The following functions provide the possibility to compute certain module series of &QQ;^d. Recall that the radical Rad_G(&QQ;^d) is defined to be the intersection of maximal &QQ;[G]-submodules of &QQ;^d. Also recall that the radical series 0=R_n < R_{n-1} < \dots < R_1 < R_0=&QQ;^d is defined by R_{i+1}:= Rad_G(R_i). This function returns a radical series for the &QQ;[G]-module &QQ;^d, where G is a solvable subgroup of GL(d,&QQ;).

A radical series of &QQ;^d can be refined to a homogeneous series. A module is said to be homogeneous if it is the direct sum of pairwise irreducible isomorphic submodules. A homogeneous series of a module is a submodule series such that the factors are homogeneous. This function returns a homogeneous series for the &QQ;[G]-module &QQ;^d, where G is an abelian subgroup of GL(d,&QQ;). A module is said to be homogeneous if it is the direct sum of pairwise irreducible isomorphic submodules. A homogeneous series of a module is a submodule series such that the factors are homogeneous. This function returns a homogeneous series for the &QQ;[G]-module &QQ;^d, where G is a triangularizable subgroup of GL(d,&QQ;).

A homogeneous series can be refined to a composition series. A composition series of a module is a submodule series such that the factors are irreducible. This function returns a composition series for the &QQ;[G]-module &QQ;^d, where G is an abelian subgroup of GL(d,&QQ;). A composition series of a module is a submodule series such that the factors are irreducible. This function returns a composition series for the &QQ;[G]-module &QQ;^d, where G is a triangularizable subgroup of GL(d,&QQ;).

Subgroups G is a subgroup of GL(d,R) where R=&QQ; or &ZZ;. If G is polycyclic, then this function returns a record containing two normal subgroups T and U of G. The group T is unipotent-by-abelian (and thus triangularizable) and of finite index in G. The group U is unipotent and is such that T/U is abelian. If G is not polycyclic, then the algorithm returns fail.
Examples Returns some examples for polycyclic rational matrix groups, where l is an integer between 1 and 24. These can be used to test the functions in this package. Some of the properties of the examples are summarised in the following table.
polenta-1.3.11/doc/chap3.txt000644 000766 000024 00000013566 14775712156 016064 0ustar00mhornstaff000000 000000 3 An example application In this section we outline three example computations with functions from the previous chapter. 3.1 Presentation for rational matrix groups  Example  gap> mats := [ [ [ 1, 0, -1/2, 0 ], [ 0, 1, 0, 1 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 1/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 1 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 0, 0, 1 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -1/2, -3, 7/6 ], [ 0, 1, -1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ],  [ [ -1, 3, 3, 0 ], [ 0, 0, 1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ] ];  gap> G := Group( mats );   # calculate an isomorphism from G to a pcp-group gap> nat := IsomorphismPcpGroup( G );;  gap> H := Image( nat ); Pcp-group with orders [ 2, 2, 3, 5, 5, 5, 0, 0, 0 ]  gap> h := GeneratorsOfGroup( H ); [ g1, g2, g3, g4, g5, g6, g7, g8, g9]  gap> mats2 := List( h, x -> PreImage( nat, x ) );;  # take a random element of G gap> exp := [ 1, 1, 1, 1, 0, 0, 0, 0, 1 ];; gap> g := MappedVector( exp, mats2 ); [ [ -1, 17/2, -1, 233/6 ],  [ 0, 1, 0, -2 ],  [ 0, 1, -1, 2 ],  [ 0, 0, 0, 1 ] ]  # map g into the image of nat gap> i := ImageElm( nat, g ); g1*g2*g3*g4*g9  # exponent vector gap> Exponents( i ); [ 1, 1, 1, 1, 0, 0, 0, 0, 1 ]  # compare the preimage with g gap> PreImagesRepresentative( nat, i ); [ [ -1, 17/2, -1, 233/6 ],  [ 0, 1, 0, -2 ],  [ 0, 1, -1, 2 ],  [ 0, 0, 0, 1 ] ]   gap> last = g; true   3.2 Modules series  Example  gap> gens := [ [ [ 1746/1405, 524/7025, 418/1405, -77/2810 ],  [ 815/843, 899/843, -1675/843, 415/281 ],  [ -3358/4215, -3512/21075, 4631/4215, -629/1405 ],  [ 258/1405, 792/7025, 1404/1405, 832/1405 ] ],  [ [ -2389/2810, 3664/21075, 8942/4215, -35851/16860 ],  [ 395/281, 2498/2529, -5105/5058, 3260/2529 ],  [ 3539/2810, -13832/63225, -12001/12645, 87053/50580 ],  [ 5359/1405, -3128/21075, -13984/4215, 40561/8430 ] ] ];  gap> H := Group( gens );   gap> RadicalSeriesSolvableMatGroup( H ); [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 0, 0, 79/138 ], [ 0, 1, 0, -275/828 ], [ 0, 0, 1, -197/414 ] ],  [ [ 1, 0, -3, 2 ], [ 0, 1, 55/4, -55/8 ] ],  [ [ 1, 4/15, 2/3, 1/6 ] ],  [ ] ]  3.3 Triangularizable subgroups  Example  gap> G := PolExamples(3);   gap> GeneratorsOfGroup( G ); [ [ [ 73/10, -35/2, 42/5, 63/2 ],  [ 27/20, -11/4, 9/5, 27/4 ],  [ -3/5, 1, -4/5, -9 ],  [ -11/20, 7/4, -2/5, 1/4 ] ],  [ [ -42/5, 423/10, 27/5, 479/10 ],  [ -23/10, 227/20, 13/10, 231/20 ],  [ 14/5, -63/5, -4/5, -79/5 ],  [ -1/10, 9/20, 1/10, 37/20 ] ] ]  gap> subgroups := SubgroupsUnipotentByAbelianByFinite( G ); rec( T := ,  U := )  gap> GeneratorsOfGroup( subgroups.T ); [ [ [ 73/10, -35/2, 42/5, 63/2 ],  [ 27/20, -11/4, 9/5, 27/4 ],  [ -3/5, 1, -4/5, -9 ],  [ -11/20, 7/4, -2/5, 1/4 ] ],  [ [ -42/5, 423/10, 27/5, 479/10 ],  [ -23/10, 227/20, 13/10, 231/20 ],  [ 14/5, -63/5, -4/5, -79/5 ],  [ -1/10, 9/20, 1/10, 37/20 ] ] ]  # so G is triangularizable!  polenta-1.3.11/doc/chapBib.html000644 000766 000024 00000010376 14775712162 016534 0ustar00mhornstaff000000 000000 GAP (Polenta) - References
Goto Chapter: Top 1 2 3 4 5 Bib Ind

References

[AE05] Assmann, B. and Eick, B., Computing polycyclic presentations for polycyclic rational matrix groups, J. Symbolic Comput., 40 (6) (2005), 1269--1284.

[Ass03] Assmann, B., Polycyclic presentations for matrix groups, Diplomarbeit, TU Braunschweig (2003)
(http://www.icm.tu-bs.de/ag_algebra/software/assmann).

[Eic01] Eick, B., Algorithms for Polycyclic Groups, Habilitationsschrift, Gesamthochschule Kassel (2001).

[EN00] Eick, B. and Nickel, W., Polycyclic (2000)
(GAP package).

[Ost96] Ostheimer, G., Algorithms for Polycyclic-by-finite groups, Ph.D. thesis, Rutgers University (1996).

[Sim94] Sims, C. C., Computation with finitely presented groups, Cambridge University Press (1994).

Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/polentabib.xml.bib000644 000766 000024 00000004413 14775712156 017710 0ustar00mhornstaff000000 000000 @phdthesis{ Ostheimer, author = {Ostheimer, G.}, title = {Algorithms for Polycyclic\texttt{\symbol{45}}by\texttt{\symbol{45}}finite groups}, school = {Rutgers University}, year = {1996}, printedkey = {Ost96} } @book{ Segal, author = {Segal, D.}, title = {Polycyclic groups}, publisher = {Cambridge University Press}, year = {1983}, printedkey = {Seg83} } @book{ Sims, author = {Sims, C. C.}, title = {Computation with finitely presented groups}, publisher = {Cambridge University Press}, year = {1994}, printedkey = {Sim94} } @mastersthesis{ Eick, author = {Eick, B.}, title = {Algorithms for Polycyclic Groups}, school = {Gesamthochschule Kassel}, year = {2001}, printedkey = {Eic01}, type = {Habilitationsschrift} } @mastersthesis{ Assmann, author = {Assmann, B.}, title = {Polycyclic presentations for matrix groups}, school = {TU Braunschweig}, year = {2003}, note = {\href {http://www.icm.tu-bs.de/ag_algebra/software/assmann} {\texttt{http://www.icm.tu\texttt{\symbol{45}}bs.de/}\discretionary {}{}{}\texttt{ag{\textunderscore}algebra/}\discretionary {}{}{}\texttt{software/}\discretionary {}{}{}\texttt{assmann}}}, printedkey = {Ass03}, type = {Diplomarbeit} } @manual{ Polycyclic, author = {Eick, B. and Nickel, W.}, title = {Polycyclic}, year = {2000}, note = {GAP package}, printedkey = {EN00} } @article{ AEi05, author = {Assmann, B. and Eick, B.}, title = {Computing polycyclic presentations for polycyclic rational matrix groups}, journal = {J. Symbolic Comput.}, volume = {40}, number = {6}, year = {2005}, pages = {1269\texttt{\symbol{45}}\texttt{\symbol{45}}1284}, printedkey = {AE05} } polenta-1.3.11/doc/chap0.html000644 000766 000024 00000021001 14775712162 016162 0ustar00mhornstaff000000 000000 GAP (Polenta) - Contents
Goto Chapter: Top 1 2 3 4 5 Bib Ind

Polenta

Polycyclic presentations for matrix groups

1.3.11

10 April 2025

Björn Assmann

Copyright

© 2003-2007 by Björn Assmann

The Polenta package 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.

Acknowledgements

We appreciate very much all past and future comments, suggestions and contributions to this package and its documentation provided by GAP users and developers.

Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/chap1.txt000644 000766 000024 00000004565 14775712156 016061 0ustar00mhornstaff000000 000000 1 Introduction 1.1 The package This package provides functions for computation with matrix groups. Let G be a subgroup of GL(d,R) where the ring R is either equal to ℚ,ℤ or a finite field F_q. Then:  We can test whether G is solvable.  We can test whether G is polycyclic.  If G is polycyclic, then we can determine a polycyclic presentation for G. A group G which is given by a polycyclic presentation can be largely investigated by algorithms implemented in the GAP-package Polycyclic [EN00]. For example we can determine if G is torsion-free and calculate the torsion subgroup. Further we can compute the derived series and the Hirsch length of the group G. Also various methods for computations with subgroups, factor groups and extensions are available. As a by-product, the Polenta package provides some functionality to compute certain module series for modules of solvable groups. For example, if G is a rational polycyclic matrix group, then we can compute the radical series of the natural ℚ[G]-module ℚ^d. 1.2 Polycyclic groups A group G is called polycyclic if it has a finite subnormal series with cyclic factors. It is a well-known fact that every polycyclic group is finitely presented by a so-called polycyclic presentation (see for example Chapter 9 in [Sim94] or Chapter 2 in [EN00] ). In GAP, groups which are defined by polycyclic presentations are called polycyclically presented groups, abbreviated PcpGroups. The overall idea of the algorithm implemented in this package was first introduced by Ostheimer in 1996 [Ost96]. In 2001 Eick presented a more detailed version [Eic01]. This package contains an implementation of Eick's algorithm. A description of this implementation together with some refinements and extensions can be found in [AE05] and [Ass03]. polenta-1.3.11/doc/chap0.txt000644 000766 000024 00000005037 14775712156 016053 0ustar00mhornstaff000000 000000  Polenta   Polycyclic presentations for matrix groups  1.3.11 10 April 2025 Björn Assmann ------------------------------------------------------- Copyright © 2003-2007 by Björn Assmann The Polenta package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (https://www.fsf.org/licenses/gpl.html) as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ------------------------------------------------------- Acknowledgements We appreciate very much all past and future comments, suggestions and contributions to this package and its documentation provided by GAP users and developers. ------------------------------------------------------- Contents (Polenta) 1 Introduction 1.1 The package 1.2 Polycyclic groups 2 Methods for matrix groups 2.1 Polycyclic presentations of matrix groups 2.1-1 PcpGroupByMatGroup 2.1-2 IsomorphismPcpGroup 2.1-3 ImagesRepresentative 2.1-4 IsSolvableGroup 2.1-5 IsTriangularizableMatGroup 2.1-6 IsPolycyclicGroup 2.2 Module series 2.2-1 RadicalSeriesSolvableMatGroup 2.2-2 HomogeneousSeriesAbelianMatGroup 2.2-3 HomogeneousSeriesTriangularizableMatGroup 2.2-4 CompositionSeriesAbelianMatGroup 2.2-5 CompositionSeriesTriangularizableMatGroup 2.3 Subgroups 2.3-1 SubgroupsUnipotentByAbelianByFinite 2.4 Examples 2.4-1 PolExamples 3 An example application 3.1 Presentation for rational matrix groups 3.2 Modules series 3.3 Triangularizable subgroups 4 Installation 4.1 Installing this package 4.2 Loading the Polenta package 4.3 Running the test suite 5 Information Messages 5.1 Info Class 5.1-1 InfoPolenta 5.2 Example  polenta-1.3.11/doc/chap4_mj.html000644 000766 000024 00000012700 14775712162 016662 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 4: Installation
Goto Chapter: Top 1 2 3 4 5 Bib Ind

4 Installation

4.1 Installing this package

The Polenta package is part of the standard distribution of GAP and so normally there should be no need to install it separately. If by any chance it is not part of your GAP distribution, then the standard method is to unpack the package into the pkg directory of your GAP distribution. This will create a polenta subdirectory. For other non-standard options please see Chapter Reference: Installing a GAP Package of the GAP Reference Manual.

Note that the GAP-Packages Alnuth and Polycyclic are needed for this package. Normally they should be contained in your distribution. If not, they can be obtained at https://www.gap-system.org/Packages/packages.html.

4.2 Loading the Polenta package

If the Polenta package is not already loaded then you have to request it explicitly. This can be done via the LoadPackage (Reference: LoadPackage) command.

4.3 Running the test suite

Once the package is installed, it is possible to check the correct installation by running the test suite of the package.

    gap> ReadPackage( "Polenta", "tst/testall.g" );

For more details on Test Files see Section Reference: Test Files of the GAP Reference Manual.

If the test suite runs into an error, even though the packages Polycyclic and Alnuth and their depdendencies have been correctly installed, then please send a message to mhorn@rptu.de including the error message.

Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/manual.css000644 000766 000024 00000015754 14775712162 016312 0ustar00mhornstaff000000 000000 /* manual.css Frank Lübeck */ /* This is the default CSS style sheet for GAPDoc HTML manuals. */ /* basic settings, fonts, sizes, colors, ... */ body { position: relative; background: #ffffff; color: #000000; width: 70%; margin: 0pt; padding: 15pt; font-family: Helvetica,Verdana,Arial,sans-serif; text-align: justify; } /* no side toc on title page, bib and index */ body.chap0 { width: 95%; } body.chapBib { width: 95%; } body.chapInd { width: 95%; } h1 { font-size: 200%; } h2 { font-size: 160%; } h3 { font-size: 160%; } h4 { font-size: 130%; } h5 { font-size: 100%; } p.foot { font-size: 60%; font-style: normal; } a:link { color: #00008e; text-decoration: none; } a:visited { color: #00008e; text-decoration: none; } a:active { color: #000000; text-decoration: none; } a:hover { background: #eeeeee; } pre { font-family: "Courier New",Courier,monospace; font-size: 100%; color:#111111; } tt,code { font-family: "Courier New",Courier,monospace; font-size: 110%; color: #000000; } var { } /* general alignment classes */ .pcenter { text-align: center; } .pleft { text-align: left; } .pright { text-align: right; } /* layout for the definitions of functions, variables, ... */ div.func { background: #e0e0e0; margin: 0pt 0pt; } /* general and special table settings */ table { border-collapse: collapse; margin-left: auto; margin-right: auto; } td, th { border-style: none; } table.func { padding: 0pt 1ex; margin-left: 1ex; margin-right: 1ex; background: transparent; /* line-height: 1.1; */ width: 100%; } table.func td.tdright { padding-right: 2ex; } /* Example elements (for old converted manuals, now in div+pre */ table.example { background: #efefef; border-style: none; border-width: 0pt; padding: 0px; width: 100% } table.example td { border-style: none; border-width: 0pt; padding: 0ex 1ex; } /* becomes ... */ div.example { background: #efefef; padding: 0ex 1ex; /* overflow-x: auto; */ overflow: auto; } /* Links to chapters in all files at top and bottom. */ /* If there are too many chapters then use 'display: none' here. */ div.chlinktop { background: #dddddd; border-style: solid; border-width: thin; margin: 2px; text-align: center; } div.chlinktop a { margin: 3px; } div.chlinktop a:hover { background: #ffffff; } div.chlinkbot { background: #dddddd; border-style: solid; border-width: thin; margin: 2px; text-align: center; /* width: 100%; */ } div.chlinkbot a { margin: 3px; } span.chlink1 { } /* and this is for the "Top", "Prev", "Next" links */ div.chlinkprevnexttop { background: #dddddd; border-style: solid; border-width: thin; text-align: center; margin: 2px; } div.chlinkprevnexttop a:hover { background: #ffffff; } div.chlinkprevnextbot { background: #dddddd; border-style: solid; border-width: thin; text-align: center; margin: 2px; } div.chlinkprevnextbot a:hover { background: #ffffff; } /* table of contents, initially don't display subsections */ div.ContSSBlock { display: none; } div.ContSSBlock br { display: none; } /* format in separate lines */ span.tocline { display: block; width: 100%; } div.ContSSBlock a { display: block; } /* this is for the main table of contents */ div.ContChap { } div.ContChap div.ContSect:hover div.ContSSBlock { display: block; position: absolute; background: #eeeeee; border-style: solid; border-width: 1px 4px 4px 1px; border-color: #666666; padding-left: 0.5ex; color: #000000; left: 20%; width: 40%; z-index: 10000; } div.ContSSBlock a:hover { background: #ffffff; } /* and here for the side menu of contents in the chapter files */ div.ChapSects { } div.ChapSects a:hover { background: #eeeeee; } div.ChapSects a:hover { display: block; width: 100%; background: #eeeeee; color: #000000; } div.ChapSects div.ContSect:hover div.ContSSBlock { display: block; position: fixed; background: #eeeeee; border-style: solid; border-width: 1px 2px 2px 1px; border-color: #666666; padding-left: 0ex; padding-right: 0.5ex; color: #000000; left: 54%; width: 25%; z-index: 10000; } div.ChapSects div.ContSect:hover div.ContSSBlock a { display: block; margin-left: 3px; } div.ChapSects div.ContSect:hover div.ContSSBlock a:hover { display: block; background: #ffffff; } div.ContSect { text-align: left; margin-left: 1em; } div.ChapSects { position: fixed; left: 75%; font-size: 90%; overflow: auto; top: 10px; bottom: 0px; } /* Table elements */ table.GAPDocTable { border-collapse: collapse; border-style: none; border-color: black; } table.GAPDocTable td, table.GAPDocTable th { padding: 3pt; border-width: thin; border-style: solid; border-color: #555555; } caption.GAPDocTable { caption-side: bottom; width: 70%; margin-top: 1em; margin-left: auto; margin-right: auto; } td.tdleft { text-align: left; } table.GAPDocTablenoborder { border-collapse: collapse; border-style: none; border-color: black; } table.GAPDocTablenoborder td, table.GAPDocTable th { padding: 3pt; border-width: 0pt; border-style: solid; border-color: #555555; } caption.GAPDocTablenoborder { caption-side: bottom; width: 70%; margin-top: 1em; margin-left: auto; margin-right: auto; } td.tdleft { text-align: left; } td.tdright { text-align: right; } td.tdcenter { text-align: center; } /* Colors and fonts can be overwritten for some types of elements. */ /* Verb elements */ pre.normal { color: #000000; } /* Func-like elements and Ref to Func-like */ code.func { color: #000000; } /* K elements */ code.keyw { color: #770000; } /* F elements */ code.file { color: #8e4510; } /* C elements */ code.code { } /* Item elements */ code.i { } /* Button elements */ strong.button { } /* Headings */ span.Heading { } /* Arg elements */ var.Arg { color: #006600; } /* Example elements, is in tables, see above */ div.Example { } /* Package elements */ strong.pkg { } /* URL-like elements */ span.URL { } /* Mark elements */ strong.Mark { } /* Ref elements */ b.Ref { } span.Ref { } /* this contains the contents page */ div.contents { } /* this contains the index page */ div.index { } /* ignore some text for non-css layout */ span.nocss { display: none; } /* colors for ColorPrompt like examples */ span.GAPprompt { color: #000097; font-weight: normal; } span.GAPbrkprompt { color: #970000; font-weight: normal; } span.GAPinput { color: #970000; } /* Bib entries */ p.BibEntry { } span.BibKey { color: #005522; } span.BibKeyLink { } b.BibAuthor { } i.BibTitle { } i.BibBookTitle { } span.BibEditor { } span.BibJournal { } span.BibType { } span.BibPublisher { } span.BibSchool { } span.BibEdition { } span.BibVolume { } span.BibSeries { } span.BibNumber { } span.BibPages { } span.BibOrganization { } span.BibAddress { } span.BibYear { } span.BibPublisher { } span.BibNote { } span.BibHowpublished { } polenta-1.3.11/doc/chap4.txt000644 000766 000024 00000003777 14775712156 016070 0ustar00mhornstaff000000 000000 4 Installation 4.1 Installing this package The Polenta package is part of the standard distribution of GAP and so normally there should be no need to install it separately. If by any chance it is not part of your GAP distribution, then the standard method is to unpack the package into the pkg directory of your GAP distribution. This will create a polenta subdirectory. For other non-standard options please see Chapter 'Reference: Installing a GAP Package' of the GAP Reference Manual. Note that the GAP-Packages Alnuth and Polycyclic are needed for this package. Normally they should be contained in your distribution. If not, they can be obtained at https://www.gap-system.org/Packages/packages.html. 4.2 Loading the Polenta package If the Polenta package is not already loaded then you have to request it explicitly. This can be done via the LoadPackage (Reference: LoadPackage) command. 4.3 Running the test suite Once the package is installed, it is possible to check the correct installation by running the test suite of the package.  Example   gap> ReadPackage( "Polenta", "tst/testall.g" );  For more details on Test Files see Section 'Reference: Test Files' of the GAP Reference Manual. If the test suite runs into an error, even though the packages Polycyclic and Alnuth and their depdendencies have been correctly installed, then please send a message to mhorn@rptu.de including the error message. polenta-1.3.11/doc/chap5.txt000644 000766 000024 00000027076 14775712156 016067 0ustar00mhornstaff000000 000000 5 Information Messages It is possible to get informations about the status of the computation of the functions of Chapter 2 of this manual. 5.1 Info Class 5.1-1 InfoPolenta InfoPolenta  info class is the Info class of the Polenta package (for more details on the Info mechanism see Section 'Reference: Info Functions' of the GAP Reference Manual). With the help of the function SetInfoLevel(InfoPolenta,level) you can change the info level of InfoPolenta.  If InfoLevel( InfoPolenta ) is equal to 0 then no information messages are displayed.  If InfoLevel( InfoPolenta ) is equal to 1 then basic informations about the process are provided. For further background on the displayed informations we refer to [Ass03] (publicly available via the Internet address http://www.icm.tu-bs.de/ag_algebra/software/assmann/diploma.pdf).  If InfoLevel( InfoPolenta ) is equal to 2 then, in addition to the basic information, the generators of computed subgroups and module series are displayed. 5.2 Example  Example  gap> SetInfoLevel( InfoPolenta, 1 );  gap> PcpGroupByMatGroup( PolExamples(11) ); #I Determine a constructive polycyclic sequence  for the input group ... #I #I Chosen admissible prime: 3 #I #I Determine a constructive polycyclic sequence  for the image under the p-congruence homomorphism ... #I finished. #I Finite image has relative orders [ 3, 2, 3, 3, 3 ]. #I #I Compute normal subgroup generators for the kernel  of the p-congruence homomorphism ... #I finished. #I #I Compute the radical series ... #I finished. #I The radical series has length 4. #I #I Compute the composition series ... #I finished. #I The composition series has length 5. #I #I Compute a constructive polycyclic sequence  for the induced action of the kernel to the composition series ... #I finished. #I This polycyclic sequence has relative orders [ ]. #I #I Calculate normal subgroup generators for the  unipotent part ... #I finished. #I #I Determine a constructive polycyclic sequence  for the unipotent part ... #I finished. #I The unipotent part has relative orders #I [ 0, 0, 0 ]. #I #I ... computation of a constructive  polycyclic sequence for the whole group finished. #I #I Compute the relations of the polycyclic  presentation of the group ... #I Compute power relations ... #I ... finished. #I Compute conjugation relations ... #I ... finished. #I Update polycyclic collector ... #I ... finished. #I finished. #I #I Construct the polycyclic presented group ... #I finished. #I Pcp-group with orders [ 3, 2, 3, 3, 3, 0, 0, 0 ]   gap> SetInfoLevel( InfoPolenta, 2 );  gap> PcpGroupByMatGroup( PolExamples(11) ); #I Determine a constructive polycyclic sequence  for the input group ... #I #I Chosen admissible prime: 3 #I #I Determine a constructive polycyclic sequence  for the image under the p-congruence homomorphism ... #I finished. #I Finite image has relative orders [ 3, 2, 3, 3, 3 ]. #I #I Compute normal subgroup generators for the kernel  of the p-congruence homomorphism ... #I finished. #I The normal subgroup generators are #I [ [ [ 1, -3/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 0, 0, 24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3, 3, 15 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3, 3, 9 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3/2, 3/2, 3/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3/2, 9/2, -69/2 ], [ 0, 1, 0, 9 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ]  , [ [ 1, 0, 0, -24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, -3, -15 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3/2, -3/2, -9/2 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ]  ],  [ [ 1, -3, -3, -12 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3, -3/2, -21 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3/2, 3/2, 9/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ] ] #I #I Compute the radical series ... #I finished. #I The radical series has length 4. #I The radical series is #I [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 0, 1 ] ],  [ ] ] #I #I Compute the composition series ... #I finished. #I The composition series has length 5. #I The composition series is #I [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 0, 1 ] ], [ ] ] #I #I Compute a constructive polycyclic sequence  for the induced action of the kernel to the composition series ... #I finished. #I This polycyclic sequence has relative orders [ ]. #I #I Calculate normal subgroup generators for the  unipotent part ... #I finished. #I The normal subgroup generators for the unipotent part are #I [ [ [ 1, -3/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 0, 0, 24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3, 3, 15 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3, 3, 9 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3/2, 3/2, 3/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3/2, 9/2, -69/2 ], [ 0, 1, 0, 9 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ]  , [ [ 1, 0, 0, -24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, -3, -15 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, -3/2, -3/2, -9/2 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ]  ],  [ [ 1, -3, -3, -12 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3, -3/2, -21 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],  [ [ 1, 3/2, 3/2, 9/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ] ] #I #I Determine a constructive polycyclic sequence  for the unipotent part ... #I finished. #I The unipotent part has relative orders #I [ 0, 0, 0 ]. #I #I ... computation of a constructive  polycyclic sequence for the whole group finished. #I #I Compute the relations of the polycyclic  presentation of the group ... #I Compute power relations ... ..... #I ... finished. #I Compute conjugation relations ... .............................................. #I ... finished. #I Update polycyclic collector ... #I ... finished. #I finished. #I #I Construct the polycyclic presented group ... #I finished. #I Pcp-group with orders [ 3, 2, 3, 3, 3, 0, 0, 0 ]  polenta-1.3.11/doc/ragged.css000644 000766 000024 00000000231 14775712162 016246 0ustar00mhornstaff000000 000000 /* times.css Frank Lübeck */ /* Change default CSS to use Times font. */ body { text-align: left; } polenta-1.3.11/doc/chap1.html000644 000766 000024 00000012651 14775712162 016176 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 1: Introduction
Goto Chapter: Top 1 2 3 4 5 Bib Ind

1 Introduction

1.1 The package

This package provides functions for computation with matrix groups. Let G be a subgroup of GL(d,R) where the ring R is either equal to ℚ,ℤ or a finite field F_q. Then:

  • We can test whether G is solvable.

  • We can test whether G is polycyclic.

  • If G is polycyclic, then we can determine a polycyclic presentation for G.

A group G which is given by a polycyclic presentation can be largely investigated by algorithms implemented in the GAP-package Polycyclic [EN00]. For example we can determine if G is torsion-free and calculate the torsion subgroup. Further we can compute the derived series and the Hirsch length of the group G. Also various methods for computations with subgroups, factor groups and extensions are available.

As a by-product, the Polenta package provides some functionality to compute certain module series for modules of solvable groups. For example, if G is a rational polycyclic matrix group, then we can compute the radical series of the natural ℚ[G]-module ℚ^d.

1.2 Polycyclic groups

A group G is called polycyclic if it has a finite subnormal series with cyclic factors. It is a well-known fact that every polycyclic group is finitely presented by a so-called polycyclic presentation (see for example Chapter 9 in [Sim94] or Chapter 2 in [EN00] ). In GAP, groups which are defined by polycyclic presentations are called polycyclically presented groups, abbreviated PcpGroups.

The overall idea of the algorithm implemented in this package was first introduced by Ostheimer in 1996 [Ost96]. In 2001 Eick presented a more detailed version [Eic01]. This package contains an implementation of Eick's algorithm. A description of this implementation together with some refinements and extensions can be found in [AE05] and [Ass03].

Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/chap5_mj.html000644 000766 000024 00000026206 14775712162 016671 0ustar00mhornstaff000000 000000 GAP (Polenta) - Chapter 5: Information Messages
Goto Chapter: Top 1 2 3 4 5 Bib Ind

5 Information Messages

It is possible to get informations about the status of the computation of the functions of Chapter 2 of this manual.

5.1 Info Class

5.1-1 InfoPolenta
‣ InfoPolenta( info class )

is the Info class of the Polenta package (for more details on the Info mechanism see Section Reference: Info Functions of the GAP Reference Manual). With the help of the function SetInfoLevel(InfoPolenta,level) you can change the info level of InfoPolenta.

  • If InfoLevel( InfoPolenta ) is equal to 0 then no information messages are displayed.

  • If InfoLevel( InfoPolenta ) is equal to 1 then basic informations about the process are provided. For further background on the displayed informations we refer to [Ass03] (publicly available via the Internet address http://www.icm.tu-bs.de/ag_algebra/software/assmann/diploma.pdf).

  • If InfoLevel( InfoPolenta ) is equal to 2 then, in addition to the basic information, the generators of computed subgroups and module series are displayed.

5.2 Example

gap> SetInfoLevel( InfoPolenta, 1 );

gap> PcpGroupByMatGroup( PolExamples(11) );
#I  Determine a constructive polycyclic sequence
    for the input group ...
#I
#I  Chosen admissible prime: 3
#I
#I  Determine a constructive polycyclic sequence
    for the image under the p-congruence homomorphism ...
#I  finished.
#I  Finite image has relative orders [ 3, 2, 3, 3, 3 ].
#I
#I  Compute normal subgroup generators for the kernel
    of the p-congruence homomorphism ...
#I  finished.
#I
#I  Compute the radical series ...
#I  finished.
#I  The radical series has length 4.
#I
#I  Compute the composition series ...
#I  finished.
#I  The composition series has length 5.
#I
#I  Compute a constructive polycyclic sequence
    for the induced action of the kernel to the composition series ...
#I  finished.
#I  This polycyclic sequence has relative orders [  ].
#I
#I  Calculate normal subgroup generators for the
    unipotent part ...
#I  finished.
#I
#I  Determine a constructive polycyclic  sequence
    for the unipotent part ...
#I  finished.
#I  The unipotent part has relative orders
#I  [ 0, 0, 0 ].
#I
#I  ... computation of a constructive
    polycyclic sequence for the whole group finished.
#I
#I  Compute the relations of the polycyclic
    presentation of the group ...
#I  Compute power relations ...
#I  ... finished.
#I  Compute conjugation relations ...
#I  ... finished.
#I  Update polycyclic collector ...
#I  ... finished.
#I  finished.
#I
#I  Construct the polycyclic presented group ...
#I  finished.
#I
Pcp-group with orders [ 3, 2, 3, 3, 3, 0, 0, 0 ]


gap> SetInfoLevel( InfoPolenta, 2 );

gap> PcpGroupByMatGroup( PolExamples(11) );
#I  Determine a constructive polycyclic sequence
    for the input group ...
#I
#I  Chosen admissible prime: 3
#I
#I  Determine a constructive polycyclic sequence
    for the image under the p-congruence homomorphism ...
#I  finished.
#I  Finite image has relative orders [ 3, 2, 3, 3, 3 ].
#I
#I  Compute normal subgroup generators for the kernel
    of the p-congruence homomorphism ...
#I  finished.
#I  The normal subgroup generators are
#I  [ [ [ 1, -3/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 0, 0, 24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, 3, 15 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, 3, 9 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3/2, 3/2, 3/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3/2, 9/2, -69/2 ], [ 0, 1, 0, 9 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ]
    , [ [ 1, 0, 0, -24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -15 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3/2, -3/2, -9/2 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ]
     ],
  [ [ 1, -3, -3, -12 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, -3/2, -21 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3/2, 3/2, 9/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ] ]
#I
#I  Compute the radical series ...
#I  finished.
#I  The radical series has length 4.
#I  The radical series is
#I  [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 0, 1 ] ],
  [  ] ]
#I
#I  Compute the composition series ...
#I  finished.
#I  The composition series has length 5.
#I  The composition series is
#I  [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 0, 0, 0, 1 ] ], [  ] ]
#I
#I  Compute a constructive polycyclic sequence
    for the induced action of the kernel to the composition series ...
#I  finished.
#I  This polycyclic sequence has relative orders [  ].
#I
#I  Calculate normal subgroup generators for the
    unipotent part ...
#I  finished.
#I  The normal subgroup generators for the unipotent part are
#I  [ [ [ 1, -3/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 0, 0, 24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, 3, 15 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, 3, 9 ], [ 0, 1, 0, 6 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3/2, 3/2, 3/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3/2, 9/2, -69/2 ], [ 0, 1, 0, 9 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ] ]
    , [ [ 1, 0, 0, -24 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -15 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, -3, -9 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3, 0, 9 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, -3/2, -3/2, -9/2 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, 3 ], [ 0, 0, 0, 1 ]
     ],
  [ [ 1, -3, -3, -12 ], [ 0, 1, 0, -6 ], [ 0, 0, 1, 6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3, -3/2, -21 ], [ 0, 1, 0, -3 ], [ 0, 0, 1, -6 ], [ 0, 0, 0, 1 ] ],
  [ [ 1, 3/2, 3/2, 9/2 ], [ 0, 1, 0, 3 ], [ 0, 0, 1, -3 ], [ 0, 0, 0, 1 ] ] ]
#I
#I  Determine a constructive polycyclic  sequence
    for the unipotent part ...
#I  finished.
#I  The unipotent part has relative orders
#I  [ 0, 0, 0 ].
#I
#I  ... computation of a constructive
    polycyclic sequence for the whole group finished.
#I
#I  Compute the relations of the polycyclic
    presentation of the group ...
#I  Compute power relations ...
.....
#I  ... finished.
#I  Compute conjugation relations ...
..............................................
#I  ... finished.
#I  Update polycyclic collector ...
#I  ... finished.
#I  finished.
#I
#I  Construct the polycyclic presented group ...
#I  finished.
#I
Pcp-group with orders [ 3, 2, 3, 3, 3, 0, 0, 0 ]
Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/toggless.js000644 000766 000024 00000004205 14775712162 016475 0ustar00mhornstaff000000 000000 /* toggless.js Frank Lübeck */ /* this file contains two functions: mergeSideTOCHooks: this changes div.ContSect elements to the class ContSectClosed and includes a hook to toggle between ContSectClosed and ContSectOpen. openclosetoc: this function does the toggling, the rest is done by CSS */ closedTOCMarker = "▶ "; openTOCMarker = "▼ "; noTOCMarker = " "; /* merge hooks into side toc for opening/closing subsections with openclosetoc */ function mergeSideTOCHooks() { var hlist = document.getElementsByTagName("div"); for (var i = 0; i < hlist.length; i++) { if (hlist[i].className == "ContSect") { var chlds = hlist[i].childNodes; var el = document.createElement("span"); var oncl = document.createAttribute("class"); oncl.nodeValue = "toctoggle"; el.setAttributeNode(oncl); var cont; if (chlds.length > 2) { var oncl = document.createAttribute("onclick"); oncl.nodeValue = "openclosetoc(event)"; el.setAttributeNode(oncl); cont = document.createTextNode(closedTOCMarker); } else { cont = document.createTextNode(noTOCMarker); } el.appendChild(cont); hlist[i].firstChild.insertBefore(el, hlist[i].firstChild.firstChild); hlist[i].className = "ContSectClosed"; } } } function openclosetoc (event) { /* first two steps to make it work in most browsers */ var evt=window.event || event; if (!evt.target) evt.target=evt.srcElement; var markClosed = document.createTextNode(closedTOCMarker); var markOpen = document.createTextNode(openTOCMarker); var par = evt.target.parentNode.parentNode; if (par.className == "ContSectOpen") { par.className = "ContSectClosed"; evt.target.replaceChild(markClosed, evt.target.firstChild); } else if (par.className == "ContSectClosed") { par.className = "ContSectOpen"; evt.target.replaceChild(markOpen, evt.target.firstChild); } } /* adjust jscontent which is called onload */ jscontentfuncs.push(mergeSideTOCHooks); polenta-1.3.11/doc/polentabib.xml000644 000766 000024 00000004243 14775712140 017147 0ustar00mhornstaff000000 000000 GretchenOstheimer Algorithms for Polycyclic-by-finite groups Rutgers University 1996 DanielSegal Polycyclic groups Cambridge University Press 1983 Charles C.Sims Computation with finitely presented groups Cambridge University Press 1994 BettinaEick Algorithms for Polycyclic Groups Gesamthochschule Kassel 2001 Habilitationsschrift BjörnAssmann Polycyclic presentations for matrix groups TU Braunschweig 2003 Diplomarbeit http://www.icm.tu-bs.de/ag_algebra/software/assmann BettinaEick WernerNickel Polycyclic 2000 GAP package
BjörnAssmann BettinaEick Computing polycyclic presentations for polycyclic rational matrix groups J. Symbolic Comput. 2005 40 6 1269--1284
polenta-1.3.11/doc/chapInd_mj.html000644 000766 000024 00000010341 14775712162 017230 0ustar00mhornstaff000000 000000 GAP (Polenta) - Index
Goto Chapter: Top 1 2 3 4 5 Bib Ind

Index

CompositionSeriesAbelianMatGroup 2.2-4
CompositionSeriesTriangularizableMatGroup 2.2-5
HomogeneousSeriesAbelianMatGroup 2.2-2
HomogeneousSeriesTriangularizableMatGroup 2.2-3
ImageElm 2.1-3
ImagesRepresentative 2.1-3
ImagesSet 2.1-3
InfoPolenta 5.1-1
Installation 4.
IsomorphismPcpGroup 2.1-2
IsPolycyclicGroup 2.1-6
IsSolvableGroup 2.1-4
IsTriangularizableMatGroup 2.1-5
License .-1
Loading the Polenta package 4.2
PcpGroupByMatGroup 2.1-1
Polenta 1.
PolExamples 2.4-1
Polycyclic 1.
RadicalSeriesSolvableMatGroup 2.2-1
SubgroupsUnipotentByAbelianByFinite 2.3-1

Goto Chapter: Top 1 2 3 4 5 Bib Ind

generated by GAPDoc2HTML

polenta-1.3.11/doc/example.xml000644 000766 000024 00000007206 14775712140 016465 0ustar00mhornstaff000000 000000 An example application In this section we outline three example computations with functions from the previous chapter.
Presentation for rational matrix groups mats := [ [ [ 1, 0, -1/2, 0 ], [ 0, 1, 0, 1 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 1, 1/2, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 1 ], [ 0, 0, 0, 1 ] ], [ [ 1, 0, 0, 1 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 1, -1/2, -3, 7/6 ], [ 0, 1, -1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ], [ [ -1, 3, 3, 0 ], [ 0, 0, 1, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 0, 1 ] ] ]; gap> G := Group( mats ); # calculate an isomorphism from G to a pcp-group gap> nat := IsomorphismPcpGroup( G );; gap> H := Image( nat ); Pcp-group with orders [ 2, 2, 3, 5, 5, 5, 0, 0, 0 ] gap> h := GeneratorsOfGroup( H ); [ g1, g2, g3, g4, g5, g6, g7, g8, g9] gap> mats2 := List( h, x -> PreImage( nat, x ) );; # take a random element of G gap> exp := [ 1, 1, 1, 1, 0, 0, 0, 0, 1 ];; gap> g := MappedVector( exp, mats2 ); [ [ -1, 17/2, -1, 233/6 ], [ 0, 1, 0, -2 ], [ 0, 1, -1, 2 ], [ 0, 0, 0, 1 ] ] # map g into the image of nat gap> i := ImageElm( nat, g ); g1*g2*g3*g4*g9 # exponent vector gap> Exponents( i ); [ 1, 1, 1, 1, 0, 0, 0, 0, 1 ] # compare the preimage with g gap> PreImagesRepresentative( nat, i ); [ [ -1, 17/2, -1, 233/6 ], [ 0, 1, 0, -2 ], [ 0, 1, -1, 2 ], [ 0, 0, 0, 1 ] ] gap> last = g; true ]]>
Modules series gens := [ [ [ 1746/1405, 524/7025, 418/1405, -77/2810 ], [ 815/843, 899/843, -1675/843, 415/281 ], [ -3358/4215, -3512/21075, 4631/4215, -629/1405 ], [ 258/1405, 792/7025, 1404/1405, 832/1405 ] ], [ [ -2389/2810, 3664/21075, 8942/4215, -35851/16860 ], [ 395/281, 2498/2529, -5105/5058, 3260/2529 ], [ 3539/2810, -13832/63225, -12001/12645, 87053/50580 ], [ 5359/1405, -3128/21075, -13984/4215, 40561/8430 ] ] ]; gap> H := Group( gens ); gap> RadicalSeriesSolvableMatGroup( H ); [ [ [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] ], [ [ 1, 0, 0, 79/138 ], [ 0, 1, 0, -275/828 ], [ 0, 0, 1, -197/414 ] ], [ [ 1, 0, -3, 2 ], [ 0, 1, 55/4, -55/8 ] ], [ [ 1, 4/15, 2/3, 1/6 ] ], [ ] ] ]]>
Triangularizable subgroups G := PolExamples(3); gap> GeneratorsOfGroup( G ); [ [ [ 73/10, -35/2, 42/5, 63/2 ], [ 27/20, -11/4, 9/5, 27/4 ], [ -3/5, 1, -4/5, -9 ], [ -11/20, 7/4, -2/5, 1/4 ] ], [ [ -42/5, 423/10, 27/5, 479/10 ], [ -23/10, 227/20, 13/10, 231/20 ], [ 14/5, -63/5, -4/5, -79/5 ], [ -1/10, 9/20, 1/10, 37/20 ] ] ] gap> subgroups := SubgroupsUnipotentByAbelianByFinite( G ); rec( T := , U := ) gap> GeneratorsOfGroup( subgroups.T ); [ [ [ 73/10, -35/2, 42/5, 63/2 ], [ 27/20, -11/4, 9/5, 27/4 ], [ -3/5, 1, -4/5, -9 ], [ -11/20, 7/4, -2/5, 1/4 ] ], [ [ -42/5, 423/10, 27/5, 479/10 ], [ -23/10, 227/20, 13/10, 231/20 ], [ 14/5, -63/5, -4/5, -79/5 ], [ -1/10, 9/20, 1/10, 37/20 ] ] ] # so G is triangularizable! ]]>
polenta-1.3.11/doc/chooser.html000644 000766 000024 00000007456 14775712162 016653 0ustar00mhornstaff000000 000000 GAPDoc Style Chooser

Setting preferences for GAPDoc manuals

Unfold subsections in menus only by mouse clicks: no (default)     yes

Show GAP examples as in sessions with ColorPrompt(true): yes (default)     no

Display side of table of contents within chapters: right (default)     left

Main document font: Helvetica/sans serif (default)     Times/serif

Paragraph formatting: left-right justified (default)     ragged right

Apply settings to last page.

polenta-1.3.11/lib/subgroups.gi000644 000766 000024 00000022440 14775712140 016660 0ustar00mhornstaff000000 000000 ############################################################################# ## #W subgroups.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## certain subgroups of matrix groups ## #Y 2004 ## ############################################################################# ## POL_Group := function( subGens, G ) if Length( subGens ) = 0 then return TrivialSubgroup( G ); else return Group( subGens ); fi; end; ############################################################################# ## #F POL_TriangNSGFI_NonAbelianPRMGroup( arg ) ## ## ## ## IN: arg[1] ..... G is an non-abelian polycyclic rational matrix group ## arg[2] ..... optional prime p ## ## OUT: Normal subgroup of finite index, ## actually the p-congruence subgroup ## InstallGlobalFunction( POL_TriangNSGFI_NonAbelianPRMGroup , function( arg ) local p, d, gens_p,G, bound_derivedLength, pcgs_I_p, gens_K_p, comSeries, gens_K_p_m, gens, gens_K_p_mutableCopy, pcgs, gensOfBlockAction, pcgs_nue_K_p, pcgs_GU, gens_U_p, pcgs_U_p, recordSeries, radSeries, isTriang, H; # setup G := arg[1]; gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an admissible prime or take the wished one if Length( arg ) = 2 then p := arg[2]; else p := DetermineAdmissiblePrime(gens); fi; Info( InfoPolenta, 1, "Chosen admissible prime: " , p ); Info( InfoPolenta, 1, " " ); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; # finite part Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the image under the p-congruence homomorphism ..." ); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); if pcgs_I_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); Info( InfoPolenta, 1, "Finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ), "." ); Info( InfoPolenta, 1, " " ); # compute the normal the subgroup gens. for the kernel of phi_p Info( InfoPolenta, 1,"Compute normal subgroup generators for the kernel\n", " of the p-congruence homomorphism ..."); gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); gens_K_p := Filtered( gens_K_p, x -> not x = IdentityMat(d) ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 2,"The normal subgroup generators are" ); Info( InfoPolenta, 2, gens_K_p ); Info( InfoPolenta, 1, " " ); # radical series Info( InfoPolenta, 1, "Compute the radical series ..."); gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); recordSeries := POL_RadicalSeriesNormalGensFullData( gens, gens_K_p_mutableCopy, d ); if recordSeries=fail then return fail; fi; radSeries := recordSeries.sers; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The radical series has length ", Length( radSeries ), "." ); Info( InfoPolenta, 2, "The radical series is" ); Info( InfoPolenta, 2, radSeries ); Info( InfoPolenta, 1, " " ); # test if G is unipotent by abelian isTriang := POL_TestIsUnipotenByAbelianGroupByRadSeries( gens, radSeries ); if isTriang then return G; fi; # compositions series Info( InfoPolenta, 1, "Compute the composition series ..."); comSeries := POL_CompositionSeriesByRadicalSeries( gens_K_p_mutableCopy, d, recordSeries.sersFullData, 1 ); if comSeries=fail then return fail; fi; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The composition series has length ", Length( comSeries ), "." ); Info( InfoPolenta, 2, "The composition series is" ); Info( InfoPolenta, 2, comSeries ); Info( InfoPolenta, 1, " " ); # induce K_p to the factors of the composition series gensOfBlockAction := POL_InducedActionToSeries(gens_K_p, comSeries); # let nue be the homomorphism which induces the action of K_p to # the factors of the series Info( InfoPolenta, 1, "Compute a constructive polycyclic sequence\n", " for the induced action of the kernel to the composition series ..."); pcgs_nue_K_p := CPCS_AbelianSSBlocks_ClosedUnderConj( gens_K_p, gens, comSeries ); if pcgs_nue_K_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); # update generators of K_p gens_K_p := pcgs_nue_K_p.gens_K_p; pcgs_nue_K_p := pcgs_nue_K_p.pcgs_nue_K_p; Info( InfoPolenta, 1, "This polycyclic sequence has relative orders ", pcgs_nue_K_p.relOrders, "." ); Info( InfoPolenta, 1, " " ); return POL_Group( gens_K_p, G ); end ); ############################################################################# ## #F POL_TriangNSGFI_PRMGroup( arg ) ## ## arg[1] = G is a rational polycyclic rational matrix group ## InstallGlobalFunction( POL_TriangNSGFI_PRMGroup , function( arg ) local G; G := arg[1]; if IsAbelian( G ) then return G; else if IsBound( arg[2] ) then return POL_TriangNSGFI_NonAbelianPRMGroup( arg[1], arg[2] ); else return POL_TriangNSGFI_NonAbelianPRMGroup( G ); fi; fi; end ); # this code has to be reviewed. In the current form we can only assure, # that it returns normal subgroup generators for K_p. ############################################################################# ## #M TriangNormalSubgroupFiniteInd( G ) ## ## G is a matrix group over the Rationals. ## Returned is triangularizable normal subgroup of finite index ## ## #InstallMethod( TriangNormalSubgroupFiniteInd, "for polycyclic matrix groups", # true, [ IsMatrixGroup ], 0, #function( G ) # local test; # test := POL_IsMatGroupOverFiniteField( G ); # if IsBool( test ) then # TryNextMethod(); # elif test = 0 then # return POL_TriangNSGFI_PRMGroup(G ); # else # TryNextMethod(); # fi; #end) ; # #InstallOtherMethod( TriangNormalSubgroupFiniteInd, # "for polycyclic matrix groups", true, # [ IsMatrixGroup, IsInt], 0, #function( G, p ) # local test; # test := POL_IsMatGroupOverFiniteField( G ); # if IsBool( test ) then # TryNextMethod(); # elif test = 0 then # if not IsPrime(p) then # Print( "Second argument must be a prime number.\n" ); # return fail; # fi; # return POL_TriangNSGFI_PRMGroup(G ); # else # TryNextMethod(); # fi; # #end ); ############################################################################# ## #M SubgroupsUnipotentByAbelianByFinite( G ) ## ## G is a matrix group over the Rationals. ## Returned is triangularizable normal subgroup K of finite index ## and an unipotent normal subgroup U of K such that K/U is abelian. ## InstallMethod( SubgroupsUnipotentByAbelianByFinite, "for polycyclic matrix groups (Polenta)", true, [ IsMatrixGroup ], 0, function( G ) local cpcs, U_p, K_p; if not IsRationalMatrixGroup( G ) then TryNextMethod( ); fi; cpcs := CPCS_PRMGroup( G ); if cpcs = fail then return fail; fi; if IsAbelian( G ) then U_p := cpcs.pcgs_U_p.pcs; return rec( T := G , U := POL_Group( U_p, G )); else U_p := cpcs.pcgs_U_p.pcs; # check if G is triangularizable if Length( cpcs.pcgs_GU.pcgs_I_p.gens ) = 0 then #G triangularizable return rec( T := G, U := POL_Group( U_p, G )); else #G not triangularizable K_p := cpcs.pcgs_GU.preImgsNue; K_p := Concatenation( K_p, U_p ); return rec( T := POL_Group( K_p, G ), U := POL_Group( U_p, G )); fi; fi; end ); InstallOtherMethod( SubgroupsUnipotentByAbelianByFinite , "for polycyclic matrix groups (Polenta)", true, [ IsMatrixGroup, IsInt], 0, function( G,p ) local cpcs, U_p, K_p; if not IsRationalMatrixGroup( G ) then TryNextMethod( ); fi; cpcs := CPCS_PRMGroup( G,p ); if cpcs = fail then return fail; fi; if IsAbelian( G ) then U_p := cpcs.pcgs_U_p.pcs; return rec( T := G , U := POL_Group( U_p, G )); else U_p := cpcs.pcgs_U_p.pcs; # check if G is triangularizable if Length( cpcs.pcgs_GU.pcgs_I_p.gens ) = 0 then #G triangularizable return rec( T := G, U := POL_Group( U_p, G )); else #G not triangularizable K_p := cpcs.pcgs_GU.preImgsNue; K_p := Concatenation( K_p, U_p ); return rec( T := POL_Group( K_p, G ), U := POL_Group( U_p, G )); fi; fi; end ); ############################################################################# ## #E polenta-1.3.11/lib/ispoly.gi000644 000766 000024 00000020463 14775712140 016151 0ustar00mhornstaff000000 000000 ############################################################################# ## #W ispoly.gi POLENTA package Bjoern Assmann ## ## Methods for testing if a rational matrix group is polycyclic ## #Y 2005 ## ############################################################################# ## #F POL_Logarithm( x ) ## ## IN: x ..... unipotent matrix ## ## OUT: log(x) ## POL_Logarithm := function( x ) local n,mat,matPow,log,i; n := Length( x[1] ); mat := x - x^0; matPow := mat; log := mat; for i in [2..n-1] do matPow := matPow*mat; log := log + (-1)^(i-1)*(i)^-1*matPow; od; return log; end; ############################################################################# ## #F POL_Exponential( v ) ## ## IN: v ..... matrix which is conjugated to an ## upper or lower triangular matrix with 0's on the diagonal ## ## OUT: exp(x) ## POL_Exponential := function( v ) local n,exp, vPow, fac, i; n := Length( v[1] ); #exp := IdentityMat(n) + v; exp := v^0 + v; vPow := v; #fac := 1; fac := v[1][1]^0; for i in [2..n-1] do vPow := vPow*v; fac := fac*i; exp := exp + (fac^-1)*vPow; od; return exp; end; ############################################################################# ## #F POL_CloseMatrixSpaceUnderLieBracket( V ) ## ## IN: V .... vector space < M_nxn( Q ) ## ## OUT: smallest Lie algebra containing V ## POL_CloseMatrixSpaceUnderLieBracket := function( V ) local basis,n,com,i,j,basis_ext, V_ext; basis := Basis( V ); n := Length( basis ); for i in [1..n] do for j in [i+1..n] do com := basis[i]*basis[j]-basis[j]*basis[i]; if not com in V then basis_ext := POL_CopyVectorList( basis ); Add( basis_ext, com ); V_ext := VectorSpace( Rationals, basis_ext, "basis" ); return POL_CloseMatrixSpaceUnderLieBracket( V_ext ); fi; od; od; return V; end; ############################################################################# ## #F ## ## IN: unipo_gens ..... matrices that generate a unipotent matrix group ## ## OUT: The Lie algebra L( ) ## POL_LieAlgebra := function( unipo_gens ) local logs,V,V_ext; # get logs logs := List( unipo_gens, POL_Logarithm ); # compute Q-span V := VectorSpace( Rationals, logs ); # close under Lie bracket V_ext := POL_CloseMatrixSpaceUnderLieBracket( V ); return V_ext; end; ############################################################################# ## #F POL_CloseLieAlgebraUnderGrpAction( gensG, L ) ## ## IN: gensG ... generators of rational matrix group G of degree n ## L ...... nilpotent Lie Algebra generated by matrices of degree n ## ## OUT: L^G, where G acts on L by l^g = log( exp(l)^g ); ## POL_CloseLieAlgebraUnderGrpAction := function( gensG, L ) local basis,b,g,exp,u,l,basis_ext,V_ext,L_ext; basis := Basis( L ); for b in basis do for g in gensG do exp := POL_Exponential( b ); u := exp^g; l := POL_Logarithm( u ); if not l in L then basis_ext := POL_CopyVectorList( basis ); Add( basis_ext, l ); V_ext := VectorSpace( Rationals, basis_ext, "basis" ); L_ext := POL_CloseMatrixSpaceUnderLieBracket( V_ext ); return POL_CloseLieAlgebraUnderGrpAction( gensG, L_ext ); fi; od; od; return L; end; ############################################################################# ## #F ## ## IN: L ......... Lie algebra ## g ......... group element ## ## OUT: Induced action of g on the Lie algebra, i.e. the linear mapping ## which maps l to log( exp(l)^g ) ## POL_InducedActionToLieAlgebra := function( g, L ) local basis,n,inducedAction,i,exp,u,log,coeff; basis := Basis( L ); n := Length( basis ); inducedAction := []; for i in [1..n] do exp := POL_Exponential( basis[i] ); u := exp^g; log := POL_Logarithm( u ); coeff := Coefficients( basis, log ); Add( inducedAction, coeff ); od; return inducedAction; end; ############################################################################# ## #F POL_IsIntegerList( list ) ## ## POL_IsIntegerList := function( list ) local z; for z in list do if not z in Integers then return false; fi; od; return true; end; ############################################################################# ## #F POL_IsIntegralActionOnLieAlgebra( gens, L ) ## ## IN: gens ....... list of matrices ## L ........... Lie algebra on which gens acts ## via l^g = Log( Exp(l)^g ) ## ## OUT: returns true if for all g in gens, the minimal polynomial of ## the induced action of g,g^-1 to L is integral. ## false otherwise. ## POL_IsIntegralActionOnLieAlgebra := function( gens, L ) local g,ind,pol,coeffs,constTerm,bool; Info( InfoPolenta, 3, "Testing whether action on Lie alg. is integral" ); for g in gens do Info( InfoPolenta, 3, "Generator that will be induced:" ); Info( InfoPolenta, 3, g ); ind := POL_InducedActionToLieAlgebra( g, L ); Info( InfoPolenta, 3, "Induced action to Lie algebra:" ); Info(InfoPolenta, 3, ind ); if not Trace( ind ) in Integers then Info( InfoPolenta, 3, "Trace not integral\n" ); return false; fi; pol := CharacteristicPolynomial( Rationals, Rationals, ind ); # pol := MinimalPolynomial( Rationals, ind ); Info( InfoPolenta, 3, "Characteristic polynomial:" ); Info(InfoPolenta, 3, pol ); coeffs := CoefficientsOfLaurentPolynomial( pol ); # test if pol_g in Z[x] if not POL_IsIntegerList( coeffs[1] ) then return false; fi; # test if pol_g^-1 in Z[X] constTerm := Value( pol, 0 ); bool := (constTerm = 1 ) or ( constTerm = -1); if not bool then return false; fi; od; return true; end; ############################################################################# ## #F POL_IsIntegralActionOnLieAlgebra_Beals( gens, L ) ## ## IN: gens ....... list of matrices ## L ........... Lie algebra on which gens acts ## via l^g = Log( Exp(l)^g ) ## ## OUT: returns true if for all g in gens, the minimal polynomial of ## the induced action of g,g^-1 to L is integral. ## false otherwise. ## POL_IsIntegralActionOnLieAlgebra_Beals := function( gens, L ) local gens_ind, G_ind, lat; gens_ind := List( gens, x-> POL_InducedActionToLieAlgebra( x, L )); G_ind := GroupByGenerators( gens_ind ); lat := InvariantLattice( G_ind ); if lat = fail then return false; else return true; fi; end; ############################################################################# ## #F ## ## IN: gensU_p ...... normal subgroup generators for U_p ## gensG ........ the generators of the parent group G ## gensGU ...... representatives of pc sequence of GU ## POL_IsFinitelgeneratedU_p := function( gensU_p, gensG, gensGU ) local L,L_ext,isIntegral,gensU_p_mod,i,method; # catch trivial case G/U = 1 if Length( gensGU ) = 0 then return true; fi; # catch trivial case U_p = 1 gensU_p_mod := []; for i in [1..Length( gensU_p )] do if not gensU_p[i]=gensU_p[i]^0 then Add( gensU_p_mod,gensU_p[i] ); fi; od; if Length( gensU_p_mod ) = 0 then return true; fi; # get Lie algebra corresponding to L := POL_LieAlgebra( gensU_p_mod ); Info( InfoPolenta, 3, "Dimension L: ", Dimension( L ) ); # close it under action of G L_ext := POL_CloseLieAlgebraUnderGrpAction( gensG, L ); Info( InfoPolenta, 3, "Dimension L_ext: ", Dimension( L_ext ) ); Info( InfoPolenta, 3, "Basis of L_ext: ", Basis( L ) ); # test whether the action of gensGU on the Lie algebra is integral method := "beals"; if method = "char" then isIntegral := POL_IsIntegralActionOnLieAlgebra_Beals( gensG, L_ext ); else isIntegral := POL_IsIntegralActionOnLieAlgebra( gensGU, L_ext ); fi; return isIntegral; end; ############################################################################# ## #E polenta-1.3.11/lib/ispolyz.gi000644 000766 000024 00000003500 14775712140 016334 0ustar00mhornstaff000000 000000 ############################################################################# ## #W ispolyz.gi POLENTA package Bjoern Assmann ## ## ############################################################################# ## #F POL_ComputePolyZSeries( G ) ## ## IN: G ............ polycyclic group given by a pcp ## ## OUT: If G is polyZ, then this function returns a series of characteristic ## subgroups, such that the factors are free-abelian. ## If G is not polyZ, then this function returns fail. ## POL_ComputePolyZSeries := function( G ) local H,sers,der,nat,im,T; # setup H := G; sers := [G]; # compute poly Z series repeat der := DerivedSubgroup( H ); nat := NaturalHomomorphismByNormalSubgroup( H, der ); im := Image( nat ); if IsFinite( im ) then return fail; else T := TorsionSubgroup( im ); H := PreImage( nat, T ); Add( sers, H ); fi; until IsTrivial( H ); SetEfaSeries( G, sers ); return sers; end; ############################################################################# ## #F POL_IsPolyZGroup( G ) ## ## IN: G ............. polycyclic group given by a pcp ## ## OUT: true if G is polyZ, false otherwise. ## POL_IsPolyZGroup := function( G ) local sers; sers := POL_ComputePolyZSeries( G ); if sers = fail then return false; else return true; fi; end; ############################################################################# ## #M IsPolyInfiniteCyclicGroup( G ) ## ## IN: G ............. polycyclic group given by a pcp ## ## OUT: true if G is polyZ, false otherwise. ## InstallMethod( IsPolyInfiniteCyclicGroup, "for pcp groups", true, [ IsPcpGroup ], 0, function( G ) return POL_IsPolyZGroup( G ); end ); polenta-1.3.11/lib/unipo.gi000644 000766 000024 00000061335 14775712140 015767 0ustar00mhornstaff000000 000000 ############################################################################# ## #W unipo.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## constructive pc-sequences for unipotent matrix groups ## #Y 2003 ## # We have to calculate a basis of Q^d # which exhibits a flag for all u in gens. # we know that the matrices # in gens are unipotent. next we have to determine the nullspace of # (u-1)^1, (u-1)^2,... we have to do that simultaneously for all # matrices in gens so we have to write them in one big matrix. ############################################################################# ## #F POL_BuildBigMatrix( modifiedGens ) ## ## writes the matrices of modifiedGens in matrix s.t. we can ## apply NullspaceRatMat ## if modifiedGens=[g_1,...,g_n] then ## BigMatrix:=(g_1,...,g_n) ## POL_BuildBigMatrix := function( modifiedGens ) local bigMatrix,i,j ; bigMatrix := []; for i in [1..Length( modifiedGens[1] )] do bigMatrix[i] := []; for j in [1..Length(modifiedGens )] do Append( bigMatrix[i],modifiedGens[j][i] ); od; od; return bigMatrix; end; #For determining a flag you have to compute the nullspace W of a matrix u #then you proceed by passing to the factor V/W an compute a new #nullspace. #this process will terminate, because u is unipotent which means that #u is conjugate to a upper triangular matrix with one's on the diagonal ############################################################################# ## #F POL_DetermineFlag( gens ) ## POL_DetermineFlag := function( gens ) local d,flag,u,bigMatrix,nullSpace,full,indGens,factorFlag, preImage,modifiedGens,nath; d := Length( gens[1][1] ); flag := []; # calculate (u-1 ) for all u in gens modifiedGens := []; for u in gens do Add( modifiedGens,u-IdentityMat(d ) ); od; # calculate the nullspace W bigMatrix := POL_BuildBigMatrix( modifiedGens ); nullSpace := NullspaceRatMat( bigMatrix ); if nullSpace=[] then #Error("Failure in POL_DetermineFlag\n Group is not unipotent\n" ); return fail; fi; # induce action to the factor V/W full := IdentityMat( d ); if Length( nullSpace )=d then return nullSpace; fi; nullSpace :=POL_CopyVectorList( nullSpace ); TriangulizeMat( nullSpace ); Append( flag, nullSpace ); nath := NaturalHomomorphismBySemiEchelonBases( full, nullSpace ); indGens := List( gens, x-> InducedActionFactorByNHSEB(x,nath) ); # recursive call factorFlag := POL_DetermineFlag( indGens ); if factorFlag = fail then return fail; fi; preImage := PreimagesRepresentativeByNHSEB( factorFlag,nath ); Append( flag,preImage ); return flag; end; ############################################################################# ## #F POL_DetermineConjugatorTriangular( gens ) ## ## brings gens in upper triangular form ## POL_DetermineConjugatorTriangular := function( gens ) local a,flag,d,g,i,j,alpha,beta; flag := POL_DetermineFlag( gens ); if flag = fail then return fail; fi; # POL_TestFlag( flag,gens ); d := Length( gens[1] ); g := []; # for an upper triangular matrix we need a inversed flag for i in [1..d] do g[i] := flag[d-i+1]; od; return g^-1; end; ############################################################################# ## #F POL_DetermineConjugatorIntegral( gens ) ## ## brings gens in integer form ## POL_DetermineConjugatorIntegral := function( gens ) local d,a,i,j,g,x,alpha; d := Length( gens[1] ); alpha := IdentityMat(d ); for i in [2..d] do a := 1; for g in gens do for j in [1..i-1] do x := DenominatorRat( alpha[j][j]^-1*g[j][i] ); a := Lcm( a, x ); od; od; alpha[i][i] := a; od; return alpha; end; ############################################################################# ## #F POL_UpperTriangIntTest( gens ) ## ## POL_UpperTriangIntTest := function( gens ) local d,goodForm,g,i,j; d := Length( gens[1] ); goodForm := true; for g in gens do for i in [1..d] do for j in [1..d] do if i=j then if not g[i][j]=1 then Info( InfoPolenta,4, i,"problemplace ",j,"\n" ); goodForm := false; return goodForm; fi; elif i < j then if DenominatorRat( g[i][j] )>1 then Info( InfoPolenta, 4,i,"problemplace ",j,"\n" ); goodForm := false; return goodForm; fi; elif not g[i][j]=0 then Info( InfoPolenta, 4,i,"problemplace ",j,"\n" ); goodForm := false; return goodForm; fi; od; od; od; return goodForm; end; ############################################################################# ## #F POL_DetermineRealConjugator( gens ) ## ## brings in upper triangular integral form ## POL_DetermineRealConjugator := function( gens ) local v,gens_mod,w,conjugator; # upper triangular form v := POL_DetermineConjugatorTriangular( gens ); if v = fail then return fail; fi; gens_mod := List( gens, x-> x^v ); # upper triangular integer form w := POL_DetermineConjugatorIntegral( gens_mod ); conjugator := v*w; # test if it is in upper triangular and integer form return conjugator; end; ############################################################################# ## #F POL_UnipotentMats2Pcp( gens ) ## ## maps the unipotent group to a Pcp-Group, and saves the ## used conjugator ## POL_UnipotentMats2Pcp := function( gens ) local v,gens_mod,w,conjugator,pcp; # determine conjugator # upper triangular form v := POL_DetermineConjugatorTriangular( gens ); if v = fail then return fail; fi; gens_mod := GeneratorsOfGroup( Group( gens )^v ); # upper triangular integer form w := POL_DetermineConjugatorIntegral( gens_mod ); conjugator := v*w; # conjugate group gens_mod := GeneratorsOfGroup( Group( gens )^conjugator ); # test if it is in upper triangular and integer form Assert( 2, POL_UpperTriangIntTest( gens_mod ) ); # convert the conjugated group to a pcp-group pcp := SubgroupUnitriangularPcpGroup( gens_mod ); return rec( pcp := pcp,conjugator := conjugator,gens_mod := gens_mod ); end; ############################################################################# ## #F POL_FirstCloseUnderConjugation( gens,gens_U_p ) ## ## extends the matrices in gens_U_p to gens_U_p2 in such a way that ## the conjugator belonging to gens_U_p2 can be used also for the ## matrices of the form gens_U_p2[i]^gens[j] ## POL_FirstCloseUnderConjugation := function( gens,gens_U_p ) local conjugator,found,g,h,matrix,newGens,rec1; conjugator := POL_DetermineRealConjugator( gens_U_p ); if conjugator = fail then return fail; fi; newGens := []; for g in gens_U_p do for h in gens do matrix := g^h; if not POL_UpperTriangIntTest( [matrix^conjugator] ) then # we have to extend our gens_U_p newGens := Concatenation( gens_U_p,[matrix] ); Info( InfoPolenta, 3, "Extending in FirstCloseUnderConjugation\n", "newGens are",newGens,"\n" ); rec1 := POL_FirstCloseUnderConjugation( gens,newGens ); return rec1; fi; od; od; # if the conjugator is good for all conjugates we can proceed return rec( gens := gens,gens_U_p := gens_U_p,conjugator := conjugator ); end; ############################################################################# ## #M POL_UnitriangularPcpGroup( n, p ) . . .. . . . for p = 0 we take UT( n, Z ) ## POL_UnitriangularPcpGroup := function( n, p ) local l, c, g, r, i, j, h, f, k, v, o, G; if not IsInt(n) or n <= 1 then return fail; fi; if not (IsPrimeInt(p) or p=0) then return fail; fi; l := n*(n-1)/2; c := FromTheLeftCollector( l ); # compute matrix generators g := []; for i in [1..n-1] do for j in [1..n-i] do r := IdentityMat( n ); r[j][i+j] := 1; Add( g, r ); od; od; # mod out p if necessary if p > 0 then g := List( g, x -> x * One( GF(p) ) ); fi; # get inverses h := List( g, x -> x^-1 ); # read of pc presentation for i in [1..l] do # commutators for j in [1..i-1] do #v := Comm( g[j], g[i] ); v := Comm( g[i], g[j] ); if v <> v^0 then if v in g then k := Position( g, v ); o := [k, 1]; elif v in h then k := Position( h, v ); o := [k, -1]; else Error("commutator out of range"); fi; SetCommutator( c, i, j, o ); fi; od; # powers if p > 0 then SetRelativeOrder( c, i, p ); v := g[i]^p; if v <> v^0 then Error("power out of range"); fi; fi; od; UpdatePolycyclicCollector( c ); # translate from collector to group G := PcpGroupByCollectorNC( c ); G!.mats := g; G!.isomorphism := GroupHomomorphismByImagesNC( G, Group(g), Igs(G), g); return G; end; ############################################################################# ## #F POL_SubgroupUnitriangularPcpGroup_Mod( mats ) ## ## just the returned value is changed in comparaison with original ## function ## POL_SubgroupUnitriangularPcpGroup_Mod := function( mats ) local rec1,n, p, G, g, i, j, r, h, m, e, v, c; # get the dimension, the char and the full unitriangular group n := Length( mats[1] ); p := Characteristic( mats[1][1][1] ); G := POL_UnitriangularPcpGroup( n, p ); # compute corresponding generators g := []; for i in [1..n-1] do for j in [1..n-i] do r := IdentityMat( n ); r[j][i+j] := 1; Add( g, r ); od; od; # get exponents for each matrix h := []; for m in mats do e := []; c := 0; for i in [1..n-1] do v := List( [1..n-i], x -> m[x][x+i] ); r := MappedVector( v, g{[c+1..c+n-i]} ); m := r^-1 * m; c := c + n-i; Append( e, v ); od; Add( h, MappedVector( e, Pcp( G ) ) ); od; # Print( " h = ",h,"\n" ); return rec( pcp := Subgroup( G, h ),UT := G ); end; ############################################################################# ## #F POL_MapToUnipotentPcp( matrix,pcp_record ) ## ## POL_MapToUnipotentPcp := function( matrix,pcp_record ) local n,p,m,i,j,r,g,e,c,v; # get the dimension, and the full unitriangular group n := Length( matrix ); p := 0; m := matrix; # compute corresponding generators g := []; for i in [1..n-1] do for j in [1..n-i] do r := IdentityMat( n ); r[j][i+j] := 1; Add( g, r ); od; od; # get exponent e := []; c := 0; for i in [1..n-1] do v := List( [1..n-i], x -> m[x][x+i] ); r := MappedVector( v, g{[c+1..c+n-i]} ); m := r^-1 * m; c := c + n-i; Append( e, v ); od; return MappedVector( e,Pcp( pcp_record.UT ) ) ; end; ############################################################################# ## #F CPCS_Unipotent( gens_U_p ) ## ## calculates a constructive pc-sequence for ## the unipotent group ## CPCS_Unipotent := function( gens_U_p ) local g,rec1,mats,A,dim,gens_U_p_mod,mat,mat3,h, mat2,pcpElement,conjugator,G,gensOfG, pcp_rec,rels,pcs,newGens,i; dim := Length( gens_U_p[1] ); #check for trivial elements gens_U_p_mod := []; for i in [1..Length( gens_U_p )] do if not gens_U_p[i]=gens_U_p[i]^0 then Add( gens_U_p_mod,gens_U_p[i] ); fi; od; # exclude the trivial case if gens_U_p_mod=[] then return rec( rels := [],pcs := [] ); fi; # find a conjugator conjugator := POL_DetermineRealConjugator( gens_U_p_mod ); if conjugator = fail then return fail; fi; #calculate a pcp for ^conjugator G := Group( gens_U_p_mod ); G := G^conjugator; gensOfG := GeneratorsOfGroup( G ); # assert that is in upper triangular and integer form Assert( 2, POL_UpperTriangIntTest( gensOfG ) ); # convert the conjugated group to a Pcp-group Info( InfoPolenta, 3, "calculate the pcp-Group of the group\n", gensOfG,"\n" ); pcp_rec := POL_SubgroupUnitriangularPcpGroup_Mod( gensOfG ); # calculate a pc-sequence for pcs := []; A := POL_UnitriangularPcpGroup( dim,0 ); mats := A!.mats; for g in GeneratorsOfPcp( Pcp( pcp_rec.pcp ) ) do #calculate preimage, i.e. convert it to a mat and conjugate it mat := MappedVector( Exponents( g ), mats ); mat := mat^( conjugator^-1 ); Add( pcs,mat ); od; # save the relative orders rels := Pcp( pcp_rec.pcp )!.rels; return rec( pcp_record := pcp_rec, conjugator := conjugator, pcs := pcs,rels := rels ); end; ############################################################################# ## #F CPCS_Unipotent_Conjugation_Version2( gens, gens_U_p ) ## ## calculate a constructive pc-sequence for ## the unipotent group ^ ## CPCS_Unipotent_Conjugation_Version2 := function( gens, gens_U_p ) local g,rec1,mats,A,dim,gens_U_p_mod,mat,mat3,h, mat2,pcpElement,conjugator,G,gensOfG, pcp_rec,rels,pcs,newGens,i, gens2; dim := Length( gens[1] ); #check for trivial elements gens_U_p_mod := []; for i in [1..Length( gens_U_p )] do if not gens_U_p[i]=gens_U_p[i]^0 then Add( gens_U_p_mod,gens_U_p[i] ); fi; od; # exclude the trivial case if gens_U_p_mod=[] then return rec( rels := [], pcs := [] ); fi; # find a good conjugator even for conjugated elements of gens_U_p rec1 := POL_FirstCloseUnderConjugation( gens, gens_U_p_mod ); if rec1 = fail then return fail; fi; gens_U_p_mod := rec1.gens_U_p; conjugator := rec1.conjugator; #calculate a pcp for ^conjugator; G := Group( gens_U_p_mod ); G := G^conjugator; gensOfG := GeneratorsOfGroup( G ); # assert that is in upper triangular and integer form Assert( 2, POL_UpperTriangIntTest( gensOfG ) ); # convert the conjugated group to a Pcp-group Info( InfoPolenta, 3, "Unipotent: calculate the pcp-Group of the group\n", gensOfG,"\n" ); pcp_rec := POL_SubgroupUnitriangularPcpGroup_Mod( gensOfG ); # check if the preimages of the gens of the pcp are # stable under conjugation A := POL_UnitriangularPcpGroup( dim,0 ); mats := A!.mats; for g in GeneratorsOfGroup( pcp_rec.pcp ) do # calculate the preimage, i.e. convert it to a matrix and conjugate mat := MappedVector( Exponents( g ),mats ); mat := mat^( conjugator^-1 ); gens2 := Concatenation( gens, List( gens, x-> x^-1 )); for h in gens2 do mat2 := mat^h; mat3 := mat2^conjugator; if not POL_MapToUnipotentPcp( mat3,pcp_rec ) in pcp_rec.pcp then #extend gens_U_p Info( InfoPolenta,3, "Extending gens_U_p \n" ); # newGens := Concatenation( gens_U_p,[mat2] ); newGens := Concatenation( gens_U_p_mod,[mat2] ); return CPCS_Unipotent_Conjugation_Version2( gens,newGens ); fi; od; od; # calculate a pc-sequence for pcs := []; for g in GeneratorsOfPcp( Pcp( pcp_rec.pcp ) ) do #calculate preimage, i.e. convert it to a mat and conjugate it mat := MappedVector( Exponents( g ),mats ); mat := mat^( conjugator^-1 ); Add( pcs,mat ); od; # save the relative orders rels := Pcp( pcp_rec.pcp )!.rels; return rec( pcp_record := pcp_rec, conjugator := conjugator, pcs := pcs,rels := rels ); end; ############################################################################# ## #F CPCS_Unipotent_Conjugation( gens, gens_U_p ) ## ## calculates a constructive pc-sequence for ## the unipotent group ^ ## CPCS_Unipotent_Conjugation := function( gens, gens_U_p ) local dim, gens_U_p_mod,rec1,conjugator,U,gensOfU, gensWithInverses, level, mat, h, mat2, mat3,P, rels, newGens,i,testMembership, pcs, gensWithInversesConj, pcs_U_p; dim := Length( gens[1] ); # clear generators list from trivial elements gens_U_p_mod := []; for i in [1..Length( gens_U_p )] do if not gens_U_p[i]=gens_U_p[i]^0 then Add( gens_U_p_mod,gens_U_p[i] ); fi; od; # exclude the trivial case if gens_U_p_mod=[] then return rec( rels := [], pcs := [] ); fi; # find a good conjugator even for conjugated elements of gens_U_p rec1 := POL_FirstCloseUnderConjugation( gens, gens_U_p_mod ); if rec1 = fail then return fail; fi; gens_U_p_mod := rec1.gens_U_p; conjugator := rec1.conjugator; #calculate a pcp for ^conjugator; U := Group( gens_U_p_mod ); U := U^conjugator; gensOfU := GeneratorsOfGroup( U ); # assert that is in upper triangular and integer form Assert( 2, POL_UpperTriangIntTest( gensOfU ) ); # compute a polycyclic sequence for U Info( InfoPolenta, 3, "calculate levels ", " of the group...\n", gensOfU,"\n" ); level := SiftUpperUnitriMatGroup( U ); Info( InfoPolenta, 3, "... finished\n" ); # check if is stable under conjugation Info( InfoPolenta, 3, "check if is stable under conjugation..."); gensWithInverses := Concatenation( gens, List( gens, x-> x^-1 )); gensWithInversesConj := List( gensWithInverses, x-> x^conjugator ); P := PolycyclicGenerators( level ); # maybe incomplete pcs of U^conjugator pcs_U_p := P.matrices; for mat in pcs_U_p do #for mat in gens_U_p do for h in gensWithInversesConj do mat2 := mat^h; Info( InfoPolenta, 3, "test membership ..." ); testMembership := DecomposeUpperUnitriMat( level, mat2 ); Info( InfoPolenta, 3, "... finished" ); if IsBool( testMembership ) then #extend gens_U_p Info(InfoPolenta,3,"Extending generator list of unipotent subgroup\n" ); #newGens := Concatenation( gens_U_p,[mat2] ); newGens := Concatenation( pcs_U_p,[mat2] ); newGens := List( newGens, x-> x^( conjugator^-1 ) ); Info( InfoPolenta, 2, "An extended list of the normal subgroup generators for the\n", " unipotent subgroup is" ); Info( InfoPolenta, 2, newGens ); return CPCS_Unipotent_Conjugation( gens,newGens ); fi; od; od; Info( InfoPolenta, 3, "...finished" ); # assemble necessary data for a constructive pcs of #P := PolycyclicGenerators( level ); rels := List( [1..Length(P.gens)], x->0 ); pcs := List( pcs_U_p, x-> x^( conjugator^-1 ) ); #U := Group( P.matrices ); #U := U^( conjugator^-1 ); return rec( level := level, pcs := pcs, gens := P.gens, conjugator := conjugator, rels := rels ); end; ############################################################################# ## #F ExponentOfCPCS_Unipotent( matrix, conPcs ) ## ## ExponentOfCPCS_Unipotent := function( matrix, conPcs ) local matrix2,exp,n,counter,i,e,decomp; # exclude trivial case if conPcs.rels=[] then return []; fi; matrix2 := matrix^conPcs.conjugator; if not POL_UpperTriangIntTest( [matrix2] ) then return fail; fi; decomp := DecomposeUpperUnitriMat( conPcs.level, matrix2 ); if IsBool( decomp ) then return fail; fi; n := Length( conPcs.gens ); exp := []; counter := 1; for i in [1..n] do if IsBound( decomp[counter] ) then e := decomp[counter]; if conPcs.gens[i] = e[1] then Add( exp, e[2] ); counter := counter + 1; else Add( exp, 0 ); fi; else Add( exp, 0 ); fi; od; Assert( 1, matrix = Exp2Groupelement( conPcs.pcs, exp ), "Failure in ExponentOfCPCS_Unipotent \n" ); return exp; end; ############################################################################# ## ## Test functions ############################################################################# ## #F POL_TestCPCS_Unipotent( gens ) ## ## POL_TestCPCS_Unipotent := function( gens ) local con, i, g, exp; con := CPCS_Unipotent( gens ); Print( "START TESTING !!!\n" ); SetAssertionLevel( 1 ); for i in [1..10] do g := POL_RandomGroupElement( gens ); Print( g ); exp := ExponentOfCPCS_Unipotent( g, con ); Print( i ); od; # SetAssertionLevel( 0 ); end; ############################################################################# ## #F POL_TestCPCS_Unipotent2( dim, numberGens_U_p ) ## ## POL_TestCPCS_Unipotent2 := function( dim, numberGens_U_p ) local g2,exp,G,k,i,j,d,mats,h2,g,matrix,U,U2,h,v,gens2,gens_U_p, gens,con, numberOfTests; g := []; matrix := []; d := dim; k := numberGens_U_p; numberOfTests := 10; # construct some unipotent rational matrix groups G := POL_UnitriangularPcpGroup( dim,0 ); mats := G!.mats; for i in [1..k] do g[i] := Random( G ); od; for i in [1..k] do matrix[i] := MappedVector( Exponents( g[i] ),mats ); od; Print( "matrix ist gleich ",matrix,"\n" ); U := Group( matrix ); # we need a random element of GL( n,Q ) h := RandomInvertibleMat( dim,Rationals ); Print( "h ist gleich ",h,"\n" ); U2 := U^h; gens_U_p := GeneratorsOfGroup( U2 ); # gens_U_p := GeneratorsOfGroup( U ); Print( "gens_U_p ist gleich ", gens_U_p,"\n" ); con := CPCS_Unipotent( gens_U_p ); Print( "START TESTING !!!\n" ); SetAssertionLevel( 1 ); for i in [1..numberOfTests] do g := POL_RandomGroupElement( gens_U_p ); Print( g ); exp := ExponentOfCPCS_Unipotent( g,con ); Print( i ); od; # SetAssertionLevel( 0 ); end; ############################################################################# ## #F POL_TestFlag( flag,gens ) ## POL_TestFlag := function( flag,gens ) local i,V,v,g, test; test := true; for i in [1..( Length( flag ) )] do V := VectorSpace( Rationals,flag{[1..i]} ); for g in gens do v := flag[i]*g; #Print( "flag[i] ist gleich ",flag[i],"\n" ); #Print( "v ist gleich ",v,"\n" ); if not v in V then Print( "Flag Fehler enthalten gleich ",v in V,"\n" ); Print( "flag[",i,"] ist gleich ",flag[i],"\n" ); Print( "v ist gleich ",v,"\n\n" ); test := false; fi; od; od; return test; end; ############################################################################# ## ## #F POL_Test_UnipotentMats2Pcp( dim, k ) ## POL_Test_UnipotentMats2Pcp := function( dim, k ) local G,i,j,d,mats,g,matrices,U,U2,h,v,gens2,gens3; SetAssertionLevel( 2 ); g := []; matrices := []; d := dim; # construct some unipotent rational matrix groups G := POL_UnitriangularPcpGroup( dim,0 ); mats := G!.mats; for i in [1..k] do g[i] := Random( G ); od; for i in [1..k] do matrices[i] := MappedVector( Exponents( g[i] ),mats );; od; Print( "used matrices are ",matrices,"\n" ); U := Group( matrices ); # random element of GL( n,Q ) h := RandomInvertibleMat( dim,Rationals ); Print( "h is ",h,"\n" ); U2 := U^h; gens2 := GeneratorsOfGroup( U2 ); gens3 := POL_UnipotentMats2Pcp( gens2 ); if gens3 = fail then return fail; fi; SetAssertionLevel( 0 ); return gens3; end; ############################################################################# ## #E polenta-1.3.11/lib/solvable.gi000644 000766 000024 00000024706 14775712140 016445 0ustar00mhornstaff000000 000000 ############################################################################# ## #W solvalble.gi POLENTA package Bjoern Assmann ## ## Methods for testing if a matrix group ## is solvable or polycyclic ## #Y 2003 ## ############################################################################# ## #F POL_IsSolvableRationalMatGroup_infinite( G ) ## POL_IsSolvableRationalMatGroup_infinite := function( G ) local p, d, gens_p, bound_derivedLength, pcgs_I_p, gens_K_p, homSeries, gens_K_p_m, gens, gens_K_p_mutableCopy, pcgs, gensOfBlockAction, pcgs_nue_K_p, pcgs_GU, gens_U_p, pcgs_U_p; # handle trivial case if IsAbelian( G ) then return true; fi; # setup gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an admissible prime p := DetermineAdmissiblePrime(gens); Info( InfoPolenta, 1, "Chosen admissible prime: " , p ); Info( InfoPolenta, 1, " " ); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; # finite part Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the image under the p-congruence homomorphism ..." ); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); if pcgs_I_p = fail then return false; fi; Info( InfoPolenta, 1, "Finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ), "." ); Info( InfoPolenta, 1, " " ); # compute the normal the subgroup gens. for the kernel of phi_p Info( InfoPolenta, 1,"Compute normal subgroup generators for the kernel\n", " of the p-congruence homomorphism ..."); gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); gens_K_p := Filtered( gens_K_p, x -> not x = IdentityMat(d) ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 2,"The normal subgroup generators are" ); Info( InfoPolenta, 2, gens_K_p ); Info( InfoPolenta, 1, " " ); # homogeneous series Info( InfoPolenta, 1, "Compute the homogeneous series ... "); gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); homSeries := POL_HomogeneousSeriesNormalGens( gens, gens_K_p_mutableCopy, d ); if homSeries = fail then return false; else Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The homogeneous series has length ", Length( homSeries ), "." ); Info( InfoPolenta, 2, "The homogeneous series is" ); Info( InfoPolenta, 2, homSeries ); Info( InfoPolenta, 1, " " ); return true; fi; end; ############################################################################# ## #F POL_IsSolvableFiniteMatGroup( G ) ## POL_IsSolvableFiniteMatGroup := function( G ) local gens, d, CPCS, bound_derivedLength; # handle trivial case if IsAbelian( G ) then return true; fi; # calculate a constructive pc-sequence gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an upper bound for the derived length of G bound_derivedLength := d+2; Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the finite input group ..." ); CPCS := CPCS_finite_word( gens, bound_derivedLength ); if CPCS = fail then return false; else Info(InfoPolenta,1,"finished."); return true; fi; end; ############################################################################# ## #M IsSolvableGroup( G ) ## ## G is a matrix group over the rationals. ## ## InstallMethod( IsSolvableGroup, "for rational matrix groups (Polenta)", true, [ IsRationalMatrixGroup ], 0, POL_IsSolvableRationalMatGroup_infinite ); ## Enforce rationality check for cyclotomic matrix groups RedispatchOnCondition( IsSolvableGroup, true, [ IsCyclotomicMatrixGroup ], [ IsRationalMatrixGroup ], RankFilter(IsCyclotomicMatrixGroup) ); ############################################################################# ## #M IsSolvableGroup( G ) ## ## G is a matrix group over a finite field. ## InstallMethod( IsSolvableGroup, "for matrix groups over a finte field (Polenta)", true, [ IsFFEMatrixGroup ], 0, POL_IsSolvableFiniteMatGroup ); ############################################################################# ## #F POL_IsPolycyclicRationalMatGroup( G ) ## POL_IsPolycyclicRationalMatGroup := function( G ) local test; if not IsFinitelyGeneratedGroup( G ) then return false; fi; if IsAbelian( G ) then return true; fi; test := CPCS_NonAbelianPRMGroup( G, 0, "testIsPoly" ); if test=false or test=fail then return false; else return true; fi; end; ############################################################################# ## #M IsPolycyclicGroup( G ) ## ## G is a finitely generated subgroup of GL(n,Z), hence G is polycycylic ## if and only if G is solvable and finitely generated. ## InstallMethod( IsPolycyclicGroup, "for integer matrix groups (Polenta)", true, [ IsIntegerMatrixGroup ], 0, function( G ) return IsFinitelyGeneratedGroup( G ) and IsSolvableGroup( G ); end ); ############################################################################# ## #M IsPolycyclicGroup( G ) ## ## G is a matrix group over the rationals ## InstallMethod( IsPolycyclicGroup, "for rational matrix groups (Polenta)", true, [ IsRationalMatrixGroup ], 0, function( G ) if IsIntegerMatrixGroup(G) then return IsFinitelyGeneratedGroup( G ) and IsSolvableGroup( G ); fi; return POL_IsPolycyclicRationalMatGroup( G ); end ); ## Enforce rationality check for cyclotomic matrix groups RedispatchOnCondition( IsPolycyclicGroup, true, [ IsCyclotomicMatrixGroup ], [ IsRationalMatrixGroup ], RankFilter(IsCyclotomicMatrixGroup) ); ############################################################################# ## #M IsPolycyclicGroup( G ) ## ## G is a matrix group over a finite field ## InstallMethod( IsPolycyclicGroup, "for matrix groups over a finite field (Polenta)", true, [ IsFFEMatrixGroup ], 0, function( G ) local F; if not IsFinitelyGeneratedGroup( G ) then return false; fi; if IsAbelian( G ) then return true; fi; return IsSolvableGroup( G ); end ); ############################################################################# ## #M IsPolycyclicMatGroup( G ) ## ## G is a matrix group, test whether it is polycyclic. ## ## TODO: Mark this as deprecated and eventually remove it; code using it ## should be changed to use IsPolycyclicGroup. ## InstallMethod( IsPolycyclicMatGroup, [ IsMatrixGroup ], IsPolycyclicGroup); ############################################################################# ## #F POL_IsTriangularizableRationalMatGroup_infinite( G ) ## POL_IsTriangularizableRationalMatGroup_infinite := function( G ) local p, d, gens_p, bound_derivedLength, pcgs_I_p, gens_K_p, gens_K_p_m, gens, gens_K_p_mutableCopy, pcgs, gensOfBlockAction, pcgs_nue_K_p, pcgs_GU, gens_U_p, pcgs_U_p, radSeries, comSeries, recordSeries, isTriang; if IsAbelian( G ) then return true; fi; # setup gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an admissible prime or take the wished one #if Length( arg ) = 2 then # p := arg[2]; #else p := DetermineAdmissiblePrime(gens); #fi; Info( InfoPolenta, 1, "Chosen admissible prime: " , p ); Info( InfoPolenta, 1, " " ); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; # finite part Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the image under the p-congruence homomorphism ..." ); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); if pcgs_I_p = fail then return false; fi; Info(InfoPolenta,1,"finished."); Info( InfoPolenta, 1, "Finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ), "." ); Info( InfoPolenta, 1, " " ); # compute the normal the subgroup gens. for the kernel of phi_p Info( InfoPolenta, 1,"Compute normal subgroup generators for the kernel\n", " of the p-congruence homomorphism ..."); gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); gens_K_p := Filtered( gens_K_p, x -> not x = IdentityMat(d) ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 2,"The normal subgroup generators are" ); Info( InfoPolenta, 2, gens_K_p ); Info( InfoPolenta, 1, " " ); # radical series Info( InfoPolenta, 1, "Compute the radical series ..."); gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); recordSeries := POL_RadicalSeriesNormalGensFullData( gens, gens_K_p_mutableCopy, d ); if recordSeries=fail then return false; fi; radSeries := recordSeries.sers; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The radical series has length ", Length( radSeries ), "." ); Info( InfoPolenta, 2, "The radical series is" ); Info( InfoPolenta, 2, radSeries ); Info( InfoPolenta, 1, " " ); # test if G is unipotent by abelian isTriang := POL_TestIsUnipotenByAbelianGroupByRadSeries( gens, radSeries ); return isTriang; end; ############################################################################# ## #M IsTriangularizableMatGroup( G ) ## ## InstallMethod( IsTriangularizableMatGroup, "for matrix groups over Q (Polenta)", true, [ IsRationalMatrixGroup ], 0, POL_IsTriangularizableRationalMatGroup_infinite ); ## Enforce rationality check for cyclotomic matrix groups RedispatchOnCondition( IsTriangularizableMatGroup, true, [ IsCyclotomicMatrixGroup ], [ IsRationalMatrixGroup ], RankFilter(IsCyclotomicMatrixGroup) ); ############################################################################# ## #E polenta-1.3.11/lib/basic.gd000644 000766 000024 00000003745 14775712140 015712 0ustar00mhornstaff000000 000000 ############################################################################# ## #W basic.gd POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## constructive pc-sequences for polycyclic rational matrix groups ## #Y 2003 ## ############################################################################# ## #F DetermineAdmissiblePrime(gensOfG) ## ## determines a prime number which does not divide the denominators ## of the entries of the matrices in gensOfG and which does not divide the ## the entries of the inverses of the matrices in gensOfG ## ## input is a list of generators of a rational polycyclic matrix group ## DeclareGlobalFunction( "DetermineAdmissiblePrime" ); ############################################################################ ## #F POL_NormalSubgroupGeneratorsOfK_p(pcgs,gensOfRealG) ## ## pcgs is a constructive pc-Sequence for I_p(G) ## (image of G under the p-congruence hom.). ## This function calculates normal subgroup generators for K_p(G) ## (the kernel of the p-congruence hom.) ## DeclareGlobalFunction( "POL_NormalSubgroupGeneratorsOfK_p" ); ############################################################################# ## #F Exp2Groupelement(list,exp) ## DeclareGlobalFunction( "Exp2Groupelement" ); ############################################################################# ## #F CopyMatrixList(list) ## DeclareGlobalFunction( "CopyMatrixList" ); ############################################################################# ## #F POL_CopyVectorList(list) ## DeclareGlobalFunction( "POL_CopyVectorList" ); ############################################################################# ## #F POL_NormalSubgroupGeneratorsU_p( pcgs_GU, gens, gens_K_p ) ## ## pcgs_GU is a constructive pc-Sequence for G/U, ## this function calculates normal subgroup generators for U_p(G) ## DeclareGlobalFunction( "POL_NormalSubgroupGeneratorsU_p" ); ############################################################################# ## #E polenta-1.3.11/lib/finite.gi000644 000766 000024 00000041340 14775712140 016105 0ustar00mhornstaff000000 000000 ############################################################################# ## #W finite.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## constructive pc-sequences for finite matrix groups ## #Y 2003 ## ############################################################################# ## #F POL_SuitableOrbitPoints( gens) ## ## gens are some matrices over GF(q) ## we calculate suitable orbit points for a stabilizer chain ## of , i.e. points with small orbits ## POL_SuitableOrbitPoints := function( gens ) local MM,cs,l,i,x,fac,F,n,csR; # calculate the module F := FieldOfMatrixList( gens ); MM := GModuleByMats(gens, F); # use the meataxe to calculate a decomposition series cs := SMTX.BasesCompositionSeries(MM); csR := Reversed( cs ); # build a basis through this series n := Length( cs ); l := []; for i in [1..(n-1)] do x := BaseSteinitzVectors(csR[i],csR[i+1]).factorspace; Append( l, x ); #l:=List([1..(n-1)], #x->BaseSteinitzVectors(csR[x],csR[x+1]).factorspace[1]); od; return l ; end; POL_NextOrbitPoint := function( pcgs, h ) local k,p,i; #k := Length( pcgs.suitableOrbitPoints ); #Print( "pcgs.suitableOrbitPoints", pcgs.suitableOrbitPoints, "\n" ); p := pcgs.suitableOrbitPoints[1]; i := 2; while pcgs.oper( p, h ) = p do p := pcgs.suitableOrbitPoints[i]; i := i+1; od; #Print( "chosen i is",i,"\n"); return p; end; POL_NextOrbitPoint2 := function( pcgs, h ) local k,p,i; k := Length( pcgs.suitableOrbitPoints ); #Print( "pcgs.suitableOrbitPoints", pcgs.suitableOrbitPoints, "\n" ); p := pcgs.suitableOrbitPoints[k]; i := 1; while pcgs.oper( p, h ) = p do p := pcgs.suitableOrbitPoints[k-i]; i := i+1; od; #Print( "chosen i is",i,"\n"); return p; end; POL_NextOrbitPoint3 := function( pcgs, h ) return Remove(pcgs.suitableOrbitPoints); end; ############################################################################# ## #F ClosureBasePcgs_word(pcgsN, g, gens, lim) ## ## Calculates a constructive pc-sequence for ^gens ## ## Every arising group element is realized as a record ## containing the real element ## and the word information corresponding to gens ## InstallGlobalFunction( ClosureBasePcgs_word,function( pcgsN, g, gens, lim ) local pcgsU,listU,u,c,l,i,comm,x,j,addGenerator; if lim < 0 then # G is not polycyclic # Error("Group is not polycyclic !\n"); return fail; fi; # check if g is in N if MemberTestByBasePcgs( pcgsN, g.groupElement ) then return pcgsN; fi; addGenerator := function(g) # add generator to the list of generators Add( pcgsU.gens, g.groupElement ); # in wordGens we store information how to # write the elements of gens in terms of gensOfG Add( pcgsU.wordGens, g.word ); # as the third argument of the next function call we signal that # g corresponds to the last element of pcgsU.gens ExtendedBasePcgsMod( pcgsU, g.groupElement, [Length(pcgsU.gens),1] ); end; # start extending U = pcgsU := StructuralCopy( pcgsN ); addGenerator(g); listU:=[g]; # loop over listU while Length( listU ) >= 1 do u := Remove( listU ); # consider all conjugates of u which are not contained in U c := []; for j in [1..Length( gens )] do x := u.groupElement ^ gens[j]; if MemberTestByBasePcgs(pcgsU, x) then # already contained in U continue; fi; Add(c, rec( groupElement := x, word := Concatenation([[j,-1]], u.word, [[j,1]]) )); od; # recurse, if /N is not abelian l := Length( pcgsN.pcref ); for i in [1..Length(c)] do comm := POL_Comm( g, c[i] ); pcgsN := ClosureBasePcgs_word(pcgsN,comm,gens,lim-1); if pcgsN = fail then return fail; fi; for j in [(i+1)..Length(c)] do comm := POL_Comm( c[j], c[i] ); pcgsN := ClosureBasePcgs_word(pcgsN,comm,gens,lim-1); if pcgsN = fail then return fail; fi; od; od; # reset U and listU # check if pcgsN was modified if Length( pcgsN.pcref) > l then pcgsU := StructuralCopy(pcgsN); for x in listU do if not MemberTestByBasePcgs(pcgsU, x.groupElement) then addGenerator(x); fi; od; fi; # finally add the conjugates to our list for x in c do Add(listU, x); if not MemberTestByBasePcgs(pcgsU, x.groupElement) then addGenerator(x); fi; od; od; return pcgsU; end ); ############################################################################# ## #F POL_Comm( g, h )..................... calculates the Comm for records of ## group elements with word information ## InstallGlobalFunction( POL_Comm , function( g, h ) local commElement, tempWord ,comm; commElement := Comm( g.groupElement, h.groupElement ); tempWord := POL_InverseWord(g.word); Append(tempWord,POL_InverseWord(h.word)); Append(tempWord,g.word); Append(tempWord,h.word); comm := rec(groupElement:=commElement,word:=tempWord); return comm; end ); ############################################################################# ## #F CPCS_finite_word( gensOfG , b) ## ## Returns a constructive polycyclic sequence for G if G is polycyclic ## of derived length at most b and it returns fail if G is not ## polycyclic ## ## Every generator is a record which contains in ## .groupElement the group element and in ## .word the wordinformation corresponding to the gensOfG list ## This feature is important if gensOfG arise as the image under ## the p-congruence homomorphism. ## ## InstallGlobalFunction( CPCS_finite_word , function( gensOfG , b) local c,f,d,pcgsOfN,x,epsilon,h,H,i,n, suitableOrbitPoints,pcgsOfN_hilf,j,k; Info( InfoPolenta, 5, "determining a constructive pcgs for the finite part..."); # Setup of N f := FieldOfMatrixList( gensOfG ); d := Length( gensOfG[1] ); suitableOrbitPoints := POL_SuitableOrbitPoints( gensOfG ); pcgsOfN := rec( orbit := [], trans := [], trels := [], defns := [], pcref := [], acton := f^d, oper := OnRight, trivl := IsOne, gens:= [], wordGens:=[], gensOfG:=gensOfG, suitableOrbitPoints := suitableOrbitPoints ); c :=0; epsilon := []; for k in [1..Length(gensOfG)] do epsilon[k] := rec(groupElement:=gensOfG[k],word:=[[k,1]]); od; # epsilon:=ShallowCopy(gensOfG); j := 0; while Length(epsilon) > 0 do h := Remove(epsilon); pcgsOfN := ClosureBasePcgs_word(pcgsOfN,h,gensOfG ,b); if pcgsOfN = fail then return fail; fi; od; Info(InfoPolenta,5,"finished"); return pcgsOfN; end ); ############################################################################# ## #F CPCS_FinitePart(gens)........... constructive pc-sequ. for image of ## under the p-congr. hom. ## InstallGlobalFunction( CPCS_FinitePart , function(gens ) local p,d,gens_p,bound_derivedLength,pcgs_I_p; #calculate the dimension of the vector space acting on d := Length(gens[1][1]); # determine an admissible prime p := DetermineAdmissiblePrime(gens); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism in GL(d,p) #gens_p := gens*One(GF(p)); gens_p := InducedByField(gens,GF(p)); # determine an upper bound for the derived length of G # it could be sharper ! bound_derivedLength := d+2; # determine a constructive polycyclic sequence for phi_p() pcgs_I_p := CPCS_finite_word(gens_p,bound_derivedLength); return pcgs_I_p; end ); ########################################################################### ## #F POL_InverseWord(word) ## ## InstallGlobalFunction( POL_InverseWord , function(word) local wordPart,tempWord,pos,exp; tempWord := []; for wordPart in Reversed(word) do Add(tempWord,[wordPart[1],wordPart[2]*-1]); od; return tempWord; end ); ############################################################################# ## #F ExtendedBasePcgsMod( pcgs, g, d ) . . . . . .. . . . . extend a base pcgs ## ## g normalizes and we compute a new pcgs for . ## InstallGlobalFunction( ExtendedBasePcgsMod , function( pcgs, g, d ) local h, e, i, o, b, m, c, l, w, j, k; # change in place - but unbind not updated information Unbind(pcgs.pcgs); Unbind(pcgs.rels); # set up h := g; e := ShallowCopy( d ); i := 0; # loop over base and divide off while not pcgs.trivl( h ) do i := i + 1; #Print(" i=",i,"\n"); # take base point (if necessary, add new base point) if i > Length( pcgs.orbit ) then #b := SmallOrbitPoint( pcgs, g ); b := POL_NextOrbitPoint2( pcgs, h); Add( pcgs.orbit, [b] ); Add( pcgs.trans, [] ); Add( pcgs.defns, [] ); Add( pcgs.trels, [] ); else b := pcgs.orbit[i][1]; fi; # compute the relative orbit length of h m := 1; c := pcgs.oper( b, h ); while not c in pcgs.orbit[i] do m := m + 1; c := pcgs.oper( c, h ); od; # enlarge pcgs, if necessary if m > 1 then #Print(" enlarge basic orbit ",i," by ",m," copies \n"); Add( pcgs.trans[i], h ); Add( pcgs.defns[i], e ); Add( pcgs.trels[i], m ); EnlargeOrbit( pcgs.orbit[i], h, m, pcgs.oper ); # we save also g to know who was responsible for the entry Add( pcgs.pcref, [i, Length(pcgs.trans[i]),g] ); fi; # divide off j := Position( pcgs.orbit[i], c ); if j > 1 then w := TransWord( j, pcgs.trels[i] ); h := h^m * SubsWord( w, pcgs.trans[i] )^-1; e := [[e,m], SubsAndInvertDefn( w, pcgs.defns[i] ) ]; else h := h^m; e := [e,m]; fi; od; end ); ############################################################################# ## #F RelativeOrdersPcgs_finite( pcgs ) ## InstallGlobalFunction( RelativeOrdersPcgs_finite , function( pcgs ) local t,g,order,i; if IsBound( pcgs.relOrders ) then return pcgs.relOrders; fi; pcgs.relOrders := []; #catch the trivial case if Length(pcgs.gens)=0 then return pcgs.relOrders; fi; g := pcgs.pcref[Length(pcgs.pcref)][3]; order := 1; i := 1; for t in Reversed( pcgs.pcref ) do if t[3]=g then order := order*pcgs.trels[t[1]][t[2]]; pcgs.relOrders[i] := order; else i := i+1; order := 1; g := t[3]; order := order*pcgs.trels[t[1]][t[2]]; pcgs.relOrders[i] := order; fi; od; return pcgs.relOrders; end ); ############################################################################# ## #F ExponentvectorPcgs_finite( pcgs, g ) ## InstallGlobalFunction( ExponentvectorPcgs_finite , function( pcgs, g ) local exp,h,index,part; exp := []; h := g; for index in Reversed([1..Length(pcgs.gens)]) do part := ExponentvectorPartPcgs( pcgs, h , index); Add(exp,part); h := (pcgs.gens[index]^-part)*h; od; if not h=h^0 then Print("Failure in the Exponent computation !\n"); fi; return exp; end ); ############################################################################# ## #F ExponentvectorPartPcgs( pcgs, g , index) ## ## g = ...* pcgs.gens[index]^ExponentvectorPartPcgs * ... ## InstallGlobalFunction( ExponentvectorPartPcgs , function( pcgs, g, index ) local h, e,part, i, o, b, m, c, l, w, j, k; # set up h := g; i := 0; e := [0,0]; # loop over base and divide off while not pcgs.trivl( h ) do i := i + 1; # take base point if i > Length( pcgs.orbit ) then # Print(g , " is not contained in Pcgs\n"); return fail; else b := pcgs.orbit[i][1]; fi; #the relative orbit length of h should be 1 m := 1; c := pcgs.oper( b, h ); while not c in pcgs.orbit[i] do m := m + 1; c := pcgs.oper( c, h ); od; if not m =1 then # Print(g , " is not contained in Pcgs\n"); return fail; fi; # divide off j := Position( pcgs.orbit[i], c ); if j > 1 then w := TransWord( j, pcgs.trels[i] ); h := h^m * SubsWord( w, pcgs.trans[i] )^-1; e := [[e,m], SubsAndInvertDefn( w, pcgs.defns[i] ) ]; fi; od; part := -ExtractIndexPart(e,index); return part; end ); ############################################################################# ## #F ExtractIndexPart( word, index) ## InstallGlobalFunction( ExtractIndexPart , function(word, index) local x; # case: word=Integer if word in Integers then if word=index then return 1; else return 0; fi; fi; # case: word=[] if IsEmpty(word) then return 0; fi; # case: word=[something,Integer] if Length(word) >1 then if word[2] in Integers then return word[2]*ExtractIndexPart(word[1],index); fi; fi; # case [something,something,..] x := ExtractIndexPart(word[1],index); x := x+ExtractIndexPart(word{[2..Length(word)]},index); return x; end ); ############################################################################# ## #F POL_TestExpVector_finite( pcgs, g ) ## InstallGlobalFunction( POL_TestExpVector_finite , function( pcgs, g ) local exp,h,n,i; exp := ExponentvectorPcgs_finite( pcgs, g ); # calculate the group element related to exp h := pcgs.gens[1]^0; n := Length(pcgs.gens); for i in Reversed([1..n]) do h := h*pcgs.gens[i]^exp[n-i+1]; od; return g=h; end ); ############################################################################# ## #F POL_Test_CPCS_FinitePart(gens) ## POL_Test_CPCS_FinitePart := function( gens ) local pcgs, i, g, test; pcgs := CPCS_FinitePart(gens); if pcgs.gens=[] then return "trivial"; fi; for i in [1..10] do g := POL_RandomGroupElement( pcgs.gensOfG ); test := POL_TestExpVector_finite( pcgs, g ); if not test then Error( "Failure in the exponent calculation in CPCS_FinitePart" ); fi; Print(i); od; Print("\n"); end; ############################################################################# ## #F POL_SetPcPresentation(pcgs) ## ## pcgs is a constructive pc-sequence, calculated ## by ConstructivePcSequenceFinitePart ## this function calculates a PcPresentation for the group described ## by pcgs ## InstallGlobalFunction( POL_SetPcPresentation, function(pcgs) local genList,ftl,n,ro,i,j,exp,conj,f_i,f_j,r_i,pcSeq; # Attention: In pcgs.gens we have the pc-Sequence in inverse order # because we built up the structure bottom up pcSeq := StructuralCopy(Reversed(pcgs.gens)); # Setup n := Length(pcgs.gens); ftl := FromTheLeftCollector(n); # calculate the relative orders ro := RelativeOrdersPcgs_finite( pcgs ); for i in [1..n] do SetRelativeOrder(ftl,i,ro[i]); od; # Set power relations for i in [1..n] do f_i := pcSeq[i]; r_i := ro[i]; exp := ExponentvectorPcgs_finite( pcgs, f_i^r_i ); genList := Exp2GenList(exp); SetPower(ftl,i,genList); od; # Set the conjugation relations for i in [1..n] do for j in [1..(i-1)] do f_i := pcSeq[i]; f_j := pcSeq[j]; conj := (f_j^-1)*f_i*f_j; exp := ExponentvectorPcgs_finite( pcgs, conj); genList := Exp2GenList(exp); SetConjugate(ftl,i,j,genList); od; od; UpdatePolycyclicCollector(ftl); return ftl; end ); ############################################################################# ## #F TestPOL_SetPcPresentation(pcgs) ## ## TestPOL_SetPcPresentation := function(pcgs) local ftl,relations,i; ftl := POL_SetPcPresentation(pcgs); relations := POL_NormalSubgroupGeneratorsOfK_p(pcgs,pcgs.gensOfG); for i in [1..Length(relations)] do if relations[i] <> relations[i]^0 then Print("Error in TestPOL_SetPcPresentation\n"); fi; od; end; ############################################################################# ## #E polenta-1.3.11/lib/series.gi000644 000766 000024 00000135523 14775712140 016130 0ustar00mhornstaff000000 000000 ############################################################################# ## #W series.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## radical series, homogeneous series and composition series of matrix groups ## #Y 2003 ## ############################################################################# ## #F POL_SplitSemisimple( base ) ## POL_SplitSemisimple := function( base ) local d, b, f, s, i; d := Length( base ); b := PrimitiveAlgebraElement( [ ], base ); f := Factors( b.poly ); if Length( f ) = 1 then return [ rec( basis := IdentityMat( Length( b.elem ) ), poly := f ) ]; fi; s := List( f, x -> NullspaceRatMat( Value( x, b.elem ) ) ); s := List( [ 1 .. Length( f ) ], x -> rec( basis := s[x], poly := f[x] ) ); return s; end; ############################################################################# ## #F RadicalOfAbelianRMGroup( mats, d ) ## ## is an abelian rational matrix group ## RadicalOfAbelianRMGroup := function( mats, d ) local coms, i, j, new, base, full, nath, indm, l, algb, newv, tmpb, subb, f, g, h, mat; base := []; full := IdentityMat( d ); # nath is the natural hom. from V to V/W nath := NaturalHomomorphismBySemiEchelonBases( full, base ); # indm for induced matrices indm := mats; # start spinning up basis and look for nilpotent elements i := 1; algb := []; while i <= Length( indm ) do # add next element to algebra basis l := Length( algb ); newv := Flat( indm[i] ); tmpb := SpinnUpEchelonBase(algb, [newv], indm{[1..i]},OnMatVector ); # check whether we have added a non-semi-simple element subb := []; for j in [l+1..Length(tmpb)] do mat := MatByVector( tmpb[j], Length(indm[i]) ); f := MinimalPolynomial( Rationals, mat ); g := Collected( Factors( f ) ); if ForAny( g, x -> x[2] > 1 ) then h := Product( List( g, x -> Value( x[1], mat ) ) ); Append( subb, List( h, x -> ShallowCopy(x) ) ); fi; od; #Print("found nilpotent submodule of dimension ", Length(subb),"\n"); # spin up new subspace of radical subb := SpinnUpEchelonBase( [], subb, indm, OnRight ); if Length( subb ) > 0 then base := PreimageByNHSEB( subb, nath ); if Length( base ) = d then # radical cannot be so big return fail; fi; nath := NaturalHomomorphismBySemiEchelonBases( full, base ); indm := List( mats, x -> InducedActionFactorByNHSEB( x, nath ) ); algb := []; i := 1; else i := i + 1; fi; od; return rec( radical := base, nathom := nath, algebra := algb ); end; ############################################################################# ## #F POL_RadicalNormalGens( gens, mats, d ) ## ## ## mats are normal subgroup generators for the Kernel K_p in G = ## ## returned is ## radical .... a basis for the radical ## nathom ..... homomorphism for Q^d to Q^d/radical ## algebra .... basis for the algebra Q[K_p^G] in flat form ## where K_p and G are induced to Q^d/radical ## POL_RadicalNormalGens := function( gens, mats, d ) local coms, i, j, new, base, full, nath, indm, l, algb, newv, tmpb, subb, f, g, h, mat,k,a,left,inducedk,right, commutes,extended,comElement,a2,y; # get commutators # because Q^d ( k-1 ) \subset Rad, where k in the commutator # subgroup ' coms := []; for i in [1..Length( mats )] do for j in [i+1..Length( mats )] do new := mats[i] * mats[j] - mats[j] * mats[i]; Append(coms, new ); od; od; # base is a basis for the module W, the radical base := SpinnUpEchelonBase( [], coms, gens, OnRight ); if Length( base ) = d then # for a radical to big return fail; fi; full := IdentityMat( d ); # nath is the natural hom. from V to V/W nath := NaturalHomomorphismBySemiEchelonBases( full, base ); # indm for induced matrices indm := List( mats, x -> InducedActionFactorByNHSEB( x, nath ) ); # start spinning up basis and look for nilpotent elements i := 1; algb := []; while i <= Length( indm ) do # check if the new element commutes with all elements in algb # if not we get a nontrivial element of the commutator commutes:=true; for a in algb do a2 := MatByVector( a, Length(indm[i]) ); left := indm[i]*a2; right := a2*indm[i]; if not left=right then commutes:=false; break; fi; od; # if it doesn't commute with all, spin up new subspace of # the radical extended := false; if not commutes then subb := left-right; subb := SpinnUpEchelonBase( [], subb, indm, OnRight ); if Length( subb ) > 0 then base := PreimageByNHSEB( subb, nath ); # Rad_K_p(Q^d) = Rad_G(Q^d) # therefore must be also a G-module base := SpinnUpEchelonBase( [], base, gens, OnRight ); if Length( base ) = d then # radical cannot be so big return fail; fi; nath := NaturalHomomorphismBySemiEchelonBases( full, base ); indm := List( mats, x ->InducedActionFactorByNHSEB(x,nath )); algb := []; i := 1; extended:=true; fi; fi; if not extended then # add next element to algebra basis l := Length( algb ); newv := Flat( indm[i] ); tmpb := SpinnUpEchelonBase(algb, [newv], indm{[1..i]}, OnMatVector ); # close the basis under the conjugation action of G for k in gens do inducedk:=InducedActionFactorByNHSEB(k,nath); y:=indm[i]^inducedk; newv:=Flat(y); tmpb := SpinnUpEchelonBase( algb, [newv], indm{[1..i]}, OnMatVector ); od; # check whether we have added a non-semi-simple element subb := []; for j in [l+1..Length(tmpb)] do mat := MatByVector( tmpb[j], Length(indm[i]) ); f := MinimalPolynomial( Rationals, mat ); g := Collected( Factors( f ) ); if ForAny( g, x -> x[2] > 1 ) then h := Product( List( g, x -> Value( x[1], mat ) ) ); Append( subb, List( h, x -> ShallowCopy(x) ) ); fi; od; # spin up new subspace of radical subb := SpinnUpEchelonBase( [], subb, indm, OnRight ); if Length( subb ) > 0 then base := PreimageByNHSEB( subb, nath ); # Rad_K_p(Q^d) = Rad_G(Q^d) # therefore must be also a G-module base := SpinnUpEchelonBase( [], base, gens, OnRight ); if Length( base ) = d then # radical cannot be so big return fail; fi; nath := NaturalHomomorphismBySemiEchelonBases( full, base ); indm := List( mats,x->InducedActionFactorByNHSEB( x, nath )); algb := []; i := 1; else i := i + 1; fi; fi; od; return rec( radical := base, nathom := nath, algebra := algb ); end; ############################################################################# ## #F POL_HomogeneousSeriesNormalGens(gens, mats, d ) ## ## mats are normal subgroup generators for the Kernel K_p in G = ## returned is a homogeneous series of of K_p module Q^d ## POL_HomogeneousSeriesNormalGens := function(gens, mats, d ) local radb, splt, nath,inducedgens, l, sers, i, sub, full, acts, rads; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := POL_RadicalNormalGens(gens, mats, d ); if radb = fail then return fail; fi; splt := POL_SplitSemisimple( radb.algebra ); nath := radb.nathom; # refine radical factor and initialize series l := Length( splt ); for i in [2..l] do sub := Concatenation( List( [i..l], x -> splt[x].basis ) ); TriangulizeMat( sub ); Add( sers, PreimageByNHSEB( sub, nath ) ); od; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); inducedgens:=List( gens, x -> InducedActionSubspaceByNHSEB( x, nath ) ); # use recursive call to refine radical rads := POL_HomogeneousSeriesNormalGens(inducedgens,acts, Length(radb.radical) ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F POL_RadicalSeriesNormalGens(gens, mats, d ) ## ## mats are normal subgroup generators for the Kernel K_p in G=, ## which is a rational polycyclic matrix group. ## returned is a radical series of Q^d ## POL_RadicalSeriesNormalGens := function(gens, mats, d ) local radb, splt, nath,inducedgens, l, sers, i, sub, full, acts, rads; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := POL_RadicalNormalGens(gens, mats, d ); if radb = fail then return fail; fi; nath := radb.nathom; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); inducedgens:=List( gens, x -> InducedActionSubspaceByNHSEB( x, nath ) ); # use recursive call to refine radical rads := POL_RadicalSeriesNormalGens(inducedgens,acts, Length(radb.radical) ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F POL_RadicalSeriesNormalGensFullData(gens, mats, d ) ## ## mats are normal subgroup generators for the Kernel K_p in G=, ## which is a rational polycyclic matrix group. ## returned is a radical series of Q^d ## and full data of the used homomorphisms and algebras ## POL_RadicalSeriesNormalGensFullData := function(gens, mats, d ) local radb, splt, nath,inducedgens, l, sers, i, sub, full, acts, sersFullData, rads, radsFullData, record; # catch the trivial case and set up if d = 0 then return rec( sers := [], sersFullData := [] ); fi; full := IdentityMat( d ); if Length( mats ) = 0 then sers := [full, []]; sersFullData := [ rec(radical := [], nathom := [], algebra := []) ]; return rec( sers:= sers, sersFullData := sersFullData ); fi; sers := [full]; # get the radical radb := POL_RadicalNormalGens(gens, mats, d ); if radb = fail then return fail; fi; nath := radb.nathom; Add( sers, radb.radical ); sersFullData := [radb ]; # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); inducedgens:=List( gens, x -> InducedActionSubspaceByNHSEB( x, nath ) ); # use recursive call to refine radical record := POL_RadicalSeriesNormalGensFullData(inducedgens,acts, Length(radb.radical) ); if record = fail then return fail; fi; rads := record.sers; radsFullData := record.sersFullData; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); Append( sersFullData , radsFullData ); return rec( sers := sers, sersFullData := sersFullData ); end; ############################################################################# ## #F RadicalSeriesAbelianRMGroup( mats, d ) ## ## G is an abelian rational matrix group ## RadicalSeriesAbelianRMGroup := function( mats, d ) local radb, splt, nath, l, sers, i, sub, full, acts, rads; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := RadicalOfAbelianRMGroup( mats, d ); if radb = fail then return fail; fi; nath := radb.nathom; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); # use recursive call to refine radical rads := RadicalSeriesAbelianRMGroup(acts, Length(radb.radical) ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F POL_HomogeneousSeriesAbelianRMGroup( mats, d ) ## ## is an abelian rational matrix group ## POL_HomogeneousSeriesAbelianRMGroup := function( mats, d ) local radb, splt, nath,inducedgens, l, sers, i, sub, full, acts, rads; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := RadicalOfAbelianRMGroup( mats, d ); if radb = fail then return fail; fi; splt := POL_SplitSemisimple( radb.algebra ); nath := radb.nathom; # refine radical factor and initialize series l := Length( splt ); for i in [2..l] do sub := Concatenation( List( [i..l], x -> splt[x].basis ) ); TriangulizeMat( sub ); Add( sers, PreimageByNHSEB( sub, nath ) ); od; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); # use recursive call to refine radical rads := POL_HomogeneousSeriesAbelianRMGroup( acts, Length(radb.radical) ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F HomogeneousSeriesAbelianMatGroup( G ) ## ## is an abelian rational matrix group ## # FIXME: This function is documented and should be turned into a GlobalFunction HomogeneousSeriesAbelianMatGroup := function( G ) local mats,d; if not IsRationalMatrixGroup( G ) or not IsAbelian( G ) then Print( "input must be an abelian rational matrix group.\n" ); return fail; fi; mats := GeneratorsOfGroup( G ); d := Length( mats[1] ); return POL_HomogeneousSeriesAbelianRMGroup( mats, d ); end; ############################################################################# ## #F RadicalSeriesPRMGroup( G ) ## ## G is a rational polycyclic matrix group ## RadicalSeriesPRMGroup := function( G ) local p,d,gens_p,bound_derivedLength,pcgs_I_p,gens_K_p, radicalSeries,gens_K_p_m, gens, gens_K_p_mutableCopy; gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an admissible prime p := DetermineAdmissiblePrime(gens); Info( InfoPolenta, 1, "Chosen admissible prime: " , p ); Info( InfoPolenta, 1, " " ); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the image under the p-congruence homomorphism ..." ); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); if pcgs_I_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); Info( InfoPolenta, 1, "Finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ), "." ); Info( InfoPolenta, 1, " " ); # compute the normal the subgroup gens. for the kernel of phi_p Info( InfoPolenta, 1,"Compute normal subgroup generators for the kernel\n", " of the p-congruence homomorphism ..."); gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); gens_K_p := Filtered( gens_K_p, x -> not x = IdentityMat(d) ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 2,"The normal subgroup generators are" ); Info( InfoPolenta, 2, gens_K_p ); Info( InfoPolenta, 1, " " ); # radical series gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); radicalSeries := POL_RadicalSeriesNormalGens( gens, gens_K_p_mutableCopy, d ); if radicalSeries=fail then return fail; fi; return radicalSeries; end; ############################################################################# ## #F POL_HomogeneousSeriesPRMGroup( G ) ## ## G is a rational polycyclic matrix group, ## returned is a homogeneous series of the natural K_p-module Q^d ## POL_HomogeneousSeriesPRMGroup := function( G ) local p,d,gens_p,bound_derivedLength,pcgs_I_p,gens_K_p, homSeries,gens_K_p_m, gens, gens_K_p_mutableCopy; gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an admissible prime p := DetermineAdmissiblePrime(gens); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; Info( InfoPolenta, 1,"determine a constructive polycyclic sequence"); Info( InfoPolenta, 1,"for the image under the p-congruence homomorph."); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); Info( InfoPolenta, 1, "finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ) ); gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); # Print( "gens_K_p is equal to", gens_K_p, "\n" ); # step 4 Info( InfoPolenta, 1, "compute the radical series \n"); gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); homSeries := POL_HomogeneousSeriesNormalGens( gens, gens_K_p_mutableCopy, d ); return homSeries; end; ############################################################################# ## #F POL_InducedActionToSeries (gens_K_p, radicalSeries) ## ## returns the action of the matrices in gens_K_p induced to the ## factors of radicalSeries ## POL_InducedActionToSeries := function(gens_K_p,radicalSeries) local action,blockGens,sizeOfBlock,d,homs,l,i,g, actionParts,hom,image_of_g,c,a,j; d:=Length(gens_K_p[1][1]); homs:=[]; blockGens:=[]; l:=Length(radicalSeries)-1; for i in [1..l] do radicalSeries[i] := SemiEchelonMat( radicalSeries[i] ).vectors; #TriangulizeMat( radicalSeries[i] ); # we cannot use TriangulizeMat, because # TriangulizeMat( radicalSeries[i] ) can change # radicalSeries[i+1]! Then radicalSeries[i+1] can fail to be # a module. od; for i in [1..l] do homs[i]:=NaturalHomomorphismBySemiEchelonBases( radicalSeries[i], radicalSeries[i+1]); od; for hom in homs do actionParts:=[]; for g in gens_K_p do action:=InducedActionFactorByNHSEB( g, hom ); Add(actionParts,action); od; Add(blockGens,actionParts); od; return blockGens; end; ############################################################################# ## #M RadicalSeriesSolvableMatGroup( G ) ## ## G is a matrix group over the Rationals ## InstallMethod( RadicalSeriesSolvableMatGroup, "for solvable matrix groups (Polenta)", true, [ IsCyclotomicMatrixGroup ], 0, function( G ) local mats, d; if not IsRationalMatrixGroup( G ) then Print( "matrix groups must defined over the rationals" ); return fail; fi; if IsAbelian( G ) then mats := GeneratorsOfGroup( G ); d := Length( mats[1] ); return RadicalSeriesAbelianRMGroup( mats, d ); else return RadicalSeriesPRMGroup( G ); fi; end ); ############################################################################# ## #F POL_SplitHomogeneous( base, mats ) ## ## split the homogeneous module into irreducibles ## POL_SplitHomogeneous := function( base, mats ) local IrreducibleList,b,space_basis, space, basis; IrreducibleList :=[]; # spinn up new irreducible module basis := SpinnUpEchelonBase( [], [base[1]], mats, OnRight ); Add( IrreducibleList, basis ); # check if basis is already big enough if Length( basis ) = Length( base ) then # = but base has nicer form return [base]; fi; for b in base do # check if b is not already contained in one of the irreducible # modules in IrreducibleList space_basis := Concatenation( IrreducibleList ); space := VectorSpace( Rationals, space_basis, "basis" ); if not b in space then # spin up new irreducible module basis := SpinnUpEchelonBase( [], [b], mats, OnRight ); Add( IrreducibleList, basis ); fi; od; return IrreducibleList; end; ############################################################################# ## #F POL_IsRationalModule( base, mats ) ## POL_IsRationalModule := function( base, mats ) local V, b, m; if Length( base ) = 0 then return true; fi; V := VectorSpace( Rationals, base ); for b in base do for m in mats do if not b*m in V then return false; fi; od; od; return true; end; ############################################################################# ## #F POL_CompositionSeriesNormalGens(gens, mats, d ) ## ## mats are normal subgroup generators for the Kernel K_p in G = ## returned is composition series of the K_p-module Q^d ## POL_CompositionSeriesNormalGens := function(gens, mats, d ) local radb, splt, nath,inducedgens, l, sers, i,j, sub, full, acts, preImageSub, irreducibleList, k, rads, induced, irreducibles, factorMats, isomIrreds, basis, sub2; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := POL_RadicalNormalGens(gens, mats, d ); if radb = fail then return fail; fi; splt := POL_SplitSemisimple( radb.algebra ); nath := radb.nathom; # refine radical factor to irreducible components l := Length( splt ); irreducibles := []; # induce action to factor factorMats := List( mats, x -> InducedActionFactorByNHSEB( x, nath )); for i in [1..l] do # split i^th homogeneous component into isomorphic comp. basis := POL_CopyVectorList( splt[i].basis ); Assert( 2, POL_IsRationalModule( basis, factorMats ), "hom. component fails to be a module" ); isomIrreds := POL_SplitHomogeneous( basis, factorMats ); for j in [1..Length( isomIrreds )] do Assert( 2, POL_IsRationalModule( isomIrreds[j], factorMats ), "irred. component fails to be a module" ); od; irreducibles := Concatenation( irreducibles, isomIrreds ); od; # initialize series k := Length( irreducibles ); for i in [2..k] do sub := Concatenation( List( [i..k], x -> irreducibles[x] ) ); sub2 := POL_CopyVectorList( sub ); TriangulizeMat( sub2 ); Assert( 2, POL_IsRationalModule( sub2, factorMats ), "sum of irred. components fails to be a module\n" ); preImageSub := PreimageByNHSEB( sub2, nath ); Assert( 2, POL_IsRationalModule( preImageSub, mats ), "sum of irred. components fails to be a module\n" ); Add( sers, preImageSub ); od; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); inducedgens:=List( gens, x -> InducedActionSubspaceByNHSEB( x, nath ) ); # use recursive call to refine radical rads := POL_CompositionSeriesNormalGens(inducedgens,acts, Length(radb.radical) ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F POL_CompositionSeriesByRadicalSeries( mats , d, sersFullData, pos ) ## ## mats are generators of a triangularizable matrix group ## sersFullData contains the full data, which were obtained in the ## computation of the radical series ## returned is composition series of the -module Q^d ## POL_CompositionSeriesByRadicalSeries := function( mats, d, sersFullData, pos) local radb, splt, nath,inducedgens, l, sers, i,j, sub, full, acts, preImageSub, irreducibleList, k, rads, induced, irreducibles, factorMats, isomIrreds, basis, sub2, indm, indm_flat, algebra; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := sersFullData[pos]; if radb = fail then return fail; fi; nath := radb.nathom; splt := POL_SplitSemisimple( radb.algebra ); # refine radical factor to irreducible components l := Length( splt ); irreducibles := []; # induce action to factor factorMats := List( mats, x -> InducedActionFactorByNHSEB( x, nath )); for i in [1..l] do # split i^th homogeneous component into isomorphic comp. basis := POL_CopyVectorList( splt[i].basis ); Assert( 2, POL_IsRationalModule( basis, factorMats ), "hom. component fails to be a module" ); isomIrreds := POL_SplitHomogeneous( basis, factorMats ); for j in [1..Length( isomIrreds )] do Assert( 2, POL_IsRationalModule( isomIrreds[j], factorMats ), "irred. component fails to be a module" ); od; irreducibles := Concatenation( irreducibles, isomIrreds ); od; # initialize series k := Length( irreducibles ); for i in [2..k] do sub := Concatenation( List( [i..k], x -> irreducibles[x] ) ); sub2 := POL_CopyVectorList( sub ); TriangulizeMat( sub2 ); Assert( 2, POL_IsRationalModule( sub2, factorMats ), "sum of irred. components fails to be a module\n" ); preImageSub := PreimageByNHSEB( sub2, nath ); Assert( 2, POL_IsRationalModule( preImageSub, mats ), "sum of irred. components fails to be a module\n" ); Add( sers, preImageSub ); od; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); # use recursive call to refine radical rads := POL_CompositionSeriesByRadicalSeries(acts, Length(radb.radical), sersFullData, pos +1 ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F POL_CompositionSeriesByRadicalSeriesRecalAlg( mats , d, sersFullData, pos ) ## ## mats are generators of a triangularizable matrix group ## sersFullData contains the full data, which were obtained in the ## computation of the radical series ## returned is composition series of the -module Q^d ## ## the algebras which are used for the splitting are recalculated in this ## version. This is for example necessary if the algebra basis in ## sersFullData are computed with a different group (for example K_p()) ## than . ## POL_CompositionSeriesByRadicalSeriesRecalAlg := function( mats, d, sersFullData, pos) local radb, splt, nath,inducedgens, l, sers, i,j, sub, full, acts, preImageSub, irreducibleList, k, rads, induced, irreducibles, factorMats, isomIrreds, basis, sub2, indm, indm_flat, algebra; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := sersFullData[pos]; if radb = fail then return fail; fi; nath := radb.nathom; #compute a base for the algebra Q[ indmats ] where #indmats is the induced action of Q^d/radical #and bring it in flat format indm := List( mats, x ->InducedActionFactorByNHSEB(x,nath )); indm_flat := List( indm, x-> Flat( x )); algebra := SpinnUpEchelonBase( [ ], indm_flat, indm, OnMatVector ); #splt := POL_SplitSemisimple( radb.algebra ); splt := POL_SplitSemisimple( algebra ); # refine radical factor to irreducible components l := Length( splt ); irreducibles := []; # induce action to factor factorMats := List( mats, x -> InducedActionFactorByNHSEB( x, nath )); for i in [1..l] do # split i^th homogeneous component into isomorphic comp. basis := POL_CopyVectorList( splt[i].basis ); Assert( 2, POL_IsRationalModule( basis, factorMats ), "hom. component fails to be a module" ); isomIrreds := POL_SplitHomogeneous( basis, factorMats ); for j in [1..Length( isomIrreds )] do Assert( 2, POL_IsRationalModule( isomIrreds[j], factorMats ), "irred. component fails to be a module" ); od; irreducibles := Concatenation( irreducibles, isomIrreds ); od; # initialize series k := Length( irreducibles ); for i in [2..k] do sub := Concatenation( List( [i..k], x -> irreducibles[x] ) ); sub2 := POL_CopyVectorList( sub ); TriangulizeMat( sub2 ); Assert( 2, POL_IsRationalModule( sub2, factorMats ), "sum of irred. components fails to be a module\n" ); preImageSub := PreimageByNHSEB( sub2, nath ); Assert( 2, POL_IsRationalModule( preImageSub, mats ), "sum of irred. components fails to be a module\n" ); Add( sers, preImageSub ); od; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); # use recursive call to refine radical rads := POL_CompositionSeriesByRadicalSeriesRecalAlg(acts, Length(radb.radical), sersFullData, pos +1 ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F POL_CompositionSeriesAbelianRMGroup( mats, d ) ## ## is an abelian rational matrix group ## returned is a composition series for the natrual -module Q^d ## POL_CompositionSeriesAbelianRMGroup := function( mats, d ) local radb, splt, nath,inducedgens, l, sers, i, sub, full, acts, rads, preImageSub, irreducibleList, k, irreducibles, factorMats, isomIrreds, basis, sub2; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := RadicalOfAbelianRMGroup( mats, d ); if radb = fail then return fail; fi; splt := POL_SplitSemisimple( radb.algebra ); nath := radb.nathom; # refine radical factor to irreducible components l := Length( splt ); irreducibles := []; # induce action to factor factorMats := List( mats, x -> InducedActionFactorByNHSEB( x, nath )); for i in [1..l] do # split i^th homogeneous component into isomorphic comp. basis := POL_CopyVectorList( splt[i].basis ); isomIrreds := POL_SplitHomogeneous( basis, factorMats ); irreducibles := Concatenation( irreducibles, isomIrreds ); od; # initialize series k := Length( irreducibles ); for i in [2..k] do sub := Concatenation( List( [i..k], x -> irreducibles[x] ) ); sub2 := POL_CopyVectorList( sub ); TriangulizeMat( sub2 ); Assert( 2, POL_IsRationalModule( sub2, factorMats ), "sum of irred. components fails to be a module\n" ); preImageSub := PreimageByNHSEB( sub2, nath ); Add( sers, preImageSub ); od; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); # use recursive call to refine radical rads := POL_CompositionSeriesAbelianRMGroup( acts, Length(radb.radical) ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F CompositionSeriesAbelianMatGroup( G ) ## ## is an abelian rational matrix group ## # FIXME: This function is documented and should be turned into a GlobalFunction CompositionSeriesAbelianMatGroup := function( G ) local mats,d; if not IsRationalMatrixGroup( G ) or not IsAbelian( G ) then Print( "input must be an abelian rational matrix group.\n" ); return fail; fi; mats := GeneratorsOfGroup( G ); d := Length( mats[1] ); return POL_CompositionSeriesAbelianRMGroup( mats, d ); end; ############################################################################# ## #F POL_CompositionSeriesTriangularizablRMGroup( gens, d ) ## ## is a triang. rational matrix group ## returned is a composition series for the natural -module Q^d ## POL_CompositionSeriesTriangularizableRMGroup := function( gens, d ) local p, gens_p,G, bound_derivedLength, pcgs_I_p, gens_K_p, gens_K_p_m, gens_K_p_mutableCopy, pcgs, gensOfBlockAction, radSeries, comSeries, recordSeries, isTriang,gens_mutableCopy; # determine an admissible prime p := DetermineAdmissiblePrime(gens); Info( InfoPolenta, 1, "Chosen admissible prime: " , p ); Info( InfoPolenta, 1, " " ); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; # finite part Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the image under the p-congruence homomorphism ..." ); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); if pcgs_I_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); Info( InfoPolenta, 1, "Finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ), "." ); Info( InfoPolenta, 1, " " ); # compute the normal the subgroup gens. for the kernel of phi_p Info( InfoPolenta, 1,"Compute normal subgroup generators for the kernel\n", " of the p-congruence homomorphism ..."); gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); gens_K_p := Filtered( gens_K_p, x -> not x = IdentityMat(d) ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 2,"The normal subgroup generators are" ); Info( InfoPolenta, 2, gens_K_p ); Info( InfoPolenta, 1, " " ); # radical series Info( InfoPolenta, 1, "Compute the radical series ..."); gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); recordSeries := POL_RadicalSeriesNormalGensFullData( gens, gens_K_p_mutableCopy, d ); if recordSeries=fail then return fail; fi; radSeries := recordSeries.sers; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The radical series has length ", Length( radSeries ), "." ); Info( InfoPolenta, 2, "The radical series is" ); Info( InfoPolenta, 2, radSeries ); Info( InfoPolenta, 1, " " ); # test if G is unipotent by abelian isTriang := POL_TestIsUnipotenByAbelianGroupByRadSeries( gens, radSeries ); if isTriang then Info( InfoPolenta, 1, "Group is triangularizable!" ); gens_mutableCopy := CopyMatrixList( gens ); # compositions series comSeries := POL_CompositionSeriesByRadicalSeriesRecalAlg( gens_mutableCopy, d, recordSeries.sersFullData, 1 ); if comSeries=fail then return fail; fi; return comSeries; else Print( "The input group is not triangularizable.\n" ); return fail; fi; end; ############################################################################# ## #F CompositionSeriesTriangularizableMatGroup( G ) ## ## is a triangularizable rational matrix group ## # FIXME: This function is documented and should be turned into a GlobalFunction CompositionSeriesTriangularizableMatGroup := function( G ) local mats,d; if not IsRationalMatrixGroup( G ) then Print( "input must be a rational matrix group.\n" ); return fail; fi; mats := GeneratorsOfGroup( G ); d := Length( mats[1] ); if IsAbelian( G ) then return POL_CompositionSeriesAbelianRMGroup( mats, d ); else return POL_CompositionSeriesTriangularizableRMGroup( mats, d ); fi; end; ############################################################################# ## #F POL_HomogeneousSeriesByRadicalSeriesRecalAlg( mats , d, sersFullData, pos ) ## ## mats are generators of a triangularizable matrix group ## sersFullData contains the full data, which were obtained in the ## computation of the radical series ## returned is homog. series of the -module Q^d ## ## the algebras which are used for the splitting are recalculated in this ## version. This is for example necessary if the algebra basis in ## sersFullData are computed with a different group (for example K_p()) ## than . ## POL_HomogeneousSeriesByRadicalSeriesRecalAlg := function( mats, d, sersFullData, pos) local radb, splt, nath,inducedgens, l, sers, i,j, sub, full, acts, preImageSub, irreducibleList, k, rads, induced, irreducibles, factorMats, isomIrreds, basis, sub2, indm, indm_flat, algebra; # catch the trivial case and set up if d = 0 then return []; fi; full := IdentityMat( d ); if Length( mats ) = 0 then return [full, []]; fi; sers := [full]; # get the radical radb := sersFullData[pos]; if radb = fail then return fail; fi; nath := radb.nathom; #compute a base for the algebra Q[ indmats ] where #indmats is the induced action of Q^d/radical #and bring it in flat format indm := List( mats, x ->InducedActionFactorByNHSEB(x,nath )); indm_flat := List( indm, x-> Flat( x )); algebra := SpinnUpEchelonBase( [ ], indm_flat, indm, OnMatVector ); #splt := POL_SplitSemisimple( radb.algebra ); splt := POL_SplitSemisimple( algebra ); # refine radical factor and initialize series l := Length( splt ); for i in [2..l] do sub := Concatenation( List( [i..l], x -> splt[x].basis ) ); TriangulizeMat( sub ); Add( sers, PreimageByNHSEB( sub, nath ) ); od; Add( sers, radb.radical ); # induce action to radical nath := NaturalHomomorphismBySemiEchelonBases( full, radb.radical); acts := List( mats, x -> InducedActionSubspaceByNHSEB( x, nath )); # use recursive call to refine radical rads := POL_HomogeneousSeriesByRadicalSeriesRecalAlg(acts, Length(radb.radical), sersFullData, pos +1 ); if rads = fail then return fail; fi; rads := List( rads, function(x) if x=[] then return []; else return x * radb.radical; fi;end ); Append( sers, rads{[2..Length(rads)]} ); return sers; end; ############################################################################# ## #F POL_HomogeneousSeriesTriangularizablRMGroup( gens, d ) ## ## is a triang. rational matrix group ## returned is a homogeneous series for the natural -module Q^d ## POL_HomogeneousSeriesTriangularizableRMGroup := function( gens, d ) local p, gens_p,G, bound_derivedLength, pcgs_I_p, gens_K_p, gens_K_p_m, gens_K_p_mutableCopy, pcgs, gensOfBlockAction, radSeries, comSeries, recordSeries, isTriang,gens_mutableCopy; # determine an admissible prime p := DetermineAdmissiblePrime(gens); Info( InfoPolenta, 1, "Chosen admissible prime: " , p ); Info( InfoPolenta, 1, " " ); # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; # finite part Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the image under the p-congruence homomorphism ..." ); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); if pcgs_I_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); Info( InfoPolenta, 1, "Finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ), "." ); Info( InfoPolenta, 1, " " ); # compute the normal the subgroup gens. for the kernel of phi_p Info( InfoPolenta, 1,"Compute normal subgroup generators for the kernel\n", " of the p-congruence homomorphism ..."); gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); gens_K_p := Filtered( gens_K_p, x -> not x = IdentityMat(d) ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 2,"The normal subgroup generators are" ); Info( InfoPolenta, 2, gens_K_p ); Info( InfoPolenta, 1, " " ); # radical series Info( InfoPolenta, 1, "Compute the radical series ..."); gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); recordSeries := POL_RadicalSeriesNormalGensFullData( gens, gens_K_p_mutableCopy, d ); if recordSeries=fail then return fail; fi; radSeries := recordSeries.sers; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The radical series has length ", Length( radSeries ), "." ); Info( InfoPolenta, 2, "The radical series is" ); Info( InfoPolenta, 2, radSeries ); Info( InfoPolenta, 1, " " ); # test if G is unipotent by abelian isTriang := POL_TestIsUnipotenByAbelianGroupByRadSeries( gens, radSeries ); if isTriang then Info( InfoPolenta, 1, "Group is triangularizable!" ); gens_mutableCopy := CopyMatrixList( gens ); # homogeneous series comSeries := POL_HomogeneousSeriesByRadicalSeriesRecalAlg( gens_mutableCopy, d, recordSeries.sersFullData, 1 ); if comSeries=fail then return fail; fi; return comSeries; else Print( "The input group is not triangularizable.\n" ); return fail; fi; end; ############################################################################# ## #F HomogeneousSeriesTriangularizableMatGroup( G ) ## ## is a triangularizable rational matrix group ## # FIXME: This function is documented and should be turned into a GlobalFunction HomogeneousSeriesTriangularizableMatGroup := function( G ) local mats,d; if not IsRationalMatrixGroup( G ) then Print( "input must be a rational matrix group.\n" ); return fail; fi; mats := GeneratorsOfGroup( G ); d := Length( mats[1] ); if IsAbelian( G ) then return POL_HomogeneousSeriesAbelianRMGroup( mats, d ); else return POL_HomogeneousSeriesTriangularizableRMGroup( mats, d ); fi; end; ############################################################################# ## #E polenta-1.3.11/lib/present.gi000644 000766 000024 00000021047 14775712140 016311 0ustar00mhornstaff000000 000000 ############################################################################# ## #W present.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## pcp-presentations for matrix groups ## #Y 2003 ## ############################################################################# ## #F POL_Exp2genList(exp); ## POL_Exp2GenList:= function(exp) local n, genList,i; n:=Length(exp); genList:=[]; for i in [1..n] do if exp[i] <> 0 then Append(genList,[i,exp[i]]); fi; od; return genList; end; ############################################################################# ## #F POL_SetPcPresentation_infinite(pcgs) ## ## pcgs is a constructive pc-Sequence,calculated by CPCS_PRMGroup ## this function calculates a PcPresentation for the group described ## by pcgs ## POL_SetPcPresentation_infinite:= function(pcgs) local genList,ftl,n,ro,i,j,exp,conj,f_i,f_j,r_i,pcsInv; # Setup n:=Length(pcgs.pcs); ftl:=FromTheLeftCollector(n); #pcSeq:=StructuralCopy((pcgs.gens)); pcsInv:=[]; for i in [1..n] do pcsInv[i]:=pcgs.pcs[i]^-1; od; # the relative orders ro:= pcgs.rels; for i in [1..n] do if ro[i]<>0 then SetRelativeOrder(ftl,i,ro[i]); fi; od; Info( InfoPolenta, 1, "Compute power relations ..." ); # Set power relations for i in [1..n] do if ro[i]<>0 then f_i:=pcgs.pcs[i]; r_i:=ro[i]; exp:=ExponentVector_CPCS_PRMGroup( f_i^r_i,pcgs ); if InfoLevel( InfoPolenta ) >= 2 then Print( "." ); fi; genList := POL_Exp2GenList(exp); SetPower(ftl,i,genList); fi; od; if InfoLevel( InfoPolenta ) >= 2 then Print( "\n" ); fi; Info( InfoPolenta, 1, "... finished." ); Info( InfoPolenta, 1, "Compute conjugation relations ..." ); # Set the conjugation relations for i in [1..n] do for j in [1..(i-1)] do # conjugation with g_j f_i:=pcgs.pcs[i]; f_j:=pcgs.pcs[j]; conj:=(pcsInv[j])*f_i*f_j; Assert(1, conj=f_i^f_j ); exp:=ExponentVector_CPCS_PRMGroup( conj,pcgs); Assert(1, conj=Product(List([1..n],i->pcgs.pcs[i]^exp[i])) ); if InfoLevel( InfoPolenta ) >= 2 then Print( "." ); fi; genList:=POL_Exp2GenList(exp); SetConjugate(ftl,i,j,genList); # conjugation with g_j^-1 if g_j has infinite order if ro[i] = 0 then conj:= f_j* f_i *(pcsInv[j]); Assert(1, conj=f_i^(f_j^-1) ); exp:=ExponentVector_CPCS_PRMGroup( conj,pcgs); Assert(1, conj=Product(List([1..n],i->pcgs.pcs[i]^exp[i])) ); if InfoLevel( InfoPolenta ) >= 2 then Print( "." ); fi; genList:=POL_Exp2GenList(exp); SetConjugate(ftl,i,-j,genList); fi; od; od; if InfoLevel( InfoPolenta ) >= 2 then Print( "\n" ); fi; Info( InfoPolenta, 1, "... finished." ); Info( InfoPolenta, 1, "Update polycyclic collector ... " ); UpdatePolycyclicCollector(ftl); Info( InfoPolenta, 1, "... finished." ); return ftl; end; # remark: some of the information (i.e. parts of the exponents vectors) # which we need in the last algorithm, # arise naturally in the computation of the normal subgroup # generators. It could be transferred from there. ############################################################################# ## #F POL_PcpGroupByMatGroup_infinite( arg ) ## ## arg[1]=G is a subgroup of GL(d, Q ). The algorithm returns a PcpGroup if G ## is polycyclic. ## POL_PcpGroupByMatGroup_infinite := function( arg ) local CPCS, pcp, K,G,p; G := arg[1]; if Length(arg)=2 then p := arg[2]; CPCS := CPCS_PRMGroup( G, p ); else CPCS := CPCS_PRMGroup( G ); fi; if CPCS = fail then return fail; fi; Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Compute the relations of the polycyclic\n", " presentation of the group ..." ); pcp := POL_SetPcPresentation_infinite( CPCS ); Info( InfoPolenta, 1,"finished." ); Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Construct the polycyclic presented group ..." ); if AssertionLevel() = 0 then K := PcpGroupByCollectorNC( pcp ); else K := PcpGroupByCollector( pcp ); fi; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, " " ); return K; end; ############################################################################# ## #F POL_SetPcPresentation_finite(pcgs) ## ## pcgs is a constructive pc-sequence of a finite group, calculated ## by CPCS_finite. ## this function calculates a PcPresentation for the group described ## by pcgs ## POL_SetPcPresentation_finite:= function(pcgs) local genList,ftl,n,ro,i,j,exp,conj,f_i,f_j,r_i,pcsInv, pcs; # setup n := Length(pcgs.gens); ftl := FromTheLeftCollector(n); # Attention: In pcgs.gens we have the pc-sequence in inverse order # because we built up the structure bottom up pcs := StructuralCopy(Reversed(pcgs.gens)); pcsInv:=[]; for i in [1..n] do pcsInv[i]:=pcs[i]^-1; od; # calculate the relative orders ro := RelativeOrdersPcgs_finite( pcgs ); # set relative orders for i in [1..n] do SetRelativeOrder(ftl,i,ro[i]); od; # Set power relations for i in [1..n] do if ro[i]<>0 then f_i:=pcs[i]; r_i:=ro[i]; exp:= ExponentvectorPcgs_finite( pcgs, f_i^r_i ); genList := POL_Exp2GenList(exp); SetPower(ftl,i,genList); fi; od; # Set the conjugation relations for i in [1..n] do for j in [1..(i-1)] do f_i:=pcs[i]; f_j:=pcs[j]; conj:=(pcsInv[j])*f_i*f_j; exp:=ExponentvectorPcgs_finite( pcgs, conj ); genList:=POL_Exp2GenList(exp); SetConjugate(ftl,i,j,genList); od; od; UpdatePolycyclicCollector(ftl); return ftl; end; ############################################################################# ## #F POL_PcpGroupByMatGroup_finite( G ) ## ## G is a subgroup of GL(d, Q ). The algorithm returns a PcpGroup if G ## is polycyclic. ## POL_PcpGroupByMatGroup_finite := function( G ) local CPCS, pcp, K, gens, d, bound_derivedLength; Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the input group ..."); # setup gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an upper bound for the derived length of G bound_derivedLength := d+2; CPCS := CPCS_finite_word( gens, bound_derivedLength ); if CPCS = fail then return fail; fi; Info( InfoPolenta, 1, "finished." ); Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Compute the relations of the polycyclic\n", " presentation of the group ..." ); pcp := POL_SetPcPresentation_finite( CPCS ); Info( InfoPolenta, 1,"finished." ); Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Construct the polycyclic presented group ..." ); K := PcpGroupByCollector( pcp ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, " " ); return K; end; ############################################################################# ## #M PcpGroupByMatGroup( G ) ## ## G is a matrix group over the Rationals or a finite field. ## Returned is PcpGroup ( polycyclically presented group) ## which is isomorphic to G. ## InstallMethod( PcpGroupByMatGroup, "for matrix groups over a finite field (Polenta)", true, [ IsFFEMatrixGroup ], 0, POL_PcpGroupByMatGroup_finite ); InstallMethod( PcpGroupByMatGroup, "for rational matrix groups (Polenta)", true, [ IsRationalMatrixGroup ], 0, POL_PcpGroupByMatGroup_infinite ); ## Enforce rationality check for cyclotomic matrix groups RedispatchOnCondition( PcpGroupByMatGroup, true, [ IsCyclotomicMatrixGroup ], [ IsRationalMatrixGroup ], RankFilter(IsCyclotomicMatrixGroup) ); InstallOtherMethod( PcpGroupByMatGroup, "for polycyclic matrix groups (Polenta)", true, [ IsCyclotomicMatrixGroup, IsInt ], 0, function( G, p ) if not IsPrime(p) then Print( "Second argument must be a prime number.\n" ); return fail; fi; if IsRationalMatrixGroup(G) then return POL_PcpGroupByMatGroup_infinite( G, p ); fi; TryNextMethod(); end ); ############################################################################# ## #E polenta-1.3.11/lib/isom.gi000644 000766 000024 00000013267 14775712140 015605 0ustar00mhornstaff000000 000000 ############################################################################# ## #W isom.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## isomorphisms from matrix groups to pcp-presentations ## #Y 2003 ## ############################################################################# ## #F POL_IsomorphismToMatrixGroup_infinite ## POL_IsomorphismToMatrixGroup_infinite := function( arg ) local CPCS, pcp, H, nat,G; G := arg[1]; # calculate a constructive pc-sequence if Length( arg ) = 2 then CPCS := CPCS_PRMGroup( G, arg[2] ); else CPCS := CPCS_PRMGroup( G ); fi; if CPCS = fail then return fail; fi; Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Compute the relations of the polycyclic\n", " presentation of the group ..." ); pcp := POL_SetPcPresentation_infinite( CPCS ); Info( InfoPolenta, 1,"finished." ); Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Construct the polycyclic presented group ..." ); H := PcpGroupByCollector( pcp ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Construct the isomorphism on the polycyclic\n", " presented group ..." ); nat := GroupHomomorphismByImagesNC( G, H, CPCS.pcs, AsList(Pcp(H)) ); Info( InfoPolenta, 1,"finished."); # add infos SetIsBijective( nat, true ); SetIsIsomorphismByPolycyclicMatrixGroup( nat, true ); nat!.CPCS := CPCS; return nat; end; ############################################################################# ## #F POL_IsomorphismToMatrixGroup_finite ## POL_IsomorphismToMatrixGroup_finite := function( G ) local CPCS, pcp, H, nat, gens, d, pcs, bound_derivedLength; Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the input group ..."); # calculate a constructive pc-sequence gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); # determine an upper bound for the derived length of G bound_derivedLength := d+2; CPCS := CPCS_finite_word( gens, bound_derivedLength ); if CPCS = fail then return fail; fi; Info( InfoPolenta, 1, "finished." ); Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Compute the relations of the polycyclic\n", " presentation of the group ..." ); pcp := POL_SetPcPresentation_finite( CPCS ); Info( InfoPolenta, 1,"finished." ); Info( InfoPolenta, 1, " " ); Info( InfoPolenta, 1,"Construct the polycyclic presented group ..." ); H := PcpGroupByCollector( pcp ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, " " ); # new generating set for G pcs := Reversed(CPCS.gens); Info( InfoPolenta, 1,"Construct the isomorphism on the polycyclic\n", " presented group ..." ); nat := GroupHomomorphismByImagesNC( G, H, pcs, AsList(Pcp(H)) ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, " " ); # add infos SetIsBijective( nat, true ); SetIsIsomorphismByFinitePolycyclicMatrixGroup( nat, true ); nat!.CPCS := CPCS; return nat; end; ############################################################################# ## #M Create isom to pcp group ## InstallMethod( IsomorphismPcpGroup, "for matrix groups over a finite field (Polenta)", true, [ IsFFEMatrixGroup ], 0, POL_IsomorphismToMatrixGroup_finite ); InstallMethod( IsomorphismPcpGroup, "for rational matrix groups (Polenta)", true, [ IsRationalMatrixGroup ], 0, POL_IsomorphismToMatrixGroup_infinite ); ## Enforce rationality check for cyclotomic matrix groups RedispatchOnCondition( IsomorphismPcpGroup, true, [ IsCyclotomicMatrixGroup ], [ IsRationalMatrixGroup ], RankFilter(IsCyclotomicMatrixGroup) ); InstallOtherMethod( IsomorphismPcpGroup, "for matrix groups (Polenta)", true, [IsCyclotomicMatrixGroup, IsInt], 0, function( G, p ) if IsRationalMatrixGroup( G ) then if not IsPrime(p) then Print( "Second argument must be a prime number.\n" ); return fail; fi; return POL_IsomorphismToMatrixGroup_infinite( G, p ); fi; TryNextMethod(); end); ############################################################################# ## #M Images under IsomorphismByPolycyclicMatrixGroup ## InstallMethod( ImagesRepresentative, "for isom by matrix groups (Polenta)", FamSourceEqFamElm, [IsGroupGeneralMappingByImages and IsIsomorphismByPolycyclicMatrixGroup, IsMultiplicativeElementWithInverse], 0, function( nat, h ) local H, e, CPCS; CPCS := nat!.CPCS; H := Range( nat ); e := ExponentVector_CPCS_PRMGroup( h, CPCS ); if e=fail then return fail; fi; if Length(e)=0 then return OneOfPcp( Pcp( H ) );fi; return MappedVector( e, Pcp(H) ); end); ############################################################################# ## #M Images under IsomorphismByFinitePolycyclicMatrixGroup ## InstallMethod( ImagesRepresentative, "for isom by finite matrix groups (Polenta)", FamSourceEqFamElm, [IsGroupGeneralMappingByImages and IsIsomorphismByFinitePolycyclicMatrixGroup, IsMultiplicativeElementWithInverse], 0, function( nat, h ) local H, e, CPCS; CPCS := nat!.CPCS; H := Range( nat ); e := ExponentvectorPcgs_finite( CPCS, h ); if e=fail then return fail; fi; if Length(e)=0 then return OneOfPcp( Pcp( H ) );fi; return MappedVector( e, Pcp(H) ); end); ############################################################################# ## #E polenta-1.3.11/lib/cpcs.gi000644 000766 000024 00000053427 14775712140 015570 0ustar00mhornstaff000000 000000 ############################################################################# ## #W cpcs.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## constructive pc-sequences for rational matrix groups ## #Y 2003 ## ############################################################################# ## #F CPCS_PRMGroup( arg ) ## ## arg[1] = G is a rational polycyclic rational matrix group ## InstallGlobalFunction( CPCS_PRMGroup , function( arg ) local G; G := arg[1]; if IsAbelian( G ) then return CPCS_AbelianPRMGroup( G ); else if IsBound( arg[2] ) then return CPCS_NonAbelianPRMGroup( arg[1], arg[2] ); else return CPCS_NonAbelianPRMGroup( G ); fi; fi; end ); ############################################################################# ## #F CPCS_NonAbelianPRMGroup( arg ) ## ## arg[1] = G is an non-abelian polycyclic rational matrix group ## InstallGlobalFunction( CPCS_NonAbelianPRMGroup , function( arg ) local p, d, gens_p,G, bound_derivedLength, pcgs_I_p, gens_K_p, gens_K_p_m, gens, gens_K_p_mutableCopy, pcgs, gensOfBlockAction, pcgs_nue_K_p, pcgs_GU, gens_U_p, pcgs_U_p, radSeries, comSeries, recordSeries, isTriang, isFiniteGen, testIsPoly; # setup G := arg[1]; gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); Info( InfoPolenta, 1, "Determine a constructive polycyclic sequence\n", " for the input group ..." ); Info( InfoPolenta, 1, " " ); # determine an admissible prime or take the wished one if (Length( arg )) >= 2 and (arg[2] <> 0 ) then p := arg[2]; else p := DetermineAdmissiblePrime(gens); fi; Info( InfoPolenta, 1, "Chosen admissible prime: " , p ); Info( InfoPolenta, 1, " " ); # check whether this function is used for testing if G is polycyclic testIsPoly := false; if Length( arg ) = 3 then if arg[3] = "testIsPoly" then testIsPoly := true; fi; fi; # calculate the gens of the group phi_p() where phi_p is # natural homomorphism to GL(d,p) gens_p := InducedByField( gens, GF(p) ); # determine an upper bound for the derived length of G bound_derivedLength := d+2; # finite part Info( InfoPolenta, 1,"Determine a constructive polycyclic sequence\n", " for the image under the p-congruence homomorphism ..." ); pcgs_I_p := CPCS_finite_word( gens_p, bound_derivedLength ); if pcgs_I_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); Info( InfoPolenta, 1, "Finite image has relative orders ", RelativeOrdersPcgs_finite( pcgs_I_p ), "." ); Info( InfoPolenta, 1, " " ); # compute the normal the subgroup gens. for the kernel of phi_p Info( InfoPolenta, 1,"Compute normal subgroup generators for the kernel\n", " of the p-congruence homomorphism ..."); gens_K_p := POL_NormalSubgroupGeneratorsOfK_p( pcgs_I_p, gens ); gens_K_p := Filtered( gens_K_p, x -> not x = IdentityMat(d) ); Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 2,"The normal subgroup generators are" ); Info( InfoPolenta, 2, gens_K_p ); Info( InfoPolenta, 1, " " ); # if the input group was finite gens_K_p is an empty list if Length( gens_K_p ) = 0 then Add( gens_K_p, gens[1]^0 );fi; # radical series Info( InfoPolenta, 1, "Compute the radical series ..."); gens_K_p_mutableCopy := CopyMatrixList( gens_K_p ); recordSeries := POL_RadicalSeriesNormalGensFullData( gens, gens_K_p_mutableCopy, d ); if recordSeries = fail then return fail; fi; radSeries := recordSeries.sers; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The radical series has length ", Length( radSeries ), "." ); Info( InfoPolenta, 2, "The radical series is" ); Info( InfoPolenta, 2, radSeries ); Info( InfoPolenta, 1, " " ); # test if G is unipotent by abelian isTriang := POL_TestIsUnipotenByAbelianGroupByRadSeries( gens, radSeries ); if isTriang then Info( InfoPolenta, 1, "Group is triangularizable!" ); return CPCS_UnipotentByAbelianGroupByRadSeries( gens, recordSeries, testIsPoly ); fi; # compositions series Info( InfoPolenta, 1, "Compute the composition series ..."); comSeries := POL_CompositionSeriesByRadicalSeries( gens_K_p_mutableCopy, d, recordSeries.sersFullData, 1 ); if comSeries=fail then return fail; fi; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The composition series has length ", Length( comSeries ), "." ); Info( InfoPolenta, 2, "The composition series is" ); Info( InfoPolenta, 2, comSeries ); Info( InfoPolenta, 1, " " ); # induce K_p to the factors of the composition series gensOfBlockAction := POL_InducedActionToSeries(gens_K_p, comSeries); # let nue be the homomorphism which induces the action of K_p to # the factors of the series Info( InfoPolenta, 1, "Compute a constructive polycyclic sequence\n", " for the induced action of the kernel to the composition series ..."); pcgs_nue_K_p := CPCS_AbelianSSBlocks_ClosedUnderConj( gens_K_p, gens, comSeries ); if pcgs_nue_K_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); # update generators of K_p gens_K_p := pcgs_nue_K_p.gens_K_p; pcgs_nue_K_p := pcgs_nue_K_p.pcgs_nue_K_p; Info( InfoPolenta, 1, "This polycyclic sequence has relative orders ", pcgs_nue_K_p.relOrders, "." ); Info( InfoPolenta, 1, " " ); # constructive pc-sequence for G/U_p pcgs_GU := CPCS_FactorGU_p( gens, pcgs_I_p, gens_K_p, pcgs_nue_K_p, comSeries, p ); # normal subgroup generators for U_p Info( InfoPolenta, 1, "Calculate normal subgroup generators for the", "\n unipotent part ..." ); gens_U_p := POL_NormalSubgroupGeneratorsU_p( pcgs_GU, gens, gens_K_p ); Info( InfoPolenta, 1, "finished." ); Info( InfoPolenta, 2, "The normal subgroup generators for the unipotent part are" ); Info( InfoPolenta, 2, gens_U_p ); Info( InfoPolenta, 1, " " ); # test whether U_p is finitely generated. Info( InfoPolenta, 3, "Testing wheter U_p is finitely generated ..." ); isFiniteGen := POL_IsFinitelgeneratedU_p( gens_U_p, gens, pcgs_GU.pcs ); Info( InfoPolenta, 3, "... finished" ); if testIsPoly then return isFiniteGen; fi; if not isFiniteGen then return fail; fi; Info( InfoPolenta, 3, " " ); # determine a constructive pc-sequence for the unipotent group U_p Info( InfoPolenta, 1 ,"Determine a constructive polycyclic sequence\n", " for the unipotent part ..."); pcgs_U_p := CPCS_Unipotent_Conjugation( gens, gens_U_p ); if pcgs_U_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); Info(InfoPolenta,1, "The unipotent part has relative orders "); Info(InfoPolenta,1, pcgs_U_p.rels, "." ); Info( InfoPolenta, 1, " " ); # construct a pcs for the hole group pcgs := POL_MergeCPCS( pcgs_U_p, pcgs_GU); Info( InfoPolenta, 1, "... computation of a constructive \n", " polycyclic sequence for the whole group finished." ); return pcgs; end ); ############################################################################# ## #F CPCS_AbelianPRMGroup( G ) ## ## G is an abelian rational polycyclic rational matrix group ## InstallGlobalFunction( CPCS_AbelianPRMGroup , function( G ) local p, d, gens_p, bound_derivedLength, pcgs_I_p, gens_K_p, comSeries, gens, gens_mutableCopy, pcgs, gensOfBlockAction, pcgs_nue_K_p, pcgs_GU, gens_U_p, pcgs_U_p; # setup gens := GeneratorsOfGroup( G ); d := Length(gens[1][1]); Info( InfoPolenta, 1, "Determine a constructive polycyclic sequence\n", " for the input group ..." ); Info( InfoPolenta, 1, " " ); # skip the the p-congruence homomorphism pcgs_I_p := rec( gens := [], relOrders := [], wordGens := []); p := 0; # composition series Info( InfoPolenta, 1, "Compute the composition series ..."); gens_mutableCopy := CopyMatrixList( gens ); comSeries := POL_CompositionSeriesAbelianRMGroup( gens_mutableCopy, d ); if comSeries = fail then return fail; fi; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The composition series has length ", Length( comSeries ), "." ); Info( InfoPolenta, 2, "The composition series is" ); Info( InfoPolenta, 2, comSeries ); Info( InfoPolenta, 1, " " ); # induce gens to the factors of the composition series gensOfBlockAction := POL_InducedActionToSeries(gens, comSeries); # let nue be the homomorphism which induces the action of G to # the factors of the series Info( InfoPolenta, 1, "Compute a constructive polycyclic sequence\n", " for the induced action of the group to the composition series ..."); pcgs_nue_K_p := CPCS_AbelianSSBlocks( gensOfBlockAction ); Info(InfoPolenta,1,"finished."); Info( InfoPolenta, 1, "This polycyclic sequence has relative orders ", pcgs_nue_K_p.relOrders, "." ); Info( InfoPolenta, 1, " " ); # constructive pc-sequence for G/U_p pcgs_GU := CPCS_FactorGU_p( gens, pcgs_I_p, gens, pcgs_nue_K_p, comSeries, p ); # normal subgroup generators for U_p Info( InfoPolenta, 1, "Calculate normal subgroup generators for the", "\n unipotent part ..." ); gens_U_p := POL_NormalSubgroupGeneratorsU_p( pcgs_GU, gens, gens ); Info( InfoPolenta, 1, "finished." ); Info( InfoPolenta, 2, "The normal subgroup generators for the unipotent part are"); Info( InfoPolenta, 2, gens_U_p ); Info( InfoPolenta, 1, " " ); # determine a constructive pc-sequence for the unipotent group U_p Info( InfoPolenta, 1 ,"Determine a constructive polycyclic sequence\n", " for the unipotent part ..."); pcgs_U_p := CPCS_Unipotent_Conjugation( gens, gens_U_p ); if pcgs_U_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); Info(InfoPolenta,1, "The unipotent part has relative orders "); Info(InfoPolenta,1, pcgs_U_p.rels, "." ); Info( InfoPolenta, 1, " " ); # construct a pcs for the hole group pcgs := POL_MergeCPCS( pcgs_U_p, pcgs_GU); Info( InfoPolenta, 1, "... computation of a constructive \n", " polycyclic sequence for the whole group finished." ); return pcgs; end ); ############################################################################# ## #F CPCS_UnipotentByAbelianGroupByRadSeries( gens, recordSeries, testIsPoly ) ## ## G is an abelian rational polycyclic rational matrix group ## InstallGlobalFunction( CPCS_UnipotentByAbelianGroupByRadSeries , function( gens, recordSeries, testIsPoly ) local p, d, gens_p, bound_derivedLength, pcgs_I_p, gens_K_p, comSeries, gens_mutableCopy, pcgs, gensOfBlockAction, pcgs_nue_K_p, pcgs_GU, gens_U_p, pcgs_U_p, isFiniteGen; # setup d := Length(gens[1][1]); # skip the the p-congruence homomorphism pcgs_I_p := rec( gens := [], relOrders := [], wordGens := []); p := 0; gens_mutableCopy := CopyMatrixList( gens ); # compositions series Info( InfoPolenta, 1, "Compute the composition series ..."); comSeries := POL_CompositionSeriesByRadicalSeriesRecalAlg( gens_mutableCopy, d, recordSeries.sersFullData, 1 ); if comSeries=fail then return fail; fi; Info( InfoPolenta, 1,"finished."); Info( InfoPolenta, 1, "The composition series has length ", Length( comSeries ), "." ); Info( InfoPolenta, 2, "The composition series is" ); Info( InfoPolenta, 2, comSeries ); Info( InfoPolenta, 1, " " ); # induce gens to the factors of the composition series gensOfBlockAction := POL_InducedActionToSeries(gens, comSeries); # let nue be the homomorphism which induces the action of G to # the factors of the series Info( InfoPolenta, 1, "Compute a constructive polycyclic sequence\n", " for the induced action of the group to the composition series ..."); pcgs_nue_K_p := CPCS_AbelianSSBlocks( gensOfBlockAction ); Info(InfoPolenta,1,"finished."); Info( InfoPolenta, 1, "This polycyclic sequence has relative orders ", pcgs_nue_K_p.relOrders, "." ); Info( InfoPolenta, 1, " " ); # constructive pc-sequence for G/U_p pcgs_GU := CPCS_FactorGU_p( gens, pcgs_I_p, gens, pcgs_nue_K_p, comSeries, p ); # normal subgroup generators for U_p Info( InfoPolenta, 1, "Calculate normal subgroup generators for the", "\n unipotent part ..." ); gens_U_p := POL_NormalSubgroupGeneratorsU_p( pcgs_GU, gens, gens ); Info( InfoPolenta, 1, "finished." ); Info( InfoPolenta, 2, "The normal subgroup generators for the unipotent part are" ); Info( InfoPolenta, 2, gens_U_p ); Info( InfoPolenta, 1, " " ); # test whether U_p is finitely generated. Info( InfoPolenta, 3, "Testing wheter U_p is finitely generated ..." ); isFiniteGen := POL_IsFinitelgeneratedU_p( gens_U_p, gens, pcgs_GU.pcs ); Info( InfoPolenta, 3, "... finished" ); if testIsPoly then return isFiniteGen; fi; if not isFiniteGen then return fail; fi; Info( InfoPolenta, 3, " " ); # determine a constructive pc-sequence for the unipotent group U_p Info( InfoPolenta, 1 ,"Determine a constructive polycyclic sequence\n", " for the unipotent part ..."); pcgs_U_p := CPCS_Unipotent_Conjugation( gens, gens_U_p ); if pcgs_U_p = fail then return fail; fi; Info(InfoPolenta,1,"finished."); Info(InfoPolenta,1, "The unipotent part has relative orders "); Info(InfoPolenta,1, pcgs_U_p.rels, "." ); Info( InfoPolenta, 1, " " ); # construct a pcs for the hole group pcgs := POL_MergeCPCS( pcgs_U_p, pcgs_GU); Info( InfoPolenta, 1, "... computation of a constructive \n", " polycyclic sequence for the whole group finished." ); return pcgs; end ); ############################################################################# ## #F CPCS_FactorGU_p( gens, pcgs_I_p, gens_K_p, pcgs_nue_K_p, radicalSeries,p) ## ## calculates a constructive pcs for the G/U_p(G) ## InstallGlobalFunction( CPCS_FactorGU_p , function( gens, pcgs_I_p, gens_K_p, pcgs_nue_K_p, radicalSeries,p) local i,preImgsNue,preImgsI_p,pcs; # calculate preimages of the pcs of K_p(G)/U_p(G) which is # isomorphic to nue(K_p(G)) preImgsNue := POL_PreImagesPcsNueK_p_G( gens_K_p, pcgs_nue_K_p); # calculate the preimages of the pcs of G/K_p(G) which is isomorphic # to I_p_G preImgsI_p := POL_PreImagesPcsI_p_G( pcgs_I_p, gens); # Attention in preImgsI_p we have a reversed order of the pcs so preImgsI_p := Reversed( preImgsI_p ); Assert( 2, TestPOL_PreImagesPcsI_p_G( preImgsI_p, p, pcgs_I_p ), "error in the calculation of the preimages of I_p"); # now we have the new pcs for G/U_p pcs := Concatenation( preImgsI_p, preImgsNue); return rec( preImgsI_p := preImgsI_p, preImgsNue := preImgsNue, pcs := pcs, p := p, radicalSeries := radicalSeries, pcgs_I_p := pcgs_I_p, pcgs_nue_K_p := pcgs_nue_K_p ); end ); ############################################################################# ## #F POL_PreImagesPcsNueK_p_G( gens_K_p, pcgs_nue_K_p ) ## InstallGlobalFunction( POL_PreImagesPcsNueK_p_G , function( gens_K_p, pcgs_nue_K_p ) local preImages,i,l1,g,l; preImages := []; l1 := pcgs_nue_K_p.trsf; for l in l1 do g := gens_K_p[1]^0; for i in [1..Length(l)] do g := g*gens_K_p[i]^l[i]; od; Add( preImages, g ); od; return preImages; end ); ############################################################################# ## #F POL_PreImagesPcsI_p_G( pcgs_I_p, gens ) ## InstallGlobalFunction( POL_PreImagesPcsI_p_G , function( pcgs_I_p, gens ) local preImages,m,l,list,k; preImages := []; list := pcgs_I_p.wordGens; for l in list do k := gens[1]^0; for m in l do k := k*gens[m[1]]^m[2]; od; Add(preImages,k); od; return preImages; end ); ############################################################################# ## #F TestPOL_PreImagesPcsI_p_G( preImgsI_p, p, pcgs_I_p ); ## InstallGlobalFunction( TestPOL_PreImagesPcsI_p_G , function( preImgsI_p, p, pcgs_I_p ) local n,i, test; n := Length( preImgsI_p ); for i in [1..n] do test := ( preImgsI_p[i]*One(GF(p)) = pcgs_I_p.gens[n-i+1]); if not test then return fail; fi; od; return true; end ); ############################################################################# ## #F ExponentVector_CPCS_FactorGU_p(pcgs_GU,g) ## InstallGlobalFunction( ExponentVector_CPCS_FactorGU_p , function( pcgs_GU, g ) local h,exp_h,k,l,exp_l,exp,test; # if G is abelian skip the I_p part if pcgs_GU.p=0 then k := g; exp_h := []; else # first we have to compute the part related to preImgs_I_p # compute the image in I_p h := g*One(GF(pcgs_GU.p)); exp_h := ExponentvectorPcgs_finite( pcgs_GU.pcgs_I_p, h ); if exp_h = fail then return fail; fi; # divide off to get the part of g which is in K_p k := POL_GetPartinK_P( g, exp_h, pcgs_GU.preImgsI_p ); # assert that k is in K_p Assert( 2, k*One( GF(pcgs_GU.p) ) = ( k*One(GF(pcgs_GU.p)) )^0, "Failure in ExponentVector_CPCS_FactorGU_p(pcgs_GU,g)\n"); fi; # now compute the image under nue l:= POL_InducedActionToSeries( [k], pcgs_GU.radicalSeries ); exp_l:=ExponentVector_AbelianSS( pcgs_GU.pcgs_nue_K_p, l ); if exp_l = fail then return fail; fi; # merge the exponents exp:=Concatenation(exp_h,exp_l); return exp; end ); ############################################################################# ## #F POL_GetPartinK_P(g,exp_h,preImgsI_p) ## InstallGlobalFunction( POL_GetPartinK_P, function( g, exp_h, preImgsI_p ) local k,i; # we know g*K_p = preImgsI_p^exp_h * K_p k := StructuralCopy(g); for i in ([1..Length(exp_h)]) do k := ( preImgsI_p[i]^-exp_h[i] ) * k; od; return k; end ); ############################################################################# ## #F RelativeOrders_CPCS_FactorGU_p( pcgs_GU ) ## InstallGlobalFunction( RelativeOrders_CPCS_FactorGU_p , function( pcgs_GU ) local relOrders_I_p,relOrders_nue_K_p,n,relOrders; relOrders_I_p := RelativeOrdersPcgs_finite( pcgs_GU.pcgs_I_p ); relOrders_nue_K_p := pcgs_GU.pcgs_nue_K_p.relOrders; # merge the relOrders relOrders := Concatenation(relOrders_I_p,relOrders_nue_K_p); return relOrders; end ); ############################################################################# ## #F POL_MergeCPCS( pcgs_U_p, pcgs_GU) ## InstallGlobalFunction( POL_MergeCPCS , function( pcgs_U_p, pcgs_GU ) local pcs,rels1,rels2,rels3,rels; pcs := Concatenation( pcgs_GU.pcs, pcgs_U_p.pcs ); rels1 := RelativeOrders_CPCS_FactorGU_p( pcgs_GU ); rels2 := pcgs_U_p.rels; rels:=Concatenation(rels1,rels2); return rec( pcgs_U_p := pcgs_U_p, pcgs_GU := pcgs_GU, pcs := pcs, rels := rels); end ); ############################################################################# ## #F ExponentVector_CPCS_PRMGroup( matrix, pcgs ) ## ## pcgs is the constructive pcs of a rational polycyclic matrix group ## InstallGlobalFunction( ExponentVector_CPCS_PRMGroup, function(matrix,pcgs) local exp1,m1,m2,exp2,exp; if matrix=matrix^0 then return List( pcgs.rels, x->0 );fi; # we have G = G/U * U, so matrix = m1 * m2 exp1 := ExponentVector_CPCS_FactorGU_p( pcgs.pcgs_GU, matrix); if exp1 = fail then return fail; fi; if Length( exp1 ) = 0 then #divide off nothing m2 := matrix; else m1 := Exp2Groupelement( pcgs.pcgs_GU.pcs, exp1 ); m2 := (m1^-1)*matrix; fi; exp2 := ExponentOfCPCS_Unipotent( m2, pcgs.pcgs_U_p ); if exp2 = fail then return fail; fi; exp := Concatenation( exp1, exp2); Assert( 2, Exp2Groupelement( pcgs.pcs, exp) = matrix, "error in ExponentVector_CPCS_PRMGroup"); return exp; end ); ############################################################################## ## #F POL_TestIsUnipotenByAbelianGroupByRadSeries( gens, radSers ) ## InstallGlobalFunction( POL_TestIsUnipotenByAbelianGroupByRadSeries, function( gens, radSers ) local ind,n,i,G; ind := POL_InducedActionToSeries( gens, radSers ); n := Length( ind ); for i in [1..n] do G := Group( ind[i] ); if not IsAbelian( G ) then return false; fi; od; return true; end ); ############################################################################# ## #E polenta-1.3.11/lib/info.gd000644 000766 000024 00000000605 14775712140 015554 0ustar00mhornstaff000000 000000 ############################################################################# ## #W info.gd POLENTA package Bjoern Assmann ## ## #Y 2003 ## ############################################################################# #I InfoClass ## DeclareInfoClass( "InfoPolenta" ); ############################################################################# ## #E polenta-1.3.11/lib/ispolyz.gd000644 000766 000024 00000000535 14775712140 016334 0ustar00mhornstaff000000 000000 ############################################################################# ## #W ispolyz.gd POLENTA package Bjoern Assmann ## ## ############################################################################# ## #M IsPolyInfiniteCyclicGroup( G ) ## ## DeclareOperation( "IsPolyInfiniteCyclicGroup", [ IsPcpGroup ] ); polenta-1.3.11/lib/subgroups.gd000644 000766 000024 00000002767 14775712140 016665 0ustar00mhornstaff000000 000000 ############################################################################# ## #W subgroups.gd POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## certain subgroups of matrix groups ## #Y 2004 ## ############################################################################# ## #F POL_TriangNSGFI_NonAbelianPRMGroup( arg ) ## ## arg[1] = G is an non-abelian polycyclic rational matrix group ## DeclareGlobalFunction( "POL_TriangNSGFI_NonAbelianPRMGroup" ); ############################################################################# ## #F POL_TriangNSGFI_PRMGroup( arg ) ## ## arg[1] = G is a rational polycyclic rational matrix group ## DeclareGlobalFunction( "POL_TriangNSGFI_PRMGroup" ); ############################################################################# ## #M TriangNormalSubgroupFiniteInd( G ) ## ## G is a matrix group over the Rationals. ## Returned is triangularizable normal subgroup of finite index ## #DeclareOperation( "TriangNormalSubgroupFiniteInd", [ IsMatrixGroup ] ); ############################################################################# ## #M SubgroupsUnipotentByAbelianByFinite( G ) ## ## G is a matrix group over the Rationals. ## Returned is triangularizable normal subgroup K of finite index ## and an unipotent normal subgroup U of K such that K/U is abelian. ## DeclareOperation( "SubgroupsUnipotentByAbelianByFinite" , [ IsMatrixGroup ] ); ############################################################################# ## #E polenta-1.3.11/lib/basic.gi000644 000766 000024 00000017056 14775712140 015717 0ustar00mhornstaff000000 000000 ############################################################################# ## #W basic.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## constructive pc-sequences for polycyclic rational matrix groups ## #Y 2003 ## ############################################################################# ## #F DetermineAdmissiblePrime(gensOfG) ## ## determines a prime number which does not divide the denominators ## of the entries of the matrices in gensOfG and which does not divide the ## the entries of the inverses of the matrices in gensOfG ## ## input is a list of generators of a rational polycyclic matrix group ## InstallGlobalFunction( DetermineAdmissiblePrime , function(gensOfG) local d,list1,list2,g,i,j,antiPrime,temp,temp2,p,found; d := Length( gensOfG[1] ); list1:=[]; list2:=[]; # construct a list of all elements in gensOfG and their inverses for g in gensOfG do Add(list1,g); Add(list1,g^-1); od; # write denominators of all matrix entries in list for g in list1 do for i in [1..d] do for j in [1..d] do Add(list2,DenominatorRat(g[i][j])); od; od; od; antiPrime:=ConsideredPrimes(list2); # choose a small prime which is not in antiPrime found:=false; p:=3; while not found do if not p in antiPrime then return p; fi; p:=NextPrimeInt(p); od; end ); ############################################################################# ## #F POL_NormalSubgroupGeneratorsOfK_p(pcgs,gensOfRealG) ## ## pcgs is a constructive pc-Sequence for I_p(G) ## (image of G under the p-congruence hom.). ## This function calculates normal subgroup generators for K_p(G) ## (the kernel of the p-congruence hom.) ## InstallGlobalFunction( POL_NormalSubgroupGeneratorsOfK_p , function( pcgs, gensOfRealG ) local g, relations, rightSide, leftSide, preimages, revPreimages, preimage, genList, ftl, n, ro, i, j, exp, conj, f_i, f_j, r_i, pcSeq; n := Length(pcgs.gens); preimages := []; relations := []; # catch the trivial case if Length(pcgs.gens)=0 then return gensOfRealG; fi; # calcuclate all preimages of pcgs.gens for i in [1..n] do preimage := SubsWord( pcgs.wordGens[i], gensOfRealG ); Add( preimages, preimage); od; # Attention: In pcgs.gens we have the pc-sequence in inverse order, # because we built up the structure bottom up pcSeq := StructuralCopy(Reversed(pcgs.gens)); revPreimages := StructuralCopy(Reversed(preimages)); # calculate the relative orders ro := RelativeOrdersPcgs_finite( pcgs ); # express the power relations in terms of gensOfRealG for i in [1..n] do f_i := pcSeq[i]; r_i := ro[i]; exp := ExponentvectorPcgs_finite( pcgs, f_i^r_i ); leftSide := revPreimages[i]^r_i; rightSide := Exp2Groupelement(revPreimages,exp); Add(relations,leftSide*(rightSide^-1)); od; # conjugation relations for i in [1..n] do for j in [1..(i-1)] do f_i := pcSeq[i]; f_j := pcSeq[j]; conj := (f_j^-1)*f_i*f_j; exp := ExponentvectorPcgs_finite( pcgs, conj); leftSide := (revPreimages[j]^-1)*revPreimages[i]*revPreimages[j]; rightSide := Exp2Groupelement(revPreimages,exp); Add( relations, leftSide*(rightSide^-1)); od; od; # Add some other relations, because we changed the generating # set of the image under the p-congruence hom. for i in [1..Length(pcgs.gensOfG)] do exp := ExponentvectorPcgs_finite( pcgs, pcgs.gensOfG[i]); rightSide := Exp2Groupelement( revPreimages, exp); leftSide := gensOfRealG[i]; Add( relations, leftSide*(rightSide^-1)); od; return relations; end ); ############################################################################# ## #F Exp2Groupelement(list,exp) ## InstallGlobalFunction( Exp2Groupelement, function(list,exp) local g,i; g:=list[1]^0; for i in [1..Length(list)] do g:=g*list[i]^exp[i]; od; return g; end ); ############################################################################# ## #F CopyMatrixList(list) ## InstallGlobalFunction( CopyMatrixList, function(list) local i,j,k,list2; list2:=[]; for i in [1..Length(list)] do Add(list2,[]); for j in [1..Length(list[i])] do Add(list2[i],[]); for k in [1..Length(list[i][j])] do Add(list2[i][j],[]); list2[i][j][k]:= list[i][j][k]; od; od; od; return list2; end ); ############################################################################# ## #F POL_CopyVectorList(list) ## InstallGlobalFunction( POL_CopyVectorList, function(list) local i,j,k,list2; list2:=[]; for i in [1..Length(list)] do Add(list2,[]); for j in [1..Length(list[i])] do Add(list2[i],[]); list2[i][j]:= list[i][j]; od; od; return list2; end ); ############################################################################# ## #F POL_NormalSubgroupGeneratorsU_p( pcgs_GU, gens, gens_K_p ) ## ## pcgs_GU is a constructive pc-Sequence for G/U, ## this function calculates normal subgroup generators for U_p(G) ## InstallGlobalFunction( POL_NormalSubgroupGeneratorsU_p , function( pcgs_GU, gens, gens_K_p ) local relations,rightSide,leftSide,preimages,revPreimages, preimage,genList,ftl,n,ro,i,j,exp,conj,f_i,f_j,r_i,pcs, g, k; # setup pcs := pcgs_GU.pcs; n:=Length(pcs); preimages:=[]; relations:=[]; k := Length( pcgs_GU.pcgs_I_p.gens ); # catch the trivial case (G/U trivial) if Length(pcgs_GU.pcs)=0 then return gens; fi; # catch the trivial case (U_p = 1) if Length(pcgs_GU.radicalSeries)=2 then return []; fi; # calculate the relative orders #ro:= RelativeOrdersPcgs( pcgs ); ro := RelativeOrders_CPCS_FactorGU_p( pcgs_GU ); # the elements stored in gens_K_p where found by evaluating # the pcp-relations of G/I_p. So we don't have to calculate them # again. for g in gens_K_p do exp := ExponentVector_CPCS_FactorGU_p( pcgs_GU, g ); leftSide := g; rightSide := Exp2Groupelement( pcs, exp ); Add( relations, leftSide*(rightSide^-1) ); od; # Express the power relations in terms of gens for i in [ (k+1)..n ] do f_i:=pcs[i]; r_i:=ro[i]; # we have to exclude the case r_i=0 because this means that # the order is equal to infinity if not r_i=0 then exp:=ExponentVector_CPCS_FactorGU_p(pcgs_GU,f_i^r_i); leftSide:=f_i^r_i; rightSide:=Exp2Groupelement(pcs,exp); Add( relations, leftSide*(rightSide^-1) ); fi; od; # conjugation relations for i in [ (k+1)..n ] do for j in [1..(i-1)] do f_i := pcs[i]; f_j := pcs[j]; conj := (f_j^-1)*f_i*f_j; exp := ExponentVector_CPCS_FactorGU_p( pcgs_GU, conj ); leftSide := (pcs[j]^-1)*pcs[i]*pcs[j]; rightSide := Exp2Groupelement(pcs,exp); Add( relations, leftSide*(rightSide^-1) ); od; od; relations := Filtered( relations,x -> not x=x^0 ); if Length( relations ) = 0 then relations[1] := gens[1]^0; fi; return relations; end ); ############################################################################# ## #E polenta-1.3.11/lib/solvable.gd000644 000766 000024 00000001626 14775712140 016434 0ustar00mhornstaff000000 000000 ############################################################################# ## #W solvalble.gi POLENTA package Bjoern Assmann ## ## Methods for testing if a matrix group ## is solvable or polycyclic ## #Y 2003 ## ############################################################################# ## #M IsPolycyclicMatGroup( G ) ## ## G is a matrix group, test whether it is polycyclic. ## ## TODO: Mark this as deprecated and eventually remove it; code using it ## should be changed to use IsPolycyclicGroup. ## DeclareOperation( "IsPolycyclicMatGroup", [ IsMatrixGroup ] ); ############################################################################# ## #M IsTriangularizableMatGroup( G ) ## ## G is a matrix group over the Rationals. ## DeclareProperty( "IsTriangularizableMatGroup", IsMatrixGroup ); ############################################################################# ## #E polenta-1.3.11/lib/series.gd000644 000766 000024 00000001124 14775712140 016110 0ustar00mhornstaff000000 000000 ############################################################################# ## #W series.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## radical series and homogeneous series of matrix groups ## #Y 2003 ## ############################################################################# ## #M RadicalSeriesSolvableMatGroup( G ) ## ## G is a matrix group over the Rationals ## ## DeclareOperation( "RadicalSeriesSolvableMatGroup", [ IsMatrixGroup ] ); ############################################################################# ## #E polenta-1.3.11/lib/semi.gi000644 000766 000024 00000017227 14775712140 015573 0ustar00mhornstaff000000 000000 ############################################################################# ## #W semi.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## constructive pc-sequences for rational abelian semisimple matrix groups ## #Y 2003 ## ############################################################################ ## #F CPCS_AbelianSSBlocks( gensOfBlockAction ) ## ## gensOfBlockAction is a list with the induced action of K_p to the ## to the factors of the homogeneous series of G ## CPCS_AbelianSSBlocks := function( gensOfBlockAction ) local normal,newGensOfBlockAction,i,rels,r2,freeGens,l,t, module,r,module2,k,full,nath,realFactor,trivial, F,relOrders; k:=Length(gensOfBlockAction[1]); full:=IdentityMat(k); # calculate the relations of the gensOfBlockAction module:=IdentityMat(k); for r in gensOfBlockAction do # trivial case: we check if r contains just 1's trivial:=true; for i in [1..Length(r)] do if not r[i]=r[i]^0 then trivial:=false; break; fi; od; if not trivial then F := FieldByMatricesNC( r ); if F = false then return fail; fi; r2 := RelationLattice( F, r ); module:=LatticeIntersection(module,r2); fi; od; # let k be the number of gens = Length(gensOfBlockAction[1]) # compute a basis for Z^k/module # with this vectors we can calculate free gens # trivial check if Length( module ) = 0 then return rec( gensOfBlockAction := gensOfBlockAction, newGensOfBlockAction := gensOfBlockAction, trsf := IdentityMat(k), rels := module, relOrders := List( [1..k] , x-> 0 ) ); fi; realFactor := GeneratorLattice( module ); relOrders := realFactor.relord; realFactor := realFactor.exps; # calculate the new free generators blockwise newGensOfBlockAction:=[]; for i in [1..Length(gensOfBlockAction)] do newGensOfBlockAction[i]:=[]; for t in realFactor do Add( newGensOfBlockAction[i], Exp2Groupelement(gensOfBlockAction[i],t)); od; od; return rec( gensOfBlockAction := gensOfBlockAction, newGensOfBlockAction := newGensOfBlockAction, trsf := realFactor, rels := module, relOrders := relOrders); end; ############################################################################# ## #F POL_TestExponentVector_AbelianSS( CPCS_nue_K_p, g, exp ) ## POL_TestExponentVector_AbelianSS := function( CPCS_nue_K_p, g, exp ) local newGens, n, i, test; newGens := CPCS_nue_K_p.newGensOfBlockAction; # n is the number of blocks n:=Length(newGens); for i in [1..n] do test := MappedVector( exp, newGens[i]) = g[i][1]; if test = false then return false; fi; od; return true; end; ############################################################################# ## #F ExponentVector_AbelianSS( CPCS_nue_K_p, g ) ## ## g is a list which entries contain the induced action of an group ## element to the blocks of the factor series ## ExponentVector_AbelianSS:=function( CPCS_nue_K_p, g ) local trivial,freeGens,n,A,m,rels3,v,exp,i,rels,r2,F, rels2,r,newGens,a,ll; # check if nue_K_p is trivial if Length( CPCS_nue_K_p.relOrders )=0 then return []; fi; # check if g is trivial n := Length( g ); trivial := ForAll([1..n], i -> g[i][1] = g[i][1]^0); # if the action of g on the radical series is trivial we # return the exponent vector [0 ... 0] of the length of the # pc sequence of nue(K_p) if trivial then ll := Length( CPCS_nue_K_p.relOrders ); return ListWithIdenticalEntries( ll, 0 ); fi; newGens := CPCS_nue_K_p.newGensOfBlockAction; # n is the number of blocks n := Length(newGens); # A contains an extended genslist, i.e. the newGens plus the # element, for which we want to compute the exp A := []; for i in [1..n] do a := StructuralCopy(newGens[i]); a := Concatenation( [g[i][1]], a ); Add(A, a); od; # compute the relations of A rels := IdentityMat(n+1); for r in A do F := FieldByMatricesNC( r ); if F = false then return fail; fi; r2 := RelationLattice( F, r ); rels := LatticeIntersection(rels, r2); od; rels := NormalFormIntMat(rels,0).normal; if not rels[1][1]=1 then return fail; fi; exp := -rels[1]; exp[1] := 0; # Reduce exp by the remaining rows for r in rels do i := PositionNonZero(r); if exp[i] < 0 then exp := exp + QuoInt(-exp[i]+r[i]-1, r[i]) * r; elif exp[i] >= r[i] then exp := exp - QuoInt(exp[i], r[i]) * r; fi; od; # Remove the leading zero Remove(exp, 1); Assert( 2, POL_TestExponentVector_AbelianSS( CPCS_nue_K_p, g, exp ), "failure in ExponentVector_AbelianSS" ); return exp; end; ############################################################################# ## #F Membership_AbelianSS(CPCS_nue_K_p,g) ## ## g is a list which entries contains the induced action to a block ## Membership_AbelianSS:=function(CPCS_nue_K_p,g) local exp; exp := ExponentVector_AbelianSS( CPCS_nue_K_p, g ); if not IsBool( exp ) then return true; else return false; fi; end; ############################################################################# ## #F CPCS_AbelianSSBlocks_ClosedUnderConj(gens_K_p,gens,radicalSeries) ## CPCS_AbelianSSBlocks_ClosedUnderConj := function(gens_K_p,gens,radicalSeries) local list,gensOfBlockAction,CPCS_nue_K_p,g,h,test,l,gens_K_p2,i; #setup gensOfBlockAction :=POL_InducedActionToSeries( gens_K_p, radicalSeries ); CPCS_nue_K_p:=CPCS_AbelianSSBlocks( gensOfBlockAction ); if CPCS_nue_K_p = fail then return fail; fi; i := 1; # test if CPCS_nue_K_p is not trivial if Length( CPCS_nue_K_p.relOrders ) > 0 then #test if the CPCS for the image is closed under conjugation Info( InfoPolenta, 1, "Close the constructive polycyclic sequence \n", " computed with the normal subgroup generators of the kernel\n", " under the conjugation action of the whole group"); for g in gens_K_p do for h in gens do l := POL_InducedActionToSeries( [g^h], radicalSeries ); if InfoLevel( InfoPolenta ) >= 1 then Print( "." ); fi; test := Membership_AbelianSS( CPCS_nue_K_p, l ); if not test then Info( InfoPolenta, 3, "Extending gens_K_p !\n"); Add(gens_K_p,g^h); #now in gens_K_p we have a more complete list of #the generators. #don't forget to modify gens_K_p as well on a #higher function level gensOfBlockAction := POL_InducedActionToSeries(gens_K_p,radicalSeries); CPCS_nue_K_p := CPCS_AbelianSSBlocks( gensOfBlockAction ); if CPCS_nue_K_p = fail then return fail; fi; fi; i := i+1; od; od; if InfoLevel( InfoPolenta ) >= 1 then Print( "\n" ); fi; fi; Info( InfoPolenta, 3, "loops inCPCS_AbelianSSBlocks_ClosedUnderConj = ", Length(gens_K_p)*Length(gens),"\n"); return rec( pcgs_nue_K_p := CPCS_nue_K_p, gens_K_p := gens_K_p); end; ############################################################################# ## #E polenta-1.3.11/lib/jordan.gi000644 000766 000024 00000012560 14775712140 016106 0ustar00mhornstaff000000 000000 ############################################################################# ## #W jordan.gi POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## the multiplicative jordan decomposition. ## #Y 2003 ## ## ## WARNING: the code in this file is not currently used, and ## in fact is not loaded by default. ## ## IN: matrix g. ## OUT:: g_s, g_u. ## ## Maybe later: Install a method for this. ## POL_MultiplicativeJordanDecomposition := function( g ) local ll, semi, uni; # get semisimple part via the additive jordan decomposition ll := JordanDecomposition( g ); semi := ll[1]; # get unipotent part uni := semi^-1 * g; # do some tests if not Comm( semi, uni ) = semi^0 then Error( "don't commute" ); fi; return [ semi, uni ]; end; # get some exams # gens := POL_AbelianIrreducibleGens( 2 ); # if false then n_blocks := 2; n_gens := 2; gens := POL_TriangularizableGens( n_blocks, n_gens ); mat := [ [ 6, 8, 6, -11, 1/2, 0, 0, 0 ], [ -7, -9, -8, 11, 0, 0, 1/2, 0 ], [ -6, -9, -7, 11, 0, 0, 1/2, 0 ], [ -3, -4, -4, 4, 0, 1/2, 0, 0 ], [ 0, 0, 0, 0, -23, -34, -26, 44 ], [ 0, 0, 0, 0, 36, 53, 42, -66 ], [ 0, 0, 0, 0, 36, 52, 41, -66 ], [ 0, 0, 0, 0, 22, 32, 26, -39 ] ]; x := Indeterminate(Rationals,"x": old ); pol := x^2+1; pol := x^3+2*x+2; pol := x^3-x +7; pol := x^2 + 1/2; mat := CompanionMat( pol ); mat2 := mat * One( F ); F := AlgebraicExtension( Rationals, pol ); pol2 := AlgExtEmbeddedPol(F,pol); Factors( pol2 ); #or use FactorsPolynomialAlgExt( F, pol ); a := RootOfDefiningPolynomial( F ); id := IdentityMat( 2, F ); NullspaceIntMat( mat2 - a*id ); fi; ## IN: args[1]=mat ..................... semisimple rational matrix. ## args[2]=pol ..................... minimal or char polynomial of ## mat. (optional parameter) ## Comment: Several strategies are possible. ## We could first compute a homogeneous series for the ## -module Q^d and then diagonalize these. ## ## For the moment we do it in an easier way. ## Compute an extension field that contains all roots ## of the (possible non-irreducible) minimal polynomial of mat. ## ## We probably need that field anyway later when we use ## it for symbolic collection. ## POL_DiagonalizeMat := function( args ) local pol, F, factors, eigen_values, eigen_spaces, id, space, T, e,fil,mat; # setup mat := args[1]; if Length( args ) = 2 then pol := args[2]; else pol := CharacteristicPolynomial( Rationals, Rationals, mat ); fi; # compute the extension field of the rationals that contains # all eigenvalues of mat. # SplittingField over the rationals requires the radiroot GAP package! F := SplittingField( pol ); factors := FactorsPolynomialAlgExt( F, pol ); # check whether all factors have degree one fil := Filtered( factors, x->Degree(x) > 1 ); if Length( fil ) > 0 then Error( "There are non-linear factors" ); fi; # get Eigen values eigen_values := List( factors, f-> -1*Value(f,0) ); # compute the according eigenspaces eigen_spaces := []; id := mat^0; for e in eigen_values do space := NullspaceMat( mat - e*id ); Add( eigen_spaces, space ); od; # get base change matrix from eigen vector basis to standard basis # T*mat*T^-1 is in diagonal form T := Concatenation( eigen_spaces ); # attach info to matrix # ? return rec( diagonalmat := T*mat*T^-1, eigen_values := eigen_values, eigen_spaces := eigen_spaces, baseChange := T, splitField := F ); end; POL_AlgebraBase := function( mats ) local base, flat; if Length( mats ) = 0 then return []; fi; flat := List( mats, Flat ); base := SpinnUpEchelonBase( [], flat, mats, OnMatVector); return base; end; if false then mat1 := [ [ 0, 0, -2 ], [ 1, 0, -2 ], [ 0, 1, 0 ] ]; mat2 := 2* mat1; mats := [mat1,mat2]; fi; ## IN mats ............. semisimple and commuting matrices over Q ## POL_DiagonalizeMatsSimultaneously := function( mats ) local basis, g_rec, g, pol, diag_rec, T, Tinv, primitiveElm; # get primitive element g for the Q-algebra Q[mats] basis := POL_AlgebraBase( mats ); g_rec := PrimitiveAlgebraElement( mats, basis ); g := g_rec.elem; pol := g_rec.poly; # diagonalize this element g diag_rec := POL_DiagonalizeMat( [g, pol] ); T := diag_rec.baseChange; Tinv := T^-1; # return list of diagonalized matrices, # and full information for T. return rec( diagonalmats := List( mats, x->T*x*Tinv ), basis := basis, primitiveElm := g, pol := pol, diag_rec := diag_rec, T := T, Tinv := Tinv ); end; ## IN: Triangularizable group G = ## OUT: attached to each gi the decomposition. ## the all should use the same base change (that is coming ## from the same radical series. ## Attach to G the radical series all other meta information that you ## to decompose. ## Then you should have a second function that does ## the decomposition for an arbitrary element. ## ############################################################################# ## #E polenta-1.3.11/lib/finite.gd000644 000766 000024 00000006724 14775712140 016107 0ustar00mhornstaff000000 000000 ############################################################################# ## #W finite.gd POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## constructive pc-sequences for finite matrix groups ## #Y 2003 ## ############################################################################# ## #F ClosureBasePcgs_word(pcgsN, g, gens, lim) ## ## Calculates a conPCS for ^gens ## ## Every arising group element is realized as a record ## containing the real element ## and the wordinformation corresponding to gens ## DeclareGlobalFunction( "ClosureBasePcgs_word" ); ############################################################################# ## #F POL_Comm( g, h )..................... calculates the Comm for records of ## group elements with word information ## DeclareGlobalFunction( "POL_Comm" ); ############################################################################# ## #F CPCS_finite_word( gensOfG , b) ## ## Returns a constructive polycyclic sequence for G if G is polycyclic ## of derived length at most b and it returns fail if G is not ## polycyclic ## ## Every generator is a record which contains in ## .groupElement the group element and in ## .word the wordinformation corresponding to the gensOfG list ## This feature is important if gensOfG arise as the image under ## the p-congruence homomorphism. ## ## DeclareGlobalFunction( "CPCS_finite_word" ); ############################################################################# ## #F CPCS_FinitePart(gens)........... constructive pc-sequ. for image of ## under the p-congr. hom. ## DeclareGlobalFunction( "CPCS_FinitePart" ); ############################################################################# ## #F POL_InverseWord(word) ## ## DeclareGlobalFunction( "POL_InverseWord" ); ############################################################################# ## #F ExtendedBasePcgsMod( pcgs, g, d ) . . . . . .. . . . . extend a base pcgs ## ## g normalizes and we compute a new pcgs for . ## DeclareGlobalFunction( "ExtendedBasePcgsMod" ); ############################################################################# ## #F RelativeOrdersPcgs_finite( pcgs ) ## DeclareGlobalFunction( "RelativeOrdersPcgs_finite" ); ############################################################################# ## #F ExponentvectorPcgs_finite( pcgs, g ) ## DeclareGlobalFunction( "ExponentvectorPcgs_finite" ); ############################################################################# ## #F ExponentvectorPartPcgs( pcgs, g , index) ## ## g = ...* pcgs.gens[index]^ExponentvectorPartPcgs * ... ## DeclareGlobalFunction( "ExponentvectorPartPcgs" ); ############################################################################# ## #F ExtractIndexPart( word, index) ## DeclareGlobalFunction( "ExtractIndexPart" ); ############################################################################# ## #F POL_SetPcPresentation(pcgs) ## ## pcgs is a constructive pc-sequence, calculated ## by ConstructivePcSequenceFinitePart ## this function calculates a PcPresentation for the Group described ## by pcgs ## DeclareGlobalFunction( "POL_SetPcPresentation" ); ############################################################################# ## #F POL_TestExpVector_finite( pcgs, g ) ## DeclareGlobalFunction( "POL_TestExpVector_finite" ); ############################################################################# ## #E polenta-1.3.11/lib/present.gd000644 000766 000024 00000001260 14775712140 016277 0ustar00mhornstaff000000 000000 ############################################################################# ## #W present.gd POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## pcp-presentations for matrix groups ## #Y 2003 ## ############################################################################# ## #O PcpGroupByMatGroup( G ) ## DeclareOperation( "PcpGroupByMatGroup", [ IsMatrixGroup ] ); DeclareProperty( "IsIsomorphismByFinitePolycyclicMatrixGroup", IsMapping); DeclareProperty( "IsIsomorphismByPolycyclicMatrixGroup", IsMapping); ############################################################################# ## #E polenta-1.3.11/lib/cpcs.gd000644 000766 000024 00000006375 14775712140 015563 0ustar00mhornstaff000000 000000 ############################################################################# ## #W cpcs.gd POLENTA package Bjoern Assmann ## ## Methods for the calculation of ## constructive pc-sequences for rational matrix groups ## #Y 2003 ## ############################################################################# ## #F CPCS_PRMGroup( arg ) ## ## arg[1]=G is a rational polycyclic rational matrix group ## DeclareGlobalFunction( "CPCS_PRMGroup" ); ############################################################################# ## #F CPCS_NonAbelianPRMGroup( arg ) ## ## arg[1]=G is an non-abelian rational polycyclic rational matrix group ## DeclareGlobalFunction( "CPCS_NonAbelianPRMGroup" ); ############################################################################# ## #F CPCS_AbelianPRMGroup( G ) ## ## G is an abelian polycyclic rational matrix group ## DeclareGlobalFunction( "CPCS_AbelianPRMGroup" ); ############################################################################# ## #F CPCS_FactorGU_p( gens, pcgs_I_p, gens_K_p, pcgs_nue_K_p, radicalSeries,p) ## ## calculates a constructive pcs for the G/U_p(G) ## DeclareGlobalFunction( "CPCS_FactorGU_p" ); ############################################################################# ## #F POL_PreImagesPcsNueK_p_G( gens_K_p, pcgs_nue_K_p ) ## DeclareGlobalFunction( "POL_PreImagesPcsNueK_p_G" ); ############################################################################# ## #F POL_PreImagesPcsI_p_G( pcgs_I_p, gens ) ## DeclareGlobalFunction( "POL_PreImagesPcsI_p_G" ); ############################################################################# ## #F TestPOL_PreImagesPcsI_p_G( preImgsI_p, p, pcgs_I_p ); ## DeclareGlobalFunction( "TestPOL_PreImagesPcsI_p_G" ); ############################################################################# ## #F ExponentVector_CPCS_FactorGU_p(pcgs_GU,g) ## DeclareGlobalFunction( "ExponentVector_CPCS_FactorGU_p" ); ############################################################################# ## #F POL_GetPartinK_P(g,exp_h,preImgsI_p) ## DeclareGlobalFunction( "POL_GetPartinK_P" ); ############################################################################# ## #F RelativeOrders_CPCS_FactorGU_p( pcgs_GU ) ## DeclareGlobalFunction( "RelativeOrders_CPCS_FactorGU_p" ); ############################################################################# ## #F POL_MergeCPCS( pcgs_U_p, pcgs_GU) ## DeclareGlobalFunction( "POL_MergeCPCS" ); ############################################################################# ## #F ExponentVector_CPCS_PRMGroup( matrix, pcgs ) ## ## pcgs is the constructive pcs of a rational polycyclic matrix group ## DeclareGlobalFunction( "ExponentVector_CPCS_PRMGroup" ); ############################################################################## ## #F POL_TestIsUnipotenByAbelianGroupByRadSeries( gens, radSers ) ## DeclareGlobalFunction( "POL_TestIsUnipotenByAbelianGroupByRadSeries" ); ############################################################################# ## #F CPCS_UnipotentByAbelianByRadSeries( gens, recordSeries ) ## ## G is an abelian rational polycyclic rational matrix group ## DeclareGlobalFunction( "CPCS_UnipotentByAbelianGroupByRadSeries" ); ############################################################################# ## #E