passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.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 +808 -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-0cd532bd.so.1 +0 -0
- passagemath_modules.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-42cda06f.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-d8ebe4b5.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
- passagemath_modules.libs/libquadmath-bb76a5fc.so.0.0.0 +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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-x86_64-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-x86_64-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-x86_64-linux-musl.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-x86_64-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-x86_64-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,2344 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
"""
|
|
3
|
+
Basis exchange matroids
|
|
4
|
+
|
|
5
|
+
:class:`BasisExchangeMatroid <sage.matroids.basis_exchange_matroid.BasisExchangeMatroid>`
|
|
6
|
+
is an abstract class implementing default matroid functionality in terms of
|
|
7
|
+
basis exchange. Several concrete matroid classes are subclasses of this. They
|
|
8
|
+
have the following methods in addition to the ones provided by the parent
|
|
9
|
+
class :mod:`Matroid <sage.matroids.matroid>`.
|
|
10
|
+
|
|
11
|
+
- :func:`bases_count() <sage.matroids.basis_exchange_matroid.BasisExchangeMatroid.bases_count>`
|
|
12
|
+
- :func:`groundset_list() <sage.matroids.basis_exchange_matroid.BasisExchangeMatroid.groundset_list>`
|
|
13
|
+
|
|
14
|
+
AUTHORS:
|
|
15
|
+
|
|
16
|
+
- Rudi Pendavingh, Stefan van Zwam (2013-04-01): initial version
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
# ****************************************************************************
|
|
20
|
+
# Copyright (C) 2013 Rudi Pendavingh <rudi.pendavingh@gmail.com>
|
|
21
|
+
# Copyright (C) 2013 Stefan van Zwam <stefanvanzwam@gmail.com>
|
|
22
|
+
#
|
|
23
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
24
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
25
|
+
# the License, or (at your option) any later version.
|
|
26
|
+
# https://www.gnu.org/licenses/
|
|
27
|
+
# ****************************************************************************
|
|
28
|
+
|
|
29
|
+
from sage.matroids.matroid cimport Matroid
|
|
30
|
+
from sage.matroids.set_system cimport SetSystem
|
|
31
|
+
from sage.data_structures.bitset_base cimport *
|
|
32
|
+
|
|
33
|
+
cdef class BasisExchangeMatroid(Matroid):
|
|
34
|
+
r"""
|
|
35
|
+
Class BasisExchangeMatroid is a virtual class that derives from Matroid.
|
|
36
|
+
It implements each of the elementary matroid methods
|
|
37
|
+
(:meth:`rank() <sage.matroids.matroid.Matroid.rank>`,
|
|
38
|
+
:meth:`max_independent() <sage.matroids.matroid.Matroid.max_independent>`,
|
|
39
|
+
:meth:`circuit() <sage.matroids.matroid.Matroid.circuit>`,
|
|
40
|
+
:meth:`closure() <sage.matroids.matroid.Matroid.closure>` etc.),
|
|
41
|
+
essentially by crawling the base exchange graph of the matroid. This is
|
|
42
|
+
the graph whose vertices are the bases of the matroid, two bases being
|
|
43
|
+
adjacent in the graph if their symmetric difference has 2 members.
|
|
44
|
+
|
|
45
|
+
This base exchange graph is not stored as such, but should be provided
|
|
46
|
+
implicitly by the child class in the form of two methods
|
|
47
|
+
``_is_exchange_pair(x, y)`` and ``_exchange(x, y)``, as well as an
|
|
48
|
+
initial basis. At any moment, BasisExchangeMatroid keeps a current basis
|
|
49
|
+
`B`. The method ``_is_exchange_pair(x, y)`` should return a boolean
|
|
50
|
+
indicating whether `B - x + y` is a basis. The method ``_exchange(x, y)``
|
|
51
|
+
is called when the current basis `B` is replaced by said `B-x + y`. It is
|
|
52
|
+
up to the child class to update its internal data structure to make
|
|
53
|
+
information relative to the new basis more accessible. For instance, a
|
|
54
|
+
linear matroid would perform a row reduction to make the column labeled by
|
|
55
|
+
`y` a standard basis vector (and therefore the columns indexed by `B-x+y`
|
|
56
|
+
would form an identity matrix).
|
|
57
|
+
|
|
58
|
+
Each of the elementary matroid methods has a straightforward greedy-type
|
|
59
|
+
implementation in terms of these two methods. For example, given a subset
|
|
60
|
+
`F` of the groundset, one can step to a basis `B` over the edges of the
|
|
61
|
+
base exchange graph which has maximal intersection with `F`, in each step
|
|
62
|
+
increasing the intersection of the current `B` with `F`. Then one computes
|
|
63
|
+
the rank of `F` as the cardinality of the intersection of `F` and `B`.
|
|
64
|
+
|
|
65
|
+
The following matroid classes can/will implement their oracle efficiently
|
|
66
|
+
by deriving from ``BasisExchangeMatroid``:
|
|
67
|
+
|
|
68
|
+
- :class:`BasisMatroid <sage.matroids.basis_matroid.BasisMatroid>`: keeps
|
|
69
|
+
a list of all bases.
|
|
70
|
+
|
|
71
|
+
- ``_is_exchange_pair(x, y)`` reduces to a query whether `B - x + y`
|
|
72
|
+
is a basis.
|
|
73
|
+
- ``_exchange(x, y)`` has no work to do.
|
|
74
|
+
|
|
75
|
+
- :class:`LinearMatroid <sage.matroids.linear_matroid.LinearMatroid>`:
|
|
76
|
+
keeps a matrix representation `A` of the matroid so that `A[B] = I`.
|
|
77
|
+
|
|
78
|
+
- ``_is_exchange_pair(x, y)`` reduces to testing whether `A[r, y]`
|
|
79
|
+
is nonzero, where `A[r, x]=1`.
|
|
80
|
+
- ``_exchange(x, y)`` should modify the matrix so that `A[B - x + y]`
|
|
81
|
+
becomes `I`, which means pivoting on `A[r, y]`.
|
|
82
|
+
|
|
83
|
+
- ``TransversalMatroid`` (not yet implemented): If `A` is a set of subsets
|
|
84
|
+
of `E`, then `I` is independent if it is a system of distinct
|
|
85
|
+
representatives of `A`, i.e. if `I` is covered by a matching of an
|
|
86
|
+
appropriate bipartite graph `G`, with color classes `A` and `E` and an
|
|
87
|
+
edge `(A_i,e)` if `e` is in the subset `A_i`. At any time you keep a
|
|
88
|
+
maximum matching `M` of `G` covering the current basis `B`.
|
|
89
|
+
|
|
90
|
+
- ``_is_exchange_pair(x, y)`` checks for the existence of an
|
|
91
|
+
`M`-alternating path `P` from `y` to `x`.
|
|
92
|
+
- ``_exchange(x, y)`` replaces `M` by the symmetric difference of
|
|
93
|
+
`M` and `E(P)`.
|
|
94
|
+
|
|
95
|
+
- ``AlgebraicMatroid`` (not yet implemented): keeps a list of polynomials
|
|
96
|
+
in variables `E - B + e` for each variable `e` in `B`.
|
|
97
|
+
|
|
98
|
+
- ``_is_exchange_pair(x, y)`` checks whether the polynomial that
|
|
99
|
+
relates `y` to `E-B` uses `x`.
|
|
100
|
+
- ``_exchange(x, y)`` make new list of polynomials by computing
|
|
101
|
+
resultants.
|
|
102
|
+
|
|
103
|
+
All but the first of the above matroids are algebraic, and all
|
|
104
|
+
implementations specializations of the algebraic one.
|
|
105
|
+
|
|
106
|
+
BasisExchangeMatroid internally renders subsets of the groundset as
|
|
107
|
+
bitsets. It provides optimized methods for enumerating bases, nonbases,
|
|
108
|
+
flats, circuits, etc.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def __init__(self, groundset, basis=None, rank=None):
|
|
112
|
+
"""
|
|
113
|
+
Construct a BasisExchangeMatroid.
|
|
114
|
+
|
|
115
|
+
A BasisExchangeMatroid is a virtual class. It is unlikely that you
|
|
116
|
+
want to create a BasisExchangeMatroid from the command line. See the
|
|
117
|
+
class docstring for
|
|
118
|
+
:class:`BasisExchangeMatroid <sage.matroids.basis_exchange_matroid.BasisExchangeMatroid>`.
|
|
119
|
+
|
|
120
|
+
INPUT:
|
|
121
|
+
|
|
122
|
+
- ``groundset`` -- set
|
|
123
|
+
- ``basis`` -- subset of groundset (default: ``None``)
|
|
124
|
+
- ``rank`` -- integer (default: ``None``)
|
|
125
|
+
|
|
126
|
+
This initializer sets up a correspondence between elements of
|
|
127
|
+
``groundset`` and ``range(len(groundset))``. ``BasisExchangeMatroid``
|
|
128
|
+
uses this correspondence for encoding of subsets of the groundset as
|
|
129
|
+
bitpacked sets of integers --- see ``_pack()`` and ``__unpack()``. In
|
|
130
|
+
general, methods of ``BasisExchangeMatroid`` having a name starting
|
|
131
|
+
with two underscores deal with such encoded subsets.
|
|
132
|
+
|
|
133
|
+
A second task of this initializer is to store the rank and initialize
|
|
134
|
+
the 'current' basis.
|
|
135
|
+
|
|
136
|
+
EXAMPLES::
|
|
137
|
+
|
|
138
|
+
sage: from sage.matroids.basis_exchange_matroid import BasisExchangeMatroid
|
|
139
|
+
sage: M = BasisExchangeMatroid(groundset='abcdef', basis='abc')
|
|
140
|
+
sage: sorted(M.groundset())
|
|
141
|
+
['a', 'b', 'c', 'd', 'e', 'f']
|
|
142
|
+
sage: sorted(M.basis())
|
|
143
|
+
['a', 'b', 'c']
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
TESTS::
|
|
147
|
+
|
|
148
|
+
sage: from sage.matroids.advanced import *
|
|
149
|
+
sage: M = BasisExchangeMatroid(groundset=[1, 2, 3], rank=2)
|
|
150
|
+
sage: TestSuite(M).run(skip='_test_pickling')
|
|
151
|
+
|
|
152
|
+
.. NOTE::
|
|
153
|
+
|
|
154
|
+
This is an abstract base class, without a data structure, so no
|
|
155
|
+
pickling mechanism was implemented.
|
|
156
|
+
"""
|
|
157
|
+
self._groundset_size = len(groundset)
|
|
158
|
+
self._bitset_size = max(self._groundset_size, 1)
|
|
159
|
+
if basis is None:
|
|
160
|
+
self._matroid_rank = rank
|
|
161
|
+
else:
|
|
162
|
+
self._matroid_rank = len(basis)
|
|
163
|
+
bitset_init(self._current_basis, self._bitset_size)
|
|
164
|
+
bitset_init(self._inside, self._bitset_size)
|
|
165
|
+
bitset_init(self._outside, self._bitset_size)
|
|
166
|
+
bitset_init(self._input, self._bitset_size)
|
|
167
|
+
bitset_init(self._input2, self._bitset_size)
|
|
168
|
+
bitset_init(self._output, self._bitset_size)
|
|
169
|
+
bitset_init(self._temp, self._bitset_size)
|
|
170
|
+
|
|
171
|
+
self._groundset = frozenset(groundset)
|
|
172
|
+
if not isinstance(groundset, tuple):
|
|
173
|
+
self._E = tuple(groundset)
|
|
174
|
+
else:
|
|
175
|
+
self._E = groundset
|
|
176
|
+
self._idx = {}
|
|
177
|
+
cdef long i
|
|
178
|
+
for i in range(self._groundset_size):
|
|
179
|
+
self._idx[self._E[i]] = i
|
|
180
|
+
|
|
181
|
+
if basis is not None:
|
|
182
|
+
self._pack(self._current_basis, frozenset(basis))
|
|
183
|
+
|
|
184
|
+
def __dealloc__(self):
|
|
185
|
+
bitset_free(self._current_basis)
|
|
186
|
+
bitset_free(self._inside)
|
|
187
|
+
bitset_free(self._outside)
|
|
188
|
+
bitset_free(self._input)
|
|
189
|
+
bitset_free(self._input2)
|
|
190
|
+
bitset_free(self._output)
|
|
191
|
+
bitset_free(self._temp)
|
|
192
|
+
|
|
193
|
+
cdef _relabel(self, mapping):
|
|
194
|
+
"""
|
|
195
|
+
Relabel each element `e` as ``mapping[e]``, where ``mapping`` is a
|
|
196
|
+
given injective map.
|
|
197
|
+
|
|
198
|
+
INPUT:
|
|
199
|
+
|
|
200
|
+
- ``mapping`` -- a Python object such that ``mapping[e]`` is the new
|
|
201
|
+
label of `e`
|
|
202
|
+
|
|
203
|
+
OUTPUT: none
|
|
204
|
+
|
|
205
|
+
.. NOTE::
|
|
206
|
+
|
|
207
|
+
For internal use. Matroids are immutable but this method does
|
|
208
|
+
modify the matroid. The use of this method will only be safe in
|
|
209
|
+
very limited circumstances, such as perhaps on a fresh copy of a
|
|
210
|
+
matroid.
|
|
211
|
+
"""
|
|
212
|
+
cdef long i
|
|
213
|
+
E = []
|
|
214
|
+
for i in range(self._groundset_size):
|
|
215
|
+
try:
|
|
216
|
+
E.append(mapping[self._E[i]])
|
|
217
|
+
except LookupError:
|
|
218
|
+
E.append(self._E[i])
|
|
219
|
+
self._E = tuple(E)
|
|
220
|
+
self._groundset = frozenset(E)
|
|
221
|
+
|
|
222
|
+
self._idx = {}
|
|
223
|
+
for i in range(self._groundset_size):
|
|
224
|
+
self._idx[self._E[i]] = i
|
|
225
|
+
|
|
226
|
+
if self._weak_partition_var:
|
|
227
|
+
self._weak_partition_var._relabel(mapping)
|
|
228
|
+
|
|
229
|
+
if self._strong_partition_var:
|
|
230
|
+
self._strong_partition_var._relabel(mapping)
|
|
231
|
+
if self._heuristic_partition_var:
|
|
232
|
+
self._heuristic_partition_var._relabel(mapping)
|
|
233
|
+
|
|
234
|
+
# the engine
|
|
235
|
+
|
|
236
|
+
cdef _pack(self, bitset_t I, F):
|
|
237
|
+
"""
|
|
238
|
+
Encode a subset F of the groundset into a bitpacked set of integers.
|
|
239
|
+
"""
|
|
240
|
+
bitset_clear(I)
|
|
241
|
+
for f in F:
|
|
242
|
+
bitset_add(I, <mp_bitcnt_t> self._idx[f])
|
|
243
|
+
|
|
244
|
+
cdef __unpack(self, bitset_t I):
|
|
245
|
+
"""
|
|
246
|
+
Unencode a bitpacked set of integers to a subset of the groundset.
|
|
247
|
+
"""
|
|
248
|
+
cdef long i
|
|
249
|
+
F = set()
|
|
250
|
+
i = bitset_first(I)
|
|
251
|
+
while i >= 0:
|
|
252
|
+
F.add(self._E[i])
|
|
253
|
+
i = bitset_next(I, i + 1)
|
|
254
|
+
return frozenset(F)
|
|
255
|
+
|
|
256
|
+
# this method needs to be overridden by child class
|
|
257
|
+
cdef bint _is_exchange_pair(self, long x, long y) except -1:
|
|
258
|
+
"""
|
|
259
|
+
Test if current_basis-x + y is a basis.
|
|
260
|
+
"""
|
|
261
|
+
raise NotImplementedError
|
|
262
|
+
|
|
263
|
+
# if this method is overridden by a child class, the child class needs to call this method
|
|
264
|
+
cdef int _exchange(self, long x, long y) except -1:
|
|
265
|
+
"""
|
|
266
|
+
Put ``current_basis <-- current_basis-x + y``.
|
|
267
|
+
"""
|
|
268
|
+
bitset_discard(self._current_basis, x)
|
|
269
|
+
bitset_add(self._current_basis, y)
|
|
270
|
+
|
|
271
|
+
cdef int _move(self, bitset_t X, bitset_t Y) except -1:
|
|
272
|
+
"""
|
|
273
|
+
Change ``current_basis`` to minimize intersection with ``X``, maximize
|
|
274
|
+
intersection with ``Y``.
|
|
275
|
+
"""
|
|
276
|
+
cdef long x, y
|
|
277
|
+
x = bitset_first(X)
|
|
278
|
+
while x >= 0:
|
|
279
|
+
y = bitset_first(Y)
|
|
280
|
+
while y >= 0:
|
|
281
|
+
if self._is_exchange_pair(x, y):
|
|
282
|
+
self._exchange(x, y)
|
|
283
|
+
bitset_discard(Y, y)
|
|
284
|
+
bitset_discard(X, x)
|
|
285
|
+
if bitset_isempty(Y):
|
|
286
|
+
return 0
|
|
287
|
+
break
|
|
288
|
+
else:
|
|
289
|
+
y = bitset_next(Y, y + 1)
|
|
290
|
+
x = bitset_next(X, x + 1)
|
|
291
|
+
|
|
292
|
+
cdef __fundamental_cocircuit(self, bitset_t C, long x):
|
|
293
|
+
"""
|
|
294
|
+
Return the unique cocircuit that meets ``self._current_basis`` in
|
|
295
|
+
exactly element ``x``.
|
|
296
|
+
"""
|
|
297
|
+
cdef long y
|
|
298
|
+
bitset_clear(C)
|
|
299
|
+
bitset_complement(self._temp, self._current_basis)
|
|
300
|
+
y = bitset_first(self._temp)
|
|
301
|
+
while y >= 0:
|
|
302
|
+
if self._is_exchange_pair(x, y):
|
|
303
|
+
bitset_add(C, y)
|
|
304
|
+
y = bitset_next(self._temp, y + 1)
|
|
305
|
+
bitset_add(C, x)
|
|
306
|
+
|
|
307
|
+
cdef __fundamental_circuit(self, bitset_t C, long y):
|
|
308
|
+
"""
|
|
309
|
+
Return the unique circuit contained in ``self._current_basis`` union ``y``.
|
|
310
|
+
"""
|
|
311
|
+
cdef long x
|
|
312
|
+
bitset_clear(C)
|
|
313
|
+
x = bitset_first(self._current_basis)
|
|
314
|
+
while x >= 0:
|
|
315
|
+
if self._is_exchange_pair(x, y):
|
|
316
|
+
bitset_add(C, x)
|
|
317
|
+
x = bitset_next(self._current_basis, x + 1)
|
|
318
|
+
bitset_add(C, y)
|
|
319
|
+
|
|
320
|
+
cdef __max_independent(self, bitset_t R, bitset_t F):
|
|
321
|
+
"""
|
|
322
|
+
Bitpacked version of ``max_independent``.
|
|
323
|
+
"""
|
|
324
|
+
bitset_difference(self._inside, self._current_basis, F)
|
|
325
|
+
bitset_difference(self._outside, F, self._current_basis)
|
|
326
|
+
self._move(self._inside, self._outside)
|
|
327
|
+
bitset_intersection(R, self._current_basis, F)
|
|
328
|
+
|
|
329
|
+
cdef __circuit(self, bitset_t R, bitset_t F):
|
|
330
|
+
"""
|
|
331
|
+
Bitpacked version of ``circuit``.
|
|
332
|
+
"""
|
|
333
|
+
bitset_difference(self._inside, self._current_basis, F)
|
|
334
|
+
bitset_difference(self._outside, F, self._current_basis)
|
|
335
|
+
cdef long x, y
|
|
336
|
+
y = bitset_first(self._outside)
|
|
337
|
+
if y < 0:
|
|
338
|
+
raise ValueError('no circuit in independent set.')
|
|
339
|
+
while y >= 0:
|
|
340
|
+
x = bitset_first(self._inside)
|
|
341
|
+
while x >= 0:
|
|
342
|
+
if self._is_exchange_pair(x, y):
|
|
343
|
+
self._exchange(x, y)
|
|
344
|
+
bitset_discard(self._outside, y)
|
|
345
|
+
bitset_discard(self._inside, x)
|
|
346
|
+
if bitset_isempty(self._outside):
|
|
347
|
+
raise ValueError('no circuit in independent set.')
|
|
348
|
+
break
|
|
349
|
+
else:
|
|
350
|
+
x = bitset_next(self._inside, x + 1)
|
|
351
|
+
if x == -1:
|
|
352
|
+
self.__fundamental_circuit(R, y)
|
|
353
|
+
return
|
|
354
|
+
y = bitset_next(self._outside, y + 1)
|
|
355
|
+
|
|
356
|
+
cdef __closure(self, bitset_t R, bitset_t F):
|
|
357
|
+
"""
|
|
358
|
+
Bitpacked version of ``closure``.
|
|
359
|
+
"""
|
|
360
|
+
bitset_difference(self._inside, self._current_basis, F)
|
|
361
|
+
bitset_difference(self._outside, F, self._current_basis)
|
|
362
|
+
self._move(self._inside, self._outside)
|
|
363
|
+
bitset_set_first_n(R, self._groundset_size)
|
|
364
|
+
cdef long x = bitset_first(self._inside)
|
|
365
|
+
while x >= 0:
|
|
366
|
+
self.__fundamental_cocircuit(F, x)
|
|
367
|
+
bitset_difference(R, R, F)
|
|
368
|
+
x = bitset_next(self._inside, x + 1)
|
|
369
|
+
|
|
370
|
+
cdef __max_coindependent(self, bitset_t R, bitset_t F):
|
|
371
|
+
"""
|
|
372
|
+
Bitpacked version of ``max_coindependent``.
|
|
373
|
+
"""
|
|
374
|
+
bitset_complement(R, F)
|
|
375
|
+
bitset_difference(self._inside, self._current_basis, R)
|
|
376
|
+
bitset_difference(self._outside, R, self._current_basis)
|
|
377
|
+
self._move(self._inside, self._outside)
|
|
378
|
+
bitset_difference(R, F, self._current_basis)
|
|
379
|
+
|
|
380
|
+
cdef __cocircuit(self, bitset_t R, bitset_t F):
|
|
381
|
+
"""
|
|
382
|
+
Bitpacked version of ``cocircuit``.
|
|
383
|
+
"""
|
|
384
|
+
bitset_complement(R, F)
|
|
385
|
+
bitset_difference(self._inside, self._current_basis, R)
|
|
386
|
+
bitset_difference(self._outside, R, self._current_basis)
|
|
387
|
+
cdef long x, y
|
|
388
|
+
x = bitset_first(self._inside)
|
|
389
|
+
if x < 0:
|
|
390
|
+
raise ValueError('no cocircuit in coindependent set.')
|
|
391
|
+
while x >= 0:
|
|
392
|
+
y = bitset_first(self._outside)
|
|
393
|
+
while y >= 0:
|
|
394
|
+
if self._is_exchange_pair(x, y):
|
|
395
|
+
self._exchange(x, y)
|
|
396
|
+
bitset_discard(self._outside, y)
|
|
397
|
+
bitset_discard(self._inside, x)
|
|
398
|
+
if bitset_isempty(self._inside):
|
|
399
|
+
raise ValueError('no cocircuit in coindependent set.')
|
|
400
|
+
break
|
|
401
|
+
else:
|
|
402
|
+
y = bitset_next(self._outside, y + 1)
|
|
403
|
+
if y == -1:
|
|
404
|
+
self.__fundamental_cocircuit(R, x)
|
|
405
|
+
return
|
|
406
|
+
x = bitset_next(self._inside, x + 1)
|
|
407
|
+
|
|
408
|
+
cdef _coclosure_internal(self, bitset_t R, bitset_t F):
|
|
409
|
+
"""
|
|
410
|
+
Bitpacked version of ``closure``.
|
|
411
|
+
"""
|
|
412
|
+
bitset_complement(R, F)
|
|
413
|
+
bitset_difference(self._inside, self._current_basis, R)
|
|
414
|
+
bitset_difference(self._outside, R, self._current_basis)
|
|
415
|
+
self._move(self._inside, self._outside)
|
|
416
|
+
bitset_set_first_n(R, self._groundset_size)
|
|
417
|
+
cdef long y = bitset_first(self._outside)
|
|
418
|
+
while y >= 0:
|
|
419
|
+
self.__fundamental_circuit(F, y)
|
|
420
|
+
bitset_difference(R, R, F)
|
|
421
|
+
y = bitset_next(self._outside, y + 1)
|
|
422
|
+
|
|
423
|
+
cdef __augment(self, bitset_t R, bitset_t X, bitset_t Y):
|
|
424
|
+
"""
|
|
425
|
+
Bitpacked version of ``augment``.
|
|
426
|
+
"""
|
|
427
|
+
bitset_difference(self._inside, self._current_basis, X)
|
|
428
|
+
bitset_difference(self._outside, X, self._current_basis)
|
|
429
|
+
self._move(self._inside, self._outside)
|
|
430
|
+
bitset_difference(self._inside, self._inside, Y)
|
|
431
|
+
bitset_difference(self._outside, Y, self._current_basis)
|
|
432
|
+
self._move(self._inside, self._outside)
|
|
433
|
+
bitset_intersection(R, self._current_basis, Y)
|
|
434
|
+
|
|
435
|
+
cdef bint __is_independent(self, bitset_t F) except -1:
|
|
436
|
+
"""
|
|
437
|
+
Bitpacked version of ``is_independent``.
|
|
438
|
+
"""
|
|
439
|
+
bitset_difference(self._inside, self._current_basis, F)
|
|
440
|
+
bitset_difference(self._outside, F, self._current_basis)
|
|
441
|
+
self._move(self._inside, self._outside)
|
|
442
|
+
return bitset_isempty(self._outside)
|
|
443
|
+
|
|
444
|
+
cdef __move_current_basis(self, bitset_t X, bitset_t Y):
|
|
445
|
+
"""
|
|
446
|
+
Bitpacked version of ``_move_current_basis``.
|
|
447
|
+
"""
|
|
448
|
+
bitset_difference(self._inside, self._current_basis, X)
|
|
449
|
+
bitset_difference(self._outside, X, self._current_basis)
|
|
450
|
+
self._move(self._inside, self._outside)
|
|
451
|
+
bitset_intersection(self._inside, self._current_basis, Y)
|
|
452
|
+
bitset_complement(self._outside, self._current_basis)
|
|
453
|
+
bitset_difference(self._outside, self._outside, Y)
|
|
454
|
+
self._move(self._inside, self._outside)
|
|
455
|
+
|
|
456
|
+
# functions for derived classes and for parent class
|
|
457
|
+
|
|
458
|
+
cdef bint _set_current_basis(self, F) noexcept:
|
|
459
|
+
"""
|
|
460
|
+
Set ``_current_basis`` to subset of the groundset ``F``.
|
|
461
|
+
"""
|
|
462
|
+
self._pack(self._input, F)
|
|
463
|
+
bitset_difference(self._inside, self._current_basis, self._input)
|
|
464
|
+
bitset_difference(self._outside, self._input, self._current_basis)
|
|
465
|
+
self._move(self._inside, self._outside)
|
|
466
|
+
return bitset_isempty(self._outside) and bitset_isempty(self._inside)
|
|
467
|
+
|
|
468
|
+
# groundset and full_rank
|
|
469
|
+
|
|
470
|
+
cpdef frozenset groundset(self):
|
|
471
|
+
"""
|
|
472
|
+
Return the groundset of the matroid.
|
|
473
|
+
|
|
474
|
+
The groundset is the set of elements that comprise the matroid.
|
|
475
|
+
|
|
476
|
+
OUTPUT: set
|
|
477
|
+
|
|
478
|
+
EXAMPLES::
|
|
479
|
+
|
|
480
|
+
sage: M = matroids.catalog.Fano()
|
|
481
|
+
sage: sorted(M.groundset())
|
|
482
|
+
['a', 'b', 'c', 'd', 'e', 'f', 'g']
|
|
483
|
+
"""
|
|
484
|
+
return self._groundset
|
|
485
|
+
|
|
486
|
+
cpdef list groundset_list(self):
|
|
487
|
+
"""
|
|
488
|
+
Return a list of elements of the groundset of the matroid.
|
|
489
|
+
|
|
490
|
+
The order of the list does not change between calls.
|
|
491
|
+
|
|
492
|
+
OUTPUT: list
|
|
493
|
+
|
|
494
|
+
.. SEEALSO::
|
|
495
|
+
|
|
496
|
+
:meth:`M.groundset() <sage.matroids.basis_exchange_matroid.BasisExchangeMatroid.groundset>`
|
|
497
|
+
|
|
498
|
+
EXAMPLES::
|
|
499
|
+
|
|
500
|
+
sage: M = matroids.catalog.Fano()
|
|
501
|
+
sage: type(M.groundset())
|
|
502
|
+
<... 'frozenset'>
|
|
503
|
+
sage: type(M.groundset_list())
|
|
504
|
+
<... 'list'>
|
|
505
|
+
sage: sorted(M.groundset_list())
|
|
506
|
+
['a', 'b', 'c', 'd', 'e', 'f', 'g']
|
|
507
|
+
|
|
508
|
+
sage: E = M.groundset_list()
|
|
509
|
+
sage: E.remove('a')
|
|
510
|
+
sage: sorted(M.groundset_list())
|
|
511
|
+
['a', 'b', 'c', 'd', 'e', 'f', 'g']
|
|
512
|
+
"""
|
|
513
|
+
return list(self._E)
|
|
514
|
+
|
|
515
|
+
def __len__(self):
|
|
516
|
+
"""
|
|
517
|
+
Return the size of the groundset.
|
|
518
|
+
|
|
519
|
+
EXAMPLES::
|
|
520
|
+
|
|
521
|
+
sage: M = matroids.catalog.Fano()
|
|
522
|
+
sage: len(M)
|
|
523
|
+
7
|
|
524
|
+
sage: len(M.groundset())
|
|
525
|
+
7
|
|
526
|
+
"""
|
|
527
|
+
return self._groundset_size
|
|
528
|
+
|
|
529
|
+
cpdef full_rank(self):
|
|
530
|
+
r"""
|
|
531
|
+
Return the rank of the matroid.
|
|
532
|
+
|
|
533
|
+
The *rank* of the matroid is the size of the largest independent
|
|
534
|
+
subset of the groundset.
|
|
535
|
+
|
|
536
|
+
OUTPUT: integer
|
|
537
|
+
|
|
538
|
+
EXAMPLES::
|
|
539
|
+
|
|
540
|
+
sage: M = matroids.catalog.Fano()
|
|
541
|
+
sage: M.full_rank()
|
|
542
|
+
3
|
|
543
|
+
sage: M.dual().full_rank()
|
|
544
|
+
4
|
|
545
|
+
"""
|
|
546
|
+
return self._matroid_rank
|
|
547
|
+
|
|
548
|
+
cpdef full_corank(self):
|
|
549
|
+
r"""
|
|
550
|
+
Return the corank of the matroid.
|
|
551
|
+
|
|
552
|
+
The *corank* of the matroid equals the rank of the dual matroid. It is
|
|
553
|
+
given by ``M.size() - M.full_rank()``.
|
|
554
|
+
|
|
555
|
+
OUTPUT: integer
|
|
556
|
+
|
|
557
|
+
.. SEEALSO::
|
|
558
|
+
|
|
559
|
+
:meth:`M.dual() <sage.matroids.matroid.Matroid.dual>`,
|
|
560
|
+
:meth:`M.full_rank() <sage.matroids.basis_exchange_matroid.BasisExchangeMatroid.full_rank>`
|
|
561
|
+
|
|
562
|
+
EXAMPLES::
|
|
563
|
+
|
|
564
|
+
sage: M = matroids.catalog.Fano()
|
|
565
|
+
sage: M.full_corank()
|
|
566
|
+
4
|
|
567
|
+
sage: M.dual().full_corank()
|
|
568
|
+
3
|
|
569
|
+
"""
|
|
570
|
+
return self._groundset_size - self._matroid_rank
|
|
571
|
+
|
|
572
|
+
# matroid oracles
|
|
573
|
+
|
|
574
|
+
cpdef basis(self):
|
|
575
|
+
r"""
|
|
576
|
+
Return an arbitrary basis of the matroid.
|
|
577
|
+
|
|
578
|
+
A *basis* is an inclusionwise maximal independent set.
|
|
579
|
+
|
|
580
|
+
.. NOTE::
|
|
581
|
+
|
|
582
|
+
The output of this method can change in between calls. It reflects
|
|
583
|
+
the internal state of the matroid. This state is updated by lots
|
|
584
|
+
of methods, including the method ``M._move_current_basis()``.
|
|
585
|
+
|
|
586
|
+
OUTPUT: set of elements
|
|
587
|
+
|
|
588
|
+
EXAMPLES::
|
|
589
|
+
|
|
590
|
+
sage: M = matroids.catalog.Fano()
|
|
591
|
+
sage: sorted(M.basis())
|
|
592
|
+
['a', 'b', 'c']
|
|
593
|
+
sage: M.rank('cd')
|
|
594
|
+
2
|
|
595
|
+
sage: sorted(M.basis())
|
|
596
|
+
['a', 'c', 'd']
|
|
597
|
+
"""
|
|
598
|
+
return self.__unpack(self._current_basis)
|
|
599
|
+
|
|
600
|
+
cpdef _move_current_basis(self, X, Y):
|
|
601
|
+
"""
|
|
602
|
+
Change current basis so that intersection with X is maximized,
|
|
603
|
+
intersection with Y is minimized.
|
|
604
|
+
|
|
605
|
+
INPUT:
|
|
606
|
+
|
|
607
|
+
- ``X`` -- an object with Python's ``frozenset`` interface containing
|
|
608
|
+
a subset of ``self.groundset()``
|
|
609
|
+
- ``Y`` -- an object with Python's ``frozenset`` interface containing
|
|
610
|
+
a subset of ``self.groundset()``
|
|
611
|
+
|
|
612
|
+
OUTPUT: nothing
|
|
613
|
+
|
|
614
|
+
EXAMPLES::
|
|
615
|
+
|
|
616
|
+
sage: from sage.matroids.advanced import *
|
|
617
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
618
|
+
sage: sorted(M.basis())
|
|
619
|
+
['a', 'b', 'c', 'e']
|
|
620
|
+
sage: M._move_current_basis('ef', 'a')
|
|
621
|
+
sage: sorted(M.basis())
|
|
622
|
+
['b', 'c', 'e', 'f']
|
|
623
|
+
"""
|
|
624
|
+
self._pack(self._input, X)
|
|
625
|
+
self._pack(self._input2, Y)
|
|
626
|
+
self.__move_current_basis(self._input, self._input2)
|
|
627
|
+
|
|
628
|
+
cpdef frozenset _max_independent(self, frozenset F):
|
|
629
|
+
"""
|
|
630
|
+
Compute a maximal independent subset.
|
|
631
|
+
|
|
632
|
+
INPUT:
|
|
633
|
+
|
|
634
|
+
- ``F`` -- an object with Python's ``frozenset`` interface containing
|
|
635
|
+
a subset of ``self.groundset()``
|
|
636
|
+
|
|
637
|
+
OUTPUT: subset of ``F``
|
|
638
|
+
|
|
639
|
+
EXAMPLES::
|
|
640
|
+
|
|
641
|
+
sage: from sage.matroids.advanced import *
|
|
642
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
643
|
+
sage: sorted(M._max_independent(frozenset(['a', 'c', 'd', 'e', 'f'])))
|
|
644
|
+
['a', 'c', 'd', 'e']
|
|
645
|
+
|
|
646
|
+
.. NOTE::
|
|
647
|
+
|
|
648
|
+
This is an unguarded method. For the version that verifies if
|
|
649
|
+
the input is indeed a subset of the groundset,
|
|
650
|
+
see :meth:`<sage.matroids.matroid.Matroid.max_independent>`.
|
|
651
|
+
"""
|
|
652
|
+
self._pack(self._input, F)
|
|
653
|
+
self.__max_independent(self._output, self._input)
|
|
654
|
+
return self.__unpack(self._output)
|
|
655
|
+
|
|
656
|
+
cpdef int _rank(self, frozenset F) except? -1:
|
|
657
|
+
"""
|
|
658
|
+
Compute the rank of a subset of the groundset.
|
|
659
|
+
|
|
660
|
+
INPUT:
|
|
661
|
+
|
|
662
|
+
- ``F`` -- an object with Python's ``frozenset`` interface containing
|
|
663
|
+
a subset of ``self.groundset()``
|
|
664
|
+
|
|
665
|
+
OUTPUT: integer
|
|
666
|
+
|
|
667
|
+
EXAMPLES::
|
|
668
|
+
|
|
669
|
+
sage: from sage.matroids.advanced import *
|
|
670
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
671
|
+
sage: M._rank(frozenset(['a', 'c', 'd', 'e', 'f']))
|
|
672
|
+
4
|
|
673
|
+
|
|
674
|
+
.. NOTE::
|
|
675
|
+
|
|
676
|
+
This is an unguarded method. For the version that verifies if
|
|
677
|
+
the input is indeed a subset of the groundset,
|
|
678
|
+
see :meth:`<sage.matroids.matroid.Matroid.rank>`.
|
|
679
|
+
"""
|
|
680
|
+
self._pack(self._input, F)
|
|
681
|
+
self.__max_independent(self._output, self._input)
|
|
682
|
+
return bitset_len(self._output)
|
|
683
|
+
|
|
684
|
+
cpdef frozenset _circuit(self, frozenset F):
|
|
685
|
+
"""
|
|
686
|
+
Return a minimal dependent subset.
|
|
687
|
+
|
|
688
|
+
INPUT:
|
|
689
|
+
|
|
690
|
+
- ``F`` -- an object with Python's ``frozenset`` interface containing
|
|
691
|
+
a subset of ``self.groundset()``
|
|
692
|
+
|
|
693
|
+
OUTPUT: circuit contained in ``F``, if it exists; otherwise, an error
|
|
694
|
+
is raised
|
|
695
|
+
|
|
696
|
+
EXAMPLES::
|
|
697
|
+
|
|
698
|
+
sage: from sage.matroids.advanced import *
|
|
699
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
700
|
+
sage: sorted(sage.matroids.matroid.Matroid._circuit(M,
|
|
701
|
+
....: frozenset(['a', 'c', 'd', 'e', 'f'])))
|
|
702
|
+
['c', 'd', 'e', 'f']
|
|
703
|
+
sage: sorted(sage.matroids.matroid.Matroid._circuit(M,
|
|
704
|
+
....: frozenset(['a', 'c', 'd'])))
|
|
705
|
+
Traceback (most recent call last):
|
|
706
|
+
...
|
|
707
|
+
ValueError: no circuit in independent set.
|
|
708
|
+
|
|
709
|
+
.. NOTE::
|
|
710
|
+
|
|
711
|
+
This is an unguarded method. For the version that verifies if
|
|
712
|
+
the input is indeed a subset of the groundset,
|
|
713
|
+
see :meth:`<sage.matroids.matroid.Matroid.circuit>`.
|
|
714
|
+
"""
|
|
715
|
+
self._pack(self._input, F)
|
|
716
|
+
self.__circuit(self._output, self._input)
|
|
717
|
+
return self.__unpack(self._output)
|
|
718
|
+
|
|
719
|
+
cpdef frozenset _fundamental_circuit(self, frozenset B, e):
|
|
720
|
+
r"""
|
|
721
|
+
Return the `B`-fundamental circuit using `e`.
|
|
722
|
+
|
|
723
|
+
Internal version that does no input checking.
|
|
724
|
+
|
|
725
|
+
INPUT:
|
|
726
|
+
|
|
727
|
+
- ``B`` -- a basis of the matroid
|
|
728
|
+
- ``e`` -- an element not in ``B``
|
|
729
|
+
|
|
730
|
+
OUTPUT: set of elements
|
|
731
|
+
|
|
732
|
+
EXAMPLES::
|
|
733
|
+
|
|
734
|
+
sage: M = matroids.catalog.P8()
|
|
735
|
+
sage: sorted(M._fundamental_circuit(frozenset('abcd'), 'e'))
|
|
736
|
+
['a', 'b', 'c', 'e']
|
|
737
|
+
"""
|
|
738
|
+
self._pack(self._input, B)
|
|
739
|
+
bitset_clear(self._input2)
|
|
740
|
+
self.__move_current_basis(self._input, self._input2)
|
|
741
|
+
self.__fundamental_circuit(self._output, self._idx[e])
|
|
742
|
+
return self.__unpack(self._output)
|
|
743
|
+
|
|
744
|
+
cpdef frozenset _closure(self, frozenset F):
|
|
745
|
+
"""
|
|
746
|
+
Return the closure of a set.
|
|
747
|
+
|
|
748
|
+
INPUT:
|
|
749
|
+
|
|
750
|
+
- ``F`` -- an object with Python's ``frozenset`` interface containing
|
|
751
|
+
a subset of ``self.groundset()``
|
|
752
|
+
|
|
753
|
+
OUTPUT: the smallest closed set containing ``F``
|
|
754
|
+
|
|
755
|
+
EXAMPLES::
|
|
756
|
+
|
|
757
|
+
sage: from sage.matroids.advanced import *
|
|
758
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
759
|
+
sage: sorted(M._closure(frozenset(['a', 'b', 'c'])))
|
|
760
|
+
['a', 'b', 'c', 'd']
|
|
761
|
+
|
|
762
|
+
.. NOTE::
|
|
763
|
+
|
|
764
|
+
This is an unguarded method. For the version that verifies if the
|
|
765
|
+
input is indeed a subset of the groundset, see
|
|
766
|
+
:meth:`<sage.matroids.matroid.Matroid.closure>`.
|
|
767
|
+
"""
|
|
768
|
+
self._pack(self._input, F)
|
|
769
|
+
self.__closure(self._output, self._input)
|
|
770
|
+
return self.__unpack(self._output)
|
|
771
|
+
|
|
772
|
+
cpdef frozenset _max_coindependent(self, frozenset F):
|
|
773
|
+
"""
|
|
774
|
+
Compute a maximal coindependent subset.
|
|
775
|
+
|
|
776
|
+
INPUT:
|
|
777
|
+
|
|
778
|
+
- ``F`` -- an object with Python's ``frozenset`` interface containing
|
|
779
|
+
a subset of ``self.groundset()``
|
|
780
|
+
|
|
781
|
+
OUTPUT: a maximal coindependent subset of ``F``
|
|
782
|
+
|
|
783
|
+
EXAMPLES::
|
|
784
|
+
|
|
785
|
+
sage: from sage.matroids.advanced import *
|
|
786
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
787
|
+
sage: sorted(M._max_coindependent(frozenset(['a', 'c', 'd', 'e', 'f'])))
|
|
788
|
+
['a', 'c', 'd', 'f']
|
|
789
|
+
|
|
790
|
+
.. NOTE::
|
|
791
|
+
|
|
792
|
+
This is an unguarded method. For the version that verifies if the
|
|
793
|
+
input is indeed a subset of the groundset,
|
|
794
|
+
see :meth:`<sage.matroids.matroid.Matroid.max_coindependent>`.
|
|
795
|
+
"""
|
|
796
|
+
self._pack(self._input, F)
|
|
797
|
+
self.__max_coindependent(self._output, self._input)
|
|
798
|
+
return self.__unpack(self._output)
|
|
799
|
+
|
|
800
|
+
cpdef int _corank(self, frozenset F) noexcept:
|
|
801
|
+
"""
|
|
802
|
+
Return the corank of a set.
|
|
803
|
+
|
|
804
|
+
INPUT:
|
|
805
|
+
|
|
806
|
+
- ``F`` -- an object with Python's ``frozenset`` interface containing
|
|
807
|
+
a subset of ``self.groundset()``
|
|
808
|
+
|
|
809
|
+
OUTPUT: integer; the corank of `F`
|
|
810
|
+
|
|
811
|
+
EXAMPLES::
|
|
812
|
+
|
|
813
|
+
sage: from sage.matroids.advanced import *
|
|
814
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
815
|
+
sage: M._corank(frozenset(['a', 'e', 'g', 'd', 'h']))
|
|
816
|
+
4
|
|
817
|
+
|
|
818
|
+
.. NOTE::
|
|
819
|
+
|
|
820
|
+
This is an unguarded method. For the version that verifies if the
|
|
821
|
+
input is indeed a subset of the groundset,
|
|
822
|
+
see :meth:`<sage.matroids.matroid.Matroid.corank>`.
|
|
823
|
+
"""
|
|
824
|
+
self._pack(self._input, F)
|
|
825
|
+
self.__max_coindependent(self._output, self._input)
|
|
826
|
+
return bitset_len(self._output)
|
|
827
|
+
|
|
828
|
+
cpdef frozenset _cocircuit(self, frozenset F):
|
|
829
|
+
"""
|
|
830
|
+
Return a minimal codependent subset.
|
|
831
|
+
|
|
832
|
+
INPUT:
|
|
833
|
+
|
|
834
|
+
- ``F`` -- an object with Python's ``frozenset`` interface containing
|
|
835
|
+
a subset of ``self.groundset()``
|
|
836
|
+
|
|
837
|
+
OUTPUT: a cocircuit contained in ``F``, if it exists; otherwise, an
|
|
838
|
+
error is raised
|
|
839
|
+
|
|
840
|
+
EXAMPLES::
|
|
841
|
+
|
|
842
|
+
sage: from sage.matroids.advanced import *
|
|
843
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
844
|
+
sage: sorted(sage.matroids.matroid.Matroid._cocircuit(M,
|
|
845
|
+
....: frozenset(['a', 'c', 'd', 'e', 'f'])))
|
|
846
|
+
['c', 'd', 'e', 'f']
|
|
847
|
+
sage: sorted(sage.matroids.matroid.Matroid._cocircuit(M,
|
|
848
|
+
....: frozenset(['a', 'c', 'd'])))
|
|
849
|
+
Traceback (most recent call last):
|
|
850
|
+
...
|
|
851
|
+
ValueError: no cocircuit in coindependent set.
|
|
852
|
+
|
|
853
|
+
.. NOTE::
|
|
854
|
+
|
|
855
|
+
This is an unguarded method. For the version that verifies if the
|
|
856
|
+
input is indeed a subset of the groundset,
|
|
857
|
+
see :meth:`<sage.matroids.matroid.Matroid.cocircuit>`.
|
|
858
|
+
"""
|
|
859
|
+
self._pack(self._input, F)
|
|
860
|
+
self.__cocircuit(self._output, self._input)
|
|
861
|
+
return self.__unpack(self._output)
|
|
862
|
+
|
|
863
|
+
cpdef frozenset _fundamental_cocircuit(self, frozenset B, e):
|
|
864
|
+
r"""
|
|
865
|
+
Return the `B`-fundamental circuit using `e`.
|
|
866
|
+
|
|
867
|
+
Internal version that does no input checking.
|
|
868
|
+
|
|
869
|
+
INPUT:
|
|
870
|
+
|
|
871
|
+
- ``B`` -- a basis of the matroid
|
|
872
|
+
- ``e`` -- an element of ``B``
|
|
873
|
+
|
|
874
|
+
OUTPUT: set of elements
|
|
875
|
+
|
|
876
|
+
EXAMPLES::
|
|
877
|
+
|
|
878
|
+
sage: M = matroids.catalog.P8()
|
|
879
|
+
sage: sorted(M._fundamental_cocircuit(frozenset('efgh'), 'e'))
|
|
880
|
+
['b', 'c', 'd', 'e']
|
|
881
|
+
"""
|
|
882
|
+
self._pack(self._input, B)
|
|
883
|
+
bitset_clear(self._input2)
|
|
884
|
+
self.__move_current_basis(self._input, self._input2)
|
|
885
|
+
self.__fundamental_cocircuit(self._output, self._idx[e])
|
|
886
|
+
return self.__unpack(self._output)
|
|
887
|
+
|
|
888
|
+
cpdef frozenset _coclosure(self, frozenset F):
|
|
889
|
+
"""
|
|
890
|
+
Return the coclosure of a set.
|
|
891
|
+
|
|
892
|
+
INPUT:
|
|
893
|
+
|
|
894
|
+
- ``X`` -- an object with Python's ``frozenset`` interface containing
|
|
895
|
+
a subset of ``self.groundset()``
|
|
896
|
+
|
|
897
|
+
OUTPUT: the smallest coclosed set containing ``X``
|
|
898
|
+
|
|
899
|
+
EXAMPLES::
|
|
900
|
+
|
|
901
|
+
sage: from sage.matroids.advanced import *
|
|
902
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
903
|
+
sage: sorted(M._coclosure(frozenset(['a', 'b', 'c'])))
|
|
904
|
+
['a', 'b', 'c', 'd']
|
|
905
|
+
|
|
906
|
+
.. NOTE::
|
|
907
|
+
|
|
908
|
+
This is an unguarded method. For the version that verifies if the
|
|
909
|
+
input is indeed a subset of the groundset,
|
|
910
|
+
see :meth:`<sage.matroids.matroid.Matroid.coclosure>`.
|
|
911
|
+
"""
|
|
912
|
+
self._pack(self._input, F)
|
|
913
|
+
self._coclosure_internal(self._output, self._input)
|
|
914
|
+
return self.__unpack(self._output)
|
|
915
|
+
|
|
916
|
+
cpdef frozenset _augment(self, frozenset X, frozenset Y):
|
|
917
|
+
r"""
|
|
918
|
+
Return a maximal subset `I` of `Y` such that `r(X + I)=r(X) + r(I)`.
|
|
919
|
+
|
|
920
|
+
This version of ``augment`` does no type checking. In particular,
|
|
921
|
+
``Y`` is assumed to be disjoint from ``X``.
|
|
922
|
+
|
|
923
|
+
INPUT:
|
|
924
|
+
|
|
925
|
+
- ``X`` -- an object with Python's ``frozenset`` interface containing
|
|
926
|
+
a subset of ``self.groundset()``
|
|
927
|
+
- ``Y`` -- an object with Python's ``frozenset`` interface containing
|
|
928
|
+
a subset of ``self.groundset()``, and disjoint from ``X``
|
|
929
|
+
|
|
930
|
+
OUTPUT: a subset `I` of ``Y`` such that `r(X + I)=r(X) + r(I)`.
|
|
931
|
+
|
|
932
|
+
EXAMPLES::
|
|
933
|
+
|
|
934
|
+
sage: from sage.matroids.advanced import *
|
|
935
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
936
|
+
sage: sorted(M._augment(frozenset(['a']), frozenset(['e', 'f', 'g', 'h'])))
|
|
937
|
+
['e', 'f', 'g']
|
|
938
|
+
"""
|
|
939
|
+
self._pack(self._input, X)
|
|
940
|
+
self._pack(self._input2, Y)
|
|
941
|
+
self.__augment(self._output, self._input, self._input2)
|
|
942
|
+
return self.__unpack(self._output)
|
|
943
|
+
|
|
944
|
+
cpdef bint _is_independent(self, frozenset F) noexcept:
|
|
945
|
+
"""
|
|
946
|
+
Test if input is independent.
|
|
947
|
+
|
|
948
|
+
INPUT:
|
|
949
|
+
|
|
950
|
+
- ``F`` -- an object with Python's ``frozenset`` interface containing
|
|
951
|
+
a subset of ``self.groundset()``
|
|
952
|
+
|
|
953
|
+
OUTPUT: boolean
|
|
954
|
+
|
|
955
|
+
EXAMPLES::
|
|
956
|
+
|
|
957
|
+
sage: from sage.matroids.advanced import *
|
|
958
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
959
|
+
sage: M._is_independent(frozenset(['a', 'b', 'c']))
|
|
960
|
+
True
|
|
961
|
+
sage: M._is_independent(frozenset(['a', 'b', 'c', 'd']))
|
|
962
|
+
False
|
|
963
|
+
|
|
964
|
+
.. NOTE::
|
|
965
|
+
|
|
966
|
+
This is an unguarded method. For the version that verifies if
|
|
967
|
+
the input is indeed a subset of the groundset,
|
|
968
|
+
see :meth:`<sage.matroids.matroid.Matroid.is_independent>`.
|
|
969
|
+
"""
|
|
970
|
+
self._pack(self._input, F)
|
|
971
|
+
return self.__is_independent(self._input)
|
|
972
|
+
|
|
973
|
+
# connectivity
|
|
974
|
+
|
|
975
|
+
cpdef components(self):
|
|
976
|
+
"""
|
|
977
|
+
Return an iterable containing the components of the matroid.
|
|
978
|
+
|
|
979
|
+
A *component* is an inclusionwise maximal connected subset of the
|
|
980
|
+
matroid. A subset is *connected* if the matroid resulting from
|
|
981
|
+
deleting the complement of that subset is
|
|
982
|
+
:meth:`connected <sage.matroids.matroid.Matroid.is_connected>`.
|
|
983
|
+
|
|
984
|
+
OUTPUT: list of subsets
|
|
985
|
+
|
|
986
|
+
.. SEEALSO::
|
|
987
|
+
|
|
988
|
+
:meth:`M.is_connected() <sage.matroids.matroid.Matroid.is_connected>`,
|
|
989
|
+
:meth:`M.delete() <sage.matroids.matroid.Matroid.delete>`
|
|
990
|
+
|
|
991
|
+
EXAMPLES::
|
|
992
|
+
|
|
993
|
+
sage: from sage.matroids.advanced import setprint
|
|
994
|
+
sage: M = Matroid(ring=QQ, matrix=[[1, 0, 0, 1, 1, 0],
|
|
995
|
+
....: [0, 1, 0, 1, 2, 0],
|
|
996
|
+
....: [0, 0, 1, 0, 0, 1]])
|
|
997
|
+
sage: setprint(M.components())
|
|
998
|
+
[{0, 1, 3, 4}, {2, 5}]
|
|
999
|
+
"""
|
|
1000
|
+
cdef long i, j, e
|
|
1001
|
+
if not self._E:
|
|
1002
|
+
return SetSystem(self._E)
|
|
1003
|
+
cdef bitset_t *comp
|
|
1004
|
+
comp = <bitset_t*>sig_malloc((self.full_rank()) * sizeof(bitset_t))
|
|
1005
|
+
e = bitset_first(self._current_basis)
|
|
1006
|
+
i=0
|
|
1007
|
+
while e>=0:
|
|
1008
|
+
bitset_init(comp[i], self._bitset_size)
|
|
1009
|
+
self.__fundamental_cocircuit(comp[i], e)
|
|
1010
|
+
e=bitset_next(self._current_basis, e+1)
|
|
1011
|
+
i=i+1
|
|
1012
|
+
|
|
1013
|
+
cdef bitset_t active_rows
|
|
1014
|
+
bitset_init(active_rows, <mp_bitcnt_t> self.full_rank()+1)
|
|
1015
|
+
bitset_set_first_n(active_rows, <mp_bitcnt_t> self.full_rank())
|
|
1016
|
+
i=0
|
|
1017
|
+
while i>=0:
|
|
1018
|
+
j = bitset_first(active_rows)
|
|
1019
|
+
while j>=0 and j<i:
|
|
1020
|
+
if not bitset_are_disjoint(comp[i], comp[j]):
|
|
1021
|
+
bitset_union(comp[i], comp[i], comp[j])
|
|
1022
|
+
bitset_discard(active_rows, j)
|
|
1023
|
+
j = bitset_next(active_rows, j+1)
|
|
1024
|
+
i = bitset_next(active_rows, i+1)
|
|
1025
|
+
|
|
1026
|
+
res = SetSystem(self._E)
|
|
1027
|
+
i = bitset_first(active_rows)
|
|
1028
|
+
while i>=0:
|
|
1029
|
+
res._append(comp[i])
|
|
1030
|
+
i = bitset_next(active_rows, i+1)
|
|
1031
|
+
|
|
1032
|
+
cdef bitset_t loop, loops
|
|
1033
|
+
bitset_init(loops, self._bitset_size)
|
|
1034
|
+
bitset_set_first_n(loops, len(self))
|
|
1035
|
+
i = bitset_first(active_rows)
|
|
1036
|
+
while i>=0:
|
|
1037
|
+
bitset_difference(loops, loops, comp[i])
|
|
1038
|
+
i = bitset_next(active_rows, i+1)
|
|
1039
|
+
|
|
1040
|
+
bitset_init(loop, self._bitset_size)
|
|
1041
|
+
bitset_clear(loop)
|
|
1042
|
+
e = bitset_first(loops)
|
|
1043
|
+
while e>=0:
|
|
1044
|
+
bitset_add(loop, e)
|
|
1045
|
+
res._append(loop)
|
|
1046
|
+
bitset_discard(loop, e)
|
|
1047
|
+
e = bitset_next(loops, e+1)
|
|
1048
|
+
|
|
1049
|
+
bitset_free(loops)
|
|
1050
|
+
bitset_free(loop)
|
|
1051
|
+
bitset_free(active_rows)
|
|
1052
|
+
for i in range(self.full_rank()):
|
|
1053
|
+
bitset_free(comp[i])
|
|
1054
|
+
sig_free(comp)
|
|
1055
|
+
return res
|
|
1056
|
+
|
|
1057
|
+
cpdef _link(self, S, T):
|
|
1058
|
+
r"""
|
|
1059
|
+
Given disjoint subsets `S` and `T`, return a connector `I` and a separation `X`,
|
|
1060
|
+
which are optimal dual solutions in Tutte's Linking Theorem:
|
|
1061
|
+
|
|
1062
|
+
.. MATH::
|
|
1063
|
+
|
|
1064
|
+
\max \{ r_N(S) + r_N(T) - r(N) \mid N = M/I\setminus J, E(N) = S\cup T\}=\\
|
|
1065
|
+
\min \{ r_M(X) + r_M(Y) - r_M(E) \mid X \subseteq S, Y \subseteq T,
|
|
1066
|
+
E = X\cup Y, X\cap Y = \emptyset \}.
|
|
1067
|
+
|
|
1068
|
+
Here `M` denotes this matroid.
|
|
1069
|
+
|
|
1070
|
+
Internal version that does not verify that ``S`` and ``T``
|
|
1071
|
+
are sets, are disjoint, are subsets of the groundset.
|
|
1072
|
+
|
|
1073
|
+
INPUT:
|
|
1074
|
+
|
|
1075
|
+
- ``S`` -- a subset of the groundset
|
|
1076
|
+
- ``T`` -- a subset of the groundset disjoint from ``S``
|
|
1077
|
+
|
|
1078
|
+
OUTPUT: tuple ``(I, X)`` of two frozensets
|
|
1079
|
+
|
|
1080
|
+
ALGORITHM:
|
|
1081
|
+
|
|
1082
|
+
Compute a maximum-cardinality common independent set `I` of
|
|
1083
|
+
of `M / S \setminus T` and `M \setminus S / T`.
|
|
1084
|
+
|
|
1085
|
+
EXAMPLES::
|
|
1086
|
+
|
|
1087
|
+
sage: M = matroids.catalog.BetsyRoss()
|
|
1088
|
+
sage: S = frozenset('ab')
|
|
1089
|
+
sage: T = frozenset('cd')
|
|
1090
|
+
sage: I, X = M._link(S, T)
|
|
1091
|
+
sage: M.connectivity(X)
|
|
1092
|
+
2
|
|
1093
|
+
sage: J = M.groundset() - (S | T | I)
|
|
1094
|
+
sage: N = (M / I).delete(J)
|
|
1095
|
+
sage: N.connectivity(S)
|
|
1096
|
+
2
|
|
1097
|
+
"""
|
|
1098
|
+
# compute maximal common independent set of self\S/T and self/T\S
|
|
1099
|
+
cdef bitset_t SS, TT
|
|
1100
|
+
bitset_init(SS, self._groundset_size)
|
|
1101
|
+
bitset_init(TT, self._groundset_size)
|
|
1102
|
+
self._pack(SS, S)
|
|
1103
|
+
self._pack(TT, T)
|
|
1104
|
+
# F = set(self.groundset()) - (S | T)
|
|
1105
|
+
cdef bitset_t F, I
|
|
1106
|
+
bitset_init(F, self._groundset_size)
|
|
1107
|
+
bitset_init(I, self._groundset_size)
|
|
1108
|
+
bitset_union(self._input, SS, TT)
|
|
1109
|
+
bitset_complement(F, self._input)
|
|
1110
|
+
# I = self._augment(S|T, F)
|
|
1111
|
+
self.__augment(I, self._input, F)
|
|
1112
|
+
cdef bitset_t X, X1, X2, next_layer, todo, out_neighbors, R
|
|
1113
|
+
bitset_init(X, self._groundset_size)
|
|
1114
|
+
bitset_init(X1, self._groundset_size)
|
|
1115
|
+
bitset_init(X2, self._groundset_size)
|
|
1116
|
+
bitset_init(next_layer, self._groundset_size)
|
|
1117
|
+
bitset_init(todo, self._groundset_size)
|
|
1118
|
+
bitset_init(out_neighbors, self._groundset_size)
|
|
1119
|
+
bitset_init(R, self._groundset_size)
|
|
1120
|
+
cdef long* predecessor
|
|
1121
|
+
predecessor = <long*>sig_malloc(self._groundset_size*sizeof(long))
|
|
1122
|
+
cdef long e, u, y
|
|
1123
|
+
cdef bint found_path = True
|
|
1124
|
+
while found_path:
|
|
1125
|
+
# X = F - I
|
|
1126
|
+
bitset_difference(X, F, I)
|
|
1127
|
+
# X1 = X - self._closure(T|I)
|
|
1128
|
+
bitset_union(self._input, TT, I)
|
|
1129
|
+
self.__closure(X1, self._input)
|
|
1130
|
+
bitset_difference(X1, X, X1)
|
|
1131
|
+
# X2 = X - self._closure(S|I)
|
|
1132
|
+
bitset_union(self._input, SS, I)
|
|
1133
|
+
self.__closure(X2, self._input)
|
|
1134
|
+
bitset_difference(X2, X, X2)
|
|
1135
|
+
bitset_intersection(R, X1, X2)
|
|
1136
|
+
e = bitset_first(R)
|
|
1137
|
+
if e >= 0:
|
|
1138
|
+
bitset_add(I, e)
|
|
1139
|
+
continue
|
|
1140
|
+
# predecessor = {x: None for x in X1}
|
|
1141
|
+
e = bitset_first(X1)
|
|
1142
|
+
while e>=0:
|
|
1143
|
+
predecessor[e] = -1
|
|
1144
|
+
e = bitset_next(X1, e+1)
|
|
1145
|
+
# next_layer = set(X1)
|
|
1146
|
+
bitset_copy(next_layer, X1)
|
|
1147
|
+
bitset_union(R, SS, X1)
|
|
1148
|
+
found_path = False
|
|
1149
|
+
while not bitset_isempty(next_layer) and not found_path:
|
|
1150
|
+
# todo = next_layer
|
|
1151
|
+
bitset_copy(todo, next_layer)
|
|
1152
|
+
# next_layer = {}
|
|
1153
|
+
bitset_clear(next_layer)
|
|
1154
|
+
u = bitset_first(todo)
|
|
1155
|
+
while u >= 0 and not found_path:
|
|
1156
|
+
if bitset_in(X, u):
|
|
1157
|
+
# out_neighbors = self._circuit(I|S.union([u])) - S.union([u])
|
|
1158
|
+
bitset_union(self._input, I, SS)
|
|
1159
|
+
bitset_add(self._input, u)
|
|
1160
|
+
self.__circuit(out_neighbors, self._input)
|
|
1161
|
+
bitset_discard(out_neighbors, u)
|
|
1162
|
+
else:
|
|
1163
|
+
# out_neighbors = X - self._closure(I|T - set([u]))
|
|
1164
|
+
bitset_union(self._input, I, TT)
|
|
1165
|
+
bitset_discard(self._input, u)
|
|
1166
|
+
self.__closure(out_neighbors, self._input)
|
|
1167
|
+
bitset_difference(out_neighbors, X, out_neighbors)
|
|
1168
|
+
bitset_difference(out_neighbors, out_neighbors, R)
|
|
1169
|
+
y = bitset_first(out_neighbors)
|
|
1170
|
+
while y >= 0:
|
|
1171
|
+
predecessor[y] = u
|
|
1172
|
+
if bitset_in(X2, y):
|
|
1173
|
+
found_path = True
|
|
1174
|
+
while y>=0:
|
|
1175
|
+
bitset_flip(I, y)
|
|
1176
|
+
y = predecessor[y]
|
|
1177
|
+
break
|
|
1178
|
+
bitset_add(R, y)
|
|
1179
|
+
bitset_add(next_layer, y)
|
|
1180
|
+
y = bitset_next(out_neighbors, y+1)
|
|
1181
|
+
u = bitset_next(todo, u+1)
|
|
1182
|
+
II = self.__unpack(I)
|
|
1183
|
+
RR = self.__unpack(R)
|
|
1184
|
+
|
|
1185
|
+
bitset_free(SS)
|
|
1186
|
+
bitset_free(TT)
|
|
1187
|
+
bitset_free(F)
|
|
1188
|
+
bitset_free(I)
|
|
1189
|
+
bitset_free(X)
|
|
1190
|
+
bitset_free(X1)
|
|
1191
|
+
bitset_free(X2)
|
|
1192
|
+
bitset_free(next_layer)
|
|
1193
|
+
bitset_free(todo)
|
|
1194
|
+
bitset_free(out_neighbors)
|
|
1195
|
+
bitset_free(R)
|
|
1196
|
+
sig_free(predecessor)
|
|
1197
|
+
|
|
1198
|
+
return II, RR
|
|
1199
|
+
|
|
1200
|
+
# enumeration
|
|
1201
|
+
|
|
1202
|
+
cpdef list whitney_numbers2(self):
|
|
1203
|
+
r"""
|
|
1204
|
+
Return the Whitney numbers of the second kind of the matroid.
|
|
1205
|
+
|
|
1206
|
+
The Whitney numbers of the second kind are here encoded as a vector
|
|
1207
|
+
`(W_0, \ldots, W_r)`, where `W_i` is the number of flats of rank `i`,
|
|
1208
|
+
and `r` is the rank of the matroid.
|
|
1209
|
+
|
|
1210
|
+
OUTPUT: list of integers
|
|
1211
|
+
|
|
1212
|
+
EXAMPLES::
|
|
1213
|
+
|
|
1214
|
+
sage: M = matroids.catalog.S8()
|
|
1215
|
+
sage: M.whitney_numbers2()
|
|
1216
|
+
[1, 8, 22, 14, 1]
|
|
1217
|
+
"""
|
|
1218
|
+
cdef bitset_t *flats
|
|
1219
|
+
cdef bitset_t *todo
|
|
1220
|
+
if self._matroid_rank == 0:
|
|
1221
|
+
return [1]
|
|
1222
|
+
flats = <bitset_t*>sig_malloc((self.full_rank() + 1) * sizeof(bitset_t))
|
|
1223
|
+
todo = <bitset_t*>sig_malloc((self.full_rank() + 1) * sizeof(bitset_t))
|
|
1224
|
+
|
|
1225
|
+
for i in range(self.full_rank() + 1):
|
|
1226
|
+
bitset_init(flats[i], self._bitset_size)
|
|
1227
|
+
bitset_init(todo[i], self._bitset_size)
|
|
1228
|
+
f_vec = [0 for i in range(self.full_rank() + 1)]
|
|
1229
|
+
i = 0
|
|
1230
|
+
bitset_clear(todo[0])
|
|
1231
|
+
self.__closure(flats[0], todo[0])
|
|
1232
|
+
bitset_complement(todo[0], flats[0])
|
|
1233
|
+
self._whitney_numbers2_rec(f_vec, flats, todo, 0, 0)
|
|
1234
|
+
for i in range(self.full_rank() + 1):
|
|
1235
|
+
bitset_free(flats[i])
|
|
1236
|
+
bitset_free(todo[i])
|
|
1237
|
+
sig_free(flats)
|
|
1238
|
+
sig_free(todo)
|
|
1239
|
+
return f_vec
|
|
1240
|
+
|
|
1241
|
+
cdef _whitney_numbers2_rec(self, object f_vec, bitset_t* flats, bitset_t* todo, long elt, long i):
|
|
1242
|
+
"""
|
|
1243
|
+
Recursion for the ``whitney_numbers2`` method.
|
|
1244
|
+
"""
|
|
1245
|
+
cdef long e
|
|
1246
|
+
f_vec[i] += 1
|
|
1247
|
+
e = bitset_next(todo[i], elt)
|
|
1248
|
+
while e >= 0:
|
|
1249
|
+
bitset_copy(self._input, flats[i])
|
|
1250
|
+
bitset_add(self._input, e)
|
|
1251
|
+
self.__closure(flats[i + 1], self._input)
|
|
1252
|
+
bitset_difference(todo[i], todo[i], flats[i + 1])
|
|
1253
|
+
bitset_difference(todo[i + 1], flats[i + 1], flats[i])
|
|
1254
|
+
if bitset_first(todo[i + 1]) == e:
|
|
1255
|
+
bitset_copy(todo[i + 1], todo[i])
|
|
1256
|
+
self._whitney_numbers2_rec(f_vec, flats, todo, e + 1, i + 1)
|
|
1257
|
+
e = bitset_next(todo[i], e)
|
|
1258
|
+
|
|
1259
|
+
cpdef SetSystem flats(self, long k):
|
|
1260
|
+
"""
|
|
1261
|
+
Return the collection of flats of the matroid of specified rank.
|
|
1262
|
+
|
|
1263
|
+
A *flat* is a closed set.
|
|
1264
|
+
|
|
1265
|
+
INPUT:
|
|
1266
|
+
|
|
1267
|
+
- ``k`` -- integer
|
|
1268
|
+
|
|
1269
|
+
OUTPUT: :class:`SetSystem`
|
|
1270
|
+
|
|
1271
|
+
.. SEEALSO::
|
|
1272
|
+
|
|
1273
|
+
:meth:`Matroid.closure() <sage.matroids.matroid.Matroid.closure>`
|
|
1274
|
+
|
|
1275
|
+
EXAMPLES::
|
|
1276
|
+
|
|
1277
|
+
sage: M = matroids.catalog.S8()
|
|
1278
|
+
sage: M.whitney_numbers2()
|
|
1279
|
+
[1, 8, 22, 14, 1]
|
|
1280
|
+
sage: len(M.flats(2))
|
|
1281
|
+
22
|
|
1282
|
+
sage: len(M.flats(8))
|
|
1283
|
+
0
|
|
1284
|
+
sage: len(M.flats(4))
|
|
1285
|
+
1
|
|
1286
|
+
"""
|
|
1287
|
+
cdef bitset_t *flats
|
|
1288
|
+
cdef bitset_t *todo
|
|
1289
|
+
if k < 0 or k > self.full_rank():
|
|
1290
|
+
return SetSystem(self._E)
|
|
1291
|
+
if k == self.full_rank():
|
|
1292
|
+
return SetSystem(self._E, subsets=[self.groundset()])
|
|
1293
|
+
flats = <bitset_t*>sig_malloc((k + 1) * sizeof(bitset_t))
|
|
1294
|
+
todo = <bitset_t*>sig_malloc((k + 1) * sizeof(bitset_t))
|
|
1295
|
+
|
|
1296
|
+
for i in range(k + 1):
|
|
1297
|
+
bitset_init(flats[i], self._bitset_size)
|
|
1298
|
+
bitset_init(todo[i], self._bitset_size)
|
|
1299
|
+
Rflats = SetSystem(self._E)
|
|
1300
|
+
i = 0
|
|
1301
|
+
bitset_clear(todo[0])
|
|
1302
|
+
self.__closure(flats[0], todo[0])
|
|
1303
|
+
bitset_complement(todo[0], flats[0])
|
|
1304
|
+
self._flats_rec(Rflats, k, flats, todo, 0, 0)
|
|
1305
|
+
for i in range(k + 1):
|
|
1306
|
+
bitset_free(flats[i])
|
|
1307
|
+
bitset_free(todo[i])
|
|
1308
|
+
sig_free(flats)
|
|
1309
|
+
sig_free(todo)
|
|
1310
|
+
return Rflats
|
|
1311
|
+
|
|
1312
|
+
cdef _flats_rec(self, SetSystem Rflats, long R, bitset_t* flats, bitset_t* todo, long elt, long i):
|
|
1313
|
+
"""
|
|
1314
|
+
Recursion for the ``flats`` method.
|
|
1315
|
+
"""
|
|
1316
|
+
cdef long e
|
|
1317
|
+
if i == R:
|
|
1318
|
+
Rflats._append(flats[i])
|
|
1319
|
+
return
|
|
1320
|
+
e = bitset_next(todo[i], elt)
|
|
1321
|
+
while e >= 0:
|
|
1322
|
+
bitset_copy(self._input, flats[i]) # I fear that self._input is dangerous in a parallel computing environment. --SvZ
|
|
1323
|
+
bitset_add(self._input, e) # It absolutely is! --RP
|
|
1324
|
+
self.__closure(flats[i + 1], self._input)
|
|
1325
|
+
bitset_difference(todo[i], todo[i], flats[i + 1])
|
|
1326
|
+
bitset_difference(todo[i + 1], flats[i + 1], flats[i])
|
|
1327
|
+
if bitset_first(todo[i + 1]) == e:
|
|
1328
|
+
bitset_copy(todo[i + 1], todo[i])
|
|
1329
|
+
self._flats_rec(Rflats, R, flats, todo, e + 1, i + 1)
|
|
1330
|
+
e = bitset_next(todo[i], e)
|
|
1331
|
+
|
|
1332
|
+
cpdef SetSystem coflats(self, long k):
|
|
1333
|
+
"""
|
|
1334
|
+
Return the collection of coflats of the matroid of specified corank.
|
|
1335
|
+
|
|
1336
|
+
A *coflat* is a coclosed set.
|
|
1337
|
+
|
|
1338
|
+
INPUT:
|
|
1339
|
+
|
|
1340
|
+
- ``k`` -- integer
|
|
1341
|
+
|
|
1342
|
+
OUTPUT: iterable containing all coflats of corank `k`
|
|
1343
|
+
|
|
1344
|
+
.. SEEALSO::
|
|
1345
|
+
|
|
1346
|
+
:meth:`Matroid.coclosure() <sage.matroids.matroid.Matroid.coclosure>`
|
|
1347
|
+
|
|
1348
|
+
EXAMPLES::
|
|
1349
|
+
|
|
1350
|
+
sage: M = matroids.catalog.S8().dual()
|
|
1351
|
+
sage: M.whitney_numbers2()
|
|
1352
|
+
[1, 8, 22, 14, 1]
|
|
1353
|
+
sage: len(M.coflats(2))
|
|
1354
|
+
22
|
|
1355
|
+
sage: len(M.coflats(8))
|
|
1356
|
+
0
|
|
1357
|
+
sage: len(M.coflats(4))
|
|
1358
|
+
1
|
|
1359
|
+
"""
|
|
1360
|
+
cdef bitset_t *coflats
|
|
1361
|
+
cdef bitset_t *todo
|
|
1362
|
+
if k < 0 or k > self.full_corank():
|
|
1363
|
+
return SetSystem(self._E)
|
|
1364
|
+
if k == self.full_corank():
|
|
1365
|
+
return SetSystem(self._E, subsets=[self.groundset()])
|
|
1366
|
+
coflats = <bitset_t*>sig_malloc((k + 1) * sizeof(bitset_t))
|
|
1367
|
+
todo = <bitset_t*>sig_malloc((k + 1) * sizeof(bitset_t))
|
|
1368
|
+
|
|
1369
|
+
for i in range(k + 1):
|
|
1370
|
+
bitset_init(coflats[i], self._bitset_size)
|
|
1371
|
+
bitset_init(todo[i], self._bitset_size)
|
|
1372
|
+
Rcoflats = SetSystem(self._E)
|
|
1373
|
+
i = 0
|
|
1374
|
+
bitset_clear(todo[0])
|
|
1375
|
+
self._coclosure_internal(coflats[0], todo[0])
|
|
1376
|
+
bitset_complement(todo[0], coflats[0])
|
|
1377
|
+
self._coflats_rec(Rcoflats, k, coflats, todo, 0, 0)
|
|
1378
|
+
for i in range(k + 1):
|
|
1379
|
+
bitset_free(coflats[i])
|
|
1380
|
+
bitset_free(todo[i])
|
|
1381
|
+
sig_free(coflats)
|
|
1382
|
+
sig_free(todo)
|
|
1383
|
+
return Rcoflats
|
|
1384
|
+
|
|
1385
|
+
cdef _coflats_rec(self, SetSystem Rcoflats, long R, bitset_t* coflats, bitset_t* todo, long elt, long i):
|
|
1386
|
+
"""
|
|
1387
|
+
Recursion for the ``coflats`` method.
|
|
1388
|
+
"""
|
|
1389
|
+
cdef long e
|
|
1390
|
+
if i == R:
|
|
1391
|
+
Rcoflats._append(coflats[i])
|
|
1392
|
+
return
|
|
1393
|
+
e = bitset_next(todo[i], elt)
|
|
1394
|
+
while e >= 0:
|
|
1395
|
+
bitset_copy(self._input, coflats[i])
|
|
1396
|
+
bitset_add(self._input, e)
|
|
1397
|
+
self._coclosure_internal(coflats[i + 1], self._input)
|
|
1398
|
+
bitset_difference(todo[i], todo[i], coflats[i + 1])
|
|
1399
|
+
bitset_difference(todo[i + 1], coflats[i + 1], coflats[i])
|
|
1400
|
+
if bitset_first(todo[i + 1]) == e:
|
|
1401
|
+
bitset_copy(todo[i + 1], todo[i])
|
|
1402
|
+
self._coflats_rec(Rcoflats, R, coflats, todo, e + 1, i + 1)
|
|
1403
|
+
e = bitset_next(todo[i], e)
|
|
1404
|
+
|
|
1405
|
+
cdef _flat_element_inv(self, long k):
|
|
1406
|
+
"""
|
|
1407
|
+
Compute a flat-element invariant of the matroid.
|
|
1408
|
+
"""
|
|
1409
|
+
cdef bitset_t *flats
|
|
1410
|
+
cdef bitset_t *todo
|
|
1411
|
+
if self._groundset_size == 0:
|
|
1412
|
+
return {}, tuple()
|
|
1413
|
+
flats = <bitset_t*>sig_malloc((k + 1) * sizeof(bitset_t))
|
|
1414
|
+
todo = <bitset_t*>sig_malloc((k + 1) * sizeof(bitset_t))
|
|
1415
|
+
|
|
1416
|
+
for i in range(k + 1):
|
|
1417
|
+
bitset_init(flats[i], self._bitset_size)
|
|
1418
|
+
bitset_init(todo[i], self._bitset_size)
|
|
1419
|
+
f_inc = [[0 for e in range(self._groundset_size + 1)] for i in range(k + 1)]
|
|
1420
|
+
i = 0
|
|
1421
|
+
bitset_clear(todo[0])
|
|
1422
|
+
self.__closure(flats[0], todo[0])
|
|
1423
|
+
bitset_complement(todo[0], flats[0])
|
|
1424
|
+
self._flat_element_inv_rec(f_inc, k, flats, todo, 0, 0)
|
|
1425
|
+
for i in range(k + 1):
|
|
1426
|
+
bitset_free(flats[i])
|
|
1427
|
+
bitset_free(todo[i])
|
|
1428
|
+
sig_free(flats)
|
|
1429
|
+
sig_free(todo)
|
|
1430
|
+
fie = {}
|
|
1431
|
+
for e in range(self._groundset_size):
|
|
1432
|
+
t = tuple([f_inc[i][e] for i in range(k + 1)])
|
|
1433
|
+
if t in fie:
|
|
1434
|
+
fie[t].add(self._E[e])
|
|
1435
|
+
else:
|
|
1436
|
+
fie[t] = set([self._E[e]])
|
|
1437
|
+
f_vec = tuple([f_inc[i][self._groundset_size] for i in range(k + 1)])
|
|
1438
|
+
return fie, f_vec
|
|
1439
|
+
|
|
1440
|
+
cdef _flat_element_inv_rec(self, object f_inc, long R, bitset_t* flats, bitset_t* todo, long elt, long i):
|
|
1441
|
+
"""
|
|
1442
|
+
Recursion for ``_flat_element_inv``.
|
|
1443
|
+
"""
|
|
1444
|
+
cdef long e, k
|
|
1445
|
+
k = bitset_len(flats[i])
|
|
1446
|
+
k = k * k
|
|
1447
|
+
e = bitset_first(flats[i])
|
|
1448
|
+
inc = f_inc[i]
|
|
1449
|
+
while e >= 0:
|
|
1450
|
+
inc[e] += k
|
|
1451
|
+
e = bitset_next(flats[i], e + 1)
|
|
1452
|
+
inc[self._groundset_size] += k
|
|
1453
|
+
if i == R:
|
|
1454
|
+
return
|
|
1455
|
+
e = bitset_next(todo[i], elt)
|
|
1456
|
+
while e >= 0:
|
|
1457
|
+
bitset_copy(self._input, flats[i])
|
|
1458
|
+
bitset_add(self._input, e)
|
|
1459
|
+
self.__closure(flats[i + 1], self._input)
|
|
1460
|
+
bitset_difference(todo[i], todo[i], flats[i + 1])
|
|
1461
|
+
bitset_difference(todo[i + 1], flats[i + 1], flats[i])
|
|
1462
|
+
if bitset_first(todo[i + 1]) == e:
|
|
1463
|
+
bitset_copy(todo[i + 1], todo[i])
|
|
1464
|
+
self._flat_element_inv_rec(f_inc, R, flats, todo, e + 1, i + 1)
|
|
1465
|
+
e = bitset_next(todo[i], e)
|
|
1466
|
+
|
|
1467
|
+
cpdef bases_count(self):
|
|
1468
|
+
"""
|
|
1469
|
+
Return the number of bases of the matroid.
|
|
1470
|
+
|
|
1471
|
+
A *basis* is an inclusionwise maximal independent set.
|
|
1472
|
+
|
|
1473
|
+
.. SEEALSO::
|
|
1474
|
+
|
|
1475
|
+
:meth:`M.basis() <sage.matroids.matroid.Matroid.basis>`.
|
|
1476
|
+
|
|
1477
|
+
OUTPUT: integer
|
|
1478
|
+
|
|
1479
|
+
EXAMPLES::
|
|
1480
|
+
|
|
1481
|
+
sage: M = matroids.catalog.N1()
|
|
1482
|
+
sage: M.bases_count()
|
|
1483
|
+
184
|
|
1484
|
+
"""
|
|
1485
|
+
if self._bcount is not None:
|
|
1486
|
+
return self._bcount
|
|
1487
|
+
cdef long res = 0
|
|
1488
|
+
bitset_clear(self._input)
|
|
1489
|
+
bitset_set_first_n(self._input, self._matroid_rank)
|
|
1490
|
+
repeat = True
|
|
1491
|
+
while repeat:
|
|
1492
|
+
if self.__is_independent(self._input):
|
|
1493
|
+
res += 1
|
|
1494
|
+
repeat = nxksrd(self._input, self._groundset_size, self._matroid_rank, True)
|
|
1495
|
+
self._bcount = res
|
|
1496
|
+
return self._bcount
|
|
1497
|
+
|
|
1498
|
+
cpdef SetSystem independent_sets(self, long k=-1):
|
|
1499
|
+
r"""
|
|
1500
|
+
Return the independent sets of the matroid.
|
|
1501
|
+
|
|
1502
|
+
INPUT:
|
|
1503
|
+
|
|
1504
|
+
- ``k`` -- integer (optional); if specified, return the size-`k`
|
|
1505
|
+
independent sets of the matroid
|
|
1506
|
+
|
|
1507
|
+
OUTPUT: :class:`SetSystem`
|
|
1508
|
+
|
|
1509
|
+
EXAMPLES::
|
|
1510
|
+
|
|
1511
|
+
sage: M = matroids.catalog.Fano()
|
|
1512
|
+
sage: I = M.independent_sets()
|
|
1513
|
+
sage: len(I)
|
|
1514
|
+
57
|
|
1515
|
+
sage: M = matroids.catalog.N1()
|
|
1516
|
+
sage: M.bases_count()
|
|
1517
|
+
184
|
|
1518
|
+
sage: [len(M.independent_sets(k)) for k in range(M.full_rank() + 1)]
|
|
1519
|
+
[1, 10, 45, 120, 201, 184]
|
|
1520
|
+
|
|
1521
|
+
TESTS::
|
|
1522
|
+
|
|
1523
|
+
sage: len([B for B in M.bases()])
|
|
1524
|
+
184
|
|
1525
|
+
"""
|
|
1526
|
+
cdef bitset_t *I
|
|
1527
|
+
cdef bitset_t *T
|
|
1528
|
+
cdef long i, e, r
|
|
1529
|
+
if k == -1: # all independent sets
|
|
1530
|
+
res = SetSystem(self._E)
|
|
1531
|
+
bitset_clear(self._input)
|
|
1532
|
+
res._append(self._input)
|
|
1533
|
+
if not self._E:
|
|
1534
|
+
return res
|
|
1535
|
+
|
|
1536
|
+
r = self.full_rank()
|
|
1537
|
+
I = <bitset_t*>sig_malloc((r + 1) * sizeof(bitset_t))
|
|
1538
|
+
T = <bitset_t*>sig_malloc((r + 1) * sizeof(bitset_t))
|
|
1539
|
+
for i in range(r + 1):
|
|
1540
|
+
bitset_init(I[i], self._bitset_size)
|
|
1541
|
+
bitset_init(T[i], self._bitset_size)
|
|
1542
|
+
|
|
1543
|
+
i = 0
|
|
1544
|
+
bitset_clear(I[0])
|
|
1545
|
+
bitset_copy(self._input, I[0])
|
|
1546
|
+
self.__closure(T[0], self._input)
|
|
1547
|
+
while i >= 0:
|
|
1548
|
+
e = bitset_first_in_complement(T[i])
|
|
1549
|
+
if e >= 0:
|
|
1550
|
+
bitset_add(T[i], e)
|
|
1551
|
+
bitset_copy(I[i+1], I[i])
|
|
1552
|
+
bitset_add(I[i+1], e)
|
|
1553
|
+
res._append(I[i+1])
|
|
1554
|
+
bitset_copy(self._input, I[i+1])
|
|
1555
|
+
self.__closure(T[i+1], self._input)
|
|
1556
|
+
bitset_union(T[i+1], T[i+1], T[i])
|
|
1557
|
+
i = i + 1
|
|
1558
|
+
else:
|
|
1559
|
+
i = i - 1
|
|
1560
|
+
for i in range(r + 1):
|
|
1561
|
+
bitset_free(I[i])
|
|
1562
|
+
bitset_free(T[i])
|
|
1563
|
+
sig_free(I)
|
|
1564
|
+
sig_free(T)
|
|
1565
|
+
return res
|
|
1566
|
+
|
|
1567
|
+
# independent k-sets
|
|
1568
|
+
cdef SetSystem BB = SetSystem(self._E)
|
|
1569
|
+
if k < 0 or k > self.full_rank():
|
|
1570
|
+
return BB
|
|
1571
|
+
bitset_clear(self._input)
|
|
1572
|
+
bitset_set_first_n(self._input, k)
|
|
1573
|
+
repeat = True
|
|
1574
|
+
while repeat:
|
|
1575
|
+
if self.__is_independent(self._input):
|
|
1576
|
+
BB._append(self._input)
|
|
1577
|
+
repeat = nxksrd(self._input, self._groundset_size, k, True)
|
|
1578
|
+
return BB
|
|
1579
|
+
|
|
1580
|
+
cpdef SetSystem dependent_sets(self, long k):
|
|
1581
|
+
"""
|
|
1582
|
+
Return the dependent sets of fixed size.
|
|
1583
|
+
|
|
1584
|
+
INPUT:
|
|
1585
|
+
|
|
1586
|
+
- ``k`` -- integer
|
|
1587
|
+
|
|
1588
|
+
OUTPUT: iterable containing all dependent sets of size ``k``
|
|
1589
|
+
|
|
1590
|
+
EXAMPLES::
|
|
1591
|
+
|
|
1592
|
+
sage: M = matroids.catalog.N1()
|
|
1593
|
+
sage: len(M.nonbases())
|
|
1594
|
+
68
|
|
1595
|
+
sage: [len(M.dependent_sets(k)) for k in range(M.full_rank() + 1)]
|
|
1596
|
+
[0, 0, 0, 0, 9, 68]
|
|
1597
|
+
|
|
1598
|
+
TESTS::
|
|
1599
|
+
|
|
1600
|
+
sage: binomial(M.size(), M.full_rank())-M.bases_count() # needs sage.symbolic
|
|
1601
|
+
68
|
|
1602
|
+
sage: len([B for B in M.nonbases()])
|
|
1603
|
+
68
|
|
1604
|
+
"""
|
|
1605
|
+
cdef SetSystem NB
|
|
1606
|
+
NB = SetSystem(self._E)
|
|
1607
|
+
if k < 0 or k > self.size():
|
|
1608
|
+
return NB
|
|
1609
|
+
bitset_clear(self._input)
|
|
1610
|
+
bitset_set_first_n(self._input, k)
|
|
1611
|
+
repeat = True
|
|
1612
|
+
if k > self.full_rank():
|
|
1613
|
+
while repeat:
|
|
1614
|
+
NB._append(self._input)
|
|
1615
|
+
repeat = nxksrd(self._input, self._groundset_size, k, True)
|
|
1616
|
+
else:
|
|
1617
|
+
while repeat:
|
|
1618
|
+
if not self.__is_independent(self._input):
|
|
1619
|
+
NB._append(self._input)
|
|
1620
|
+
repeat = nxksrd(self._input, self._groundset_size, k, True)
|
|
1621
|
+
NB.resize()
|
|
1622
|
+
return NB
|
|
1623
|
+
|
|
1624
|
+
cpdef SetSystem nonspanning_circuits(self):
|
|
1625
|
+
"""
|
|
1626
|
+
Return the nonspanning circuits of the matroid.
|
|
1627
|
+
|
|
1628
|
+
A *nonspanning circuit* is a circuit whose rank is strictly smaller
|
|
1629
|
+
than the rank of the matroid.
|
|
1630
|
+
|
|
1631
|
+
OUTPUT: iterable containing all nonspanning circuits
|
|
1632
|
+
|
|
1633
|
+
.. SEEALSO::
|
|
1634
|
+
|
|
1635
|
+
:meth:`Matroid.circuit() <sage.matroids.matroid.Matroid.circuit>`,
|
|
1636
|
+
:meth:`Matroid.rank() <sage.matroids.matroid.Matroid.rank>`
|
|
1637
|
+
|
|
1638
|
+
EXAMPLES::
|
|
1639
|
+
|
|
1640
|
+
sage: M = matroids.catalog.N1()
|
|
1641
|
+
sage: len(M.nonspanning_circuits())
|
|
1642
|
+
23
|
|
1643
|
+
"""
|
|
1644
|
+
cdef SetSystem NSC
|
|
1645
|
+
NSC = SetSystem(self._E)
|
|
1646
|
+
if self._groundset_size == 0:
|
|
1647
|
+
return NSC
|
|
1648
|
+
bitset_clear(self._input)
|
|
1649
|
+
bitset_set_first_n(self._input, self._matroid_rank)
|
|
1650
|
+
cdef long e, f
|
|
1651
|
+
repeat = True
|
|
1652
|
+
while repeat:
|
|
1653
|
+
if self.__is_independent(self._input):
|
|
1654
|
+
bitset_complement(self._input2, self._current_basis)
|
|
1655
|
+
e = bitset_first(self._current_basis)
|
|
1656
|
+
while e >= 0:
|
|
1657
|
+
self.__fundamental_cocircuit(self._output, e)
|
|
1658
|
+
if e > bitset_first(self._output):
|
|
1659
|
+
bitset_intersection(self._input2, self._input2, self._output)
|
|
1660
|
+
e = bitset_next(self._current_basis, e + 1)
|
|
1661
|
+
f = bitset_first(self._input2)
|
|
1662
|
+
while f >= 0:
|
|
1663
|
+
self.__fundamental_circuit(self._output, f)
|
|
1664
|
+
if f == bitset_first(self._output) and bitset_len(self._output) <= self._matroid_rank:
|
|
1665
|
+
NSC._append(self._output)
|
|
1666
|
+
f = bitset_next(self._input2, f + 1)
|
|
1667
|
+
repeat = nxksrd(self._input, self._groundset_size, self._matroid_rank, True)
|
|
1668
|
+
NSC.resize()
|
|
1669
|
+
return NSC
|
|
1670
|
+
|
|
1671
|
+
cpdef SetSystem noncospanning_cocircuits(self):
|
|
1672
|
+
"""
|
|
1673
|
+
Return the noncospanning cocircuits of the matroid.
|
|
1674
|
+
|
|
1675
|
+
A *noncospanning cocircuit* is a cocircuit whose corank is strictly
|
|
1676
|
+
smaller than the corank of the matroid.
|
|
1677
|
+
|
|
1678
|
+
OUTPUT: iterable containing all nonspanning circuits
|
|
1679
|
+
|
|
1680
|
+
.. SEEALSO::
|
|
1681
|
+
|
|
1682
|
+
:meth:`Matroid.cocircuit() <sage.matroids.matroid.Matroid.cocircuit>`,
|
|
1683
|
+
:meth:`Matroid.corank() <sage.matroids.matroid.Matroid.corank>`
|
|
1684
|
+
|
|
1685
|
+
EXAMPLES::
|
|
1686
|
+
|
|
1687
|
+
sage: M = matroids.catalog.N1()
|
|
1688
|
+
sage: len(M.noncospanning_cocircuits())
|
|
1689
|
+
23
|
|
1690
|
+
"""
|
|
1691
|
+
cdef SetSystem NSC
|
|
1692
|
+
NSC = SetSystem(self._E)
|
|
1693
|
+
if self._groundset_size == 0:
|
|
1694
|
+
return NSC
|
|
1695
|
+
bitset_clear(self._input)
|
|
1696
|
+
bitset_set_first_n(self._input, self._matroid_rank)
|
|
1697
|
+
cdef long e, f, corank
|
|
1698
|
+
corank = self._groundset_size - self._matroid_rank
|
|
1699
|
+
repeat = True
|
|
1700
|
+
while repeat:
|
|
1701
|
+
if self.__is_independent(self._input):
|
|
1702
|
+
bitset_copy(self._input2, self._current_basis)
|
|
1703
|
+
e = bitset_first(self._current_basis)
|
|
1704
|
+
for e in range(self._groundset_size):
|
|
1705
|
+
if not bitset_in(self._current_basis, e):
|
|
1706
|
+
self.__fundamental_circuit(self._output, e)
|
|
1707
|
+
if e > bitset_first(self._output):
|
|
1708
|
+
bitset_intersection(self._input2, self._input2, self._output)
|
|
1709
|
+
f = bitset_first(self._input2)
|
|
1710
|
+
while f >= 0:
|
|
1711
|
+
self.__fundamental_cocircuit(self._output, f)
|
|
1712
|
+
if f == bitset_first(self._output) and bitset_len(self._output) <= corank:
|
|
1713
|
+
NSC._append(self._output)
|
|
1714
|
+
f = bitset_next(self._input2, f + 1)
|
|
1715
|
+
repeat = nxksrd(self._input, self._groundset_size, self._matroid_rank, True)
|
|
1716
|
+
NSC.resize()
|
|
1717
|
+
return NSC
|
|
1718
|
+
|
|
1719
|
+
cpdef SetSystem cocircuits(self):
|
|
1720
|
+
"""
|
|
1721
|
+
Return the cocircuits of the matroid.
|
|
1722
|
+
|
|
1723
|
+
OUTPUT: iterable containing all cocircuits
|
|
1724
|
+
|
|
1725
|
+
.. SEEALSO::
|
|
1726
|
+
|
|
1727
|
+
:meth:`Matroid.cocircuit() <sage.matroids.matroid.Matroid.cocircuit>`
|
|
1728
|
+
|
|
1729
|
+
EXAMPLES::
|
|
1730
|
+
|
|
1731
|
+
sage: M = Matroid(bases=matroids.catalog.NonFano().bases())
|
|
1732
|
+
sage: sorted([sorted(C) for C in M.cocircuits()])
|
|
1733
|
+
[['a', 'b', 'c', 'd', 'g'], ['a', 'b', 'c', 'e', 'g'],
|
|
1734
|
+
['a', 'b', 'c', 'f', 'g'], ['a', 'b', 'd', 'e'],
|
|
1735
|
+
['a', 'c', 'd', 'f'], ['a', 'e', 'f', 'g'], ['b', 'c', 'e', 'f'],
|
|
1736
|
+
['b', 'd', 'f', 'g'], ['c', 'd', 'e', 'g']]
|
|
1737
|
+
"""
|
|
1738
|
+
cdef SetSystem NSC
|
|
1739
|
+
NSC = SetSystem(self._E)
|
|
1740
|
+
if self._groundset_size == 0:
|
|
1741
|
+
return NSC
|
|
1742
|
+
bitset_clear(self._input)
|
|
1743
|
+
bitset_set_first_n(self._input, self._matroid_rank)
|
|
1744
|
+
cdef long e, f
|
|
1745
|
+
repeat = True
|
|
1746
|
+
while repeat:
|
|
1747
|
+
if self.__is_independent(self._input):
|
|
1748
|
+
bitset_copy(self._input2, self._current_basis)
|
|
1749
|
+
e = bitset_first(self._current_basis)
|
|
1750
|
+
for e in range(self._groundset_size):
|
|
1751
|
+
if not bitset_in(self._current_basis, e):
|
|
1752
|
+
self.__fundamental_circuit(self._output, e)
|
|
1753
|
+
if e > bitset_first(self._output):
|
|
1754
|
+
bitset_intersection(self._input2, self._input2, self._output)
|
|
1755
|
+
f = bitset_first(self._input2)
|
|
1756
|
+
while f >= 0:
|
|
1757
|
+
self.__fundamental_cocircuit(self._output, f)
|
|
1758
|
+
if f == bitset_first(self._output):
|
|
1759
|
+
NSC._append(self._output)
|
|
1760
|
+
f = bitset_next(self._input2, f + 1)
|
|
1761
|
+
repeat = nxksrd(self._input, self._groundset_size, self._matroid_rank, True)
|
|
1762
|
+
NSC.resize()
|
|
1763
|
+
return NSC
|
|
1764
|
+
|
|
1765
|
+
cpdef SetSystem circuits(self, k=None):
|
|
1766
|
+
"""
|
|
1767
|
+
Return the circuits of the matroid.
|
|
1768
|
+
|
|
1769
|
+
OUTPUT: iterable containing all circuits
|
|
1770
|
+
|
|
1771
|
+
.. SEEALSO::
|
|
1772
|
+
|
|
1773
|
+
:meth:`M.circuit() <sage.matroids.matroid.Matroid.circuit>`
|
|
1774
|
+
|
|
1775
|
+
EXAMPLES::
|
|
1776
|
+
|
|
1777
|
+
sage: M = Matroid(matroids.catalog.NonFano().bases())
|
|
1778
|
+
sage: sorted([sorted(C) for C in M.circuits()])
|
|
1779
|
+
[['a', 'b', 'c', 'g'], ['a', 'b', 'd', 'e'], ['a', 'b', 'f'],
|
|
1780
|
+
['a', 'c', 'd', 'f'], ['a', 'c', 'e'], ['a', 'd', 'e', 'f'],
|
|
1781
|
+
['a', 'd', 'g'], ['a', 'e', 'f', 'g'], ['b', 'c', 'd'],
|
|
1782
|
+
['b', 'c', 'e', 'f'], ['b', 'd', 'e', 'f'], ['b', 'd', 'f', 'g'],
|
|
1783
|
+
['b', 'e', 'g'], ['c', 'd', 'e', 'f'], ['c', 'd', 'e', 'g'],
|
|
1784
|
+
['c', 'f', 'g'], ['d', 'e', 'f', 'g']]
|
|
1785
|
+
"""
|
|
1786
|
+
cdef SetSystem NSC
|
|
1787
|
+
NSC = SetSystem(self._E)
|
|
1788
|
+
if self._groundset_size == 0:
|
|
1789
|
+
return NSC
|
|
1790
|
+
bitset_clear(self._input)
|
|
1791
|
+
bitset_set_first_n(self._input, self._matroid_rank)
|
|
1792
|
+
cdef long e, f
|
|
1793
|
+
repeat = True
|
|
1794
|
+
while repeat:
|
|
1795
|
+
if self.__is_independent(self._input):
|
|
1796
|
+
bitset_complement(self._input2, self._current_basis)
|
|
1797
|
+
e = bitset_first(self._current_basis)
|
|
1798
|
+
while e >= 0:
|
|
1799
|
+
self.__fundamental_cocircuit(self._output, e)
|
|
1800
|
+
if e > bitset_first(self._output):
|
|
1801
|
+
bitset_intersection(self._input2, self._input2, self._output)
|
|
1802
|
+
e = bitset_next(self._current_basis, e + 1)
|
|
1803
|
+
f = bitset_first(self._input2)
|
|
1804
|
+
while f >= 0:
|
|
1805
|
+
self.__fundamental_circuit(self._output, f)
|
|
1806
|
+
if f == bitset_first(self._output):
|
|
1807
|
+
NSC._append(self._output)
|
|
1808
|
+
f = bitset_next(self._input2, f + 1)
|
|
1809
|
+
repeat = nxksrd(self._input, self._groundset_size, self._matroid_rank, True)
|
|
1810
|
+
NSC.resize()
|
|
1811
|
+
if k:
|
|
1812
|
+
return SetSystem(self.groundset(), [C for C in NSC if len(C) == k])
|
|
1813
|
+
else:
|
|
1814
|
+
return NSC
|
|
1815
|
+
|
|
1816
|
+
# isomorphism
|
|
1817
|
+
|
|
1818
|
+
cpdef _characteristic_setsystem(self):
|
|
1819
|
+
r"""
|
|
1820
|
+
Return a characteristic set-system for this matroid, on the same
|
|
1821
|
+
groundset.
|
|
1822
|
+
|
|
1823
|
+
OUTPUT: :class:`<sage.matroids.set_system.SetSystem>`
|
|
1824
|
+
|
|
1825
|
+
EXAMPLES::
|
|
1826
|
+
|
|
1827
|
+
sage: M = matroids.catalog.N1()
|
|
1828
|
+
sage: M._characteristic_setsystem()
|
|
1829
|
+
SetSystem of 23 sets over 10 elements
|
|
1830
|
+
sage: len(M._characteristic_setsystem())
|
|
1831
|
+
23
|
|
1832
|
+
"""
|
|
1833
|
+
if 2 * self._matroid_rank > self._groundset_size:
|
|
1834
|
+
return self.nonspanning_circuits()
|
|
1835
|
+
else:
|
|
1836
|
+
return self.noncospanning_cocircuits()
|
|
1837
|
+
|
|
1838
|
+
cpdef _weak_invariant(self):
|
|
1839
|
+
"""
|
|
1840
|
+
Return an isomorphism invariant of the matroid.
|
|
1841
|
+
|
|
1842
|
+
Compared to ``BasisExchangeMatroid._strong_invariant()`` this invariant
|
|
1843
|
+
distinguishes less frequently between nonisomorphic matroids but takes
|
|
1844
|
+
less time to compute. See also
|
|
1845
|
+
:meth:`<BasisExchangeMatroid._weak_partition>`.
|
|
1846
|
+
|
|
1847
|
+
OUTPUT: integer isomorphism invariant
|
|
1848
|
+
|
|
1849
|
+
EXAMPLES::
|
|
1850
|
+
|
|
1851
|
+
sage: M = Matroid(bases=matroids.catalog.Fano().bases())
|
|
1852
|
+
sage: N = Matroid(matroids.catalog.NonFano().bases())
|
|
1853
|
+
sage: M._weak_invariant() == N._weak_invariant()
|
|
1854
|
+
False
|
|
1855
|
+
"""
|
|
1856
|
+
from sage.matroids.utilities import cmp_elements_key
|
|
1857
|
+
if self._weak_invariant_var is None:
|
|
1858
|
+
if self.full_rank() == 0 or self.full_corank() == 0:
|
|
1859
|
+
self._weak_invariant_var = 0
|
|
1860
|
+
self._weak_partition_var = SetSystem(self._E, [self.groundset()])
|
|
1861
|
+
else:
|
|
1862
|
+
k = min(self.full_rank() - 1, 2)
|
|
1863
|
+
fie, f_vec = self._flat_element_inv(k)
|
|
1864
|
+
self._weak_invariant_var = hash(tuple([tuple([(f, len(fie[f])) for f in sorted(fie, key=cmp_elements_key)]), f_vec]))
|
|
1865
|
+
self._weak_partition_var = SetSystem(self._E, [fie[f] for f in sorted(fie, key=cmp_elements_key)])
|
|
1866
|
+
return self._weak_invariant_var
|
|
1867
|
+
|
|
1868
|
+
cpdef _weak_partition(self):
|
|
1869
|
+
"""
|
|
1870
|
+
Return an ordered partition based on the incidences of elements with
|
|
1871
|
+
low-dimensional flats.
|
|
1872
|
+
|
|
1873
|
+
EXAMPLES::
|
|
1874
|
+
|
|
1875
|
+
sage: M = Matroid(matroids.catalog.Vamos().bases())
|
|
1876
|
+
sage: [sorted(p) for p in M._weak_partition()]
|
|
1877
|
+
[['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']]
|
|
1878
|
+
"""
|
|
1879
|
+
self._weak_invariant()
|
|
1880
|
+
return self._weak_partition_var
|
|
1881
|
+
|
|
1882
|
+
cpdef _strong_invariant(self):
|
|
1883
|
+
"""
|
|
1884
|
+
Return an isomorphism invariant of the matroid.
|
|
1885
|
+
|
|
1886
|
+
Compared to ``BasisExchangeMatroid._weak_invariant()`` this invariant
|
|
1887
|
+
distinguishes more frequently between nonisomorphic matroids but takes
|
|
1888
|
+
more time to compute. See also
|
|
1889
|
+
:meth:`<BasisExchangeMatroid._strong_partition>`.
|
|
1890
|
+
|
|
1891
|
+
OUTPUT: integer isomorphism invariant
|
|
1892
|
+
|
|
1893
|
+
EXAMPLES::
|
|
1894
|
+
|
|
1895
|
+
sage: M = Matroid(matroids.catalog.Fano().bases())
|
|
1896
|
+
sage: N = Matroid(matroids.catalog.NonFano().bases())
|
|
1897
|
+
sage: M._strong_invariant() == N._strong_invariant()
|
|
1898
|
+
False
|
|
1899
|
+
"""
|
|
1900
|
+
if self._strong_invariant_var is None:
|
|
1901
|
+
CP = self._characteristic_setsystem()._equitable_partition(self._weak_partition())
|
|
1902
|
+
self._strong_partition_var = CP[0]
|
|
1903
|
+
self._strong_invariant_var = CP[2]
|
|
1904
|
+
return self._strong_invariant_var
|
|
1905
|
+
|
|
1906
|
+
cpdef _strong_partition(self):
|
|
1907
|
+
"""
|
|
1908
|
+
Return an equitable partition which refines ``_weak_partition()``.
|
|
1909
|
+
|
|
1910
|
+
EXAMPLES::
|
|
1911
|
+
|
|
1912
|
+
sage: from sage.matroids.advanced import *
|
|
1913
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
1914
|
+
sage: [sorted(p) for p in M._strong_partition()]
|
|
1915
|
+
[['a', 'b', 'e', 'f'], ['c', 'd', 'g', 'h']]
|
|
1916
|
+
"""
|
|
1917
|
+
self._strong_invariant()
|
|
1918
|
+
return self._strong_partition_var
|
|
1919
|
+
|
|
1920
|
+
cpdef _heuristic_invariant(self):
|
|
1921
|
+
"""
|
|
1922
|
+
Return a number characteristic for the construction of
|
|
1923
|
+
``_heuristic_partition()``.
|
|
1924
|
+
|
|
1925
|
+
EXAMPLES::
|
|
1926
|
+
|
|
1927
|
+
sage: from sage.matroids.advanced import *
|
|
1928
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
1929
|
+
sage: N = BasisMatroid(matroids.catalog.Vamos())
|
|
1930
|
+
sage: M._heuristic_invariant() == N._heuristic_invariant()
|
|
1931
|
+
True
|
|
1932
|
+
"""
|
|
1933
|
+
if self._heuristic_invariant_var is None:
|
|
1934
|
+
CP = self._characteristic_setsystem()._heuristic_partition(self._strong_partition())
|
|
1935
|
+
self._heuristic_partition_var = CP[0]
|
|
1936
|
+
self._heuristic_invariant_var = CP[2]
|
|
1937
|
+
return self._heuristic_invariant_var
|
|
1938
|
+
|
|
1939
|
+
cpdef _heuristic_partition(self):
|
|
1940
|
+
"""
|
|
1941
|
+
Return an ordered partition into singletons which refines an equitable
|
|
1942
|
+
partition of the matroid.
|
|
1943
|
+
|
|
1944
|
+
The purpose of this partition is to heuristically find an isomorphism
|
|
1945
|
+
between two matroids, by lining up their respective
|
|
1946
|
+
``heuristic_partitions``.
|
|
1947
|
+
|
|
1948
|
+
EXAMPLES::
|
|
1949
|
+
|
|
1950
|
+
sage: from sage.matroids.advanced import *
|
|
1951
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
1952
|
+
sage: N = BasisMatroid(matroids.catalog.Vamos())
|
|
1953
|
+
sage: PM = M._heuristic_partition()
|
|
1954
|
+
sage: PN = N._heuristic_partition()
|
|
1955
|
+
sage: morphism = {}
|
|
1956
|
+
sage: for i in range(len(M)): morphism[min(PM[i])] = min(PN[i])
|
|
1957
|
+
sage: M._is_isomorphism(N, morphism)
|
|
1958
|
+
True
|
|
1959
|
+
"""
|
|
1960
|
+
self._heuristic_invariant()
|
|
1961
|
+
return self._heuristic_partition_var
|
|
1962
|
+
|
|
1963
|
+
cdef _flush(self):
|
|
1964
|
+
"""
|
|
1965
|
+
Delete all invariants.
|
|
1966
|
+
"""
|
|
1967
|
+
self._weak_invariant_var = None
|
|
1968
|
+
self._strong_invariant_var = None
|
|
1969
|
+
self._heuristic_invariant_var = None
|
|
1970
|
+
|
|
1971
|
+
cpdef _equitable_partition(self, P=None):
|
|
1972
|
+
"""
|
|
1973
|
+
Return the equitable refinement of a given ordered partition.
|
|
1974
|
+
|
|
1975
|
+
The coarsest equitable partition of the groundset of this matroid
|
|
1976
|
+
that refines P.
|
|
1977
|
+
|
|
1978
|
+
INPUT:
|
|
1979
|
+
|
|
1980
|
+
- ``P`` -- ordered partition of the groundset (default: ``None``);
|
|
1981
|
+
if ``None``, the trivial partition is used
|
|
1982
|
+
|
|
1983
|
+
OUTPUT: SetSystem
|
|
1984
|
+
|
|
1985
|
+
EXAMPLES::
|
|
1986
|
+
|
|
1987
|
+
sage: from sage.matroids.advanced import *
|
|
1988
|
+
sage: M = BasisMatroid(matroids.catalog.Vamos())
|
|
1989
|
+
sage: [sorted(p) for p in M._equitable_partition()]
|
|
1990
|
+
[['a', 'b', 'e', 'f'], ['c', 'd', 'g', 'h']]
|
|
1991
|
+
sage: [sorted(p) for p in M._equitable_partition(['a', 'bcdefgh'])]
|
|
1992
|
+
[['a'], ['b'], ['e', 'f'], ['c', 'd', 'g', 'h']]
|
|
1993
|
+
"""
|
|
1994
|
+
if P is not None:
|
|
1995
|
+
EQ = self._characteristic_setsystem()._equitable_partition(SetSystem(self._E, P))
|
|
1996
|
+
else:
|
|
1997
|
+
EQ = self._characteristic_setsystem()._equitable_partition()
|
|
1998
|
+
return EQ[0]
|
|
1999
|
+
|
|
2000
|
+
cpdef _is_isomorphism(self, other, morphism):
|
|
2001
|
+
r"""
|
|
2002
|
+
Version of ``is_isomorphism()`` that does no type checking.
|
|
2003
|
+
|
|
2004
|
+
INPUT:
|
|
2005
|
+
|
|
2006
|
+
- ``other`` -- matroid
|
|
2007
|
+
- ``morphism`` -- dictionary mapping the groundset of ``self`` to
|
|
2008
|
+
the groundset of ``other``
|
|
2009
|
+
|
|
2010
|
+
OUTPUT: boolean
|
|
2011
|
+
|
|
2012
|
+
EXAMPLES::
|
|
2013
|
+
|
|
2014
|
+
sage: from sage.matroids.advanced import *
|
|
2015
|
+
sage: M = matroids.catalog.Pappus()
|
|
2016
|
+
sage: N = BasisMatroid(matroids.catalog.NonPappus())
|
|
2017
|
+
sage: N._is_isomorphism(M, {e:e for e in M.groundset()})
|
|
2018
|
+
False
|
|
2019
|
+
|
|
2020
|
+
sage: M = matroids.catalog.Fano().delete(['g'])
|
|
2021
|
+
sage: N = matroids.Wheel(3)
|
|
2022
|
+
sage: morphism = {'a':0, 'b':1, 'c': 2, 'd':4, 'e':5, 'f':3}
|
|
2023
|
+
sage: M._is_isomorphism(N, morphism)
|
|
2024
|
+
True
|
|
2025
|
+
|
|
2026
|
+
TESTS:
|
|
2027
|
+
|
|
2028
|
+
Check that :issue:`23300` was fixed::
|
|
2029
|
+
|
|
2030
|
+
sage: def f(X):
|
|
2031
|
+
....: return min(len(X), 2)
|
|
2032
|
+
....:
|
|
2033
|
+
sage: M = Matroid(groundset='abcd', rank_function=f)
|
|
2034
|
+
sage: N = Matroid(field=GF(3), reduced_matrix=[[1,1],[1,-1]])
|
|
2035
|
+
sage: N._is_isomorphism(M, {0:'a', 1:'b', 2:'c', 3:'d'})
|
|
2036
|
+
True
|
|
2037
|
+
"""
|
|
2038
|
+
if not isinstance(other, BasisExchangeMatroid):
|
|
2039
|
+
from sage.matroids.basis_matroid import BasisMatroid
|
|
2040
|
+
ot = BasisMatroid(other)
|
|
2041
|
+
else:
|
|
2042
|
+
ot = other
|
|
2043
|
+
return self.__is_isomorphism(ot, morphism)
|
|
2044
|
+
|
|
2045
|
+
cdef bint __is_isomorphism(self, BasisExchangeMatroid other, morphism) noexcept:
|
|
2046
|
+
"""
|
|
2047
|
+
Bitpacked version of ``is_isomorphism``.
|
|
2048
|
+
"""
|
|
2049
|
+
cdef long i
|
|
2050
|
+
morph = [other._idx[morphism[self._E[i]]] for i in range(len(self))]
|
|
2051
|
+
bitset_clear(self._input)
|
|
2052
|
+
bitset_set_first_n(self._input, self._matroid_rank)
|
|
2053
|
+
repeat = True
|
|
2054
|
+
while repeat:
|
|
2055
|
+
bitset_clear(other._input)
|
|
2056
|
+
i = bitset_first(self._input)
|
|
2057
|
+
while i != -1:
|
|
2058
|
+
bitset_add(other._input, <mp_bitcnt_t> morph[i])
|
|
2059
|
+
i = bitset_next(self._input, i + 1)
|
|
2060
|
+
if self.__is_independent(self._input) != other.__is_independent(other._input):
|
|
2061
|
+
return False
|
|
2062
|
+
repeat = nxksrd(self._input, self._groundset_size, self._matroid_rank, True)
|
|
2063
|
+
return True
|
|
2064
|
+
|
|
2065
|
+
cpdef _isomorphism(self, other):
|
|
2066
|
+
"""
|
|
2067
|
+
Return an isomorphism form ``self`` to ``other``, if one exists.
|
|
2068
|
+
|
|
2069
|
+
Internal version that performs no checks on input.
|
|
2070
|
+
|
|
2071
|
+
INPUT:
|
|
2072
|
+
|
|
2073
|
+
- ``other`` -- matroid
|
|
2074
|
+
|
|
2075
|
+
OUTPUT: dictionary or ``None``
|
|
2076
|
+
|
|
2077
|
+
EXAMPLES::
|
|
2078
|
+
|
|
2079
|
+
sage: from sage.matroids.advanced import *
|
|
2080
|
+
sage: M1 = matroids.Wheel(3)
|
|
2081
|
+
sage: M2 = matroids.CompleteGraphic(4) # needs sage.graphs
|
|
2082
|
+
sage: morphism = M1._isomorphism(M2) # needs sage.graphs
|
|
2083
|
+
sage: M1._is_isomorphism(M2, morphism) # needs sage.graphs
|
|
2084
|
+
True
|
|
2085
|
+
sage: M1 = matroids.catalog.Fano()
|
|
2086
|
+
sage: M2 = matroids.catalog.NonFano()
|
|
2087
|
+
sage: M1._isomorphism(M2) is None
|
|
2088
|
+
True
|
|
2089
|
+
|
|
2090
|
+
TESTS:
|
|
2091
|
+
|
|
2092
|
+
Check that :issue:`23300` was fixed::
|
|
2093
|
+
|
|
2094
|
+
sage: def f(X):
|
|
2095
|
+
....: return min(len(X), 2)
|
|
2096
|
+
....:
|
|
2097
|
+
sage: M = Matroid(groundset='abcd', rank_function=f)
|
|
2098
|
+
sage: N = Matroid(field=GF(3), reduced_matrix=[[1,1],[1,-1]])
|
|
2099
|
+
sage: N._isomorphism(M) is not None
|
|
2100
|
+
True
|
|
2101
|
+
"""
|
|
2102
|
+
if not isinstance(other, BasisExchangeMatroid):
|
|
2103
|
+
from sage.matroids.basis_matroid import BasisMatroid
|
|
2104
|
+
other = BasisMatroid(other)
|
|
2105
|
+
if self is other:
|
|
2106
|
+
return {e: e for e in self.groundset()}
|
|
2107
|
+
if len(self) != len(other):
|
|
2108
|
+
return None
|
|
2109
|
+
if self.full_rank() != other.full_rank():
|
|
2110
|
+
return None
|
|
2111
|
+
if self.full_rank() == 0 or self.full_corank() == 0:
|
|
2112
|
+
return {self.groundset_list()[i]: other.groundset_list()[i] for i in range(len(self))}
|
|
2113
|
+
|
|
2114
|
+
if self._weak_invariant() != other._weak_invariant():
|
|
2115
|
+
return None
|
|
2116
|
+
PS = self._weak_partition()
|
|
2117
|
+
PO = other._weak_partition()
|
|
2118
|
+
if len(PS) == len(self) and len(PO) == len(other):
|
|
2119
|
+
morphism = {}
|
|
2120
|
+
for i in range(len(self)):
|
|
2121
|
+
morphism[min(PS[i])] = min(PO[i])
|
|
2122
|
+
if self.__is_isomorphism(other, morphism):
|
|
2123
|
+
return morphism
|
|
2124
|
+
else:
|
|
2125
|
+
return None
|
|
2126
|
+
|
|
2127
|
+
if self._strong_invariant() != other._strong_invariant():
|
|
2128
|
+
return False
|
|
2129
|
+
PS = self._strong_partition()
|
|
2130
|
+
PO = other._strong_partition()
|
|
2131
|
+
if len(PS) == len(self) and len(PO) == len(other):
|
|
2132
|
+
morphism = {}
|
|
2133
|
+
for i in range(len(self)):
|
|
2134
|
+
morphism[min(PS[i])] = min(PO[i])
|
|
2135
|
+
if self.__is_isomorphism(other, morphism):
|
|
2136
|
+
return morphism
|
|
2137
|
+
else:
|
|
2138
|
+
return None
|
|
2139
|
+
|
|
2140
|
+
if self._heuristic_invariant() == other._heuristic_invariant():
|
|
2141
|
+
PHS = self._heuristic_partition()
|
|
2142
|
+
PHO = other._heuristic_partition()
|
|
2143
|
+
morphism = {}
|
|
2144
|
+
for i in range(len(self)):
|
|
2145
|
+
morphism[min(PHS[i])] = min(PHO[i])
|
|
2146
|
+
if self.__is_isomorphism(other, morphism):
|
|
2147
|
+
return morphism
|
|
2148
|
+
|
|
2149
|
+
return self._characteristic_setsystem()._isomorphism(other._characteristic_setsystem(), PS, PO)
|
|
2150
|
+
|
|
2151
|
+
cpdef _is_isomorphic(self, other, certificate=False):
|
|
2152
|
+
"""
|
|
2153
|
+
Test if ``self`` is isomorphic to ``other``.
|
|
2154
|
+
|
|
2155
|
+
Internal version that performs no checks on input.
|
|
2156
|
+
|
|
2157
|
+
INPUT:
|
|
2158
|
+
|
|
2159
|
+
- ``other`` -- matroid
|
|
2160
|
+
- ``certificate`` -- boolean (default: ``False``)
|
|
2161
|
+
|
|
2162
|
+
OUTPUT: boolean, and, if ``certificate = True``, a dictionary giving
|
|
2163
|
+
the isomorphism or ``None``
|
|
2164
|
+
|
|
2165
|
+
.. NOTE::
|
|
2166
|
+
|
|
2167
|
+
Internal version that does no input checking.
|
|
2168
|
+
|
|
2169
|
+
EXAMPLES::
|
|
2170
|
+
|
|
2171
|
+
sage: from sage.matroids.advanced import *
|
|
2172
|
+
sage: M1 = BasisMatroid(matroids.Wheel(3))
|
|
2173
|
+
sage: M2 = matroids.CompleteGraphic(4) # needs sage.graphs
|
|
2174
|
+
sage: M1._is_isomorphic(M2) # needs sage.graphs
|
|
2175
|
+
True
|
|
2176
|
+
sage: M1._is_isomorphic(M2, certificate=True) # needs sage.graphs
|
|
2177
|
+
(True, {0: 0, 1: 1, 2: 2, 3: 3, 4: 5, 5: 4})
|
|
2178
|
+
sage: M1 = BasisMatroid(matroids.catalog.Fano())
|
|
2179
|
+
sage: M2 = matroids.catalog.NonFano()
|
|
2180
|
+
sage: M1._is_isomorphic(M2)
|
|
2181
|
+
False
|
|
2182
|
+
sage: M1._is_isomorphic(M2, certificate=True)
|
|
2183
|
+
(False, None)
|
|
2184
|
+
"""
|
|
2185
|
+
if certificate:
|
|
2186
|
+
return self._is_isomorphic(other), self._isomorphism(other)
|
|
2187
|
+
if not isinstance(other, BasisExchangeMatroid):
|
|
2188
|
+
return other._is_isomorphic(self)
|
|
2189
|
+
# Either generic test, which converts other to BasisMatroid,
|
|
2190
|
+
# or overridden method.
|
|
2191
|
+
if self is other:
|
|
2192
|
+
return True
|
|
2193
|
+
if len(self) != len(other):
|
|
2194
|
+
return False
|
|
2195
|
+
if self.full_rank() != other.full_rank():
|
|
2196
|
+
return False
|
|
2197
|
+
if self.full_rank() == 0 or self.full_corank() == 0:
|
|
2198
|
+
return True
|
|
2199
|
+
if self.full_rank() == 1:
|
|
2200
|
+
return len(self.loops()) == len(other.loops())
|
|
2201
|
+
if self.full_corank() == 1:
|
|
2202
|
+
return len(self.coloops()) == len(other.coloops())
|
|
2203
|
+
|
|
2204
|
+
if self._weak_invariant() != other._weak_invariant():
|
|
2205
|
+
return False
|
|
2206
|
+
PS = self._weak_partition()
|
|
2207
|
+
PO = other._weak_partition()
|
|
2208
|
+
if len(PS) == len(self) and len(PO) == len(other):
|
|
2209
|
+
morphism = {}
|
|
2210
|
+
for i in range(len(self)):
|
|
2211
|
+
morphism[min(PS[i])] = min(PO[i])
|
|
2212
|
+
return self.__is_isomorphism(other, morphism)
|
|
2213
|
+
|
|
2214
|
+
if self._strong_invariant() != other._strong_invariant():
|
|
2215
|
+
return False
|
|
2216
|
+
PS = self._strong_partition()
|
|
2217
|
+
PO = other._strong_partition()
|
|
2218
|
+
if len(PS) == len(self) and len(PO) == len(other):
|
|
2219
|
+
morphism = {}
|
|
2220
|
+
for i in range(len(self)):
|
|
2221
|
+
morphism[min(PS[i])] = min(PO[i])
|
|
2222
|
+
return self.__is_isomorphism(other, morphism)
|
|
2223
|
+
|
|
2224
|
+
if self._heuristic_invariant() == other._heuristic_invariant():
|
|
2225
|
+
PHS = self._heuristic_partition()
|
|
2226
|
+
PHO = other._heuristic_partition()
|
|
2227
|
+
morphism = {}
|
|
2228
|
+
for i in range(len(self)):
|
|
2229
|
+
morphism[min(PHS[i])] = min(PHO[i])
|
|
2230
|
+
if self.__is_isomorphism(other, morphism):
|
|
2231
|
+
return True
|
|
2232
|
+
|
|
2233
|
+
return self._characteristic_setsystem()._isomorphism(other._characteristic_setsystem(), PS, PO) is not None
|
|
2234
|
+
|
|
2235
|
+
cpdef is_valid(self, certificate=False):
|
|
2236
|
+
r"""
|
|
2237
|
+
Test if the data obey the matroid axioms.
|
|
2238
|
+
|
|
2239
|
+
This method checks the basis axioms for the class. If `B` is the set
|
|
2240
|
+
of bases of a matroid `M`, then
|
|
2241
|
+
|
|
2242
|
+
* `B` is nonempty
|
|
2243
|
+
* if `X` and `Y` are in `B`, and `x` is in `X - Y`, then there is a
|
|
2244
|
+
`y` in `Y - X` such that `(X - x) + y` is again a member of `B`.
|
|
2245
|
+
|
|
2246
|
+
INPUT:
|
|
2247
|
+
|
|
2248
|
+
- ``certificate`` -- boolean (default: ``False``)
|
|
2249
|
+
|
|
2250
|
+
OUTPUT: boolean, or (boolean, dictionary)
|
|
2251
|
+
|
|
2252
|
+
EXAMPLES::
|
|
2253
|
+
|
|
2254
|
+
sage: from sage.matroids.advanced import *
|
|
2255
|
+
sage: M = BasisMatroid(matroids.catalog.Fano())
|
|
2256
|
+
sage: M.is_valid()
|
|
2257
|
+
True
|
|
2258
|
+
sage: M = Matroid(groundset='abcd', bases=['ab', 'cd'])
|
|
2259
|
+
sage: M.is_valid(certificate=True)
|
|
2260
|
+
(False, {'error': 'exchange axiom failed'})
|
|
2261
|
+
|
|
2262
|
+
TESTS:
|
|
2263
|
+
|
|
2264
|
+
Verify that :issue:`20172` was fixed::
|
|
2265
|
+
|
|
2266
|
+
sage: M = Matroid(groundset='1234', bases=['12','13','23','34'])
|
|
2267
|
+
sage: M.is_valid()
|
|
2268
|
+
False
|
|
2269
|
+
"""
|
|
2270
|
+
cdef long pointerX, pointerY, x, y, ln
|
|
2271
|
+
cdef bint foundpair
|
|
2272
|
+
cdef SetSystem BB
|
|
2273
|
+
BB = self.bases()
|
|
2274
|
+
pointerX = 0
|
|
2275
|
+
ln = len(BB)
|
|
2276
|
+
while pointerX < ln: # for X in BB
|
|
2277
|
+
pointerY = 0
|
|
2278
|
+
while pointerY < ln: # for Y in BB
|
|
2279
|
+
# Set current basis to Y
|
|
2280
|
+
bitset_difference(self._inside, self._current_basis, BB._subsets[pointerY])
|
|
2281
|
+
bitset_difference(self._outside, BB._subsets[pointerY], self._current_basis)
|
|
2282
|
+
self._move(self._inside, self._outside)
|
|
2283
|
+
if not bitset_eq(self._current_basis, BB._subsets[pointerY]):
|
|
2284
|
+
# We failed to set the current basis to Y through basis exchanges.
|
|
2285
|
+
# Therefore, the exchange axioms are violated!
|
|
2286
|
+
return False if not certificate else (False, {"error": "exchange axiom failed"})
|
|
2287
|
+
bitset_difference(self._input, BB._subsets[pointerX], BB._subsets[pointerY])
|
|
2288
|
+
bitset_difference(self._input2, BB._subsets[pointerY], BB._subsets[pointerX])
|
|
2289
|
+
x = bitset_first(self._input)
|
|
2290
|
+
while x >= 0: # for x in X-Y
|
|
2291
|
+
foundpair = False
|
|
2292
|
+
y = bitset_first(self._input2)
|
|
2293
|
+
while y >= 0: # for y in Y-X
|
|
2294
|
+
if self._is_exchange_pair(y, x):
|
|
2295
|
+
foundpair = True
|
|
2296
|
+
y = -1
|
|
2297
|
+
else:
|
|
2298
|
+
y = bitset_next(self._input2, y + 1)
|
|
2299
|
+
if not foundpair:
|
|
2300
|
+
return False if not certificate else (False, {"error": "exchange axiom failed"})
|
|
2301
|
+
x = bitset_next(self._input, x + 1)
|
|
2302
|
+
pointerY += 1
|
|
2303
|
+
pointerX += 1
|
|
2304
|
+
return True if not certificate else (True, {})
|
|
2305
|
+
|
|
2306
|
+
cdef bint nxksrd(bitset_s* b, long n, long k, bint succ) noexcept:
|
|
2307
|
+
"""
|
|
2308
|
+
Next size-k subset of a size-n set in a revolving-door sequence.
|
|
2309
|
+
|
|
2310
|
+
It will cycle through all such sets, returning each set exactly
|
|
2311
|
+
once. Each successive set differs from the last in exactly one
|
|
2312
|
+
element.
|
|
2313
|
+
|
|
2314
|
+
This returns ``True`` if there is a next set, ``False`` otherwise.
|
|
2315
|
+
"""
|
|
2316
|
+
# next k-subset of n-set in a revolving-door sequence
|
|
2317
|
+
if n == k or k == 0:
|
|
2318
|
+
return False
|
|
2319
|
+
if bitset_in(b, n - 1):
|
|
2320
|
+
if nxksrd(b, n - 1, k - 1, not succ):
|
|
2321
|
+
return True
|
|
2322
|
+
else:
|
|
2323
|
+
if succ:
|
|
2324
|
+
return False
|
|
2325
|
+
else:
|
|
2326
|
+
if k == 1:
|
|
2327
|
+
bitset_add(b, n - 2)
|
|
2328
|
+
else:
|
|
2329
|
+
bitset_add(b, k - 2)
|
|
2330
|
+
bitset_discard(b, n - 1)
|
|
2331
|
+
return True
|
|
2332
|
+
else:
|
|
2333
|
+
if nxksrd(b, n - 1, k, succ):
|
|
2334
|
+
return True
|
|
2335
|
+
else:
|
|
2336
|
+
if succ:
|
|
2337
|
+
if k == 1:
|
|
2338
|
+
bitset_discard(b, n - 2)
|
|
2339
|
+
else:
|
|
2340
|
+
bitset_discard(b, k - 2)
|
|
2341
|
+
bitset_add(b, n - 1)
|
|
2342
|
+
return True
|
|
2343
|
+
else:
|
|
2344
|
+
return False
|