passagemath-gap-pkg-semigroups 10.6.30__cp311-cp311-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-gap-pkg-semigroups might be problematic. Click here for more details.
- gap/pkg/semigroups/CHANGELOG.md +1699 -0
- gap/pkg/semigroups/CONTRIBUTING.md +91 -0
- gap/pkg/semigroups/GNUmakefile +110 -0
- gap/pkg/semigroups/GNUmakefile.in +110 -0
- gap/pkg/semigroups/GPL +674 -0
- gap/pkg/semigroups/LICENSE +16 -0
- gap/pkg/semigroups/Makefile +26 -0
- gap/pkg/semigroups/Makefile.gappkg +225 -0
- gap/pkg/semigroups/PackageInfo.g +529 -0
- gap/pkg/semigroups/README.md +102 -0
- gap/pkg/semigroups/VERSIONS +112 -0
- gap/pkg/semigroups/aclocal.m4 +375 -0
- gap/pkg/semigroups/autogen.sh +25 -0
- gap/pkg/semigroups/bin/aarch64-apple-darwin23-default64-kv10/semigroups.so +0 -0
- gap/pkg/semigroups/config.guess +1807 -0
- gap/pkg/semigroups/config.log +1158 -0
- gap/pkg/semigroups/config.status +1131 -0
- gap/pkg/semigroups/config.sub +1960 -0
- gap/pkg/semigroups/configure +9742 -0
- gap/pkg/semigroups/configure.ac +71 -0
- gap/pkg/semigroups/data/doc/greens.pickle +1 -0
- gap/pkg/semigroups/data/gens/fullbool-8.pickle.gz +0 -0
- gap/pkg/semigroups/data/gens/fullbool.pickle.gz +0 -0
- gap/pkg/semigroups/data/gens/hall.pickle.gz +0 -0
- gap/pkg/semigroups/data/gens/reflex-6.pickle.gz +0 -0
- gap/pkg/semigroups/data/gens/reflex.pickle.gz +0 -0
- gap/pkg/semigroups/data/tst/bipart4 +10 -0
- gap/pkg/semigroups/data/tst/pperm10 +1 -0
- gap/pkg/semigroups/data/tst/tables.gz +0 -0
- gap/pkg/semigroups/data/tst/testdata +1 -0
- gap/pkg/semigroups/data/tst/testinstall.pickle +1 -0
- gap/pkg/semigroups/data/tst/trans3 +7 -0
- gap/pkg/semigroups/data/tst/trans3-old +7 -0
- gap/pkg/semigroups/environment.yml +7 -0
- gap/pkg/semigroups/gap/attributes/acting.gd +15 -0
- gap/pkg/semigroups/gap/attributes/acting.gi +297 -0
- gap/pkg/semigroups/gap/attributes/attr.gd +91 -0
- gap/pkg/semigroups/gap/attributes/attr.gi +1214 -0
- gap/pkg/semigroups/gap/attributes/dual.gd +25 -0
- gap/pkg/semigroups/gap/attributes/dual.gi +209 -0
- gap/pkg/semigroups/gap/attributes/factor.gd +17 -0
- gap/pkg/semigroups/gap/attributes/factor.gi +453 -0
- gap/pkg/semigroups/gap/attributes/homomorph.gd +84 -0
- gap/pkg/semigroups/gap/attributes/homomorph.gi +591 -0
- gap/pkg/semigroups/gap/attributes/inverse.gd +38 -0
- gap/pkg/semigroups/gap/attributes/inverse.gi +708 -0
- gap/pkg/semigroups/gap/attributes/isomorph.gd +16 -0
- gap/pkg/semigroups/gap/attributes/isomorph.gi +377 -0
- gap/pkg/semigroups/gap/attributes/isorms.gd +49 -0
- gap/pkg/semigroups/gap/attributes/isorms.gi +1383 -0
- gap/pkg/semigroups/gap/attributes/maximal.gd +16 -0
- gap/pkg/semigroups/gap/attributes/maximal.gi +1876 -0
- gap/pkg/semigroups/gap/attributes/properties.gd +109 -0
- gap/pkg/semigroups/gap/attributes/properties.gi +1658 -0
- gap/pkg/semigroups/gap/attributes/rms-translat.gd +39 -0
- gap/pkg/semigroups/gap/attributes/rms-translat.gi +1078 -0
- gap/pkg/semigroups/gap/attributes/semifp.gd +12 -0
- gap/pkg/semigroups/gap/attributes/semifp.gi +84 -0
- gap/pkg/semigroups/gap/attributes/translat.gd +474 -0
- gap/pkg/semigroups/gap/attributes/translat.gi +1779 -0
- gap/pkg/semigroups/gap/congruences/cong.gd +154 -0
- gap/pkg/semigroups/gap/congruences/cong.gi +351 -0
- gap/pkg/semigroups/gap/congruences/conginv.gd +38 -0
- gap/pkg/semigroups/gap/congruences/conginv.gi +589 -0
- gap/pkg/semigroups/gap/congruences/conglatt.gd +101 -0
- gap/pkg/semigroups/gap/congruences/conglatt.gi +886 -0
- gap/pkg/semigroups/gap/congruences/congpairs.gd +21 -0
- gap/pkg/semigroups/gap/congruences/congpairs.gi +272 -0
- gap/pkg/semigroups/gap/congruences/congpart.gd +90 -0
- gap/pkg/semigroups/gap/congruences/congpart.gi +449 -0
- gap/pkg/semigroups/gap/congruences/congrees.gd +20 -0
- gap/pkg/semigroups/gap/congruences/congrees.gi +313 -0
- gap/pkg/semigroups/gap/congruences/congrms.gd +54 -0
- gap/pkg/semigroups/gap/congruences/congrms.gi +1467 -0
- gap/pkg/semigroups/gap/congruences/congsemigraph.gd +28 -0
- gap/pkg/semigroups/gap/congruences/congsemigraph.gi +289 -0
- gap/pkg/semigroups/gap/congruences/congsimple.gd +27 -0
- gap/pkg/semigroups/gap/congruences/congsimple.gi +236 -0
- gap/pkg/semigroups/gap/congruences/conguniv.gd +20 -0
- gap/pkg/semigroups/gap/congruences/conguniv.gi +271 -0
- gap/pkg/semigroups/gap/congruences/congwordgraph.gd +21 -0
- gap/pkg/semigroups/gap/congruences/congwordgraph.gi +250 -0
- gap/pkg/semigroups/gap/elements/bipart.gd +71 -0
- gap/pkg/semigroups/gap/elements/bipart.gi +995 -0
- gap/pkg/semigroups/gap/elements/blocks.gd +31 -0
- gap/pkg/semigroups/gap/elements/blocks.gi +134 -0
- gap/pkg/semigroups/gap/elements/boolmat.gd +74 -0
- gap/pkg/semigroups/gap/elements/boolmat.gi +726 -0
- gap/pkg/semigroups/gap/elements/elements.gd +11 -0
- gap/pkg/semigroups/gap/elements/elements.gi +121 -0
- gap/pkg/semigroups/gap/elements/ffmat.gd +71 -0
- gap/pkg/semigroups/gap/elements/ffmat.gi +311 -0
- gap/pkg/semigroups/gap/elements/maxplusmat.gd +131 -0
- gap/pkg/semigroups/gap/elements/maxplusmat.gi +782 -0
- gap/pkg/semigroups/gap/elements/pbr.gd +51 -0
- gap/pkg/semigroups/gap/elements/pbr.gi +740 -0
- gap/pkg/semigroups/gap/elements/pperm.gd +11 -0
- gap/pkg/semigroups/gap/elements/pperm.gi +14 -0
- gap/pkg/semigroups/gap/elements/semiringmat.gd +136 -0
- gap/pkg/semigroups/gap/elements/semiringmat.gi +717 -0
- gap/pkg/semigroups/gap/elements/star.gd +21 -0
- gap/pkg/semigroups/gap/elements/star.gi +21 -0
- gap/pkg/semigroups/gap/elements/trans.gd +13 -0
- gap/pkg/semigroups/gap/elements/trans.gi +50 -0
- gap/pkg/semigroups/gap/fp/freeband.gd +22 -0
- gap/pkg/semigroups/gap/fp/freeband.gi +502 -0
- gap/pkg/semigroups/gap/fp/freeinverse.gd +30 -0
- gap/pkg/semigroups/gap/fp/freeinverse.gi +465 -0
- gap/pkg/semigroups/gap/fp/tietze.gd +89 -0
- gap/pkg/semigroups/gap/fp/tietze.gi +1578 -0
- gap/pkg/semigroups/gap/fp/word.gd +15 -0
- gap/pkg/semigroups/gap/fp/word.gi +67 -0
- gap/pkg/semigroups/gap/greens/acting-inverse.gi +774 -0
- gap/pkg/semigroups/gap/greens/acting-regular.gi +553 -0
- gap/pkg/semigroups/gap/greens/acting.gd +81 -0
- gap/pkg/semigroups/gap/greens/acting.gi +2433 -0
- gap/pkg/semigroups/gap/greens/froidure-pin.gd +25 -0
- gap/pkg/semigroups/gap/greens/froidure-pin.gi +741 -0
- gap/pkg/semigroups/gap/greens/generic.gd +117 -0
- gap/pkg/semigroups/gap/greens/generic.gi +630 -0
- gap/pkg/semigroups/gap/ideals/acting.gd +17 -0
- gap/pkg/semigroups/gap/ideals/acting.gi +1155 -0
- gap/pkg/semigroups/gap/ideals/froidure-pin.gd +11 -0
- gap/pkg/semigroups/gap/ideals/froidure-pin.gi +105 -0
- gap/pkg/semigroups/gap/ideals/ideals.gd +45 -0
- gap/pkg/semigroups/gap/ideals/ideals.gi +442 -0
- gap/pkg/semigroups/gap/ideals/lambda-rho.gd +16 -0
- gap/pkg/semigroups/gap/ideals/lambda-rho.gi +614 -0
- gap/pkg/semigroups/gap/libsemigroups/cong.gd +24 -0
- gap/pkg/semigroups/gap/libsemigroups/cong.gi +431 -0
- gap/pkg/semigroups/gap/libsemigroups/fpsemi.gd +16 -0
- gap/pkg/semigroups/gap/libsemigroups/fpsemi.gi +53 -0
- gap/pkg/semigroups/gap/libsemigroups/froidure-pin.gd +17 -0
- gap/pkg/semigroups/gap/libsemigroups/froidure-pin.gi +945 -0
- gap/pkg/semigroups/gap/libsemigroups/sims1.gd +38 -0
- gap/pkg/semigroups/gap/libsemigroups/sims1.gi +308 -0
- gap/pkg/semigroups/gap/main/acting.gd +36 -0
- gap/pkg/semigroups/gap/main/acting.gi +779 -0
- gap/pkg/semigroups/gap/main/froidure-pin.gd +72 -0
- gap/pkg/semigroups/gap/main/froidure-pin.gi +655 -0
- gap/pkg/semigroups/gap/main/graded.gd +26 -0
- gap/pkg/semigroups/gap/main/graded.gi +355 -0
- gap/pkg/semigroups/gap/main/lambda-rho.gd +29 -0
- gap/pkg/semigroups/gap/main/lambda-rho.gi +514 -0
- gap/pkg/semigroups/gap/main/orbits.gd +24 -0
- gap/pkg/semigroups/gap/main/orbits.gi +512 -0
- gap/pkg/semigroups/gap/main/semiact.gd +20 -0
- gap/pkg/semigroups/gap/main/semiact.gi +821 -0
- gap/pkg/semigroups/gap/main/setup.gd +61 -0
- gap/pkg/semigroups/gap/main/setup.gi +1094 -0
- gap/pkg/semigroups/gap/obsolete.gd +9 -0
- gap/pkg/semigroups/gap/obsolete.gi +14 -0
- gap/pkg/semigroups/gap/options.g +55 -0
- gap/pkg/semigroups/gap/semigroups/grpperm.gd +12 -0
- gap/pkg/semigroups/gap/semigroups/grpperm.gi +177 -0
- gap/pkg/semigroups/gap/semigroups/semibipart.gd +28 -0
- gap/pkg/semigroups/gap/semigroups/semibipart.gi +570 -0
- gap/pkg/semigroups/gap/semigroups/semiboolmat.gd +20 -0
- gap/pkg/semigroups/gap/semigroups/semiboolmat.gi +104 -0
- gap/pkg/semigroups/gap/semigroups/semicons.gd +52 -0
- gap/pkg/semigroups/gap/semigroups/semicons.gi +1194 -0
- gap/pkg/semigroups/gap/semigroups/semidp.gd +13 -0
- gap/pkg/semigroups/gap/semigroups/semidp.gi +509 -0
- gap/pkg/semigroups/gap/semigroups/semieunit.gd +126 -0
- gap/pkg/semigroups/gap/semigroups/semieunit.gi +889 -0
- gap/pkg/semigroups/gap/semigroups/semiex.gd +104 -0
- gap/pkg/semigroups/gap/semigroups/semiex.gi +1590 -0
- gap/pkg/semigroups/gap/semigroups/semiffmat.gd +37 -0
- gap/pkg/semigroups/gap/semigroups/semiffmat.gi +565 -0
- gap/pkg/semigroups/gap/semigroups/semifp.gd +28 -0
- gap/pkg/semigroups/gap/semigroups/semifp.gi +1364 -0
- gap/pkg/semigroups/gap/semigroups/semigraph.gd +40 -0
- gap/pkg/semigroups/gap/semigroups/semigraph.gi +292 -0
- gap/pkg/semigroups/gap/semigroups/semigrp.gd +165 -0
- gap/pkg/semigroups/gap/semigroups/semigrp.gi +1225 -0
- gap/pkg/semigroups/gap/semigroups/semimaxplus.gd +72 -0
- gap/pkg/semigroups/gap/semigroups/semimaxplus.gi +710 -0
- gap/pkg/semigroups/gap/semigroups/semintmat.gd +13 -0
- gap/pkg/semigroups/gap/semigroups/semintmat.gi +74 -0
- gap/pkg/semigroups/gap/semigroups/semipbr.gd +19 -0
- gap/pkg/semigroups/gap/semigroups/semipbr.gi +139 -0
- gap/pkg/semigroups/gap/semigroups/semipperm.gd +27 -0
- gap/pkg/semigroups/gap/semigroups/semipperm.gi +711 -0
- gap/pkg/semigroups/gap/semigroups/semiquo.gd +14 -0
- gap/pkg/semigroups/gap/semigroups/semiquo.gi +97 -0
- gap/pkg/semigroups/gap/semigroups/semiringmat.gd +16 -0
- gap/pkg/semigroups/gap/semigroups/semiringmat.gi +21 -0
- gap/pkg/semigroups/gap/semigroups/semirms.gd +19 -0
- gap/pkg/semigroups/gap/semigroups/semirms.gi +977 -0
- gap/pkg/semigroups/gap/semigroups/semitrans.gd +49 -0
- gap/pkg/semigroups/gap/semigroups/semitrans.gi +909 -0
- gap/pkg/semigroups/gap/tools/display.gd +24 -0
- gap/pkg/semigroups/gap/tools/display.gi +749 -0
- gap/pkg/semigroups/gap/tools/io.gd +17 -0
- gap/pkg/semigroups/gap/tools/io.gi +543 -0
- gap/pkg/semigroups/gap/tools/iterators.gd +16 -0
- gap/pkg/semigroups/gap/tools/iterators.gi +253 -0
- gap/pkg/semigroups/gap/tools/utils.gd +19 -0
- gap/pkg/semigroups/gap/tools/utils.gi +756 -0
- gap/pkg/semigroups/gapbind14/.ccls +18 -0
- gap/pkg/semigroups/gapbind14/.clang-format +104 -0
- gap/pkg/semigroups/gapbind14/CPPLINT.cfg +5 -0
- gap/pkg/semigroups/gapbind14/LICENSE +674 -0
- gap/pkg/semigroups/gapbind14/README.md +76 -0
- gap/pkg/semigroups/gapbind14/demo/.gitignore +4 -0
- gap/pkg/semigroups/gapbind14/demo/LICENSE +293 -0
- gap/pkg/semigroups/gapbind14/demo/Makefile.gappkg +220 -0
- gap/pkg/semigroups/gapbind14/demo/Makefile.in +19 -0
- gap/pkg/semigroups/gapbind14/demo/PackageInfo.g +87 -0
- gap/pkg/semigroups/gapbind14/demo/README.md +17 -0
- gap/pkg/semigroups/gapbind14/demo/configure +34 -0
- gap/pkg/semigroups/gapbind14/demo/gap/gapbind_demo.gd +19 -0
- gap/pkg/semigroups/gapbind14/demo/gap/gapbind_demo.gi +10 -0
- gap/pkg/semigroups/gapbind14/demo/init.g +16 -0
- gap/pkg/semigroups/gapbind14/demo/makedoc.g +10 -0
- gap/pkg/semigroups/gapbind14/demo/read.g +6 -0
- gap/pkg/semigroups/gapbind14/demo/src/gapbind_demo.cc +142 -0
- gap/pkg/semigroups/gapbind14/demo/tst/testall.g +12 -0
- gap/pkg/semigroups/gapbind14/include/gapbind14/cpp_fn.hpp +223 -0
- gap/pkg/semigroups/gapbind14/include/gapbind14/gap_include.hpp +26 -0
- gap/pkg/semigroups/gapbind14/include/gapbind14/gapbind14.hpp +445 -0
- gap/pkg/semigroups/gapbind14/include/gapbind14/tame_free_fn.hpp +420 -0
- gap/pkg/semigroups/gapbind14/include/gapbind14/tame_mem_fn.hpp +556 -0
- gap/pkg/semigroups/gapbind14/include/gapbind14/to_cpp.hpp +162 -0
- gap/pkg/semigroups/gapbind14/include/gapbind14/to_gap.hpp +158 -0
- gap/pkg/semigroups/gapbind14/src/.clang-format +108 -0
- gap/pkg/semigroups/gapbind14/src/gapbind14.cpp +334 -0
- gap/pkg/semigroups/init.g +150 -0
- gap/pkg/semigroups/m4/ax_append_flag.m4 +50 -0
- gap/pkg/semigroups/m4/ax_check_compile_flag.m4 +53 -0
- gap/pkg/semigroups/m4/ax_check_hpcombi.m4 +121 -0
- gap/pkg/semigroups/m4/ax_check_libsemigroup.m4 +68 -0
- gap/pkg/semigroups/m4/ax_compare_version.m4 +177 -0
- gap/pkg/semigroups/m4/ax_cxx_compile_stdcxx.m4 +1009 -0
- gap/pkg/semigroups/m4/ax_cxx_compile_stdcxx_14.m4 +34 -0
- gap/pkg/semigroups/m4/ax_prefix_config_h.m4 +203 -0
- gap/pkg/semigroups/m4/ax_pthread.m4 +522 -0
- gap/pkg/semigroups/m4/find_gap.m4 +94 -0
- gap/pkg/semigroups/makedoc.g +153 -0
- gap/pkg/semigroups/prerequisites.sh +62 -0
- gap/pkg/semigroups/read.g +105 -0
- gap/pkg/semigroups/release.toml +6 -0
- gap/pkg/semigroups/tst/extreme/README +2 -0
- gap/pkg/semigroups/tst/extreme/attrinv.tst +703 -0
- gap/pkg/semigroups/tst/extreme/bipart.tst +2803 -0
- gap/pkg/semigroups/tst/extreme/closure.tst +652 -0
- gap/pkg/semigroups/tst/extreme/cong.tst +286 -0
- gap/pkg/semigroups/tst/extreme/conginv.tst +43 -0
- gap/pkg/semigroups/tst/extreme/examples.tst +2449 -0
- gap/pkg/semigroups/tst/extreme/freeband.tst +37 -0
- gap/pkg/semigroups/tst/extreme/greens-acting-regular.tst +27 -0
- gap/pkg/semigroups/tst/extreme/greens-acting.tst +1999 -0
- gap/pkg/semigroups/tst/extreme/ideals.tst +858 -0
- gap/pkg/semigroups/tst/extreme/inverse.tst +1025 -0
- gap/pkg/semigroups/tst/extreme/maximal.tst +856 -0
- gap/pkg/semigroups/tst/extreme/misc.tst +4236 -0
- gap/pkg/semigroups/tst/extreme/monoid_pkg.tst +1488 -0
- gap/pkg/semigroups/tst/extreme/properties.tst +914 -0
- gap/pkg/semigroups/tst/extreme/semibipart.tst +2837 -0
- gap/pkg/semigroups/tst/extreme/semieunit.tst +49 -0
- gap/pkg/semigroups/tst/extreme/semiffmat.tst +353 -0
- gap/pkg/semigroups/tst/extreme/semigroups.tst +245 -0
- gap/pkg/semigroups/tst/extreme/semiiter.tst +58 -0
- gap/pkg/semigroups/tst/extreme/semirms.tst +1091 -0
- gap/pkg/semigroups/tst/extreme/transform.tst +305 -0
- gap/pkg/semigroups/tst/extreme/translat.tst +44 -0
- gap/pkg/semigroups/tst/standard/README +2 -0
- gap/pkg/semigroups/tst/standard/attributes/acting.tst +388 -0
- gap/pkg/semigroups/tst/standard/attributes/attr.tst +2404 -0
- gap/pkg/semigroups/tst/standard/attributes/dual.tst +308 -0
- gap/pkg/semigroups/tst/standard/attributes/factor.tst +629 -0
- gap/pkg/semigroups/tst/standard/attributes/homomorph.tst +1134 -0
- gap/pkg/semigroups/tst/standard/attributes/inverse.tst +1521 -0
- gap/pkg/semigroups/tst/standard/attributes/isomorph.tst +435 -0
- gap/pkg/semigroups/tst/standard/attributes/isorms.tst +1147 -0
- gap/pkg/semigroups/tst/standard/attributes/maximal.tst +853 -0
- gap/pkg/semigroups/tst/standard/attributes/properties.tst +2028 -0
- gap/pkg/semigroups/tst/standard/attributes/semifp.tst +53 -0
- gap/pkg/semigroups/tst/standard/attributes/translat.tst +796 -0
- gap/pkg/semigroups/tst/standard/congruences/cong.tst +1044 -0
- gap/pkg/semigroups/tst/standard/congruences/conginv.tst +292 -0
- gap/pkg/semigroups/tst/standard/congruences/conglatt.tst +421 -0
- gap/pkg/semigroups/tst/standard/congruences/congpairs.tst +1011 -0
- gap/pkg/semigroups/tst/standard/congruences/congrees.tst +288 -0
- gap/pkg/semigroups/tst/standard/congruences/congrms.tst +701 -0
- gap/pkg/semigroups/tst/standard/congruences/congsemigraph.tst +422 -0
- gap/pkg/semigroups/tst/standard/congruences/congsimple.tst +311 -0
- gap/pkg/semigroups/tst/standard/congruences/conguniv.tst +259 -0
- gap/pkg/semigroups/tst/standard/congruences/congwordgraph.tst +330 -0
- gap/pkg/semigroups/tst/standard/elements/bipart.tst +783 -0
- gap/pkg/semigroups/tst/standard/elements/blocks.tst +166 -0
- gap/pkg/semigroups/tst/standard/elements/boolmat.tst +608 -0
- gap/pkg/semigroups/tst/standard/elements/elements.tst +117 -0
- gap/pkg/semigroups/tst/standard/elements/ffmat.tst +349 -0
- gap/pkg/semigroups/tst/standard/elements/maxplusmat.tst +613 -0
- gap/pkg/semigroups/tst/standard/elements/pbr.tst +506 -0
- gap/pkg/semigroups/tst/standard/elements/pperm.tst +32 -0
- gap/pkg/semigroups/tst/standard/elements/semiringmat.tst +601 -0
- gap/pkg/semigroups/tst/standard/elements/trans.tst +58 -0
- gap/pkg/semigroups/tst/standard/fp/freeband.tst +311 -0
- gap/pkg/semigroups/tst/standard/fp/freeinverse.tst +147 -0
- gap/pkg/semigroups/tst/standard/fp/tietze.tst +780 -0
- gap/pkg/semigroups/tst/standard/fp/word.tst +106 -0
- gap/pkg/semigroups/tst/standard/greens/acting-inverse.tst +545 -0
- gap/pkg/semigroups/tst/standard/greens/acting-regular.tst +396 -0
- gap/pkg/semigroups/tst/standard/greens/acting.tst +2033 -0
- gap/pkg/semigroups/tst/standard/greens/froidure-pin.tst +1831 -0
- gap/pkg/semigroups/tst/standard/greens/generic.tst +1436 -0
- gap/pkg/semigroups/tst/standard/ideals/acting.tst +279 -0
- gap/pkg/semigroups/tst/standard/ideals/froidure-pin.tst +178 -0
- gap/pkg/semigroups/tst/standard/ideals/ideals.tst +380 -0
- gap/pkg/semigroups/tst/standard/libsemigroups/cong.tst +310 -0
- gap/pkg/semigroups/tst/standard/libsemigroups/froidure-pin.tst +778 -0
- gap/pkg/semigroups/tst/standard/libsemigroups/sims1.tst +379 -0
- gap/pkg/semigroups/tst/standard/main/acting.tst +411 -0
- gap/pkg/semigroups/tst/standard/main/froidure-pin.tst +392 -0
- gap/pkg/semigroups/tst/standard/main/semiact.tst +203 -0
- gap/pkg/semigroups/tst/standard/main/setup.tst +1144 -0
- gap/pkg/semigroups/tst/standard/obsolete.tst +19 -0
- gap/pkg/semigroups/tst/standard/options.tst +54 -0
- gap/pkg/semigroups/tst/standard/semigroups/grpperm.tst +581 -0
- gap/pkg/semigroups/tst/standard/semigroups/semibipart.tst +2635 -0
- gap/pkg/semigroups/tst/standard/semigroups/semiboolmat.tst +1871 -0
- gap/pkg/semigroups/tst/standard/semigroups/semicons.tst +1173 -0
- gap/pkg/semigroups/tst/standard/semigroups/semidp.tst +739 -0
- gap/pkg/semigroups/tst/standard/semigroups/semieunit.tst +339 -0
- gap/pkg/semigroups/tst/standard/semigroups/semiex.tst +2055 -0
- gap/pkg/semigroups/tst/standard/semigroups/semiffmat.tst +746 -0
- gap/pkg/semigroups/tst/standard/semigroups/semifp.tst +2702 -0
- gap/pkg/semigroups/tst/standard/semigroups/semigraph.tst +133 -0
- gap/pkg/semigroups/tst/standard/semigroups/semigrp.tst +1112 -0
- gap/pkg/semigroups/tst/standard/semigroups/semimaxplus.tst +654 -0
- gap/pkg/semigroups/tst/standard/semigroups/semipbr.tst +2142 -0
- gap/pkg/semigroups/tst/standard/semigroups/semipperm.tst +2169 -0
- gap/pkg/semigroups/tst/standard/semigroups/semiquo.tst +278 -0
- gap/pkg/semigroups/tst/standard/semigroups/semirms.tst +3010 -0
- gap/pkg/semigroups/tst/standard/semigroups/semitrans.tst +2758 -0
- gap/pkg/semigroups/tst/standard/tools/display.tst +1040 -0
- gap/pkg/semigroups/tst/standard/tools/io.tst +363 -0
- gap/pkg/semigroups/tst/testinstall.tst +1815 -0
- gap/pkg/semigroups/tst/teststandard.g +22 -0
- gap/pkg/semigroups/tst/workspaces/load-workspace.tst +142 -0
- gap/pkg/semigroups/tst/workspaces/load.g +11 -0
- gap/pkg/semigroups/tst/workspaces/save-workspace.tst +166 -0
- gap/pkg/semigroups/tst/workspaces/save.g +14 -0
- passagemath_gap_pkg_semigroups-10.6.30.dist-info/METADATA +93 -0
- passagemath_gap_pkg_semigroups-10.6.30.dist-info/METADATA.bak +94 -0
- passagemath_gap_pkg_semigroups-10.6.30.dist-info/RECORD +354 -0
- passagemath_gap_pkg_semigroups-10.6.30.dist-info/WHEEL +6 -0
- passagemath_gap_pkg_semigroups-10.6.30.dist-info/top_level.txt +1 -0
- passagemath_gap_pkg_semigroups.dylibs/libsemigroups.2.dylib +0 -0
- sage/all__sagemath_gap_pkg_semigroups.py +1 -0
- sage/libs/all__sagemath_gap_pkg_semigroups.py +1 -0
- sage/libs/gap_pkg_semigroups.cpython-311-darwin.so +0 -0
|
@@ -0,0 +1,1578 @@
|
|
|
1
|
+
############################################################################
|
|
2
|
+
##
|
|
3
|
+
## fp/tietze.gi
|
|
4
|
+
## Copyright (C) 2021-2022 Tom Conti-Leslie
|
|
5
|
+
## Ben Spiers
|
|
6
|
+
##
|
|
7
|
+
## Licensing information can be found in the README file of this package.
|
|
8
|
+
##
|
|
9
|
+
############################################################################
|
|
10
|
+
##
|
|
11
|
+
|
|
12
|
+
########################################################################
|
|
13
|
+
# This file is organised as follows:
|
|
14
|
+
#
|
|
15
|
+
# 1. Definition of the Semigroup Tietze (IsStzPresentation) object
|
|
16
|
+
# 2. Viewing methods for IsStzPresentation objects
|
|
17
|
+
# 3. Internal Tietze transformation functions
|
|
18
|
+
# 4. User-accessible Tietze transformation functions (wrappers)
|
|
19
|
+
# 5. Internal helper functions for word/relation manipulation etc.
|
|
20
|
+
# 6. Internal auto-checkers and appliers for presentation simplifying
|
|
21
|
+
# 7. SimplifyPresentation etc.
|
|
22
|
+
# 8. Other
|
|
23
|
+
########################################################################
|
|
24
|
+
|
|
25
|
+
########################################################################
|
|
26
|
+
# 1. Definition of the Semigroup Tietze (IsStzPresentation) object
|
|
27
|
+
########################################################################
|
|
28
|
+
|
|
29
|
+
InstallMethod(StzPresentation, "for a finitely presented semigroup",
|
|
30
|
+
[IsFpSemigroup],
|
|
31
|
+
function(S)
|
|
32
|
+
local gens, out, rels, type;
|
|
33
|
+
|
|
34
|
+
type := NewType(NewFamily("StzFamily", IsStzPresentation),
|
|
35
|
+
IsStzPresentation and IsComponentObjectRep);
|
|
36
|
+
|
|
37
|
+
rels := List(RelationsOfFpSemigroup(S),
|
|
38
|
+
x -> [LetterRepAssocWord(x[1]), LetterRepAssocWord(x[2])]);
|
|
39
|
+
gens := List(GeneratorsOfSemigroup(S), ViewString);
|
|
40
|
+
|
|
41
|
+
out := rec(GeneratorsOfStzPresentation := gens,
|
|
42
|
+
RelationsOfStzPresentation := rels,
|
|
43
|
+
UnreducedFpSemigroup := S,
|
|
44
|
+
TietzeForwardMap := List(
|
|
45
|
+
[1 .. Length(GeneratorsOfSemigroup(S))], x -> [x]),
|
|
46
|
+
TietzeBackwardMap := List(
|
|
47
|
+
[1 .. Length(GeneratorsOfSemigroup(S))], x -> [x]),
|
|
48
|
+
usedGens := Set(gens));
|
|
49
|
+
|
|
50
|
+
return Objectify(type, out);
|
|
51
|
+
end);
|
|
52
|
+
|
|
53
|
+
InstallMethod(SetRelationsOfStzPresentation,
|
|
54
|
+
[IsStzPresentation, IsList],
|
|
55
|
+
function(stz, arg)
|
|
56
|
+
if not ForAll(arg, IsList) or
|
|
57
|
+
not ForAll(arg, x -> Length(x) = 2 and ForAll(x, IsList)) or
|
|
58
|
+
not ForAll(arg, x -> ForAll(x, y -> ForAll(y, IsPosInt))) then
|
|
59
|
+
ErrorNoReturn("parameter <arg> must be a list of pairs of words in ",
|
|
60
|
+
"LetterRep format");
|
|
61
|
+
fi;
|
|
62
|
+
stz!.RelationsOfStzPresentation := arg;
|
|
63
|
+
end);
|
|
64
|
+
|
|
65
|
+
InstallMethod(RelationsOfStzPresentation, [IsStzPresentation],
|
|
66
|
+
stz -> stz!.RelationsOfStzPresentation);
|
|
67
|
+
|
|
68
|
+
InstallMethod(UnreducedFpSemigroup, [IsStzPresentation],
|
|
69
|
+
stz -> stz!.UnreducedFpSemigroup);
|
|
70
|
+
|
|
71
|
+
InstallMethod(TietzeForwardMap, [IsStzPresentation],
|
|
72
|
+
stz -> stz!.TietzeForwardMap);
|
|
73
|
+
|
|
74
|
+
InstallMethod(TietzeBackwardMap, [IsStzPresentation],
|
|
75
|
+
stz -> stz!.TietzeBackwardMap);
|
|
76
|
+
|
|
77
|
+
InstallMethod(GeneratorsOfStzPresentation, [IsStzPresentation],
|
|
78
|
+
stz -> stz!.GeneratorsOfStzPresentation);
|
|
79
|
+
|
|
80
|
+
InstallMethod(SetGeneratorsOfStzPresentation, [IsStzPresentation, IsList],
|
|
81
|
+
function(stz, newGens)
|
|
82
|
+
stz!.GeneratorsOfStzPresentation := newGens;
|
|
83
|
+
end);
|
|
84
|
+
|
|
85
|
+
InstallMethod(StzIsomorphism,
|
|
86
|
+
[IsStzPresentation],
|
|
87
|
+
function(stz)
|
|
88
|
+
local source, range, forward_dict, forward_map, backward_dict, backward_map;
|
|
89
|
+
source := UnreducedFpSemigroup(stz);
|
|
90
|
+
range := SEMIGROUPS.StzConvertObjToFpSemigroup(stz);
|
|
91
|
+
|
|
92
|
+
# build forward map
|
|
93
|
+
forward_dict := TietzeForwardMap(stz);
|
|
94
|
+
forward_map := function(word)
|
|
95
|
+
local new_word;
|
|
96
|
+
new_word := SEMIGROUPS.StzExpandWord(
|
|
97
|
+
LetterRepAssocWord(UnderlyingElement(word)), forward_dict);
|
|
98
|
+
return Product(new_word, x -> GeneratorsOfSemigroup(range)[x]);
|
|
99
|
+
end;
|
|
100
|
+
|
|
101
|
+
# build backward map
|
|
102
|
+
backward_dict := TietzeBackwardMap(stz);
|
|
103
|
+
backward_map := function(word)
|
|
104
|
+
local new_word;
|
|
105
|
+
new_word := SEMIGROUPS.StzExpandWord(
|
|
106
|
+
LetterRepAssocWord(UnderlyingElement(word)), backward_dict);
|
|
107
|
+
return Product(new_word, x -> GeneratorsOfSemigroup(source)[x]);
|
|
108
|
+
end;
|
|
109
|
+
|
|
110
|
+
# TODO(later) are we okay to assume this is necessarily an isomorphism?
|
|
111
|
+
return SemigroupIsomorphismByFunctionNC(source,
|
|
112
|
+
range,
|
|
113
|
+
forward_map,
|
|
114
|
+
backward_map);
|
|
115
|
+
end);
|
|
116
|
+
|
|
117
|
+
InstallMethod(SetTietzeForwardMap,
|
|
118
|
+
"for an stz presentation and list",
|
|
119
|
+
[IsStzPresentation, IsList],
|
|
120
|
+
function(stz, newMaps)
|
|
121
|
+
if not ForAll(newMaps, x -> IsList(x) and ForAll(x, IsPosInt)) then
|
|
122
|
+
ErrorNoReturn("the 2nd argument <newMaps> must ",
|
|
123
|
+
"be a list of lists of positive integers");
|
|
124
|
+
fi;
|
|
125
|
+
stz!.TietzeForwardMap := newMaps;
|
|
126
|
+
end);
|
|
127
|
+
|
|
128
|
+
InstallMethod(SetTietzeBackwardMap,
|
|
129
|
+
"for an stz presentation and list",
|
|
130
|
+
[IsStzPresentation, IsList],
|
|
131
|
+
function(stz, newMaps)
|
|
132
|
+
if not ForAll(newMaps, x -> IsList(x) and ForAll(x, IsPosInt)) then
|
|
133
|
+
ErrorNoReturn("the 2nd argument <newMaps> must ",
|
|
134
|
+
"be a list of lists of positive integers");
|
|
135
|
+
fi;
|
|
136
|
+
stz!.TietzeBackwardMap := newMaps;
|
|
137
|
+
end);
|
|
138
|
+
|
|
139
|
+
InstallMethod(TietzeForwardMapReplaceSubword,
|
|
140
|
+
"for an stz presentation, list, and list",
|
|
141
|
+
[IsStzPresentation, IsList, IsList],
|
|
142
|
+
function(stz, subWord, newSubWord)
|
|
143
|
+
local newMaps;
|
|
144
|
+
newMaps := List(stz!.TietzeForwardMap,
|
|
145
|
+
x -> SEMIGROUPS.StzReplaceSubwordRel(x,
|
|
146
|
+
subWord,
|
|
147
|
+
newSubWord));
|
|
148
|
+
stz!.TietzeForwardMap := newMaps;
|
|
149
|
+
end);
|
|
150
|
+
|
|
151
|
+
# Length of an StzPresentation is defined as the number of generators plus the
|
|
152
|
+
# length of every word in the defining relations
|
|
153
|
+
InstallMethod(Length, "for an stz presentation", [IsStzPresentation],
|
|
154
|
+
function(stz)
|
|
155
|
+
local out, rel;
|
|
156
|
+
out := Length(stz!.GeneratorsOfStzPresentation);
|
|
157
|
+
for rel in RelationsOfStzPresentation(stz) do
|
|
158
|
+
out := out + Length(rel[1]) + Length(rel[2]);
|
|
159
|
+
od;
|
|
160
|
+
return out;
|
|
161
|
+
end);
|
|
162
|
+
|
|
163
|
+
InstallMethod(\<, "for stz presentations",
|
|
164
|
+
[IsStzPresentation, IsStzPresentation],
|
|
165
|
+
{stz1, stz2} -> Length(stz1) < Length(stz2));
|
|
166
|
+
|
|
167
|
+
########################################################################
|
|
168
|
+
# 2. Viewing methods for IsStzPresentation objects
|
|
169
|
+
########################################################################
|
|
170
|
+
|
|
171
|
+
InstallMethod(ViewString,
|
|
172
|
+
[IsStzPresentation],
|
|
173
|
+
function(stz)
|
|
174
|
+
local num_gens, num_rels;
|
|
175
|
+
num_gens := Length(stz!.GeneratorsOfStzPresentation);
|
|
176
|
+
num_rels := Length(stz!.RelationsOfStzPresentation);
|
|
177
|
+
return Concatenation(
|
|
178
|
+
StringFormatted("<fp semigroup presentation with {} and {}",
|
|
179
|
+
Pluralize(num_gens, "generator"),
|
|
180
|
+
Pluralize(num_rels, "relation")),
|
|
181
|
+
StringFormatted("\< with length {}>", Length(stz)));
|
|
182
|
+
end);
|
|
183
|
+
|
|
184
|
+
SEMIGROUPS.StzRelationDisplayString := function(stz, i)
|
|
185
|
+
local rels, f, gens, w1, w2;
|
|
186
|
+
rels := RelationsOfStzPresentation(stz);
|
|
187
|
+
if i > Length(rels) then
|
|
188
|
+
return fail;
|
|
189
|
+
else
|
|
190
|
+
# We'd like patterns to be grouped, i.e. abab=(ab)^2 when displayed. To
|
|
191
|
+
# do this we sneakily piggyback off display methods for the free semigroup.
|
|
192
|
+
f := FreeSemigroup(GeneratorsOfStzPresentation(stz));
|
|
193
|
+
gens := GeneratorsOfSemigroup(f);
|
|
194
|
+
w1 := Product(rels[i][1], x -> gens[x]);
|
|
195
|
+
w2 := Product(rels[i][2], x -> gens[x]);
|
|
196
|
+
return Concatenation(PrintString(i),
|
|
197
|
+
". ",
|
|
198
|
+
PrintString(w1),
|
|
199
|
+
" = ",
|
|
200
|
+
PrintString(w2));
|
|
201
|
+
fi;
|
|
202
|
+
end;
|
|
203
|
+
|
|
204
|
+
InstallMethod(StzPrintRelations,
|
|
205
|
+
"for an stz presentation and a list of pos ints",
|
|
206
|
+
[IsStzPresentation, IsList],
|
|
207
|
+
function(stz, list)
|
|
208
|
+
local i;
|
|
209
|
+
# This function displays the current relations in terms of the current
|
|
210
|
+
# generators for a semigroup Tietze presentation.
|
|
211
|
+
if IsEmpty(RelationsOfStzPresentation(stz)) then
|
|
212
|
+
Info(InfoFpSemigroup,
|
|
213
|
+
1,
|
|
214
|
+
"There are no relations in the presentation <stz>");
|
|
215
|
+
fi;
|
|
216
|
+
|
|
217
|
+
# Print relations at each index of the list, unless incorrect index,
|
|
218
|
+
# in which case skip.
|
|
219
|
+
for i in list do
|
|
220
|
+
if IsPosInt(i) and i <= Length(RelationsOfStzPresentation(stz)) then
|
|
221
|
+
Info(InfoFpSemigroup, 1, SEMIGROUPS.StzRelationDisplayString(stz, i));
|
|
222
|
+
fi;
|
|
223
|
+
od;
|
|
224
|
+
end);
|
|
225
|
+
|
|
226
|
+
InstallMethod(StzPrintRelations, "for an stz presentation",
|
|
227
|
+
[IsStzPresentation],
|
|
228
|
+
function(stz)
|
|
229
|
+
StzPrintRelations(stz, [1 .. Length(RelationsOfStzPresentation(stz))]);
|
|
230
|
+
end);
|
|
231
|
+
|
|
232
|
+
InstallMethod(StzPrintRelation, "for an stz presentation and a pos int",
|
|
233
|
+
[IsStzPresentation, IsPosInt],
|
|
234
|
+
function(stz, int)
|
|
235
|
+
StzPrintRelations(stz, [int]);
|
|
236
|
+
end);
|
|
237
|
+
|
|
238
|
+
InstallMethod(StzPrintGenerators,
|
|
239
|
+
"for an stz presentation and a list of pos ints",
|
|
240
|
+
[IsStzPresentation, IsList],
|
|
241
|
+
function(stz, list)
|
|
242
|
+
local flat, gens, out, rel, i;
|
|
243
|
+
# This function displays a list of generators and number of occurrences
|
|
244
|
+
# of each
|
|
245
|
+
|
|
246
|
+
# warn if there are no generators in the list (not sure this could happen)
|
|
247
|
+
if IsEmpty(GeneratorsOfStzPresentation(stz)) then
|
|
248
|
+
Info(InfoFpSemigroup, 1,
|
|
249
|
+
"There are no generators in the presentation <stz>");
|
|
250
|
+
fi;
|
|
251
|
+
|
|
252
|
+
# create flat flat list of relations to count occurrences
|
|
253
|
+
flat := [];
|
|
254
|
+
for rel in RelationsOfStzPresentation(stz) do
|
|
255
|
+
Append(flat, rel[1]);
|
|
256
|
+
Append(flat, rel[2]);
|
|
257
|
+
od;
|
|
258
|
+
|
|
259
|
+
# enumerate and count generators
|
|
260
|
+
gens := GeneratorsOfStzPresentation(stz);
|
|
261
|
+
for i in list do
|
|
262
|
+
# only print if requested index is valid
|
|
263
|
+
if IsPosInt(i) and i <= Length(gens) then
|
|
264
|
+
out := Concatenation(PrintString(i),
|
|
265
|
+
". ",
|
|
266
|
+
gens[i],
|
|
267
|
+
" ",
|
|
268
|
+
PrintString(Number(flat, x -> x = i)),
|
|
269
|
+
" occurrences");
|
|
270
|
+
Info(InfoFpSemigroup, 1, out);
|
|
271
|
+
fi;
|
|
272
|
+
od;
|
|
273
|
+
end);
|
|
274
|
+
|
|
275
|
+
InstallMethod(StzPrintGenerators, "for an stz presentation",
|
|
276
|
+
[IsStzPresentation],
|
|
277
|
+
function(stz)
|
|
278
|
+
StzPrintGenerators(stz, [1 .. Length(GeneratorsOfStzPresentation(stz))]);
|
|
279
|
+
end);
|
|
280
|
+
|
|
281
|
+
InstallMethod(StzPrintPresentation, "for an stz presentation",
|
|
282
|
+
[IsStzPresentation],
|
|
283
|
+
function(stz)
|
|
284
|
+
local status, oldgens, oldfree, oldelms, newgens, newfree, newelms, w, i;
|
|
285
|
+
# prints everything that is known about the presentation.
|
|
286
|
+
|
|
287
|
+
# current generators
|
|
288
|
+
Info(InfoFpSemigroup, 1, "Current generators:");
|
|
289
|
+
StzPrintGenerators(stz);
|
|
290
|
+
|
|
291
|
+
# current relations
|
|
292
|
+
Info(InfoFpSemigroup, 1, "");
|
|
293
|
+
Info(InfoFpSemigroup, 1, "Current relations:");
|
|
294
|
+
StzPrintRelations(stz);
|
|
295
|
+
|
|
296
|
+
# total number and total length
|
|
297
|
+
Info(InfoFpSemigroup, 1, "");
|
|
298
|
+
status := "There ";
|
|
299
|
+
if Length(stz!.GeneratorsOfStzPresentation) = 1 then
|
|
300
|
+
status := Concatenation(status, "is 1 generator");
|
|
301
|
+
else
|
|
302
|
+
status := Concatenation(status,
|
|
303
|
+
"are ",
|
|
304
|
+
PrintString(
|
|
305
|
+
Length(GeneratorsOfStzPresentation(stz))),
|
|
306
|
+
" generators");
|
|
307
|
+
fi;
|
|
308
|
+
status := Concatenation(status, " and ");
|
|
309
|
+
if Length(stz!.RelationsOfStzPresentation) = 1 then
|
|
310
|
+
status := Concatenation(status, "1 relation");
|
|
311
|
+
else
|
|
312
|
+
status := Concatenation(status,
|
|
313
|
+
PrintString(Length(stz!.RelationsOfStzPresentation)),
|
|
314
|
+
" relations");
|
|
315
|
+
fi;
|
|
316
|
+
status := Concatenation(status,
|
|
317
|
+
" of total length ",
|
|
318
|
+
PrintString(Length(stz)),
|
|
319
|
+
".");
|
|
320
|
+
Info(InfoFpSemigroup, 1, status);
|
|
321
|
+
|
|
322
|
+
# build free semigroup of old gens for display
|
|
323
|
+
oldgens := GeneratorsOfSemigroup(UnreducedFpSemigroup(stz));
|
|
324
|
+
oldgens := List(oldgens, ViewString);
|
|
325
|
+
oldfree := FreeSemigroup(oldgens);
|
|
326
|
+
oldelms := GeneratorsOfSemigroup(oldfree);
|
|
327
|
+
|
|
328
|
+
# build free semigroup of new gens for display
|
|
329
|
+
newgens := GeneratorsOfStzPresentation(stz);
|
|
330
|
+
newfree := FreeSemigroup(newgens);
|
|
331
|
+
newelms := GeneratorsOfSemigroup(newfree);
|
|
332
|
+
|
|
333
|
+
# old generators expressed using current ones
|
|
334
|
+
Info(InfoFpSemigroup, 1, "");
|
|
335
|
+
Info(InfoFpSemigroup, 1, "Generators of original fp semigroup expressed as");
|
|
336
|
+
Info(InfoFpSemigroup, 1,
|
|
337
|
+
"combinations of generators in current presentation:");
|
|
338
|
+
for i in [1 .. Length(oldgens)] do
|
|
339
|
+
w := Product(TietzeForwardMap(stz)[i], x -> newelms[x]);
|
|
340
|
+
Info(InfoFpSemigroup, 1, Concatenation(PrintString(i),
|
|
341
|
+
". ",
|
|
342
|
+
oldgens[i],
|
|
343
|
+
" = ",
|
|
344
|
+
PrintString(w)));
|
|
345
|
+
od;
|
|
346
|
+
|
|
347
|
+
# new generators expressed using old ones
|
|
348
|
+
Info(InfoFpSemigroup, 1, "");
|
|
349
|
+
Info(InfoFpSemigroup, 1, "Generators of current presentation expressed as");
|
|
350
|
+
Info(InfoFpSemigroup, 1,
|
|
351
|
+
"combinations of generators of original fp semigroup:");
|
|
352
|
+
for i in [1 .. Length(newgens)] do
|
|
353
|
+
w := Product(TietzeBackwardMap(stz)[i], x -> oldelms[x]);
|
|
354
|
+
Info(InfoFpSemigroup, 1, Concatenation(PrintString(i),
|
|
355
|
+
". ",
|
|
356
|
+
newgens[i],
|
|
357
|
+
" = ",
|
|
358
|
+
PrintString(w)));
|
|
359
|
+
od;
|
|
360
|
+
end);
|
|
361
|
+
|
|
362
|
+
########################################################################
|
|
363
|
+
# 3. Internal Tietze transformation functions
|
|
364
|
+
########################################################################
|
|
365
|
+
|
|
366
|
+
# TIETZE TRANSFORMATION 1: INTERNAL: ADD REDUNDANT RELATION - NO CHECK
|
|
367
|
+
SEMIGROUPS.TietzeTransformation1 := function(stz, pair)
|
|
368
|
+
local rels_copy;
|
|
369
|
+
# Arguments:
|
|
370
|
+
# - <stz> should be a Semigroup Tietze (IsStzPresentation) object.
|
|
371
|
+
# - <pair> should be a list containing two LetterRep words.
|
|
372
|
+
#
|
|
373
|
+
# This function returns nothing, and modifies <stz> in place by adding a new
|
|
374
|
+
# relation given by <pair>. This relation is assumed to be redundant based
|
|
375
|
+
# on the relations already present in RelationsOfStzPresentation(<stz>)
|
|
376
|
+
# (although this is not checked).
|
|
377
|
+
#
|
|
378
|
+
# WARNING: this is an internal function and performs only minimal argument
|
|
379
|
+
# checks. Entering arguments in the wrong format may result in errors that
|
|
380
|
+
# are difficult to interpret. Argument checks are carried out in the
|
|
381
|
+
# analogous, documented function: StzAddRelation. However, these checks
|
|
382
|
+
# may not terminate in some cases.
|
|
383
|
+
|
|
384
|
+
# Add relation
|
|
385
|
+
rels_copy := ShallowCopy(RelationsOfStzPresentation(stz));
|
|
386
|
+
Add(rels_copy, pair);
|
|
387
|
+
stz!.RelationsOfStzPresentation := rels_copy;
|
|
388
|
+
return;
|
|
389
|
+
end;
|
|
390
|
+
|
|
391
|
+
# TIETZE TRANSFORMATION 2: INTERNAL: REMOVE REDUNDANT RELATION - NO CHECK
|
|
392
|
+
SEMIGROUPS.TietzeTransformation2 := function(stz, index)
|
|
393
|
+
local rels_copy;
|
|
394
|
+
# Arguments:
|
|
395
|
+
# - <stz> should be a Semigroup Tietze (IsStzPresentation) object.
|
|
396
|
+
# - <index> should be the index of the relation in
|
|
397
|
+
# RelationsOfStzPresentation(<stz>) that needs to be removed.
|
|
398
|
+
#
|
|
399
|
+
# This function returns nothing, and modifies <stz> in place by removing
|
|
400
|
+
# relation number <index>, assumed to be redundant (though redundancy of
|
|
401
|
+
# that relation is not checked).
|
|
402
|
+
#
|
|
403
|
+
# WARNING: this is an internal function and performs only minimal argument
|
|
404
|
+
# checks. Entering arguments in the wrong format may result in errors that
|
|
405
|
+
# are difficult to interpret. Argument checks are carried out in the
|
|
406
|
+
# analogous, documented function: StzRemoveRelation. However, these checks
|
|
407
|
+
# may not terminate in some cases.
|
|
408
|
+
|
|
409
|
+
# Remove relation
|
|
410
|
+
rels_copy := ShallowCopy(RelationsOfStzPresentation(stz));
|
|
411
|
+
Remove(rels_copy, index);
|
|
412
|
+
stz!.RelationsOfStzPresentation := rels_copy;
|
|
413
|
+
end;
|
|
414
|
+
|
|
415
|
+
# TIETZE TRANSFORMATION 3: INTERNAL: ADD NEW GENERATOR - NO CHECK
|
|
416
|
+
SEMIGROUPS.TietzeTransformation3 := function(stz, word, name)
|
|
417
|
+
local new_gens, new_rels, back_word, new_maps, letter;
|
|
418
|
+
# Arguments:
|
|
419
|
+
# - <stz> should be a Semigroup Tietze (IsStzPresentation) object.
|
|
420
|
+
# - <word> should be a LetterRep word.
|
|
421
|
+
# - <name> should be a string, or fail.
|
|
422
|
+
#
|
|
423
|
+
# This function returns nothing, and modifies <stz> in place by adding a new
|
|
424
|
+
# generator and the relation gen = <word>.
|
|
425
|
+
# The name for the new generator is <name>, unless this argument is fail,
|
|
426
|
+
# in which case the name is automatically generated using
|
|
427
|
+
# SEMIGROUPS.NewGeneratorName.
|
|
428
|
+
# This function also updates the Tietze backwards map so that the new
|
|
429
|
+
# generator can be expressed as a word on the generators of the original
|
|
430
|
+
# semigroup.
|
|
431
|
+
#
|
|
432
|
+
# WARNING: this is an internal function and performs only minimal argument
|
|
433
|
+
# checks. Entering arguments in the wrong format may result in errors that
|
|
434
|
+
# are difficult to interpret. Argument checks are carried out in the
|
|
435
|
+
# analogous, documented function: StzAddGenerator.
|
|
436
|
+
|
|
437
|
+
# Add new generator string to the list of gens in similar format
|
|
438
|
+
new_gens := ShallowCopy(stz!.GeneratorsOfStzPresentation);
|
|
439
|
+
new_rels := ShallowCopy(stz!.RelationsOfStzPresentation);
|
|
440
|
+
if name = fail or name in stz!.GeneratorsOfStzPresentation then
|
|
441
|
+
# either name was not specified, or it was but is already a generator.
|
|
442
|
+
# generate a new generator name, as of yet unused.
|
|
443
|
+
Add(new_gens, SEMIGROUPS.NewGeneratorName(List(stz!.usedGens)));
|
|
444
|
+
else
|
|
445
|
+
# this must mean the argument is a string as of yet unused, so add that
|
|
446
|
+
Add(new_gens, ShallowCopy(name));
|
|
447
|
+
fi;
|
|
448
|
+
|
|
449
|
+
# in either case we have added a new generator: for cosmetic reasons,
|
|
450
|
+
# prohibit that generator name from being auto-used again (in case we delete
|
|
451
|
+
# it)
|
|
452
|
+
UniteSet(stz!.usedGens, new_gens);
|
|
453
|
+
|
|
454
|
+
# Add relation setting new gen equal to <word>
|
|
455
|
+
Add(new_rels, [word, [Length(stz!.GeneratorsOfStzPresentation) + 1]]);
|
|
456
|
+
|
|
457
|
+
# Update internal representation of the stz object
|
|
458
|
+
SetGeneratorsOfStzPresentation(stz, new_gens);
|
|
459
|
+
SetRelationsOfStzPresentation(stz, new_rels);
|
|
460
|
+
|
|
461
|
+
# Now we need to update the backwards map to express the new generator in
|
|
462
|
+
# terms of the original generators.
|
|
463
|
+
back_word := [];
|
|
464
|
+
new_maps := ShallowCopy(TietzeBackwardMap(stz));
|
|
465
|
+
for letter in word do
|
|
466
|
+
Append(back_word, new_maps[letter]);
|
|
467
|
+
od;
|
|
468
|
+
Add(new_maps, back_word);
|
|
469
|
+
SetTietzeBackwardMap(stz, new_maps);
|
|
470
|
+
end;
|
|
471
|
+
|
|
472
|
+
# TIETZE TRANSFORMATION 4: INTERNAL: REMOVE GENERATOR - MINIMAL CHECKS
|
|
473
|
+
SEMIGROUPS.TietzeTransformation4 := function(stz, gen, index)
|
|
474
|
+
local found_expr, expr, decrement, tempMaps, tempRels, tempGens;
|
|
475
|
+
# Arguments:
|
|
476
|
+
# - <stz> should be a Semigroup Tietze (IsStzPresentation) object.
|
|
477
|
+
# - <gen> should be a pos int.
|
|
478
|
+
# - <index> should be a pos int.
|
|
479
|
+
#
|
|
480
|
+
# This function returns nothing, and modifies <stz> in place by removing
|
|
481
|
+
# generator number <gen> using relation number <index>.
|
|
482
|
+
# If relation number <index> of <stz> is not of the form
|
|
483
|
+
# [<gen>] = *some word not including <gen>* (or that relation flipped),
|
|
484
|
+
# then this function throws ErrorNoReturn.
|
|
485
|
+
# This function also updates the Tietze forward map, so that any generator
|
|
486
|
+
# in the original semigroup expressed as a combination of generators
|
|
487
|
+
# including <gen> is now represented without using <gen> (since <gen>
|
|
488
|
+
# has been removed).
|
|
489
|
+
#
|
|
490
|
+
# WARNING: this is an internal function and performs only minimal argument
|
|
491
|
+
# checks. Entering arguments in the wrong format may result in errors that
|
|
492
|
+
# are difficult to interpret. Argument checks are carried out in the
|
|
493
|
+
# analogous, documented function: StzRemoveGenerator.
|
|
494
|
+
|
|
495
|
+
# check we can express <gen> using only other generators with relation
|
|
496
|
+
# number <index>
|
|
497
|
+
found_expr := false;
|
|
498
|
+
if RelationsOfStzPresentation(stz)[index][1] = [gen] and
|
|
499
|
+
not gen in RelationsOfStzPresentation(stz)[index][2] then
|
|
500
|
+
expr := RelationsOfStzPresentation(stz)[index][2];
|
|
501
|
+
found_expr := true;
|
|
502
|
+
elif RelationsOfStzPresentation(stz)[index][2] = [gen] and
|
|
503
|
+
not gen in RelationsOfStzPresentation(stz)[index][1] then
|
|
504
|
+
expr := RelationsOfStzPresentation(stz)[index][1];
|
|
505
|
+
found_expr := true;
|
|
506
|
+
fi;
|
|
507
|
+
|
|
508
|
+
# check we found an expression for <gen>. If not, nothing can be done.
|
|
509
|
+
if not found_expr then
|
|
510
|
+
ErrorNoReturn("TietzeTransformation4, internal function: third argument\n",
|
|
511
|
+
"<index> does not point to a relation expressing second\n",
|
|
512
|
+
"argument <gen> as a combination of other generators");
|
|
513
|
+
fi;
|
|
514
|
+
|
|
515
|
+
# Define decrement function to bump down generator numbers past the one
|
|
516
|
+
# we're going to remove
|
|
517
|
+
decrement := function(z)
|
|
518
|
+
if z <= gen then # shouldn't be equal but just in case
|
|
519
|
+
return z;
|
|
520
|
+
else
|
|
521
|
+
return z - 1;
|
|
522
|
+
fi;
|
|
523
|
+
end;
|
|
524
|
+
|
|
525
|
+
# update forward mapping component
|
|
526
|
+
# TODO(later) do we really need TietzeForwardMapReplaceSubword?
|
|
527
|
+
TietzeForwardMapReplaceSubword(stz, [gen], expr);
|
|
528
|
+
tempMaps := ShallowCopy(TietzeForwardMap(stz));
|
|
529
|
+
Apply(tempMaps, x -> List(x, decrement));
|
|
530
|
+
SetTietzeForwardMap(stz, tempMaps);
|
|
531
|
+
|
|
532
|
+
# remove generator from backward mapping component
|
|
533
|
+
tempMaps := ShallowCopy(TietzeBackwardMap(stz));
|
|
534
|
+
Remove(tempMaps, gen);
|
|
535
|
+
SetTietzeBackwardMap(stz, tempMaps);
|
|
536
|
+
|
|
537
|
+
# sub in expression we found and remove relation we used for gen
|
|
538
|
+
tempRels := ShallowCopy(RelationsOfStzPresentation(stz));
|
|
539
|
+
Remove(tempRels, index);
|
|
540
|
+
tempRels := SEMIGROUPS.StzReplaceSubword(tempRels, [gen], expr);
|
|
541
|
+
SetRelationsOfStzPresentation(stz, tempRels);
|
|
542
|
+
Apply(stz!.RelationsOfStzPresentation, x -> List(x, y -> List(y, decrement)));
|
|
543
|
+
|
|
544
|
+
# remove generator.
|
|
545
|
+
tempGens := ShallowCopy(GeneratorsOfStzPresentation(stz));
|
|
546
|
+
Remove(tempGens, gen);
|
|
547
|
+
SetGeneratorsOfStzPresentation(stz, tempGens);
|
|
548
|
+
end;
|
|
549
|
+
|
|
550
|
+
########################################################################
|
|
551
|
+
# 4. User-accessible Tietze transformation functions (wrappers)
|
|
552
|
+
########################################################################
|
|
553
|
+
|
|
554
|
+
# Tietze Transformation 1: Add relation
|
|
555
|
+
InstallMethod(StzAddRelation, "for an stz presentation and a pair of words",
|
|
556
|
+
[IsStzPresentation, IsList],
|
|
557
|
+
1, # bump ahead of next implementation and do the list size arg check here
|
|
558
|
+
function(stz, pair)
|
|
559
|
+
local n, f, free_fam, r, s, fp_fam, w1, w2, p1, p2, word, letter;
|
|
560
|
+
# <pair> should be a pair of LetterRep words.
|
|
561
|
+
|
|
562
|
+
# argument checks:
|
|
563
|
+
if Length(pair) <> 2 then
|
|
564
|
+
ErrorNoReturn("StzAddRelation: second argument <pair> should be a list\n",
|
|
565
|
+
"of length 2");
|
|
566
|
+
fi;
|
|
567
|
+
n := Length(stz!.GeneratorsOfStzPresentation);
|
|
568
|
+
for word in pair do
|
|
569
|
+
if not IsList(word) then
|
|
570
|
+
TryNextMethod(); # pass this on to the case where the list may be a pair
|
|
571
|
+
# of words in OG semigroup
|
|
572
|
+
elif IsEmpty(word) then
|
|
573
|
+
ErrorNoReturn("StzAddRelation: words in second argument <pair> should\n",
|
|
574
|
+
"be non-empty");
|
|
575
|
+
else
|
|
576
|
+
for letter in word do
|
|
577
|
+
if not (IsPosInt(letter) and letter <= n) then
|
|
578
|
+
ErrorNoReturn("StzAddRelation: words in second argument <pair>\n",
|
|
579
|
+
"should be lists of pos ints no greater than the\n",
|
|
580
|
+
"number of generators of first argument <stz>");
|
|
581
|
+
fi;
|
|
582
|
+
od;
|
|
583
|
+
fi;
|
|
584
|
+
od;
|
|
585
|
+
|
|
586
|
+
# check that the pair can be deduced from the other relations, by
|
|
587
|
+
# creating fp semigroup with current relations.
|
|
588
|
+
|
|
589
|
+
# base free semigroup
|
|
590
|
+
f := FreeSemigroup(stz!.GeneratorsOfStzPresentation);
|
|
591
|
+
free_fam := FamilyObj(f.1); # marrow for creating free semigp words
|
|
592
|
+
r := List(stz!.RelationsOfStzPresentation,
|
|
593
|
+
x -> List(x, y -> AssocWordByLetterRep(free_fam, y)));
|
|
594
|
+
s := f / r; # fp semigroup
|
|
595
|
+
fp_fam := FamilyObj(s.1); # marrow for creating fp words
|
|
596
|
+
# words first in free semigroup, then map to fp semigroup:
|
|
597
|
+
w1 := AssocWordByLetterRep(free_fam, pair[1]);
|
|
598
|
+
w2 := AssocWordByLetterRep(free_fam, pair[2]);
|
|
599
|
+
p1 := ElementOfFpSemigroup(fp_fam, w1);
|
|
600
|
+
p2 := ElementOfFpSemigroup(fp_fam, w2);
|
|
601
|
+
# check if words are equal in the fp semigroup
|
|
602
|
+
# WARNING: may run forever if undecidable
|
|
603
|
+
if p1 = p2 then
|
|
604
|
+
SEMIGROUPS.TietzeTransformation1(stz, pair);
|
|
605
|
+
return;
|
|
606
|
+
else
|
|
607
|
+
ErrorNoReturn("StzAddRelation: second argument <pair> must list two\n",
|
|
608
|
+
"words that are equal in the presentation <stz>");
|
|
609
|
+
fi;
|
|
610
|
+
end);
|
|
611
|
+
|
|
612
|
+
InstallMethod(StzAddRelation,
|
|
613
|
+
"for an stz presentation and a pair of semigroup elements",
|
|
614
|
+
[IsStzPresentation, IsList],
|
|
615
|
+
function(stz, pair)
|
|
616
|
+
local s, pairwords, word;
|
|
617
|
+
# retrieve original semigroup
|
|
618
|
+
s := UnreducedFpSemigroup(stz);
|
|
619
|
+
for word in pair do
|
|
620
|
+
if not word in s then
|
|
621
|
+
TryNextMethod();
|
|
622
|
+
fi;
|
|
623
|
+
od;
|
|
624
|
+
|
|
625
|
+
# convert into words in original semigroup
|
|
626
|
+
pairwords := List(pair, UnderlyingElement);
|
|
627
|
+
Apply(pairwords, LetterRepAssocWord);
|
|
628
|
+
# map to words in new semigroup
|
|
629
|
+
Apply(pairwords, x -> SEMIGROUPS.StzExpandWord(x, TietzeForwardMap(stz)));
|
|
630
|
+
|
|
631
|
+
# apply tietze1, with argument checks
|
|
632
|
+
StzAddRelation(stz, pairwords);
|
|
633
|
+
return;
|
|
634
|
+
end);
|
|
635
|
+
|
|
636
|
+
# Tietze Transformation 1: Add relation (NO REDUNDANCY CHECK)
|
|
637
|
+
InstallMethod(StzAddRelationNC, "for an stz presentation and a pair of words",
|
|
638
|
+
[IsStzPresentation, IsList],
|
|
639
|
+
1, # bump priority, do list size check here
|
|
640
|
+
function(stz, pair)
|
|
641
|
+
local n, word, letter;
|
|
642
|
+
# <pair> should be a pair of LetterRep words.
|
|
643
|
+
|
|
644
|
+
# argument checks:
|
|
645
|
+
if Length(pair) <> 2 then
|
|
646
|
+
ErrorNoReturn("StzAddRelationNC: second argument <pair> should be a list\n",
|
|
647
|
+
"of length 2");
|
|
648
|
+
fi;
|
|
649
|
+
n := Length(stz!.GeneratorsOfStzPresentation);
|
|
650
|
+
for word in pair do
|
|
651
|
+
if not IsList(word) then
|
|
652
|
+
TryNextMethod(); # pass this on to the case where the list may be a pair
|
|
653
|
+
# of words in OG semigroup
|
|
654
|
+
elif IsEmpty(word) then
|
|
655
|
+
ErrorNoReturn("StzAddRelationNC: words in second argument <pair>\n",
|
|
656
|
+
"should be non-empty");
|
|
657
|
+
else
|
|
658
|
+
for letter in word do
|
|
659
|
+
if not (IsPosInt(letter) and letter <= n) then
|
|
660
|
+
ErrorNoReturn("StzAddRelationNC: words in second argument <pair>\n",
|
|
661
|
+
"should be lists of pos ints no greater than the\n",
|
|
662
|
+
"number of generators of first argument <stz>");
|
|
663
|
+
fi;
|
|
664
|
+
od;
|
|
665
|
+
fi;
|
|
666
|
+
od;
|
|
667
|
+
|
|
668
|
+
# WARNING: no checks are run to verify that the pair is redundant. This
|
|
669
|
+
# may result in an output semigroup which is non-isomorphic to the
|
|
670
|
+
# starting semigroup.
|
|
671
|
+
SEMIGROUPS.TietzeTransformation1(stz, pair);
|
|
672
|
+
return;
|
|
673
|
+
end);
|
|
674
|
+
|
|
675
|
+
InstallMethod(StzAddRelationNC,
|
|
676
|
+
"for an stz presentation and a pair of semigroup elements",
|
|
677
|
+
[IsStzPresentation, IsList],
|
|
678
|
+
function(stz, pair)
|
|
679
|
+
local s, pairwords, word;
|
|
680
|
+
# retrieve original semigroup
|
|
681
|
+
s := UnreducedFpSemigroup(stz);
|
|
682
|
+
for word in pair do
|
|
683
|
+
if not word in s then
|
|
684
|
+
TryNextMethod();
|
|
685
|
+
fi;
|
|
686
|
+
od;
|
|
687
|
+
|
|
688
|
+
# convert into words in original semigroup
|
|
689
|
+
pairwords := List(pair, UnderlyingElement);
|
|
690
|
+
Apply(pairwords, LetterRepAssocWord);
|
|
691
|
+
# map to words in new semigroup
|
|
692
|
+
Apply(pairwords, x -> SEMIGROUPS.StzExpandWord(x, TietzeForwardMap(stz)));
|
|
693
|
+
|
|
694
|
+
# apply tietze1, without argument checks
|
|
695
|
+
# WARNING: no checks are run to verify that the pair is redundant. This
|
|
696
|
+
# may result in an output semigroup which is non-isomorphic to the
|
|
697
|
+
# starting semigroup.
|
|
698
|
+
SEMIGROUPS.TietzeTransformation1(stz, pairwords);
|
|
699
|
+
return;
|
|
700
|
+
end);
|
|
701
|
+
|
|
702
|
+
# Tietze Transformation 2: Remove relation
|
|
703
|
+
InstallMethod(StzRemoveRelation,
|
|
704
|
+
"for an stz presentation and a pos int",
|
|
705
|
+
[IsStzPresentation, IsPosInt],
|
|
706
|
+
function(stz, index)
|
|
707
|
+
local rels, pair, new_f, new_gens, new_s, free_fam, w1, w2, fp_fam, p1, p2;
|
|
708
|
+
# <index> should be the index of the relation needing removing in the
|
|
709
|
+
# overall list of relations.
|
|
710
|
+
|
|
711
|
+
# argument check: valid index
|
|
712
|
+
rels := ShallowCopy(stz!.RelationsOfStzPresentation);
|
|
713
|
+
if index > Length(rels) then
|
|
714
|
+
ErrorNoReturn("StzRemoveRelation: second argument <index> must be less\n",
|
|
715
|
+
"than or equal to the number of relations of the first\n",
|
|
716
|
+
"argument <stz>");
|
|
717
|
+
fi;
|
|
718
|
+
|
|
719
|
+
# create hypothetical fp semigroup that would be the result of removing
|
|
720
|
+
# the requested pair
|
|
721
|
+
pair := rels[index];
|
|
722
|
+
Remove(rels, index);
|
|
723
|
+
new_f := FreeSemigroup(stz!.GeneratorsOfStzPresentation);
|
|
724
|
+
new_gens := GeneratorsOfSemigroup(new_f);
|
|
725
|
+
new_s := new_f / List(rels,
|
|
726
|
+
x -> List(x,
|
|
727
|
+
y -> Product(List(y,
|
|
728
|
+
z -> new_gens[z]))));
|
|
729
|
+
|
|
730
|
+
# create two associative words
|
|
731
|
+
free_fam := FamilyObj(new_f.1);
|
|
732
|
+
w1 := AssocWordByLetterRep(free_fam, pair[1]);
|
|
733
|
+
w2 := AssocWordByLetterRep(free_fam, pair[2]);
|
|
734
|
+
|
|
735
|
+
# map these words to hypothetical fp semigroup words and check equality
|
|
736
|
+
fp_fam := FamilyObj(new_s.1);
|
|
737
|
+
p1 := ElementOfFpSemigroup(fp_fam, w1);
|
|
738
|
+
p2 := ElementOfFpSemigroup(fp_fam, w2);
|
|
739
|
+
|
|
740
|
+
# WARNING: may run forever if undecidable
|
|
741
|
+
if p1 = p2 then
|
|
742
|
+
SEMIGROUPS.TietzeTransformation2(stz, index);
|
|
743
|
+
return;
|
|
744
|
+
else
|
|
745
|
+
ErrorNoReturn("StzRemoveRelation: second argument <index> must point to\n",
|
|
746
|
+
"a relation that is redundant in the presentation <stz>");
|
|
747
|
+
fi;
|
|
748
|
+
end);
|
|
749
|
+
|
|
750
|
+
# Tietze Transformation 2: Remove relation (NO REDUNDANCY CHECK)
|
|
751
|
+
InstallMethod(StzRemoveRelationNC,
|
|
752
|
+
"for an stz presentation and a pos int",
|
|
753
|
+
[IsStzPresentation, IsPosInt],
|
|
754
|
+
function(stz, index)
|
|
755
|
+
if index > Length(RelationsOfStzPresentation(stz)) then
|
|
756
|
+
ErrorNoReturn("StzRemoveRelationNC: second argument <index> must be less\n",
|
|
757
|
+
"than or equal to the number of relations of the first\n",
|
|
758
|
+
"argument <stz>");
|
|
759
|
+
fi;
|
|
760
|
+
|
|
761
|
+
# WARNING: no checks are run to verify that the pair is redundant. This
|
|
762
|
+
# may result in an output semigroup which is non-isomorphic to the
|
|
763
|
+
# starting semigroup.
|
|
764
|
+
SEMIGROUPS.TietzeTransformation2(stz, index);
|
|
765
|
+
return;
|
|
766
|
+
end);
|
|
767
|
+
|
|
768
|
+
# Tietze Transformation 3: Add generator
|
|
769
|
+
InstallMethod(StzAddGenerator,
|
|
770
|
+
"for an stz presentation and a LetterRep word",
|
|
771
|
+
[IsStzPresentation, IsList],
|
|
772
|
+
function(stz, word)
|
|
773
|
+
local n, letter;
|
|
774
|
+
# argument checks
|
|
775
|
+
if IsEmpty(word) then
|
|
776
|
+
ErrorNoReturn("StzAddGenerator: cannot add generator equal to the empty\n",
|
|
777
|
+
"word");
|
|
778
|
+
fi;
|
|
779
|
+
n := Length(GeneratorsOfStzPresentation(stz));
|
|
780
|
+
for letter in word do
|
|
781
|
+
if not (IsPosInt(letter) and letter <= n) then
|
|
782
|
+
# the argument has not been entered as a list of pos ints. Pass off to
|
|
783
|
+
# potential future methods for Tietze3, but this is likely to be a
|
|
784
|
+
# mistake.
|
|
785
|
+
ErrorNoReturn("StzAddGenerator: second argument <word> is not a\n",
|
|
786
|
+
"list of pos ints at most equal to the number of\n",
|
|
787
|
+
"generators of the first argument <stz>");
|
|
788
|
+
fi;
|
|
789
|
+
od;
|
|
790
|
+
|
|
791
|
+
# at this point all is good, so request new generator to be added with
|
|
792
|
+
# a new generator name auto-created.
|
|
793
|
+
SEMIGROUPS.TietzeTransformation3(stz, word, fail);
|
|
794
|
+
end);
|
|
795
|
+
|
|
796
|
+
InstallMethod(StzAddGenerator,
|
|
797
|
+
"for an stz presentation and a fp semigroup element",
|
|
798
|
+
[IsStzPresentation, IsElementOfFpSemigroup],
|
|
799
|
+
function(stz, word)
|
|
800
|
+
local letterrepword;
|
|
801
|
+
# argument check: word should be an element of the unreduced semigroup
|
|
802
|
+
# (that way we can express it as a word on the current tietze generators)
|
|
803
|
+
if not word in UnreducedFpSemigroup(stz) then
|
|
804
|
+
TryNextMethod();
|
|
805
|
+
fi;
|
|
806
|
+
|
|
807
|
+
# if we do have an element of s, use the forward map to express it as a word
|
|
808
|
+
# on the current generators, then run the original implementation of Tietze 3.
|
|
809
|
+
letterrepword := SEMIGROUPS.StzExpandWord(
|
|
810
|
+
LetterRepAssocWord(UnderlyingElement(word)),
|
|
811
|
+
TietzeForwardMap(stz));
|
|
812
|
+
StzAddGenerator(stz, letterrepword);
|
|
813
|
+
end);
|
|
814
|
+
|
|
815
|
+
# Tietze Transformation 3: Add generator (with specified new generator name)
|
|
816
|
+
InstallMethod(StzAddGenerator,
|
|
817
|
+
"for an stz presentation, a LetterRep word and a string",
|
|
818
|
+
[IsStzPresentation, IsList, IsString],
|
|
819
|
+
function(stz, word, name)
|
|
820
|
+
local n, letter;
|
|
821
|
+
# argument check 0: new word is non-empty
|
|
822
|
+
if IsEmpty(word) then
|
|
823
|
+
ErrorNoReturn("StzAddGenerator: cannot add generator equal to the empty\n",
|
|
824
|
+
"word");
|
|
825
|
+
fi;
|
|
826
|
+
# argument check 1: word is a valid word
|
|
827
|
+
n := Length(GeneratorsOfStzPresentation(stz));
|
|
828
|
+
for letter in word do
|
|
829
|
+
if not (IsPosInt(letter) and letter <= n) then
|
|
830
|
+
# the argument has not been entered as a list of pos ints. Pass off to
|
|
831
|
+
# potential future methods for Tietze3, but this is likely to be a
|
|
832
|
+
# mistake.
|
|
833
|
+
ErrorNoReturn("StzAddGenerator: second argument <word> is not a\n",
|
|
834
|
+
"list of pos ints at most equal to the number of\n",
|
|
835
|
+
"generators of the first argument <stz>");
|
|
836
|
+
fi;
|
|
837
|
+
od;
|
|
838
|
+
|
|
839
|
+
# argument check 2: requested generator name not yet used
|
|
840
|
+
if name in GeneratorsOfStzPresentation(stz) then
|
|
841
|
+
ErrorNoReturn("StzAddGenerator: third argument <name> should not be the\n",
|
|
842
|
+
"name of a pre-existing generator");
|
|
843
|
+
fi;
|
|
844
|
+
|
|
845
|
+
# otherwise we are all good
|
|
846
|
+
SEMIGROUPS.TietzeTransformation3(stz, word, name);
|
|
847
|
+
end);
|
|
848
|
+
|
|
849
|
+
InstallMethod(StzAddGenerator,
|
|
850
|
+
"for an stz presentation, a fp semigroup element and a string",
|
|
851
|
+
[IsStzPresentation, IsElementOfFpSemigroup, IsString],
|
|
852
|
+
function(stz, word, name)
|
|
853
|
+
local letterrepword;
|
|
854
|
+
# argument check: word should be an element of the unreduced semigroup
|
|
855
|
+
# (that way we can express it as a word on the current tietze generators)
|
|
856
|
+
if not word in UnreducedFpSemigroup(stz) then
|
|
857
|
+
TryNextMethod();
|
|
858
|
+
fi;
|
|
859
|
+
|
|
860
|
+
# if we do have an element of s, use the forward map to express it as a word
|
|
861
|
+
# on the current generators, then run the original implementation of Tietze 3.
|
|
862
|
+
letterrepword := SEMIGROUPS.StzExpandWord(
|
|
863
|
+
LetterRepAssocWord(UnderlyingElement(word)),
|
|
864
|
+
TietzeForwardMap(stz));
|
|
865
|
+
StzAddGenerator(stz, letterrepword, name);
|
|
866
|
+
end);
|
|
867
|
+
|
|
868
|
+
# Tietze Transformation 4: Remove generator
|
|
869
|
+
InstallMethod(StzRemoveGenerator,
|
|
870
|
+
"for an stz presentation and a positive integer",
|
|
871
|
+
[IsStzPresentation, IsPosInt],
|
|
872
|
+
function(stz, gen)
|
|
873
|
+
local found, index, i, rels;
|
|
874
|
+
# argument check 1: requested removal is potentially possible
|
|
875
|
+
if Length(GeneratorsOfStzPresentation(stz)) = 1 then
|
|
876
|
+
ErrorNoReturn("StzRemoveGenerator: cannot remove only remaining\n",
|
|
877
|
+
"generator \"",
|
|
878
|
+
GeneratorsOfStzPresentation(stz)[1],
|
|
879
|
+
"\"");
|
|
880
|
+
elif gen > Length(GeneratorsOfStzPresentation(stz)) then
|
|
881
|
+
ErrorNoReturn("StzRemoveGenerator: second argument <gen> must be no\n",
|
|
882
|
+
"greater than the total number of generators");
|
|
883
|
+
fi;
|
|
884
|
+
|
|
885
|
+
# argument check 2: generator can be expressed as a product of others.
|
|
886
|
+
# this check has to be repeated inside Tietze4, but we include it here to
|
|
887
|
+
# ensure that an incorrect input is clearly reported to the user.
|
|
888
|
+
found := false;
|
|
889
|
+
rels := RelationsOfStzPresentation(stz);
|
|
890
|
+
for i in [1 .. Length(rels)] do
|
|
891
|
+
if (rels[i][1] = [gen] and not gen in rels[i][2]) or
|
|
892
|
+
(rels[i][2] = [gen] and not gen in rels[i][1]) then
|
|
893
|
+
found := true;
|
|
894
|
+
index := i;
|
|
895
|
+
continue;
|
|
896
|
+
fi;
|
|
897
|
+
od;
|
|
898
|
+
if not found then
|
|
899
|
+
ErrorNoReturn("StzRemoveGenerator: there is no relation in first\n",
|
|
900
|
+
"argument <stz> expressing second argument <gen> as a\n",
|
|
901
|
+
"product of other generators");
|
|
902
|
+
fi;
|
|
903
|
+
|
|
904
|
+
# otherwise all good; apply internal Tietze 4 function (it will check
|
|
905
|
+
# whether any relation can actually express that generator as a combination
|
|
906
|
+
# of others)
|
|
907
|
+
SEMIGROUPS.TietzeTransformation4(stz, gen, index);
|
|
908
|
+
end);
|
|
909
|
+
|
|
910
|
+
InstallMethod(StzRemoveGenerator,
|
|
911
|
+
"for an stz presentation and a generator name",
|
|
912
|
+
[IsStzPresentation, IsString],
|
|
913
|
+
function(stz, genname)
|
|
914
|
+
local gen;
|
|
915
|
+
# find index of genname in stz gens
|
|
916
|
+
gen := Position(GeneratorsOfStzPresentation(stz), genname);
|
|
917
|
+
if gen = fail then
|
|
918
|
+
ErrorNoReturn("StzRemoveGenerator: second argument <gen> does not\n",
|
|
919
|
+
"correspond to a generator name in first argument <stz>");
|
|
920
|
+
else
|
|
921
|
+
StzRemoveGenerator(stz, gen);
|
|
922
|
+
fi;
|
|
923
|
+
end);
|
|
924
|
+
|
|
925
|
+
# Tietze transformation 4 with specified index (e.g. if there are several
|
|
926
|
+
# relations allowing the generator to be removed and the user wants a specific
|
|
927
|
+
# one)
|
|
928
|
+
InstallMethod(StzRemoveGenerator,
|
|
929
|
+
"for an stz presentation and two pos ints",
|
|
930
|
+
[IsStzPresentation, IsPosInt, IsPosInt],
|
|
931
|
+
function(stz, gen, index)
|
|
932
|
+
# first argument check: requested generator exists
|
|
933
|
+
if Length(GeneratorsOfStzPresentation(stz)) = 1 then
|
|
934
|
+
ErrorNoReturn("StzRemoveGenerator: cannot remove only remaining\n",
|
|
935
|
+
"generator \"",
|
|
936
|
+
GeneratorsOfStzPresentation(stz)[1],
|
|
937
|
+
"\"");
|
|
938
|
+
elif gen > Length(GeneratorsOfStzPresentation(stz)) then
|
|
939
|
+
ErrorNoReturn("StzRemoveGenerator: second argument <gen> must be no\n",
|
|
940
|
+
"greater than the total number of generators");
|
|
941
|
+
fi;
|
|
942
|
+
|
|
943
|
+
# second argument check: index exists
|
|
944
|
+
if index > Length(RelationsOfStzPresentation(stz)) then
|
|
945
|
+
ErrorNoReturn("StzRemoveGenerator: third argument <index> must be no\n",
|
|
946
|
+
"greater than the total number of relations in first\n",
|
|
947
|
+
"argument <stz>");
|
|
948
|
+
fi;
|
|
949
|
+
|
|
950
|
+
# third argument check: a reasonable relation number has been supplied
|
|
951
|
+
if (RelationsOfStzPresentation(stz)[index][1] <> [gen]
|
|
952
|
+
or gen in RelationsOfStzPresentation(stz)[index][2])
|
|
953
|
+
and (RelationsOfStzPresentation(stz)[index][2] <> [gen]
|
|
954
|
+
or gen in RelationsOfStzPresentation(stz)[index][1]) then
|
|
955
|
+
ErrorNoReturn("StzRemoveGenerator: third argument <index> does not point\n",
|
|
956
|
+
"to a relation expressing second argument <gen> as a\n",
|
|
957
|
+
"combination of other generators in first argument <stz>");
|
|
958
|
+
fi;
|
|
959
|
+
|
|
960
|
+
# if we made it this far then the substitution can be made
|
|
961
|
+
SEMIGROUPS.TietzeTransformation4(stz, gen, index);
|
|
962
|
+
end);
|
|
963
|
+
|
|
964
|
+
InstallMethod(StzRemoveGenerator,
|
|
965
|
+
"for an stz presentation, a generator name and a pos int",
|
|
966
|
+
[IsStzPresentation, IsString, IsPosInt],
|
|
967
|
+
function(stz, genname, index)
|
|
968
|
+
local gen;
|
|
969
|
+
# find index of genname in stz gens
|
|
970
|
+
gen := Position(GeneratorsOfStzPresentation(stz), genname);
|
|
971
|
+
if gen = fail then
|
|
972
|
+
ErrorNoReturn("StzRemoveGenerator: second argument <gen> does not\n",
|
|
973
|
+
"correspond to a generator name in first argument <stz>");
|
|
974
|
+
else
|
|
975
|
+
StzRemoveGenerator(stz, gen, index);
|
|
976
|
+
fi;
|
|
977
|
+
end);
|
|
978
|
+
|
|
979
|
+
# Tietze Transformation 1/2: substitute relation
|
|
980
|
+
InstallMethod(StzSubstituteRelation,
|
|
981
|
+
"for an stz presentation and two positive integers",
|
|
982
|
+
[IsStzPresentation, IsPosInt, IsPosInt],
|
|
983
|
+
function(stz, index, side)
|
|
984
|
+
local oldword, newword, new_rel, i;
|
|
985
|
+
# argument check
|
|
986
|
+
if index > Length(RelationsOfStzPresentation(stz)) then
|
|
987
|
+
ErrorNoReturn("StzSubstituteRelation: second argument <index> must be no\n",
|
|
988
|
+
"greater than the number of relations in first argument\n",
|
|
989
|
+
"<stz>");
|
|
990
|
+
fi;
|
|
991
|
+
if not side in [1, 2] then
|
|
992
|
+
ErrorNoReturn("StzSubstituteRelation: third argument <side> must be\n",
|
|
993
|
+
"either 1 or 2");
|
|
994
|
+
fi;
|
|
995
|
+
|
|
996
|
+
oldword := ShallowCopy(RelationsOfStzPresentation(stz)[index][side]);
|
|
997
|
+
newword := ShallowCopy(RelationsOfStzPresentation(stz)[index][[2, 1][side]]);
|
|
998
|
+
|
|
999
|
+
# Push relations onto the end of the stack of relations, each time replacing
|
|
1000
|
+
# the relation at the front by that relation, with oldword -> newword.
|
|
1001
|
+
# Each time, immediately delete the replaced relation at the front of the
|
|
1002
|
+
# stack, and do this as many times as there are relations, so that order
|
|
1003
|
+
# is preserved.
|
|
1004
|
+
# Special case for relation number <index> itself: it should not be changed.
|
|
1005
|
+
for i in [1 .. Length(RelationsOfStzPresentation(stz))] do
|
|
1006
|
+
if i = index then
|
|
1007
|
+
new_rel := [oldword, newword];
|
|
1008
|
+
else
|
|
1009
|
+
new_rel := List(stz!.RelationsOfStzPresentation[1],
|
|
1010
|
+
x -> SEMIGROUPS.StzReplaceSubwordRel(x,
|
|
1011
|
+
oldword,
|
|
1012
|
+
newword));
|
|
1013
|
+
fi;
|
|
1014
|
+
SEMIGROUPS.TietzeTransformation1(stz, new_rel);
|
|
1015
|
+
SEMIGROUPS.TietzeTransformation2(stz, 1);
|
|
1016
|
+
od;
|
|
1017
|
+
end);
|
|
1018
|
+
|
|
1019
|
+
########################################################################
|
|
1020
|
+
# 5. Internal helper functions for word/relation manipulation etc.
|
|
1021
|
+
########################################################################
|
|
1022
|
+
|
|
1023
|
+
SEMIGROUPS.StzReplaceSubword := function(rels, subword, newWord)
|
|
1024
|
+
local newRels, rel1, rel2, i;
|
|
1025
|
+
|
|
1026
|
+
newRels := List([1 .. Length(rels)], x -> []);
|
|
1027
|
+
for i in [1 .. Length(rels)] do
|
|
1028
|
+
rel1 := SEMIGROUPS.StzReplaceSubwordRel(rels[i][1], subword, newWord);
|
|
1029
|
+
rel2 := SEMIGROUPS.StzReplaceSubwordRel(rels[i][2], subword, newWord);
|
|
1030
|
+
newRels[i] := [rel1, rel2];
|
|
1031
|
+
od;
|
|
1032
|
+
return newRels;
|
|
1033
|
+
end;
|
|
1034
|
+
|
|
1035
|
+
SEMIGROUPS.StzReplaceSubwordRel := function(word, subword, newWord)
|
|
1036
|
+
local out, k, l, i;
|
|
1037
|
+
# Searches a single LetterRepAssocWord list and replaces instances of
|
|
1038
|
+
# subword with newWord.
|
|
1039
|
+
|
|
1040
|
+
# build word up as we read through the old word.
|
|
1041
|
+
out := [];
|
|
1042
|
+
k := Length(subword);
|
|
1043
|
+
l := Length(word);
|
|
1044
|
+
i := 1; # current index that we are looking at when trying to see subword
|
|
1045
|
+
while i <= l do
|
|
1046
|
+
if word{[i .. Minimum(i + k - 1, l)]} = subword then
|
|
1047
|
+
# in this, case the word starting at i needs to be substituted out.
|
|
1048
|
+
# (the minimum is there to make sure we don't fall off the end of word)
|
|
1049
|
+
Append(out, newWord);
|
|
1050
|
+
# jump to end of occurrence
|
|
1051
|
+
i := i + k;
|
|
1052
|
+
else
|
|
1053
|
+
# move over by one and append the original letter, since the word is not
|
|
1054
|
+
# seen here.
|
|
1055
|
+
Add(out, word[i]);
|
|
1056
|
+
i := i + 1;
|
|
1057
|
+
fi;
|
|
1058
|
+
od;
|
|
1059
|
+
return out;
|
|
1060
|
+
end;
|
|
1061
|
+
|
|
1062
|
+
# takes in a letterrep word and replaces every letter with its expression in
|
|
1063
|
+
# dict.
|
|
1064
|
+
# NOTE: does not check arguments. Assumes in good faith that every integer
|
|
1065
|
+
# in word has an entry in the list <dict>.
|
|
1066
|
+
SEMIGROUPS.StzExpandWord := function(word, dict)
|
|
1067
|
+
local out, letter;
|
|
1068
|
+
out := [];
|
|
1069
|
+
for letter in word do
|
|
1070
|
+
Append(out, dict[letter]);
|
|
1071
|
+
od;
|
|
1072
|
+
return out;
|
|
1073
|
+
end;
|
|
1074
|
+
|
|
1075
|
+
SEMIGROUPS.NewGeneratorName := function(names_immut)
|
|
1076
|
+
local alph, Alph, na, nA, names_prefx, names_suffx, int_positions, prefixes,
|
|
1077
|
+
prefixes_collected, p, ints, i, name, names;
|
|
1078
|
+
names := [];
|
|
1079
|
+
for name in names_immut do
|
|
1080
|
+
Add(names, ShallowCopy(name));
|
|
1081
|
+
od;
|
|
1082
|
+
|
|
1083
|
+
# useful helper variables
|
|
1084
|
+
alph := "abcdefghijklmnopqrstuvwxyz";
|
|
1085
|
+
Alph := "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
1086
|
+
|
|
1087
|
+
# SPECIAL CASE 0: empty list
|
|
1088
|
+
if IsEmpty(names) then
|
|
1089
|
+
return "a";
|
|
1090
|
+
fi;
|
|
1091
|
+
|
|
1092
|
+
# SPECIAL CASE 1: only one generator
|
|
1093
|
+
if Length(names) = 1 then
|
|
1094
|
+
if Length(names[1]) = 1 then
|
|
1095
|
+
if names[1][1] in Alph then
|
|
1096
|
+
return [First(Alph, x -> not [x] in names)];
|
|
1097
|
+
elif names[1][1] in alph then
|
|
1098
|
+
return [First(alph, x -> not [x] in names)];
|
|
1099
|
+
else
|
|
1100
|
+
return "a";
|
|
1101
|
+
fi;
|
|
1102
|
+
else
|
|
1103
|
+
return "a";
|
|
1104
|
+
fi;
|
|
1105
|
+
fi;
|
|
1106
|
+
|
|
1107
|
+
# SPECIAL CASE 2: single letter names are present. Add an unused letter
|
|
1108
|
+
# with the most common capitalisation
|
|
1109
|
+
na := Length(Filtered(names, x -> Length(x) = 1 and x[1] in alph));
|
|
1110
|
+
nA := Length(Filtered(names, x -> Length(x) = 1 and x[1] in Alph));
|
|
1111
|
+
if 2 <= na and na < 26 then
|
|
1112
|
+
if na <= nA and nA < 26 then
|
|
1113
|
+
return [First(Alph, x -> not [x] in names)];
|
|
1114
|
+
else
|
|
1115
|
+
return [First(alph, x -> not [x] in names)];
|
|
1116
|
+
fi;
|
|
1117
|
+
elif 2 <= nA and nA < 26 then
|
|
1118
|
+
return [First(Alph, x -> not [x] in names)];
|
|
1119
|
+
fi;
|
|
1120
|
+
|
|
1121
|
+
# SPECIAL CASE 3: there are names like s1, s3, s23, etc or x12, etc
|
|
1122
|
+
names_prefx := [];
|
|
1123
|
+
names_suffx := [];
|
|
1124
|
+
for name in names do
|
|
1125
|
+
Add(names_prefx, [name[1]]);
|
|
1126
|
+
Add(names_suffx, name{[2 .. Length(name)]});
|
|
1127
|
+
od;
|
|
1128
|
+
int_positions := PositionsProperty(names_suffx, x -> Int(x) <> fail
|
|
1129
|
+
and x <> ""
|
|
1130
|
+
and x[1] <> '-');
|
|
1131
|
+
if Length(int_positions) >= 2 then
|
|
1132
|
+
prefixes := names_prefx{int_positions};
|
|
1133
|
+
prefixes_collected := Collected(prefixes);
|
|
1134
|
+
# look for highest frequency in collected list
|
|
1135
|
+
p := prefixes_collected[PositionMaximum(prefixes_collected, x -> x[2])][1];
|
|
1136
|
+
# find maximum suffix int, even amongst those with prefix not p
|
|
1137
|
+
ints := List(names_suffx{int_positions}, Int);
|
|
1138
|
+
i := Maximum(ints) + 1;
|
|
1139
|
+
return Concatenation(p, String(i));
|
|
1140
|
+
fi;
|
|
1141
|
+
|
|
1142
|
+
# if none of the special cases are covered, just try s1, s2,... until good
|
|
1143
|
+
for i in [1 .. Length(names) + 1] do
|
|
1144
|
+
if not Concatenation("s", String(i)) in names then
|
|
1145
|
+
return Concatenation("s", String(i));
|
|
1146
|
+
fi;
|
|
1147
|
+
od;
|
|
1148
|
+
end;
|
|
1149
|
+
|
|
1150
|
+
# Counts the number of times a subword appears in the relations of an stz
|
|
1151
|
+
# presentation, ensuring that the subwords do not overlap
|
|
1152
|
+
# (Eg, for relations [[1,1,1,1],[1,1]], the subword [1,1] would return 3 and not
|
|
1153
|
+
# 4)
|
|
1154
|
+
SEMIGROUPS.StzCountRelationSubwords := function(stz, subWord)
|
|
1155
|
+
local count, relSide, rel, rels, pos, len, relSideCopy;
|
|
1156
|
+
rels := RelationsOfStzPresentation(stz);
|
|
1157
|
+
len := Length(subWord);
|
|
1158
|
+
count := 0;
|
|
1159
|
+
for rel in rels do
|
|
1160
|
+
for relSide in rel do
|
|
1161
|
+
pos := PositionSublist(relSide, subWord);
|
|
1162
|
+
relSideCopy := ShallowCopy(relSide);
|
|
1163
|
+
while pos <> fail do
|
|
1164
|
+
count := count + 1;
|
|
1165
|
+
relSideCopy := List([(pos + len) .. Length(relSideCopy)],
|
|
1166
|
+
x -> relSideCopy[x]);
|
|
1167
|
+
pos := PositionSublist(relSideCopy, subWord);
|
|
1168
|
+
od;
|
|
1169
|
+
od;
|
|
1170
|
+
od;
|
|
1171
|
+
return count;
|
|
1172
|
+
end;
|
|
1173
|
+
|
|
1174
|
+
# Converts an Stz presentation into an fp semigroup.
|
|
1175
|
+
SEMIGROUPS.StzConvertObjToFpSemigroup := function(stz)
|
|
1176
|
+
local F, rels, gens;
|
|
1177
|
+
F := FreeSemigroup(stz!.GeneratorsOfStzPresentation);
|
|
1178
|
+
rels := RelationsOfStzPresentation(stz);
|
|
1179
|
+
gens := GeneratorsOfSemigroup(F);
|
|
1180
|
+
return F / List(rels, x -> List(x, y -> Product(List(y, z -> gens[z]))));
|
|
1181
|
+
end;
|
|
1182
|
+
|
|
1183
|
+
########################################################################
|
|
1184
|
+
# 6. Internal auto-checkers and appliers for presentation simplifying
|
|
1185
|
+
########################################################################
|
|
1186
|
+
|
|
1187
|
+
## Format to add a new reduction check:
|
|
1188
|
+
## StzCheck: function that takes an stz presentation as input and checks all
|
|
1189
|
+
## possible instances of the desired reduction, and outputs as a
|
|
1190
|
+
## record the least length of the possible reductions together with
|
|
1191
|
+
## the arguments required to achieve that length
|
|
1192
|
+
## StzApply: function that takes an stz presentation and the above record as
|
|
1193
|
+
## input and applies the arguments from the record to achieve the
|
|
1194
|
+
## desired reduction
|
|
1195
|
+
## Add the above two functions to the list results in StzSimplifyOnce as the
|
|
1196
|
+
## pair [StzApply, StzCheck(stz)]
|
|
1197
|
+
|
|
1198
|
+
SEMIGROUPS.StzFrequentSubwordCheck := function(stz)
|
|
1199
|
+
local best_gain, best_word, flat, count_occurrences, n, c, gain, word,
|
|
1200
|
+
pair, i, j;
|
|
1201
|
+
# SUPER INEFFICIENT (~n^3), do something about this eventually (@Reinis?)
|
|
1202
|
+
# Look at every subword, count how many times it appears, and see whether
|
|
1203
|
+
# introducing a new generator equal to a given subword would make the
|
|
1204
|
+
# whole presentation shorter
|
|
1205
|
+
best_gain := 0; # best reduction seen so far
|
|
1206
|
+
best_word := []; # word currently holding record
|
|
1207
|
+
|
|
1208
|
+
# flat list of words (don't care about which one is related to which)
|
|
1209
|
+
flat := [];
|
|
1210
|
+
for pair in stz!.RelationsOfStzPresentation do
|
|
1211
|
+
Append(flat, ShallowCopy(pair)); # TODO(later) might not need shallow copy
|
|
1212
|
+
od;
|
|
1213
|
+
|
|
1214
|
+
# function to count occurrences of subword in list of lists
|
|
1215
|
+
count_occurrences := function(list, subword)
|
|
1216
|
+
local count, k, l, i, word;
|
|
1217
|
+
count := 0;
|
|
1218
|
+
k := Length(subword);
|
|
1219
|
+
for word in list do
|
|
1220
|
+
l := Length(word);
|
|
1221
|
+
i := 1; # index at which to start counting
|
|
1222
|
+
while i <= l - k + 1 do
|
|
1223
|
+
if word{[i .. i + k - 1]} = subword then
|
|
1224
|
+
count := count + 1;
|
|
1225
|
+
# jump to end of occurrence
|
|
1226
|
+
i := i + k;
|
|
1227
|
+
else
|
|
1228
|
+
# move over by one
|
|
1229
|
+
i := i + 1;
|
|
1230
|
+
fi;
|
|
1231
|
+
od;
|
|
1232
|
+
od;
|
|
1233
|
+
return count;
|
|
1234
|
+
end;
|
|
1235
|
+
|
|
1236
|
+
# now check for every subword, how many times it appears
|
|
1237
|
+
for word in flat do
|
|
1238
|
+
# N.B. ASSUMES WORDS NON-EMPTY
|
|
1239
|
+
n := Length(word);
|
|
1240
|
+
for i in [1 .. n - 1] do
|
|
1241
|
+
for j in [i + 1 .. n] do
|
|
1242
|
+
c := count_occurrences(flat, word{[i .. j]});
|
|
1243
|
+
# now calculate what a gain that would be:
|
|
1244
|
+
# subbing out every instance of word{[i .. j]} for a word of length 1
|
|
1245
|
+
# makes us gain j - i characters per substitution
|
|
1246
|
+
# BUT, we also have a new generator cost of 1
|
|
1247
|
+
# AND a new relation cost of 3 + j - i
|
|
1248
|
+
gain := (c - 1) * (j - i) - 3;
|
|
1249
|
+
if gain > best_gain then
|
|
1250
|
+
best_gain := gain;
|
|
1251
|
+
best_word := word{[i .. j]};
|
|
1252
|
+
fi;
|
|
1253
|
+
od;
|
|
1254
|
+
od;
|
|
1255
|
+
od;
|
|
1256
|
+
return rec(reduction := Length(stz) - best_gain,
|
|
1257
|
+
word := best_word);
|
|
1258
|
+
end;
|
|
1259
|
+
|
|
1260
|
+
SEMIGROUPS.StzFrequentSubwordApply := function(stz, metadata)
|
|
1261
|
+
local word, rels, n, gens, k, shortened_rels, new_rel, i, str, f, aWord;
|
|
1262
|
+
|
|
1263
|
+
# have received instruction to sub out metadata.word for something shorter.
|
|
1264
|
+
word := metadata.word;
|
|
1265
|
+
rels := ShallowCopy(RelationsOfStzPresentation(stz));
|
|
1266
|
+
n := Length(rels);
|
|
1267
|
+
gens := ShallowCopy(GeneratorsOfStzPresentation(stz));
|
|
1268
|
+
k := Length(gens);
|
|
1269
|
+
|
|
1270
|
+
# Build message
|
|
1271
|
+
str := "<Creating new generator to replace instances of word: ";
|
|
1272
|
+
f := FreeSemigroup(gens);
|
|
1273
|
+
aWord := AssocWordByLetterRep(FamilyObj(f.1), metadata.word);
|
|
1274
|
+
Append(str, PrintString(aWord));
|
|
1275
|
+
Append(str, ">");
|
|
1276
|
+
Info(InfoFpSemigroup, 2, PRINT_STRINGIFY(str));
|
|
1277
|
+
|
|
1278
|
+
# first, add new generator.
|
|
1279
|
+
SEMIGROUPS.TietzeTransformation3(stz, word, fail);
|
|
1280
|
+
|
|
1281
|
+
# then, go through and add loads of relations which are the old ones but
|
|
1282
|
+
# with the old word subbed out.
|
|
1283
|
+
shortened_rels := SEMIGROUPS.StzReplaceSubword(rels, word, [k + 1]);
|
|
1284
|
+
for new_rel in shortened_rels do
|
|
1285
|
+
SEMIGROUPS.TietzeTransformation1(stz, new_rel);
|
|
1286
|
+
od;
|
|
1287
|
+
|
|
1288
|
+
# finally, remove the original relations.
|
|
1289
|
+
for i in [1 .. n] do
|
|
1290
|
+
SEMIGROUPS.TietzeTransformation2(stz, 1);
|
|
1291
|
+
od;
|
|
1292
|
+
return;
|
|
1293
|
+
end;
|
|
1294
|
+
|
|
1295
|
+
# Checks each relation in the stz presentation in turn and determines if
|
|
1296
|
+
# replacing the longer side by the shorter side reduces the length of the
|
|
1297
|
+
# presentation
|
|
1298
|
+
SEMIGROUPS.StzRelsSubCheck := function(stz)
|
|
1299
|
+
local rels, currentMin, currentRel, tempRel, len, relLenDiff, numInstances,
|
|
1300
|
+
newLen, i;
|
|
1301
|
+
rels := RelationsOfStzPresentation(stz);
|
|
1302
|
+
currentMin := Length(stz);
|
|
1303
|
+
currentRel := 0;
|
|
1304
|
+
for i in [1 .. Length(rels)] do
|
|
1305
|
+
tempRel := ShallowCopy(rels[i]);
|
|
1306
|
+
SortBy(tempRel, Length);
|
|
1307
|
+
len := Length(stz);
|
|
1308
|
+
relLenDiff := Length(tempRel[2]) - Length(tempRel[1]);
|
|
1309
|
+
numInstances := SEMIGROUPS.StzCountRelationSubwords(stz, tempRel[2]) - 1;
|
|
1310
|
+
newLen := len - numInstances * relLenDiff;
|
|
1311
|
+
if newLen < currentMin then
|
|
1312
|
+
currentMin := newLen;
|
|
1313
|
+
currentRel := i;
|
|
1314
|
+
fi;
|
|
1315
|
+
od;
|
|
1316
|
+
return rec(reduction := currentMin,
|
|
1317
|
+
argument := currentRel);
|
|
1318
|
+
end;
|
|
1319
|
+
|
|
1320
|
+
# Checks each relation of the stz presentation to see if any are of the form
|
|
1321
|
+
# a = w, where a is a generator and w is a word not containing a, then
|
|
1322
|
+
# determines the length if the generator and relation were removed
|
|
1323
|
+
SEMIGROUPS.StzRedundantGeneratorCheck := function(stz)
|
|
1324
|
+
local rel, rels, numInstances, relPos, tempPositions, r, out, redLen,
|
|
1325
|
+
genToRemove, wordToReplace, foundRedundant, currentMin, currentGen,
|
|
1326
|
+
currentRel;
|
|
1327
|
+
rels := RelationsOfStzPresentation(stz);
|
|
1328
|
+
out := [];
|
|
1329
|
+
currentMin := Length(stz);
|
|
1330
|
+
currentGen := 0;
|
|
1331
|
+
currentRel := 0;
|
|
1332
|
+
for rel in rels do
|
|
1333
|
+
foundRedundant := false;
|
|
1334
|
+
if Length(rel[1]) = 1 and Length(rel[2]) = 1 and rel[1] <> rel[2] then
|
|
1335
|
+
genToRemove := rel[1][1];
|
|
1336
|
+
wordToReplace := rel[2];
|
|
1337
|
+
Append(out, [Length(stz) - 3]);
|
|
1338
|
+
if Length(stz) - 3 < currentMin then
|
|
1339
|
+
currentMin := Length(stz) - 3;
|
|
1340
|
+
currentGen := genToRemove;
|
|
1341
|
+
currentRel := Position(rels, rel);
|
|
1342
|
+
fi;
|
|
1343
|
+
continue;
|
|
1344
|
+
elif Length(rel[1]) = 1 and Length(rel[2]) > 1 and
|
|
1345
|
+
(not (rel[1][1] in rel[2])) then
|
|
1346
|
+
genToRemove := rel[1][1];
|
|
1347
|
+
wordToReplace := rel[2];
|
|
1348
|
+
foundRedundant := true;
|
|
1349
|
+
elif Length(rel[2]) = 1 and Length(rel[1]) > 1 and
|
|
1350
|
+
(not (rel[2][1] in rel[1])) then
|
|
1351
|
+
genToRemove := rel[2][1];
|
|
1352
|
+
wordToReplace := rel[1];
|
|
1353
|
+
foundRedundant := true;
|
|
1354
|
+
fi;
|
|
1355
|
+
if foundRedundant then
|
|
1356
|
+
relPos := Position(rels, rel);
|
|
1357
|
+
numInstances := 0;
|
|
1358
|
+
for r in Concatenation([1 .. relPos - 1], [relPos + 1 .. Length(rels)]) do
|
|
1359
|
+
tempPositions := Length(Positions(Concatenation(rels[r][1], rels[r][2]),
|
|
1360
|
+
genToRemove));
|
|
1361
|
+
numInstances := numInstances + tempPositions;
|
|
1362
|
+
od;
|
|
1363
|
+
redLen := Length(stz) + (numInstances * (Length(wordToReplace) - 1)) -
|
|
1364
|
+
2 - Length(wordToReplace);
|
|
1365
|
+
if redLen < currentMin then
|
|
1366
|
+
currentMin := redLen;
|
|
1367
|
+
currentGen := genToRemove;
|
|
1368
|
+
currentRel := Position(rels, rel);
|
|
1369
|
+
fi;
|
|
1370
|
+
fi;
|
|
1371
|
+
od;
|
|
1372
|
+
return rec(reduction := currentMin,
|
|
1373
|
+
argument := currentGen,
|
|
1374
|
+
infoRel := currentRel);
|
|
1375
|
+
end;
|
|
1376
|
+
|
|
1377
|
+
# Checks each relation to determine if it is a direct duplicate of another
|
|
1378
|
+
# (ie does not check equivalence in terms of other relations, just whether they
|
|
1379
|
+
# are literally the same relation)
|
|
1380
|
+
SEMIGROUPS.StzDuplicateRelsCheck := function(stz)
|
|
1381
|
+
local rel, rels, i, tempRel, j, currentMin, currentRel, len;
|
|
1382
|
+
rels := RelationsOfStzPresentation(stz);
|
|
1383
|
+
currentMin := Length(stz);
|
|
1384
|
+
currentRel := 0;
|
|
1385
|
+
if Length(rels) < 2 then
|
|
1386
|
+
return rec(reduction := Length(stz),
|
|
1387
|
+
argument := 1);
|
|
1388
|
+
else
|
|
1389
|
+
for j in [1 .. Length(rels)] do
|
|
1390
|
+
rel := rels[j];
|
|
1391
|
+
for i in Concatenation([1 .. j - 1],
|
|
1392
|
+
[j + 1 .. Length(rels)]) do
|
|
1393
|
+
tempRel := rels[i];
|
|
1394
|
+
if (tempRel[1] = rel[1] and tempRel[2] = rel[2]) or
|
|
1395
|
+
(tempRel[1] = rel[2] and tempRel[2] = rel[1]) then
|
|
1396
|
+
len := Length(stz) - Length(rel[1]) - Length(rel[2]);
|
|
1397
|
+
if len < currentMin then
|
|
1398
|
+
currentMin := len;
|
|
1399
|
+
currentRel := j;
|
|
1400
|
+
fi;
|
|
1401
|
+
fi;
|
|
1402
|
+
od;
|
|
1403
|
+
od;
|
|
1404
|
+
return rec(reduction := currentMin,
|
|
1405
|
+
argument := currentRel);
|
|
1406
|
+
fi;
|
|
1407
|
+
end;
|
|
1408
|
+
|
|
1409
|
+
# Checks each relation to determine if any are of the form w = w, where w is a
|
|
1410
|
+
# word over the generators
|
|
1411
|
+
SEMIGROUPS.StzTrivialRelationCheck := function(stz)
|
|
1412
|
+
local rels, len, i, currentMin, currentRel, newLen;
|
|
1413
|
+
rels := RelationsOfStzPresentation(stz);
|
|
1414
|
+
len := Length(stz);
|
|
1415
|
+
currentMin := len;
|
|
1416
|
+
currentRel := 0;
|
|
1417
|
+
for i in [1 .. Length(rels)] do
|
|
1418
|
+
if rels[i][1] = rels[i][2] then
|
|
1419
|
+
newLen := len - Length(rels[i][1]) - Length(rels[i][2]);
|
|
1420
|
+
if newLen < currentMin then
|
|
1421
|
+
currentMin := newLen;
|
|
1422
|
+
currentRel := i;
|
|
1423
|
+
fi;
|
|
1424
|
+
fi;
|
|
1425
|
+
od;
|
|
1426
|
+
return rec(reduction := currentMin,
|
|
1427
|
+
argument := currentRel);
|
|
1428
|
+
end;
|
|
1429
|
+
|
|
1430
|
+
# Removes a trivial relation
|
|
1431
|
+
SEMIGROUPS.StzTrivialRelationApply := function(stz, args)
|
|
1432
|
+
local str;
|
|
1433
|
+
str := "<Removing trivial relation: ";
|
|
1434
|
+
Append(str, SEMIGROUPS.StzRelationDisplayString(stz, args.argument));
|
|
1435
|
+
Append(str, ">");
|
|
1436
|
+
Info(InfoFpSemigroup, 2, PRINT_STRINGIFY(str));
|
|
1437
|
+
SEMIGROUPS.TietzeTransformation2(stz, args.argument);
|
|
1438
|
+
end;
|
|
1439
|
+
|
|
1440
|
+
# Removes a duplicated relation
|
|
1441
|
+
SEMIGROUPS.StzDuplicateRelsApply := function(stz, args)
|
|
1442
|
+
local str;
|
|
1443
|
+
str := "<Removing duplicate relation: ";
|
|
1444
|
+
Append(str, SEMIGROUPS.StzRelationDisplayString(stz, args.argument));
|
|
1445
|
+
Append(str, ">");
|
|
1446
|
+
Info(InfoFpSemigroup, 2, PRINT_STRINGIFY(str));
|
|
1447
|
+
SEMIGROUPS.TietzeTransformation2(stz, args.argument);
|
|
1448
|
+
end;
|
|
1449
|
+
|
|
1450
|
+
# Removes a redundant generator
|
|
1451
|
+
SEMIGROUPS.StzGensRedundantApply := function(stz, args)
|
|
1452
|
+
local str;
|
|
1453
|
+
str := "<Removing redundant generator ";
|
|
1454
|
+
Append(str, GeneratorsOfStzPresentation(stz)[args.argument]);
|
|
1455
|
+
Append(str, " using relation : ");
|
|
1456
|
+
Append(str, SEMIGROUPS.StzRelationDisplayString(stz, args.infoRel));
|
|
1457
|
+
Append(str, ">");
|
|
1458
|
+
Info(InfoFpSemigroup, 2, PRINT_STRINGIFY(str));
|
|
1459
|
+
SEMIGROUPS.TietzeTransformation4(stz, args.argument, args.infoRel);
|
|
1460
|
+
end;
|
|
1461
|
+
|
|
1462
|
+
# Replaces all instances of one side of a relation with the other inside each
|
|
1463
|
+
# other relation
|
|
1464
|
+
SEMIGROUPS.StzRelsSubApply := function(stz, args)
|
|
1465
|
+
local str, relIndex, rels, rel, subword, replaceWord, containsRel, newRel, i,
|
|
1466
|
+
j;
|
|
1467
|
+
str := "<Replacing all instances in other relations of relation: ";
|
|
1468
|
+
Append(str, SEMIGROUPS.StzRelationDisplayString(stz, args.argument));
|
|
1469
|
+
Append(str, ">");
|
|
1470
|
+
Info(InfoFpSemigroup, 2, PRINT_STRINGIFY(str));
|
|
1471
|
+
|
|
1472
|
+
relIndex := args.argument;
|
|
1473
|
+
rels := RelationsOfStzPresentation(stz);
|
|
1474
|
+
rel := ShallowCopy(rels[relIndex]);
|
|
1475
|
+
SortBy(rel, Length);
|
|
1476
|
+
# TODO(later) line above: potential edge cases where we are not substituting
|
|
1477
|
+
# the longer for the shorter, but rather two words of equal length? I guess
|
|
1478
|
+
# not, since the checker function would only suggest this applier function if
|
|
1479
|
+
# there was an actual reduction? In that case, careful to use correctly
|
|
1480
|
+
|
|
1481
|
+
# record words to sub out (one we are searching for) and to replace with
|
|
1482
|
+
subword := rel[2];
|
|
1483
|
+
replaceWord := rel[1];
|
|
1484
|
+
|
|
1485
|
+
# keep track of relation indices where we substituted
|
|
1486
|
+
containsRel := [];
|
|
1487
|
+
for i in [1 .. Length(rels)] do
|
|
1488
|
+
if i <> relIndex and
|
|
1489
|
+
(PositionSublist(rels[i][1], subword) <> fail or
|
|
1490
|
+
PositionSublist(rels[i][2], subword) <> fail) then
|
|
1491
|
+
Add(containsRel, i);
|
|
1492
|
+
fi;
|
|
1493
|
+
od;
|
|
1494
|
+
|
|
1495
|
+
for i in containsRel do
|
|
1496
|
+
newRel := List([1 .. 2], x -> ShallowCopy(rels[i][x]));
|
|
1497
|
+
newRel := List(newRel, x -> SEMIGROUPS.StzReplaceSubwordRel(x, subword,
|
|
1498
|
+
replaceWord));
|
|
1499
|
+
SEMIGROUPS.TietzeTransformation1(stz, newRel);
|
|
1500
|
+
od;
|
|
1501
|
+
for j in [1 .. Length(containsRel)] do
|
|
1502
|
+
SEMIGROUPS.TietzeTransformation2(stz, containsRel[j]);
|
|
1503
|
+
containsRel := containsRel - 1;
|
|
1504
|
+
od;
|
|
1505
|
+
end;
|
|
1506
|
+
|
|
1507
|
+
########################################################################
|
|
1508
|
+
# 7. SimplifyPresentation etc.
|
|
1509
|
+
########################################################################
|
|
1510
|
+
|
|
1511
|
+
InstallMethod(StzSimplifyOnce,
|
|
1512
|
+
[IsStzPresentation],
|
|
1513
|
+
function(stz)
|
|
1514
|
+
local rels, results, len, mins, result, func, args;
|
|
1515
|
+
rels := RelationsOfStzPresentation(stz);
|
|
1516
|
+
if IsEmpty(rels) then
|
|
1517
|
+
return false;
|
|
1518
|
+
else
|
|
1519
|
+
results := [[SEMIGROUPS.StzGensRedundantApply,
|
|
1520
|
+
SEMIGROUPS.StzRedundantGeneratorCheck(stz)],
|
|
1521
|
+
[SEMIGROUPS.StzDuplicateRelsApply,
|
|
1522
|
+
SEMIGROUPS.StzDuplicateRelsCheck(stz)],
|
|
1523
|
+
[SEMIGROUPS.StzRelsSubApply,
|
|
1524
|
+
SEMIGROUPS.StzRelsSubCheck(stz)],
|
|
1525
|
+
[SEMIGROUPS.StzFrequentSubwordApply,
|
|
1526
|
+
SEMIGROUPS.StzFrequentSubwordCheck(stz)],
|
|
1527
|
+
[SEMIGROUPS.StzTrivialRelationApply,
|
|
1528
|
+
SEMIGROUPS.StzTrivialRelationCheck(stz)]];
|
|
1529
|
+
len := Length(stz);
|
|
1530
|
+
mins := List(results, x -> x[2].reduction);
|
|
1531
|
+
if Minimum(mins) < len then
|
|
1532
|
+
result := results[Position(mins, Minimum(mins))];
|
|
1533
|
+
func := result[1];
|
|
1534
|
+
args := result[2];
|
|
1535
|
+
func(stz, args);
|
|
1536
|
+
return true;
|
|
1537
|
+
fi;
|
|
1538
|
+
return false;
|
|
1539
|
+
fi;
|
|
1540
|
+
end);
|
|
1541
|
+
|
|
1542
|
+
InstallMethod(StzSimplifyPresentation,
|
|
1543
|
+
[IsStzPresentation],
|
|
1544
|
+
function(stz)
|
|
1545
|
+
local transformApplied;
|
|
1546
|
+
transformApplied := true;
|
|
1547
|
+
Info(InfoFpSemigroup, 2, "Applying StzSimplifyPresentation...");
|
|
1548
|
+
Info(InfoFpSemigroup, 2, "StzSimplifyPresentation is verbose by default. ",
|
|
1549
|
+
"Use SetInfoLevel(InfoFpSemigroup, 1) to hide");
|
|
1550
|
+
Info(InfoFpSemigroup, 2, "output while maintaining ability to use ",
|
|
1551
|
+
"StzPrintRelations, StzPrintGenerators, etc.");
|
|
1552
|
+
Info(InfoFpSemigroup, 2, Concatenation("Current: ", ViewString(stz)));
|
|
1553
|
+
while transformApplied do
|
|
1554
|
+
transformApplied := StzSimplifyOnce(stz);
|
|
1555
|
+
if transformApplied then
|
|
1556
|
+
Info(InfoFpSemigroup, 2, Concatenation("Current: ", ViewString(stz)));
|
|
1557
|
+
fi;
|
|
1558
|
+
od;
|
|
1559
|
+
end);
|
|
1560
|
+
|
|
1561
|
+
InstallMethod(SimplifiedFpSemigroup,
|
|
1562
|
+
[IsFpSemigroup],
|
|
1563
|
+
function(S)
|
|
1564
|
+
local T, map;
|
|
1565
|
+
map := SimplifyFpSemigroup(S);
|
|
1566
|
+
T := Range(map);
|
|
1567
|
+
SetUnreducedFpSemigroup(T, S);
|
|
1568
|
+
SetFpTietzeIsomorphism(T, map);
|
|
1569
|
+
return T;
|
|
1570
|
+
end);
|
|
1571
|
+
|
|
1572
|
+
InstallMethod(SimplifyFpSemigroup, "for an f.p. semigroup", [IsFpSemigroup],
|
|
1573
|
+
function(S)
|
|
1574
|
+
local stz;
|
|
1575
|
+
stz := StzPresentation(S);
|
|
1576
|
+
StzSimplifyPresentation(stz);
|
|
1577
|
+
return StzIsomorphism(stz);
|
|
1578
|
+
end);
|