passagemath-modules 10.6.31rc3__cp314-cp314-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.
Potentially problematic release.
This version of passagemath-modules might be problematic. Click here for more details.
- passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
- passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_modules.libs/libgfortran-67378ab2.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-23768756.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-7897025b.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-e34bb864.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-503f0c35.3.29.so +0 -0
- sage/algebras/all__sagemath_modules.py +20 -0
- sage/algebras/catalog.py +148 -0
- sage/algebras/clifford_algebra.py +3107 -0
- sage/algebras/clifford_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/clifford_algebra_element.pxd +16 -0
- sage/algebras/clifford_algebra_element.pyx +997 -0
- sage/algebras/commutative_dga.py +4252 -0
- sage/algebras/exterior_algebra_groebner.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/exterior_algebra_groebner.pxd +55 -0
- sage/algebras/exterior_algebra_groebner.pyx +727 -0
- sage/algebras/finite_dimensional_algebras/all.py +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
- sage/algebras/finite_gca.py +528 -0
- sage/algebras/group_algebra.py +232 -0
- sage/algebras/lie_algebras/abelian.py +197 -0
- sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
- sage/algebras/lie_algebras/all.py +25 -0
- sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
- sage/algebras/lie_algebras/bch.py +177 -0
- sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
- sage/algebras/lie_algebras/bgg_resolution.py +232 -0
- sage/algebras/lie_algebras/center_uea.py +767 -0
- sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
- sage/algebras/lie_algebras/examples.py +683 -0
- sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
- sage/algebras/lie_algebras/heisenberg.py +820 -0
- sage/algebras/lie_algebras/lie_algebra.py +1562 -0
- sage/algebras/lie_algebras/lie_algebra_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
- sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
- sage/algebras/lie_algebras/morphism.py +661 -0
- sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
- sage/algebras/lie_algebras/onsager.py +1324 -0
- sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
- sage/algebras/lie_algebras/quotient.py +462 -0
- sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
- sage/algebras/lie_algebras/representation.py +1040 -0
- sage/algebras/lie_algebras/structure_coefficients.py +459 -0
- sage/algebras/lie_algebras/subalgebra.py +967 -0
- sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
- sage/algebras/lie_algebras/verma_module.py +1630 -0
- sage/algebras/lie_algebras/virasoro.py +1186 -0
- sage/algebras/octonion_algebra.cpython-314-aarch64-linux-musl.so +0 -0
- sage/algebras/octonion_algebra.pxd +20 -0
- sage/algebras/octonion_algebra.pyx +987 -0
- sage/algebras/orlik_solomon.py +907 -0
- sage/algebras/orlik_terao.py +779 -0
- sage/algebras/steenrod/all.py +7 -0
- sage/algebras/steenrod/steenrod_algebra.py +4258 -0
- sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
- sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
- sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
- sage/algebras/weyl_algebra.py +1126 -0
- sage/all__sagemath_modules.py +62 -0
- sage/calculus/all__sagemath_modules.py +19 -0
- sage/calculus/expr.py +205 -0
- sage/calculus/integration.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/riemann.pyx +1521 -0
- sage/calculus/test_sympy.py +201 -0
- sage/calculus/transforms/all.py +7 -0
- sage/calculus/transforms/dft.py +844 -0
- sage/calculus/transforms/dwt.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/transforms/dwt.pxd +7 -0
- sage/calculus/transforms/dwt.pyx +160 -0
- sage/calculus/transforms/fft.cpython-314-aarch64-linux-musl.so +0 -0
- sage/calculus/transforms/fft.pxd +12 -0
- sage/calculus/transforms/fft.pyx +487 -0
- sage/calculus/wester.py +662 -0
- sage/coding/abstract_code.py +1108 -0
- sage/coding/ag_code.py +868 -0
- sage/coding/ag_code_decoders.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/ag_code_decoders.pyx +2639 -0
- sage/coding/all.py +15 -0
- sage/coding/bch_code.py +494 -0
- sage/coding/binary_code.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/binary_code.pxd +124 -0
- sage/coding/binary_code.pyx +4139 -0
- sage/coding/bounds_catalog.py +43 -0
- sage/coding/channel.py +819 -0
- sage/coding/channels_catalog.py +29 -0
- sage/coding/code_bounds.py +755 -0
- sage/coding/code_constructions.py +804 -0
- sage/coding/codes_catalog.py +111 -0
- sage/coding/cyclic_code.py +1329 -0
- sage/coding/databases.py +316 -0
- sage/coding/decoder.py +373 -0
- sage/coding/decoders_catalog.py +88 -0
- sage/coding/delsarte_bounds.py +709 -0
- sage/coding/encoder.py +390 -0
- sage/coding/encoders_catalog.py +64 -0
- sage/coding/extended_code.py +468 -0
- sage/coding/gabidulin_code.py +1058 -0
- sage/coding/golay_code.py +404 -0
- sage/coding/goppa_code.py +441 -0
- sage/coding/grs_code.py +2371 -0
- sage/coding/guava.py +107 -0
- sage/coding/guruswami_sudan/all.py +1 -0
- sage/coding/guruswami_sudan/gs_decoder.py +897 -0
- sage/coding/guruswami_sudan/interpolation.py +409 -0
- sage/coding/guruswami_sudan/utils.py +176 -0
- sage/coding/hamming_code.py +176 -0
- sage/coding/information_set_decoder.py +1032 -0
- sage/coding/kasami_codes.cpython-314-aarch64-linux-musl.so +0 -0
- sage/coding/kasami_codes.pyx +351 -0
- sage/coding/linear_code.py +3067 -0
- sage/coding/linear_code_no_metric.py +1354 -0
- sage/coding/linear_rank_metric.py +961 -0
- sage/coding/parity_check_code.py +353 -0
- sage/coding/punctured_code.py +719 -0
- sage/coding/reed_muller_code.py +999 -0
- sage/coding/self_dual_codes.py +942 -0
- sage/coding/source_coding/all.py +2 -0
- sage/coding/source_coding/huffman.py +553 -0
- sage/coding/subfield_subcode.py +423 -0
- sage/coding/two_weight_db.py +399 -0
- sage/combinat/all__sagemath_modules.py +7 -0
- sage/combinat/cartesian_product.py +347 -0
- sage/combinat/family.py +11 -0
- sage/combinat/free_module.py +1977 -0
- sage/combinat/root_system/all.py +147 -0
- sage/combinat/root_system/ambient_space.py +527 -0
- sage/combinat/root_system/associahedron.py +471 -0
- sage/combinat/root_system/braid_move_calculator.py +143 -0
- sage/combinat/root_system/braid_orbit.cpython-314-aarch64-linux-musl.so +0 -0
- sage/combinat/root_system/braid_orbit.pyx +144 -0
- sage/combinat/root_system/branching_rules.py +2301 -0
- sage/combinat/root_system/cartan_matrix.py +1245 -0
- sage/combinat/root_system/cartan_type.py +3069 -0
- sage/combinat/root_system/coxeter_group.py +162 -0
- sage/combinat/root_system/coxeter_matrix.py +1261 -0
- sage/combinat/root_system/coxeter_type.py +681 -0
- sage/combinat/root_system/dynkin_diagram.py +900 -0
- sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
- sage/combinat/root_system/fundamental_group.py +795 -0
- sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
- sage/combinat/root_system/integrable_representations.py +1227 -0
- sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
- sage/combinat/root_system/pieri_factors.py +1147 -0
- sage/combinat/root_system/plot.py +1615 -0
- sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
- sage/combinat/root_system/root_lattice_realizations.py +4628 -0
- sage/combinat/root_system/root_space.py +487 -0
- sage/combinat/root_system/root_system.py +882 -0
- sage/combinat/root_system/type_A.py +348 -0
- sage/combinat/root_system/type_A_affine.py +227 -0
- sage/combinat/root_system/type_A_infinity.py +241 -0
- sage/combinat/root_system/type_B.py +347 -0
- sage/combinat/root_system/type_BC_affine.py +287 -0
- sage/combinat/root_system/type_B_affine.py +216 -0
- sage/combinat/root_system/type_C.py +317 -0
- sage/combinat/root_system/type_C_affine.py +188 -0
- sage/combinat/root_system/type_D.py +357 -0
- sage/combinat/root_system/type_D_affine.py +208 -0
- sage/combinat/root_system/type_E.py +641 -0
- sage/combinat/root_system/type_E_affine.py +231 -0
- sage/combinat/root_system/type_F.py +387 -0
- sage/combinat/root_system/type_F_affine.py +137 -0
- sage/combinat/root_system/type_G.py +293 -0
- sage/combinat/root_system/type_G_affine.py +132 -0
- sage/combinat/root_system/type_H.py +105 -0
- sage/combinat/root_system/type_I.py +110 -0
- sage/combinat/root_system/type_Q.py +150 -0
- sage/combinat/root_system/type_affine.py +509 -0
- sage/combinat/root_system/type_dual.py +704 -0
- sage/combinat/root_system/type_folded.py +301 -0
- sage/combinat/root_system/type_marked.py +748 -0
- sage/combinat/root_system/type_reducible.py +601 -0
- sage/combinat/root_system/type_relabel.py +730 -0
- sage/combinat/root_system/type_super_A.py +837 -0
- sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
- sage/combinat/root_system/weight_space.py +639 -0
- sage/combinat/root_system/weyl_characters.py +2238 -0
- sage/crypto/__init__.py +4 -0
- sage/crypto/all.py +28 -0
- sage/crypto/block_cipher/all.py +7 -0
- sage/crypto/block_cipher/des.py +1065 -0
- sage/crypto/block_cipher/miniaes.py +2171 -0
- sage/crypto/block_cipher/present.py +909 -0
- sage/crypto/block_cipher/sdes.py +1527 -0
- sage/crypto/boolean_function.cpython-314-aarch64-linux-musl.so +0 -0
- sage/crypto/boolean_function.pxd +10 -0
- sage/crypto/boolean_function.pyx +1487 -0
- sage/crypto/cipher.py +78 -0
- sage/crypto/classical.py +3668 -0
- sage/crypto/classical_cipher.py +569 -0
- sage/crypto/cryptosystem.py +387 -0
- sage/crypto/key_exchange/all.py +7 -0
- sage/crypto/key_exchange/catalog.py +24 -0
- sage/crypto/key_exchange/diffie_hellman.py +323 -0
- sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
- sage/crypto/lattice.py +312 -0
- sage/crypto/lfsr.py +295 -0
- sage/crypto/lwe.py +840 -0
- sage/crypto/mq/__init__.py +4 -0
- sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
- sage/crypto/mq/rijndael_gf.py +2345 -0
- sage/crypto/mq/sbox.py +7 -0
- sage/crypto/mq/sr.py +3344 -0
- sage/crypto/public_key/all.py +5 -0
- sage/crypto/public_key/blum_goldwasser.py +776 -0
- sage/crypto/sbox.cpython-314-aarch64-linux-musl.so +0 -0
- sage/crypto/sbox.pyx +2090 -0
- sage/crypto/sboxes.py +2090 -0
- sage/crypto/stream.py +390 -0
- sage/crypto/stream_cipher.py +297 -0
- sage/crypto/util.py +519 -0
- sage/ext/all__sagemath_modules.py +1 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_modules.py +2 -0
- sage/ext/interpreters/wrapper_cc.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_cc.pxd +30 -0
- sage/ext/interpreters/wrapper_cc.pyx +252 -0
- sage/ext/interpreters/wrapper_cdf.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_cdf.pxd +26 -0
- sage/ext/interpreters/wrapper_cdf.pyx +245 -0
- sage/ext/interpreters/wrapper_rdf.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_rdf.pxd +23 -0
- sage/ext/interpreters/wrapper_rdf.pyx +221 -0
- sage/ext/interpreters/wrapper_rr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_rr.pxd +28 -0
- sage/ext/interpreters/wrapper_rr.pyx +335 -0
- sage/geometry/all__sagemath_modules.py +5 -0
- sage/geometry/toric_lattice.py +1745 -0
- sage/geometry/toric_lattice_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/geometry/toric_lattice_element.pyx +432 -0
- sage/groups/abelian_gps/abelian_group.py +1925 -0
- sage/groups/abelian_gps/abelian_group_element.py +164 -0
- sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
- sage/groups/abelian_gps/dual_abelian_group.py +421 -0
- sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
- sage/groups/abelian_gps/element_base.py +341 -0
- sage/groups/abelian_gps/values.py +488 -0
- sage/groups/additive_abelian/additive_abelian_group.py +476 -0
- sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
- sage/groups/additive_abelian/all.py +4 -0
- sage/groups/additive_abelian/qmodnz.py +231 -0
- sage/groups/additive_abelian/qmodnz_element.py +349 -0
- sage/groups/affine_gps/affine_group.py +535 -0
- sage/groups/affine_gps/all.py +1 -0
- sage/groups/affine_gps/catalog.py +17 -0
- sage/groups/affine_gps/euclidean_group.py +246 -0
- sage/groups/affine_gps/group_element.py +562 -0
- sage/groups/all__sagemath_modules.py +12 -0
- sage/groups/galois_group.py +479 -0
- sage/groups/matrix_gps/all.py +4 -0
- sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
- sage/groups/matrix_gps/catalog.py +26 -0
- sage/groups/matrix_gps/coxeter_group.py +927 -0
- sage/groups/matrix_gps/finitely_generated.py +487 -0
- sage/groups/matrix_gps/group_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/matrix_gps/group_element.pxd +11 -0
- sage/groups/matrix_gps/group_element.pyx +431 -0
- sage/groups/matrix_gps/linear.py +440 -0
- sage/groups/matrix_gps/matrix_group.py +617 -0
- sage/groups/matrix_gps/named_group.py +296 -0
- sage/groups/matrix_gps/orthogonal.py +544 -0
- sage/groups/matrix_gps/symplectic.py +251 -0
- sage/groups/matrix_gps/unitary.py +436 -0
- sage/groups/misc_gps/all__sagemath_modules.py +1 -0
- sage/groups/misc_gps/argument_groups.py +1905 -0
- sage/groups/misc_gps/imaginary_groups.py +479 -0
- sage/groups/perm_gps/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
- sage/homology/algebraic_topological_model.py +595 -0
- sage/homology/all.py +2 -0
- sage/homology/all__sagemath_modules.py +8 -0
- sage/homology/chain_complex.py +2148 -0
- sage/homology/chain_complex_homspace.py +165 -0
- sage/homology/chain_complex_morphism.py +629 -0
- sage/homology/chain_homotopy.py +604 -0
- sage/homology/chains.py +653 -0
- sage/homology/free_resolution.py +923 -0
- sage/homology/graded_resolution.py +567 -0
- sage/homology/hochschild_complex.py +756 -0
- sage/homology/homology_group.py +188 -0
- sage/homology/homology_morphism.py +422 -0
- sage/homology/homology_vector_space_with_basis.py +1454 -0
- sage/homology/koszul_complex.py +169 -0
- sage/homology/matrix_utils.py +205 -0
- sage/libs/all__sagemath_modules.py +1 -0
- sage/libs/gsl/__init__.py +1 -0
- sage/libs/gsl/airy.pxd +56 -0
- sage/libs/gsl/all.pxd +66 -0
- sage/libs/gsl/array.cpython-314-aarch64-linux-musl.so +0 -0
- sage/libs/gsl/array.pxd +5 -0
- sage/libs/gsl/array.pyx +102 -0
- sage/libs/gsl/bessel.pxd +208 -0
- sage/libs/gsl/blas.pxd +116 -0
- sage/libs/gsl/blas_types.pxd +34 -0
- sage/libs/gsl/block.pxd +52 -0
- sage/libs/gsl/chebyshev.pxd +37 -0
- sage/libs/gsl/clausen.pxd +12 -0
- sage/libs/gsl/combination.pxd +47 -0
- sage/libs/gsl/complex.pxd +151 -0
- sage/libs/gsl/coulomb.pxd +30 -0
- sage/libs/gsl/coupling.pxd +21 -0
- sage/libs/gsl/dawson.pxd +12 -0
- sage/libs/gsl/debye.pxd +24 -0
- sage/libs/gsl/dilog.pxd +14 -0
- sage/libs/gsl/eigen.pxd +46 -0
- sage/libs/gsl/elementary.pxd +12 -0
- sage/libs/gsl/ellint.pxd +48 -0
- sage/libs/gsl/elljac.pxd +8 -0
- sage/libs/gsl/erf.pxd +32 -0
- sage/libs/gsl/errno.pxd +26 -0
- sage/libs/gsl/exp.pxd +44 -0
- sage/libs/gsl/expint.pxd +44 -0
- sage/libs/gsl/fermi_dirac.pxd +44 -0
- sage/libs/gsl/fft.pxd +121 -0
- sage/libs/gsl/fit.pxd +50 -0
- sage/libs/gsl/gamma.pxd +94 -0
- sage/libs/gsl/gegenbauer.pxd +26 -0
- sage/libs/gsl/histogram.pxd +176 -0
- sage/libs/gsl/hyperg.pxd +52 -0
- sage/libs/gsl/integration.pxd +69 -0
- sage/libs/gsl/interp.pxd +109 -0
- sage/libs/gsl/laguerre.pxd +24 -0
- sage/libs/gsl/lambert.pxd +16 -0
- sage/libs/gsl/legendre.pxd +90 -0
- sage/libs/gsl/linalg.pxd +185 -0
- sage/libs/gsl/log.pxd +26 -0
- sage/libs/gsl/math.pxd +43 -0
- sage/libs/gsl/matrix.pxd +143 -0
- sage/libs/gsl/matrix_complex.pxd +130 -0
- sage/libs/gsl/min.pxd +67 -0
- sage/libs/gsl/monte.pxd +56 -0
- sage/libs/gsl/ntuple.pxd +32 -0
- sage/libs/gsl/odeiv.pxd +70 -0
- sage/libs/gsl/permutation.pxd +78 -0
- sage/libs/gsl/poly.pxd +40 -0
- sage/libs/gsl/pow_int.pxd +12 -0
- sage/libs/gsl/psi.pxd +28 -0
- sage/libs/gsl/qrng.pxd +29 -0
- sage/libs/gsl/random.pxd +257 -0
- sage/libs/gsl/rng.pxd +100 -0
- sage/libs/gsl/roots.pxd +72 -0
- sage/libs/gsl/sort.pxd +36 -0
- sage/libs/gsl/statistics.pxd +59 -0
- sage/libs/gsl/sum.pxd +55 -0
- sage/libs/gsl/synchrotron.pxd +16 -0
- sage/libs/gsl/transport.pxd +24 -0
- sage/libs/gsl/trig.pxd +58 -0
- sage/libs/gsl/types.pxd +137 -0
- sage/libs/gsl/vector.pxd +101 -0
- sage/libs/gsl/vector_complex.pxd +83 -0
- sage/libs/gsl/wavelet.pxd +49 -0
- sage/libs/gsl/zeta.pxd +28 -0
- sage/libs/mpc/__init__.pxd +114 -0
- sage/libs/mpc/types.pxd +28 -0
- sage/libs/mpfr/__init__.pxd +299 -0
- sage/libs/mpfr/types.pxd +26 -0
- sage/libs/mpmath/__init__.py +1 -0
- sage/libs/mpmath/all.py +27 -0
- sage/libs/mpmath/all__sagemath_modules.py +1 -0
- sage/libs/mpmath/utils.cpython-314-aarch64-linux-musl.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/action.pxd +26 -0
- sage/matrix/action.pyx +596 -0
- sage/matrix/all.py +9 -0
- sage/matrix/args.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/args.pxd +144 -0
- sage/matrix/args.pyx +1668 -0
- sage/matrix/benchmark.py +1258 -0
- sage/matrix/berlekamp_massey.py +95 -0
- sage/matrix/compute_J_ideal.py +926 -0
- sage/matrix/constructor.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_cdv.pxd +4 -0
- sage/matrix/matrix_cdv.pyx +93 -0
- sage/matrix/matrix_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_complex_double_dense.pxd +5 -0
- sage/matrix/matrix_complex_double_dense.pyx +98 -0
- sage/matrix/matrix_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_dense.pxd +5 -0
- sage/matrix/matrix_dense.pyx +343 -0
- sage/matrix/matrix_domain_dense.pxd +5 -0
- sage/matrix/matrix_domain_sparse.pxd +5 -0
- sage/matrix/matrix_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_double_dense.pxd +7 -0
- sage/matrix/matrix_double_dense.pyx +3906 -0
- sage/matrix/matrix_double_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_double_sparse.pxd +6 -0
- sage/matrix/matrix_double_sparse.pyx +248 -0
- sage/matrix/matrix_generic_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_generic_dense.pxd +7 -0
- sage/matrix/matrix_generic_dense.pyx +354 -0
- sage/matrix/matrix_generic_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_generic_sparse.pxd +7 -0
- sage/matrix/matrix_generic_sparse.pyx +461 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
- sage/matrix/matrix_misc.py +313 -0
- sage/matrix/matrix_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_numpy_dense.pxd +14 -0
- sage/matrix/matrix_numpy_dense.pyx +450 -0
- sage/matrix/matrix_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
- sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
- sage/matrix/matrix_polynomial_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_polynomial_dense.pxd +5 -0
- sage/matrix/matrix_polynomial_dense.pyx +5341 -0
- sage/matrix/matrix_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_real_double_dense.pxd +7 -0
- sage/matrix/matrix_real_double_dense.pyx +122 -0
- sage/matrix/matrix_space.py +2848 -0
- sage/matrix/matrix_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_sparse.pxd +5 -0
- sage/matrix/matrix_sparse.pyx +1222 -0
- sage/matrix/matrix_window.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_window.pxd +37 -0
- sage/matrix/matrix_window.pyx +242 -0
- sage/matrix/misc_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/misc_mpfr.pyx +80 -0
- sage/matrix/operation_table.py +1182 -0
- sage/matrix/special.py +3666 -0
- sage/matrix/strassen.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matrix/strassen.pyx +851 -0
- sage/matrix/symplectic_basis.py +541 -0
- sage/matrix/template.pxd +6 -0
- sage/matrix/tests.py +71 -0
- sage/matroids/advanced.py +77 -0
- sage/matroids/all.py +13 -0
- sage/matroids/basis_exchange_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/basis_exchange_matroid.pxd +96 -0
- sage/matroids/basis_exchange_matroid.pyx +2344 -0
- sage/matroids/basis_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/basis_matroid.pxd +45 -0
- sage/matroids/basis_matroid.pyx +1217 -0
- sage/matroids/catalog.py +44 -0
- sage/matroids/chow_ring.py +473 -0
- sage/matroids/chow_ring_ideal.py +849 -0
- sage/matroids/circuit_closures_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/circuit_closures_matroid.pxd +16 -0
- sage/matroids/circuit_closures_matroid.pyx +559 -0
- sage/matroids/circuits_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/circuits_matroid.pxd +38 -0
- sage/matroids/circuits_matroid.pyx +947 -0
- sage/matroids/constructor.py +1086 -0
- sage/matroids/database_collections.py +365 -0
- sage/matroids/database_matroids.py +5338 -0
- sage/matroids/dual_matroid.py +583 -0
- sage/matroids/extension.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/flats_matroid.pxd +28 -0
- sage/matroids/flats_matroid.pyx +715 -0
- sage/matroids/gammoid.py +600 -0
- sage/matroids/graphic_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/graphic_matroid.pxd +39 -0
- sage/matroids/graphic_matroid.pyx +2024 -0
- sage/matroids/lean_matrix.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/lean_matrix.pxd +126 -0
- sage/matroids/lean_matrix.pyx +3667 -0
- sage/matroids/linear_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/matroid.pxd +243 -0
- sage/matroids/matroid.pyx +8759 -0
- sage/matroids/matroids_catalog.py +190 -0
- sage/matroids/matroids_plot_helpers.py +890 -0
- sage/matroids/minor_matroid.py +480 -0
- sage/matroids/minorfix.h +9 -0
- sage/matroids/named_matroids.py +5 -0
- sage/matroids/rank_matroid.py +268 -0
- sage/matroids/set_system.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/set_system.pxd +38 -0
- sage/matroids/set_system.pyx +800 -0
- sage/matroids/transversal_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/transversal_matroid.pxd +14 -0
- sage/matroids/transversal_matroid.pyx +893 -0
- sage/matroids/union_matroid.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-aarch64-linux-musl.so +0 -0
- sage/matroids/unpickling.pyx +843 -0
- sage/matroids/utilities.py +809 -0
- sage/misc/all__sagemath_modules.py +20 -0
- sage/misc/c3.cpython-314-aarch64-linux-musl.so +0 -0
- sage/misc/c3.pyx +238 -0
- sage/misc/compat.py +87 -0
- sage/misc/element_with_label.py +173 -0
- sage/misc/func_persist.py +79 -0
- sage/misc/pickle_old.cpython-314-aarch64-linux-musl.so +0 -0
- sage/misc/pickle_old.pyx +19 -0
- sage/misc/proof.py +7 -0
- sage/misc/replace_dot_all.py +472 -0
- sage/misc/sagedoc_conf.py +168 -0
- sage/misc/sphinxify.py +167 -0
- sage/misc/test_class_pickling.py +85 -0
- sage/modules/all.py +42 -0
- sage/modules/complex_double_vector.py +25 -0
- sage/modules/diamond_cutting.py +380 -0
- sage/modules/fg_pid/all.py +1 -0
- sage/modules/fg_pid/fgp_element.py +456 -0
- sage/modules/fg_pid/fgp_module.py +2091 -0
- sage/modules/fg_pid/fgp_morphism.py +550 -0
- sage/modules/filtered_vector_space.py +1271 -0
- sage/modules/finite_submodule_iter.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/finite_submodule_iter.pxd +27 -0
- sage/modules/finite_submodule_iter.pyx +452 -0
- sage/modules/fp_graded/all.py +1 -0
- sage/modules/fp_graded/element.py +346 -0
- sage/modules/fp_graded/free_element.py +298 -0
- sage/modules/fp_graded/free_homspace.py +53 -0
- sage/modules/fp_graded/free_module.py +1060 -0
- sage/modules/fp_graded/free_morphism.py +217 -0
- sage/modules/fp_graded/homspace.py +563 -0
- sage/modules/fp_graded/module.py +1340 -0
- sage/modules/fp_graded/morphism.py +1990 -0
- sage/modules/fp_graded/steenrod/all.py +1 -0
- sage/modules/fp_graded/steenrod/homspace.py +65 -0
- sage/modules/fp_graded/steenrod/module.py +477 -0
- sage/modules/fp_graded/steenrod/morphism.py +404 -0
- sage/modules/fp_graded/steenrod/profile.py +241 -0
- sage/modules/free_module.py +8447 -0
- sage/modules/free_module_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/free_module_element.pxd +22 -0
- sage/modules/free_module_element.pyx +5445 -0
- sage/modules/free_module_homspace.py +369 -0
- sage/modules/free_module_integer.py +896 -0
- sage/modules/free_module_morphism.py +823 -0
- sage/modules/free_module_pseudohomspace.py +352 -0
- sage/modules/free_module_pseudomorphism.py +578 -0
- sage/modules/free_quadratic_module.py +1706 -0
- sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
- sage/modules/matrix_morphism.py +1745 -0
- sage/modules/misc.py +103 -0
- sage/modules/module_functors.py +192 -0
- sage/modules/multi_filtered_vector_space.py +719 -0
- sage/modules/ore_module.py +2208 -0
- sage/modules/ore_module_element.py +178 -0
- sage/modules/ore_module_homspace.py +147 -0
- sage/modules/ore_module_morphism.py +968 -0
- sage/modules/quotient_module.py +699 -0
- sage/modules/real_double_vector.py +22 -0
- sage/modules/submodule.py +255 -0
- sage/modules/tensor_operations.py +567 -0
- sage/modules/torsion_quadratic_module.py +1352 -0
- sage/modules/tutorial_free_modules.py +248 -0
- sage/modules/vector_complex_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_complex_double_dense.pxd +6 -0
- sage/modules/vector_complex_double_dense.pyx +117 -0
- sage/modules/vector_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_double_dense.pxd +6 -0
- sage/modules/vector_double_dense.pyx +604 -0
- sage/modules/vector_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_integer_dense.pxd +15 -0
- sage/modules/vector_integer_dense.pyx +361 -0
- sage/modules/vector_integer_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_integer_sparse.pxd +29 -0
- sage/modules/vector_integer_sparse.pyx +406 -0
- sage/modules/vector_modn_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_modn_dense.pxd +12 -0
- sage/modules/vector_modn_dense.pyx +394 -0
- sage/modules/vector_modn_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_modn_sparse.pxd +21 -0
- sage/modules/vector_modn_sparse.pyx +298 -0
- sage/modules/vector_numpy_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_numpy_dense.pxd +15 -0
- sage/modules/vector_numpy_dense.pyx +304 -0
- sage/modules/vector_numpy_integer_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_numpy_integer_dense.pxd +7 -0
- sage/modules/vector_numpy_integer_dense.pyx +54 -0
- sage/modules/vector_rational_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_rational_dense.pxd +15 -0
- sage/modules/vector_rational_dense.pyx +387 -0
- sage/modules/vector_rational_sparse.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_rational_sparse.pxd +30 -0
- sage/modules/vector_rational_sparse.pyx +413 -0
- sage/modules/vector_real_double_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/vector_real_double_dense.pxd +6 -0
- sage/modules/vector_real_double_dense.pyx +126 -0
- sage/modules/vector_space_homspace.py +430 -0
- sage/modules/vector_space_morphism.py +989 -0
- sage/modules/with_basis/all.py +15 -0
- sage/modules/with_basis/cell_module.py +494 -0
- sage/modules/with_basis/indexed_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/modules/with_basis/indexed_element.pxd +13 -0
- sage/modules/with_basis/indexed_element.pyx +1058 -0
- sage/modules/with_basis/invariant.py +1075 -0
- sage/modules/with_basis/morphism.py +1636 -0
- sage/modules/with_basis/representation.py +2939 -0
- sage/modules/with_basis/subquotient.py +685 -0
- sage/numerical/all__sagemath_modules.py +6 -0
- sage/numerical/gauss_legendre.cpython-314-aarch64-linux-musl.so +0 -0
- sage/numerical/gauss_legendre.pyx +381 -0
- sage/numerical/optimize.py +910 -0
- sage/probability/all.py +10 -0
- sage/probability/probability_distribution.cpython-314-aarch64-linux-musl.so +0 -0
- sage/probability/probability_distribution.pyx +1242 -0
- sage/probability/random_variable.py +411 -0
- sage/quadratic_forms/all.py +4 -0
- sage/quadratic_forms/all__sagemath_modules.py +15 -0
- sage/quadratic_forms/binary_qf.py +2042 -0
- sage/quadratic_forms/bqf_class_group.py +748 -0
- sage/quadratic_forms/constructions.py +93 -0
- sage/quadratic_forms/count_local_2.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/count_local_2.pyx +365 -0
- sage/quadratic_forms/extras.py +195 -0
- sage/quadratic_forms/quadratic_form.py +1753 -0
- sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
- sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
- sage/quadratic_forms/quadratic_form__evaluate.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
- sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
- sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
- sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
- sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
- sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
- sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
- sage/quadratic_forms/quadratic_form__theta.py +352 -0
- sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
- sage/quadratic_forms/random_quadraticform.py +209 -0
- sage/quadratic_forms/ternary.cpython-314-aarch64-linux-musl.so +0 -0
- sage/quadratic_forms/ternary.pyx +1154 -0
- sage/quadratic_forms/ternary_qf.py +2027 -0
- sage/rings/all__sagemath_modules.py +28 -0
- sage/rings/asymptotic/all__sagemath_modules.py +1 -0
- sage/rings/asymptotic/misc.py +1252 -0
- sage/rings/cc.py +4 -0
- sage/rings/cfinite_sequence.py +1306 -0
- sage/rings/complex_conversion.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_conversion.pxd +8 -0
- sage/rings/complex_conversion.pyx +23 -0
- sage/rings/complex_double.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_double.pxd +21 -0
- sage/rings/complex_double.pyx +2654 -0
- sage/rings/complex_mpc.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_mpc.pxd +21 -0
- sage/rings/complex_mpc.pyx +2576 -0
- sage/rings/complex_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/complex_mpfr.pxd +18 -0
- sage/rings/complex_mpfr.pyx +3602 -0
- sage/rings/derivation.py +2334 -0
- sage/rings/finite_rings/all__sagemath_modules.py +1 -0
- sage/rings/finite_rings/maps_finite_field.py +191 -0
- sage/rings/function_field/all__sagemath_modules.py +8 -0
- sage/rings/function_field/derivations.py +102 -0
- sage/rings/function_field/derivations_rational.py +132 -0
- sage/rings/function_field/differential.py +853 -0
- sage/rings/function_field/divisor.py +1107 -0
- sage/rings/function_field/drinfeld_modules/action.py +199 -0
- sage/rings/function_field/drinfeld_modules/all.py +1 -0
- sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
- sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
- sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
- sage/rings/function_field/drinfeld_modules/homset.py +420 -0
- sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
- sage/rings/function_field/hermite_form_polynomial.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/khuri_makdisi.pyx +935 -0
- sage/rings/invariants/all.py +4 -0
- sage/rings/invariants/invariant_theory.py +4597 -0
- sage/rings/invariants/reconstruction.py +395 -0
- sage/rings/polynomial/all__sagemath_modules.py +17 -0
- sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
- sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
- sage/rings/polynomial/ore_function_element.py +952 -0
- sage/rings/polynomial/ore_function_field.py +1028 -0
- sage/rings/polynomial/ore_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
- sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
- sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
- sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
- sage/rings/polynomial/skew_polynomial_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
- sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
- sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
- sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
- sage/rings/polynomial/skew_polynomial_ring.py +908 -0
- sage/rings/real_double_element_gsl.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/real_double_element_gsl.pxd +8 -0
- sage/rings/real_double_element_gsl.pyx +794 -0
- sage/rings/real_field.py +58 -0
- sage/rings/real_mpfr.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/real_mpfr.pxd +29 -0
- sage/rings/real_mpfr.pyx +6122 -0
- sage/rings/ring_extension.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension.pxd +42 -0
- sage/rings/ring_extension.pyx +2779 -0
- sage/rings/ring_extension_conversion.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_conversion.pxd +16 -0
- sage/rings/ring_extension_conversion.pyx +462 -0
- sage/rings/ring_extension_element.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_element.pxd +21 -0
- sage/rings/ring_extension_element.pyx +1635 -0
- sage/rings/ring_extension_homset.py +64 -0
- sage/rings/ring_extension_morphism.cpython-314-aarch64-linux-musl.so +0 -0
- sage/rings/ring_extension_morphism.pxd +35 -0
- sage/rings/ring_extension_morphism.pyx +920 -0
- sage/schemes/all__sagemath_modules.py +1 -0
- sage/schemes/projective/all__sagemath_modules.py +1 -0
- sage/schemes/projective/coherent_sheaf.py +300 -0
- sage/schemes/projective/cohomology.py +510 -0
- sage/stats/all.py +15 -0
- sage/stats/basic_stats.py +489 -0
- sage/stats/distributions/all.py +7 -0
- sage/stats/distributions/catalog.py +34 -0
- sage/stats/distributions/dgs.h +50 -0
- sage/stats/distributions/dgs.pxd +111 -0
- sage/stats/distributions/dgs_bern.h +400 -0
- sage/stats/distributions/dgs_gauss.h +614 -0
- sage/stats/distributions/dgs_misc.h +104 -0
- sage/stats/distributions/discrete_gaussian_integer.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
- sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
- sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
- sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
- sage/stats/hmm/all.py +15 -0
- sage/stats/hmm/chmm.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/distributions.pxd +29 -0
- sage/stats/hmm/distributions.pyx +531 -0
- sage/stats/hmm/hmm.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/hmm.pxd +17 -0
- sage/stats/hmm/hmm.pyx +1388 -0
- sage/stats/hmm/util.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/intlist.pxd +14 -0
- sage/stats/intlist.pyx +588 -0
- sage/stats/r.py +49 -0
- sage/stats/time_series.cpython-314-aarch64-linux-musl.so +0 -0
- sage/stats/time_series.pxd +6 -0
- sage/stats/time_series.pyx +2546 -0
- sage/tensor/all.py +2 -0
- sage/tensor/modules/all.py +8 -0
- sage/tensor/modules/alternating_contr_tensor.py +761 -0
- sage/tensor/modules/comp.py +5598 -0
- sage/tensor/modules/ext_pow_free_module.py +824 -0
- sage/tensor/modules/finite_rank_free_module.py +3589 -0
- sage/tensor/modules/format_utilities.py +333 -0
- sage/tensor/modules/free_module_alt_form.py +858 -0
- sage/tensor/modules/free_module_automorphism.py +1207 -0
- sage/tensor/modules/free_module_basis.py +1074 -0
- sage/tensor/modules/free_module_element.py +284 -0
- sage/tensor/modules/free_module_homset.py +652 -0
- sage/tensor/modules/free_module_linear_group.py +564 -0
- sage/tensor/modules/free_module_morphism.py +1581 -0
- sage/tensor/modules/free_module_tensor.py +3289 -0
- sage/tensor/modules/reflexive_module.py +386 -0
- sage/tensor/modules/tensor_free_module.py +780 -0
- sage/tensor/modules/tensor_free_submodule.py +538 -0
- sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
- sage/tensor/modules/tensor_with_indices.py +1043 -0
|
@@ -0,0 +1,4139 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
# sage.doctest: needs sage.modules sage.rings.finite_rings
|
|
3
|
+
r"""
|
|
4
|
+
Optimized low-level binary code representation
|
|
5
|
+
|
|
6
|
+
Some computations with linear binary codes. Fix a basis for `\GF{2}^n`.
|
|
7
|
+
A linear binary code is a linear subspace of `\GF{2}^n`, together with
|
|
8
|
+
this choice of basis. A permutation `g \in S_n` of the fixed basis
|
|
9
|
+
gives rise to a permutation of the vectors, or words, in `\GF{2}^n`,
|
|
10
|
+
sending `(w_i)` to `(w_{g(i)})`. The permutation automorphism group of
|
|
11
|
+
the code `C` is the set of permutations of the basis that bijectively
|
|
12
|
+
map `C` to itself. Note that if `g` is such a permutation, then
|
|
13
|
+
|
|
14
|
+
.. MATH::
|
|
15
|
+
|
|
16
|
+
g(a_i) + g(b_i) = (a_{g(i)} + b_{g(i)}) = g((a_i) + (b_i)).
|
|
17
|
+
|
|
18
|
+
Over other fields, it is also required that the map be linear, which
|
|
19
|
+
as per above boils down to scalar multiplication. However, over
|
|
20
|
+
`\GF{2},` the only scalars are 0 and 1, so the linearity condition has
|
|
21
|
+
trivial effect.
|
|
22
|
+
|
|
23
|
+
AUTHOR:
|
|
24
|
+
|
|
25
|
+
- Robert L Miller (Oct-Nov 2007)
|
|
26
|
+
|
|
27
|
+
* compiled code data structure
|
|
28
|
+
* union-find based orbit partition
|
|
29
|
+
* optimized partition stack class
|
|
30
|
+
* NICE-based partition refinement algorithm
|
|
31
|
+
* canonical generation function
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
# ***************************************************************************
|
|
35
|
+
# Copyright (C) 2007 Robert L. Miller <rlmillster@gmail.com>
|
|
36
|
+
#
|
|
37
|
+
# This program is free software: you can redistribute it and/or modify
|
|
38
|
+
# it under the terms of the GNU General Public License as published by
|
|
39
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
40
|
+
# (at your option) any later version.
|
|
41
|
+
# https://www.gnu.org/licenses/
|
|
42
|
+
# ***************************************************************************
|
|
43
|
+
|
|
44
|
+
from libc.string cimport memcpy
|
|
45
|
+
from cpython.mem cimport *
|
|
46
|
+
from cpython.object cimport PyObject_RichCompare
|
|
47
|
+
from cysignals.memory cimport sig_malloc, sig_free
|
|
48
|
+
|
|
49
|
+
from sage.structure.element cimport Matrix
|
|
50
|
+
from sage.misc.timing import cputime
|
|
51
|
+
from sage.rings.integer cimport Integer
|
|
52
|
+
from copy import copy
|
|
53
|
+
from sage.data_structures.bitset_base cimport *
|
|
54
|
+
|
|
55
|
+
WORD_SIZE = sizeof(codeword) << 3
|
|
56
|
+
|
|
57
|
+
cdef enum:
|
|
58
|
+
chunk_size = 8
|
|
59
|
+
|
|
60
|
+
cdef inline int min(int a, int b) noexcept:
|
|
61
|
+
if a > b:
|
|
62
|
+
return b
|
|
63
|
+
else:
|
|
64
|
+
return a
|
|
65
|
+
|
|
66
|
+
# NOTE - Since most of the functions are used from within the module, cdef'd
|
|
67
|
+
# functions come without an underscore, and the def'd equivalents, which are
|
|
68
|
+
# essentially only for doctesting and debugging, have underscores.
|
|
69
|
+
|
|
70
|
+
cdef int *hamming_weights() noexcept:
|
|
71
|
+
cdef int *ham_wts
|
|
72
|
+
cdef int i
|
|
73
|
+
ham_wts = <int *> sig_malloc(65536 * sizeof(int))
|
|
74
|
+
if ham_wts is NULL:
|
|
75
|
+
sig_free(ham_wts)
|
|
76
|
+
raise MemoryError("Memory.")
|
|
77
|
+
ham_wts[0] = 0
|
|
78
|
+
ham_wts[1] = 1
|
|
79
|
+
ham_wts[2] = 1
|
|
80
|
+
ham_wts[3] = 2
|
|
81
|
+
for i from 4 <= i < 16:
|
|
82
|
+
ham_wts[i] = ham_wts[i & 3] + ham_wts[(i>>2) & 3]
|
|
83
|
+
for i from 16 <= i < 256:
|
|
84
|
+
ham_wts[i] = ham_wts[i & 15] + ham_wts[(i>>4) & 15]
|
|
85
|
+
for i from 256 <= i < 65536:
|
|
86
|
+
ham_wts[i] = ham_wts[i & 255] + ham_wts[(i>>8) & 255]
|
|
87
|
+
return ham_wts
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def weight_dist(M):
|
|
91
|
+
"""
|
|
92
|
+
Compute the weight distribution of the row space of `M`.
|
|
93
|
+
|
|
94
|
+
EXAMPLES::
|
|
95
|
+
|
|
96
|
+
sage: from sage.coding.binary_code import weight_dist
|
|
97
|
+
sage: M = Matrix(GF(2), [
|
|
98
|
+
....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0],
|
|
99
|
+
....: [0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
|
|
100
|
+
....: [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1],
|
|
101
|
+
....: [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1],
|
|
102
|
+
....: [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]])
|
|
103
|
+
sage: weight_dist(M)
|
|
104
|
+
[1, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1]
|
|
105
|
+
sage: M = Matrix(GF(2), [
|
|
106
|
+
....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0],
|
|
107
|
+
....: [0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0],
|
|
108
|
+
....: [0,0,0,0,0,1,0,1,0,0,0,1,1,1,1,1,1],
|
|
109
|
+
....: [0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1]])
|
|
110
|
+
sage: weight_dist(M)
|
|
111
|
+
[1, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 4, 0, 0, 0, 0, 0]
|
|
112
|
+
sage: M = Matrix(GF(2), [
|
|
113
|
+
....: [1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,0],
|
|
114
|
+
....: [0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0],
|
|
115
|
+
....: [0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0],
|
|
116
|
+
....: [0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0],
|
|
117
|
+
....: [0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0],
|
|
118
|
+
....: [0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0],
|
|
119
|
+
....: [0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0],
|
|
120
|
+
....: [0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1]])
|
|
121
|
+
sage: weight_dist(M)
|
|
122
|
+
[1, 0, 0, 0, 0, 0, 68, 0, 85, 0, 68, 0, 34, 0, 0, 0, 0, 0]
|
|
123
|
+
"""
|
|
124
|
+
cdef bitset_t word
|
|
125
|
+
cdef int i,j,k, dim=M.nrows(), deg=M.ncols()
|
|
126
|
+
cdef list L
|
|
127
|
+
cdef MemoryAllocator mem = MemoryAllocator()
|
|
128
|
+
cdef int *LL = <int *> mem.malloc((deg+1) * sizeof(int))
|
|
129
|
+
cdef bitset_s *basis = <bitset_s *> mem.malloc(dim * sizeof(bitset_s))
|
|
130
|
+
for i from 0 <= i < dim:
|
|
131
|
+
bitset_init(&basis[i], deg)
|
|
132
|
+
bitset_zero(&basis[i])
|
|
133
|
+
for j in M.row(i).nonzero_positions():
|
|
134
|
+
bitset_set(&basis[i], j)
|
|
135
|
+
for i in range(deg + 1):
|
|
136
|
+
LL[i] = 0
|
|
137
|
+
bitset_init(word, deg)
|
|
138
|
+
bitset_zero(word)
|
|
139
|
+
i = 0
|
|
140
|
+
j = 0
|
|
141
|
+
while True:
|
|
142
|
+
LL[bitset_hamming_weight(word)] += 1
|
|
143
|
+
i ^= 1
|
|
144
|
+
k = 0
|
|
145
|
+
if not i:
|
|
146
|
+
while not j & (1 << k):
|
|
147
|
+
k += 1
|
|
148
|
+
k += 1
|
|
149
|
+
if k == dim:
|
|
150
|
+
break
|
|
151
|
+
j ^= (1 << k)
|
|
152
|
+
bitset_xor(word, word, &basis[k])
|
|
153
|
+
bitset_free(word)
|
|
154
|
+
L = [int(LL[i]) for i from 0 <= i < deg+1]
|
|
155
|
+
for i from 0 <= i < dim:
|
|
156
|
+
bitset_free(&basis[i])
|
|
157
|
+
return L
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_word_perms(t_limit=5.0):
|
|
161
|
+
r"""
|
|
162
|
+
Test the :class:`WordPermutation` structs for at least ``t_limit`` seconds.
|
|
163
|
+
|
|
164
|
+
These are structures written in pure C for speed, and are tested from this
|
|
165
|
+
function, which performs the following tests:
|
|
166
|
+
|
|
167
|
+
1. Tests :func:`create_word_perm`, which creates a :class:`WordPermutation`
|
|
168
|
+
from a Python list `L` representing a permutation `i \mapsto
|
|
169
|
+
L[i]`. Takes a random word and permutes it by a random list permutation,
|
|
170
|
+
and tests that the result agrees with doing it the slow way.
|
|
171
|
+
|
|
172
|
+
1b. Tests :func:`create_array_word_perm`, which creates a
|
|
173
|
+
:class:`WordPermutation` from a C array. Does the same as above.
|
|
174
|
+
|
|
175
|
+
2. Tests :func:`create_comp_word_perm`, which creates a
|
|
176
|
+
:class:`WordPermutation` as a composition of two
|
|
177
|
+
:class:`WordPermutation` objects. Takes a random word and two random
|
|
178
|
+
permutations, and tests that the result of permuting by the composition
|
|
179
|
+
is correct.
|
|
180
|
+
|
|
181
|
+
3. Tests :func:`create_inv_word_perm` and :func:`create_id_word_perm`,
|
|
182
|
+
which create a :class:`WordPermutation` as the inverse and identity
|
|
183
|
+
permutations, resp. Takes a random word and a random permutation, and
|
|
184
|
+
tests that the result permuting by the permutation and its inverse in
|
|
185
|
+
either order, and permuting by the identity both return the original
|
|
186
|
+
word.
|
|
187
|
+
|
|
188
|
+
.. NOTE::
|
|
189
|
+
|
|
190
|
+
The functions :func:`permute_word_by_wp` and :func:`dealloc_word_perm`
|
|
191
|
+
are implicitly involved in each of the above tests.
|
|
192
|
+
|
|
193
|
+
TESTS::
|
|
194
|
+
|
|
195
|
+
sage: from sage.coding.binary_code import test_word_perms
|
|
196
|
+
sage: test_word_perms() # long time (5s on sage.math, 2011)
|
|
197
|
+
"""
|
|
198
|
+
cdef WordPermutation *g
|
|
199
|
+
cdef WordPermutation *h
|
|
200
|
+
cdef WordPermutation *i
|
|
201
|
+
cdef codeword cw1, cw2, cw3
|
|
202
|
+
cdef int n = sizeof(codeword) << 3
|
|
203
|
+
cdef int j
|
|
204
|
+
cdef int *arr = <int*> sig_malloc(n * sizeof(int))
|
|
205
|
+
if arr is NULL:
|
|
206
|
+
raise MemoryError("Error allocating memory.")
|
|
207
|
+
from sage.misc.prandom import randint
|
|
208
|
+
from sage.combinat.permutation import Permutations
|
|
209
|
+
S = Permutations(list(range(n)))
|
|
210
|
+
t = cputime()
|
|
211
|
+
while cputime(t) < t_limit:
|
|
212
|
+
word = [randint(0, 1) for _ in range(n)]
|
|
213
|
+
cw1 = 0
|
|
214
|
+
for j from 0 <= j < n:
|
|
215
|
+
cw1 += (<codeword>word[j]) << (<codeword>j)
|
|
216
|
+
# 1. test create_word_perm
|
|
217
|
+
gg = S.random_element()
|
|
218
|
+
g = create_word_perm(gg)
|
|
219
|
+
word2 = [0]*n
|
|
220
|
+
for j from 0 <= j < n:
|
|
221
|
+
word2[gg[j]] = word[j]
|
|
222
|
+
cw2 = permute_word_by_wp(g, cw1)
|
|
223
|
+
cw3 = 0
|
|
224
|
+
for j from 0 <= j < n:
|
|
225
|
+
cw3 += (<codeword>word2[j]) << (<codeword>j)
|
|
226
|
+
if cw3 != cw2:
|
|
227
|
+
print("ERROR1")
|
|
228
|
+
dealloc_word_perm(g)
|
|
229
|
+
# 1b. test create_array_word_perm
|
|
230
|
+
gg = S.random_element()
|
|
231
|
+
for j from 0 <= j < n:
|
|
232
|
+
arr[j] = gg[j]
|
|
233
|
+
g = create_array_word_perm(arr, 0, n)
|
|
234
|
+
word2 = [0]*n
|
|
235
|
+
for j from 0 <= j < n:
|
|
236
|
+
word2[gg[j]] = word[j]
|
|
237
|
+
cw2 = permute_word_by_wp(g, cw1)
|
|
238
|
+
cw3 = 0
|
|
239
|
+
for j from 0 <= j < n:
|
|
240
|
+
cw3 += (<codeword>word2[j]) << (<codeword>j)
|
|
241
|
+
if cw3 != cw2:
|
|
242
|
+
print("ERROR1b")
|
|
243
|
+
dealloc_word_perm(g)
|
|
244
|
+
# 2. test create_comp_word_perm
|
|
245
|
+
gg = S.random_element()
|
|
246
|
+
hh = S.random_element()
|
|
247
|
+
g = create_word_perm(gg)
|
|
248
|
+
h = create_word_perm(hh)
|
|
249
|
+
i = create_comp_word_perm(g, h)
|
|
250
|
+
word2 = [0]*n
|
|
251
|
+
for j from 0 <= j < n:
|
|
252
|
+
word2[gg[hh[j]]] = word[j]
|
|
253
|
+
cw2 = permute_word_by_wp(i, cw1)
|
|
254
|
+
cw3 = 0
|
|
255
|
+
for j from 0 <= j < n:
|
|
256
|
+
cw3 += (<codeword>word2[j]) << (<codeword>j)
|
|
257
|
+
if cw3 != cw2:
|
|
258
|
+
print("ERROR2")
|
|
259
|
+
dealloc_word_perm(g)
|
|
260
|
+
dealloc_word_perm(h)
|
|
261
|
+
dealloc_word_perm(i)
|
|
262
|
+
# 3. test create_inv_word_perm and create_id_word_perm
|
|
263
|
+
gg = S.random_element()
|
|
264
|
+
g = create_word_perm(gg)
|
|
265
|
+
h = create_inv_word_perm(g)
|
|
266
|
+
i = create_id_word_perm(n)
|
|
267
|
+
cw2 = permute_word_by_wp(g, cw1)
|
|
268
|
+
cw2 = permute_word_by_wp(h, cw2)
|
|
269
|
+
if cw1 != cw2:
|
|
270
|
+
print("ERROR3a")
|
|
271
|
+
cw2 = permute_word_by_wp(h, cw1)
|
|
272
|
+
cw2 = permute_word_by_wp(g, cw2)
|
|
273
|
+
if cw1 != cw2:
|
|
274
|
+
print("ERROR3b")
|
|
275
|
+
cw2 = permute_word_by_wp(i, cw1)
|
|
276
|
+
if cw1 != cw2:
|
|
277
|
+
print("ERROR3c")
|
|
278
|
+
dealloc_word_perm(g)
|
|
279
|
+
dealloc_word_perm(h)
|
|
280
|
+
dealloc_word_perm(i)
|
|
281
|
+
sig_free(arr)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
cdef WordPermutation *create_word_perm(object list_perm) noexcept:
|
|
285
|
+
r"""
|
|
286
|
+
Create a word permutation from a Python list permutation L, i.e. such that
|
|
287
|
+
`i \mapsto L[i]`.
|
|
288
|
+
"""
|
|
289
|
+
cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1
|
|
290
|
+
cdef codeword *images_i
|
|
291
|
+
cdef codeword image
|
|
292
|
+
cdef WordPermutation *word_perm = <WordPermutation *> sig_malloc(sizeof(WordPermutation))
|
|
293
|
+
if word_perm is NULL:
|
|
294
|
+
raise RuntimeError("Error allocating memory.")
|
|
295
|
+
word_perm.degree = len(list_perm)
|
|
296
|
+
list_perm = copy(list_perm)
|
|
297
|
+
while num_chunks*chunk_size < word_perm.degree:
|
|
298
|
+
num_chunks += 1
|
|
299
|
+
word_perm.images = <codeword **> sig_malloc(num_chunks * sizeof(codeword *))
|
|
300
|
+
if word_perm.images is NULL:
|
|
301
|
+
sig_free(word_perm)
|
|
302
|
+
raise RuntimeError("Error allocating memory.")
|
|
303
|
+
word_perm.chunk_num = num_chunks
|
|
304
|
+
words_per_chunk = 1 << chunk_size
|
|
305
|
+
word_perm.gate = ((<codeword>1) << chunk_size) - 1
|
|
306
|
+
list_perm += list(range(len(list_perm), chunk_size*num_chunks))
|
|
307
|
+
word_perm.chunk_words = words_per_chunk
|
|
308
|
+
for i from 0 <= i < num_chunks:
|
|
309
|
+
images_i = <codeword *> sig_malloc(words_per_chunk * sizeof(codeword))
|
|
310
|
+
if images_i is NULL:
|
|
311
|
+
for j from 0 <= j < i:
|
|
312
|
+
sig_free(word_perm.images[j])
|
|
313
|
+
sig_free(word_perm.images)
|
|
314
|
+
sig_free(word_perm)
|
|
315
|
+
raise RuntimeError("Error allocating memory.")
|
|
316
|
+
word_perm.images[i] = images_i
|
|
317
|
+
for j from 0 <= j < chunk_size:
|
|
318
|
+
images_i[1 << j] = (<codeword>1) << list_perm[chunk_size*i + j]
|
|
319
|
+
image = <codeword> 0
|
|
320
|
+
parity = 0
|
|
321
|
+
comb = 0
|
|
322
|
+
while True:
|
|
323
|
+
images_i[comb] = image
|
|
324
|
+
parity ^= 1
|
|
325
|
+
j = 0
|
|
326
|
+
if not parity:
|
|
327
|
+
while not comb & (1 << j):
|
|
328
|
+
j += 1
|
|
329
|
+
j += 1
|
|
330
|
+
if j == chunk_size:
|
|
331
|
+
break
|
|
332
|
+
comb ^= (1 << j)
|
|
333
|
+
image ^= images_i[1 << j]
|
|
334
|
+
return word_perm
|
|
335
|
+
|
|
336
|
+
cdef WordPermutation *create_array_word_perm(int *array, int start, int degree) noexcept:
|
|
337
|
+
"""
|
|
338
|
+
Create a word permutation of a given degree from a C array, starting at start.
|
|
339
|
+
"""
|
|
340
|
+
cdef int i, j, cslim, parity, comb, words_per_chunk, num_chunks = 1
|
|
341
|
+
cdef codeword *images_i
|
|
342
|
+
cdef codeword image
|
|
343
|
+
cdef WordPermutation *word_perm = <WordPermutation *> sig_malloc(sizeof(WordPermutation))
|
|
344
|
+
if word_perm is NULL:
|
|
345
|
+
raise RuntimeError("Error allocating memory.")
|
|
346
|
+
word_perm.degree = degree
|
|
347
|
+
while num_chunks*chunk_size < word_perm.degree:
|
|
348
|
+
num_chunks += 1
|
|
349
|
+
word_perm.images = <codeword **> sig_malloc(num_chunks * sizeof(codeword *))
|
|
350
|
+
if word_perm.images is NULL:
|
|
351
|
+
sig_free(word_perm)
|
|
352
|
+
raise RuntimeError("Error allocating memory.")
|
|
353
|
+
word_perm.chunk_num = num_chunks
|
|
354
|
+
words_per_chunk = 1 << chunk_size
|
|
355
|
+
word_perm.gate = ((<codeword>1) << chunk_size) - 1
|
|
356
|
+
word_perm.chunk_words = words_per_chunk
|
|
357
|
+
for i from 0 <= i < num_chunks:
|
|
358
|
+
images_i = <codeword *> sig_malloc(words_per_chunk * sizeof(codeword))
|
|
359
|
+
if images_i is NULL:
|
|
360
|
+
for j from 0 <= j < i:
|
|
361
|
+
sig_free(word_perm.images[j])
|
|
362
|
+
sig_free(word_perm.images)
|
|
363
|
+
sig_free(word_perm)
|
|
364
|
+
raise RuntimeError("Error allocating memory.")
|
|
365
|
+
word_perm.images[i] = images_i
|
|
366
|
+
cslim = min(chunk_size, degree - i*chunk_size)
|
|
367
|
+
for j from 0 <= j < cslim:
|
|
368
|
+
images_i[1 << j] = (<codeword>1) << array[start + chunk_size*i + j]
|
|
369
|
+
image = <codeword> 0
|
|
370
|
+
parity = 0
|
|
371
|
+
comb = 0
|
|
372
|
+
while True:
|
|
373
|
+
images_i[comb] = image
|
|
374
|
+
parity ^= 1
|
|
375
|
+
j = 0
|
|
376
|
+
if not parity:
|
|
377
|
+
while not comb & (1 << j):
|
|
378
|
+
j += 1
|
|
379
|
+
j += 1
|
|
380
|
+
if j == chunk_size:
|
|
381
|
+
break
|
|
382
|
+
comb ^= (1 << j)
|
|
383
|
+
image ^= images_i[1 << j]
|
|
384
|
+
return word_perm
|
|
385
|
+
|
|
386
|
+
cdef WordPermutation *create_id_word_perm(int degree) noexcept:
|
|
387
|
+
"""
|
|
388
|
+
Create the identity word permutation of degree degree.
|
|
389
|
+
"""
|
|
390
|
+
cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1
|
|
391
|
+
cdef codeword *images_i
|
|
392
|
+
cdef codeword image
|
|
393
|
+
cdef WordPermutation *word_perm = <WordPermutation *> sig_malloc(sizeof(WordPermutation))
|
|
394
|
+
if word_perm is NULL:
|
|
395
|
+
raise RuntimeError("Error allocating memory.")
|
|
396
|
+
word_perm.degree = degree
|
|
397
|
+
while num_chunks*chunk_size < degree:
|
|
398
|
+
num_chunks += 1
|
|
399
|
+
word_perm.images = <codeword **> sig_malloc(num_chunks * sizeof(codeword *))
|
|
400
|
+
if word_perm.images is NULL:
|
|
401
|
+
sig_free(word_perm)
|
|
402
|
+
raise RuntimeError("Error allocating memory.")
|
|
403
|
+
word_perm.chunk_num = num_chunks
|
|
404
|
+
words_per_chunk = 1 << chunk_size
|
|
405
|
+
word_perm.gate = ((<codeword>1) << chunk_size) - 1
|
|
406
|
+
word_perm.chunk_words = words_per_chunk
|
|
407
|
+
for i from 0 <= i < num_chunks:
|
|
408
|
+
images_i = <codeword *> sig_malloc(words_per_chunk * sizeof(codeword))
|
|
409
|
+
if images_i is NULL:
|
|
410
|
+
for j from 0 <= j < i:
|
|
411
|
+
sig_free(word_perm.images[j])
|
|
412
|
+
sig_free(word_perm.images)
|
|
413
|
+
sig_free(word_perm)
|
|
414
|
+
raise RuntimeError("Error allocating memory.")
|
|
415
|
+
word_perm.images[i] = images_i
|
|
416
|
+
for j from 0 <= j < chunk_size:
|
|
417
|
+
images_i[1 << j] = (<codeword>1) << (chunk_size*i + j)
|
|
418
|
+
image = <codeword> 0
|
|
419
|
+
parity = 0
|
|
420
|
+
comb = 0
|
|
421
|
+
while True:
|
|
422
|
+
images_i[comb] = image
|
|
423
|
+
parity ^= 1
|
|
424
|
+
j = 0
|
|
425
|
+
if not parity:
|
|
426
|
+
while not comb & (1 << j):
|
|
427
|
+
j += 1
|
|
428
|
+
j += 1
|
|
429
|
+
if j == chunk_size:
|
|
430
|
+
break
|
|
431
|
+
comb ^= (1 << j)
|
|
432
|
+
image ^= images_i[1 << j]
|
|
433
|
+
return word_perm
|
|
434
|
+
|
|
435
|
+
cdef WordPermutation *create_comp_word_perm(WordPermutation *g, WordPermutation *h) noexcept:
|
|
436
|
+
r"""
|
|
437
|
+
Create the composition of word permutations `g \circ h`.
|
|
438
|
+
"""
|
|
439
|
+
cdef int i, j, parity, comb, words_per_chunk, num_chunks = 1
|
|
440
|
+
cdef codeword *images_i
|
|
441
|
+
cdef codeword image
|
|
442
|
+
cdef WordPermutation *word_perm = <WordPermutation *> sig_malloc(sizeof(WordPermutation))
|
|
443
|
+
if word_perm is NULL:
|
|
444
|
+
raise RuntimeError("Error allocating memory.")
|
|
445
|
+
word_perm.degree = g.degree
|
|
446
|
+
while num_chunks*chunk_size < word_perm.degree:
|
|
447
|
+
num_chunks += 1
|
|
448
|
+
word_perm.images = <codeword **> sig_malloc(num_chunks * sizeof(codeword *))
|
|
449
|
+
if word_perm.images is NULL:
|
|
450
|
+
sig_free(word_perm)
|
|
451
|
+
raise RuntimeError("Error allocating memory.")
|
|
452
|
+
word_perm.chunk_num = num_chunks
|
|
453
|
+
words_per_chunk = 1 << chunk_size
|
|
454
|
+
word_perm.gate = ((<codeword>1) << chunk_size) - 1
|
|
455
|
+
word_perm.chunk_words = words_per_chunk
|
|
456
|
+
for i from 0 <= i < num_chunks:
|
|
457
|
+
images_i = <codeword *> sig_malloc(words_per_chunk * sizeof(codeword))
|
|
458
|
+
if images_i is NULL:
|
|
459
|
+
for j from 0 <= j < i:
|
|
460
|
+
sig_free(word_perm.images[j])
|
|
461
|
+
sig_free(word_perm.images)
|
|
462
|
+
sig_free(word_perm)
|
|
463
|
+
raise RuntimeError("Error allocating memory.")
|
|
464
|
+
word_perm.images[i] = images_i
|
|
465
|
+
for j in range(chunk_size):
|
|
466
|
+
image = (<codeword>1) << (chunk_size*i + j)
|
|
467
|
+
image = permute_word_by_wp(h, image)
|
|
468
|
+
image = permute_word_by_wp(g, image)
|
|
469
|
+
images_i[1 << j] = image
|
|
470
|
+
image = <codeword> 0
|
|
471
|
+
parity = 0
|
|
472
|
+
comb = 0
|
|
473
|
+
while True:
|
|
474
|
+
images_i[comb] = image
|
|
475
|
+
parity ^= 1
|
|
476
|
+
j = 0
|
|
477
|
+
if not parity:
|
|
478
|
+
while not comb & (1 << j):
|
|
479
|
+
j += 1
|
|
480
|
+
j += 1
|
|
481
|
+
if j == chunk_size:
|
|
482
|
+
break
|
|
483
|
+
comb ^= (1 << j)
|
|
484
|
+
image ^= images_i[1 << j]
|
|
485
|
+
return word_perm
|
|
486
|
+
|
|
487
|
+
cdef WordPermutation *create_inv_word_perm(WordPermutation *g) noexcept:
|
|
488
|
+
r"""
|
|
489
|
+
Create the inverse `g^{-1}` of the word permutation of `g`.
|
|
490
|
+
"""
|
|
491
|
+
cdef int i, j
|
|
492
|
+
cdef int *array = <int *> sig_malloc(g.degree * sizeof(int))
|
|
493
|
+
cdef codeword temp
|
|
494
|
+
cdef WordPermutation *w
|
|
495
|
+
for i from 0 <= i < g.degree:
|
|
496
|
+
j = 0
|
|
497
|
+
temp = permute_word_by_wp(g, (<codeword>1) << i)
|
|
498
|
+
while not ((<codeword>1) << j) & temp:
|
|
499
|
+
j += 1
|
|
500
|
+
array[j] = i
|
|
501
|
+
w = create_array_word_perm(array, 0, g.degree)
|
|
502
|
+
sig_free(array)
|
|
503
|
+
return w
|
|
504
|
+
|
|
505
|
+
cdef int dealloc_word_perm(WordPermutation *wp) noexcept:
|
|
506
|
+
"""
|
|
507
|
+
Free the memory used by a word permutation.
|
|
508
|
+
"""
|
|
509
|
+
cdef int i
|
|
510
|
+
for i from 0 <= i < wp.chunk_num:
|
|
511
|
+
sig_free(wp.images[i])
|
|
512
|
+
sig_free(wp.images)
|
|
513
|
+
sig_free(wp)
|
|
514
|
+
|
|
515
|
+
cdef codeword permute_word_by_wp(WordPermutation *wp, codeword word) noexcept:
|
|
516
|
+
"""
|
|
517
|
+
Return the codeword obtained by applying the permutation wp to word.
|
|
518
|
+
"""
|
|
519
|
+
cdef int num_chunks = wp.chunk_num
|
|
520
|
+
cdef int i
|
|
521
|
+
cdef codeword gate = wp.gate
|
|
522
|
+
cdef codeword image = 0
|
|
523
|
+
cdef codeword **images = wp.images
|
|
524
|
+
for i from 0 <= i < num_chunks:
|
|
525
|
+
image += images[i][(word >> i*chunk_size) & gate]
|
|
526
|
+
return image
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
def test_expand_to_ortho_basis(B=None):
|
|
530
|
+
r"""
|
|
531
|
+
This function is written in pure C for speed, and is tested from this
|
|
532
|
+
function.
|
|
533
|
+
|
|
534
|
+
INPUT:
|
|
535
|
+
|
|
536
|
+
- ``B`` -- a :class:`BinaryCode` in standard form
|
|
537
|
+
|
|
538
|
+
OUTPUT:
|
|
539
|
+
|
|
540
|
+
An array of codewords which represent the expansion of a basis for `B` to a
|
|
541
|
+
basis for `(B^\prime)^\perp`, where `B^\prime = B` if the all-ones vector 1
|
|
542
|
+
is in `B`, otherwise `B^\prime = \text{span}(B,1)` (note that this guarantees
|
|
543
|
+
that all the vectors in the span of the output have even weight).
|
|
544
|
+
|
|
545
|
+
TESTS::
|
|
546
|
+
|
|
547
|
+
sage: from sage.coding.binary_code import test_expand_to_ortho_basis, BinaryCode
|
|
548
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,1,1,0,0,0,0], [0,0,1,1,1,1,1,1,1,1]])
|
|
549
|
+
sage: B = BinaryCode(M)
|
|
550
|
+
sage: B.put_in_std_form()
|
|
551
|
+
0
|
|
552
|
+
sage: test_expand_to_ortho_basis(B=B)
|
|
553
|
+
INPUT CODE:
|
|
554
|
+
Binary [10,2] linear code, generator matrix
|
|
555
|
+
[1010001111]
|
|
556
|
+
[0101111111]
|
|
557
|
+
Expanding to the basis of an orthogonal complement...
|
|
558
|
+
Basis:
|
|
559
|
+
0010000010
|
|
560
|
+
0001000010
|
|
561
|
+
0000100001
|
|
562
|
+
0000010001
|
|
563
|
+
0000001001
|
|
564
|
+
"""
|
|
565
|
+
cdef codeword *output
|
|
566
|
+
cdef int k=0, i
|
|
567
|
+
cdef BinaryCode C
|
|
568
|
+
if not isinstance(B, BinaryCode):
|
|
569
|
+
raise TypeError()
|
|
570
|
+
C = B
|
|
571
|
+
print("INPUT CODE:")
|
|
572
|
+
print(C)
|
|
573
|
+
print("Expanding to the basis of an orthogonal complement...")
|
|
574
|
+
output = expand_to_ortho_basis(C, C.ncols)
|
|
575
|
+
print("Basis:")
|
|
576
|
+
while output[k]:
|
|
577
|
+
k += 1
|
|
578
|
+
for i from 0 <= i < k:
|
|
579
|
+
print(''.join(reversed(Integer(output[i]).binary().zfill(C.ncols))))
|
|
580
|
+
sig_free(output)
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
cdef codeword *expand_to_ortho_basis(BinaryCode B, int n) noexcept:
|
|
584
|
+
r"""
|
|
585
|
+
INPUT:
|
|
586
|
+
|
|
587
|
+
- ``B`` -- a BinaryCode in standard form
|
|
588
|
+
- ``n`` -- the degree
|
|
589
|
+
|
|
590
|
+
OUTPUT:
|
|
591
|
+
|
|
592
|
+
An array of codewords which represent the expansion of a basis for `B` to a
|
|
593
|
+
basis for `(B^\prime)^\perp`, where `B^\prime = B` if the all-ones vector 1
|
|
594
|
+
is in `B`, otherwise `B^\prime = \text{span}(B,1)` (note that this guarantees
|
|
595
|
+
that all the vectors in the span of the output have even weight).
|
|
596
|
+
"""
|
|
597
|
+
# assumes B is already in standard form
|
|
598
|
+
cdef codeword *basis
|
|
599
|
+
cdef codeword word = 0, temp, new, pivots = 0, combo, parity
|
|
600
|
+
cdef codeword n_gate = (~<codeword>0) >> ((sizeof(codeword)<<3) - n)
|
|
601
|
+
cdef int i, j, m, k = B.nrows
|
|
602
|
+
cdef WordPermutation *wp
|
|
603
|
+
basis = <codeword *> sig_malloc((n + 1) * sizeof(codeword))
|
|
604
|
+
if basis is NULL:
|
|
605
|
+
raise MemoryError()
|
|
606
|
+
for i from 0 <= i < k:
|
|
607
|
+
basis[i] = B.basis[i]
|
|
608
|
+
word ^= basis[i]
|
|
609
|
+
# If 11...1 is already a word of the code,
|
|
610
|
+
# then being orthogonal to the code guarantees
|
|
611
|
+
# being even weight. Otherwise, add this in.
|
|
612
|
+
word = (~word) & n_gate
|
|
613
|
+
if word:
|
|
614
|
+
basis[k] = word
|
|
615
|
+
temp = (<codeword>1) << k
|
|
616
|
+
i = k
|
|
617
|
+
while not word & temp:
|
|
618
|
+
temp = temp << 1
|
|
619
|
+
i += 1
|
|
620
|
+
for j from 0 <= j < k:
|
|
621
|
+
if temp & basis[j]:
|
|
622
|
+
basis[j] ^= word
|
|
623
|
+
temp += (<codeword>1 << k) - 1
|
|
624
|
+
i = k
|
|
625
|
+
word = <codeword>1 << k
|
|
626
|
+
k += 1
|
|
627
|
+
else: # NOTE THIS WILL NEVER HAPPEN AS CURRENTLY SET UP!
|
|
628
|
+
temp = (<codeword>1 << k) - 1
|
|
629
|
+
i = k
|
|
630
|
+
word = <codeword>1 << k
|
|
631
|
+
# Now:
|
|
632
|
+
# k is the length of the basis so far
|
|
633
|
+
j = k
|
|
634
|
+
while i < n:
|
|
635
|
+
# we are now looking at the ith free variable,
|
|
636
|
+
# word has a 1 in the ith place, and
|
|
637
|
+
# j is the current row we are putting in basis
|
|
638
|
+
new = 0
|
|
639
|
+
for m from 0 <= m < k:
|
|
640
|
+
if basis[m] & word:
|
|
641
|
+
new ^= basis[m]
|
|
642
|
+
basis[j] = (new & temp) + word
|
|
643
|
+
j += ((word ^ temp) >> i) & 1
|
|
644
|
+
i += 1
|
|
645
|
+
word = word << 1
|
|
646
|
+
temp = (<codeword>1 << B.nrows) - 1
|
|
647
|
+
for i from k <= i < n:
|
|
648
|
+
basis[i-k] = basis[i] ^ B.words[basis[i] & temp]
|
|
649
|
+
k = n-k
|
|
650
|
+
i = 0
|
|
651
|
+
word = (<codeword>1 << B.nrows)
|
|
652
|
+
while i < k and (word & n_gate):
|
|
653
|
+
m = i
|
|
654
|
+
while m < k and not basis[m] & word:
|
|
655
|
+
m += 1
|
|
656
|
+
if m < k:
|
|
657
|
+
pivots += word
|
|
658
|
+
if m != i:
|
|
659
|
+
new = basis[i]
|
|
660
|
+
basis[i] = basis[m]
|
|
661
|
+
basis[m] = new
|
|
662
|
+
for j from 0 <= j < i:
|
|
663
|
+
if basis[j] & word:
|
|
664
|
+
basis[j] ^= basis[i]
|
|
665
|
+
for j from i < j < k:
|
|
666
|
+
if basis[j] & word:
|
|
667
|
+
basis[j] ^= basis[i]
|
|
668
|
+
i += 1
|
|
669
|
+
word = word << 1
|
|
670
|
+
for j from i <= j < n:
|
|
671
|
+
basis[j] = 0
|
|
672
|
+
# now basis is length i
|
|
673
|
+
perm = list(range(B.nrows))
|
|
674
|
+
perm_c = []
|
|
675
|
+
for j from B.nrows <= j < B.ncols:
|
|
676
|
+
if (<codeword>1 << j) & pivots:
|
|
677
|
+
perm.append(j)
|
|
678
|
+
else:
|
|
679
|
+
perm_c.append(j)
|
|
680
|
+
perm.extend(perm_c)
|
|
681
|
+
perm.extend(list(range(B.ncols, n)))
|
|
682
|
+
perm_c = [0]*n
|
|
683
|
+
for j from 0 <= j < n:
|
|
684
|
+
perm_c[perm[j]] = j
|
|
685
|
+
wp = create_word_perm(perm_c)
|
|
686
|
+
for j from 0 <= j < i:
|
|
687
|
+
basis[j] = permute_word_by_wp(wp, basis[j])
|
|
688
|
+
for j from 0 <= j < B.nrows:
|
|
689
|
+
B.basis[j] = permute_word_by_wp(wp, B.basis[j])
|
|
690
|
+
dealloc_word_perm(wp)
|
|
691
|
+
word = 0
|
|
692
|
+
parity = 0
|
|
693
|
+
combo = 0
|
|
694
|
+
while True:
|
|
695
|
+
B.words[combo] = word
|
|
696
|
+
parity ^= 1
|
|
697
|
+
j = 0
|
|
698
|
+
if not parity:
|
|
699
|
+
while not combo & (1 << j):
|
|
700
|
+
j += 1
|
|
701
|
+
j += 1
|
|
702
|
+
if j == B.nrows:
|
|
703
|
+
break
|
|
704
|
+
else:
|
|
705
|
+
combo ^= (1 << j)
|
|
706
|
+
word ^= B.basis[j]
|
|
707
|
+
return basis
|
|
708
|
+
|
|
709
|
+
cdef class BinaryCode:
|
|
710
|
+
"""
|
|
711
|
+
Minimal, but optimized, binary code object.
|
|
712
|
+
|
|
713
|
+
EXAMPLES::
|
|
714
|
+
|
|
715
|
+
sage: import sage.coding.binary_code
|
|
716
|
+
sage: from sage.coding.binary_code import *
|
|
717
|
+
sage: M = Matrix(GF(2), [[1,1,1,1]])
|
|
718
|
+
sage: B = BinaryCode(M) # create from matrix
|
|
719
|
+
sage: C = BinaryCode(B, 60) # create using glue
|
|
720
|
+
sage: D = BinaryCode(C, 240)
|
|
721
|
+
sage: E = BinaryCode(D, 85)
|
|
722
|
+
sage: B
|
|
723
|
+
Binary [4,1] linear code, generator matrix
|
|
724
|
+
[1111]
|
|
725
|
+
sage: C
|
|
726
|
+
Binary [6,2] linear code, generator matrix
|
|
727
|
+
[111100]
|
|
728
|
+
[001111]
|
|
729
|
+
sage: D
|
|
730
|
+
Binary [8,3] linear code, generator matrix
|
|
731
|
+
[11110000]
|
|
732
|
+
[00111100]
|
|
733
|
+
[00001111]
|
|
734
|
+
sage: E
|
|
735
|
+
Binary [8,4] linear code, generator matrix
|
|
736
|
+
[11110000]
|
|
737
|
+
[00111100]
|
|
738
|
+
[00001111]
|
|
739
|
+
[10101010]
|
|
740
|
+
|
|
741
|
+
sage: M = Matrix(GF(2), [[1]*32])
|
|
742
|
+
sage: B = BinaryCode(M)
|
|
743
|
+
sage: B
|
|
744
|
+
Binary [32,1] linear code, generator matrix
|
|
745
|
+
[11111111111111111111111111111111]
|
|
746
|
+
"""
|
|
747
|
+
def __cinit__(self, arg1, arg2=None):
|
|
748
|
+
"""
|
|
749
|
+
Initialize.
|
|
750
|
+
|
|
751
|
+
TESTS::
|
|
752
|
+
|
|
753
|
+
sage: import sage.coding.binary_code
|
|
754
|
+
sage: from sage.coding.binary_code import *
|
|
755
|
+
sage: M = Matrix(GF(2), [[1,1,1,1]])
|
|
756
|
+
sage: B = BinaryCode(M)
|
|
757
|
+
sage: TestSuite(B).run()
|
|
758
|
+
"""
|
|
759
|
+
cdef int nrows, i, j, size
|
|
760
|
+
cdef int nwords, other_nwords, parity, combination
|
|
761
|
+
cdef codeword word, glue_word
|
|
762
|
+
cdef BinaryCode other
|
|
763
|
+
cdef codeword *self_words
|
|
764
|
+
cdef codeword *self_basis
|
|
765
|
+
cdef codeword *other_basis
|
|
766
|
+
|
|
767
|
+
self.radix = sizeof(int) << 3
|
|
768
|
+
|
|
769
|
+
if isinstance(arg1, Matrix):
|
|
770
|
+
self.ncols = arg1.ncols()
|
|
771
|
+
self.nrows = arg1.nrows()
|
|
772
|
+
nrows = self.nrows
|
|
773
|
+
self.nwords = 1 << nrows
|
|
774
|
+
nwords = self.nwords
|
|
775
|
+
elif isinstance(arg1, BinaryCode):
|
|
776
|
+
other = <BinaryCode> arg1
|
|
777
|
+
self.nrows = other.nrows + 1
|
|
778
|
+
glue_word = <codeword> arg2
|
|
779
|
+
size = 0
|
|
780
|
+
while 0 < ((<codeword> 1) << size) <= glue_word:
|
|
781
|
+
size += 1
|
|
782
|
+
if other.ncols > size:
|
|
783
|
+
self.ncols = other.ncols
|
|
784
|
+
else:
|
|
785
|
+
self.ncols = size
|
|
786
|
+
other_nwords = other.nwords
|
|
787
|
+
self.nwords = 2 * other_nwords
|
|
788
|
+
nrows = self.nrows
|
|
789
|
+
nwords = self.nwords
|
|
790
|
+
else:
|
|
791
|
+
raise NotImplementedError
|
|
792
|
+
|
|
793
|
+
if self.nrows >= self.radix or self.ncols > self.radix:
|
|
794
|
+
raise NotImplementedError("Columns and rows are stored as ints. This code is too big.")
|
|
795
|
+
|
|
796
|
+
self.mem = MemoryAllocator()
|
|
797
|
+
self.words = <codeword *> self.mem.malloc(nwords * sizeof(int))
|
|
798
|
+
self.basis = <codeword *> self.mem.malloc(nrows * sizeof(int))
|
|
799
|
+
self_words = self.words
|
|
800
|
+
self_basis = self.basis
|
|
801
|
+
|
|
802
|
+
if isinstance(arg1, Matrix):
|
|
803
|
+
rows = arg1.rows()
|
|
804
|
+
for i from 0 <= i < nrows:
|
|
805
|
+
word = <codeword> 0
|
|
806
|
+
for j in rows[i].nonzero_positions():
|
|
807
|
+
word += (1<<j)
|
|
808
|
+
self_basis[i] = word
|
|
809
|
+
|
|
810
|
+
word = <codeword> 0
|
|
811
|
+
parity = 0
|
|
812
|
+
combination = 0
|
|
813
|
+
while True:
|
|
814
|
+
self_words[combination] = word
|
|
815
|
+
parity ^= 1
|
|
816
|
+
j = 0
|
|
817
|
+
if not parity:
|
|
818
|
+
while not combination & (1 << j):
|
|
819
|
+
j += 1
|
|
820
|
+
j += 1
|
|
821
|
+
if j == nrows:
|
|
822
|
+
break
|
|
823
|
+
else:
|
|
824
|
+
combination ^= (1 << j)
|
|
825
|
+
word ^= self_basis[j]
|
|
826
|
+
|
|
827
|
+
else: # isinstance(arg1, BinaryCode)
|
|
828
|
+
other_basis = other.basis
|
|
829
|
+
for i from 0 <= i < nrows-1:
|
|
830
|
+
self_basis[i] = other_basis[i]
|
|
831
|
+
i = nrows - 1
|
|
832
|
+
self_basis[i] = glue_word
|
|
833
|
+
|
|
834
|
+
memcpy(self_words, other.words, other_nwords*(self.radix>>3))
|
|
835
|
+
|
|
836
|
+
for combination from 0 <= combination < other_nwords:
|
|
837
|
+
self_words[combination+other_nwords] = self_words[combination] ^ glue_word
|
|
838
|
+
|
|
839
|
+
def __reduce__(self):
|
|
840
|
+
"""
|
|
841
|
+
Method for pickling and unpickling BinaryCodes.
|
|
842
|
+
|
|
843
|
+
TESTS::
|
|
844
|
+
|
|
845
|
+
sage: from sage.coding.binary_code import *
|
|
846
|
+
sage: M = Matrix(GF(2), [[1,1,1,1]])
|
|
847
|
+
sage: B = BinaryCode(M)
|
|
848
|
+
sage: loads(dumps(B)) == B
|
|
849
|
+
True
|
|
850
|
+
"""
|
|
851
|
+
return BinaryCode, (self.matrix(),)
|
|
852
|
+
|
|
853
|
+
def __richcmp__(self, other, int op):
|
|
854
|
+
"""
|
|
855
|
+
Comparison of BinaryCodes.
|
|
856
|
+
|
|
857
|
+
TESTS::
|
|
858
|
+
|
|
859
|
+
sage: from sage.coding.binary_code import *
|
|
860
|
+
sage: M = Matrix(GF(2), [[1,1,1,1]])
|
|
861
|
+
sage: B = BinaryCode(M)
|
|
862
|
+
sage: C = BinaryCode(B.matrix())
|
|
863
|
+
sage: B == C
|
|
864
|
+
True
|
|
865
|
+
"""
|
|
866
|
+
if type(self) is not type(other):
|
|
867
|
+
return NotImplemented
|
|
868
|
+
return PyObject_RichCompare(self.matrix(), other.matrix(), op)
|
|
869
|
+
|
|
870
|
+
def matrix(self):
|
|
871
|
+
"""
|
|
872
|
+
Return the generator matrix of the :class:`BinaryCode`, i.e. the code is
|
|
873
|
+
the rowspace of ``B.matrix()``.
|
|
874
|
+
|
|
875
|
+
EXAMPLES::
|
|
876
|
+
|
|
877
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0], [0,0,1,1,1,1]])
|
|
878
|
+
sage: from sage.coding.binary_code import *
|
|
879
|
+
sage: B = BinaryCode(M)
|
|
880
|
+
sage: B.matrix()
|
|
881
|
+
[1 1 1 1 0 0]
|
|
882
|
+
[0 0 1 1 1 1]
|
|
883
|
+
"""
|
|
884
|
+
cdef int i, j
|
|
885
|
+
from sage.matrix.constructor import matrix
|
|
886
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
887
|
+
rows = []
|
|
888
|
+
for i from 0 <= i < self.nrows:
|
|
889
|
+
row = [0]*self.ncols
|
|
890
|
+
for j from 0 <= j < self.ncols:
|
|
891
|
+
if self.basis[i] & ((<codeword>1) << j):
|
|
892
|
+
row[j] = 1
|
|
893
|
+
rows.append(row)
|
|
894
|
+
return matrix(GF(2), self.nrows, self.ncols, rows)
|
|
895
|
+
|
|
896
|
+
def print_data(self):
|
|
897
|
+
"""
|
|
898
|
+
Print all data for ``self``.
|
|
899
|
+
|
|
900
|
+
EXAMPLES::
|
|
901
|
+
|
|
902
|
+
sage: # needs sage.graphs
|
|
903
|
+
sage: import sage.coding.binary_code
|
|
904
|
+
sage: from sage.coding.binary_code import *
|
|
905
|
+
sage: M = Matrix(GF(2), [[1,1,1,1]])
|
|
906
|
+
sage: B = BinaryCode(M)
|
|
907
|
+
sage: C = BinaryCode(B, 60)
|
|
908
|
+
sage: D = BinaryCode(C, 240)
|
|
909
|
+
sage: E = BinaryCode(D, 85)
|
|
910
|
+
sage: B.print_data() # random - actually "print(P.print_data())"
|
|
911
|
+
ncols: 4
|
|
912
|
+
nrows: 1
|
|
913
|
+
nwords: 2
|
|
914
|
+
radix: 32
|
|
915
|
+
basis:
|
|
916
|
+
1111
|
|
917
|
+
words:
|
|
918
|
+
0000
|
|
919
|
+
1111
|
|
920
|
+
sage: C.print_data() # random - actually "print(P.print_data())"
|
|
921
|
+
ncols: 6
|
|
922
|
+
nrows: 2
|
|
923
|
+
nwords: 4
|
|
924
|
+
radix: 32
|
|
925
|
+
basis:
|
|
926
|
+
111100
|
|
927
|
+
001111
|
|
928
|
+
words:
|
|
929
|
+
000000
|
|
930
|
+
111100
|
|
931
|
+
001111
|
|
932
|
+
110011
|
|
933
|
+
sage: D.print_data() # random - actually "print(P.print_data())"
|
|
934
|
+
ncols: 8
|
|
935
|
+
nrows: 3
|
|
936
|
+
nwords: 8
|
|
937
|
+
radix: 32
|
|
938
|
+
basis:
|
|
939
|
+
11110000
|
|
940
|
+
00111100
|
|
941
|
+
00001111
|
|
942
|
+
words:
|
|
943
|
+
00000000
|
|
944
|
+
11110000
|
|
945
|
+
00111100
|
|
946
|
+
11001100
|
|
947
|
+
00001111
|
|
948
|
+
11111111
|
|
949
|
+
00110011
|
|
950
|
+
11000011
|
|
951
|
+
sage: E.print_data() # random - actually "print(P.print_data())"
|
|
952
|
+
ncols: 8
|
|
953
|
+
nrows: 4
|
|
954
|
+
nwords: 16
|
|
955
|
+
radix: 32
|
|
956
|
+
basis:
|
|
957
|
+
11110000
|
|
958
|
+
00111100
|
|
959
|
+
00001111
|
|
960
|
+
10101010
|
|
961
|
+
words:
|
|
962
|
+
00000000
|
|
963
|
+
11110000
|
|
964
|
+
00111100
|
|
965
|
+
11001100
|
|
966
|
+
00001111
|
|
967
|
+
11111111
|
|
968
|
+
00110011
|
|
969
|
+
11000011
|
|
970
|
+
10101010
|
|
971
|
+
01011010
|
|
972
|
+
10010110
|
|
973
|
+
01100110
|
|
974
|
+
10100101
|
|
975
|
+
01010101
|
|
976
|
+
10011001
|
|
977
|
+
01101001
|
|
978
|
+
"""
|
|
979
|
+
from sage.graphs.generic_graph_pyx import int_to_binary_string
|
|
980
|
+
cdef int ui
|
|
981
|
+
cdef int i
|
|
982
|
+
s = ''
|
|
983
|
+
s += "ncols:" + str(self.ncols)
|
|
984
|
+
s += "\nnrows:" + str(self.nrows)
|
|
985
|
+
s += "\nnwords:" + str(self.nwords)
|
|
986
|
+
s += "\nradix:" + str(self.radix)
|
|
987
|
+
s += "\nbasis:\n"
|
|
988
|
+
for i from 0 <= i < self.nrows:
|
|
989
|
+
b = list(int_to_binary_string(self.basis[i]).zfill(self.ncols))
|
|
990
|
+
b.reverse()
|
|
991
|
+
b.append('\n')
|
|
992
|
+
s += ''.join(b)
|
|
993
|
+
s += "\nwords:\n"
|
|
994
|
+
for ui from 0 <= ui < self.nwords:
|
|
995
|
+
b = list(int_to_binary_string(self.words[ui]).zfill(self.ncols))
|
|
996
|
+
b.reverse()
|
|
997
|
+
b.append('\n')
|
|
998
|
+
s += ''.join(b)
|
|
999
|
+
|
|
1000
|
+
def __repr__(self) -> str:
|
|
1001
|
+
"""
|
|
1002
|
+
String representation of ``self``.
|
|
1003
|
+
|
|
1004
|
+
EXAMPLES::
|
|
1005
|
+
|
|
1006
|
+
sage: import sage.coding.binary_code
|
|
1007
|
+
sage: from sage.coding.binary_code import *
|
|
1008
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
|
|
1009
|
+
sage: B = BinaryCode(M)
|
|
1010
|
+
sage: B
|
|
1011
|
+
Binary [8,4] linear code, generator matrix
|
|
1012
|
+
[11110000]
|
|
1013
|
+
[00111100]
|
|
1014
|
+
[00001111]
|
|
1015
|
+
[10101010]
|
|
1016
|
+
"""
|
|
1017
|
+
cdef int i
|
|
1018
|
+
s = 'Binary [%d,%d] linear code, generator matrix\n' % (
|
|
1019
|
+
self.ncols, self.nrows)
|
|
1020
|
+
for i in range(self.nrows):
|
|
1021
|
+
s += '[' + self._word((<codeword> 1)<<i) + ']\n'
|
|
1022
|
+
return s
|
|
1023
|
+
|
|
1024
|
+
def _word(self, coords):
|
|
1025
|
+
"""
|
|
1026
|
+
Considering ``coords`` as an integer in binary, think of the 0s and 1s
|
|
1027
|
+
as coefficients of the basis given by ``self.matrix()``. This function
|
|
1028
|
+
returns a string representation of that word.
|
|
1029
|
+
|
|
1030
|
+
EXAMPLES::
|
|
1031
|
+
|
|
1032
|
+
sage: from sage.coding.binary_code import *
|
|
1033
|
+
sage: M = Matrix(GF(2), [[1,1,1,1]])
|
|
1034
|
+
sage: B = BinaryCode(M)
|
|
1035
|
+
sage: B._word(0)
|
|
1036
|
+
'0000'
|
|
1037
|
+
sage: B._word(1)
|
|
1038
|
+
'1111'
|
|
1039
|
+
|
|
1040
|
+
Note that behavior under input which does not represent a word in
|
|
1041
|
+
the code is unspecified (gives nonsense).
|
|
1042
|
+
"""
|
|
1043
|
+
return ''.join('%d' % self.is_one(coords, j)
|
|
1044
|
+
for j in range(self.ncols))
|
|
1045
|
+
|
|
1046
|
+
def _is_one(self, word, col):
|
|
1047
|
+
"""
|
|
1048
|
+
Return the col-th letter of word, i.e. 0 or 1. Words are expressed
|
|
1049
|
+
as integers, which represent linear combinations of the rows of the
|
|
1050
|
+
generator matrix of the code.
|
|
1051
|
+
|
|
1052
|
+
EXAMPLES::
|
|
1053
|
+
|
|
1054
|
+
sage: import sage.coding.binary_code
|
|
1055
|
+
sage: from sage.coding.binary_code import *
|
|
1056
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
|
|
1057
|
+
sage: B = BinaryCode(M)
|
|
1058
|
+
sage: B
|
|
1059
|
+
Binary [8,4] linear code, generator matrix
|
|
1060
|
+
[11110000]
|
|
1061
|
+
[00111100]
|
|
1062
|
+
[00001111]
|
|
1063
|
+
[10101010]
|
|
1064
|
+
sage: B._is_one(7, 4)
|
|
1065
|
+
0
|
|
1066
|
+
sage: B._is_one(8, 4)
|
|
1067
|
+
1
|
|
1068
|
+
sage: B._is_automorphism([1,0,3,2,4,5,6,7], [0, 1, 2, 3, 4, 5, 6, 7, 9, 8, 11, 10, 13, 12, 15, 14])
|
|
1069
|
+
1
|
|
1070
|
+
"""
|
|
1071
|
+
return self.is_one(word, col) != 0
|
|
1072
|
+
|
|
1073
|
+
cdef int is_one(self, int word, int column) noexcept:
|
|
1074
|
+
return (self.words[word] & (<codeword> 1 << column)) >> column
|
|
1075
|
+
|
|
1076
|
+
def _is_automorphism(self, col_gamma, word_gamma):
|
|
1077
|
+
"""
|
|
1078
|
+
Check whether a given permutation is an automorphism of the code.
|
|
1079
|
+
|
|
1080
|
+
INPUT:
|
|
1081
|
+
|
|
1082
|
+
- ``col_gamma`` -- permutation sending i |--> col_gamma[i] acting
|
|
1083
|
+
on the columns
|
|
1084
|
+
- ``word_gamma`` -- permutation sending i |--> word_gamma[i] acting
|
|
1085
|
+
on the words
|
|
1086
|
+
|
|
1087
|
+
EXAMPLES::
|
|
1088
|
+
|
|
1089
|
+
sage: import sage.coding.binary_code
|
|
1090
|
+
sage: from sage.coding.binary_code import *
|
|
1091
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
|
|
1092
|
+
sage: B = BinaryCode(M)
|
|
1093
|
+
sage: B
|
|
1094
|
+
Binary [8,4] linear code, generator matrix
|
|
1095
|
+
[11110000]
|
|
1096
|
+
[00111100]
|
|
1097
|
+
[00001111]
|
|
1098
|
+
[10101010]
|
|
1099
|
+
sage: B._is_automorphism([1,0,3,2,4,5,6,7], [0, 1, 2, 3, 4, 5, 6, 7, 9, 8, 11, 10, 13, 12, 15, 14])
|
|
1100
|
+
1
|
|
1101
|
+
"""
|
|
1102
|
+
cdef int i
|
|
1103
|
+
cdef int *_col_gamma
|
|
1104
|
+
cdef int *_word_gamma
|
|
1105
|
+
_word_gamma = <int *> sig_malloc(self.nwords * sizeof(int))
|
|
1106
|
+
_col_gamma = <int *> sig_malloc(self.ncols * sizeof(int))
|
|
1107
|
+
if _col_gamma is NULL or _word_gamma is NULL:
|
|
1108
|
+
if _word_gamma is not NULL:
|
|
1109
|
+
sig_free(_word_gamma)
|
|
1110
|
+
if _col_gamma is not NULL:
|
|
1111
|
+
sig_free(_col_gamma)
|
|
1112
|
+
raise MemoryError("Memory.")
|
|
1113
|
+
for i from 0 <= i < self.nwords:
|
|
1114
|
+
_word_gamma[i] = word_gamma[i]
|
|
1115
|
+
for i from 0 <= i < self.ncols:
|
|
1116
|
+
_col_gamma[i] = col_gamma[i]
|
|
1117
|
+
result = self.is_automorphism(_col_gamma, _word_gamma)
|
|
1118
|
+
sig_free(_col_gamma)
|
|
1119
|
+
sig_free(_word_gamma)
|
|
1120
|
+
return result
|
|
1121
|
+
|
|
1122
|
+
cdef int is_automorphism(self, int *col_gamma, int *word_gamma) noexcept:
|
|
1123
|
+
cdef int i, j, self_nwords = self.nwords, self_ncols = self.ncols
|
|
1124
|
+
i = 1
|
|
1125
|
+
while i < self_nwords:
|
|
1126
|
+
for j from 0 <= j < self_ncols:
|
|
1127
|
+
if self.is_one(i, j) != self.is_one(word_gamma[i], col_gamma[j]):
|
|
1128
|
+
return 0
|
|
1129
|
+
i = i << 1
|
|
1130
|
+
return 1
|
|
1131
|
+
|
|
1132
|
+
def apply_permutation(self, labeling):
|
|
1133
|
+
"""
|
|
1134
|
+
Apply a column permutation to the code.
|
|
1135
|
+
|
|
1136
|
+
INPUT:
|
|
1137
|
+
|
|
1138
|
+
- ``labeling`` -- list permutation of the columns
|
|
1139
|
+
|
|
1140
|
+
EXAMPLES::
|
|
1141
|
+
|
|
1142
|
+
sage: from sage.coding.binary_code import *
|
|
1143
|
+
sage: B = BinaryCode(codes.GolayCode(GF(2)).generator_matrix())
|
|
1144
|
+
sage: B
|
|
1145
|
+
Binary [24,12] linear code, generator matrix
|
|
1146
|
+
[100000000000101011100011]
|
|
1147
|
+
[010000000000111110010010]
|
|
1148
|
+
[001000000000110100101011]
|
|
1149
|
+
[000100000000110001110110]
|
|
1150
|
+
[000010000000110011011001]
|
|
1151
|
+
[000001000000011001101101]
|
|
1152
|
+
[000000100000001100110111]
|
|
1153
|
+
[000000010000101101111000]
|
|
1154
|
+
[000000001000010110111100]
|
|
1155
|
+
[000000000100001011011110]
|
|
1156
|
+
[000000000010101110001101]
|
|
1157
|
+
[000000000001010111000111]
|
|
1158
|
+
sage: B.apply_permutation(list(range(11,-1,-1)) + list(range(12, 24)))
|
|
1159
|
+
sage: B
|
|
1160
|
+
Binary [24,12] linear code, generator matrix
|
|
1161
|
+
[000000000001101011100011]
|
|
1162
|
+
[000000000010111110010010]
|
|
1163
|
+
[000000000100110100101011]
|
|
1164
|
+
[000000001000110001110110]
|
|
1165
|
+
[000000010000110011011001]
|
|
1166
|
+
[000000100000011001101101]
|
|
1167
|
+
[000001000000001100110111]
|
|
1168
|
+
[000010000000101101111000]
|
|
1169
|
+
[000100000000010110111100]
|
|
1170
|
+
[001000000000001011011110]
|
|
1171
|
+
[010000000000101110001101]
|
|
1172
|
+
[100000000000010111000111]
|
|
1173
|
+
"""
|
|
1174
|
+
# Tests for this function implicitly test _apply_permutation_to_basis
|
|
1175
|
+
# and _update_words_from_basis. These functions should not be used
|
|
1176
|
+
# individually by the user, so they remain cdef'd.
|
|
1177
|
+
self._apply_permutation_to_basis(labeling)
|
|
1178
|
+
self._update_words_from_basis()
|
|
1179
|
+
|
|
1180
|
+
cdef void _apply_permutation_to_basis(self, object labeling) noexcept:
|
|
1181
|
+
cdef WordPermutation *wp
|
|
1182
|
+
cdef int i
|
|
1183
|
+
wp = create_word_perm(labeling)
|
|
1184
|
+
for i from 0 <= i < self.nrows:
|
|
1185
|
+
self.basis[i] = permute_word_by_wp(wp, self.basis[i])
|
|
1186
|
+
dealloc_word_perm(wp)
|
|
1187
|
+
|
|
1188
|
+
cdef void _update_words_from_basis(self) noexcept:
|
|
1189
|
+
cdef codeword word
|
|
1190
|
+
cdef int j, parity, combination
|
|
1191
|
+
word = 0
|
|
1192
|
+
parity = 0
|
|
1193
|
+
combination = 0
|
|
1194
|
+
while True:
|
|
1195
|
+
self.words[combination] = word
|
|
1196
|
+
parity ^= 1
|
|
1197
|
+
j = 0
|
|
1198
|
+
if not parity:
|
|
1199
|
+
while not combination & (1 << j):
|
|
1200
|
+
j += 1
|
|
1201
|
+
j += 1
|
|
1202
|
+
if j == self.nrows:
|
|
1203
|
+
break
|
|
1204
|
+
else:
|
|
1205
|
+
combination ^= (1 << j)
|
|
1206
|
+
word ^= self.basis[j]
|
|
1207
|
+
|
|
1208
|
+
cpdef int put_in_std_form(self) noexcept:
|
|
1209
|
+
"""
|
|
1210
|
+
Put the code in binary form, which is defined by an identity matrix on
|
|
1211
|
+
the left, augmented by a matrix of data.
|
|
1212
|
+
|
|
1213
|
+
EXAMPLES::
|
|
1214
|
+
|
|
1215
|
+
sage: from sage.coding.binary_code import *
|
|
1216
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0], [0,0,1,1,1,1]])
|
|
1217
|
+
sage: B = BinaryCode(M); B
|
|
1218
|
+
Binary [6,2] linear code, generator matrix
|
|
1219
|
+
[111100]
|
|
1220
|
+
[001111]
|
|
1221
|
+
sage: B.put_in_std_form(); B
|
|
1222
|
+
0
|
|
1223
|
+
Binary [6,2] linear code, generator matrix
|
|
1224
|
+
[101011]
|
|
1225
|
+
[010111]
|
|
1226
|
+
"""
|
|
1227
|
+
cdef codeword swap, current = 1, pivots = 0
|
|
1228
|
+
cdef int i, j, k, row = 0
|
|
1229
|
+
cdef object perm
|
|
1230
|
+
while row < self.nrows:
|
|
1231
|
+
i = row
|
|
1232
|
+
while i < self.nrows and not self.basis[i] & current:
|
|
1233
|
+
i += 1
|
|
1234
|
+
if i < self.nrows:
|
|
1235
|
+
pivots += current
|
|
1236
|
+
if i != row:
|
|
1237
|
+
swap = self.basis[row]
|
|
1238
|
+
self.basis[row] = self.basis[i]
|
|
1239
|
+
self.basis[i] = swap
|
|
1240
|
+
for j from 0 <= j < row:
|
|
1241
|
+
if self.basis[j] & current:
|
|
1242
|
+
self.basis[j] ^= self.basis[row]
|
|
1243
|
+
for j from row < j < self.nrows:
|
|
1244
|
+
if self.basis[j] & current:
|
|
1245
|
+
self.basis[j] ^= self.basis[row]
|
|
1246
|
+
row += 1
|
|
1247
|
+
current = current << 1
|
|
1248
|
+
perm = [0]*self.ncols
|
|
1249
|
+
j = 0
|
|
1250
|
+
k = self.nrows
|
|
1251
|
+
for i from 0 <= i < self.ncols:
|
|
1252
|
+
if ((<codeword>1) << i) & pivots:
|
|
1253
|
+
perm[i] = j
|
|
1254
|
+
j += 1
|
|
1255
|
+
else:
|
|
1256
|
+
perm[i] = k
|
|
1257
|
+
k += 1
|
|
1258
|
+
self._apply_permutation_to_basis(perm)
|
|
1259
|
+
self._update_words_from_basis()
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
cdef class OrbitPartition:
|
|
1263
|
+
"""
|
|
1264
|
+
Structure which keeps track of which vertices are equivalent
|
|
1265
|
+
under the part of the automorphism group that has already been
|
|
1266
|
+
seen, during search. Essentially a disjoint-set data structure*,
|
|
1267
|
+
which also keeps track of the minimum element and size of each
|
|
1268
|
+
cell of the partition, and the size of the partition.
|
|
1269
|
+
|
|
1270
|
+
See :wikipedia:`Disjoint-set_data_structure`
|
|
1271
|
+
"""
|
|
1272
|
+
def __cinit__(self, int nrows, int ncols):
|
|
1273
|
+
"""
|
|
1274
|
+
Initialize.
|
|
1275
|
+
|
|
1276
|
+
TESTS::
|
|
1277
|
+
|
|
1278
|
+
sage: import sage.coding.binary_code
|
|
1279
|
+
sage: from sage.coding.binary_code import *
|
|
1280
|
+
sage: O = OrbitPartition(4, 8)
|
|
1281
|
+
sage: TestSuite(O).run(skip='_test_pickling')
|
|
1282
|
+
"""
|
|
1283
|
+
cdef int col
|
|
1284
|
+
cdef int nwords, word
|
|
1285
|
+
nwords = (1 << nrows)
|
|
1286
|
+
self.nwords = nwords
|
|
1287
|
+
self.ncols = ncols
|
|
1288
|
+
self.mem = MemoryAllocator()
|
|
1289
|
+
self.wd_parent = <int *> self.mem.malloc(nwords * sizeof(int))
|
|
1290
|
+
self.wd_rank = <int *> self.mem.malloc(nwords * sizeof(int))
|
|
1291
|
+
self.wd_min_cell_rep = <int *> self.mem.malloc(nwords * sizeof(int))
|
|
1292
|
+
self.wd_size = <int *> self.mem.malloc(nwords * sizeof(int))
|
|
1293
|
+
self.col_parent = <int *> self.mem.malloc(ncols * sizeof(int))
|
|
1294
|
+
self.col_rank = <int *> self.mem.malloc(ncols * sizeof(int))
|
|
1295
|
+
self.col_min_cell_rep = <int *> self.mem.malloc(ncols * sizeof(int))
|
|
1296
|
+
self.col_size = <int *> self.mem.malloc(ncols * sizeof(int))
|
|
1297
|
+
for word from 0 <= word < nwords:
|
|
1298
|
+
self.wd_parent[word] = word
|
|
1299
|
+
self.wd_rank[word] = 0
|
|
1300
|
+
self.wd_min_cell_rep[word] = word
|
|
1301
|
+
self.wd_size[word] = 1
|
|
1302
|
+
for col from 0 <= col < ncols:
|
|
1303
|
+
self.col_parent[col] = col
|
|
1304
|
+
self.col_rank[col] = 0
|
|
1305
|
+
self.col_min_cell_rep[col] = col
|
|
1306
|
+
self.col_size[col] = 1
|
|
1307
|
+
|
|
1308
|
+
def __repr__(self):
|
|
1309
|
+
"""
|
|
1310
|
+
Return a string representation of the orbit partition.
|
|
1311
|
+
|
|
1312
|
+
EXAMPLES::
|
|
1313
|
+
|
|
1314
|
+
sage: import sage.coding.binary_code
|
|
1315
|
+
sage: from sage.coding.binary_code import *
|
|
1316
|
+
sage: O = OrbitPartition(4, 8)
|
|
1317
|
+
sage: O
|
|
1318
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1319
|
+
Words:
|
|
1320
|
+
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
1321
|
+
Columns:
|
|
1322
|
+
0,1,2,3,4,5,6,7
|
|
1323
|
+
"""
|
|
1324
|
+
cdef int i
|
|
1325
|
+
cdef int j
|
|
1326
|
+
s = 'OrbitPartition on %d words and %d columns. Data:\n' % (self.nwords,
|
|
1327
|
+
self.ncols)
|
|
1328
|
+
# s += 'Parents::\n'
|
|
1329
|
+
s += 'Words:\n'
|
|
1330
|
+
for i from 0 <= i < self.nwords:
|
|
1331
|
+
s += '%d,' % self.wd_parent[i]
|
|
1332
|
+
s = s[:-1] + '\nColumns:\n'
|
|
1333
|
+
for j from 0 <= j < self.ncols:
|
|
1334
|
+
s += '%d,' % self.col_parent[j]
|
|
1335
|
+
# s = s[:-1] + '\n'
|
|
1336
|
+
# s += 'Min Cell Reps::\n'
|
|
1337
|
+
# s += 'Words:\n'
|
|
1338
|
+
# for i from 0 <= i < self.nwords:
|
|
1339
|
+
# s += '%d,' % self.wd_min_cell_rep[i]
|
|
1340
|
+
# s = s[:-1] + '\nColumns:\n'
|
|
1341
|
+
# for j from 0 <= j < self.ncols:
|
|
1342
|
+
# s += '%d,' % self.col_min_cell_rep[j]
|
|
1343
|
+
return s[:-1]
|
|
1344
|
+
|
|
1345
|
+
def _wd_find(self, word):
|
|
1346
|
+
"""
|
|
1347
|
+
Return the root of word.
|
|
1348
|
+
|
|
1349
|
+
EXAMPLES::
|
|
1350
|
+
|
|
1351
|
+
sage: import sage.coding.binary_code
|
|
1352
|
+
sage: from sage.coding.binary_code import *
|
|
1353
|
+
sage: O = OrbitPartition(4, 8)
|
|
1354
|
+
sage: O
|
|
1355
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1356
|
+
Words:
|
|
1357
|
+
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
1358
|
+
Columns:
|
|
1359
|
+
0,1,2,3,4,5,6,7
|
|
1360
|
+
sage: O._wd_find(12)
|
|
1361
|
+
12
|
|
1362
|
+
"""
|
|
1363
|
+
return self.wd_find(word)
|
|
1364
|
+
|
|
1365
|
+
cdef int wd_find(self, int word) noexcept:
|
|
1366
|
+
if self.wd_parent[word] == word:
|
|
1367
|
+
return word
|
|
1368
|
+
else:
|
|
1369
|
+
self.wd_parent[word] = self.wd_find(self.wd_parent[word])
|
|
1370
|
+
return self.wd_parent[word]
|
|
1371
|
+
|
|
1372
|
+
def _wd_union(self, x, y):
|
|
1373
|
+
"""
|
|
1374
|
+
Join the cells containing x and y.
|
|
1375
|
+
|
|
1376
|
+
EXAMPLES::
|
|
1377
|
+
|
|
1378
|
+
sage: import sage.coding.binary_code
|
|
1379
|
+
sage: from sage.coding.binary_code import *
|
|
1380
|
+
sage: O = OrbitPartition(4, 8)
|
|
1381
|
+
sage: O
|
|
1382
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1383
|
+
Words:
|
|
1384
|
+
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
1385
|
+
Columns:
|
|
1386
|
+
0,1,2,3,4,5,6,7
|
|
1387
|
+
sage: O._wd_union(1,10)
|
|
1388
|
+
sage: O
|
|
1389
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1390
|
+
Words:
|
|
1391
|
+
0,1,2,3,4,5,6,7,8,9,1,11,12,13,14,15
|
|
1392
|
+
Columns:
|
|
1393
|
+
0,1,2,3,4,5,6,7
|
|
1394
|
+
sage: O._wd_find(10)
|
|
1395
|
+
1
|
|
1396
|
+
"""
|
|
1397
|
+
self.wd_union(x, y)
|
|
1398
|
+
|
|
1399
|
+
cdef void wd_union(self, int x, int y) noexcept:
|
|
1400
|
+
cdef int x_root, y_root
|
|
1401
|
+
x_root = self.wd_find(x)
|
|
1402
|
+
y_root = self.wd_find(y)
|
|
1403
|
+
if self.wd_rank[x_root] > self.wd_rank[y_root]:
|
|
1404
|
+
self.wd_parent[y_root] = x_root
|
|
1405
|
+
self.wd_min_cell_rep[x_root] = min(self.wd_min_cell_rep[x_root],self.wd_min_cell_rep[y_root])
|
|
1406
|
+
self.wd_size[x_root] += self.wd_size[y_root]
|
|
1407
|
+
elif self.wd_rank[x_root] < self.wd_rank[y_root]:
|
|
1408
|
+
self.wd_parent[x_root] = y_root
|
|
1409
|
+
self.wd_min_cell_rep[y_root] = min(self.wd_min_cell_rep[x_root],self.wd_min_cell_rep[y_root])
|
|
1410
|
+
self.wd_size[y_root] += self.wd_size[x_root]
|
|
1411
|
+
elif x_root != y_root:
|
|
1412
|
+
self.wd_parent[y_root] = x_root
|
|
1413
|
+
self.wd_min_cell_rep[x_root] = min(self.wd_min_cell_rep[x_root],self.wd_min_cell_rep[y_root])
|
|
1414
|
+
self.wd_size[x_root] += self.wd_size[y_root]
|
|
1415
|
+
self.wd_rank[x_root] += 1
|
|
1416
|
+
|
|
1417
|
+
def _col_find(self, col):
|
|
1418
|
+
"""
|
|
1419
|
+
Return the root of col.
|
|
1420
|
+
|
|
1421
|
+
EXAMPLES::
|
|
1422
|
+
|
|
1423
|
+
sage: import sage.coding.binary_code
|
|
1424
|
+
sage: from sage.coding.binary_code import *
|
|
1425
|
+
sage: O = OrbitPartition(4, 8)
|
|
1426
|
+
sage: O
|
|
1427
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1428
|
+
Words:
|
|
1429
|
+
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
1430
|
+
Columns:
|
|
1431
|
+
0,1,2,3,4,5,6,7
|
|
1432
|
+
sage: O._col_find(6)
|
|
1433
|
+
6
|
|
1434
|
+
"""
|
|
1435
|
+
return self.col_find(col)
|
|
1436
|
+
|
|
1437
|
+
cdef int col_find(self, int col) noexcept:
|
|
1438
|
+
if self.col_parent[col] == col:
|
|
1439
|
+
return col
|
|
1440
|
+
else:
|
|
1441
|
+
self.col_parent[col] = self.col_find(self.col_parent[col])
|
|
1442
|
+
return self.col_parent[col]
|
|
1443
|
+
|
|
1444
|
+
def _col_union(self, x, y):
|
|
1445
|
+
"""
|
|
1446
|
+
Join the cells containing x and y.
|
|
1447
|
+
|
|
1448
|
+
EXAMPLES::
|
|
1449
|
+
|
|
1450
|
+
sage: import sage.coding.binary_code
|
|
1451
|
+
sage: from sage.coding.binary_code import *
|
|
1452
|
+
sage: O = OrbitPartition(4, 8)
|
|
1453
|
+
sage: O
|
|
1454
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1455
|
+
Words:
|
|
1456
|
+
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
1457
|
+
Columns:
|
|
1458
|
+
0,1,2,3,4,5,6,7
|
|
1459
|
+
sage: O._col_union(1,4)
|
|
1460
|
+
sage: O
|
|
1461
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1462
|
+
Words:
|
|
1463
|
+
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
1464
|
+
Columns:
|
|
1465
|
+
0,1,2,3,1,5,6,7
|
|
1466
|
+
sage: O._col_find(4)
|
|
1467
|
+
1
|
|
1468
|
+
"""
|
|
1469
|
+
self.col_union(x, y)
|
|
1470
|
+
|
|
1471
|
+
cdef void col_union(self, int x, int y) noexcept:
|
|
1472
|
+
cdef int x_root, y_root
|
|
1473
|
+
x_root = self.col_find(x)
|
|
1474
|
+
y_root = self.col_find(y)
|
|
1475
|
+
if self.col_rank[x_root] > self.col_rank[y_root]:
|
|
1476
|
+
self.col_parent[y_root] = x_root
|
|
1477
|
+
self.col_min_cell_rep[x_root] = min(self.col_min_cell_rep[x_root],self.col_min_cell_rep[y_root])
|
|
1478
|
+
self.col_size[x_root] += self.col_size[y_root]
|
|
1479
|
+
elif self.col_rank[x_root] < self.col_rank[y_root]:
|
|
1480
|
+
self.col_parent[x_root] = y_root
|
|
1481
|
+
self.col_min_cell_rep[y_root] = min(self.col_min_cell_rep[x_root],self.col_min_cell_rep[y_root])
|
|
1482
|
+
self.col_size[y_root] += self.col_size[x_root]
|
|
1483
|
+
elif x_root != y_root:
|
|
1484
|
+
self.col_parent[y_root] = x_root
|
|
1485
|
+
self.col_min_cell_rep[x_root] = min(self.col_min_cell_rep[x_root],self.col_min_cell_rep[y_root])
|
|
1486
|
+
self.col_size[x_root] += self.col_size[y_root]
|
|
1487
|
+
self.col_rank[x_root] += 1
|
|
1488
|
+
|
|
1489
|
+
def _merge_perm(self, col_gamma, wd_gamma):
|
|
1490
|
+
"""
|
|
1491
|
+
Merges the cells of ``self`` under the given permutation. If gamma[a] = b,
|
|
1492
|
+
then after merge_perm, a and b will be in the same cell. Returns 0 if
|
|
1493
|
+
nothing was done, otherwise returns 1.
|
|
1494
|
+
|
|
1495
|
+
EXAMPLES::
|
|
1496
|
+
|
|
1497
|
+
sage: import sage.coding.binary_code
|
|
1498
|
+
sage: from sage.coding.binary_code import *
|
|
1499
|
+
sage: O = OrbitPartition(4, 8)
|
|
1500
|
+
sage: O
|
|
1501
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1502
|
+
Words:
|
|
1503
|
+
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
|
1504
|
+
Columns:
|
|
1505
|
+
0,1,2,3,4,5,6,7
|
|
1506
|
+
sage: O._merge_perm([1,0,3,2,4,5,6,7], [0,1,2,3,4,5,6,7,9,8,11,10,13,12,15,14])
|
|
1507
|
+
1
|
|
1508
|
+
sage: O
|
|
1509
|
+
OrbitPartition on 16 words and 8 columns. Data:
|
|
1510
|
+
Words:
|
|
1511
|
+
0,1,2,3,4,5,6,7,8,8,10,10,12,12,14,14
|
|
1512
|
+
Columns:
|
|
1513
|
+
0,0,2,2,4,5,6,7
|
|
1514
|
+
"""
|
|
1515
|
+
cdef int i
|
|
1516
|
+
cdef int *_col_gamma
|
|
1517
|
+
cdef int *_wd_gamma
|
|
1518
|
+
_wd_gamma = <int *> sig_malloc(self.nwords * sizeof(int))
|
|
1519
|
+
_col_gamma = <int *> sig_malloc(self.ncols * sizeof(int))
|
|
1520
|
+
if _col_gamma is NULL or _wd_gamma is NULL:
|
|
1521
|
+
if _wd_gamma is not NULL:
|
|
1522
|
+
sig_free(_wd_gamma)
|
|
1523
|
+
if _col_gamma is not NULL:
|
|
1524
|
+
sig_free(_col_gamma)
|
|
1525
|
+
raise MemoryError("Memory.")
|
|
1526
|
+
for i from 0 <= i < self.nwords:
|
|
1527
|
+
_wd_gamma[i] = wd_gamma[i]
|
|
1528
|
+
for i from 0 <= i < self.ncols:
|
|
1529
|
+
_col_gamma[i] = col_gamma[i]
|
|
1530
|
+
result = self.merge_perm(_col_gamma, _wd_gamma)
|
|
1531
|
+
sig_free(_col_gamma)
|
|
1532
|
+
sig_free(_wd_gamma)
|
|
1533
|
+
return result
|
|
1534
|
+
|
|
1535
|
+
cdef int merge_perm(self, int *col_gamma, int *wd_gamma) noexcept:
|
|
1536
|
+
cdef int i, gamma_i_root
|
|
1537
|
+
cdef int j, gamma_j_root, return_value = 0
|
|
1538
|
+
for i in range(self.nwords):
|
|
1539
|
+
gamma_i_root = self.wd_find(wd_gamma[i])
|
|
1540
|
+
if gamma_i_root != i:
|
|
1541
|
+
return_value = 1
|
|
1542
|
+
self.wd_union(i, gamma_i_root)
|
|
1543
|
+
for j in range(self.ncols):
|
|
1544
|
+
gamma_j_root = self.col_find(col_gamma[j])
|
|
1545
|
+
if gamma_j_root != j:
|
|
1546
|
+
return_value = 1
|
|
1547
|
+
self.col_union(j, gamma_j_root)
|
|
1548
|
+
return return_value
|
|
1549
|
+
|
|
1550
|
+
cdef class PartitionStack:
|
|
1551
|
+
"""
|
|
1552
|
+
Partition stack structure for traversing the search tree during automorphism
|
|
1553
|
+
group computation.
|
|
1554
|
+
"""
|
|
1555
|
+
def __cinit__(self, arg1, arg2=None):
|
|
1556
|
+
"""
|
|
1557
|
+
Initialize.
|
|
1558
|
+
|
|
1559
|
+
TESTS::
|
|
1560
|
+
|
|
1561
|
+
sage: import sage.coding.binary_code
|
|
1562
|
+
sage: from sage.coding.binary_code import *
|
|
1563
|
+
sage: P = PartitionStack(2, 6)
|
|
1564
|
+
sage: TestSuite(P).run(skip='_test_pickling')
|
|
1565
|
+
"""
|
|
1566
|
+
cdef int k, nwords, ncols, sizeof_int
|
|
1567
|
+
cdef PartitionStack other = None
|
|
1568
|
+
cdef int *wd_ents
|
|
1569
|
+
cdef int *wd_lvls
|
|
1570
|
+
cdef int *col_ents
|
|
1571
|
+
cdef int *col_lvls
|
|
1572
|
+
cdef int *col_degs
|
|
1573
|
+
cdef int *col_counts
|
|
1574
|
+
cdef int *col_output
|
|
1575
|
+
cdef int *wd_degs
|
|
1576
|
+
cdef int *wd_counts
|
|
1577
|
+
cdef int *wd_output
|
|
1578
|
+
sizeof_int = sizeof(int)
|
|
1579
|
+
|
|
1580
|
+
try:
|
|
1581
|
+
self.nrows = <int> arg1
|
|
1582
|
+
self.nwords = 1 << self.nrows
|
|
1583
|
+
self.ncols = <int> arg2
|
|
1584
|
+
except Exception:
|
|
1585
|
+
other = arg1
|
|
1586
|
+
self.nrows = other.nrows
|
|
1587
|
+
self.nwords = other.nwords
|
|
1588
|
+
self.ncols = other.ncols
|
|
1589
|
+
|
|
1590
|
+
self.radix = sizeof_int << 3
|
|
1591
|
+
self.flag = (1 << (self.radix-1))
|
|
1592
|
+
|
|
1593
|
+
# data
|
|
1594
|
+
self.mem = MemoryAllocator()
|
|
1595
|
+
self.wd_ents = <int *> self.mem.malloc(self.nwords * sizeof_int)
|
|
1596
|
+
self.wd_lvls = <int *> self.mem.malloc(self.nwords * sizeof_int)
|
|
1597
|
+
self.col_ents = <int *> self.mem.malloc(self.ncols * sizeof_int)
|
|
1598
|
+
self.col_lvls = <int *> self.mem.malloc(self.ncols * sizeof_int)
|
|
1599
|
+
|
|
1600
|
+
# scratch space
|
|
1601
|
+
self.col_degs = <int *> self.mem.malloc(self.ncols * sizeof_int)
|
|
1602
|
+
self.col_counts = <int *> self.mem.malloc(self.nwords * sizeof_int)
|
|
1603
|
+
self.col_output = <int *> self.mem.malloc(self.ncols * sizeof_int)
|
|
1604
|
+
self.wd_degs = <int *> self.mem.malloc(self.nwords * sizeof_int)
|
|
1605
|
+
self.wd_counts = <int *> self.mem.malloc((self.ncols + 1) * sizeof_int)
|
|
1606
|
+
self.wd_output = <int *> self.mem.malloc(self.nwords * sizeof_int)
|
|
1607
|
+
|
|
1608
|
+
nwords = self.nwords
|
|
1609
|
+
ncols = self.ncols
|
|
1610
|
+
|
|
1611
|
+
if other:
|
|
1612
|
+
memcpy(self.wd_ents, other.wd_ents, self.nwords * sizeof_int)
|
|
1613
|
+
memcpy(self.wd_lvls, other.wd_lvls, self.nwords * sizeof_int)
|
|
1614
|
+
memcpy(self.col_ents, other.col_ents, self.ncols * sizeof_int)
|
|
1615
|
+
memcpy(self.col_lvls, other.col_lvls, self.ncols * sizeof_int)
|
|
1616
|
+
else:
|
|
1617
|
+
wd_ents = self.wd_ents
|
|
1618
|
+
wd_lvls = self.wd_lvls
|
|
1619
|
+
col_ents = self.col_ents
|
|
1620
|
+
col_lvls = self.col_lvls
|
|
1621
|
+
for k from 0 <= k < nwords-1:
|
|
1622
|
+
wd_ents[k] = k
|
|
1623
|
+
wd_lvls[k] = 2*ncols
|
|
1624
|
+
for k from 0 <= k < ncols-1:
|
|
1625
|
+
col_ents[k] = k
|
|
1626
|
+
col_lvls[k] = 2*ncols
|
|
1627
|
+
wd_ents[nwords-1] = nwords-1
|
|
1628
|
+
wd_lvls[nwords-1] = -1
|
|
1629
|
+
col_ents[ncols-1] = ncols-1
|
|
1630
|
+
col_lvls[ncols-1] = -1
|
|
1631
|
+
|
|
1632
|
+
col_degs = self.col_degs
|
|
1633
|
+
col_counts = self.col_counts
|
|
1634
|
+
col_output = self.col_output
|
|
1635
|
+
wd_degs = self.wd_degs
|
|
1636
|
+
wd_counts = self.wd_counts
|
|
1637
|
+
wd_output = self.wd_output
|
|
1638
|
+
for k from 0 <= k < ncols:
|
|
1639
|
+
col_degs[k]=0
|
|
1640
|
+
col_output[k]=0
|
|
1641
|
+
wd_counts[k]=0
|
|
1642
|
+
wd_counts[ncols]=0
|
|
1643
|
+
for k from 0 <= k < nwords:
|
|
1644
|
+
col_counts[k]=0
|
|
1645
|
+
wd_degs[k]=0
|
|
1646
|
+
wd_output[k]=0
|
|
1647
|
+
|
|
1648
|
+
def __dealloc__(self):
|
|
1649
|
+
if self.basis_locations:
|
|
1650
|
+
sig_free(self.basis_locations)
|
|
1651
|
+
|
|
1652
|
+
def print_data(self):
|
|
1653
|
+
"""
|
|
1654
|
+
Print all data for ``self``.
|
|
1655
|
+
|
|
1656
|
+
EXAMPLES::
|
|
1657
|
+
|
|
1658
|
+
sage: import sage.coding.binary_code
|
|
1659
|
+
sage: from sage.coding.binary_code import *
|
|
1660
|
+
sage: P = PartitionStack(2, 6)
|
|
1661
|
+
sage: print(P.print_data())
|
|
1662
|
+
nwords:4
|
|
1663
|
+
nrows:2
|
|
1664
|
+
ncols:6
|
|
1665
|
+
radix:32
|
|
1666
|
+
wd_ents:
|
|
1667
|
+
0
|
|
1668
|
+
1
|
|
1669
|
+
2
|
|
1670
|
+
3
|
|
1671
|
+
wd_lvls:
|
|
1672
|
+
12
|
|
1673
|
+
12
|
|
1674
|
+
12
|
|
1675
|
+
-1
|
|
1676
|
+
col_ents:
|
|
1677
|
+
0
|
|
1678
|
+
1
|
|
1679
|
+
2
|
|
1680
|
+
3
|
|
1681
|
+
4
|
|
1682
|
+
5
|
|
1683
|
+
col_lvls:
|
|
1684
|
+
12
|
|
1685
|
+
12
|
|
1686
|
+
12
|
|
1687
|
+
12
|
|
1688
|
+
12
|
|
1689
|
+
-1
|
|
1690
|
+
col_degs:
|
|
1691
|
+
0
|
|
1692
|
+
0
|
|
1693
|
+
0
|
|
1694
|
+
0
|
|
1695
|
+
0
|
|
1696
|
+
0
|
|
1697
|
+
col_counts:
|
|
1698
|
+
0
|
|
1699
|
+
0
|
|
1700
|
+
0
|
|
1701
|
+
0
|
|
1702
|
+
col_output:
|
|
1703
|
+
0
|
|
1704
|
+
0
|
|
1705
|
+
0
|
|
1706
|
+
0
|
|
1707
|
+
0
|
|
1708
|
+
0
|
|
1709
|
+
wd_degs:
|
|
1710
|
+
0
|
|
1711
|
+
0
|
|
1712
|
+
0
|
|
1713
|
+
0
|
|
1714
|
+
wd_counts:
|
|
1715
|
+
0
|
|
1716
|
+
0
|
|
1717
|
+
0
|
|
1718
|
+
0
|
|
1719
|
+
0
|
|
1720
|
+
0
|
|
1721
|
+
0
|
|
1722
|
+
wd_output:
|
|
1723
|
+
0
|
|
1724
|
+
0
|
|
1725
|
+
0
|
|
1726
|
+
0
|
|
1727
|
+
"""
|
|
1728
|
+
cdef int i, j
|
|
1729
|
+
s = ''
|
|
1730
|
+
s += "nwords:" + str(self.nwords) + '\n'
|
|
1731
|
+
s += "nrows:" + str(self.nrows) + '\n'
|
|
1732
|
+
s += "ncols:" + str(self.ncols) + '\n'
|
|
1733
|
+
s += "radix:" + str(self.radix) + '\n'
|
|
1734
|
+
s += "wd_ents:" + '\n'
|
|
1735
|
+
for i from 0 <= i < self.nwords:
|
|
1736
|
+
s += str(self.wd_ents[i]) + '\n'
|
|
1737
|
+
s += "wd_lvls:" + '\n'
|
|
1738
|
+
for i from 0 <= i < self.nwords:
|
|
1739
|
+
s += str(self.wd_lvls[i]) + '\n'
|
|
1740
|
+
s += "col_ents:" + '\n'
|
|
1741
|
+
for i from 0 <= i < self.ncols:
|
|
1742
|
+
s += str(self.col_ents[i]) + '\n'
|
|
1743
|
+
s += "col_lvls:" + '\n'
|
|
1744
|
+
for i from 0 <= i < self.ncols:
|
|
1745
|
+
s += str(self.col_lvls[i]) + '\n'
|
|
1746
|
+
s += "col_degs:" + '\n'
|
|
1747
|
+
for i from 0 <= i < self.ncols:
|
|
1748
|
+
s += str(self.col_degs[i]) + '\n'
|
|
1749
|
+
s += "col_counts:" + '\n'
|
|
1750
|
+
for i from 0 <= i < self.nwords:
|
|
1751
|
+
s += str(self.col_counts[i]) + '\n'
|
|
1752
|
+
s += "col_output:" + '\n'
|
|
1753
|
+
for i from 0 <= i < self.ncols:
|
|
1754
|
+
s += str(self.col_output[i]) + '\n'
|
|
1755
|
+
s += "wd_degs:" + '\n'
|
|
1756
|
+
for i from 0 <= i < self.nwords:
|
|
1757
|
+
s += str(self.wd_degs[i]) + '\n'
|
|
1758
|
+
s += "wd_counts:" + '\n'
|
|
1759
|
+
for i from 0 <= i < self.ncols + 1:
|
|
1760
|
+
s += str(self.wd_counts[i]) + '\n'
|
|
1761
|
+
s += "wd_output:" + '\n'
|
|
1762
|
+
for i from 0 <= i < self.nwords:
|
|
1763
|
+
s += str(self.wd_output[i]) + '\n'
|
|
1764
|
+
if self.basis_locations:
|
|
1765
|
+
s += "basis_locations:" + '\n'
|
|
1766
|
+
j = 1
|
|
1767
|
+
while (1 << j) < self.nwords:
|
|
1768
|
+
j += 1
|
|
1769
|
+
for i from 0 <= i < j:
|
|
1770
|
+
s += str(self.basis_locations[i]) + '\n'
|
|
1771
|
+
return s
|
|
1772
|
+
|
|
1773
|
+
def __repr__(self) -> str:
|
|
1774
|
+
"""
|
|
1775
|
+
Return a string representation of ``self``.
|
|
1776
|
+
|
|
1777
|
+
EXAMPLES::
|
|
1778
|
+
|
|
1779
|
+
sage: import sage.coding.binary_code
|
|
1780
|
+
sage: from sage.coding.binary_code import *
|
|
1781
|
+
sage: P = PartitionStack(2, 6)
|
|
1782
|
+
sage: P
|
|
1783
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
1784
|
+
"""
|
|
1785
|
+
cdef int k
|
|
1786
|
+
s = ''
|
|
1787
|
+
last = ''
|
|
1788
|
+
current = ''
|
|
1789
|
+
for k in range(2 * self.ncols):
|
|
1790
|
+
current = self._repr_at_k(k)
|
|
1791
|
+
if current == last:
|
|
1792
|
+
break
|
|
1793
|
+
s += current
|
|
1794
|
+
last = current
|
|
1795
|
+
return s
|
|
1796
|
+
|
|
1797
|
+
def _repr_at_k(self, k) -> str:
|
|
1798
|
+
"""
|
|
1799
|
+
Give a string representing the partition at level k.
|
|
1800
|
+
|
|
1801
|
+
EXAMPLES::
|
|
1802
|
+
|
|
1803
|
+
sage: from sage.coding.binary_code import *
|
|
1804
|
+
sage: P = PartitionStack(2, 6); P
|
|
1805
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
1806
|
+
sage: P._repr_at_k(0)
|
|
1807
|
+
'({0,1,2,3}) ({0,1,2,3,4,5})\n'
|
|
1808
|
+
"""
|
|
1809
|
+
cdef int j
|
|
1810
|
+
s = '({'
|
|
1811
|
+
for j in range(self.nwords):
|
|
1812
|
+
s += str(self.wd_ents[j])
|
|
1813
|
+
if self.wd_lvls[j] <= k:
|
|
1814
|
+
s += '},{'
|
|
1815
|
+
else:
|
|
1816
|
+
s += ','
|
|
1817
|
+
s = s[:-2] + ') '
|
|
1818
|
+
s += '({'
|
|
1819
|
+
for j in range(self.ncols):
|
|
1820
|
+
s += str(self.col_ents[j])
|
|
1821
|
+
if self.col_lvls[j] <= k:
|
|
1822
|
+
s += '},{'
|
|
1823
|
+
else:
|
|
1824
|
+
s += ','
|
|
1825
|
+
s = s[:-2] + ')\n'
|
|
1826
|
+
return s
|
|
1827
|
+
|
|
1828
|
+
def _is_discrete(self, k):
|
|
1829
|
+
"""
|
|
1830
|
+
Return whether the partition at level k is discrete.
|
|
1831
|
+
|
|
1832
|
+
EXAMPLES::
|
|
1833
|
+
|
|
1834
|
+
sage: import sage.coding.binary_code
|
|
1835
|
+
sage: from sage.coding.binary_code import *
|
|
1836
|
+
sage: P = PartitionStack(2, 6)
|
|
1837
|
+
sage: [P._split_vertex(i,i+1) for i in range(5)]
|
|
1838
|
+
[0, 1, 2, 3, 4]
|
|
1839
|
+
sage: P._sort_wds(0, [0,2,3,1], 5)
|
|
1840
|
+
0
|
|
1841
|
+
sage: P
|
|
1842
|
+
({0,3,1,2}) ({0,1,2,3,4,5})
|
|
1843
|
+
({0,3,1,2}) ({0},{1,2,3,4,5})
|
|
1844
|
+
({0,3,1,2}) ({0},{1},{2,3,4,5})
|
|
1845
|
+
({0,3,1,2}) ({0},{1},{2},{3,4,5})
|
|
1846
|
+
({0,3,1,2}) ({0},{1},{2},{3},{4,5})
|
|
1847
|
+
({0},{3},{1},{2}) ({0},{1},{2},{3},{4},{5})
|
|
1848
|
+
sage: P._is_discrete(4)
|
|
1849
|
+
0
|
|
1850
|
+
sage: P._is_discrete(5)
|
|
1851
|
+
1
|
|
1852
|
+
"""
|
|
1853
|
+
return self.is_discrete(k)
|
|
1854
|
+
|
|
1855
|
+
cdef int is_discrete(self, int k) noexcept:
|
|
1856
|
+
cdef int i, self_ncols = self.ncols, self_nwords = self.nwords
|
|
1857
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
1858
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
1859
|
+
for i from 0 <= i < self_ncols:
|
|
1860
|
+
if self_col_lvls[i] > k:
|
|
1861
|
+
return 0
|
|
1862
|
+
for i from 0 <= i < self_nwords:
|
|
1863
|
+
if self_wd_lvls[i] > k:
|
|
1864
|
+
return 0
|
|
1865
|
+
return 1
|
|
1866
|
+
|
|
1867
|
+
def _num_cells(self, k):
|
|
1868
|
+
"""
|
|
1869
|
+
Return the number of cells in the partition at level k.
|
|
1870
|
+
|
|
1871
|
+
EXAMPLES::
|
|
1872
|
+
|
|
1873
|
+
sage: import sage.coding.binary_code
|
|
1874
|
+
sage: from sage.coding.binary_code import *
|
|
1875
|
+
sage: P = PartitionStack(2, 6)
|
|
1876
|
+
sage: [P._split_vertex(i,i+1) for i in range(5)]
|
|
1877
|
+
[0, 1, 2, 3, 4]
|
|
1878
|
+
sage: P
|
|
1879
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
1880
|
+
({0,1,2,3}) ({0},{1,2,3,4,5})
|
|
1881
|
+
({0,1,2,3}) ({0},{1},{2,3,4,5})
|
|
1882
|
+
({0,1,2,3}) ({0},{1},{2},{3,4,5})
|
|
1883
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4,5})
|
|
1884
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
|
|
1885
|
+
sage: P._num_cells(3)
|
|
1886
|
+
5
|
|
1887
|
+
"""
|
|
1888
|
+
return self.num_cells(k)
|
|
1889
|
+
|
|
1890
|
+
cdef int num_cells(self, int k) noexcept:
|
|
1891
|
+
cdef int i, j = 0
|
|
1892
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
1893
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
1894
|
+
for i from 0 <= i < self.nwords:
|
|
1895
|
+
if self_wd_lvls[i] <= k:
|
|
1896
|
+
j += 1
|
|
1897
|
+
for i from 0 <= i < self.ncols:
|
|
1898
|
+
if self_col_lvls[i] <= k:
|
|
1899
|
+
j += 1
|
|
1900
|
+
return j
|
|
1901
|
+
|
|
1902
|
+
def _sat_225(self, k):
|
|
1903
|
+
"""
|
|
1904
|
+
Return whether the partition at level k satisfies the hypotheses of
|
|
1905
|
+
Lemma 2.25 in Brendan McKay's Practical Graph Isomorphism paper (see
|
|
1906
|
+
sage/graphs/graph_isom.pyx.
|
|
1907
|
+
|
|
1908
|
+
EXAMPLES::
|
|
1909
|
+
|
|
1910
|
+
sage: import sage.coding.binary_code
|
|
1911
|
+
sage: from sage.coding.binary_code import *
|
|
1912
|
+
sage: P = PartitionStack(2, 6)
|
|
1913
|
+
sage: [P._split_vertex(i,i+1) for i in range(5)]
|
|
1914
|
+
[0, 1, 2, 3, 4]
|
|
1915
|
+
sage: P._sat_225(3)
|
|
1916
|
+
0
|
|
1917
|
+
sage: P._sat_225(4)
|
|
1918
|
+
1
|
|
1919
|
+
sage: P
|
|
1920
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
1921
|
+
({0,1,2,3}) ({0},{1,2,3,4,5})
|
|
1922
|
+
({0,1,2,3}) ({0},{1},{2,3,4,5})
|
|
1923
|
+
({0,1,2,3}) ({0},{1},{2},{3,4,5})
|
|
1924
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4,5})
|
|
1925
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
|
|
1926
|
+
"""
|
|
1927
|
+
return self.sat_225(k)
|
|
1928
|
+
|
|
1929
|
+
cdef int sat_225(self, int k) noexcept:
|
|
1930
|
+
cdef int i, n = self.nwords + self.ncols, in_cell = 0
|
|
1931
|
+
cdef int nontrivial_cells = 0, total_cells = self.num_cells(k)
|
|
1932
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
1933
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
1934
|
+
if n <= total_cells + 4:
|
|
1935
|
+
return 1
|
|
1936
|
+
for i from 0 <= i < self.nwords:
|
|
1937
|
+
if self_wd_lvls[i] <= k:
|
|
1938
|
+
if in_cell:
|
|
1939
|
+
nontrivial_cells += 1
|
|
1940
|
+
in_cell = 0
|
|
1941
|
+
else:
|
|
1942
|
+
in_cell = 1
|
|
1943
|
+
in_cell = 0
|
|
1944
|
+
for i from 0 <= i < self.ncols:
|
|
1945
|
+
if self_col_lvls[i] <= k:
|
|
1946
|
+
if in_cell:
|
|
1947
|
+
nontrivial_cells += 1
|
|
1948
|
+
in_cell = 0
|
|
1949
|
+
else:
|
|
1950
|
+
in_cell = 1
|
|
1951
|
+
if n == total_cells + nontrivial_cells:
|
|
1952
|
+
return 1
|
|
1953
|
+
if n == total_cells + nontrivial_cells + 1:
|
|
1954
|
+
return 1
|
|
1955
|
+
return 0
|
|
1956
|
+
|
|
1957
|
+
# def _new_min_cell_reps(self, k): #TODO
|
|
1958
|
+
# """
|
|
1959
|
+
# Returns an integer whose bits represent which columns are minimal cell
|
|
1960
|
+
# representatives.
|
|
1961
|
+
#
|
|
1962
|
+
# EXAMPLES::
|
|
1963
|
+
#
|
|
1964
|
+
# sage: import sage.coding.binary_code
|
|
1965
|
+
# sage: from sage.coding.binary_code import *
|
|
1966
|
+
# sage: P = PartitionStack(2, 6)
|
|
1967
|
+
# sage: [P._split_column(i,i+1) for i in range(5)]
|
|
1968
|
+
# [0, 1, 2, 3, 4]
|
|
1969
|
+
# sage: a = P._min_cell_reps(2)
|
|
1970
|
+
# sage: Integer(a).binary()
|
|
1971
|
+
# '111'
|
|
1972
|
+
# sage: P
|
|
1973
|
+
# ({0,1,2,3})
|
|
1974
|
+
# ({0,1,2,3})
|
|
1975
|
+
# ({0,1,2,3})
|
|
1976
|
+
# ({0,1,2,3})
|
|
1977
|
+
# ({0,1,2,3,4,5})
|
|
1978
|
+
# ({0},{1,2,3,4,5})
|
|
1979
|
+
# ({0},{1},{2,3,4,5})
|
|
1980
|
+
# ({0},{1},{2},{3,4,5})
|
|
1981
|
+
# ({0},{1},{2},{3},{4,5})
|
|
1982
|
+
# ({0},{1},{2},{3},{4},{5})
|
|
1983
|
+
#
|
|
1984
|
+
# """
|
|
1985
|
+
# return self.min_cell_reps(k)
|
|
1986
|
+
#
|
|
1987
|
+
# cdef int min_cell_reps(self, int k):
|
|
1988
|
+
# cdef int i
|
|
1989
|
+
# cdef int reps = 1
|
|
1990
|
+
# cdef int *self_col_lvls = self.col_lvls
|
|
1991
|
+
# for i from 0 < i < self.ncols:
|
|
1992
|
+
# if self_col_lvls[i-1] <= k:
|
|
1993
|
+
# reps += (1 << i)
|
|
1994
|
+
# return reps
|
|
1995
|
+
#
|
|
1996
|
+
cdef void new_min_cell_reps(self, int k, unsigned int *Omega, int start) noexcept:
|
|
1997
|
+
cdef int i
|
|
1998
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
1999
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
2000
|
+
cdef int *self_col_ents = self.col_ents
|
|
2001
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
2002
|
+
cdef int length, word
|
|
2003
|
+
cdef int radix = self.radix, nwords = self.nwords, ncols = self.ncols
|
|
2004
|
+
length = 1 + nwords/radix
|
|
2005
|
+
if nwords % radix:
|
|
2006
|
+
length += 1
|
|
2007
|
+
for i in range(length):
|
|
2008
|
+
Omega[start+i] = 0
|
|
2009
|
+
for i in range(1, ncols):
|
|
2010
|
+
Omega[start] += ((self_col_lvls[i-1] <= k) << self_col_ents[i])
|
|
2011
|
+
Omega[start+1] = (1 << self_wd_ents[0])
|
|
2012
|
+
for i in range(1, nwords):
|
|
2013
|
+
if self_wd_lvls[i-1] <= k:
|
|
2014
|
+
word = self_wd_lvls[i-1]
|
|
2015
|
+
Omega[start+1+word/radix] += (1 << word % radix)
|
|
2016
|
+
|
|
2017
|
+
# def _fixed_cols(self, mcrs, k): #TODO
|
|
2018
|
+
# """
|
|
2019
|
+
# Returns an integer whose bits represent which columns are fixed. For
|
|
2020
|
+
# efficiency, mcrs is the output of min_cell_reps.
|
|
2021
|
+
#
|
|
2022
|
+
# EXAMPLES::
|
|
2023
|
+
#
|
|
2024
|
+
# sage: import sage.coding.binary_code
|
|
2025
|
+
# sage: from sage.coding.binary_code import *
|
|
2026
|
+
# sage: P = PartitionStack(2, 6)
|
|
2027
|
+
# sage: [P._split_column(i,i+1) for i in range(5)]
|
|
2028
|
+
# [0, 1, 2, 3, 4]
|
|
2029
|
+
# sage: a = P._fixed_cols(7, 2)
|
|
2030
|
+
# sage: Integer(a).binary()
|
|
2031
|
+
# '11'
|
|
2032
|
+
# sage: P
|
|
2033
|
+
# ({0,1,2,3})
|
|
2034
|
+
# ({0,1,2,3})
|
|
2035
|
+
# ({0,1,2,3})
|
|
2036
|
+
# ({0,1,2,3})
|
|
2037
|
+
# ({0,1,2,3,4,5})
|
|
2038
|
+
# ({0},{1,2,3,4,5})
|
|
2039
|
+
# ({0},{1},{2,3,4,5})
|
|
2040
|
+
# ({0},{1},{2},{3,4,5})
|
|
2041
|
+
# ({0},{1},{2},{3},{4,5})
|
|
2042
|
+
# ({0},{1},{2},{3},{4},{5})
|
|
2043
|
+
#
|
|
2044
|
+
# """
|
|
2045
|
+
# return self.fixed_cols(mcrs, k)
|
|
2046
|
+
#
|
|
2047
|
+
# cdef int fixed_cols(self, int mcrs, int k):
|
|
2048
|
+
# cdef int i
|
|
2049
|
+
# cdef int fixed = 0
|
|
2050
|
+
# cdef int *self_col_lvls = self.col_lvls
|
|
2051
|
+
# for i from 0 <= i < self.ncols:
|
|
2052
|
+
# if self_col_lvls[i] <= k:
|
|
2053
|
+
# fixed += (1 << i)
|
|
2054
|
+
# return fixed & mcrs
|
|
2055
|
+
#
|
|
2056
|
+
cdef void fixed_vertices(self, int k, unsigned int *Phi, unsigned int *Omega, int start) noexcept:
|
|
2057
|
+
cdef int i, length, ell, fixed = 0
|
|
2058
|
+
cdef int radix = self.radix, nwords = self.nwords, ncols = self.ncols
|
|
2059
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
2060
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
2061
|
+
cdef int *self_col_ents = self.col_ents
|
|
2062
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
2063
|
+
for i from 0 <= i < ncols:
|
|
2064
|
+
fixed += ((self_col_lvls[i] <= k) << self_col_ents[i])
|
|
2065
|
+
Phi[start] = fixed & Omega[start]
|
|
2066
|
+
# zero out the rest of Phi
|
|
2067
|
+
length = 1 + nwords/self.radix
|
|
2068
|
+
if nwords % self.radix:
|
|
2069
|
+
length += 1
|
|
2070
|
+
for i from 0 < i < length:
|
|
2071
|
+
Phi[start+i] = 0
|
|
2072
|
+
for i from 0 <= i < nwords:
|
|
2073
|
+
ell = self_wd_ents[i]
|
|
2074
|
+
Phi[start+1+ell/radix] = ((self_wd_lvls[i] <= k) << ell % radix)
|
|
2075
|
+
for i from 0 < i < length:
|
|
2076
|
+
Phi[i] &= Omega[i]
|
|
2077
|
+
|
|
2078
|
+
# def _first_smallest_nontrivial(self, k): #TODO
|
|
2079
|
+
# """
|
|
2080
|
+
# Returns an integer representing the first, smallest nontrivial cell of columns.
|
|
2081
|
+
#
|
|
2082
|
+
# EXAMPLES::
|
|
2083
|
+
#
|
|
2084
|
+
# sage: import sage.coding.binary_code
|
|
2085
|
+
# sage: from sage.coding.binary_code import *
|
|
2086
|
+
# sage: P = PartitionStack(2, 6)
|
|
2087
|
+
# sage: [P._split_column(i,i+1) for i in range(5)]
|
|
2088
|
+
# [0, 1, 2, 3, 4]
|
|
2089
|
+
# sage: a = P._first_smallest_nontrivial(2)
|
|
2090
|
+
# sage: Integer(a).binary().zfill(32)
|
|
2091
|
+
# '00000000000000000000000000111100'
|
|
2092
|
+
# sage: P
|
|
2093
|
+
# ({0,1,2,3})
|
|
2094
|
+
# ({0,1,2,3})
|
|
2095
|
+
# ({0,1,2,3})
|
|
2096
|
+
# ({0,1,2,3})
|
|
2097
|
+
# ({0,1,2,3,4,5})
|
|
2098
|
+
# ({0},{1,2,3,4,5})
|
|
2099
|
+
# ({0},{1},{2,3,4,5})
|
|
2100
|
+
# ({0},{1},{2},{3,4,5})
|
|
2101
|
+
# ({0},{1},{2},{3},{4,5})
|
|
2102
|
+
# ({0},{1},{2},{3},{4},{5})
|
|
2103
|
+
#
|
|
2104
|
+
# """
|
|
2105
|
+
# return self.first_smallest_nontrivial(k)
|
|
2106
|
+
#
|
|
2107
|
+
# cdef int first_smallest_nontrivial(self, int k):
|
|
2108
|
+
# cdef int cell
|
|
2109
|
+
# cdef int i = 0, j = 0, location = 0, ncols = self.ncols
|
|
2110
|
+
# cdef int *self_col_lvls = self.col_lvls
|
|
2111
|
+
# while True:
|
|
2112
|
+
# if self_col_lvls[i] <= k:
|
|
2113
|
+
# if i != j and ncols > i - j + 1:
|
|
2114
|
+
# ncols = i - j + 1
|
|
2115
|
+
# location = j
|
|
2116
|
+
# j = i + 1
|
|
2117
|
+
# if self_col_lvls[i] == -1: break
|
|
2118
|
+
# i += 1
|
|
2119
|
+
# # location now points to the beginning of the first, smallest,
|
|
2120
|
+
# # nontrivial cell
|
|
2121
|
+
# j = location
|
|
2122
|
+
# self.v = self.col_ents[j]
|
|
2123
|
+
# while True:
|
|
2124
|
+
# if self_col_lvls[j] <= k: break
|
|
2125
|
+
# j += 1
|
|
2126
|
+
# # j now points to the last element of the cell
|
|
2127
|
+
# i = self.radix - j - 1 # the cell is represented in binary, reading from the right:
|
|
2128
|
+
# cell = (~0 << location) ^ (~0 << j+1) # <------- self.radix ----->
|
|
2129
|
+
# return cell # [0]*(radix-j-1) + [1]*(j-location+1) + [0]*location
|
|
2130
|
+
#
|
|
2131
|
+
cdef int new_first_smallest_nontrivial(self, int k, unsigned int *W, int start) noexcept:
|
|
2132
|
+
cdef int ell
|
|
2133
|
+
cdef int i = 0, j = 0, location = 0, min = self.ncols, nwords = self.nwords
|
|
2134
|
+
cdef int min_is_col = 1, radix = self.radix
|
|
2135
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
2136
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
2137
|
+
cdef int *self_col_ents = self.col_ents
|
|
2138
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
2139
|
+
while True:
|
|
2140
|
+
if self_col_lvls[i] <= k:
|
|
2141
|
+
if i != j and min > i - j + 1:
|
|
2142
|
+
min = i - j + 1
|
|
2143
|
+
location = j
|
|
2144
|
+
j = i + 1
|
|
2145
|
+
if self_col_lvls[i] == -1:
|
|
2146
|
+
break
|
|
2147
|
+
i += 1
|
|
2148
|
+
# i = 0; j = 0
|
|
2149
|
+
# while True:
|
|
2150
|
+
# if self_wd_lvls[i] <= k:
|
|
2151
|
+
# if i != j and min > i - j + 1:
|
|
2152
|
+
# min = i - j + 1
|
|
2153
|
+
# min_is_col = 0
|
|
2154
|
+
# location = j
|
|
2155
|
+
# j = i + 1
|
|
2156
|
+
# if self_wd_lvls[i] == -1:
|
|
2157
|
+
# break
|
|
2158
|
+
# i += 1
|
|
2159
|
+
# location now points to the beginning of the first, smallest,
|
|
2160
|
+
# nontrivial cell
|
|
2161
|
+
j = location
|
|
2162
|
+
# zero out this level of W:
|
|
2163
|
+
ell = 1 + nwords/radix
|
|
2164
|
+
if nwords % radix:
|
|
2165
|
+
ell += 1
|
|
2166
|
+
for i from 0 <= i < ell:
|
|
2167
|
+
W[start+i] = 0
|
|
2168
|
+
if min_is_col:
|
|
2169
|
+
while True:
|
|
2170
|
+
if self_col_lvls[j] <= k:
|
|
2171
|
+
break
|
|
2172
|
+
j += 1
|
|
2173
|
+
# j now points to the last element of the cell
|
|
2174
|
+
i = location
|
|
2175
|
+
while i <= j:
|
|
2176
|
+
W[start] ^= (1 << self_col_ents[i])
|
|
2177
|
+
i += 1
|
|
2178
|
+
return self_col_ents[location]
|
|
2179
|
+
else:
|
|
2180
|
+
while True:
|
|
2181
|
+
if self_wd_lvls[j] <= k:
|
|
2182
|
+
break
|
|
2183
|
+
j += 1
|
|
2184
|
+
# j now points to the last element of the cell
|
|
2185
|
+
i = location
|
|
2186
|
+
while i <= j:
|
|
2187
|
+
ell = self_wd_ents[i]
|
|
2188
|
+
W[start+1+ell/radix] ^= (1 << ell % radix)
|
|
2189
|
+
i += 1
|
|
2190
|
+
return self_wd_ents[location] ^ self.flag
|
|
2191
|
+
|
|
2192
|
+
def _dangerous_dont_use_set_ents_lvls(self, col_ents, col_lvls, wd_ents, wd_lvls):
|
|
2193
|
+
"""
|
|
2194
|
+
For debugging only.
|
|
2195
|
+
|
|
2196
|
+
EXAMPLES::
|
|
2197
|
+
|
|
2198
|
+
sage: import sage.coding.binary_code
|
|
2199
|
+
sage: from sage.coding.binary_code import *
|
|
2200
|
+
sage: P = PartitionStack(2, 6)
|
|
2201
|
+
sage: P
|
|
2202
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
2203
|
+
sage: P._dangerous_dont_use_set_ents_lvls([99]*6, [0,3,2,3,5,-1], [4,3,5,6], [3,2,1,-1])
|
|
2204
|
+
sage: P
|
|
2205
|
+
({4,3,5,6}) ({99},{99,99,99,99,99})
|
|
2206
|
+
({4,3,5},{6}) ({99},{99,99,99,99,99})
|
|
2207
|
+
({4,3},{5},{6}) ({99},{99,99},{99,99,99})
|
|
2208
|
+
({4},{3},{5},{6}) ({99},{99},{99},{99},{99,99})
|
|
2209
|
+
"""
|
|
2210
|
+
cdef int i
|
|
2211
|
+
for i from 0 <= i < len(col_ents):
|
|
2212
|
+
self.col_ents[i] = col_ents[i]
|
|
2213
|
+
for i from 0 <= i < len(col_lvls):
|
|
2214
|
+
self.col_lvls[i] = col_lvls[i]
|
|
2215
|
+
for i from 0 <= i < len(wd_ents):
|
|
2216
|
+
self.wd_ents[i] = wd_ents[i]
|
|
2217
|
+
for i from 0 <= i < len(wd_lvls):
|
|
2218
|
+
self.wd_lvls[i] = wd_lvls[i]
|
|
2219
|
+
|
|
2220
|
+
def _col_percolate(self, start, end):
|
|
2221
|
+
"""
|
|
2222
|
+
Do one round of bubble sort on ents.
|
|
2223
|
+
|
|
2224
|
+
EXAMPLES::
|
|
2225
|
+
|
|
2226
|
+
sage: import sage.coding.binary_code
|
|
2227
|
+
sage: from sage.coding.binary_code import *
|
|
2228
|
+
sage: P = PartitionStack(2, 6)
|
|
2229
|
+
sage: P._dangerous_dont_use_set_ents_lvls(list(range(5,-1,-1)), [1,2,2,3,3,-1], list(range(3,-1,-1)), [1,1,2,-1])
|
|
2230
|
+
sage: P
|
|
2231
|
+
({3,2,1,0}) ({5,4,3,2,1,0})
|
|
2232
|
+
({3},{2},{1,0}) ({5},{4,3,2,1,0})
|
|
2233
|
+
({3},{2},{1},{0}) ({5},{4},{3},{2,1,0})
|
|
2234
|
+
({3},{2},{1},{0}) ({5},{4},{3},{2},{1},{0})
|
|
2235
|
+
sage: P._wd_percolate(0,3)
|
|
2236
|
+
sage: P._col_percolate(0,5)
|
|
2237
|
+
sage: P
|
|
2238
|
+
({0,3,2,1}) ({0,5,4,3,2,1})
|
|
2239
|
+
({0},{3},{2,1}) ({0},{5,4,3,2,1})
|
|
2240
|
+
({0},{3},{2},{1}) ({0},{5},{4},{3,2,1})
|
|
2241
|
+
({0},{3},{2},{1}) ({0},{5},{4},{3},{2},{1})
|
|
2242
|
+
"""
|
|
2243
|
+
self.col_percolate(start, end)
|
|
2244
|
+
|
|
2245
|
+
cdef void col_percolate(self, int start, int end) noexcept:
|
|
2246
|
+
cdef int i, temp
|
|
2247
|
+
cdef int *self_col_ents = self.col_ents
|
|
2248
|
+
for i from end >= i > start:
|
|
2249
|
+
if self_col_ents[i] < self_col_ents[i-1]:
|
|
2250
|
+
temp = self.col_ents[i]
|
|
2251
|
+
self_col_ents[i] = self_col_ents[i-1]
|
|
2252
|
+
self_col_ents[i-1] = temp
|
|
2253
|
+
|
|
2254
|
+
def _wd_percolate(self, start, end):
|
|
2255
|
+
"""
|
|
2256
|
+
Do one round of bubble sort on ents.
|
|
2257
|
+
|
|
2258
|
+
EXAMPLES::
|
|
2259
|
+
|
|
2260
|
+
sage: import sage.coding.binary_code
|
|
2261
|
+
sage: from sage.coding.binary_code import *
|
|
2262
|
+
sage: P = PartitionStack(2, 6)
|
|
2263
|
+
sage: P._dangerous_dont_use_set_ents_lvls(list(range(5,-1,-1)), [1,2,2,3,3,-1], list(range(3,-1,-1)), [1,1,2,-1])
|
|
2264
|
+
sage: P
|
|
2265
|
+
({3,2,1,0}) ({5,4,3,2,1,0})
|
|
2266
|
+
({3},{2},{1,0}) ({5},{4,3,2,1,0})
|
|
2267
|
+
({3},{2},{1},{0}) ({5},{4},{3},{2,1,0})
|
|
2268
|
+
({3},{2},{1},{0}) ({5},{4},{3},{2},{1},{0})
|
|
2269
|
+
sage: P._wd_percolate(0,3)
|
|
2270
|
+
sage: P._col_percolate(0,5)
|
|
2271
|
+
sage: P
|
|
2272
|
+
({0,3,2,1}) ({0,5,4,3,2,1})
|
|
2273
|
+
({0},{3},{2,1}) ({0},{5,4,3,2,1})
|
|
2274
|
+
({0},{3},{2},{1}) ({0},{5},{4},{3,2,1})
|
|
2275
|
+
({0},{3},{2},{1}) ({0},{5},{4},{3},{2},{1})
|
|
2276
|
+
"""
|
|
2277
|
+
self.wd_percolate(start, end)
|
|
2278
|
+
|
|
2279
|
+
cdef void wd_percolate(self, int start, int end) noexcept:
|
|
2280
|
+
cdef int i, temp
|
|
2281
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
2282
|
+
for i from end >= i > start:
|
|
2283
|
+
if self_wd_ents[i] < self_wd_ents[i-1]:
|
|
2284
|
+
temp = self.wd_ents[i]
|
|
2285
|
+
self_wd_ents[i] = self_wd_ents[i-1]
|
|
2286
|
+
self_wd_ents[i-1] = temp
|
|
2287
|
+
|
|
2288
|
+
# def _split_column(self, int v, int k): #TODO
|
|
2289
|
+
# """
|
|
2290
|
+
# Split column v out, placing it before the rest of the cell it was in.
|
|
2291
|
+
# Returns the location of the split column.
|
|
2292
|
+
#
|
|
2293
|
+
# EXAMPLES::
|
|
2294
|
+
#
|
|
2295
|
+
# sage: import sage.coding.binary_code
|
|
2296
|
+
# sage: from sage.coding.binary_code import *
|
|
2297
|
+
# sage: P = PartitionStack(2, 6)
|
|
2298
|
+
# sage: [P._split_column(i,i+1) for i in range(5)]
|
|
2299
|
+
# [0, 1, 2, 3, 4]
|
|
2300
|
+
# sage: P
|
|
2301
|
+
# ({0,1,2,3})
|
|
2302
|
+
# ({0,1,2,3})
|
|
2303
|
+
# ({0,1,2,3})
|
|
2304
|
+
# ({0,1,2,3})
|
|
2305
|
+
# ({0,1,2,3,4,5})
|
|
2306
|
+
# ({0},{1,2,3,4,5})
|
|
2307
|
+
# ({0},{1},{2,3,4,5})
|
|
2308
|
+
# ({0},{1},{2},{3,4,5})
|
|
2309
|
+
# ({0},{1},{2},{3},{4,5})
|
|
2310
|
+
# ({0},{1},{2},{3},{4},{5})
|
|
2311
|
+
# sage: P = PartitionStack(2, 6)
|
|
2312
|
+
# sage: P._split_column(0,1)
|
|
2313
|
+
# 0
|
|
2314
|
+
# sage: P._split_column(2,2)
|
|
2315
|
+
# 1
|
|
2316
|
+
# sage: P
|
|
2317
|
+
# ({0,1,2,3})
|
|
2318
|
+
# ({0,1,2,3})
|
|
2319
|
+
# ({0,1,2,3})
|
|
2320
|
+
# ({0,1,2,3})
|
|
2321
|
+
# ({0,2,1,3,4,5})
|
|
2322
|
+
# ({0},{2,1,3,4,5})
|
|
2323
|
+
# ({0},{2},{1,3,4,5})
|
|
2324
|
+
# ({0},{2},{1,3,4,5})
|
|
2325
|
+
# ({0},{2},{1,3,4,5})
|
|
2326
|
+
# ({0},{2},{1,3,4,5})
|
|
2327
|
+
#
|
|
2328
|
+
# """
|
|
2329
|
+
# return self.split_column(v, k)
|
|
2330
|
+
#
|
|
2331
|
+
# cdef int split_column(self, int v, int k):
|
|
2332
|
+
# cdef int i = 0, j
|
|
2333
|
+
# cdef int *self_col_ents = self.col_ents
|
|
2334
|
+
# cdef int *self_col_lvls = self.col_lvls
|
|
2335
|
+
# while self_col_ents[i] != v: i += 1
|
|
2336
|
+
# j = i
|
|
2337
|
+
# while self_col_lvls[i] > k: i += 1
|
|
2338
|
+
# if j == 0 or self_col_lvls[j-1] <= k:
|
|
2339
|
+
# self.col_percolate(j+1, i)
|
|
2340
|
+
# else:
|
|
2341
|
+
# while j != 0 and self_col_lvls[j-1] > k:
|
|
2342
|
+
# self_col_ents[j] = self_col_ents[j-1]
|
|
2343
|
+
# j -= 1
|
|
2344
|
+
# self_col_ents[j] = v
|
|
2345
|
+
# self_col_lvls[j] = k
|
|
2346
|
+
# return j
|
|
2347
|
+
#
|
|
2348
|
+
|
|
2349
|
+
def _split_vertex(self, v, k):
|
|
2350
|
+
"""
|
|
2351
|
+
Split vertex v out, placing it before the rest of the cell it was in.
|
|
2352
|
+
Returns the location of the split vertex.
|
|
2353
|
+
|
|
2354
|
+
.. NOTE::
|
|
2355
|
+
|
|
2356
|
+
There is a convention regarding whether a vertex is a word or a
|
|
2357
|
+
column. See the 'flag' attribute of the PartitionStack object:
|
|
2358
|
+
If vertex&flag is not zero, it is a word.
|
|
2359
|
+
|
|
2360
|
+
EXAMPLES::
|
|
2361
|
+
|
|
2362
|
+
sage: import sage.coding.binary_code
|
|
2363
|
+
sage: from sage.coding.binary_code import *
|
|
2364
|
+
sage: P = PartitionStack(2, 6)
|
|
2365
|
+
sage: [P._split_vertex(i,i+1) for i in range(5)]
|
|
2366
|
+
[0, 1, 2, 3, 4]
|
|
2367
|
+
sage: P
|
|
2368
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
2369
|
+
({0,1,2,3}) ({0},{1,2,3,4,5})
|
|
2370
|
+
({0,1,2,3}) ({0},{1},{2,3,4,5})
|
|
2371
|
+
({0,1,2,3}) ({0},{1},{2},{3,4,5})
|
|
2372
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4,5})
|
|
2373
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
|
|
2374
|
+
"""
|
|
2375
|
+
return self.split_vertex(v, k)
|
|
2376
|
+
|
|
2377
|
+
cdef int split_vertex(self, int v, int k) noexcept:
|
|
2378
|
+
cdef int i = 0, j, flag = self.flag
|
|
2379
|
+
cdef int *ents
|
|
2380
|
+
cdef int *lvls
|
|
2381
|
+
if v & flag:
|
|
2382
|
+
ents = self.wd_ents
|
|
2383
|
+
lvls = self.wd_lvls
|
|
2384
|
+
v = v ^ flag
|
|
2385
|
+
while ents[i] != v:
|
|
2386
|
+
i += 1
|
|
2387
|
+
v = v ^ flag
|
|
2388
|
+
else:
|
|
2389
|
+
ents = self.col_ents
|
|
2390
|
+
lvls = self.col_lvls
|
|
2391
|
+
while ents[i] != v:
|
|
2392
|
+
i += 1
|
|
2393
|
+
j = i
|
|
2394
|
+
while lvls[i] > k:
|
|
2395
|
+
i += 1
|
|
2396
|
+
if j == 0 or lvls[j-1] <= k:
|
|
2397
|
+
if v & self.flag:
|
|
2398
|
+
self.wd_percolate(j+1, i)
|
|
2399
|
+
else:
|
|
2400
|
+
self.col_percolate(j+1, i)
|
|
2401
|
+
else:
|
|
2402
|
+
while j != 0 and lvls[j-1] > k:
|
|
2403
|
+
ents[j] = ents[j-1]
|
|
2404
|
+
j -= 1
|
|
2405
|
+
if v & flag:
|
|
2406
|
+
ents[j] = v ^ flag
|
|
2407
|
+
else:
|
|
2408
|
+
ents[j] = v
|
|
2409
|
+
lvls[j] = k
|
|
2410
|
+
if v & flag:
|
|
2411
|
+
return j ^ flag
|
|
2412
|
+
else:
|
|
2413
|
+
return j
|
|
2414
|
+
|
|
2415
|
+
def _col_degree(self, C, col, wd_ptr, k):
|
|
2416
|
+
"""
|
|
2417
|
+
Return the number of words in the cell specified by wd_ptr that have a
|
|
2418
|
+
1 in the col-th column.
|
|
2419
|
+
|
|
2420
|
+
EXAMPLES::
|
|
2421
|
+
|
|
2422
|
+
sage: import sage.coding.binary_code
|
|
2423
|
+
sage: from sage.coding.binary_code import *
|
|
2424
|
+
sage: P = PartitionStack(2, 6)
|
|
2425
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0],[0,0,1,1,1,1]])
|
|
2426
|
+
sage: B = BinaryCode(M)
|
|
2427
|
+
sage: B
|
|
2428
|
+
Binary [6,2] linear code, generator matrix
|
|
2429
|
+
[111100]
|
|
2430
|
+
[001111]
|
|
2431
|
+
sage: [P._split_vertex(i,i+1) for i in range(5)]
|
|
2432
|
+
[0, 1, 2, 3, 4]
|
|
2433
|
+
sage: P
|
|
2434
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
2435
|
+
({0,1,2,3}) ({0},{1,2,3,4,5})
|
|
2436
|
+
({0,1,2,3}) ({0},{1},{2,3,4,5})
|
|
2437
|
+
({0,1,2,3}) ({0},{1},{2},{3,4,5})
|
|
2438
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4,5})
|
|
2439
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
|
|
2440
|
+
sage: P._col_degree(B, 2, 0, 2)
|
|
2441
|
+
2
|
|
2442
|
+
"""
|
|
2443
|
+
return self.col_degree(C, col, wd_ptr, k)
|
|
2444
|
+
|
|
2445
|
+
cdef int col_degree(self, BinaryCode CG, int col, int wd_ptr, int k) noexcept:
|
|
2446
|
+
cdef int i = 0
|
|
2447
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
2448
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
2449
|
+
while True:
|
|
2450
|
+
if CG.is_one(self_wd_ents[wd_ptr], col):
|
|
2451
|
+
i += 1
|
|
2452
|
+
if self_wd_lvls[wd_ptr] > k:
|
|
2453
|
+
wd_ptr += 1
|
|
2454
|
+
else:
|
|
2455
|
+
break
|
|
2456
|
+
return i
|
|
2457
|
+
|
|
2458
|
+
def _wd_degree(self, C, wd, col_ptr, k):
|
|
2459
|
+
"""
|
|
2460
|
+
Return the number of columns in the cell specified by col_ptr that are
|
|
2461
|
+
1 in wd.
|
|
2462
|
+
|
|
2463
|
+
EXAMPLES::
|
|
2464
|
+
|
|
2465
|
+
sage: import sage.coding.binary_code
|
|
2466
|
+
sage: from sage.coding.binary_code import *
|
|
2467
|
+
sage: P = PartitionStack(2, 6)
|
|
2468
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0],[0,0,1,1,1,1]])
|
|
2469
|
+
sage: B = BinaryCode(M)
|
|
2470
|
+
sage: B
|
|
2471
|
+
Binary [6,2] linear code, generator matrix
|
|
2472
|
+
[111100]
|
|
2473
|
+
[001111]
|
|
2474
|
+
sage: [P._split_vertex(i,i+1) for i in range(5)]
|
|
2475
|
+
[0, 1, 2, 3, 4]
|
|
2476
|
+
sage: P
|
|
2477
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
2478
|
+
({0,1,2,3}) ({0},{1,2,3,4,5})
|
|
2479
|
+
({0,1,2,3}) ({0},{1},{2,3,4,5})
|
|
2480
|
+
({0,1,2,3}) ({0},{1},{2},{3,4,5})
|
|
2481
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4,5})
|
|
2482
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
|
|
2483
|
+
sage: P._wd_degree(B, 1, 1, 1)
|
|
2484
|
+
3
|
|
2485
|
+
"""
|
|
2486
|
+
cdef int *ham_wts = hamming_weights()
|
|
2487
|
+
result = self.wd_degree(C, wd, col_ptr, k, ham_wts)
|
|
2488
|
+
sig_free(ham_wts)
|
|
2489
|
+
return result
|
|
2490
|
+
|
|
2491
|
+
cdef int wd_degree(self, BinaryCode CG, int wd, int col_ptr, int k, int *ham_wts) noexcept:
|
|
2492
|
+
|
|
2493
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
2494
|
+
cdef int *self_col_ents = self.col_ents
|
|
2495
|
+
cdef int mask = (1 << self_col_ents[col_ptr])
|
|
2496
|
+
while self_col_lvls[col_ptr] > k:
|
|
2497
|
+
col_ptr += 1
|
|
2498
|
+
mask += (1 << self_col_ents[col_ptr])
|
|
2499
|
+
mask &= CG.words[wd]
|
|
2500
|
+
return ham_wts[mask & 65535] + ham_wts[(mask >> 16) & 65535]
|
|
2501
|
+
|
|
2502
|
+
def _sort_cols(self, start, degrees, k):
|
|
2503
|
+
"""
|
|
2504
|
+
Essentially a counting sort, but on only one cell of the partition.
|
|
2505
|
+
|
|
2506
|
+
INPUT:
|
|
2507
|
+
|
|
2508
|
+
- ``start`` -- location of the beginning of the cell
|
|
2509
|
+
- ``k`` -- at what level of refinement the partition of interest lies
|
|
2510
|
+
- ``degrees`` -- the counts to sort by
|
|
2511
|
+
|
|
2512
|
+
EXAMPLES::
|
|
2513
|
+
|
|
2514
|
+
sage: import sage.coding.binary_code
|
|
2515
|
+
sage: from sage.coding.binary_code import *
|
|
2516
|
+
sage: P = PartitionStack(2, 6)
|
|
2517
|
+
sage: [P._split_vertex(i,i+1) for i in range(5)]
|
|
2518
|
+
[0, 1, 2, 3, 4]
|
|
2519
|
+
sage: P._sort_cols(1, [0,2,2,1,1], 1)
|
|
2520
|
+
2
|
|
2521
|
+
sage: P
|
|
2522
|
+
({0,1,2,3}) ({0,1,4,5,2,3})
|
|
2523
|
+
({0,1,2,3}) ({0},{1},{4,5},{2,3})
|
|
2524
|
+
"""
|
|
2525
|
+
cdef int i
|
|
2526
|
+
for i from 0 <= i < len(degrees):
|
|
2527
|
+
self.col_degs[i] = degrees[i]
|
|
2528
|
+
return self.sort_cols(start, k)
|
|
2529
|
+
|
|
2530
|
+
cdef int sort_cols(self, int start, int k) noexcept:
|
|
2531
|
+
cdef int i, j, max, max_location
|
|
2532
|
+
cdef int self_nwords = self.nwords, ii
|
|
2533
|
+
cdef int *self_col_counts = self.col_counts
|
|
2534
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
2535
|
+
cdef int *self_col_degs = self.col_degs
|
|
2536
|
+
cdef int *self_col_ents = self.col_ents
|
|
2537
|
+
cdef int *self_col_output = self.col_output
|
|
2538
|
+
for ii from 0 <= ii < self_nwords:
|
|
2539
|
+
self_col_counts[ii] = 0
|
|
2540
|
+
i = 0
|
|
2541
|
+
while self_col_lvls[i+start] > k:
|
|
2542
|
+
self_col_counts[self_col_degs[i]] += 1
|
|
2543
|
+
i += 1
|
|
2544
|
+
self_col_counts[self_col_degs[i]] += 1
|
|
2545
|
+
|
|
2546
|
+
# i+start is the right endpoint of the cell now
|
|
2547
|
+
max = self_col_counts[0]
|
|
2548
|
+
max_location = 0
|
|
2549
|
+
for ii from 0 < ii < self_nwords:
|
|
2550
|
+
if self_col_counts[ii] > max:
|
|
2551
|
+
max = self_col_counts[ii]
|
|
2552
|
+
max_location = ii
|
|
2553
|
+
self_col_counts[ii] += self_col_counts[ii-1]
|
|
2554
|
+
|
|
2555
|
+
for j from i >= j >= 0:
|
|
2556
|
+
self_col_counts[self_col_degs[j]] -= 1
|
|
2557
|
+
self_col_output[self_col_counts[self_col_degs[j]]] = self_col_ents[start+j]
|
|
2558
|
+
|
|
2559
|
+
max_location = self_col_counts[max_location] + start
|
|
2560
|
+
|
|
2561
|
+
for j from 0 <= j <= i:
|
|
2562
|
+
self_col_ents[start+j] = self_col_output[j]
|
|
2563
|
+
|
|
2564
|
+
ii = 1
|
|
2565
|
+
while ii < self_nwords and self_col_counts[ii] <= i:
|
|
2566
|
+
if self_col_counts[ii] > 0:
|
|
2567
|
+
self_col_lvls[start + self_col_counts[ii] - 1] = k
|
|
2568
|
+
self.col_percolate(start + self_col_counts[ii-1], start + self_col_counts[ii] - 1)
|
|
2569
|
+
ii += 1
|
|
2570
|
+
|
|
2571
|
+
return max_location
|
|
2572
|
+
|
|
2573
|
+
def _sort_wds(self, start, degrees, k):
|
|
2574
|
+
"""
|
|
2575
|
+
Essentially a counting sort, but on only one cell of the partition.
|
|
2576
|
+
|
|
2577
|
+
INPUT:
|
|
2578
|
+
|
|
2579
|
+
- ``start`` -- location of the beginning of the cell
|
|
2580
|
+
- ``k`` -- at what level of refinement the partition of interest lies
|
|
2581
|
+
- ``degrees`` -- the counts to sort by
|
|
2582
|
+
|
|
2583
|
+
EXAMPLES::
|
|
2584
|
+
|
|
2585
|
+
sage: import sage.coding.binary_code
|
|
2586
|
+
sage: from sage.coding.binary_code import *
|
|
2587
|
+
sage: P = PartitionStack(3, 6)
|
|
2588
|
+
sage: P._sort_wds(0, [0,0,3,3,3,3,2,2], 1)
|
|
2589
|
+
4
|
|
2590
|
+
sage: P
|
|
2591
|
+
({0,1,6,7,2,3,4,5}) ({0,1,2,3,4,5})
|
|
2592
|
+
({0,1},{6,7},{2,3,4,5}) ({0,1,2,3,4,5})
|
|
2593
|
+
"""
|
|
2594
|
+
cdef int i
|
|
2595
|
+
for i from 0 <= i < len(degrees):
|
|
2596
|
+
self.wd_degs[i] = degrees[i]
|
|
2597
|
+
return self.sort_wds(start, k)
|
|
2598
|
+
|
|
2599
|
+
cdef int sort_wds(self, int start, int k) noexcept:
|
|
2600
|
+
cdef int i, j, max, max_location
|
|
2601
|
+
cdef int ii, self_ncols = self.ncols
|
|
2602
|
+
cdef int *self_wd_counts = self.wd_counts
|
|
2603
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
2604
|
+
cdef int *self_wd_degs = self.wd_degs
|
|
2605
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
2606
|
+
cdef int *self_wd_output = self.wd_output
|
|
2607
|
+
|
|
2608
|
+
for ii in range(self_ncols + 1):
|
|
2609
|
+
self_wd_counts[ii] = 0
|
|
2610
|
+
i = 0
|
|
2611
|
+
while self_wd_lvls[i+start] > k:
|
|
2612
|
+
self_wd_counts[self_wd_degs[i]] += 1
|
|
2613
|
+
i += 1
|
|
2614
|
+
self_wd_counts[self_wd_degs[i]] += 1
|
|
2615
|
+
|
|
2616
|
+
# i+start is the right endpoint of the cell now
|
|
2617
|
+
max = self_wd_counts[0]
|
|
2618
|
+
max_location = 0
|
|
2619
|
+
for ii from 0 < ii < self_ncols+1:
|
|
2620
|
+
if self_wd_counts[ii] > max:
|
|
2621
|
+
max = self_wd_counts[ii]
|
|
2622
|
+
max_location = ii
|
|
2623
|
+
self_wd_counts[ii] += self_wd_counts[ii-1]
|
|
2624
|
+
|
|
2625
|
+
for j from i >= j >= 0:
|
|
2626
|
+
if j > i:
|
|
2627
|
+
break # cython bug with ints...
|
|
2628
|
+
self_wd_counts[self_wd_degs[j]] -= 1
|
|
2629
|
+
self_wd_output[self_wd_counts[self_wd_degs[j]]] = self_wd_ents[start+j]
|
|
2630
|
+
|
|
2631
|
+
max_location = self_wd_counts[max_location] + start
|
|
2632
|
+
|
|
2633
|
+
for j from 0 <= j <= i:
|
|
2634
|
+
self_wd_ents[start+j] = self_wd_output[j]
|
|
2635
|
+
|
|
2636
|
+
ii = 1
|
|
2637
|
+
while ii < self_ncols+1 and self_wd_counts[ii] <= i:
|
|
2638
|
+
if self_wd_counts[ii] > 0:
|
|
2639
|
+
self_wd_lvls[start + self_wd_counts[ii] - 1] = k
|
|
2640
|
+
self.wd_percolate(start + self_wd_counts[ii-1], start + self_wd_counts[ii] - 1)
|
|
2641
|
+
ii += 1
|
|
2642
|
+
|
|
2643
|
+
return max_location
|
|
2644
|
+
|
|
2645
|
+
def _refine(self, k, alpha, CG):
|
|
2646
|
+
"""
|
|
2647
|
+
EXAMPLES::
|
|
2648
|
+
|
|
2649
|
+
sage: import sage.coding.binary_code
|
|
2650
|
+
sage: from sage.coding.binary_code import *
|
|
2651
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
|
|
2652
|
+
sage: B = BinaryCode(M)
|
|
2653
|
+
sage: P = PartitionStack(4, 8)
|
|
2654
|
+
sage: P._refine(1, [[0,0],[1,0]], B)
|
|
2655
|
+
181
|
|
2656
|
+
sage: P._split_vertex(0, 2)
|
|
2657
|
+
0
|
|
2658
|
+
sage: P._refine(2, [[0,0]], B)
|
|
2659
|
+
290
|
|
2660
|
+
sage: P._split_vertex(1, 3)
|
|
2661
|
+
1
|
|
2662
|
+
sage: P._refine(3, [[0,1]], B)
|
|
2663
|
+
463
|
|
2664
|
+
sage: P._split_vertex(2, 4)
|
|
2665
|
+
2
|
|
2666
|
+
sage: P._refine(4, [[0,2]], B)
|
|
2667
|
+
1500
|
|
2668
|
+
sage: P._split_vertex(3, 5)
|
|
2669
|
+
3
|
|
2670
|
+
sage: P._refine(5, [[0,3]], B)
|
|
2671
|
+
641
|
|
2672
|
+
sage: P._split_vertex(4, 6)
|
|
2673
|
+
4
|
|
2674
|
+
sage: P._refine(6, [[0,4]], B)
|
|
2675
|
+
1224
|
|
2676
|
+
sage: P._is_discrete(5)
|
|
2677
|
+
0
|
|
2678
|
+
sage: P._is_discrete(6)
|
|
2679
|
+
1
|
|
2680
|
+
sage: P
|
|
2681
|
+
({0,4,6,2,13,9,11,15,10,14,12,8,7,3,1,5}) ({0,1,2,3,4,7,6,5})
|
|
2682
|
+
({0},{4,6,2,13,9,11,15,10,14,12,8,7,3,1},{5}) ({0,1,2,3,4,7,6,5})
|
|
2683
|
+
({0},{4,6,2,13,9,11,15},{10,14,12,8,7,3,1},{5}) ({0},{1,2,3,4,7,6,5})
|
|
2684
|
+
({0},{4,6,2},{13,9,11,15},{10,14,12,8},{7,3,1},{5}) ({0},{1},{2,3,4,7,6,5})
|
|
2685
|
+
({0},{4},{6,2},{13,9},{11,15},{10,14},{12,8},{7,3},{1},{5}) ({0},{1},{2},{3,4,7,6,5})
|
|
2686
|
+
({0},{4},{6,2},{13,9},{11,15},{10,14},{12,8},{7,3},{1},{5}) ({0},{1},{2},{3},{4,7,6,5})
|
|
2687
|
+
({0},{4},{6},{2},{13},{9},{11},{15},{10},{14},{12},{8},{7},{3},{1},{5}) ({0},{1},{2},{3},{4},{7},{6},{5})
|
|
2688
|
+
"""
|
|
2689
|
+
cdef int i, alpha_length = len(alpha)
|
|
2690
|
+
cdef int *_alpha = <int *> sig_malloc((self.nwords + self.ncols) * sizeof(int))
|
|
2691
|
+
cdef int *ham_wts = hamming_weights()
|
|
2692
|
+
if _alpha is NULL:
|
|
2693
|
+
raise MemoryError("Memory.")
|
|
2694
|
+
for i from 0 <= i < alpha_length:
|
|
2695
|
+
if alpha[i][0]:
|
|
2696
|
+
_alpha[i] = alpha[i][1] ^ self.flag
|
|
2697
|
+
else:
|
|
2698
|
+
_alpha[i] = alpha[i][1]
|
|
2699
|
+
result = self.refine(k, _alpha, alpha_length, CG, ham_wts)
|
|
2700
|
+
sig_free(_alpha)
|
|
2701
|
+
sig_free(ham_wts)
|
|
2702
|
+
return result
|
|
2703
|
+
|
|
2704
|
+
cdef int refine(self, int k, int *alpha, int alpha_length, BinaryCode CG, int *ham_wts) noexcept:
|
|
2705
|
+
cdef int q, r, s, t, flag = self.flag, self_ncols = self.ncols
|
|
2706
|
+
cdef int t_w, invariant = 0, i, j, m = 0
|
|
2707
|
+
cdef int *self_wd_degs = self.wd_degs
|
|
2708
|
+
cdef int *self_wd_lvls = self.wd_lvls
|
|
2709
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
2710
|
+
cdef int *self_col_degs = self.col_degs
|
|
2711
|
+
cdef int *self_col_lvls = self.col_lvls
|
|
2712
|
+
cdef int *self_col_ents = self.col_ents
|
|
2713
|
+
while not self.is_discrete(k) and m < alpha_length:
|
|
2714
|
+
invariant += 1
|
|
2715
|
+
j = 0
|
|
2716
|
+
if alpha[m] & flag:
|
|
2717
|
+
while j < self_ncols:
|
|
2718
|
+
i = j
|
|
2719
|
+
s = 0
|
|
2720
|
+
invariant += 8
|
|
2721
|
+
while True:
|
|
2722
|
+
self_col_degs[i-j] = self.col_degree(CG, self_col_ents[i], alpha[m]^flag, k)
|
|
2723
|
+
if s == 0 and self_col_degs[i-j] != self_col_degs[0]:
|
|
2724
|
+
s = 1
|
|
2725
|
+
i += 1
|
|
2726
|
+
if self_col_lvls[i-1] <= k:
|
|
2727
|
+
break
|
|
2728
|
+
if s:
|
|
2729
|
+
invariant += 8
|
|
2730
|
+
t = self.sort_cols(j, k)
|
|
2731
|
+
invariant += t
|
|
2732
|
+
q = m
|
|
2733
|
+
while q < alpha_length:
|
|
2734
|
+
if alpha[q] == j:
|
|
2735
|
+
alpha[q] = t
|
|
2736
|
+
break
|
|
2737
|
+
q += 1
|
|
2738
|
+
r = j
|
|
2739
|
+
while True:
|
|
2740
|
+
if r == j or self.col_lvls[r-1] == k:
|
|
2741
|
+
if r != t:
|
|
2742
|
+
alpha[alpha_length] = r
|
|
2743
|
+
alpha_length += 1
|
|
2744
|
+
r += 1
|
|
2745
|
+
if r >= i:
|
|
2746
|
+
break
|
|
2747
|
+
invariant += self.col_degree(CG, self_col_ents[i-1], alpha[m]^flag, k)
|
|
2748
|
+
invariant += (i-j)
|
|
2749
|
+
j = i
|
|
2750
|
+
else:
|
|
2751
|
+
while j < self.nwords:
|
|
2752
|
+
i = j
|
|
2753
|
+
s = 0
|
|
2754
|
+
invariant += 64
|
|
2755
|
+
while True:
|
|
2756
|
+
self_wd_degs[i-j] = self.wd_degree(CG, self_wd_ents[i], alpha[m], k, ham_wts)
|
|
2757
|
+
if s == 0 and self_wd_degs[i-j] != self_wd_degs[0]:
|
|
2758
|
+
s = 1
|
|
2759
|
+
i += 1
|
|
2760
|
+
if self_wd_lvls[i-1] <= k:
|
|
2761
|
+
break
|
|
2762
|
+
if s:
|
|
2763
|
+
invariant += 64
|
|
2764
|
+
t_w = self.sort_wds(j, k)
|
|
2765
|
+
invariant += t_w
|
|
2766
|
+
q = m
|
|
2767
|
+
j ^= flag
|
|
2768
|
+
while q < alpha_length:
|
|
2769
|
+
if alpha[q] == j:
|
|
2770
|
+
alpha[q] = t_w ^ flag
|
|
2771
|
+
break
|
|
2772
|
+
q += 1
|
|
2773
|
+
j ^= flag
|
|
2774
|
+
r = j
|
|
2775
|
+
while True:
|
|
2776
|
+
if r == j or self.wd_lvls[r-1] == k:
|
|
2777
|
+
if r != t_w:
|
|
2778
|
+
alpha[alpha_length] = r^flag
|
|
2779
|
+
alpha_length += 1
|
|
2780
|
+
r += 1
|
|
2781
|
+
if r >= i:
|
|
2782
|
+
break
|
|
2783
|
+
invariant += self.wd_degree(CG, self_wd_ents[i-1], alpha[m], k, ham_wts)
|
|
2784
|
+
invariant += (i-j)
|
|
2785
|
+
j = i
|
|
2786
|
+
m += 1
|
|
2787
|
+
return invariant
|
|
2788
|
+
|
|
2789
|
+
def _clear(self, k):
|
|
2790
|
+
"""
|
|
2791
|
+
EXAMPLES::
|
|
2792
|
+
|
|
2793
|
+
sage: import sage.coding.binary_code
|
|
2794
|
+
sage: from sage.coding.binary_code import *
|
|
2795
|
+
sage: P = PartitionStack(2, 6)
|
|
2796
|
+
sage: [P._split_vertex(i,i+1) for i in range(5)]
|
|
2797
|
+
[0, 1, 2, 3, 4]
|
|
2798
|
+
sage: P
|
|
2799
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
2800
|
+
({0,1,2,3}) ({0},{1,2,3,4,5})
|
|
2801
|
+
({0,1,2,3}) ({0},{1},{2,3,4,5})
|
|
2802
|
+
({0,1,2,3}) ({0},{1},{2},{3,4,5})
|
|
2803
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4,5})
|
|
2804
|
+
({0,1,2,3}) ({0},{1},{2},{3},{4},{5})
|
|
2805
|
+
sage: P._clear(2)
|
|
2806
|
+
sage: P
|
|
2807
|
+
({0,1,2,3}) ({0,1,2,3,4,5})
|
|
2808
|
+
({0,1,2,3}) ({0},{1,2,3,4,5})
|
|
2809
|
+
"""
|
|
2810
|
+
self.clear(k)
|
|
2811
|
+
|
|
2812
|
+
cdef void clear(self, int k) noexcept:
|
|
2813
|
+
cdef int i, j = 0, nwords = self.nwords, ncols = self.ncols
|
|
2814
|
+
cdef int *wd_lvls = self.wd_lvls
|
|
2815
|
+
cdef int *col_lvls = self.col_lvls
|
|
2816
|
+
for i from 0 <= i < nwords:
|
|
2817
|
+
if wd_lvls[i] >= k:
|
|
2818
|
+
wd_lvls[i] += 1
|
|
2819
|
+
if wd_lvls[i] < k:
|
|
2820
|
+
self.wd_percolate(j, i)
|
|
2821
|
+
j = i + 1
|
|
2822
|
+
j = 0
|
|
2823
|
+
for i from 0 <= i < ncols:
|
|
2824
|
+
if col_lvls[i] >= k:
|
|
2825
|
+
col_lvls[i] += 1
|
|
2826
|
+
if col_lvls[i] < k:
|
|
2827
|
+
self.col_percolate(j, i)
|
|
2828
|
+
j = i + 1
|
|
2829
|
+
|
|
2830
|
+
cpdef int cmp(self, PartitionStack other, BinaryCode CG) noexcept:
|
|
2831
|
+
"""
|
|
2832
|
+
EXAMPLES::
|
|
2833
|
+
|
|
2834
|
+
sage: import sage.coding.binary_code
|
|
2835
|
+
sage: from sage.coding.binary_code import *
|
|
2836
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0], [0,0,1,1,1,1,0,0],
|
|
2837
|
+
....: [0,0,0,0,1,1,1,1], [1,0,1,0,1,0,1,0]])
|
|
2838
|
+
sage: B = BinaryCode(M)
|
|
2839
|
+
sage: P = PartitionStack(4, 8)
|
|
2840
|
+
sage: P._refine(0, [[0,0],[1,0]], B)
|
|
2841
|
+
181
|
|
2842
|
+
sage: P._split_vertex(0, 1)
|
|
2843
|
+
0
|
|
2844
|
+
sage: P._refine(1, [[0,0]], B)
|
|
2845
|
+
290
|
|
2846
|
+
sage: P._split_vertex(1, 2)
|
|
2847
|
+
1
|
|
2848
|
+
sage: P._refine(2, [[0,1]], B)
|
|
2849
|
+
463
|
|
2850
|
+
sage: P._split_vertex(2, 3)
|
|
2851
|
+
2
|
|
2852
|
+
sage: P._refine(3, [[0,2]], B)
|
|
2853
|
+
1500
|
|
2854
|
+
sage: P._split_vertex(4, 4)
|
|
2855
|
+
4
|
|
2856
|
+
sage: P._refine(4, [[0,4]], B)
|
|
2857
|
+
1224
|
|
2858
|
+
sage: P._is_discrete(4)
|
|
2859
|
+
1
|
|
2860
|
+
sage: Q = PartitionStack(P)
|
|
2861
|
+
sage: Q._clear(4)
|
|
2862
|
+
sage: Q._split_vertex(5, 4)
|
|
2863
|
+
4
|
|
2864
|
+
sage: Q._refine(4, [[0,4]], B)
|
|
2865
|
+
1224
|
|
2866
|
+
sage: Q._is_discrete(4)
|
|
2867
|
+
1
|
|
2868
|
+
sage: Q.cmp(P, B)
|
|
2869
|
+
0
|
|
2870
|
+
"""
|
|
2871
|
+
cdef int i, j, l, m, ncols = self.ncols, nwords = self.nwords
|
|
2872
|
+
for i in range(1, nwords):
|
|
2873
|
+
for j in range(ncols):
|
|
2874
|
+
l = CG.is_one(self.wd_ents[i], self.col_ents[j])
|
|
2875
|
+
m = CG.is_one(other.wd_ents[i], other.col_ents[j])
|
|
2876
|
+
if l != m:
|
|
2877
|
+
return l - m
|
|
2878
|
+
return 0
|
|
2879
|
+
|
|
2880
|
+
def print_basis(self):
|
|
2881
|
+
"""
|
|
2882
|
+
EXAMPLES::
|
|
2883
|
+
|
|
2884
|
+
sage: import sage.coding.binary_code
|
|
2885
|
+
sage: from sage.coding.binary_code import *
|
|
2886
|
+
sage: P = PartitionStack(4, 8)
|
|
2887
|
+
sage: P._dangerous_dont_use_set_ents_lvls(
|
|
2888
|
+
....: list(range(8)),
|
|
2889
|
+
....: list(range(7)) + [-1],
|
|
2890
|
+
....: [4,7,12,11,1,9,3,0,2,5,6,8,10,13,14,15],
|
|
2891
|
+
....: [0]*16)
|
|
2892
|
+
sage: P
|
|
2893
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1,2,3,4,5,6,7})
|
|
2894
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2,3,4,5,6,7})
|
|
2895
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3,4,5,6,7})
|
|
2896
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4,5,6,7})
|
|
2897
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5,6,7})
|
|
2898
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5},{6,7})
|
|
2899
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5},{6},{7})
|
|
2900
|
+
sage: P._find_basis()
|
|
2901
|
+
sage: P.print_basis()
|
|
2902
|
+
basis_locations:
|
|
2903
|
+
4
|
|
2904
|
+
8
|
|
2905
|
+
0
|
|
2906
|
+
11
|
|
2907
|
+
"""
|
|
2908
|
+
cdef int i, j
|
|
2909
|
+
if self.basis_locations:
|
|
2910
|
+
print("basis_locations:")
|
|
2911
|
+
j = 1
|
|
2912
|
+
while (1 << j) < self.nwords:
|
|
2913
|
+
j += 1
|
|
2914
|
+
for i from 0 <= i < j:
|
|
2915
|
+
print(self.basis_locations[i])
|
|
2916
|
+
|
|
2917
|
+
def _find_basis(self):
|
|
2918
|
+
"""
|
|
2919
|
+
EXAMPLES::
|
|
2920
|
+
|
|
2921
|
+
sage: import sage.coding.binary_code
|
|
2922
|
+
sage: from sage.coding.binary_code import *
|
|
2923
|
+
sage: P = PartitionStack(4, 8)
|
|
2924
|
+
sage: P._dangerous_dont_use_set_ents_lvls(list(range(8)), list(range(7))+[-1], [4,7,12,11,1,9,3,0,2,5,6,8,10,13,14,15], [0]*16)
|
|
2925
|
+
sage: P
|
|
2926
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1,2,3,4,5,6,7})
|
|
2927
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2,3,4,5,6,7})
|
|
2928
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3,4,5,6,7})
|
|
2929
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4,5,6,7})
|
|
2930
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5,6,7})
|
|
2931
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5},{6,7})
|
|
2932
|
+
({4},{7},{12},{11},{1},{9},{3},{0},{2},{5},{6},{8},{10},{13},{14},{15}) ({0},{1},{2},{3},{4},{5},{6},{7})
|
|
2933
|
+
sage: P._find_basis()
|
|
2934
|
+
sage: P.print_basis()
|
|
2935
|
+
basis_locations:
|
|
2936
|
+
4
|
|
2937
|
+
8
|
|
2938
|
+
0
|
|
2939
|
+
11
|
|
2940
|
+
"""
|
|
2941
|
+
cdef int *ham_wts = hamming_weights()
|
|
2942
|
+
self.find_basis(ham_wts)
|
|
2943
|
+
sig_free(ham_wts)
|
|
2944
|
+
|
|
2945
|
+
cdef int find_basis(self, int *ham_wts) noexcept:
|
|
2946
|
+
cdef int i = 0, j, k, nwords = self.nwords, weight, basis_elts = 0, nrows = self.nrows
|
|
2947
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
2948
|
+
if self.basis_locations is NULL:
|
|
2949
|
+
self.basis_locations = <int *> sig_malloc(2 * nrows * sizeof(int))
|
|
2950
|
+
if self.basis_locations is NULL:
|
|
2951
|
+
raise MemoryError("Memory.")
|
|
2952
|
+
while i < nwords:
|
|
2953
|
+
j = self_wd_ents[i]
|
|
2954
|
+
weight = ham_wts[j & 65535] + ham_wts[(j>>16) & 65535]
|
|
2955
|
+
if weight == 1:
|
|
2956
|
+
basis_elts += 1
|
|
2957
|
+
k = 0
|
|
2958
|
+
while not (1<<k) & j:
|
|
2959
|
+
k += 1
|
|
2960
|
+
self.basis_locations[k] = i
|
|
2961
|
+
if basis_elts == nrows:
|
|
2962
|
+
break
|
|
2963
|
+
i += 1
|
|
2964
|
+
for i from 0 <= i < nrows:
|
|
2965
|
+
self.basis_locations[nrows + i] = self_wd_ents[1 << i]
|
|
2966
|
+
|
|
2967
|
+
def _get_permutation(self, other):
|
|
2968
|
+
"""
|
|
2969
|
+
EXAMPLES::
|
|
2970
|
+
|
|
2971
|
+
sage: import sage.coding.binary_code
|
|
2972
|
+
sage: from sage.coding.binary_code import *
|
|
2973
|
+
sage: M = Matrix(GF(2), [[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1],[1,0,1,0,1,0,1,0]])
|
|
2974
|
+
sage: B = BinaryCode(M)
|
|
2975
|
+
sage: P = PartitionStack(4, 8)
|
|
2976
|
+
sage: P._refine(0, [[0,0],[1,0]], B)
|
|
2977
|
+
181
|
|
2978
|
+
sage: P._split_vertex(0, 1)
|
|
2979
|
+
0
|
|
2980
|
+
sage: P._refine(1, [[0,0]], B)
|
|
2981
|
+
290
|
|
2982
|
+
sage: P._split_vertex(1, 2)
|
|
2983
|
+
1
|
|
2984
|
+
sage: P._refine(2, [[0,1]], B)
|
|
2985
|
+
463
|
|
2986
|
+
sage: P._split_vertex(2, 3)
|
|
2987
|
+
2
|
|
2988
|
+
sage: P._refine(3, [[0,2]], B)
|
|
2989
|
+
1500
|
|
2990
|
+
sage: P._split_vertex(4, 4)
|
|
2991
|
+
4
|
|
2992
|
+
sage: P._refine(4, [[0,4]], B)
|
|
2993
|
+
1224
|
|
2994
|
+
sage: P._is_discrete(4)
|
|
2995
|
+
1
|
|
2996
|
+
sage: Q = PartitionStack(P)
|
|
2997
|
+
sage: Q._clear(4)
|
|
2998
|
+
sage: Q._split_vertex(5, 4)
|
|
2999
|
+
4
|
|
3000
|
+
sage: Q._refine(4, [[0,4]], B)
|
|
3001
|
+
1224
|
|
3002
|
+
sage: Q._is_discrete(4)
|
|
3003
|
+
1
|
|
3004
|
+
sage: P._get_permutation(Q)
|
|
3005
|
+
([0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 8, 9, 10, 11], [0, 1, 2, 3, 5, 4, 7, 6])
|
|
3006
|
+
"""
|
|
3007
|
+
cdef int i
|
|
3008
|
+
cdef MemoryAllocator loc_mem = MemoryAllocator()
|
|
3009
|
+
cdef int *word_g = <int *> loc_mem.malloc(self.nwords * sizeof(int))
|
|
3010
|
+
cdef int *col_g = <int *> loc_mem.malloc(self.ncols * sizeof(int))
|
|
3011
|
+
self.get_permutation(other, word_g, col_g)
|
|
3012
|
+
word_l = [word_g[i] for i from 0 <= i < self.nwords]
|
|
3013
|
+
col_l = [col_g[i] for i from 0 <= i < self.ncols]
|
|
3014
|
+
return word_l, col_l
|
|
3015
|
+
|
|
3016
|
+
cdef void get_permutation(self, PartitionStack other, int *word_gamma, int *col_gamma) noexcept:
|
|
3017
|
+
cdef int i
|
|
3018
|
+
cdef int *self_wd_ents = self.wd_ents
|
|
3019
|
+
cdef int *other_wd_ents = other.wd_ents
|
|
3020
|
+
cdef int *self_col_ents = self.col_ents
|
|
3021
|
+
cdef int *other_col_ents = other.col_ents
|
|
3022
|
+
# word_gamma[i] := image of the ith row as linear comb of rows
|
|
3023
|
+
for i from 0 <= i < self.nwords:
|
|
3024
|
+
word_gamma[other_wd_ents[i]] = self_wd_ents[i]
|
|
3025
|
+
for i from 0 <= i < self.ncols:
|
|
3026
|
+
col_gamma[other_col_ents[i]] = self_col_ents[i]
|
|
3027
|
+
|
|
3028
|
+
cdef class BinaryCodeClassifier:
|
|
3029
|
+
|
|
3030
|
+
def __cinit__(self):
|
|
3031
|
+
"""
|
|
3032
|
+
Initialize.
|
|
3033
|
+
|
|
3034
|
+
TESTS::
|
|
3035
|
+
|
|
3036
|
+
sage: import sage.coding.binary_code
|
|
3037
|
+
sage: from sage.coding.binary_code import *
|
|
3038
|
+
sage: BC = BinaryCodeClassifier()
|
|
3039
|
+
sage: TestSuite(BC).run(skip='_test_pickling')
|
|
3040
|
+
"""
|
|
3041
|
+
self.radix = sizeof(codeword) << 3
|
|
3042
|
+
self.ham_wts = hamming_weights()
|
|
3043
|
+
self.L = 100 # memory limit for Phi and Omega- multiply by 8KB
|
|
3044
|
+
self.aut_gens_size = self.radix * 100
|
|
3045
|
+
|
|
3046
|
+
self.w_gamma_size = 1 << (self.radix/2)
|
|
3047
|
+
self.alpha_size = self.w_gamma_size + self.radix
|
|
3048
|
+
self.Phi_size = self.w_gamma_size/self.radix + 1
|
|
3049
|
+
|
|
3050
|
+
self.mem = MemoryAllocator()
|
|
3051
|
+
self.w_gamma = <int *> self.mem.malloc(self.w_gamma_size * sizeof(int))
|
|
3052
|
+
self.alpha = <int *> self.mem.malloc(self.alpha_size * sizeof(int))
|
|
3053
|
+
self.Phi = <unsigned int *> self.mem.malloc(self.Phi_size * (self.L+1) * sizeof(unsigned int))
|
|
3054
|
+
self.Omega = <unsigned int *> self.mem.malloc(self.Phi_size * self.L * sizeof(unsigned int))
|
|
3055
|
+
self.W = <unsigned int *> self.mem.malloc(self.Phi_size * self.radix * 2 * sizeof(unsigned int))
|
|
3056
|
+
|
|
3057
|
+
self.base = <int *> self.mem.malloc(self.radix * sizeof(int))
|
|
3058
|
+
self.aut_gp_gens = <int *> self.mem.malloc(self.aut_gens_size * sizeof(int))
|
|
3059
|
+
self.c_gamma = <int *> self.mem.malloc(self.radix * sizeof(int))
|
|
3060
|
+
self.labeling = <int *> self.mem.malloc(self.radix * 3 * sizeof(int))
|
|
3061
|
+
self.Lambda1 = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
|
|
3062
|
+
self.Lambda2 = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
|
|
3063
|
+
self.Lambda3 = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
|
|
3064
|
+
self.v = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
|
|
3065
|
+
self.e = <int *> self.mem.malloc(self.radix * 2 * sizeof(int))
|
|
3066
|
+
|
|
3067
|
+
cdef void record_automorphism(self, int *gamma, int ncols) noexcept:
|
|
3068
|
+
cdef int i, j
|
|
3069
|
+
if self.aut_gp_index + ncols > self.aut_gens_size:
|
|
3070
|
+
self.aut_gens_size *= 2
|
|
3071
|
+
self.aut_gp_gens = <int *> self.mem.realloc(self.aut_gp_gens, self.aut_gens_size * sizeof(int))
|
|
3072
|
+
j = self.aut_gp_index
|
|
3073
|
+
for i from 0 <= i < ncols:
|
|
3074
|
+
self.aut_gp_gens[i+j] = gamma[i]
|
|
3075
|
+
self.aut_gp_index += ncols
|
|
3076
|
+
|
|
3077
|
+
def _aut_gp_and_can_label(self, CC, verbosity=0):
|
|
3078
|
+
"""
|
|
3079
|
+
Compute the automorphism group and canonical label of the code ``CC``.
|
|
3080
|
+
|
|
3081
|
+
INPUT:
|
|
3082
|
+
|
|
3083
|
+
- ``CC`` -- a BinaryCode object
|
|
3084
|
+
- ``verbosity`` -- nonnegative integer
|
|
3085
|
+
|
|
3086
|
+
OUTPUT:
|
|
3087
|
+
|
|
3088
|
+
a tuple, (gens, labeling, size, base)
|
|
3089
|
+
- gens; list of permutations (in list form) representing generators
|
|
3090
|
+
of the permutation automorphism group of the code CC
|
|
3091
|
+
- labeling; a permutation representing the canonical labeling of the
|
|
3092
|
+
code. mostly for internal use; entries describe the relabeling
|
|
3093
|
+
on the columns.
|
|
3094
|
+
- size; the order of the automorphism group
|
|
3095
|
+
- base; a set of cols whose action determines the action on all cols
|
|
3096
|
+
|
|
3097
|
+
EXAMPLES::
|
|
3098
|
+
|
|
3099
|
+
sage: import sage.coding.binary_code
|
|
3100
|
+
sage: from sage.coding.binary_code import *
|
|
3101
|
+
sage: BC = BinaryCodeClassifier()
|
|
3102
|
+
|
|
3103
|
+
sage: M = Matrix(GF(2),[
|
|
3104
|
+
....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0],
|
|
3105
|
+
....: [0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
|
|
3106
|
+
....: [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1],
|
|
3107
|
+
....: [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1],
|
|
3108
|
+
....: [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]])
|
|
3109
|
+
sage: B = BinaryCode(M)
|
|
3110
|
+
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
|
|
3111
|
+
|
|
3112
|
+
sage: # needs sage.groups
|
|
3113
|
+
sage: S = SymmetricGroup(M.ncols())
|
|
3114
|
+
sage: L = [S([x+1 for x in g]) for g in gens]
|
|
3115
|
+
sage: PermutationGroup(L).order()
|
|
3116
|
+
322560
|
|
3117
|
+
sage: size
|
|
3118
|
+
322560
|
|
3119
|
+
|
|
3120
|
+
sage: M = Matrix(GF(2),[
|
|
3121
|
+
....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0],
|
|
3122
|
+
....: [0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0],
|
|
3123
|
+
....: [0,0,0,0,0,1,0,1,0,0,0,1,1,1,1,1,1],
|
|
3124
|
+
....: [0,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1]])
|
|
3125
|
+
sage: B = BinaryCode(M)
|
|
3126
|
+
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
|
|
3127
|
+
|
|
3128
|
+
sage: # needs sage.groups
|
|
3129
|
+
sage: S = SymmetricGroup(M.ncols())
|
|
3130
|
+
sage: L = [S([x+1 for x in g]) for g in gens]
|
|
3131
|
+
sage: PermutationGroup(L).order()
|
|
3132
|
+
2304
|
|
3133
|
+
sage: size
|
|
3134
|
+
2304
|
|
3135
|
+
|
|
3136
|
+
sage: M = Matrix(GF(2),[
|
|
3137
|
+
....: [1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,0],
|
|
3138
|
+
....: [0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0],
|
|
3139
|
+
....: [0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0,0],
|
|
3140
|
+
....: [0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,0],
|
|
3141
|
+
....: [0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0],
|
|
3142
|
+
....: [0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0,0],
|
|
3143
|
+
....: [0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1,0],
|
|
3144
|
+
....: [0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,1]])
|
|
3145
|
+
sage: B = BinaryCode(M)
|
|
3146
|
+
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
|
|
3147
|
+
|
|
3148
|
+
sage: # needs sage.groups
|
|
3149
|
+
sage: S = SymmetricGroup(M.ncols())
|
|
3150
|
+
sage: L = [S([x+1 for x in g]) for g in gens]
|
|
3151
|
+
sage: PermutationGroup(L).order()
|
|
3152
|
+
136
|
|
3153
|
+
sage: size
|
|
3154
|
+
136
|
|
3155
|
+
|
|
3156
|
+
sage: M = Matrix(GF(2),[
|
|
3157
|
+
....: [0,1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1],
|
|
3158
|
+
....: [1,0,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0],
|
|
3159
|
+
....: [0,1,1,1,0,0,0,1,0,0,1,1,0,0,0,1,1,1,0,1,0,0],
|
|
3160
|
+
....: [1,1,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,0,0,1],
|
|
3161
|
+
....: [1,1,0,0,0,1,0,0,1,0,1,0,0,1,1,1,0,1,0,0,1,0],
|
|
3162
|
+
....: [1,0,0,0,1,0,0,1,0,1,1,0,1,1,1,0,1,0,0,1,0,0],
|
|
3163
|
+
....: [0,0,0,1,0,0,1,0,1,1,1,1,1,1,0,1,0,0,1,0,0,0],
|
|
3164
|
+
....: [0,0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,1,0,0,0,1],
|
|
3165
|
+
....: [0,1,0,0,1,0,1,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1],
|
|
3166
|
+
....: [1,0,0,1,0,1,1,1,0,0,0,0,1,0,0,1,0,0,0,1,1,1],
|
|
3167
|
+
....: [0,0,1,0,1,1,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1,0]])
|
|
3168
|
+
sage: B = BinaryCode(M)
|
|
3169
|
+
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
|
|
3170
|
+
|
|
3171
|
+
sage: # needs sage.groups
|
|
3172
|
+
sage: S = SymmetricGroup(M.ncols())
|
|
3173
|
+
sage: L = [S([x+1 for x in g]) for g in gens]
|
|
3174
|
+
sage: PermutationGroup(L).order()
|
|
3175
|
+
887040
|
|
3176
|
+
sage: size
|
|
3177
|
+
887040
|
|
3178
|
+
|
|
3179
|
+
sage: B = BinaryCode(Matrix(GF(2),[[1,0,1],[0,1,1]]))
|
|
3180
|
+
sage: BC._aut_gp_and_can_label(B)
|
|
3181
|
+
([[0, 2, 1], [1, 0, 2]], [0, 1, 2], 6, [0, 1])
|
|
3182
|
+
|
|
3183
|
+
sage: B = BinaryCode(Matrix(GF(2),[[1,1,1,1]]))
|
|
3184
|
+
sage: BC._aut_gp_and_can_label(B)
|
|
3185
|
+
([[0, 1, 3, 2], [0, 2, 1, 3], [1, 0, 2, 3]], [0, 1, 2, 3], 24, [0, 1, 2])
|
|
3186
|
+
|
|
3187
|
+
sage: B = BinaryCode(Matrix(GF(2),[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]]))
|
|
3188
|
+
sage: gens, labeling, size, base = BC._aut_gp_and_can_label(B)
|
|
3189
|
+
sage: size
|
|
3190
|
+
87178291200
|
|
3191
|
+
|
|
3192
|
+
sage: M = Matrix(GF(2),[
|
|
3193
|
+
....: [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0],
|
|
3194
|
+
....: [0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0],
|
|
3195
|
+
....: [0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1],
|
|
3196
|
+
....: [0,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,1],
|
|
3197
|
+
....: [0,0,0,1,0,0,0,1,0,1,0,1,0,1,1,1,0,1],
|
|
3198
|
+
....: [0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,1,1,0]])
|
|
3199
|
+
sage: B = BinaryCode(M)
|
|
3200
|
+
sage: BC._aut_gp_and_can_label(B)[2]
|
|
3201
|
+
2160
|
|
3202
|
+
|
|
3203
|
+
sage: M = Matrix(GF(2),[
|
|
3204
|
+
....: [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
3205
|
+
....: [0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
3206
|
+
....: [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
3207
|
+
....: [0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0],
|
|
3208
|
+
....: [0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0],
|
|
3209
|
+
....: [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0],
|
|
3210
|
+
....: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
|
|
3211
|
+
....: [1,0,1,0,1,0,1,0,1,1,0,0,0,0,0,0,1,1,0,0],
|
|
3212
|
+
....: [1,1,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,0,0],
|
|
3213
|
+
....: [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,1,0]])
|
|
3214
|
+
sage: B = BinaryCode(M)
|
|
3215
|
+
sage: BC._aut_gp_and_can_label(B)[2]
|
|
3216
|
+
294912
|
|
3217
|
+
|
|
3218
|
+
sage: M = Matrix(GF(2), [
|
|
3219
|
+
....: [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
3220
|
+
....: [0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
|
3221
|
+
....: [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
|
|
3222
|
+
....: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0],
|
|
3223
|
+
....: [0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0],
|
|
3224
|
+
....: [0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0],
|
|
3225
|
+
....: [0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1],
|
|
3226
|
+
....: [0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,1,0,0,1,1,1,0,1],
|
|
3227
|
+
....: [0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1,1,1,1,0,0,0,1]])
|
|
3228
|
+
sage: B = BinaryCode(M)
|
|
3229
|
+
sage: BC = BinaryCodeClassifier()
|
|
3230
|
+
sage: BC._aut_gp_and_can_label(B)[2]
|
|
3231
|
+
442368
|
|
3232
|
+
"""
|
|
3233
|
+
cdef int i, j
|
|
3234
|
+
cdef BinaryCode C = CC
|
|
3235
|
+
self.aut_gp_and_can_label(C, verbosity)
|
|
3236
|
+
i = 0
|
|
3237
|
+
py_aut_gp_gens = []
|
|
3238
|
+
while i < self.aut_gp_index:
|
|
3239
|
+
gen = [self.aut_gp_gens[i+j] for j from 0 <= j < C.ncols]
|
|
3240
|
+
py_aut_gp_gens.append(gen)
|
|
3241
|
+
i += C.ncols
|
|
3242
|
+
py_labeling = [self.labeling[i] for i from 0 <= i < C.ncols]
|
|
3243
|
+
base = []
|
|
3244
|
+
for i from 0 <= i < self.radix:
|
|
3245
|
+
if self.base[i] == -1:
|
|
3246
|
+
break
|
|
3247
|
+
base.append(self.base[i])
|
|
3248
|
+
aut_gp_size = self.aut_gp_size
|
|
3249
|
+
return py_aut_gp_gens, py_labeling, aut_gp_size, base
|
|
3250
|
+
|
|
3251
|
+
cdef void aut_gp_and_can_label(self, BinaryCode C, int verbosity) noexcept:
|
|
3252
|
+
|
|
3253
|
+
# declare variables:
|
|
3254
|
+
cdef int i, j, ii, jj, iii, jjj, iiii # local variables
|
|
3255
|
+
|
|
3256
|
+
cdef PartitionStack nu, zeta, rho # nu is the current position in the tree,
|
|
3257
|
+
# zeta the first terminal position,
|
|
3258
|
+
# and rho the best-so-far guess at canonical labeling position
|
|
3259
|
+
cdef int k = 0 # the number of partitions in nu
|
|
3260
|
+
cdef int k_rho # the number of partitions in rho
|
|
3261
|
+
cdef int *v = self.v # list of vertices determining nu
|
|
3262
|
+
cdef int h = -1 # longest common ancestor of zeta and nu: zeta[h] == nu[h], zeta[h+1] != nu[h+1]
|
|
3263
|
+
# -1 indicates that zeta is not yet defined
|
|
3264
|
+
cdef int hb # longest common ancestor of rho and nu:
|
|
3265
|
+
# rho[hb] == nu[hb], rho[hb+1] != nu[hb+1]
|
|
3266
|
+
cdef int hh = 1 # the height of the oldest ancestor of nu satisfying Lemma 2.25 in [1]:
|
|
3267
|
+
# if nu does not satisfy it at k, then hh = k
|
|
3268
|
+
cdef int ht # smallest such that all descendants of zeta[ht] are equivalent under
|
|
3269
|
+
# the portion of the automorphism group so far discovered
|
|
3270
|
+
cdef int *alpha # for storing pointers to cells of nu[k]
|
|
3271
|
+
cdef int tvc # tvc keeps track of which vertex is the first where nu and zeta differ-
|
|
3272
|
+
# zeta was defined by splitting one vertex, and nu was defined by splitting tvc
|
|
3273
|
+
|
|
3274
|
+
cdef OrbitPartition Theta # keeps track of which vertices have been discovered to be equivalent
|
|
3275
|
+
cdef unsigned int *Phi # Phi stores the fixed point sets of each automorphism
|
|
3276
|
+
cdef unsigned int *Omega # Omega stores the minimal elements of each cell of the orbit partition
|
|
3277
|
+
cdef int l = -1 # current index for storing values in Phi and Omega- we start at -1 so that when
|
|
3278
|
+
# we increment first, the first place we write to is 0.
|
|
3279
|
+
cdef unsigned int *W # for each k, W[k] is a list (as int mask) of the vertices to be searched down from
|
|
3280
|
+
# the current partition, at k. Phi and Omega are ultimately used to make the size of
|
|
3281
|
+
# W as small as possible
|
|
3282
|
+
cdef int *e # 0 or 1, whether or not we have used Omega and Phi to narrow down W[k] yet: see states 12 and 17
|
|
3283
|
+
|
|
3284
|
+
cdef int index = 0 # Define $\Gamma^{(-1)} := \text{Aut}(C)$, and
|
|
3285
|
+
# $\Gamma^{(i)} := \Gamma^{(-1)}_{v_0,...,v_i}$.
|
|
3286
|
+
# Then index = $|\Gamma^{(k-1)}|/|\Gamma^{(k)}|$ at (POINT A)
|
|
3287
|
+
# and size = $|\Gamma^{(k-1)}|$ at (POINT A) and (POINT B).
|
|
3288
|
+
|
|
3289
|
+
cdef int *Lambda = self.Lambda1 # for tracking indicator values- zf and zb are
|
|
3290
|
+
cdef int *zf__Lambda_zeta = self.Lambda2 # indicator vectors remembering Lambda[k] for
|
|
3291
|
+
cdef int *zb__Lambda_rho = self.Lambda3 # zeta and rho, respectively
|
|
3292
|
+
cdef int qzb # keeps track of Lambda[k] {>,<,=} zb[k]
|
|
3293
|
+
cdef int hzf__h_zeta # the max height for which Lambda and zf agree
|
|
3294
|
+
cdef int hzb__h_rho = -1 # the max height for which Lambda and zb agree
|
|
3295
|
+
|
|
3296
|
+
cdef int *word_gamma
|
|
3297
|
+
cdef int *col_gamma = self.c_gamma # used for storing permutations
|
|
3298
|
+
cdef int nwords = C.nwords, ncols = C.ncols, nrows = C.nrows
|
|
3299
|
+
cdef int *ham_wts = self.ham_wts
|
|
3300
|
+
cdef int state # keeps track of position in algorithm - see sage/graphs/graph_isom.pyx, search for "STATE DIAGRAM"
|
|
3301
|
+
|
|
3302
|
+
self.aut_gp_index = 0
|
|
3303
|
+
self.aut_gp_size = Integer(1)
|
|
3304
|
+
|
|
3305
|
+
if self.w_gamma_size < nwords:
|
|
3306
|
+
while self.w_gamma_size < nwords:
|
|
3307
|
+
self.w_gamma_size *= 2
|
|
3308
|
+
self.alpha_size = self.w_gamma_size + self.radix
|
|
3309
|
+
self.Phi_size = self.w_gamma_size/self.radix + 1
|
|
3310
|
+
self.w_gamma = <int *> self.mem.realloc(self.w_gamma, self.w_gamma_size * sizeof(int))
|
|
3311
|
+
self.alpha = <int *> self.mem.realloc(self.alpha, self.alpha_size * sizeof(int))
|
|
3312
|
+
self.Phi = <unsigned int *> self.mem.realloc(self.Phi, self.Phi_size * self.L * sizeof(int))
|
|
3313
|
+
self.Omega = <unsigned int *> self.mem.realloc(self.Omega, self.Phi_size * self.L * sizeof(int))
|
|
3314
|
+
self.W = <unsigned int *> self.mem.realloc(self.W, self.Phi_size * self.radix * 2 * sizeof(int))
|
|
3315
|
+
|
|
3316
|
+
for i from 0 <= i < self.Phi_size * self.L:
|
|
3317
|
+
self.Omega[i] = 0
|
|
3318
|
+
word_gamma = self.w_gamma
|
|
3319
|
+
alpha = self.alpha # think of alpha as of length exactly nwords + ncols
|
|
3320
|
+
Phi = self.Phi
|
|
3321
|
+
Omega = self.Omega
|
|
3322
|
+
W = self.W
|
|
3323
|
+
e = self.e
|
|
3324
|
+
nu = PartitionStack(nrows, ncols)
|
|
3325
|
+
Theta = OrbitPartition(nrows, ncols)
|
|
3326
|
+
|
|
3327
|
+
# trivial case
|
|
3328
|
+
if ncols == 0 or nrows == 0:
|
|
3329
|
+
raise NotImplementedError("Must supply a nontrivial code.")
|
|
3330
|
+
|
|
3331
|
+
state = 1
|
|
3332
|
+
while state != -1:
|
|
3333
|
+
|
|
3334
|
+
if state == 1: # Entry point: once only
|
|
3335
|
+
alpha[0] = 0
|
|
3336
|
+
alpha[1] = nu.flag
|
|
3337
|
+
nu.refine(k, alpha, 2, C, ham_wts)
|
|
3338
|
+
if nu.sat_225(k):
|
|
3339
|
+
hh = k
|
|
3340
|
+
if nu.is_discrete(k):
|
|
3341
|
+
state = 18
|
|
3342
|
+
continue
|
|
3343
|
+
|
|
3344
|
+
# store the first smallest nontrivial cell in W[k], and set v[k]
|
|
3345
|
+
# equal to its minimum element
|
|
3346
|
+
v[k] = nu.new_first_smallest_nontrivial(k, W, self.Phi_size * k)
|
|
3347
|
+
|
|
3348
|
+
Lambda[k] = 0
|
|
3349
|
+
e[k] = 0
|
|
3350
|
+
state = 2
|
|
3351
|
+
|
|
3352
|
+
elif state == 2: # Move down the search tree one level by refining nu:
|
|
3353
|
+
# split out a vertex, and refine nu against it
|
|
3354
|
+
k += 1
|
|
3355
|
+
nu.clear(k)
|
|
3356
|
+
|
|
3357
|
+
alpha[0] = nu.split_vertex(v[k-1], k)
|
|
3358
|
+
Lambda[k] = nu.refine(k, alpha, 1, C, ham_wts) # store the invariant to Lambda[k]
|
|
3359
|
+
# only if this is the first time moving down the search tree:
|
|
3360
|
+
if h == -1:
|
|
3361
|
+
state = 5
|
|
3362
|
+
continue
|
|
3363
|
+
|
|
3364
|
+
# update hzf__h_zeta
|
|
3365
|
+
if hzf__h_zeta == k-1 and Lambda[k] == zf__Lambda_zeta[k]:
|
|
3366
|
+
hzf__h_zeta = k
|
|
3367
|
+
# update qzb
|
|
3368
|
+
if qzb == 0:
|
|
3369
|
+
if zb__Lambda_rho[k] == -1 or Lambda[k] < zb__Lambda_rho[k]:
|
|
3370
|
+
qzb = -1
|
|
3371
|
+
elif Lambda[k] > zb__Lambda_rho[k]:
|
|
3372
|
+
qzb = 1
|
|
3373
|
+
else:
|
|
3374
|
+
qzb = 0
|
|
3375
|
+
# update hzb
|
|
3376
|
+
if hzb__h_rho == k-1 and qzb == 0:
|
|
3377
|
+
hzb__h_rho = k
|
|
3378
|
+
# if Lambda[k] > zb[k], then zb[k] := Lambda[k]
|
|
3379
|
+
# (zb keeps track of the indicator invariants corresponding to
|
|
3380
|
+
# rho, the closest canonical leaf so far seen- if Lambda is
|
|
3381
|
+
# bigger, then rho must be about to change
|
|
3382
|
+
if qzb > 0:
|
|
3383
|
+
zb__Lambda_rho[k] = Lambda[k]
|
|
3384
|
+
state = 3
|
|
3385
|
+
|
|
3386
|
+
elif state == 3: # attempt to rule out automorphisms while moving down the tree
|
|
3387
|
+
# if k > hzf, then we know that nu currently does not look like zeta, the first
|
|
3388
|
+
# terminal node encountered, thus there is no automorphism to discover. If qzb < 0,
|
|
3389
|
+
# i.e. Lambda[k] < zb[k], then the indicator is not maximal, and we can't reach a
|
|
3390
|
+
# canonical leaf. If neither of these is the case, then proceed to state 4.
|
|
3391
|
+
if hzf__h_zeta <= k or qzb >= 0:
|
|
3392
|
+
state = 4
|
|
3393
|
+
else:
|
|
3394
|
+
state = 6
|
|
3395
|
+
|
|
3396
|
+
elif state == 4: # at this point we have -not- ruled out the presence of automorphisms
|
|
3397
|
+
if nu.is_discrete(k):
|
|
3398
|
+
state = 7
|
|
3399
|
+
continue # we have a terminal node, so process it
|
|
3400
|
+
|
|
3401
|
+
# otherwise, prepare to split out another column:
|
|
3402
|
+
# store the first smallest nontrivial cell in W[k], and set v[k]
|
|
3403
|
+
# equal to its minimum element
|
|
3404
|
+
v[k] = nu.new_first_smallest_nontrivial(k, W, self.Phi_size * k)
|
|
3405
|
+
if not nu.sat_225(k):
|
|
3406
|
+
hh = k + 1
|
|
3407
|
+
e[k] = 0 # see state 12 and 17
|
|
3408
|
+
state = 2 # continue down the tree
|
|
3409
|
+
|
|
3410
|
+
elif state == 5:
|
|
3411
|
+
# same as state 3, but in the case where we haven't yet defined zeta
|
|
3412
|
+
# i.e. this is our first time down the tree. Once we get to the bottom,
|
|
3413
|
+
# we will have zeta = nu = rho, so we do:
|
|
3414
|
+
zf__Lambda_zeta[k] = Lambda[k]
|
|
3415
|
+
zb__Lambda_rho[k] = Lambda[k]
|
|
3416
|
+
state = 4
|
|
3417
|
+
|
|
3418
|
+
elif state == 6: # at this stage, there is no reason to continue downward, so backtrack
|
|
3419
|
+
j = k
|
|
3420
|
+
|
|
3421
|
+
# return to the longest ancestor nu[i] of nu that could have a
|
|
3422
|
+
# descendant equivalent to zeta or could improve on rho.
|
|
3423
|
+
# All terminal nodes descending from nu[hh] are known to be
|
|
3424
|
+
# equivalent, so i < hh. Also, if i > hzb, none of the
|
|
3425
|
+
# descendants of nu[i] can improve rho, since the indicator is
|
|
3426
|
+
# off (Lambda(nu) < Lambda(rho)). If i >= ht, then no descendant
|
|
3427
|
+
# of nu[i] is equivalent to zeta (see [1, p67]).
|
|
3428
|
+
if ht-1 > hzb__h_rho:
|
|
3429
|
+
if ht-1 < hh-1:
|
|
3430
|
+
k = ht-1
|
|
3431
|
+
else:
|
|
3432
|
+
k = hh-1
|
|
3433
|
+
else:
|
|
3434
|
+
if hzb__h_rho < hh-1:
|
|
3435
|
+
k = hzb__h_rho
|
|
3436
|
+
else:
|
|
3437
|
+
k = hh-1
|
|
3438
|
+
# TODO: is the following line necessary?
|
|
3439
|
+
if k == -1:
|
|
3440
|
+
k = 0
|
|
3441
|
+
|
|
3442
|
+
if hb > k: # update hb since we are backtracking
|
|
3443
|
+
hb = k
|
|
3444
|
+
# if j == hh, then all nodes lower than our current position are equivalent, so bail out
|
|
3445
|
+
if j == hh:
|
|
3446
|
+
state = 13
|
|
3447
|
+
continue
|
|
3448
|
+
|
|
3449
|
+
# recall hh: the height of the oldest ancestor of zeta for which Lemma 2.25 is
|
|
3450
|
+
# satisfied, which implies that all terminal nodes descended from there are equivalent.
|
|
3451
|
+
# If we are looking at such a node, then the partition at nu[hh] can be used for later
|
|
3452
|
+
# pruning, so we store its fixed set and a set of representatives of its cells.
|
|
3453
|
+
if l < self.L-1:
|
|
3454
|
+
l += 1
|
|
3455
|
+
nu.new_min_cell_reps(hh, Omega, self.Phi_size*l)
|
|
3456
|
+
nu.fixed_vertices(hh, Phi, Omega, self.Phi_size*l)
|
|
3457
|
+
|
|
3458
|
+
state = 12
|
|
3459
|
+
|
|
3460
|
+
elif state == 7: # we have just arrived at a terminal node of the search tree T(G, Pi)
|
|
3461
|
+
# if this is the first terminal node, go directly to 18, to
|
|
3462
|
+
# process zeta
|
|
3463
|
+
if h == -1:
|
|
3464
|
+
state = 18
|
|
3465
|
+
continue
|
|
3466
|
+
|
|
3467
|
+
# hzf is the extremal height of ancestors of both nu and zeta, so if k < hzf, nu is not
|
|
3468
|
+
# equivalent to zeta, i.e. there is no automorphism to discover.
|
|
3469
|
+
if k < hzf__h_zeta:
|
|
3470
|
+
state = 8
|
|
3471
|
+
continue
|
|
3472
|
+
|
|
3473
|
+
nu.get_permutation(zeta, word_gamma, col_gamma)
|
|
3474
|
+
|
|
3475
|
+
# if C^gamma == C, the permutation is an automorphism, goto 10
|
|
3476
|
+
if C.is_automorphism(col_gamma, word_gamma):
|
|
3477
|
+
state = 10
|
|
3478
|
+
else:
|
|
3479
|
+
state = 8
|
|
3480
|
+
|
|
3481
|
+
elif state == 8: # we have just ruled out the presence of automorphism and have not yet
|
|
3482
|
+
# considered whether nu improves on rho
|
|
3483
|
+
# if qzb < 0, then rho already has larger indicator tuple
|
|
3484
|
+
if qzb < 0:
|
|
3485
|
+
state = 6
|
|
3486
|
+
continue
|
|
3487
|
+
|
|
3488
|
+
# if Lambda[k] > zb[k] or nu is shorter than rho, then we have an improvement for rho
|
|
3489
|
+
if (qzb > 0) or (k < k_rho):
|
|
3490
|
+
state = 9
|
|
3491
|
+
continue
|
|
3492
|
+
|
|
3493
|
+
# now Lambda[k] == zb[k] and k == k_rho, so we appeal to an enumeration:
|
|
3494
|
+
j = nu.cmp(rho, C)
|
|
3495
|
+
# if C(nu) > C(rho), we have a new label, goto 9
|
|
3496
|
+
if j > 0:
|
|
3497
|
+
state = 9
|
|
3498
|
+
continue
|
|
3499
|
+
|
|
3500
|
+
# if C(nu) < C(rho), no new label, goto 6
|
|
3501
|
+
if j < 0:
|
|
3502
|
+
state = 6
|
|
3503
|
+
continue
|
|
3504
|
+
|
|
3505
|
+
# if C(nu) == C(rho), get the automorphism and goto 10
|
|
3506
|
+
rho.get_permutation(nu, word_gamma, col_gamma)
|
|
3507
|
+
|
|
3508
|
+
state = 10
|
|
3509
|
+
|
|
3510
|
+
elif state == 9: # nu is a better guess at the canonical label than rho
|
|
3511
|
+
rho = PartitionStack(nu)
|
|
3512
|
+
k_rho = k
|
|
3513
|
+
qzb = 0
|
|
3514
|
+
hb = k
|
|
3515
|
+
hzb__h_rho = k
|
|
3516
|
+
# set zb[k+1] = Infinity
|
|
3517
|
+
zb__Lambda_rho[k+1] = -1
|
|
3518
|
+
state = 6
|
|
3519
|
+
|
|
3520
|
+
elif state == 10: # we have an automorphism to process
|
|
3521
|
+
# increment l
|
|
3522
|
+
if l < self.L-1: l += 1
|
|
3523
|
+
# store information about the automorphism to Omega and Phi
|
|
3524
|
+
ii = self.Phi_size*l
|
|
3525
|
+
jj = 1 + nwords/self.radix
|
|
3526
|
+
# Omega[ii] = ~(~0 << ncols)
|
|
3527
|
+
for i from 0 <= i < jj:
|
|
3528
|
+
Omega[ii+i] = ~0
|
|
3529
|
+
Phi[ii+i] = 0
|
|
3530
|
+
if nwords % self.radix:
|
|
3531
|
+
jj += 1
|
|
3532
|
+
# Omega[ii+jj-1] = ~((1 << nwords % self.radix) - 1)
|
|
3533
|
+
# Omega stores the minimum cell representatives
|
|
3534
|
+
i = 0
|
|
3535
|
+
while i < ncols:
|
|
3536
|
+
j = col_gamma[i] # i is a minimum
|
|
3537
|
+
while j != i: # cell rep,
|
|
3538
|
+
Omega[ii] ^= (1<<j) # so cancel
|
|
3539
|
+
j = col_gamma[j] # cellmates
|
|
3540
|
+
i += 1
|
|
3541
|
+
while i < ncols and not Omega[ii]&(1<<i): # find minimal element
|
|
3542
|
+
i += 1 # of next cell
|
|
3543
|
+
i = 0
|
|
3544
|
+
jj = self.radix
|
|
3545
|
+
while i < nwords:
|
|
3546
|
+
j = word_gamma[i]
|
|
3547
|
+
while j != i:
|
|
3548
|
+
Omega[ii+1+j/jj] ^= (1<<(j % jj))
|
|
3549
|
+
j = word_gamma[j]
|
|
3550
|
+
i += 1
|
|
3551
|
+
while i < nwords and not Omega[ii+1+i/jj]&(1<<(i % jj)):
|
|
3552
|
+
i += 1
|
|
3553
|
+
# Phi stores the columns fixed by the automorphism
|
|
3554
|
+
for i from 0 <= i < ncols:
|
|
3555
|
+
if col_gamma[i] == i:
|
|
3556
|
+
Phi[ii] ^= (1 << i)
|
|
3557
|
+
for i from 0 <= i < nwords:
|
|
3558
|
+
if word_gamma[i] == i:
|
|
3559
|
+
Phi[ii+1+i/jj] ^= (1<<(i % jj))
|
|
3560
|
+
|
|
3561
|
+
# Now incorporate the automorphism into Theta
|
|
3562
|
+
j = Theta.merge_perm(col_gamma, word_gamma)
|
|
3563
|
+
|
|
3564
|
+
# j stores whether anything happened or not- if not, then the automorphism we have
|
|
3565
|
+
# discovered is already in the subgroup spanned by the generators we have output
|
|
3566
|
+
if not j:
|
|
3567
|
+
state = 11
|
|
3568
|
+
continue
|
|
3569
|
+
|
|
3570
|
+
# otherwise, we have a new generator, so record it:
|
|
3571
|
+
self.record_automorphism(col_gamma, ncols)
|
|
3572
|
+
# The variable tvc was set to be the minimum element of W[k] the last time the
|
|
3573
|
+
# algorithm came up to meet zeta. At this point, we were considering the new
|
|
3574
|
+
# possibilities for descending away from zeta at this level.
|
|
3575
|
+
# if this is still a minimum cell representative of Theta, even in light
|
|
3576
|
+
# of this new automorphism, then the current branch off of zeta hasn't been
|
|
3577
|
+
# found equivalent to one already searched yet, so there may still be a
|
|
3578
|
+
# better canonical label downward.
|
|
3579
|
+
if tvc & nu.flag:
|
|
3580
|
+
i = tvc^nu.flag
|
|
3581
|
+
if Theta.wd_min_cell_rep[Theta.wd_find(i)] == i:
|
|
3582
|
+
state = 11
|
|
3583
|
+
continue
|
|
3584
|
+
elif Theta.col_min_cell_rep[Theta.col_find(tvc)] == tvc:
|
|
3585
|
+
state = 11
|
|
3586
|
+
continue
|
|
3587
|
+
|
|
3588
|
+
# Otherwise, proceed to where zeta meets nu:
|
|
3589
|
+
k = h
|
|
3590
|
+
state = 13
|
|
3591
|
+
|
|
3592
|
+
elif state == 11: # We have just found a new automorphism, and deduced that there may
|
|
3593
|
+
# be a better canonical label below the current branch off of zeta. So go to where
|
|
3594
|
+
# nu meets rho
|
|
3595
|
+
k = hb
|
|
3596
|
+
state = 12
|
|
3597
|
+
|
|
3598
|
+
elif state == 12: # Coming here from either state 6 or 11, the algorithm has discovered
|
|
3599
|
+
# some new information. 11 came from 10, where a new line in Omega and
|
|
3600
|
+
# Phi was just recorded, and 6 stored information about implicit auto-
|
|
3601
|
+
# morphisms in Omega and Phi
|
|
3602
|
+
if e[k] == 1:
|
|
3603
|
+
# this means that the algorithm has come upward to this position (in state 17)
|
|
3604
|
+
# before, so we have already intersected W[k] with the bulk of Omega and Phi, but
|
|
3605
|
+
# we should still catch up with the latest ones
|
|
3606
|
+
ii = self.Phi_size*l
|
|
3607
|
+
jj = self.Phi_size*k
|
|
3608
|
+
j = 1 + nwords/self.radix
|
|
3609
|
+
if nwords % self.radix:
|
|
3610
|
+
j += 1
|
|
3611
|
+
W[jj] &= Omega[ii]
|
|
3612
|
+
for i from 0 < i < j:
|
|
3613
|
+
W[jj+i] &= Omega[ii+i]
|
|
3614
|
+
state = 13
|
|
3615
|
+
|
|
3616
|
+
elif state == 13: # hub state
|
|
3617
|
+
if k == -1:
|
|
3618
|
+
state = -1
|
|
3619
|
+
continue # exit point
|
|
3620
|
+
|
|
3621
|
+
if k > h:
|
|
3622
|
+
state = 17
|
|
3623
|
+
continue # we are still on the same principal branch from zeta
|
|
3624
|
+
|
|
3625
|
+
if k == h:
|
|
3626
|
+
state = 14
|
|
3627
|
+
continue # update the stabilizer index and check for new splits,
|
|
3628
|
+
# since we have returned to a partition of zeta
|
|
3629
|
+
# otherwise k < h, hence we have just backtracked up zeta, and are one level closer to done
|
|
3630
|
+
h = k
|
|
3631
|
+
tvc = 0
|
|
3632
|
+
jj = self.Phi_size*k
|
|
3633
|
+
if W[jj]:
|
|
3634
|
+
while not (1 << tvc) & W[jj]:
|
|
3635
|
+
tvc += 1
|
|
3636
|
+
else:
|
|
3637
|
+
ii = 0
|
|
3638
|
+
while not W[jj+1+ii]:
|
|
3639
|
+
ii += 1
|
|
3640
|
+
while not W[jj+1+ii] & (1 << tvc):
|
|
3641
|
+
tvc += 1
|
|
3642
|
+
tvc = (ii*self.radix + tvc) ^ nu.flag
|
|
3643
|
+
# now tvc points to the minimal cell representative of W[k]
|
|
3644
|
+
state = 14
|
|
3645
|
+
|
|
3646
|
+
elif state == 14: # see if there are any more splits to make from this level of zeta (see state 17)
|
|
3647
|
+
if v[k]&nu.flag == tvc&nu.flag:
|
|
3648
|
+
if tvc&nu.flag:
|
|
3649
|
+
if Theta.wd_find(v[k]^nu.flag) == Theta.wd_find(tvc^nu.flag):
|
|
3650
|
+
index += 1
|
|
3651
|
+
else:
|
|
3652
|
+
if Theta.col_find(v[k]) == Theta.col_find(tvc):
|
|
3653
|
+
index += 1
|
|
3654
|
+
|
|
3655
|
+
# keep tabs on how many elements are in the same cell of Theta as tvc
|
|
3656
|
+
# find the next split
|
|
3657
|
+
jj = self.Phi_size*k
|
|
3658
|
+
if v[k]&nu.flag:
|
|
3659
|
+
ii = self.radix
|
|
3660
|
+
i = (v[k]^nu.flag) + 1
|
|
3661
|
+
while i < nwords and not (1 << i % ii) & W[jj+1+i/ii]:
|
|
3662
|
+
i += 1
|
|
3663
|
+
if i < nwords:
|
|
3664
|
+
v[k] = i^nu.flag
|
|
3665
|
+
else:
|
|
3666
|
+
# there is no new split at this level
|
|
3667
|
+
state = 16
|
|
3668
|
+
continue
|
|
3669
|
+
# new split column better be a minimal representative in Theta, or wasted effort
|
|
3670
|
+
if Theta.wd_min_cell_rep[Theta.wd_find(i)] == i:
|
|
3671
|
+
state = 15
|
|
3672
|
+
else:
|
|
3673
|
+
state = 14
|
|
3674
|
+
else:
|
|
3675
|
+
i = v[k] + 1
|
|
3676
|
+
while i < ncols and not (1 << i) & W[jj]:
|
|
3677
|
+
i += 1
|
|
3678
|
+
if i < ncols:
|
|
3679
|
+
v[k] = i
|
|
3680
|
+
else:
|
|
3681
|
+
# there is no new split at this level
|
|
3682
|
+
state = 16
|
|
3683
|
+
continue
|
|
3684
|
+
# new split column better be a minimal representative in Theta, or wasted effort
|
|
3685
|
+
if Theta.col_min_cell_rep[Theta.col_find(v[k])] == v[k]:
|
|
3686
|
+
state = 15
|
|
3687
|
+
else:
|
|
3688
|
+
state = 14
|
|
3689
|
+
|
|
3690
|
+
elif state == 15: # split out the column v[k]
|
|
3691
|
+
# hh is smallest such that nu[hh] satisfies Lemma 2.25. If it is larger than k+1,
|
|
3692
|
+
# it must be modified, since we are changing that part
|
|
3693
|
+
if k + 1 < hh:
|
|
3694
|
+
hh = k + 1
|
|
3695
|
+
# hzf is maximal such that indicators line up for nu and zeta
|
|
3696
|
+
if k < hzf__h_zeta:
|
|
3697
|
+
hzf__h_zeta = k
|
|
3698
|
+
# hzb is longest such that nu and rho have the same indicators
|
|
3699
|
+
if hzb__h_rho >= k:
|
|
3700
|
+
hzb__h_rho = k
|
|
3701
|
+
qzb = 0
|
|
3702
|
+
state = 2
|
|
3703
|
+
|
|
3704
|
+
elif state == 16: # backtrack up zeta, updating information about stabilizer vector
|
|
3705
|
+
jj = self.Phi_size*k
|
|
3706
|
+
if W[jj]:
|
|
3707
|
+
i = W[jj]
|
|
3708
|
+
j = ham_wts[i & 65535] + ham_wts[(i >> 16) & 65535]
|
|
3709
|
+
else:
|
|
3710
|
+
i = 0
|
|
3711
|
+
j = 0
|
|
3712
|
+
ii = self.radix
|
|
3713
|
+
while i*ii < nwords:
|
|
3714
|
+
iii = W[jj+1+i]
|
|
3715
|
+
j += ham_wts[iii & 65535] + ham_wts[(iii >> 16) & 65535]
|
|
3716
|
+
i += 1
|
|
3717
|
+
if j == index and ht == k + 1:
|
|
3718
|
+
ht = k
|
|
3719
|
+
self.aut_gp_size *= index
|
|
3720
|
+
# (POINT A)
|
|
3721
|
+
index = 0
|
|
3722
|
+
k -= 1
|
|
3723
|
+
if hb > k: # update hb since we are backtracking
|
|
3724
|
+
hb = k
|
|
3725
|
+
state = 13
|
|
3726
|
+
|
|
3727
|
+
elif state == 17: # see if there are any more splits to make from this level of nu (and not zeta)
|
|
3728
|
+
|
|
3729
|
+
jjj = self.Phi_size*k
|
|
3730
|
+
if e[k] == 0: # now is the time to narrow down W[k] by Omega and Phi
|
|
3731
|
+
# intersect W[k] with each Omega[i] such that v[0]...v[k-1] is in Phi[i]
|
|
3732
|
+
jj = self.Phi_size*self.L
|
|
3733
|
+
iii = nwords/self.radix
|
|
3734
|
+
if nwords % self.radix:
|
|
3735
|
+
iii += 1
|
|
3736
|
+
for ii from 0 <= ii < iii:
|
|
3737
|
+
Phi[jj+ii] = 0
|
|
3738
|
+
for ii from 0 <= ii < k:
|
|
3739
|
+
if v[ii]&nu.flag:
|
|
3740
|
+
i = v[ii]^nu.flag
|
|
3741
|
+
Phi[jj+1+i/self.radix] ^= (1 << i % self.radix)
|
|
3742
|
+
else:
|
|
3743
|
+
Phi[jj] ^= (1 << v[ii])
|
|
3744
|
+
for i from 0 <= i <= l:
|
|
3745
|
+
ii = self.Phi_size*i
|
|
3746
|
+
iiii = 1
|
|
3747
|
+
for j from 0 <= j < iii:
|
|
3748
|
+
if Phi[ii + j] & Phi[jj + j] != Phi[jj + j]:
|
|
3749
|
+
iiii = 0
|
|
3750
|
+
break
|
|
3751
|
+
if iiii:
|
|
3752
|
+
for j from 0 <= j < iii:
|
|
3753
|
+
W[jjj + j] &= Omega[ii + j]
|
|
3754
|
+
e[k] = 1
|
|
3755
|
+
|
|
3756
|
+
# see if there is a vertex to split out
|
|
3757
|
+
if nu.flag&v[k]:
|
|
3758
|
+
i = (v[k]^nu.flag)
|
|
3759
|
+
while i < nwords:
|
|
3760
|
+
i += 1
|
|
3761
|
+
if (1 << i % self.radix) & W[jjj+1+i/self.radix]:
|
|
3762
|
+
break
|
|
3763
|
+
if i < nwords:
|
|
3764
|
+
v[k] = i^nu.flag
|
|
3765
|
+
state = 15
|
|
3766
|
+
continue
|
|
3767
|
+
else:
|
|
3768
|
+
i = v[k]
|
|
3769
|
+
while i < ncols:
|
|
3770
|
+
i += 1
|
|
3771
|
+
if (1 << i) & W[jjj]:
|
|
3772
|
+
break
|
|
3773
|
+
if i < ncols:
|
|
3774
|
+
v[k] = i
|
|
3775
|
+
state = 15
|
|
3776
|
+
continue
|
|
3777
|
+
|
|
3778
|
+
k -= 1
|
|
3779
|
+
state = 13
|
|
3780
|
+
|
|
3781
|
+
elif state == 18: # the first time nu becomes a discrete partition: set up zeta, our "identity" leaf
|
|
3782
|
+
# initialize counters for zeta:
|
|
3783
|
+
h = k # zeta[h] == nu[h]
|
|
3784
|
+
ht = k # nodes descended from zeta[ht] are all equivalent
|
|
3785
|
+
hzf__h_zeta = k # max such that indicators for zeta and nu agree
|
|
3786
|
+
zeta = PartitionStack(nu)
|
|
3787
|
+
for i from 0 <= i < k:
|
|
3788
|
+
self.base[i] = v[i]
|
|
3789
|
+
self.base_size = k
|
|
3790
|
+
if k != self.radix:
|
|
3791
|
+
self.base[k] = -1
|
|
3792
|
+
# (POINT B)
|
|
3793
|
+
k -= 1
|
|
3794
|
+
rho = PartitionStack(nu)
|
|
3795
|
+
# initialize counters for rho:
|
|
3796
|
+
k_rho = k+1 # number of partitions in rho
|
|
3797
|
+
hzb__h_rho = k # max such that indicators for rho and nu agree - BDM had k+1
|
|
3798
|
+
hb = k # rho[hb] == nu[hb] - BDM had k+1
|
|
3799
|
+
qzb = 0 # Lambda[k] == zb[k], so...
|
|
3800
|
+
state = 13
|
|
3801
|
+
|
|
3802
|
+
# end big while loop
|
|
3803
|
+
rho.find_basis(ham_wts)
|
|
3804
|
+
for i from 0 <= i < ncols:
|
|
3805
|
+
self.labeling[rho.col_ents[i]] = i
|
|
3806
|
+
for i from 0 <= i < 2*nrows:
|
|
3807
|
+
self.labeling[i+ncols] = rho.basis_locations[i]
|
|
3808
|
+
|
|
3809
|
+
def put_in_canonical_form(self, BinaryCode B):
|
|
3810
|
+
"""
|
|
3811
|
+
Put the code into canonical form.
|
|
3812
|
+
|
|
3813
|
+
Canonical form is obtained by performing row reduction, permuting the
|
|
3814
|
+
pivots to the front so that the generator matrix is of the form: the
|
|
3815
|
+
identity matrix augmented to the right by arbitrary data.
|
|
3816
|
+
|
|
3817
|
+
EXAMPLES::
|
|
3818
|
+
|
|
3819
|
+
sage: from sage.coding.binary_code import *
|
|
3820
|
+
sage: BC = BinaryCodeClassifier()
|
|
3821
|
+
sage: B = BinaryCode(codes.GolayCode(GF(2)).generator_matrix())
|
|
3822
|
+
sage: B.apply_permutation(list(range(24,-1,-1)))
|
|
3823
|
+
sage: B
|
|
3824
|
+
Binary [24,12] linear code, generator matrix
|
|
3825
|
+
[011000111010100000000000]
|
|
3826
|
+
[001001001111100000000001]
|
|
3827
|
+
[011010100101100000000010]
|
|
3828
|
+
[001101110001100000000100]
|
|
3829
|
+
[010011011001100000001000]
|
|
3830
|
+
[010110110011000000010000]
|
|
3831
|
+
[011101100110000000100000]
|
|
3832
|
+
[000011110110100001000000]
|
|
3833
|
+
[000111101101000010000000]
|
|
3834
|
+
[001111011010000100000000]
|
|
3835
|
+
[010110001110101000000000]
|
|
3836
|
+
[011100011101010000000000]
|
|
3837
|
+
sage: BC.put_in_canonical_form(B)
|
|
3838
|
+
sage: B
|
|
3839
|
+
Binary [24,12] linear code, generator matrix
|
|
3840
|
+
[100000000000001100111001]
|
|
3841
|
+
[010000000000001010001111]
|
|
3842
|
+
[001000000000001111010010]
|
|
3843
|
+
[000100000000010110101010]
|
|
3844
|
+
[000010000000010110010101]
|
|
3845
|
+
[000001000000010001101101]
|
|
3846
|
+
[000000100000011000110110]
|
|
3847
|
+
[000000010000011111001001]
|
|
3848
|
+
[000000001000010101110011]
|
|
3849
|
+
[000000000100010011011110]
|
|
3850
|
+
[000000000010001011110101]
|
|
3851
|
+
[000000000001001101101110]
|
|
3852
|
+
"""
|
|
3853
|
+
aut_gp_gens, labeling, size, base = self._aut_gp_and_can_label(B)
|
|
3854
|
+
B._apply_permutation_to_basis(labeling)
|
|
3855
|
+
B.put_in_std_form()
|
|
3856
|
+
|
|
3857
|
+
def generate_children(self, BinaryCode B, int n, int d=2):
|
|
3858
|
+
"""
|
|
3859
|
+
Use canonical augmentation to generate children of the code `B`.
|
|
3860
|
+
|
|
3861
|
+
INPUT:
|
|
3862
|
+
|
|
3863
|
+
- ``B`` -- a :class:`BinaryCode`
|
|
3864
|
+
|
|
3865
|
+
- ``n`` -- limit on the degree of the code
|
|
3866
|
+
|
|
3867
|
+
- ``d`` -- test whether new vector has weight divisible by `d`. If
|
|
3868
|
+
`d=4`, this ensures that all doubly-even canonically augmented
|
|
3869
|
+
children are generated.
|
|
3870
|
+
|
|
3871
|
+
EXAMPLES::
|
|
3872
|
+
|
|
3873
|
+
sage: from sage.coding.binary_code import *
|
|
3874
|
+
sage: BC = BinaryCodeClassifier()
|
|
3875
|
+
sage: B = BinaryCode(Matrix(GF(2), [[1,1,1,1]]))
|
|
3876
|
+
sage: BC.generate_children(B, 6, 4) # needs sage.groups
|
|
3877
|
+
[
|
|
3878
|
+
[1 1 1 1 0 0]
|
|
3879
|
+
[0 1 0 1 1 1]
|
|
3880
|
+
]
|
|
3881
|
+
|
|
3882
|
+
.. NOTE::
|
|
3883
|
+
|
|
3884
|
+
The function ``codes.databases.self_orthogonal_binary_codes`` makes heavy
|
|
3885
|
+
use of this function.
|
|
3886
|
+
|
|
3887
|
+
MORE EXAMPLES::
|
|
3888
|
+
|
|
3889
|
+
sage: # needs sage.groups
|
|
3890
|
+
sage: soc_iter = codes.databases.self_orthogonal_binary_codes(12, 6, 4)
|
|
3891
|
+
sage: L = list(soc_iter)
|
|
3892
|
+
sage: for n in range(13):
|
|
3893
|
+
....: s = 'n=%2d : ' % n
|
|
3894
|
+
....: for k in range(1,7):
|
|
3895
|
+
....: s += '%3d ' % len([C for C in L
|
|
3896
|
+
....: if C.length() == n and C.dimension() == k])
|
|
3897
|
+
....: print(s)
|
|
3898
|
+
n= 0 : 0 0 0 0 0 0
|
|
3899
|
+
n= 1 : 0 0 0 0 0 0
|
|
3900
|
+
n= 2 : 0 0 0 0 0 0
|
|
3901
|
+
n= 3 : 0 0 0 0 0 0
|
|
3902
|
+
n= 4 : 1 0 0 0 0 0
|
|
3903
|
+
n= 5 : 0 0 0 0 0 0
|
|
3904
|
+
n= 6 : 0 1 0 0 0 0
|
|
3905
|
+
n= 7 : 0 0 1 0 0 0
|
|
3906
|
+
n= 8 : 1 1 1 1 0 0
|
|
3907
|
+
n= 9 : 0 0 0 0 0 0
|
|
3908
|
+
n=10 : 0 1 1 1 0 0
|
|
3909
|
+
n=11 : 0 0 1 1 0 0
|
|
3910
|
+
n=12 : 1 2 3 4 2 0
|
|
3911
|
+
"""
|
|
3912
|
+
cdef BinaryCode m
|
|
3913
|
+
cdef codeword *ortho_basis
|
|
3914
|
+
cdef codeword *B_can_lab
|
|
3915
|
+
cdef codeword current, swap
|
|
3916
|
+
cdef codeword word, temp, gate, nonzero_gate, orbit, bwd, k_gate
|
|
3917
|
+
cdef codeword *temp_basis
|
|
3918
|
+
cdef codeword *orbit_checks
|
|
3919
|
+
cdef codeword orb_chx_size, orb_chx_shift, radix_gate
|
|
3920
|
+
cdef WordPermutation *gwp
|
|
3921
|
+
cdef WordPermutation *hwp
|
|
3922
|
+
cdef WordPermutation *can_lab
|
|
3923
|
+
cdef WordPermutation *can_lab_inv
|
|
3924
|
+
cdef WordPermutation **parent_generators
|
|
3925
|
+
cdef BinaryCode B_aug
|
|
3926
|
+
cdef int i, ii, j, jj, ij, k = 0, parity, combo, num_gens
|
|
3927
|
+
cdef int base_size, row
|
|
3928
|
+
cdef int *multimod2_index
|
|
3929
|
+
cdef int *ham_wts = self.ham_wts
|
|
3930
|
+
cdef int *num_inner_gens
|
|
3931
|
+
cdef int *num_outer_gens
|
|
3932
|
+
cdef int *v
|
|
3933
|
+
cdef int log_2_radix
|
|
3934
|
+
cdef bint bingo, bingo2, bingo3
|
|
3935
|
+
|
|
3936
|
+
B.put_in_std_form()
|
|
3937
|
+
ortho_basis = expand_to_ortho_basis(B, n) # modifies B!
|
|
3938
|
+
|
|
3939
|
+
aut_gp_gens, labeling, size, base = self._aut_gp_and_can_label(B)
|
|
3940
|
+
B_can_lab = <codeword *> sig_malloc(B.nrows * sizeof(codeword))
|
|
3941
|
+
can_lab = create_word_perm(labeling[:B.ncols])
|
|
3942
|
+
if B_can_lab is NULL or can_lab is NULL:
|
|
3943
|
+
sig_free(ortho_basis)
|
|
3944
|
+
if B_can_lab is not NULL:
|
|
3945
|
+
sig_free(B_can_lab)
|
|
3946
|
+
if can_lab is not NULL:
|
|
3947
|
+
sig_free(can_lab)
|
|
3948
|
+
raise MemoryError()
|
|
3949
|
+
for i from 0 <= i < B.nrows:
|
|
3950
|
+
B_can_lab[i] = permute_word_by_wp(can_lab, B.basis[i])
|
|
3951
|
+
dealloc_word_perm(can_lab)
|
|
3952
|
+
row = 0
|
|
3953
|
+
current = 1
|
|
3954
|
+
while row < B.nrows:
|
|
3955
|
+
i = row
|
|
3956
|
+
while i < B.nrows and not B_can_lab[i] & current:
|
|
3957
|
+
i += 1
|
|
3958
|
+
if i < B.nrows:
|
|
3959
|
+
if i != row:
|
|
3960
|
+
swap = B_can_lab[row]
|
|
3961
|
+
B_can_lab[row] = B_can_lab[i]
|
|
3962
|
+
B_can_lab[i] = swap
|
|
3963
|
+
for j from 0 <= j < row:
|
|
3964
|
+
if B_can_lab[j] & current:
|
|
3965
|
+
B_can_lab[j] ^= B_can_lab[row]
|
|
3966
|
+
for j from row < j < B.nrows:
|
|
3967
|
+
if B_can_lab[j] & current:
|
|
3968
|
+
B_can_lab[j] ^= B_can_lab[row]
|
|
3969
|
+
row += 1
|
|
3970
|
+
current = current << 1
|
|
3971
|
+
num_gens = len(aut_gp_gens)
|
|
3972
|
+
base_size = len(base)
|
|
3973
|
+
|
|
3974
|
+
parent_generators = <WordPermutation **> sig_malloc(len(aut_gp_gens) * sizeof(WordPermutation*))
|
|
3975
|
+
temp_basis = <codeword *> sig_malloc(self.radix * sizeof(codeword))
|
|
3976
|
+
|
|
3977
|
+
output = []
|
|
3978
|
+
|
|
3979
|
+
for i in range(len(aut_gp_gens)):
|
|
3980
|
+
parent_generators[i] = create_word_perm(aut_gp_gens[i] + list(range(B.ncols, n)))
|
|
3981
|
+
|
|
3982
|
+
word = 0
|
|
3983
|
+
while ortho_basis[k] & (((<codeword>1) << B.ncols) - 1):
|
|
3984
|
+
k += 1
|
|
3985
|
+
j = k
|
|
3986
|
+
while ortho_basis[j]:
|
|
3987
|
+
word ^= ortho_basis[j]
|
|
3988
|
+
j += 1
|
|
3989
|
+
|
|
3990
|
+
log_2_radix = 0
|
|
3991
|
+
while ((<codeword>1) << log_2_radix) < <codeword>self.radix:
|
|
3992
|
+
log_2_radix += 1
|
|
3993
|
+
# now we assume (<codeword>1 << log_2_radix) == self.radix
|
|
3994
|
+
if k < log_2_radix:
|
|
3995
|
+
orb_chx_size = 0
|
|
3996
|
+
else:
|
|
3997
|
+
orb_chx_size = k - log_2_radix
|
|
3998
|
+
orbit_checks = <codeword *> sig_malloc(((<codeword>1) << orb_chx_size) * sizeof(codeword))
|
|
3999
|
+
if orbit_checks is NULL:
|
|
4000
|
+
raise MemoryError()
|
|
4001
|
+
for temp from 0 <= temp < ((<codeword>1) << orb_chx_size):
|
|
4002
|
+
orbit_checks[temp] = 0
|
|
4003
|
+
|
|
4004
|
+
combo = 0
|
|
4005
|
+
parity = 0
|
|
4006
|
+
gate = (<codeword>1 << B.nrows) - 1
|
|
4007
|
+
k_gate = (<codeword>1 << k) - 1
|
|
4008
|
+
nonzero_gate = ((<codeword>1 << (n-B.ncols)) - 1) << B.ncols
|
|
4009
|
+
radix_gate = (((<codeword>1) << log_2_radix) - 1)
|
|
4010
|
+
|
|
4011
|
+
while True:
|
|
4012
|
+
if nonzero_gate & word == nonzero_gate and \
|
|
4013
|
+
(ham_wts[word & 65535] + ham_wts[(word >> 16) & 65535]) % d == 0:
|
|
4014
|
+
temp = (word >> B.nrows) & ((<codeword>1 << k) - 1)
|
|
4015
|
+
if not orbit_checks[temp >> log_2_radix] & ((<codeword>1) << (temp & radix_gate)):
|
|
4016
|
+
B_aug = BinaryCode(B, word)
|
|
4017
|
+
aug_aut_gp_gens, aug_labeling, aug_size, aug_base = self._aut_gp_and_can_label(B_aug)
|
|
4018
|
+
|
|
4019
|
+
# check if (B, B_aug) ~ (m(B_aug), B_aug)
|
|
4020
|
+
|
|
4021
|
+
can_lab = create_word_perm(aug_labeling[:n])
|
|
4022
|
+
|
|
4023
|
+
can_lab_inv = create_inv_word_perm(can_lab)
|
|
4024
|
+
for j from 0 <= j < B_aug.nrows:
|
|
4025
|
+
temp_basis[j] = permute_word_by_wp(can_lab, B_aug.basis[j])
|
|
4026
|
+
|
|
4027
|
+
# row reduce to get canonical label
|
|
4028
|
+
i = 0
|
|
4029
|
+
j = 0
|
|
4030
|
+
while j < B_aug.nrows:
|
|
4031
|
+
ii = j
|
|
4032
|
+
while ii < B_aug.nrows and not temp_basis[ii] & (<codeword>1 << i):
|
|
4033
|
+
ii += 1
|
|
4034
|
+
if ii != B_aug.nrows:
|
|
4035
|
+
if ii != j:
|
|
4036
|
+
swap = temp_basis[ii]
|
|
4037
|
+
temp_basis[ii] = temp_basis[j]
|
|
4038
|
+
temp_basis[j] = swap
|
|
4039
|
+
for jj from 0 <= jj < j:
|
|
4040
|
+
if temp_basis[jj] & (<codeword>1 << i):
|
|
4041
|
+
temp_basis[jj] ^= temp_basis[j]
|
|
4042
|
+
for jj from j < jj < B_aug.nrows:
|
|
4043
|
+
if temp_basis[jj] & (<codeword>1 << i):
|
|
4044
|
+
temp_basis[jj] ^= temp_basis[j]
|
|
4045
|
+
j += 1
|
|
4046
|
+
i += 1
|
|
4047
|
+
# done row reduction
|
|
4048
|
+
|
|
4049
|
+
for j from 0 <= j < B.nrows:
|
|
4050
|
+
temp_basis[j] = permute_word_by_wp(can_lab_inv, temp_basis[j])
|
|
4051
|
+
from sage.matrix.constructor import matrix
|
|
4052
|
+
from sage.rings.integer_ring import ZZ
|
|
4053
|
+
from sage.groups.perm_gps.permgroup import PermutationGroup
|
|
4054
|
+
from sage.groups.perm_gps.constructor import PermutationGroupElement
|
|
4055
|
+
from sage.libs.gap.libgap import libgap
|
|
4056
|
+
rs = []
|
|
4057
|
+
for i from 0 <= i < B.nrows:
|
|
4058
|
+
r = []
|
|
4059
|
+
for j from 0 <= j < n:
|
|
4060
|
+
r.append((((<codeword>1)<<j)&temp_basis[i])>>j)
|
|
4061
|
+
rs.append(r)
|
|
4062
|
+
m = BinaryCode(matrix(ZZ, rs))
|
|
4063
|
+
|
|
4064
|
+
m_aut_gp_gens, m_labeling, m_size, m_base = self._aut_gp_and_can_label(m)
|
|
4065
|
+
if True: # size*factorial(n-B.ncols) == m_size:
|
|
4066
|
+
|
|
4067
|
+
if len(m_aut_gp_gens) == 0:
|
|
4068
|
+
aut_m = PermutationGroup([()])
|
|
4069
|
+
else:
|
|
4070
|
+
aut_m = PermutationGroup([PermutationGroupElement([a+1 for a in g]) for g in m_aut_gp_gens])
|
|
4071
|
+
|
|
4072
|
+
if len(aug_aut_gp_gens) == 0:
|
|
4073
|
+
aut_B_aug = libgap(PermutationGroup([()]))
|
|
4074
|
+
else:
|
|
4075
|
+
aut_B_aug = libgap(PermutationGroup([PermutationGroupElement([a+1 for a in g]) for g in aug_aut_gp_gens]))
|
|
4076
|
+
H = libgap(aut_m).Intersection2(aut_B_aug)
|
|
4077
|
+
rt_transversal = [[int(a) - 1 for a in g.ListPerm(n)] for g in aut_B_aug.RightTransversal(H) if not g.IsOne()]
|
|
4078
|
+
rt_transversal.append(list(range(n)))
|
|
4079
|
+
|
|
4080
|
+
bingo2 = 0
|
|
4081
|
+
for coset_rep in rt_transversal:
|
|
4082
|
+
hwp = create_word_perm(coset_rep)
|
|
4083
|
+
# dealloc_word_perm(gwp)
|
|
4084
|
+
bingo2 = 1
|
|
4085
|
+
for j from 0 <= j < B.nrows:
|
|
4086
|
+
temp = permute_word_by_wp(hwp, temp_basis[j])
|
|
4087
|
+
if temp != B.words[temp & gate]:
|
|
4088
|
+
bingo2 = 0
|
|
4089
|
+
dealloc_word_perm(hwp)
|
|
4090
|
+
break
|
|
4091
|
+
if bingo2:
|
|
4092
|
+
dealloc_word_perm(hwp)
|
|
4093
|
+
break
|
|
4094
|
+
if bingo2:
|
|
4095
|
+
from sage.matrix.constructor import matrix
|
|
4096
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
4097
|
+
M = matrix(GF(2), B_aug.nrows, B_aug.ncols)
|
|
4098
|
+
for i from 0 <= i < B_aug.ncols:
|
|
4099
|
+
for j from 0 <= j < B_aug.nrows:
|
|
4100
|
+
M[j,i] = B_aug.is_one(1 << j, i)
|
|
4101
|
+
output.append(M)
|
|
4102
|
+
dealloc_word_perm(can_lab)
|
|
4103
|
+
dealloc_word_perm(can_lab_inv)
|
|
4104
|
+
# ...
|
|
4105
|
+
|
|
4106
|
+
orbits = [word]
|
|
4107
|
+
j = 0
|
|
4108
|
+
while j < len(orbits):
|
|
4109
|
+
for i from 0 <= i < len(aut_gp_gens):
|
|
4110
|
+
temp = <codeword> orbits[j]
|
|
4111
|
+
temp = permute_word_by_wp(parent_generators[i], temp)
|
|
4112
|
+
temp ^= B.words[temp & gate]
|
|
4113
|
+
if temp not in orbits:
|
|
4114
|
+
orbits.append(temp)
|
|
4115
|
+
j += 1
|
|
4116
|
+
for temp in orbits:
|
|
4117
|
+
temp = (temp >> B.nrows) & k_gate
|
|
4118
|
+
orbit_checks[temp >> log_2_radix] |= ((<codeword>1) << (temp & radix_gate))
|
|
4119
|
+
|
|
4120
|
+
parity ^= 1
|
|
4121
|
+
i = 0
|
|
4122
|
+
if not parity:
|
|
4123
|
+
while not combo & (1 << i):
|
|
4124
|
+
i += 1
|
|
4125
|
+
i += 1
|
|
4126
|
+
if i == k:
|
|
4127
|
+
break
|
|
4128
|
+
else:
|
|
4129
|
+
combo ^= (1 << i)
|
|
4130
|
+
word ^= ortho_basis[i]
|
|
4131
|
+
|
|
4132
|
+
for i from 0 <= i < len(aut_gp_gens):
|
|
4133
|
+
dealloc_word_perm(parent_generators[i])
|
|
4134
|
+
sig_free(B_can_lab)
|
|
4135
|
+
sig_free(parent_generators)
|
|
4136
|
+
sig_free(orbit_checks)
|
|
4137
|
+
sig_free(ortho_basis)
|
|
4138
|
+
sig_free(temp_basis)
|
|
4139
|
+
return output
|