passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.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.
- passagemath_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
|
@@ -0,0 +1,1792 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Data structures
|
|
4
|
+
|
|
5
|
+
This module implements basic data structures essential to the rest of the
|
|
6
|
+
partn_ref module.
|
|
7
|
+
|
|
8
|
+
REFERENCES:
|
|
9
|
+
|
|
10
|
+
[1] McKay, Brendan D. Practical Graph Isomorphism. Congressus Numerantium,
|
|
11
|
+
Vol. 30 (1981), pp. 45-87.
|
|
12
|
+
[2] Fredman, M. and Saks, M. The cell probe complexity of dynamic data
|
|
13
|
+
structures. Proceedings of the Twenty-First Annual ACM Symposium on
|
|
14
|
+
Theory of Computing, pp. 345–354. May 1989.
|
|
15
|
+
[3] Seress, Akos. Permutation Group Algorithms. Cambridge University Press,
|
|
16
|
+
2003.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
#*****************************************************************************
|
|
20
|
+
# Copyright (C) 2006 - 2011 Robert L. Miller <rlmillster@gmail.com>
|
|
21
|
+
#
|
|
22
|
+
# This program is free software: you can redistribute it and/or modify
|
|
23
|
+
# it under the terms of the GNU General Public License as published by
|
|
24
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
25
|
+
# (at your option) any later version.
|
|
26
|
+
# https://www.gnu.org/licenses/
|
|
27
|
+
#*****************************************************************************
|
|
28
|
+
|
|
29
|
+
from libc.math cimport log, ceil
|
|
30
|
+
from libc.string cimport memcpy, memset
|
|
31
|
+
from libc.stdlib cimport rand
|
|
32
|
+
from cysignals.memory cimport sig_malloc, sig_calloc, sig_realloc, sig_free
|
|
33
|
+
|
|
34
|
+
from sage.data_structures.bitset_base cimport *
|
|
35
|
+
from sage.rings.integer cimport Integer
|
|
36
|
+
# from sage.libs.flint.ulong_extras cimport n_is_prime
|
|
37
|
+
# -- avoid modularization obstruction -- function is only used for a doctest helper
|
|
38
|
+
from sage.arith.misc import is_prime as n_is_prime
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# OrbitPartition (OP)
|
|
42
|
+
|
|
43
|
+
cdef inline OrbitPartition *OP_new(int n) noexcept:
|
|
44
|
+
"""
|
|
45
|
+
Allocate and return a pointer to a new OrbitPartition of degree n. Return a
|
|
46
|
+
null pointer in the case of an allocation failure.
|
|
47
|
+
"""
|
|
48
|
+
cdef OrbitPartition *OP = <OrbitPartition *> \
|
|
49
|
+
sig_malloc(sizeof(OrbitPartition))
|
|
50
|
+
if OP is NULL:
|
|
51
|
+
return NULL
|
|
52
|
+
OP.parent = <int *> sig_malloc(n * sizeof(int))
|
|
53
|
+
OP.rank = <int *> sig_malloc(n * sizeof(int))
|
|
54
|
+
OP.mcr = <int *> sig_malloc(n * sizeof(int))
|
|
55
|
+
OP.size = <int *> sig_malloc(n * sizeof(int))
|
|
56
|
+
if OP.parent is NULL or OP.rank is NULL or OP.mcr is NULL or OP.size is NULL:
|
|
57
|
+
sig_free(OP.parent)
|
|
58
|
+
sig_free(OP.rank)
|
|
59
|
+
sig_free(OP.mcr)
|
|
60
|
+
sig_free(OP.size)
|
|
61
|
+
sig_free(OP)
|
|
62
|
+
return NULL
|
|
63
|
+
OP.degree = n
|
|
64
|
+
OP.num_cells = n
|
|
65
|
+
OP_clear(OP)
|
|
66
|
+
return OP
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
cdef inline void OP_dealloc(OrbitPartition *OP) noexcept:
|
|
70
|
+
if OP is not NULL:
|
|
71
|
+
sig_free(OP.parent)
|
|
72
|
+
sig_free(OP.rank)
|
|
73
|
+
sig_free(OP.mcr)
|
|
74
|
+
sig_free(OP.size)
|
|
75
|
+
sig_free(OP)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
cdef OP_string(OrbitPartition *OP):
|
|
79
|
+
"""
|
|
80
|
+
Return a string representation of the OrbitPartition.
|
|
81
|
+
"""
|
|
82
|
+
cdef i,j
|
|
83
|
+
s = ""
|
|
84
|
+
for i in range(OP.degree):
|
|
85
|
+
s += " "
|
|
86
|
+
j = OP_find(OP, i)
|
|
87
|
+
s += "%d -> %d" % (i, j)
|
|
88
|
+
return s
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
cdef inline void OP_make_set(OrbitPartition *OP) noexcept:
|
|
92
|
+
"""
|
|
93
|
+
Increase the degree of the input partition by one.
|
|
94
|
+
|
|
95
|
+
An error is raised in case of memory allocation failure.
|
|
96
|
+
"""
|
|
97
|
+
cdef int n = OP.degree
|
|
98
|
+
|
|
99
|
+
OP.parent = <int *> sig_realloc(OP.parent, (n + 1) * sizeof(int))
|
|
100
|
+
OP.rank = <int *> sig_realloc(OP.rank, (n + 1) * sizeof(int))
|
|
101
|
+
OP.mcr = <int *> sig_realloc(OP.mcr, (n + 1) * sizeof(int))
|
|
102
|
+
OP.size = <int *> sig_realloc(OP.size, (n + 1) * sizeof(int))
|
|
103
|
+
if OP.parent is NULL or OP.rank is NULL or OP.mcr is NULL or OP.size is NULL:
|
|
104
|
+
sig_free(OP.parent)
|
|
105
|
+
sig_free(OP.rank)
|
|
106
|
+
sig_free(OP.mcr)
|
|
107
|
+
sig_free(OP.size)
|
|
108
|
+
raise MemoryError("unable to reallocate memory in OP_make_set method")
|
|
109
|
+
OP.degree = n + 1
|
|
110
|
+
OP.num_cells = OP.num_cells + 1
|
|
111
|
+
|
|
112
|
+
OP.parent[n] = n
|
|
113
|
+
OP.rank[n] = 0
|
|
114
|
+
OP.mcr[n] = n
|
|
115
|
+
OP.size[n] = 1
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def OP_represent(int n, merges, perm):
|
|
119
|
+
"""
|
|
120
|
+
Demonstration and testing.
|
|
121
|
+
|
|
122
|
+
TESTS::
|
|
123
|
+
|
|
124
|
+
sage: from sage.groups.perm_gps.partn_ref.data_structures import OP_represent
|
|
125
|
+
sage: OP_represent(9, [(0,1),(2,3),(3,4)], [1,2,0,4,3,6,7,5,8])
|
|
126
|
+
Allocating OrbitPartition...
|
|
127
|
+
Allocation passed.
|
|
128
|
+
Checking that each element reports itself as its root.
|
|
129
|
+
Each element reports itself as its root.
|
|
130
|
+
Merging:
|
|
131
|
+
Merged 0 and 1.
|
|
132
|
+
Merged 2 and 3.
|
|
133
|
+
Merged 3 and 4.
|
|
134
|
+
Done merging.
|
|
135
|
+
Finding:
|
|
136
|
+
0 -> 0, root: size=2, mcr=0, rank=1
|
|
137
|
+
1 -> 0
|
|
138
|
+
2 -> 2, root: size=3, mcr=2, rank=1
|
|
139
|
+
3 -> 2
|
|
140
|
+
4 -> 2
|
|
141
|
+
5 -> 5, root: size=1, mcr=5, rank=0
|
|
142
|
+
6 -> 6, root: size=1, mcr=6, rank=0
|
|
143
|
+
7 -> 7, root: size=1, mcr=7, rank=0
|
|
144
|
+
8 -> 8, root: size=1, mcr=8, rank=0
|
|
145
|
+
Allocating array to test merge_perm.
|
|
146
|
+
Allocation passed.
|
|
147
|
+
Merging permutation: [1, 2, 0, 4, 3, 6, 7, 5, 8]
|
|
148
|
+
Done merging.
|
|
149
|
+
Finding:
|
|
150
|
+
0 -> 0, root: size=5, mcr=0, rank=2
|
|
151
|
+
1 -> 0
|
|
152
|
+
2 -> 0
|
|
153
|
+
3 -> 0
|
|
154
|
+
4 -> 0
|
|
155
|
+
5 -> 5, root: size=3, mcr=5, rank=1
|
|
156
|
+
6 -> 5
|
|
157
|
+
7 -> 5
|
|
158
|
+
8 -> 8, root: size=1, mcr=8, rank=0
|
|
159
|
+
Deallocating OrbitPartition.
|
|
160
|
+
Done.
|
|
161
|
+
"""
|
|
162
|
+
cdef int i
|
|
163
|
+
print("Allocating OrbitPartition...")
|
|
164
|
+
cdef OrbitPartition *OP = OP_new(n)
|
|
165
|
+
if OP is NULL:
|
|
166
|
+
print("Allocation failed!")
|
|
167
|
+
return
|
|
168
|
+
print("Allocation passed.")
|
|
169
|
+
print("Checking that each element reports itself as its root.")
|
|
170
|
+
good = True
|
|
171
|
+
for i in range(n):
|
|
172
|
+
if not OP_find(OP, i) == i:
|
|
173
|
+
print("Failed at i = %d!" % i)
|
|
174
|
+
good = False
|
|
175
|
+
if good:
|
|
176
|
+
print("Each element reports itself as its root.")
|
|
177
|
+
print("Merging:")
|
|
178
|
+
for i,j in merges:
|
|
179
|
+
OP_join(OP, i, j)
|
|
180
|
+
print("Merged %d and %d." % (i, j))
|
|
181
|
+
print("Done merging.")
|
|
182
|
+
print("Finding:")
|
|
183
|
+
for i in range(n):
|
|
184
|
+
j = OP_find(OP, i)
|
|
185
|
+
s = "%d -> %d" % (i, j)
|
|
186
|
+
if i == j:
|
|
187
|
+
s += ", root: size=%d, mcr=%d, rank=%d" % \
|
|
188
|
+
(OP.size[i], OP.mcr[i], OP.rank[i])
|
|
189
|
+
print(s)
|
|
190
|
+
print("Allocating array to test merge_perm.")
|
|
191
|
+
cdef int *gamma = <int *> sig_malloc( n * sizeof(int) )
|
|
192
|
+
if gamma is NULL:
|
|
193
|
+
print("Allocation failed!")
|
|
194
|
+
OP_dealloc(OP)
|
|
195
|
+
return
|
|
196
|
+
print("Allocation passed.")
|
|
197
|
+
for i in range(n):
|
|
198
|
+
gamma[i] = perm[i]
|
|
199
|
+
print("Merging permutation: %s" % perm)
|
|
200
|
+
OP_merge_list_perm(OP, gamma)
|
|
201
|
+
print("Done merging.")
|
|
202
|
+
print("Finding:")
|
|
203
|
+
for i in range(n):
|
|
204
|
+
j = OP_find(OP, i)
|
|
205
|
+
s = "%d -> %d" % (i, j)
|
|
206
|
+
if i == j:
|
|
207
|
+
s += ", root: size=%d, mcr=%d, rank=%d" % \
|
|
208
|
+
(OP.size[i], OP.mcr[i], OP.rank[i])
|
|
209
|
+
print(s)
|
|
210
|
+
print("Deallocating OrbitPartition.")
|
|
211
|
+
sig_free(gamma)
|
|
212
|
+
OP_dealloc(OP)
|
|
213
|
+
print("Done.")
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# PartitionStack (PS)
|
|
217
|
+
|
|
218
|
+
cdef inline PartitionStack *PS_new(int n, bint unit_partition) noexcept:
|
|
219
|
+
"""
|
|
220
|
+
Allocate and return a pointer to a new PartitionStack of degree n. Return a
|
|
221
|
+
null pointer in the case of an allocation failure.
|
|
222
|
+
"""
|
|
223
|
+
cdef PartitionStack *PS = <PartitionStack *> \
|
|
224
|
+
sig_malloc(sizeof(PartitionStack))
|
|
225
|
+
cdef int *int_array = <int *> sig_malloc( 2*n * sizeof(int) )
|
|
226
|
+
if PS is NULL or int_array is NULL:
|
|
227
|
+
sig_free(PS)
|
|
228
|
+
sig_free(int_array)
|
|
229
|
+
return NULL
|
|
230
|
+
PS.entries = int_array
|
|
231
|
+
PS.levels = int_array + n
|
|
232
|
+
PS.depth = 0
|
|
233
|
+
PS.degree = n
|
|
234
|
+
if unit_partition:
|
|
235
|
+
PS_unit_partition(PS)
|
|
236
|
+
return PS
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
cdef void PS_unit_partition(PartitionStack *PS) noexcept:
|
|
240
|
+
"""
|
|
241
|
+
Set partition stack to a single partition with a single cell.
|
|
242
|
+
"""
|
|
243
|
+
cdef int i, n = PS.degree
|
|
244
|
+
PS.depth = 0
|
|
245
|
+
for i in range(n - 1):
|
|
246
|
+
PS.entries[i] = i
|
|
247
|
+
PS.levels[i] = n
|
|
248
|
+
PS.entries[n-1] = n - 1
|
|
249
|
+
PS.levels[n-1] = -1
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
cdef inline PartitionStack *PS_copy(PartitionStack *PS) noexcept:
|
|
253
|
+
"""
|
|
254
|
+
Allocate and return a pointer to a copy of PartitionStack PS. Return a null
|
|
255
|
+
pointer in the case of an allocation failure.
|
|
256
|
+
"""
|
|
257
|
+
cdef int n = PS.degree
|
|
258
|
+
|
|
259
|
+
cdef PartitionStack *PS2 = <PartitionStack *> \
|
|
260
|
+
sig_malloc(sizeof(PartitionStack))
|
|
261
|
+
cdef int *int_array = <int *> sig_malloc( 2*n * sizeof(int) )
|
|
262
|
+
if PS2 is NULL or int_array is NULL:
|
|
263
|
+
sig_free(PS2)
|
|
264
|
+
sig_free(int_array)
|
|
265
|
+
return NULL
|
|
266
|
+
PS2.entries = int_array
|
|
267
|
+
PS2.levels = int_array + n
|
|
268
|
+
PS_copy_from_to(PS, PS2)
|
|
269
|
+
return PS2
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
cdef inline void PS_dealloc(PartitionStack *PS) noexcept:
|
|
273
|
+
if PS is not NULL:
|
|
274
|
+
sig_free(PS.entries)
|
|
275
|
+
sig_free(PS)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
cdef PartitionStack *PS_from_list(list L) noexcept:
|
|
279
|
+
"""
|
|
280
|
+
Allocate and return a pointer to a PartitionStack representing L. Return a
|
|
281
|
+
null pointer in the case of an allocation failure.
|
|
282
|
+
"""
|
|
283
|
+
cdef int cell, i, num_cells = len(L), cur_start = 0, cur_len, n = 0
|
|
284
|
+
for cell in range(num_cells):
|
|
285
|
+
n += len(L[cell])
|
|
286
|
+
cdef PartitionStack *PS = PS_new(n, 0)
|
|
287
|
+
if PS is NULL:
|
|
288
|
+
return NULL
|
|
289
|
+
for cell in range(num_cells):
|
|
290
|
+
cur_len = len(L[cell])
|
|
291
|
+
for i in range(cur_len):
|
|
292
|
+
PS.entries[cur_start + i] = L[cell][i]
|
|
293
|
+
PS.levels[cur_start + i] = n
|
|
294
|
+
PS_move_min_to_front(PS, cur_start, cur_start+cur_len-1)
|
|
295
|
+
cur_start += cur_len
|
|
296
|
+
PS.levels[cur_start-1] = 0
|
|
297
|
+
if n > 0:
|
|
298
|
+
PS.levels[n-1] = -1
|
|
299
|
+
PS.depth = 0
|
|
300
|
+
PS.degree = n
|
|
301
|
+
return PS
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
cdef PS_print(PartitionStack *PS):
|
|
305
|
+
"""
|
|
306
|
+
Print a visual representation of PS.
|
|
307
|
+
"""
|
|
308
|
+
cdef int i
|
|
309
|
+
for i in range(PS.depth + 1):
|
|
310
|
+
PS_print_partition(PS, i)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
cdef PS_print_partition(PartitionStack *PS, int k):
|
|
314
|
+
"""
|
|
315
|
+
Print the partition at depth k.
|
|
316
|
+
"""
|
|
317
|
+
s = '('
|
|
318
|
+
for i in range(PS.degree):
|
|
319
|
+
s += str(PS.entries[i])
|
|
320
|
+
if PS.levels[i] <= k:
|
|
321
|
+
s += '|'
|
|
322
|
+
else:
|
|
323
|
+
s += ' '
|
|
324
|
+
s = s[:-1] + ')'
|
|
325
|
+
print(s)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
cdef int PS_first_smallest(PartitionStack *PS, bitset_t b, int *second_pos=NULL) noexcept:
|
|
329
|
+
"""
|
|
330
|
+
Find the first occurrence of the smallest cell of size greater than one,
|
|
331
|
+
which is admissible (checked by the function ``test_allowance``).
|
|
332
|
+
Its entries are stored to `b` and its minimum element is returned.
|
|
333
|
+
"""
|
|
334
|
+
cdef int i = 0, j = 0, location = 0, n = PS.degree
|
|
335
|
+
bitset_zero(b)
|
|
336
|
+
while True:
|
|
337
|
+
if PS.levels[i] <= PS.depth:
|
|
338
|
+
if i != j and n > i - j + 1:
|
|
339
|
+
n = i - j + 1
|
|
340
|
+
location = j
|
|
341
|
+
j = i + 1
|
|
342
|
+
if PS.levels[i] == -1:
|
|
343
|
+
break
|
|
344
|
+
i += 1
|
|
345
|
+
# location now points to the beginning of the first, smallest,
|
|
346
|
+
# nontrivial cell
|
|
347
|
+
i = location
|
|
348
|
+
while True:
|
|
349
|
+
bitset_flip(b, PS.entries[i])
|
|
350
|
+
if PS.levels[i] <= PS.depth:
|
|
351
|
+
break
|
|
352
|
+
i += 1
|
|
353
|
+
|
|
354
|
+
if second_pos != NULL:
|
|
355
|
+
if n == 2:
|
|
356
|
+
second_pos[0] = PS.entries[location + 1]
|
|
357
|
+
else:
|
|
358
|
+
second_pos[0] = -1
|
|
359
|
+
|
|
360
|
+
return PS.entries[location]
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
cdef int PS_all_new_cells(PartitionStack *PS, bitset_t** nonsingletons_ptr) noexcept:
|
|
364
|
+
"""
|
|
365
|
+
Suppose a cell ``C`` was split into ``a`` components at ``PS.level``.
|
|
366
|
+
Set the rows of the matrix ``nonsingletons_ptr`` to the first
|
|
367
|
+
``a-1`` components of ``C`` for all those ``C``.
|
|
368
|
+
Return the number of rows of ``nonsingletons_ptr``.
|
|
369
|
+
"""
|
|
370
|
+
cdef int beg=0, end, n = PS.degree, count=0, i, n_1 = n-1
|
|
371
|
+
cdef bitset_t scratch
|
|
372
|
+
bitset_init(scratch, n)
|
|
373
|
+
cdef bitset_t* nonsingletons = nonsingletons_ptr[0]
|
|
374
|
+
|
|
375
|
+
while beg < n_1:
|
|
376
|
+
end = beg
|
|
377
|
+
while end!=n and PS.levels[end] > PS.depth:
|
|
378
|
+
end+=1
|
|
379
|
+
|
|
380
|
+
if end != n:
|
|
381
|
+
if PS.levels[end] == PS.depth:
|
|
382
|
+
bitset_zero(scratch)
|
|
383
|
+
for i in range(beg, end + 1):
|
|
384
|
+
bitset_set(scratch, PS.entries[i])
|
|
385
|
+
count +=1
|
|
386
|
+
nonsingletons = <bitset_t*> sig_realloc(nonsingletons, count * sizeof(bitset_t))
|
|
387
|
+
if nonsingletons is NULL:
|
|
388
|
+
raise MemoryError("Memory error in PS_all_new_cells")
|
|
389
|
+
bitset_init(nonsingletons[count-1], n)
|
|
390
|
+
bitset_copy(nonsingletons[count-1], scratch)
|
|
391
|
+
else:
|
|
392
|
+
if beg == 0:
|
|
393
|
+
nonsingletons = <bitset_t*> sig_realloc(nonsingletons, sizeof(bitset_t))
|
|
394
|
+
if nonsingletons is NULL:
|
|
395
|
+
raise MemoryError("Memory error in PS_all_new_cells")
|
|
396
|
+
bitset_init(nonsingletons[0], n)
|
|
397
|
+
bitset_zero(scratch)
|
|
398
|
+
bitset_complement(nonsingletons[0], scratch)
|
|
399
|
+
count = 1
|
|
400
|
+
beg = end+1
|
|
401
|
+
nonsingletons_ptr[0] = nonsingletons
|
|
402
|
+
return count
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
cdef int PS_find_element(PartitionStack *PS, bitset_t b, int x) except -1:
|
|
406
|
+
"""
|
|
407
|
+
Find the cell containing x, store its entries to b and return the location
|
|
408
|
+
of the beginning of the cell.
|
|
409
|
+
"""
|
|
410
|
+
cdef int i, location, n = PS.degree
|
|
411
|
+
bitset_zero(b)
|
|
412
|
+
for i in range(n):
|
|
413
|
+
if PS.entries[i] == x:
|
|
414
|
+
location = i
|
|
415
|
+
break
|
|
416
|
+
else:
|
|
417
|
+
raise ValueError("element not found")
|
|
418
|
+
while location > 0 and PS.levels[location-1] > PS.depth:
|
|
419
|
+
location -= 1
|
|
420
|
+
i = 0
|
|
421
|
+
while 1:
|
|
422
|
+
bitset_set(b, PS.entries[location+i])
|
|
423
|
+
if PS.levels[location+i] <= PS.depth:
|
|
424
|
+
break
|
|
425
|
+
i += 1
|
|
426
|
+
return location
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
cdef list PS_singletons(PartitionStack * part):
|
|
430
|
+
"""
|
|
431
|
+
Return the list of all singletons in the ``PartitionStack``.
|
|
432
|
+
"""
|
|
433
|
+
cdef list l = []
|
|
434
|
+
cdef int i
|
|
435
|
+
|
|
436
|
+
if part.levels[0] <= part.depth:
|
|
437
|
+
l.append(0)
|
|
438
|
+
|
|
439
|
+
for i in range(1, part.degree):
|
|
440
|
+
if part.levels[i] <= part.depth and part.levels[i - 1] <= part.depth:
|
|
441
|
+
l.append(i)
|
|
442
|
+
|
|
443
|
+
return l
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def PS_represent(partition, splits):
|
|
447
|
+
"""
|
|
448
|
+
Demonstration and testing.
|
|
449
|
+
|
|
450
|
+
TESTS::
|
|
451
|
+
|
|
452
|
+
sage: from sage.groups.perm_gps.partn_ref.data_structures import PS_represent
|
|
453
|
+
sage: PS_represent([[6],[3,4,8,7],[1,9,5],[0,2]], [6,1,8,2])
|
|
454
|
+
Allocating PartitionStack...
|
|
455
|
+
Allocation passed:
|
|
456
|
+
(0 1 2 3 4 5 6 7 8 9)
|
|
457
|
+
Checking that entries are in order and correct level.
|
|
458
|
+
Everything seems in order, deallocating.
|
|
459
|
+
Deallocated.
|
|
460
|
+
Creating PartitionStack from partition [[6], [3, 4, 8, 7], [1, 9, 5], [0, 2]].
|
|
461
|
+
PartitionStack's data:
|
|
462
|
+
entries -> [6, 3, 4, 8, 7, 1, 9, 5, 0, 2]
|
|
463
|
+
levels -> [0, 10, 10, 10, 0, 10, 10, 0, 10, -1]
|
|
464
|
+
depth = 0, degree = 10
|
|
465
|
+
(6|3 4 8 7|1 9 5|0 2)
|
|
466
|
+
Checking PS_is_discrete:
|
|
467
|
+
False
|
|
468
|
+
Checking PS_num_cells:
|
|
469
|
+
4
|
|
470
|
+
Checking PS_is_mcr, min cell reps are:
|
|
471
|
+
[6, 3, 1, 0]
|
|
472
|
+
Checking PS_is_fixed, fixed elements are:
|
|
473
|
+
[6]
|
|
474
|
+
Copying PartitionStack:
|
|
475
|
+
(6|3 4 8 7|1 9 5|0 2)
|
|
476
|
+
Checking for consistency.
|
|
477
|
+
Everything is consistent.
|
|
478
|
+
Clearing copy:
|
|
479
|
+
(0 3 4 8 7 1 9 5 6 2)
|
|
480
|
+
Splitting point 6 from original:
|
|
481
|
+
0
|
|
482
|
+
(6|3 4 8 7|1 9 5|0 2)
|
|
483
|
+
Splitting point 1 from original:
|
|
484
|
+
5
|
|
485
|
+
(6|3 4 8 7|1|5 9|0 2)
|
|
486
|
+
Splitting point 8 from original:
|
|
487
|
+
1
|
|
488
|
+
(6|8|3 4 7|1|5 9|0 2)
|
|
489
|
+
Splitting point 2 from original:
|
|
490
|
+
8
|
|
491
|
+
(6|8|3 4 7|1|5 9|2|0)
|
|
492
|
+
Getting permutation from PS2->PS:
|
|
493
|
+
[6, 1, 0, 8, 3, 9, 2, 7, 4, 5]
|
|
494
|
+
Finding first smallest:
|
|
495
|
+
Minimal element is 5, bitset is:
|
|
496
|
+
0000010001
|
|
497
|
+
Finding element 1:
|
|
498
|
+
Location is: 5
|
|
499
|
+
Bitset is:
|
|
500
|
+
0100000000
|
|
501
|
+
Deallocating PartitionStacks.
|
|
502
|
+
Done.
|
|
503
|
+
"""
|
|
504
|
+
cdef int i, n = sum([len(cell) for cell in partition])
|
|
505
|
+
cdef int *gamma
|
|
506
|
+
cdef bitset_t b
|
|
507
|
+
print("Allocating PartitionStack...")
|
|
508
|
+
cdef PartitionStack *PS = PS_new(n, 1)
|
|
509
|
+
cdef PartitionStack *PS2
|
|
510
|
+
if PS is NULL:
|
|
511
|
+
print("Allocation failed!")
|
|
512
|
+
return
|
|
513
|
+
print("Allocation passed:")
|
|
514
|
+
PS_print(PS)
|
|
515
|
+
print("Checking that entries are in order and correct level.")
|
|
516
|
+
good = True
|
|
517
|
+
for i in range(n - 1):
|
|
518
|
+
if not (PS.entries[i] == i and PS.levels[i] == n):
|
|
519
|
+
print("Failed at i = %d!" % i)
|
|
520
|
+
print(PS.entries[i], PS.levels[i], i, n)
|
|
521
|
+
good = False
|
|
522
|
+
if not (PS.entries[n-1] == n-1 and PS.levels[n-1] == -1):
|
|
523
|
+
print("Failed at i = %d!" % (n-1))
|
|
524
|
+
good = False
|
|
525
|
+
if not PS.degree == n or not PS.depth == 0:
|
|
526
|
+
print("Incorrect degree or depth!")
|
|
527
|
+
good = False
|
|
528
|
+
if good:
|
|
529
|
+
print("Everything seems in order, deallocating.")
|
|
530
|
+
PS_dealloc(PS)
|
|
531
|
+
print("Deallocated.")
|
|
532
|
+
print("Creating PartitionStack from partition %s." % partition)
|
|
533
|
+
PS = PS_from_list(partition)
|
|
534
|
+
print("PartitionStack's data:")
|
|
535
|
+
print("entries -> %s" % [PS.entries[i] for i in range(n)])
|
|
536
|
+
print("levels -> %s" % [PS.levels[i] for i in range(n)])
|
|
537
|
+
print("depth = %d, degree = %d" % (PS.depth,PS.degree))
|
|
538
|
+
PS_print(PS)
|
|
539
|
+
print("Checking PS_is_discrete:")
|
|
540
|
+
print("True" if PS_is_discrete(PS) else "False")
|
|
541
|
+
print("Checking PS_num_cells:")
|
|
542
|
+
print(PS_num_cells(PS))
|
|
543
|
+
print("Checking PS_is_mcr, min cell reps are:")
|
|
544
|
+
L = [PS.entries[i] for i in range(n) if PS_is_mcr(PS, i)]
|
|
545
|
+
print(L)
|
|
546
|
+
print("Checking PS_is_fixed, fixed elements are:")
|
|
547
|
+
print([PS.entries[l] for l in L if PS_is_fixed(PS, l)])
|
|
548
|
+
print("Copying PartitionStack:")
|
|
549
|
+
PS2 = PS_copy(PS)
|
|
550
|
+
PS_print(PS2)
|
|
551
|
+
print("Checking for consistency.")
|
|
552
|
+
good = True
|
|
553
|
+
for i in range(n):
|
|
554
|
+
if PS.entries[i] != PS2.entries[i] or PS.levels[i] != PS2.levels[i]:
|
|
555
|
+
print("Failed at i = %d!" % i)
|
|
556
|
+
good = False
|
|
557
|
+
if PS.degree != PS2.degree or PS.depth != PS2.depth:
|
|
558
|
+
print("Failure with degree or depth!")
|
|
559
|
+
good = False
|
|
560
|
+
if good:
|
|
561
|
+
print("Everything is consistent.")
|
|
562
|
+
print("Clearing copy:")
|
|
563
|
+
PS_clear(PS2)
|
|
564
|
+
PS_print(PS2)
|
|
565
|
+
for s in splits:
|
|
566
|
+
print("Splitting point %d from original:" % s)
|
|
567
|
+
print(PS_split_point(PS, s))
|
|
568
|
+
PS_print(PS)
|
|
569
|
+
print("Getting permutation from PS2->PS:")
|
|
570
|
+
gamma = <int *> sig_malloc(n * sizeof(int))
|
|
571
|
+
PS_get_perm_from(PS, PS2, gamma)
|
|
572
|
+
print([gamma[i] for i in range(n)])
|
|
573
|
+
sig_free(gamma)
|
|
574
|
+
print("Finding first smallest:")
|
|
575
|
+
bitset_init(b, n)
|
|
576
|
+
i = PS_first_smallest(PS, b)
|
|
577
|
+
print("Minimal element is %d, bitset is:" % i)
|
|
578
|
+
print(bitset_string(b))
|
|
579
|
+
bitset_free(b)
|
|
580
|
+
print("Finding element 1:")
|
|
581
|
+
bitset_init(b, n)
|
|
582
|
+
print("Location is: {}".format(PS_find_element(PS, b, 1)))
|
|
583
|
+
print("Bitset is:")
|
|
584
|
+
print(bitset_string(b))
|
|
585
|
+
bitset_free(b)
|
|
586
|
+
print("Deallocating PartitionStacks.")
|
|
587
|
+
PS_dealloc(PS)
|
|
588
|
+
PS_dealloc(PS2)
|
|
589
|
+
print("Done.")
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
# StabilizerChain (SC)
|
|
593
|
+
|
|
594
|
+
cdef enum:
|
|
595
|
+
default_num_gens = 8
|
|
596
|
+
default_num_bits = 64
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
cdef StabilizerChain *SC_new(int n, bint init_gens=True) noexcept:
|
|
600
|
+
"""
|
|
601
|
+
Allocate and return a pointer to a new StabilizerChain of degree n. Return
|
|
602
|
+
a null pointer in the case of an allocation failure.
|
|
603
|
+
"""
|
|
604
|
+
cdef int i
|
|
605
|
+
cdef StabilizerChain *SC = <StabilizerChain *> \
|
|
606
|
+
sig_calloc(1, sizeof(StabilizerChain))
|
|
607
|
+
if SC is NULL:
|
|
608
|
+
return NULL
|
|
609
|
+
SC.degree = n
|
|
610
|
+
SC.base_size = 0
|
|
611
|
+
if n == 0:
|
|
612
|
+
# All internal pointers have been initialized to NULL by sig_calloc
|
|
613
|
+
return SC
|
|
614
|
+
|
|
615
|
+
# first level allocations
|
|
616
|
+
cdef int *int_array = <int *> sig_malloc( (3*n*n + 6*n + 1) * sizeof(int) )
|
|
617
|
+
cdef int **int_ptrs = <int **> sig_calloc( 5*n, sizeof(int *) )
|
|
618
|
+
SC.OP_scratch = OP_new(n)
|
|
619
|
+
# bitset_init without the MemoryError:
|
|
620
|
+
cdef long limbs = (default_num_bits - 1)/(8*sizeof(unsigned long)) + 1
|
|
621
|
+
SC.gen_used.size = default_num_bits
|
|
622
|
+
SC.gen_is_id.size = default_num_bits
|
|
623
|
+
SC.gen_used.limbs = limbs
|
|
624
|
+
SC.gen_is_id.limbs = limbs
|
|
625
|
+
SC.gen_used.bits = <mp_limb_t*>sig_malloc(limbs * sizeof(mp_limb_t))
|
|
626
|
+
SC.gen_is_id.bits = <mp_limb_t*>sig_malloc(limbs * sizeof(mp_limb_t))
|
|
627
|
+
|
|
628
|
+
# check for allocation failures
|
|
629
|
+
if int_array is NULL or int_ptrs is NULL or \
|
|
630
|
+
SC.gen_used.bits is NULL or SC.gen_is_id.bits is NULL or \
|
|
631
|
+
SC.OP_scratch is NULL:
|
|
632
|
+
sig_free(int_array)
|
|
633
|
+
sig_free(int_ptrs)
|
|
634
|
+
SC_dealloc(SC)
|
|
635
|
+
return NULL
|
|
636
|
+
|
|
637
|
+
SC.gen_used.bits[limbs-1] = 0
|
|
638
|
+
SC.gen_is_id.bits[limbs-1] = 0
|
|
639
|
+
|
|
640
|
+
SC.orbit_sizes = int_array
|
|
641
|
+
SC.num_gens = int_array + n
|
|
642
|
+
SC.array_size = int_array + 2 * n
|
|
643
|
+
SC.perm_scratch = int_array + 3 * n # perm_scratch is length 3*n+1 for sorting
|
|
644
|
+
int_array += 6*n + 1
|
|
645
|
+
|
|
646
|
+
SC.generators = int_ptrs
|
|
647
|
+
SC.gen_inverses = int_ptrs + n
|
|
648
|
+
SC.base_orbits = int_ptrs + 2 * n
|
|
649
|
+
SC.parents = int_ptrs + 3 * n
|
|
650
|
+
SC.labels = int_ptrs + 4 * n
|
|
651
|
+
for i in range(n):
|
|
652
|
+
SC.base_orbits[i] = int_array
|
|
653
|
+
SC.parents[i] = int_array + n
|
|
654
|
+
SC.labels[i] = int_array + 2 * n
|
|
655
|
+
int_array += 3 * n
|
|
656
|
+
|
|
657
|
+
# second level allocations
|
|
658
|
+
if init_gens:
|
|
659
|
+
for i in range(n):
|
|
660
|
+
SC.array_size[i] = default_num_gens
|
|
661
|
+
SC.generators[i] = <int *> sig_malloc( default_num_gens*n * sizeof(int) )
|
|
662
|
+
SC.gen_inverses[i] = <int *> sig_malloc( default_num_gens*n * sizeof(int) )
|
|
663
|
+
if SC.generators[i] is NULL or SC.gen_inverses[i] is NULL:
|
|
664
|
+
SC_dealloc(SC)
|
|
665
|
+
return NULL
|
|
666
|
+
|
|
667
|
+
return SC
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
cdef inline int SC_realloc_gens(StabilizerChain *SC, int level, int size) noexcept:
|
|
671
|
+
"""
|
|
672
|
+
Reallocate generator array at level `level` to size `size`.
|
|
673
|
+
|
|
674
|
+
Return 1 in case of an allocation failure.
|
|
675
|
+
"""
|
|
676
|
+
cdef int *temp
|
|
677
|
+
cdef int n = SC.degree
|
|
678
|
+
|
|
679
|
+
temp = <int *> sig_realloc(SC.generators[level], n * size * sizeof(int))
|
|
680
|
+
if temp is NULL:
|
|
681
|
+
return 1
|
|
682
|
+
SC.generators[level] = temp
|
|
683
|
+
|
|
684
|
+
temp = <int *> sig_realloc(SC.gen_inverses[level], n * size * sizeof(int))
|
|
685
|
+
if temp is NULL:
|
|
686
|
+
return 1
|
|
687
|
+
SC.gen_inverses[level] = temp
|
|
688
|
+
|
|
689
|
+
SC.array_size[level] = size
|
|
690
|
+
return 0
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
cdef inline void SC_dealloc(StabilizerChain *SC) noexcept:
|
|
694
|
+
cdef int i, n
|
|
695
|
+
if SC is not NULL:
|
|
696
|
+
n = SC.degree
|
|
697
|
+
if SC.generators is not NULL:
|
|
698
|
+
for i in range(n):
|
|
699
|
+
sig_free(SC.generators[i])
|
|
700
|
+
sig_free(SC.gen_inverses[i])
|
|
701
|
+
sig_free(SC.generators) # frees int_ptrs
|
|
702
|
+
sig_free(SC.orbit_sizes) # frees int_array
|
|
703
|
+
sig_free(SC.gen_used.bits)
|
|
704
|
+
sig_free(SC.gen_is_id.bits)
|
|
705
|
+
OP_dealloc(SC.OP_scratch)
|
|
706
|
+
sig_free(SC)
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
cdef StabilizerChain *SC_symmetric_group(int n) noexcept:
|
|
710
|
+
"""
|
|
711
|
+
Return a stabilizer chain for the symmetric group on {0, 1, ..., n-1}.
|
|
712
|
+
|
|
713
|
+
Return ``NULL`` in the case of an allocation failure.
|
|
714
|
+
"""
|
|
715
|
+
cdef int i, j, b
|
|
716
|
+
cdef StabilizerChain *SC = SC_new(n, False)
|
|
717
|
+
if SC is NULL:
|
|
718
|
+
return NULL
|
|
719
|
+
SC.base_size = n-1
|
|
720
|
+
for i in range(n - 1):
|
|
721
|
+
SC.array_size[i] = n-i-1
|
|
722
|
+
SC.array_size[n-1] = default_num_gens
|
|
723
|
+
for i in range(n):
|
|
724
|
+
SC.generators[i] = <int *> sig_malloc( SC.array_size[i]*n * sizeof(int) )
|
|
725
|
+
SC.gen_inverses[i] = <int *> sig_malloc( SC.array_size[i]*n * sizeof(int) )
|
|
726
|
+
if SC.generators[i] is NULL or SC.gen_inverses[i] is NULL:
|
|
727
|
+
SC_dealloc(SC)
|
|
728
|
+
return NULL
|
|
729
|
+
cdef int *id_perm = SC.perm_scratch
|
|
730
|
+
for i in range(n):
|
|
731
|
+
id_perm[i] = i
|
|
732
|
+
for i in range(n - 1):
|
|
733
|
+
b = i
|
|
734
|
+
SC.orbit_sizes[i] = n-i
|
|
735
|
+
SC.num_gens[i] = n-i-1
|
|
736
|
+
for j in range(i):
|
|
737
|
+
SC.parents[i][j] = -1
|
|
738
|
+
for j in range(n - i):
|
|
739
|
+
SC.base_orbits[i][j] = i+j
|
|
740
|
+
SC.parents[i][i+j] = b
|
|
741
|
+
SC.labels[i][i+j] = j
|
|
742
|
+
for j in range(n - i - 1):
|
|
743
|
+
# j-th generator sends i+j+1 to b
|
|
744
|
+
memcpy(SC.generators[i] + n*j, id_perm, n * sizeof(int) )
|
|
745
|
+
SC.generators[i][n*j + i+j+1] = b
|
|
746
|
+
SC.generators[i][n*j + b] = i+j+1
|
|
747
|
+
memcpy(SC.gen_inverses[i] + n*j, SC.generators[i] + n*j, n * sizeof(int) )
|
|
748
|
+
return SC
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
cdef StabilizerChain *SC_alternating_group(int n) noexcept:
|
|
752
|
+
"""
|
|
753
|
+
Return a stabilizer chain for the alternating group on {0, 1, ..., n-1}.
|
|
754
|
+
|
|
755
|
+
Return ``NULL`` in the case of an allocation failure.
|
|
756
|
+
"""
|
|
757
|
+
cdef int i, j, b
|
|
758
|
+
cdef StabilizerChain *SC = SC_new(n, False)
|
|
759
|
+
if SC is NULL:
|
|
760
|
+
return NULL
|
|
761
|
+
SC.base_size = n-2
|
|
762
|
+
for i in range(n - 2):
|
|
763
|
+
SC.array_size[i] = n-i-1
|
|
764
|
+
SC.array_size[n-2] = default_num_gens
|
|
765
|
+
SC.array_size[n-1] = default_num_gens
|
|
766
|
+
for i in range(n):
|
|
767
|
+
SC.generators[i] = <int *> sig_malloc( SC.array_size[i]*n * sizeof(int) )
|
|
768
|
+
SC.gen_inverses[i] = <int *> sig_malloc( SC.array_size[i]*n * sizeof(int) )
|
|
769
|
+
if SC.generators[i] is NULL or SC.gen_inverses[i] is NULL:
|
|
770
|
+
SC_dealloc(SC)
|
|
771
|
+
return NULL
|
|
772
|
+
cdef int *id_perm = SC.perm_scratch
|
|
773
|
+
for i in range(n):
|
|
774
|
+
id_perm[i] = i
|
|
775
|
+
for i in range(n - 2):
|
|
776
|
+
b = i
|
|
777
|
+
SC.orbit_sizes[i] = n-i
|
|
778
|
+
SC.num_gens[i] = n-i-2
|
|
779
|
+
for j in range(i):
|
|
780
|
+
SC.parents[i][j] = -1
|
|
781
|
+
for j in range(n - i):
|
|
782
|
+
SC.base_orbits[i][j] = i+j
|
|
783
|
+
SC.parents[i][i+j] = b
|
|
784
|
+
SC.labels[i][i+j] = j
|
|
785
|
+
SC.labels[i][n-1] = -(n-i-2)
|
|
786
|
+
for j in range(n - i - 2):
|
|
787
|
+
# j-th generator sends i+j+1 to b, i+j+2 to i+j+1, and b to i+j+2
|
|
788
|
+
memcpy(SC.generators[i] + n*j, id_perm, n * sizeof(int) )
|
|
789
|
+
SC.generators[i][n*j + i+j+1] = b
|
|
790
|
+
SC.generators[i][n*j + b ] = i+j+2
|
|
791
|
+
SC.generators[i][n*j + i+j+2] = i+j+1
|
|
792
|
+
SC_invert_perm(SC.gen_inverses[i] + n*j, SC.generators[i] + n*j, n)
|
|
793
|
+
return SC
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
cdef int SC_realloc_bitsets(StabilizerChain *SC, unsigned long size) noexcept:
|
|
797
|
+
"""
|
|
798
|
+
If size is larger than current allocation, double the size of the bitsets
|
|
799
|
+
until it is not.
|
|
800
|
+
|
|
801
|
+
Return 1 in case of an allocation failure.
|
|
802
|
+
"""
|
|
803
|
+
cdef unsigned long size_old = SC.gen_used.size
|
|
804
|
+
if size <= size_old:
|
|
805
|
+
return 0
|
|
806
|
+
cdef unsigned long new_size = size_old
|
|
807
|
+
while new_size < size:
|
|
808
|
+
new_size *= 2
|
|
809
|
+
cdef long limbs = (new_size - 1)/(8*sizeof(unsigned long)) + 1
|
|
810
|
+
cdef mp_limb_t *tmp = <mp_limb_t*> sig_realloc(SC.gen_used.bits, limbs * sizeof(mp_limb_t))
|
|
811
|
+
if tmp is not NULL:
|
|
812
|
+
SC.gen_used.bits = tmp
|
|
813
|
+
else:
|
|
814
|
+
return 1
|
|
815
|
+
tmp = <mp_limb_t*> sig_realloc(SC.gen_is_id.bits, limbs * sizeof(mp_limb_t))
|
|
816
|
+
if tmp is not NULL:
|
|
817
|
+
SC.gen_is_id.bits = tmp
|
|
818
|
+
else:
|
|
819
|
+
return 1
|
|
820
|
+
SC.gen_used.limbs = limbs
|
|
821
|
+
SC.gen_is_id.limbs = limbs
|
|
822
|
+
SC.gen_used.size = new_size
|
|
823
|
+
SC.gen_is_id.size = new_size
|
|
824
|
+
SC.gen_used.bits[size_old >> index_shift] &= limb_lower_bits_down(size_old)
|
|
825
|
+
memset(SC.gen_used.bits + (size_old >> index_shift) + 1, 0,
|
|
826
|
+
(limbs - (size_old >> index_shift) - 1) * sizeof(unsigned long))
|
|
827
|
+
SC.gen_is_id.bits[size_old >> index_shift] &= limb_lower_bits_down(size_old)
|
|
828
|
+
memset(SC.gen_is_id.bits + (size_old >> index_shift) + 1, 0,
|
|
829
|
+
(limbs - (size_old >> index_shift) - 1) * sizeof(unsigned long))
|
|
830
|
+
return 0
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
cdef StabilizerChain *SC_copy(StabilizerChain *SC, int level) noexcept:
|
|
834
|
+
"""
|
|
835
|
+
Create a copy of the first `level` levels of SC. Must have 0 < level.
|
|
836
|
+
|
|
837
|
+
Return a null pointer in case of allocation failure.
|
|
838
|
+
"""
|
|
839
|
+
cdef int i, n = SC.degree
|
|
840
|
+
cdef StabilizerChain *SCC = SC_new(n, False)
|
|
841
|
+
if SCC is NULL:
|
|
842
|
+
return NULL
|
|
843
|
+
level = min(level, SC.base_size)
|
|
844
|
+
for i in range(level):
|
|
845
|
+
SCC.generators[i] = <int *> sig_malloc( SC.array_size[i]*n * sizeof(int) )
|
|
846
|
+
SCC.gen_inverses[i] = <int *> sig_malloc( SC.array_size[i]*n * sizeof(int) )
|
|
847
|
+
if SCC.generators[i] is NULL or SCC.gen_inverses[i] is NULL:
|
|
848
|
+
SC_dealloc(SCC)
|
|
849
|
+
return NULL
|
|
850
|
+
SCC.array_size[i] = SC.array_size[i]
|
|
851
|
+
for i in range(level, n):
|
|
852
|
+
SCC.generators[i] = <int *> sig_malloc( default_num_gens*n * sizeof(int) )
|
|
853
|
+
SCC.gen_inverses[i] = <int *> sig_malloc( default_num_gens*n * sizeof(int) )
|
|
854
|
+
if SCC.generators[i] is NULL or SCC.gen_inverses[i] is NULL:
|
|
855
|
+
SC_dealloc(SCC)
|
|
856
|
+
return NULL
|
|
857
|
+
SCC.array_size[i] = default_num_gens
|
|
858
|
+
SC_copy_nomalloc(SCC, SC, level) # no chance for memory error here...
|
|
859
|
+
return SCC
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
cdef int SC_copy_nomalloc(StabilizerChain *SC_dest, StabilizerChain *SC, int level) noexcept:
|
|
863
|
+
cdef int i, n = SC.degree
|
|
864
|
+
level = min(level, SC.base_size)
|
|
865
|
+
SC_dest.base_size = level
|
|
866
|
+
memcpy(SC_dest.orbit_sizes, SC.orbit_sizes, 2*n * sizeof(int) ) # copies orbit_sizes, num_gens
|
|
867
|
+
memcpy(SC_dest.base_orbits[0], SC.base_orbits[0], 3*n*n * sizeof(int) ) # copies base_orbits, parents, labels
|
|
868
|
+
for i in range(level):
|
|
869
|
+
if SC.num_gens[i] > SC_dest.array_size[i]:
|
|
870
|
+
if SC_realloc_gens(SC_dest, i, max(SC.num_gens[i], 2*SC_dest.array_size[i])):
|
|
871
|
+
return 1
|
|
872
|
+
memcpy(SC_dest.generators[i], SC.generators[i], SC.num_gens[i]*n * sizeof(int) )
|
|
873
|
+
memcpy(SC_dest.gen_inverses[i], SC.gen_inverses[i], SC.num_gens[i]*n * sizeof(int) )
|
|
874
|
+
return 0
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
cdef SC_print_level(StabilizerChain *SC, int level):
|
|
878
|
+
cdef int i, j, n = SC.degree
|
|
879
|
+
if level < SC.base_size:
|
|
880
|
+
print('/ level {}'.format(level))
|
|
881
|
+
print('| orbit {}'.format([SC.base_orbits[level][i]
|
|
882
|
+
for i in range(SC.orbit_sizes[level])]))
|
|
883
|
+
print('| parents {}'.format([SC.parents[level][i] for i in range(n)]))
|
|
884
|
+
print('| labels {}'.format([SC.labels[level][i] for i in range(n)]))
|
|
885
|
+
print('|')
|
|
886
|
+
print('| generators {}'.format([[SC.generators[level][n*i + j]
|
|
887
|
+
for j in range(n)]
|
|
888
|
+
for i in range(SC.num_gens[level])]))
|
|
889
|
+
print(r'\ inverses {}'.format([[SC.gen_inverses[level][n*i + j]
|
|
890
|
+
for j in range(n)]
|
|
891
|
+
for i in range(SC.num_gens[level])]))
|
|
892
|
+
else:
|
|
893
|
+
print('/ level {}'.format(level))
|
|
894
|
+
print('|')
|
|
895
|
+
print(r'\ base_size {}'.format(SC.base_size))
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
cdef StabilizerChain *SC_new_base(StabilizerChain *SC, int *base, int base_len) noexcept:
|
|
899
|
+
"""
|
|
900
|
+
Create a new stabilizer chain whose base starts with the given base, and
|
|
901
|
+
which represents the same permutation group. Original StabilizerChain is
|
|
902
|
+
unmodified.
|
|
903
|
+
|
|
904
|
+
Use SC_cleanup to remove redundant base points.
|
|
905
|
+
|
|
906
|
+
Return a null pointer in case of an allocation failure.
|
|
907
|
+
"""
|
|
908
|
+
cdef StabilizerChain *NEW = SC_new(SC.degree)
|
|
909
|
+
if NEW is NULL:
|
|
910
|
+
return NULL
|
|
911
|
+
if SC_new_base_nomalloc(NEW, SC, base, base_len):
|
|
912
|
+
SC_dealloc(NEW)
|
|
913
|
+
return NULL
|
|
914
|
+
return NEW
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
cdef int SC_new_base_nomalloc(StabilizerChain *SC_dest, StabilizerChain *SC, int *base, int base_len) noexcept:
|
|
918
|
+
cdef int i
|
|
919
|
+
SC_dest.base_size = 0
|
|
920
|
+
for i in range(base_len):
|
|
921
|
+
SC_add_base_point(SC_dest, base[i])
|
|
922
|
+
if SC_update(SC_dest, SC, 0):
|
|
923
|
+
SC_dealloc(SC_dest)
|
|
924
|
+
return 1
|
|
925
|
+
return 0
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
cdef int SC_update(StabilizerChain *dest, StabilizerChain *source, int level) noexcept:
|
|
929
|
+
cdef mpz_t src_order, dst_order
|
|
930
|
+
cdef int *perm = dest.perm_scratch
|
|
931
|
+
mpz_init(src_order)
|
|
932
|
+
mpz_init(dst_order)
|
|
933
|
+
SC_order(source, level, src_order)
|
|
934
|
+
SC_order(dest, level, dst_order)
|
|
935
|
+
cdef int i, first_moved, b
|
|
936
|
+
while mpz_cmp(dst_order, src_order):
|
|
937
|
+
SC_random_element(source, level, perm)
|
|
938
|
+
i = level
|
|
939
|
+
while i < dest.base_size:
|
|
940
|
+
b = dest.base_orbits[i][0]
|
|
941
|
+
if perm[b] != b:
|
|
942
|
+
break
|
|
943
|
+
i += 1
|
|
944
|
+
else:
|
|
945
|
+
for b in range(dest.degree):
|
|
946
|
+
if perm[b] != b:
|
|
947
|
+
break
|
|
948
|
+
else:
|
|
949
|
+
continue
|
|
950
|
+
SC_add_base_point(dest, b)
|
|
951
|
+
first_moved = i
|
|
952
|
+
for i in range(level, first_moved + 1):
|
|
953
|
+
if SC_insert_and_sift(dest, i, perm, 1, 0): # don't sift!
|
|
954
|
+
mpz_clear(dst_order)
|
|
955
|
+
mpz_clear(src_order)
|
|
956
|
+
return 1
|
|
957
|
+
SC_order(dest, level, dst_order)
|
|
958
|
+
mpz_clear(src_order)
|
|
959
|
+
mpz_clear(dst_order)
|
|
960
|
+
return 0
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
cdef StabilizerChain *SC_insert_base_point(StabilizerChain *SC, int level, int p) noexcept:
|
|
964
|
+
"""
|
|
965
|
+
Insert the point ``p`` as a base point on level ``level``. Return a new
|
|
966
|
+
StabilizerChain with this new base. Original StabilizerChain is unmodified.
|
|
967
|
+
|
|
968
|
+
Use SC_cleanup to remove redundant base points.
|
|
969
|
+
|
|
970
|
+
Return a null pointer in case of an allocation failure.
|
|
971
|
+
"""
|
|
972
|
+
cdef int i, b, n = SC.degree
|
|
973
|
+
cdef StabilizerChain *NEW
|
|
974
|
+
if level > 0:
|
|
975
|
+
NEW = SC_copy(SC, level)
|
|
976
|
+
else:
|
|
977
|
+
NEW = SC_new(n)
|
|
978
|
+
if NEW is NULL:
|
|
979
|
+
return NULL
|
|
980
|
+
SC_add_base_point(NEW, p)
|
|
981
|
+
for i in range(level, SC.base_size):
|
|
982
|
+
b = SC.base_orbits[i][0]
|
|
983
|
+
if b != p:
|
|
984
|
+
SC_add_base_point(NEW, b)
|
|
985
|
+
if SC_update(NEW, SC, level):
|
|
986
|
+
SC_dealloc(NEW)
|
|
987
|
+
return NULL
|
|
988
|
+
return NEW
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
cdef int SC_insert_base_point_nomalloc(StabilizerChain *SC_dest, StabilizerChain *SC, int level, int p) noexcept:
|
|
992
|
+
cdef int i, b
|
|
993
|
+
SC_copy_nomalloc(SC_dest, SC, level)
|
|
994
|
+
SC_add_base_point(SC_dest, p)
|
|
995
|
+
for i in range(level, SC.base_size):
|
|
996
|
+
b = SC.base_orbits[i][0]
|
|
997
|
+
if b != p:
|
|
998
|
+
SC_add_base_point(SC_dest, b)
|
|
999
|
+
if SC_update(SC_dest, SC, level):
|
|
1000
|
+
return 1
|
|
1001
|
+
return 0
|
|
1002
|
+
|
|
1003
|
+
|
|
1004
|
+
cdef int SC_re_tree(StabilizerChain *SC, int level, int *perm, int x) noexcept:
|
|
1005
|
+
"""
|
|
1006
|
+
Return values:
|
|
1007
|
+
0 - No errors.
|
|
1008
|
+
1 - Allocation failure.
|
|
1009
|
+
"""
|
|
1010
|
+
cdef int *gen
|
|
1011
|
+
cdef int *gen_inv
|
|
1012
|
+
cdef int i, b, gen_index, n = SC.degree
|
|
1013
|
+
|
|
1014
|
+
# make sure we have room for the new generator:
|
|
1015
|
+
if SC.array_size[level] == SC.num_gens[level]:
|
|
1016
|
+
if SC_realloc_gens(SC, level, 2*SC.array_size[level]):
|
|
1017
|
+
return 1
|
|
1018
|
+
cdef int *new_gen = SC.generators[level] + n*SC.num_gens[level]
|
|
1019
|
+
cdef int *new_gen_inv = SC.gen_inverses[level] + n*SC.num_gens[level]
|
|
1020
|
+
|
|
1021
|
+
# new generator is perm^(-1) * (path from x to base) (left to right composition)
|
|
1022
|
+
SC_invert_perm(new_gen, perm, n)
|
|
1023
|
+
SC_compose_up_to_base(SC, level, x, new_gen)
|
|
1024
|
+
SC_invert_perm(new_gen_inv, new_gen, n)
|
|
1025
|
+
SC.num_gens[level] += 1
|
|
1026
|
+
|
|
1027
|
+
# now that we have our generators, regenerate the tree, breadth-first
|
|
1028
|
+
b = SC.base_orbits[level][0]
|
|
1029
|
+
for i in range(n):
|
|
1030
|
+
SC.parents[level][i] = -1
|
|
1031
|
+
SC.parents[level][b] = b
|
|
1032
|
+
i = 0
|
|
1033
|
+
SC.orbit_sizes[level] = 1
|
|
1034
|
+
while i < SC.orbit_sizes[level]:
|
|
1035
|
+
x = SC.base_orbits[level][i]
|
|
1036
|
+
for gen_index from SC.num_gens[level] > gen_index >= 0:
|
|
1037
|
+
gen_inv = SC.gen_inverses[level] + n*gen_index
|
|
1038
|
+
SC_scan(SC, level, x, gen_index, gen_inv, 1)
|
|
1039
|
+
for gen_index from 0 <= gen_index < SC.num_gens[level]:
|
|
1040
|
+
gen = SC.generators[level] + n*gen_index
|
|
1041
|
+
SC_scan(SC, level, x, gen_index, gen, -1)
|
|
1042
|
+
i += 1
|
|
1043
|
+
return 0
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
cdef int SC_sift(StabilizerChain *SC, int level, int x, int *gens, int num_gens, int *new_gens) noexcept:
|
|
1047
|
+
"""
|
|
1048
|
+
Apply Schreier's subgroup lemma[1] as follows. Given a level, a point x, and
|
|
1049
|
+
a generator s, find the coset traversal element r coming from x.
|
|
1050
|
+
Try inserting rsR(rs)^(-1) (composing left to right) on level+1, where
|
|
1051
|
+
R(g) is the coset representative of g.
|
|
1052
|
+
|
|
1053
|
+
level - which level we are currently working on
|
|
1054
|
+
x - the object representing r
|
|
1055
|
+
gens - points to the generators to sift by
|
|
1056
|
+
num_gens - how many of these there are
|
|
1057
|
+
new_gens - space of size at least num_gens*n for the sifted perms to go
|
|
1058
|
+
|
|
1059
|
+
Return 1 in case of an allocation failure.
|
|
1060
|
+
"""
|
|
1061
|
+
cdef int n = SC.degree
|
|
1062
|
+
if num_gens == 0:
|
|
1063
|
+
return 0
|
|
1064
|
+
|
|
1065
|
+
# copy a representative taking base to the point x to each of these
|
|
1066
|
+
cdef int i
|
|
1067
|
+
cdef int *temp = SC.gen_inverses[level] + n*SC.num_gens[level] # one more scratch space
|
|
1068
|
+
# (available since num_gens > 0)
|
|
1069
|
+
cdef int *rep_inv = temp
|
|
1070
|
+
SC_identify(rep_inv, n)
|
|
1071
|
+
SC_compose_up_to_base(SC, level, x, rep_inv)
|
|
1072
|
+
SC_invert_perm(new_gens, rep_inv, n)
|
|
1073
|
+
for i from 0 < i < num_gens:
|
|
1074
|
+
memcpy(new_gens + n*i, new_gens, n*sizeof(int))
|
|
1075
|
+
|
|
1076
|
+
# post-compose each one with a generator
|
|
1077
|
+
for i from 0 <= i < num_gens:
|
|
1078
|
+
SC_mult_perms(new_gens + n*i, new_gens + n*i, gens + n*i, n)
|
|
1079
|
+
|
|
1080
|
+
# for each one, look up the representative it now gives, and post-compose with that inverse
|
|
1081
|
+
cdef int y, b = SC.base_orbits[level][0]
|
|
1082
|
+
cdef int *perm
|
|
1083
|
+
cdef int *perm_rep_inv = temp
|
|
1084
|
+
for i from 0 <= i < num_gens:
|
|
1085
|
+
perm = new_gens + n*i # this is now rs
|
|
1086
|
+
y = perm[b]
|
|
1087
|
+
SC_identify(perm_rep_inv, n)
|
|
1088
|
+
SC_compose_up_to_base(SC, level, y, perm_rep_inv)
|
|
1089
|
+
SC_mult_perms(perm, perm, perm_rep_inv, n)
|
|
1090
|
+
return SC_insert(SC, level+1, new_gens, num_gens)
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
cdef int SC_insert_and_sift(StabilizerChain *SC, int level, int *pi, int num_perms, bint sift) noexcept:
|
|
1094
|
+
cdef int i, j, b, n = SC.degree
|
|
1095
|
+
cdef int perm_gen_index
|
|
1096
|
+
if sift:
|
|
1097
|
+
if SC_realloc_bitsets(SC, num_perms):
|
|
1098
|
+
return 1
|
|
1099
|
+
bitset_clear(&SC.gen_used)
|
|
1100
|
+
bitset_clear(&SC.gen_is_id)
|
|
1101
|
+
b = -1
|
|
1102
|
+
for perm_gen_index from 0 <= perm_gen_index < num_perms:
|
|
1103
|
+
for i from 0 <= i < n:
|
|
1104
|
+
if pi[n*perm_gen_index + i] != i:
|
|
1105
|
+
b = i
|
|
1106
|
+
break
|
|
1107
|
+
else:
|
|
1108
|
+
bitset_set(&SC.gen_is_id, perm_gen_index)
|
|
1109
|
+
if b != -1:
|
|
1110
|
+
break
|
|
1111
|
+
if b == -1:
|
|
1112
|
+
return 0
|
|
1113
|
+
if sift and level == SC.base_size:
|
|
1114
|
+
SC_add_base_point(SC, b)
|
|
1115
|
+
else:
|
|
1116
|
+
b = SC.base_orbits[level][0]
|
|
1117
|
+
# Now b is the base element at level `level`
|
|
1118
|
+
|
|
1119
|
+
# Record the old orbit elements and the old generators (see sifting phase)
|
|
1120
|
+
cdef int old_num_gens = SC.num_gens[level]
|
|
1121
|
+
|
|
1122
|
+
# Add new points to the tree:
|
|
1123
|
+
cdef int x
|
|
1124
|
+
cdef int *perm
|
|
1125
|
+
cdef int start_over = 1
|
|
1126
|
+
cdef int re_treed = 0
|
|
1127
|
+
while start_over:
|
|
1128
|
+
start_over = 0
|
|
1129
|
+
for i from 0 <= i < SC.orbit_sizes[level]:
|
|
1130
|
+
x = SC.base_orbits[level][i]
|
|
1131
|
+
for perm_gen_index from 0 <= perm_gen_index < num_perms:
|
|
1132
|
+
if sift and bitset_check(&SC.gen_is_id, perm_gen_index):
|
|
1133
|
+
continue
|
|
1134
|
+
perm = pi + n*perm_gen_index
|
|
1135
|
+
if SC.parents[level][perm[x]] == -1:
|
|
1136
|
+
# now we have an x which maps to a new point under perm,
|
|
1137
|
+
re_treed = 1
|
|
1138
|
+
if sift:
|
|
1139
|
+
bitset_set(&SC.gen_used, perm_gen_index)
|
|
1140
|
+
if SC_re_tree(SC, level, perm, x):
|
|
1141
|
+
return 1
|
|
1142
|
+
start_over = 1 # we must look anew
|
|
1143
|
+
break
|
|
1144
|
+
if start_over:
|
|
1145
|
+
break
|
|
1146
|
+
if not re_treed:
|
|
1147
|
+
continue
|
|
1148
|
+
for perm_gen_index from 0 <= perm_gen_index < old_num_gens:
|
|
1149
|
+
perm = SC.generators[level] + n*perm_gen_index
|
|
1150
|
+
if SC.parents[level][perm[x]] == -1:
|
|
1151
|
+
# now we have an x which maps to a new point under perm,
|
|
1152
|
+
if SC_re_tree(SC, level, perm, x):
|
|
1153
|
+
return 1
|
|
1154
|
+
start_over = 1 # we must look anew
|
|
1155
|
+
break
|
|
1156
|
+
if start_over:
|
|
1157
|
+
break
|
|
1158
|
+
for j from level < j < SC.base_size:
|
|
1159
|
+
for perm_gen_index from 0 <= perm_gen_index < SC.num_gens[j]:
|
|
1160
|
+
perm = SC.generators[j] + n*perm_gen_index
|
|
1161
|
+
if SC.parents[level][perm[x]] == -1:
|
|
1162
|
+
# now we have an x which maps to a new point under perm,
|
|
1163
|
+
if SC_re_tree(SC, level, perm, x):
|
|
1164
|
+
return 1
|
|
1165
|
+
start_over = 1 # we must look anew
|
|
1166
|
+
break
|
|
1167
|
+
if not sift:
|
|
1168
|
+
return 0
|
|
1169
|
+
|
|
1170
|
+
# store the rest of the unused generators in the generator array, after the added ones
|
|
1171
|
+
cdef int new_size
|
|
1172
|
+
cdef int unused_gens = 0
|
|
1173
|
+
for perm_gen_index from 0 <= perm_gen_index < num_perms:
|
|
1174
|
+
if not bitset_check(&SC.gen_used, perm_gen_index) and not bitset_check(&SC.gen_is_id, perm_gen_index):
|
|
1175
|
+
unused_gens += 1
|
|
1176
|
+
if 2*(SC.num_gens[level] + unused_gens) > SC.array_size[level]:
|
|
1177
|
+
new_size = max(2*(SC.num_gens[level] + unused_gens), 2*SC.array_size[level])
|
|
1178
|
+
if SC_realloc_gens(SC, level, new_size):
|
|
1179
|
+
return 1
|
|
1180
|
+
i = 0
|
|
1181
|
+
for perm_gen_index from 0 <= perm_gen_index < num_perms:
|
|
1182
|
+
if not bitset_check(&SC.gen_used, perm_gen_index) and not bitset_check(&SC.gen_is_id, perm_gen_index):
|
|
1183
|
+
memcpy(SC.generators[level] + n*(SC.num_gens[level]+i), pi + n*perm_gen_index, n*sizeof(int))
|
|
1184
|
+
i += 1
|
|
1185
|
+
|
|
1186
|
+
# Sift:
|
|
1187
|
+
cdef int *gens = SC.generators[level]
|
|
1188
|
+
cdef int total_gens = SC.num_gens[level] + unused_gens
|
|
1189
|
+
cdef int section, gens_in_section
|
|
1190
|
+
for i from 0 <= i < SC.orbit_sizes[level]:
|
|
1191
|
+
x = SC.base_orbits[level][i]
|
|
1192
|
+
section = 0
|
|
1193
|
+
while section*n < total_gens:
|
|
1194
|
+
gens_in_section = min(n, total_gens - section*n)
|
|
1195
|
+
if SC_sift(SC, level, x, gens + n*n*section, gens_in_section, gens + n*total_gens):
|
|
1196
|
+
return 1
|
|
1197
|
+
section += 1
|
|
1198
|
+
return 0
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
cdef bint SC_is_giant(int n, int num_perms, int *perms, float p, bitset_t support) noexcept:
|
|
1202
|
+
"""
|
|
1203
|
+
Test whether the group generated by the input permutations is a giant, i.e.,
|
|
1204
|
+
the alternating or symmetric group.
|
|
1205
|
+
|
|
1206
|
+
If the group is not a giant, this routine will return False. This could also
|
|
1207
|
+
indicate an allocation failure.
|
|
1208
|
+
|
|
1209
|
+
If the group is a giant, this routine will return ``True`` with approximate
|
|
1210
|
+
probability ``p``. It will set `support' to the support of the group in this
|
|
1211
|
+
case. Use bitset_len to get the size of support.
|
|
1212
|
+
|
|
1213
|
+
The bitset `support' must be initialized. Must have 0 <= p < 1.
|
|
1214
|
+
|
|
1215
|
+
Running time is roughly O(-ln(1-p)*n*ln(m)) where m <= n is the size of the
|
|
1216
|
+
support of the group.
|
|
1217
|
+
"""
|
|
1218
|
+
cdef int i, j, num_steps, support_root
|
|
1219
|
+
cdef size_t m = 1
|
|
1220
|
+
cdef unsigned long q
|
|
1221
|
+
cdef int *gen
|
|
1222
|
+
cdef int *perm = <int *> sig_malloc(n*sizeof(int))
|
|
1223
|
+
cdef OrbitPartition *OP = OP_new(n)
|
|
1224
|
+
if OP is NULL or perm is NULL:
|
|
1225
|
+
OP_dealloc(OP)
|
|
1226
|
+
sig_free(perm)
|
|
1227
|
+
return False
|
|
1228
|
+
|
|
1229
|
+
# giants are transitive
|
|
1230
|
+
for j from 0 <= j < num_perms:
|
|
1231
|
+
gen = perms + n*j
|
|
1232
|
+
for i from 0 <= i < n:
|
|
1233
|
+
OP_join(OP, i, gen[i])
|
|
1234
|
+
for i from 0 <= i < n:
|
|
1235
|
+
if OP.parent[i] == i:
|
|
1236
|
+
if OP.size[i] != 1:
|
|
1237
|
+
if m != 1:
|
|
1238
|
+
m = 1
|
|
1239
|
+
break
|
|
1240
|
+
else:
|
|
1241
|
+
m = OP.size[i]
|
|
1242
|
+
support_root = i
|
|
1243
|
+
if m == 1:
|
|
1244
|
+
OP_dealloc(OP)
|
|
1245
|
+
sig_free(perm)
|
|
1246
|
+
return False
|
|
1247
|
+
bitset_zero(support)
|
|
1248
|
+
for i from 0 <= i < n:
|
|
1249
|
+
if OP_find(OP, i) == support_root:
|
|
1250
|
+
bitset_set(support, i)
|
|
1251
|
+
|
|
1252
|
+
# get a bit lost in the group, so our random elements are more random:
|
|
1253
|
+
SC_identify(perm, n)
|
|
1254
|
+
for i from 0 <= i < 10:
|
|
1255
|
+
SC_mult_perms(perm, perm, perms + n*(rand() % num_perms), n)
|
|
1256
|
+
|
|
1257
|
+
# look for elements with cycles of prime length q, m/2 < q < m-2
|
|
1258
|
+
num_steps = <int> ceil(-log(1-p)*log(m)/log(2))
|
|
1259
|
+
for j from 0 <= j < num_steps:
|
|
1260
|
+
OP_clear(OP)
|
|
1261
|
+
for i from 0 <= i < n:
|
|
1262
|
+
OP_join(OP, i, perm[i])
|
|
1263
|
+
for i from 0 <= i < n:
|
|
1264
|
+
if OP.parent[i] == i:
|
|
1265
|
+
q = OP.size[i]
|
|
1266
|
+
if m < 2*q and q < m-2:
|
|
1267
|
+
if n_is_prime(q):
|
|
1268
|
+
sig_free(perm)
|
|
1269
|
+
OP_dealloc(OP)
|
|
1270
|
+
return True
|
|
1271
|
+
SC_mult_perms(perm, perm, perms + n*(rand() % num_perms), n)
|
|
1272
|
+
OP_dealloc(OP)
|
|
1273
|
+
sig_free(perm)
|
|
1274
|
+
return False
|
|
1275
|
+
|
|
1276
|
+
|
|
1277
|
+
def SC_test_list_perms(list L, int n, int limit, bint gap, bint limit_complain, bint test_contains):
|
|
1278
|
+
"""
|
|
1279
|
+
Test that the permutation group generated by list perms in L of degree n
|
|
1280
|
+
is of the correct order, by comparing with GAP. Don't test if the group is
|
|
1281
|
+
of size greater than limit.
|
|
1282
|
+
|
|
1283
|
+
TESTS::
|
|
1284
|
+
|
|
1285
|
+
sage: # needs sage.groups
|
|
1286
|
+
sage: from sage.groups.perm_gps.partn_ref.data_structures import SC_test_list_perms
|
|
1287
|
+
sage: limit = 10^7
|
|
1288
|
+
sage: def test_Sn_on_m_points(n, m, gap, contains):
|
|
1289
|
+
....: perm1 = [1,0] + list(range(2, m))
|
|
1290
|
+
....: perm2 = [(i+1)%n for i in range( n )] + list(range(n,m))
|
|
1291
|
+
....: SC_test_list_perms([perm1, perm2], m, limit, gap, 0, contains)
|
|
1292
|
+
sage: for i in range(2,9):
|
|
1293
|
+
....: test_Sn_on_m_points(i,i,1,0)
|
|
1294
|
+
sage: for i in range(2,9):
|
|
1295
|
+
....: test_Sn_on_m_points(i,i,0,1)
|
|
1296
|
+
sage: for i in range(2,9): # long time
|
|
1297
|
+
....: test_Sn_on_m_points(i,i,1,1)
|
|
1298
|
+
sage: test_Sn_on_m_points(8,8,1,1)
|
|
1299
|
+
sage: def test_stab_chain_fns_1(n, gap, contains):
|
|
1300
|
+
....: perm1 = sum([[2*i+1,2*i] for i in range(n)], [])
|
|
1301
|
+
....: perm2 = [(i+1)%(2*n) for i in range( 2*n)]
|
|
1302
|
+
....: SC_test_list_perms([perm1, perm2], 2*n, limit, gap, 0, contains)
|
|
1303
|
+
sage: for n in range(1,11):
|
|
1304
|
+
....: test_stab_chain_fns_1(n, 1, 0)
|
|
1305
|
+
sage: for n in range(1,11):
|
|
1306
|
+
....: test_stab_chain_fns_1(n, 0, 1)
|
|
1307
|
+
sage: for n in range(1,9): # long time
|
|
1308
|
+
....: test_stab_chain_fns_1(n, 1, 1)
|
|
1309
|
+
sage: test_stab_chain_fns_1(11, 1, 1)
|
|
1310
|
+
sage: def test_stab_chain_fns_2(n, gap, contains):
|
|
1311
|
+
....: perms = []
|
|
1312
|
+
....: for p,e in factor(n):
|
|
1313
|
+
....: perm1 = [(p*(i//p)) + ((i+1)%p) for i in range(n)]
|
|
1314
|
+
....: perms.append(perm1)
|
|
1315
|
+
....: SC_test_list_perms(perms, n, limit, gap, 0, contains)
|
|
1316
|
+
sage: for n in range(2,11):
|
|
1317
|
+
....: test_stab_chain_fns_2(n, 1, 0)
|
|
1318
|
+
sage: for n in range(2,11):
|
|
1319
|
+
....: test_stab_chain_fns_2(n, 0, 1)
|
|
1320
|
+
sage: for n in range(2,11): # long time
|
|
1321
|
+
....: test_stab_chain_fns_2(n, 1, 1)
|
|
1322
|
+
sage: test_stab_chain_fns_2(11, 1, 1)
|
|
1323
|
+
sage: def test_stab_chain_fns_3(n, gap, contains):
|
|
1324
|
+
....: perm1 = [(-i)%n for i in range( n )]
|
|
1325
|
+
....: perm2 = [(i+1)%n for i in range( n )]
|
|
1326
|
+
....: SC_test_list_perms([perm1, perm2], n, limit, gap, 0, contains)
|
|
1327
|
+
sage: for n in range(2,20):
|
|
1328
|
+
....: test_stab_chain_fns_3(n, 1, 0)
|
|
1329
|
+
sage: for n in range(2,20):
|
|
1330
|
+
....: test_stab_chain_fns_3(n, 0, 1)
|
|
1331
|
+
sage: for n in range(2,14): # long time
|
|
1332
|
+
....: test_stab_chain_fns_3(n, 1, 1)
|
|
1333
|
+
sage: test_stab_chain_fns_3(20, 1, 1)
|
|
1334
|
+
sage: def test_stab_chain_fns_4(n, g, gap, contains):
|
|
1335
|
+
....: perms = []
|
|
1336
|
+
....: for _ in range(g):
|
|
1337
|
+
....: perm = list(range(n))
|
|
1338
|
+
....: shuffle(perm)
|
|
1339
|
+
....: perms.append(perm)
|
|
1340
|
+
....: SC_test_list_perms(perms, n, limit, gap, 0, contains)
|
|
1341
|
+
sage: for n in range(4,9): # long time
|
|
1342
|
+
....: test_stab_chain_fns_4(n, 1, 1, 0)
|
|
1343
|
+
....: test_stab_chain_fns_4(n, 2, 1, 0)
|
|
1344
|
+
....: test_stab_chain_fns_4(n, 2, 1, 0)
|
|
1345
|
+
....: test_stab_chain_fns_4(n, 2, 1, 0)
|
|
1346
|
+
....: test_stab_chain_fns_4(n, 2, 1, 0)
|
|
1347
|
+
....: test_stab_chain_fns_4(n, 3, 1, 0)
|
|
1348
|
+
sage: for n in range(4,9): # known bug (see :issue:`32187`), not tested
|
|
1349
|
+
....: test_stab_chain_fns_4(n, 1, 0, 1)
|
|
1350
|
+
....: for j in range(6):
|
|
1351
|
+
....: test_stab_chain_fns_4(n, 2, 0, 1)
|
|
1352
|
+
....: test_stab_chain_fns_4(n, 3, 0, 1)
|
|
1353
|
+
sage: for n in range(4,8): # long time
|
|
1354
|
+
....: test_stab_chain_fns_4(n, 1, 1, 1)
|
|
1355
|
+
....: test_stab_chain_fns_4(n, 2, 1, 1)
|
|
1356
|
+
....: test_stab_chain_fns_4(n, 2, 1, 1)
|
|
1357
|
+
....: test_stab_chain_fns_4(n, 3, 1, 1)
|
|
1358
|
+
sage: test_stab_chain_fns_4(8, 2, 1, 1)
|
|
1359
|
+
sage: def test_stab_chain_fns_5(n, gap, contains):
|
|
1360
|
+
....: perms = []
|
|
1361
|
+
....: m = n//3
|
|
1362
|
+
....: perm1 = list(range(2*m))
|
|
1363
|
+
....: shuffle(perm1)
|
|
1364
|
+
....: perm1 += list(range(2*m,n))
|
|
1365
|
+
....: perm2 = list(range(m,n))
|
|
1366
|
+
....: shuffle(perm2)
|
|
1367
|
+
....: perm2 = list(range(m)) + perm2
|
|
1368
|
+
....: SC_test_list_perms([perm1, perm2], n, limit, gap, 0, contains)
|
|
1369
|
+
sage: for n in [4..9]: # long time
|
|
1370
|
+
....: for _ in range(2):
|
|
1371
|
+
....: test_stab_chain_fns_5(n, 1, 0)
|
|
1372
|
+
sage: for n in [4..8]: # long time
|
|
1373
|
+
....: test_stab_chain_fns_5(n, 0, 1)
|
|
1374
|
+
sage: for n in [4..9]: # long time
|
|
1375
|
+
....: test_stab_chain_fns_5(n, 1, 1)
|
|
1376
|
+
sage: def random_perm(x):
|
|
1377
|
+
....: shuffle(x)
|
|
1378
|
+
....: return x
|
|
1379
|
+
sage: def test_stab_chain_fns_6(m, n, k, gap, contains):
|
|
1380
|
+
....: perms = []
|
|
1381
|
+
....: for i in range(k):
|
|
1382
|
+
....: perm = sum([random_perm(list(range(i*(n//m),min(n,(i+1)*(n//m))))) for i in range(m)], [])
|
|
1383
|
+
....: perms.append(perm)
|
|
1384
|
+
....: SC_test_list_perms(perms, m*(n//m), limit, gap, 0, contains)
|
|
1385
|
+
sage: for m in range(2,9): # long time
|
|
1386
|
+
....: for n in range(m,3*m):
|
|
1387
|
+
....: for k in range(1,3):
|
|
1388
|
+
....: test_stab_chain_fns_6(m,n,k, 1, 0)
|
|
1389
|
+
sage: for m in range(2,10):
|
|
1390
|
+
....: for n in range(m,4*m):
|
|
1391
|
+
....: for k in range(1,3):
|
|
1392
|
+
....: test_stab_chain_fns_6(m,n,k, 0, 1)
|
|
1393
|
+
sage: test_stab_chain_fns_6(10,20,2, 1, 1)
|
|
1394
|
+
sage: test_stab_chain_fns_6(8,16,2, 1, 1)
|
|
1395
|
+
sage: test_stab_chain_fns_6(6,36,2, 1, 1)
|
|
1396
|
+
sage: test_stab_chain_fns_6(4,40,3, 1, 1)
|
|
1397
|
+
sage: test_stab_chain_fns_6(4,40,2, 1, 1)
|
|
1398
|
+
sage: def test_stab_chain_fns_7(n, cop, gap, contains):
|
|
1399
|
+
....: perms = []
|
|
1400
|
+
....: for i in range(0,n//2,2):
|
|
1401
|
+
....: p = list(range(n))
|
|
1402
|
+
....: p[i] = i+1
|
|
1403
|
+
....: p[i+1] = i
|
|
1404
|
+
....: if cop:
|
|
1405
|
+
....: perms.append([c for c in p])
|
|
1406
|
+
....: else:
|
|
1407
|
+
....: perms.append(p)
|
|
1408
|
+
....: SC_test_list_perms(perms, n, limit, gap, 0, contains)
|
|
1409
|
+
sage: for n in [6..14]:
|
|
1410
|
+
....: test_stab_chain_fns_7(n, 1, 1, 0)
|
|
1411
|
+
....: test_stab_chain_fns_7(n, 0, 1, 0)
|
|
1412
|
+
sage: for n in [6..30]:
|
|
1413
|
+
....: test_stab_chain_fns_7(n, 1, 0, 1)
|
|
1414
|
+
....: test_stab_chain_fns_7(n, 0, 0, 1)
|
|
1415
|
+
sage: for n in [6..14]: # long time
|
|
1416
|
+
....: test_stab_chain_fns_7(n, 1, 1, 1)
|
|
1417
|
+
....: test_stab_chain_fns_7(n, 0, 1, 1)
|
|
1418
|
+
sage: test_stab_chain_fns_7(20, 1, 1, 1)
|
|
1419
|
+
sage: test_stab_chain_fns_7(20, 0, 1, 1)
|
|
1420
|
+
"""
|
|
1421
|
+
if gap:
|
|
1422
|
+
from sage.groups.perm_gps.permgroup import PermutationGroup
|
|
1423
|
+
from sage.groups.perm_gps.constructor import PermutationGroupElement
|
|
1424
|
+
from sage.misc.prandom import shuffle
|
|
1425
|
+
|
|
1426
|
+
cdef StabilizerChain *SC
|
|
1427
|
+
cdef StabilizerChain *SCC
|
|
1428
|
+
cdef StabilizerChain *SCCC
|
|
1429
|
+
cdef StabilizerChain *SC_nb
|
|
1430
|
+
cdef Integer order, order2
|
|
1431
|
+
cdef int i, j, m, SC_says
|
|
1432
|
+
cdef bitset_t giant_support
|
|
1433
|
+
if gap:
|
|
1434
|
+
G = PermutationGroup([[i+1 for i in p] for p in L])
|
|
1435
|
+
if G.order() > limit:
|
|
1436
|
+
if limit_complain:
|
|
1437
|
+
print('TOO BIG')
|
|
1438
|
+
return
|
|
1439
|
+
SC = SC_new(n)
|
|
1440
|
+
cdef int *perm = <int *>sig_malloc(n * (len(L)+3) * sizeof(int))
|
|
1441
|
+
try:
|
|
1442
|
+
bitset_init(giant_support, n)
|
|
1443
|
+
except MemoryError:
|
|
1444
|
+
sig_free(perm)
|
|
1445
|
+
SC_dealloc(SC)
|
|
1446
|
+
raise MemoryError
|
|
1447
|
+
if perm is NULL or SC is NULL:
|
|
1448
|
+
bitset_free(giant_support)
|
|
1449
|
+
sig_free(perm)
|
|
1450
|
+
SC_dealloc(SC)
|
|
1451
|
+
raise MemoryError
|
|
1452
|
+
cdef int *perm2 = perm + n
|
|
1453
|
+
cdef int *perm3 = perm + 2 * n
|
|
1454
|
+
for Lperm in L:
|
|
1455
|
+
for i from 0 <= i < n:
|
|
1456
|
+
perm[i] = Lperm[i]
|
|
1457
|
+
if SC_insert(SC, 0, perm, 1):
|
|
1458
|
+
bitset_free(giant_support)
|
|
1459
|
+
sig_free(perm)
|
|
1460
|
+
SC_dealloc(SC)
|
|
1461
|
+
raise MemoryError
|
|
1462
|
+
SCC = SC_copy(SC, n)
|
|
1463
|
+
SCCC = SC_insert_base_point(SC, 0, n-1)
|
|
1464
|
+
for i from 0 <= i < n:
|
|
1465
|
+
perm[i] = n-i-1
|
|
1466
|
+
SC_nb = SC_new_base(SC, perm, n)
|
|
1467
|
+
if SCC is NULL or SCCC is NULL or SC_nb is NULL:
|
|
1468
|
+
bitset_free(giant_support)
|
|
1469
|
+
sig_free(perm)
|
|
1470
|
+
SC_dealloc(SC)
|
|
1471
|
+
SC_dealloc(SCC)
|
|
1472
|
+
SC_dealloc(SCCC)
|
|
1473
|
+
SC_dealloc(SC_nb)
|
|
1474
|
+
raise MemoryError
|
|
1475
|
+
giant = False
|
|
1476
|
+
try:
|
|
1477
|
+
order = Integer(0)
|
|
1478
|
+
SC_order(SC,0,order.value)
|
|
1479
|
+
j = 0
|
|
1480
|
+
for Lperm in L:
|
|
1481
|
+
for i from 0 <= i < n:
|
|
1482
|
+
perm[n*j + i] = Lperm[i]
|
|
1483
|
+
j += 1
|
|
1484
|
+
if SC_is_giant(n, len(L), perm, 0.9, giant_support):
|
|
1485
|
+
giant = True
|
|
1486
|
+
m = bitset_len(giant_support)
|
|
1487
|
+
from sage.arith.misc import factorial
|
|
1488
|
+
if not (order == factorial(m) or order == factorial(m)/2):
|
|
1489
|
+
print("SC_is_giant failed: %s %s" % (str(L), order))
|
|
1490
|
+
raise AssertionError
|
|
1491
|
+
if order == factorial(n):
|
|
1492
|
+
SC_dealloc(SC)
|
|
1493
|
+
SC = SC_symmetric_group(n)
|
|
1494
|
+
SC_order(SC,0,order.value)
|
|
1495
|
+
if not order == factorial(n):
|
|
1496
|
+
print("SC_symmetric_group failed: %s %s" % (str(L), order))
|
|
1497
|
+
raise AssertionError
|
|
1498
|
+
elif order == factorial(n)/2:
|
|
1499
|
+
SC_dealloc(SC)
|
|
1500
|
+
SC = SC_alternating_group(n)
|
|
1501
|
+
SC_order(SC,0,order.value)
|
|
1502
|
+
if not order == factorial(n)/2:
|
|
1503
|
+
print("SC_alternating_group failed: %s %s" % (str(L), order))
|
|
1504
|
+
raise AssertionError
|
|
1505
|
+
order2 = Integer(0)
|
|
1506
|
+
SC_order(SCC,0,order2.value)
|
|
1507
|
+
if order != order2:
|
|
1508
|
+
print("FAIL {}".format(L))
|
|
1509
|
+
print('SC_copy(n) does not agree with order of original {} {}'.format(order, order2))
|
|
1510
|
+
raise AssertionError
|
|
1511
|
+
SC_order(SCCC,0,order2.value)
|
|
1512
|
+
if order != order2:
|
|
1513
|
+
print("FAIL {}".format(L))
|
|
1514
|
+
print('does not agree with order of inserted base point {} {}'.format(order, order2))
|
|
1515
|
+
raise AssertionError
|
|
1516
|
+
SC_order(SC_nb,0,order2.value)
|
|
1517
|
+
if order != order2:
|
|
1518
|
+
print("FAIL {}".format(L))
|
|
1519
|
+
print('does not agree with order of new base {} {}'.format(order, order2))
|
|
1520
|
+
raise AssertionError
|
|
1521
|
+
if test_contains:
|
|
1522
|
+
for i from 0 <= i < 3:
|
|
1523
|
+
SC_random_element(SC, 0, perm)
|
|
1524
|
+
if not SC_contains(SC, 0, perm, 0):
|
|
1525
|
+
print("FAIL {}".format(L))
|
|
1526
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1527
|
+
print('SC_random_element says it is an element, SC_contains(modify=0) does not')
|
|
1528
|
+
raise AssertionError
|
|
1529
|
+
if not SC_contains(SC, 0, perm, 1):
|
|
1530
|
+
print("FAIL {}".format(L))
|
|
1531
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1532
|
+
print('SC_random_element says it is an element, SC_contains(modify=1) does not')
|
|
1533
|
+
raise AssertionError
|
|
1534
|
+
if not SC_contains(SCC, 0, perm, 0):
|
|
1535
|
+
print("FAIL {}".format(L))
|
|
1536
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1537
|
+
print('SC_random_element says it is an element, SC_contains(modify=0) does not on copy')
|
|
1538
|
+
raise AssertionError
|
|
1539
|
+
if not SC_contains(SCC, 0, perm, 1):
|
|
1540
|
+
print("FAIL {}".format(L))
|
|
1541
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1542
|
+
print('SC_random_element says it is an element, SC_contains(modify=1) does not on copy')
|
|
1543
|
+
raise AssertionError
|
|
1544
|
+
if not SC_contains(SCCC, 0, perm, 0):
|
|
1545
|
+
print("FAIL {}".format(L))
|
|
1546
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1547
|
+
print('SC_random_element says it is an element, SC_contains(modify=0) does not on inserted base point')
|
|
1548
|
+
raise AssertionError
|
|
1549
|
+
if not SC_contains(SCCC, 0, perm, 1):
|
|
1550
|
+
print("FAIL {}".format(L))
|
|
1551
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1552
|
+
print('SC_random_element says it is an element, SC_contains(modify=1) does not on inserted base point')
|
|
1553
|
+
raise AssertionError
|
|
1554
|
+
if not SC_contains(SC_nb, 0, perm, 0):
|
|
1555
|
+
print("FAIL {}".format(L))
|
|
1556
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1557
|
+
print('SC_random_element says it is an element, SC_contains(modify=0) does not on new base')
|
|
1558
|
+
raise AssertionError
|
|
1559
|
+
if not SC_contains(SC_nb, 0, perm, 1):
|
|
1560
|
+
print("FAIL {}".format(L))
|
|
1561
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1562
|
+
print('SC_random_element says it is an element, SC_contains(modify=1) does not on new base')
|
|
1563
|
+
raise AssertionError
|
|
1564
|
+
SC_random_element(SCC, 0, perm2)
|
|
1565
|
+
if not SC_contains(SC, 0, perm2, 0):
|
|
1566
|
+
print("FAIL {}".format(L))
|
|
1567
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1568
|
+
print('SC_random_element says it is an element of copy, SC_contains(modify=0) does not')
|
|
1569
|
+
raise AssertionError
|
|
1570
|
+
if not SC_contains(SC, 0, perm2, 1):
|
|
1571
|
+
print("FAIL {}".format(L))
|
|
1572
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1573
|
+
print('SC_random_element says it is an element of copy, SC_contains(modify=1) does not')
|
|
1574
|
+
raise AssertionError
|
|
1575
|
+
SC_random_element(SCCC, 0, perm3)
|
|
1576
|
+
if not SC_contains(SC, 0, perm3, 0):
|
|
1577
|
+
print("FAIL {}".format(L))
|
|
1578
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1579
|
+
print('SC_random_element says it is an element of inserted base point, SC_contains(modify=0) does not')
|
|
1580
|
+
raise AssertionError
|
|
1581
|
+
if not SC_contains(SC, 0, perm3, 1):
|
|
1582
|
+
print("FAIL {}".format(L))
|
|
1583
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1584
|
+
print('SC_random_element says it is an element of inserted base point, SC_contains(modify=1) does not')
|
|
1585
|
+
raise AssertionError
|
|
1586
|
+
SC_random_element(SC_nb, 0, perm3)
|
|
1587
|
+
if not SC_contains(SC, 0, perm3, 0):
|
|
1588
|
+
print("FAIL {}".format(L))
|
|
1589
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1590
|
+
print('SC_random_element says it is an element of new base, SC_contains(modify=0) does not')
|
|
1591
|
+
raise AssertionError
|
|
1592
|
+
if not SC_contains(SC, 0, perm3, 1):
|
|
1593
|
+
print("FAIL {}".format(L))
|
|
1594
|
+
print('element {}'.format([perm[ii] for ii in range(n)]))
|
|
1595
|
+
print('SC_random_element says it is an element of new base, SC_contains(modify=1) does not')
|
|
1596
|
+
raise AssertionError
|
|
1597
|
+
if gap:
|
|
1598
|
+
order = Integer(0)
|
|
1599
|
+
SC_order(SC,0,order.value)
|
|
1600
|
+
j = 0
|
|
1601
|
+
for Lperm in L:
|
|
1602
|
+
for i from 0 <= i < n:
|
|
1603
|
+
perm[n*j + i] = Lperm[i]
|
|
1604
|
+
j += 1
|
|
1605
|
+
if SC_is_giant(n, len(L), perm, 0.9, giant_support):
|
|
1606
|
+
from sage.arith.misc import factorial
|
|
1607
|
+
m = bitset_len(giant_support)
|
|
1608
|
+
if order != factorial(m) and order != factorial(m)//2:
|
|
1609
|
+
print("SC_is_giant failed: %s %s" % (str(L), order))
|
|
1610
|
+
raise AssertionError
|
|
1611
|
+
if order != G.order():
|
|
1612
|
+
print("FAIL {}".format(L))
|
|
1613
|
+
print('order was computed to be {}'.format(order))
|
|
1614
|
+
print('GAP says it is {}'.format(G.order()))
|
|
1615
|
+
raise AssertionError
|
|
1616
|
+
if test_contains:
|
|
1617
|
+
for i from 0 <= i < 3:
|
|
1618
|
+
permy = G.random_element()
|
|
1619
|
+
for j from 0 <= j < n:
|
|
1620
|
+
perm[j] = permy(j+1)-1
|
|
1621
|
+
if not SC_contains(SC, 0, perm, 0):
|
|
1622
|
+
print("FAIL {}".format(L))
|
|
1623
|
+
print('element {}'.format(permy))
|
|
1624
|
+
print('GAP says it is an element, SC_contains(modify=0) does not')
|
|
1625
|
+
raise AssertionError
|
|
1626
|
+
if not SC_contains(SC, 0, perm, 1):
|
|
1627
|
+
print("FAIL {}".format(L))
|
|
1628
|
+
print('element {}'.format(permy))
|
|
1629
|
+
print('GAP says it is an element, SC_contains(modify=1) does not')
|
|
1630
|
+
raise AssertionError
|
|
1631
|
+
permy = list(range(1, n + 1))
|
|
1632
|
+
shuffle(permy)
|
|
1633
|
+
gap_says = (PermutationGroupElement(permy) in G)
|
|
1634
|
+
for j from 0 <= j < n:
|
|
1635
|
+
perm[j] = permy[j]-1
|
|
1636
|
+
SC_says = SC_contains(SC, 0, perm, 0)
|
|
1637
|
+
if bool(SC_says) != bool(gap_says):
|
|
1638
|
+
print("FAIL {}".format(L))
|
|
1639
|
+
print('element {}'.format(permy))
|
|
1640
|
+
print('GAP says %d, SC_contains(modify=0) says %d' % (gap_says, SC_says))
|
|
1641
|
+
raise AssertionError
|
|
1642
|
+
SC_says = SC_contains(SC, 0, perm, 1)
|
|
1643
|
+
if bool(SC_says) != bool(gap_says):
|
|
1644
|
+
print("FAIL {}".format(L))
|
|
1645
|
+
print('element {}'.format(permy))
|
|
1646
|
+
print('GAP says %d, SC_contains(modify=0) says %d' % (gap_says, SC_says))
|
|
1647
|
+
raise AssertionError
|
|
1648
|
+
SC_random_element(SC, 0, perm)
|
|
1649
|
+
for j from 0 <= j < n:
|
|
1650
|
+
permy[j] = perm[j]+1
|
|
1651
|
+
gap_says = (PermutationGroupElement(permy) in G)
|
|
1652
|
+
if not SC_contains(SC, 0, perm, 0):
|
|
1653
|
+
print("FAIL {}".format(L))
|
|
1654
|
+
print('element {}'.format(permy))
|
|
1655
|
+
print('random element not contained in group, modify=false')
|
|
1656
|
+
raise AssertionError
|
|
1657
|
+
if not SC_contains(SC, 0, perm, 1):
|
|
1658
|
+
print("FAIL {}".format(L))
|
|
1659
|
+
print('element {}'.format(permy))
|
|
1660
|
+
print('random element not contained in group, modify=true')
|
|
1661
|
+
raise AssertionError
|
|
1662
|
+
if not gap_says:
|
|
1663
|
+
print("FAIL {}".format(L))
|
|
1664
|
+
print('element {}'.format(permy))
|
|
1665
|
+
print('random element not contained in group, according to GAP')
|
|
1666
|
+
raise AssertionError
|
|
1667
|
+
except Exception:
|
|
1668
|
+
if giant:
|
|
1669
|
+
print("detected giant!")
|
|
1670
|
+
raise
|
|
1671
|
+
finally:
|
|
1672
|
+
bitset_free(giant_support)
|
|
1673
|
+
sig_free(perm)
|
|
1674
|
+
SC_dealloc(SC)
|
|
1675
|
+
SC_dealloc(SCC)
|
|
1676
|
+
SC_dealloc(SCCC)
|
|
1677
|
+
SC_dealloc(SC_nb)
|
|
1678
|
+
|
|
1679
|
+
|
|
1680
|
+
# Functions
|
|
1681
|
+
|
|
1682
|
+
cdef int sort_by_function(PartitionStack *PS, int start, int *degrees) noexcept:
|
|
1683
|
+
"""
|
|
1684
|
+
A simple counting sort, given the degrees of vertices to a certain cell.
|
|
1685
|
+
|
|
1686
|
+
INPUT:
|
|
1687
|
+
|
|
1688
|
+
- ``PS`` -- the partition stack to be checked
|
|
1689
|
+
- ``start`` -- beginning index of the cell to be sorted
|
|
1690
|
+
- ``degrees`` -- the values to be sorted by, must have extra scratch space for a
|
|
1691
|
+
total of `3*n+1`
|
|
1692
|
+
"""
|
|
1693
|
+
cdef int n = PS.degree
|
|
1694
|
+
cdef int i, j, max, max_location
|
|
1695
|
+
cdef int *counts = degrees + n
|
|
1696
|
+
cdef int *output = degrees + 2*n + 1
|
|
1697
|
+
for i from 0 <= i <= n:
|
|
1698
|
+
counts[i] = 0
|
|
1699
|
+
i = 0
|
|
1700
|
+
while PS.levels[i+start] > PS.depth:
|
|
1701
|
+
counts[degrees[i]] += 1
|
|
1702
|
+
i += 1
|
|
1703
|
+
counts[degrees[i]] += 1
|
|
1704
|
+
# i+start is the right endpoint of the cell now
|
|
1705
|
+
max = counts[0]
|
|
1706
|
+
max_location = 0
|
|
1707
|
+
for j from 0 < j <= n:
|
|
1708
|
+
if counts[j] > max:
|
|
1709
|
+
max = counts[j]
|
|
1710
|
+
max_location = j
|
|
1711
|
+
counts[j] += counts[j - 1]
|
|
1712
|
+
for j from i >= j >= 0:
|
|
1713
|
+
counts[degrees[j]] -= 1
|
|
1714
|
+
output[counts[degrees[j]]] = PS.entries[start+j]
|
|
1715
|
+
max_location = counts[max_location]+start
|
|
1716
|
+
for j from 0 <= j <= i:
|
|
1717
|
+
PS.entries[start+j] = output[j]
|
|
1718
|
+
j = 1
|
|
1719
|
+
while j <= n and counts[j] <= i:
|
|
1720
|
+
if counts[j] > 0:
|
|
1721
|
+
PS.levels[start + counts[j] - 1] = PS.depth
|
|
1722
|
+
PS_move_min_to_front(PS, start + counts[j-1], start + counts[j] - 1)
|
|
1723
|
+
j += 1
|
|
1724
|
+
return max_location
|
|
1725
|
+
|
|
1726
|
+
|
|
1727
|
+
cdef int refine_by_orbits(PartitionStack *PS, StabilizerChain *SC, int *perm_stack, int *cells_to_refine_by, int *ctrb_len) noexcept:
|
|
1728
|
+
"""
|
|
1729
|
+
Given a stabilizer chain SC, refine the partition stack PS so that each cell
|
|
1730
|
+
contains elements from at most one orbit, and sort the refined cells by
|
|
1731
|
+
their minimal cell representatives in the orbit of the group.
|
|
1732
|
+
"""
|
|
1733
|
+
cdef int start, level, gen_index, i, j, k, x, n = SC.degree
|
|
1734
|
+
cdef int *gen
|
|
1735
|
+
cdef int *min_cell_reps = SC.perm_scratch
|
|
1736
|
+
cdef int *perm = perm_stack + n*PS.depth
|
|
1737
|
+
cdef OrbitPartition *OP = SC.OP_scratch
|
|
1738
|
+
cdef int invariant = 1
|
|
1739
|
+
OP_clear(OP)
|
|
1740
|
+
for level from PS.depth <= level < SC.base_size:
|
|
1741
|
+
for gen_index from 0 <= gen_index < SC.num_gens[level]:
|
|
1742
|
+
gen = SC.generators[level] + gen_index*n
|
|
1743
|
+
for i from 0 <= i < n:
|
|
1744
|
+
OP_join(OP, i, gen[i])
|
|
1745
|
+
start = 0
|
|
1746
|
+
while start < n:
|
|
1747
|
+
i = 0
|
|
1748
|
+
while 1:
|
|
1749
|
+
x = PS.entries[start+i]
|
|
1750
|
+
x = perm[x]
|
|
1751
|
+
min_cell_reps[i] = OP.mcr[OP_find(OP, x)]
|
|
1752
|
+
i += 1
|
|
1753
|
+
if PS.levels[start+i-1] <= PS.depth:
|
|
1754
|
+
break
|
|
1755
|
+
invariant += sort_by_function(PS, start, min_cell_reps)
|
|
1756
|
+
invariant += i
|
|
1757
|
+
# update cells_to_refine_by
|
|
1758
|
+
k = start
|
|
1759
|
+
for j from start <= j < start+i:
|
|
1760
|
+
if PS.levels[j] == PS.depth:
|
|
1761
|
+
k = j+1
|
|
1762
|
+
cells_to_refine_by[ctrb_len[0]] = k
|
|
1763
|
+
ctrb_len[0] += 1
|
|
1764
|
+
start += i
|
|
1765
|
+
return invariant
|
|
1766
|
+
|
|
1767
|
+
|
|
1768
|
+
cdef int compute_relabeling(StabilizerChain *group, StabilizerChain *scratch_group,
|
|
1769
|
+
int *permutation, int *relabeling) noexcept:
|
|
1770
|
+
"""
|
|
1771
|
+
Technically, compute the INVERSE of the relabeling
|
|
1772
|
+
"""
|
|
1773
|
+
cdef int i, j, x, y, m, n = group.degree, orbit_element
|
|
1774
|
+
cdef int *scratch = group.perm_scratch
|
|
1775
|
+
if SC_new_base_nomalloc(scratch_group, group, permutation, n):
|
|
1776
|
+
return 1
|
|
1777
|
+
group = scratch_group
|
|
1778
|
+
SC_identify(relabeling, n)
|
|
1779
|
+
for i from 0 <= i < n:
|
|
1780
|
+
m = n
|
|
1781
|
+
for j from 0 <= j < group.orbit_sizes[i]:
|
|
1782
|
+
orbit_element = group.base_orbits[i][j]
|
|
1783
|
+
x = relabeling[orbit_element]
|
|
1784
|
+
if x < m:
|
|
1785
|
+
m = x
|
|
1786
|
+
y = orbit_element
|
|
1787
|
+
SC_invert_perm(scratch, relabeling, n)
|
|
1788
|
+
SC_compose_up_to_base(group, i, y, scratch)
|
|
1789
|
+
SC_invert_perm(relabeling, scratch, n)
|
|
1790
|
+
SC_invert_perm(scratch, relabeling, n)
|
|
1791
|
+
memcpy(relabeling, scratch, n*sizeof(int))
|
|
1792
|
+
return 0
|