passagemath-flint 10.6.1rc10__cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_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.
- passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
- passagemath_flint-10.6.1rc10.dist-info/RECORD +361 -0
- passagemath_flint-10.6.1rc10.dist-info/WHEEL +6 -0
- passagemath_flint-10.6.1rc10.dist-info/top_level.txt +2 -0
- passagemath_flint.libs/libflint-aecb9cc5.so.21.0.0 +0 -0
- passagemath_flint.libs/libgf2x-a4cdec90.so.3.0.0 +0 -0
- passagemath_flint.libs/libgfortran-8f1e9814.so.5.0.0 +0 -0
- passagemath_flint.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_flint.libs/libgsl-cda90e79.so.28.0.0 +0 -0
- passagemath_flint.libs/libmpfi-e3c25853.so.0.0.0 +0 -0
- passagemath_flint.libs/libmpfr-82690d50.so.6.2.1 +0 -0
- passagemath_flint.libs/libntl-74e7d9a3.so.44.0.1 +0 -0
- passagemath_flint.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
- passagemath_flint.libs/libquadmath-828275a7.so.0.0.0 +0 -0
- sage/all__sagemath_flint.py +29 -0
- sage/combinat/all__sagemath_flint.py +1 -0
- sage/combinat/posets/all__sagemath_flint.py +1 -0
- sage/combinat/posets/hasse_cython_flint.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/combinat/posets/hasse_cython_flint.pyx +194 -0
- sage/data_structures/all__sagemath_flint.py +1 -0
- sage/data_structures/bounded_integer_sequences.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/data_structures/bounded_integer_sequences.pxd +62 -0
- sage/data_structures/bounded_integer_sequences.pyx +1418 -0
- sage/graphs/all__sagemath_flint.py +1 -0
- sage/graphs/chrompoly.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/graphs/chrompoly.pyx +555 -0
- sage/graphs/matchpoly.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/graphs/matchpoly.pyx +412 -0
- sage/libs/all__sagemath_flint.py +17 -0
- sage/libs/arb/__init__.py +1 -0
- sage/libs/arb/acb.pxd +154 -0
- sage/libs/arb/acb_calc.pxd +9 -0
- sage/libs/arb/acb_elliptic.pxd +25 -0
- sage/libs/arb/acb_hypgeom.pxd +74 -0
- sage/libs/arb/acb_mat.pxd +62 -0
- sage/libs/arb/acb_modular.pxd +17 -0
- sage/libs/arb/acb_poly.pxd +216 -0
- sage/libs/arb/arb.pxd +240 -0
- sage/libs/arb/arb_fmpz_poly.pxd +21 -0
- sage/libs/arb/arb_hypgeom.pxd +83 -0
- sage/libs/arb/arb_wrap.h +34 -0
- sage/libs/arb/arf.pxd +131 -0
- sage/libs/arb/arith.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/arb/arith.pyx +87 -0
- sage/libs/arb/bernoulli.pxd +6 -0
- sage/libs/arb/mag.pxd +77 -0
- sage/libs/arb/types.pxd +37 -0
- sage/libs/flint/__init__.py +1 -0
- sage/libs/flint/acb.pxd +270 -0
- sage/libs/flint/acb_calc.pxd +22 -0
- sage/libs/flint/acb_dft.pxd +51 -0
- sage/libs/flint/acb_dirichlet.pxd +112 -0
- sage/libs/flint/acb_elliptic.pxd +42 -0
- sage/libs/flint/acb_hypgeom.pxd +169 -0
- sage/libs/flint/acb_macros.pxd +9 -0
- sage/libs/flint/acb_mat.pxd +136 -0
- sage/libs/flint/acb_mat_macros.pxd +10 -0
- sage/libs/flint/acb_modular.pxd +62 -0
- sage/libs/flint/acb_poly.pxd +251 -0
- sage/libs/flint/acb_poly_macros.pxd +8 -0
- sage/libs/flint/acb_theta.pxd +124 -0
- sage/libs/flint/acf.pxd +32 -0
- sage/libs/flint/aprcl.pxd +84 -0
- sage/libs/flint/arb.pxd +382 -0
- sage/libs/flint/arb_calc.pxd +31 -0
- sage/libs/flint/arb_fmpz_poly.pxd +34 -0
- sage/libs/flint/arb_fpwrap.pxd +215 -0
- sage/libs/flint/arb_hypgeom.pxd +147 -0
- sage/libs/flint/arb_macros.pxd +9 -0
- sage/libs/flint/arb_mat.pxd +140 -0
- sage/libs/flint/arb_mat_macros.pxd +10 -0
- sage/libs/flint/arb_poly.pxd +237 -0
- sage/libs/flint/arf.pxd +167 -0
- sage/libs/flint/arith.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/arith.pxd +76 -0
- sage/libs/flint/arith.pyx +77 -0
- sage/libs/flint/arith_sage.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/arith_sage.pyx +308 -0
- sage/libs/flint/bernoulli.pxd +28 -0
- sage/libs/flint/bool_mat.pxd +52 -0
- sage/libs/flint/ca.pxd +203 -0
- sage/libs/flint/ca_ext.pxd +34 -0
- sage/libs/flint/ca_field.pxd +32 -0
- sage/libs/flint/ca_mat.pxd +117 -0
- sage/libs/flint/ca_poly.pxd +104 -0
- sage/libs/flint/ca_vec.pxd +46 -0
- sage/libs/flint/calcium.pxd +27 -0
- sage/libs/flint/d_mat.pxd +39 -0
- sage/libs/flint/d_vec.pxd +32 -0
- sage/libs/flint/dirichlet.pxd +57 -0
- sage/libs/flint/dlog.pxd +53 -0
- sage/libs/flint/double_extras.pxd +24 -0
- sage/libs/flint/double_interval.pxd +36 -0
- sage/libs/flint/fexpr.pxd +104 -0
- sage/libs/flint/fexpr_builtin.pxd +20 -0
- sage/libs/flint/fft.pxd +66 -0
- sage/libs/flint/flint.pxd +36 -0
- sage/libs/flint/flint_ntl_wrap.h +35 -0
- sage/libs/flint/flint_sage.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/flint_sage.pyx +163 -0
- sage/libs/flint/flint_wrap.h +190 -0
- sage/libs/flint/fmpq.pxd +137 -0
- sage/libs/flint/fmpq_mat.pxd +105 -0
- sage/libs/flint/fmpq_mat_macros.pxd +10 -0
- sage/libs/flint/fmpq_mpoly.pxd +165 -0
- sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
- sage/libs/flint/fmpq_poly.pxd +241 -0
- sage/libs/flint/fmpq_poly_macros.pxd +9 -0
- sage/libs/flint/fmpq_poly_sage.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/fmpq_poly_sage.pxd +31 -0
- sage/libs/flint/fmpq_poly_sage.pyx +48 -0
- sage/libs/flint/fmpq_vec.pxd +27 -0
- sage/libs/flint/fmpz.pxd +256 -0
- sage/libs/flint/fmpz_extras.pxd +32 -0
- sage/libs/flint/fmpz_factor.pxd +42 -0
- sage/libs/flint/fmpz_factor_sage.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_factor_sage.pxd +4 -0
- sage/libs/flint/fmpz_factor_sage.pyx +29 -0
- sage/libs/flint/fmpz_lll.pxd +49 -0
- sage/libs/flint/fmpz_macros.pxd +8 -0
- sage/libs/flint/fmpz_mat.pxd +184 -0
- sage/libs/flint/fmpz_mat_macros.pxd +10 -0
- sage/libs/flint/fmpz_mod.pxd +46 -0
- sage/libs/flint/fmpz_mod_mat.pxd +71 -0
- sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
- sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
- sage/libs/flint/fmpz_mod_poly.pxd +249 -0
- sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
- sage/libs/flint/fmpz_mod_vec.pxd +27 -0
- sage/libs/flint/fmpz_mpoly.pxd +224 -0
- sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
- sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
- sage/libs/flint/fmpz_poly.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_poly.pxd +407 -0
- sage/libs/flint/fmpz_poly.pyx +19 -0
- sage/libs/flint/fmpz_poly_factor.pxd +33 -0
- sage/libs/flint/fmpz_poly_macros.pxd +8 -0
- sage/libs/flint/fmpz_poly_mat.pxd +71 -0
- sage/libs/flint/fmpz_poly_q.pxd +55 -0
- sage/libs/flint/fmpz_poly_sage.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/fmpz_poly_sage.pxd +20 -0
- sage/libs/flint/fmpz_poly_sage.pyx +500 -0
- sage/libs/flint/fmpz_vec.pxd +80 -0
- sage/libs/flint/fmpzi.pxd +52 -0
- sage/libs/flint/fq.pxd +97 -0
- sage/libs/flint/fq_default.pxd +84 -0
- sage/libs/flint/fq_default_mat.pxd +70 -0
- sage/libs/flint/fq_default_poly.pxd +97 -0
- sage/libs/flint/fq_default_poly_factor.pxd +39 -0
- sage/libs/flint/fq_embed.pxd +28 -0
- sage/libs/flint/fq_mat.pxd +83 -0
- sage/libs/flint/fq_nmod.pxd +95 -0
- sage/libs/flint/fq_nmod_embed.pxd +28 -0
- sage/libs/flint/fq_nmod_mat.pxd +83 -0
- sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
- sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
- sage/libs/flint/fq_nmod_poly.pxd +202 -0
- sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
- sage/libs/flint/fq_nmod_vec.pxd +33 -0
- sage/libs/flint/fq_poly.pxd +204 -0
- sage/libs/flint/fq_poly_factor.pxd +47 -0
- sage/libs/flint/fq_vec.pxd +33 -0
- sage/libs/flint/fq_zech.pxd +99 -0
- sage/libs/flint/fq_zech_embed.pxd +28 -0
- sage/libs/flint/fq_zech_mat.pxd +78 -0
- sage/libs/flint/fq_zech_poly.pxd +198 -0
- sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
- sage/libs/flint/fq_zech_vec.pxd +33 -0
- sage/libs/flint/gr.pxd +174 -0
- sage/libs/flint/gr_generic.pxd +215 -0
- sage/libs/flint/gr_mat.pxd +161 -0
- sage/libs/flint/gr_mpoly.pxd +68 -0
- sage/libs/flint/gr_poly.pxd +276 -0
- sage/libs/flint/gr_special.pxd +237 -0
- sage/libs/flint/gr_vec.pxd +120 -0
- sage/libs/flint/hypgeom.pxd +24 -0
- sage/libs/flint/long_extras.pxd +23 -0
- sage/libs/flint/mag.pxd +131 -0
- sage/libs/flint/mag_macros.pxd +8 -0
- sage/libs/flint/mpf_mat.pxd +36 -0
- sage/libs/flint/mpf_vec.pxd +34 -0
- sage/libs/flint/mpfr_mat.pxd +27 -0
- sage/libs/flint/mpfr_vec.pxd +25 -0
- sage/libs/flint/mpn_extras.pxd +41 -0
- sage/libs/flint/mpoly.pxd +72 -0
- sage/libs/flint/nf.pxd +19 -0
- sage/libs/flint/nf_elem.pxd +74 -0
- sage/libs/flint/nmod.pxd +35 -0
- sage/libs/flint/nmod_mat.pxd +104 -0
- sage/libs/flint/nmod_mpoly.pxd +144 -0
- sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
- sage/libs/flint/nmod_poly.pxd +339 -0
- sage/libs/flint/nmod_poly_factor.pxd +44 -0
- sage/libs/flint/nmod_poly_linkage.pxi +710 -0
- sage/libs/flint/nmod_poly_mat.pxd +76 -0
- sage/libs/flint/nmod_vec.pxd +40 -0
- sage/libs/flint/ntl_interface.pxd +17 -0
- sage/libs/flint/padic.pxd +93 -0
- sage/libs/flint/padic_mat.pxd +64 -0
- sage/libs/flint/padic_poly.pxd +88 -0
- sage/libs/flint/partitions.pxd +23 -0
- sage/libs/flint/perm.pxd +26 -0
- sage/libs/flint/profiler.pxd +24 -0
- sage/libs/flint/qadic.pxd +77 -0
- sage/libs/flint/qfb.pxd +44 -0
- sage/libs/flint/qqbar.pxd +172 -0
- sage/libs/flint/qsieve.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/qsieve.pxd +41 -0
- sage/libs/flint/qsieve.pyx +21 -0
- sage/libs/flint/qsieve_sage.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/qsieve_sage.pyx +67 -0
- sage/libs/flint/thread_pool.pxd +25 -0
- sage/libs/flint/types.pxd +2076 -0
- sage/libs/flint/ulong_extras.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/ulong_extras.pxd +141 -0
- sage/libs/flint/ulong_extras.pyx +21 -0
- sage/libs/flint/ulong_extras_sage.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/libs/flint/ulong_extras_sage.pyx +21 -0
- sage/matrix/all__sagemath_flint.py +1 -0
- sage/matrix/change_ring.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/matrix/change_ring.pyx +43 -0
- sage/matrix/matrix_complex_ball_dense.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_complex_ball_dense.pxd +14 -0
- sage/matrix/matrix_complex_ball_dense.pyx +973 -0
- sage/matrix/matrix_cyclo_dense.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_cyclo_dense.pxd +16 -0
- sage/matrix/matrix_cyclo_dense.pyx +1761 -0
- sage/matrix/matrix_integer_dense.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_dense.pxd +32 -0
- sage/matrix/matrix_integer_dense.pyx +5801 -0
- sage/matrix/matrix_integer_dense_hnf.py +1294 -0
- sage/matrix/matrix_integer_dense_saturation.py +346 -0
- sage/matrix/matrix_integer_sparse.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_integer_sparse.pxd +9 -0
- sage/matrix/matrix_integer_sparse.pyx +1090 -0
- sage/matrix/matrix_rational_dense.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_dense.pxd +23 -0
- sage/matrix/matrix_rational_dense.pyx +2995 -0
- sage/matrix/matrix_rational_sparse.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_rational_sparse.pxd +11 -0
- sage/matrix/matrix_rational_sparse.pyx +789 -0
- sage/matrix/misc_flint.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/matrix/misc_flint.pyx +109 -0
- sage/modular/all__sagemath_flint.py +1 -0
- sage/modular/modform/all__sagemath_flint.py +1 -0
- sage/modular/modform/eis_series_cython.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/modular/modform/eis_series_cython.pyx +226 -0
- sage/modular/modsym/all__sagemath_flint.py +1 -0
- sage/modular/modsym/apply.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/modular/modsym/apply.pxd +6 -0
- sage/modular/modsym/apply.pyx +113 -0
- sage/modular/modsym/heilbronn.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/modular/modsym/heilbronn.pyx +966 -0
- sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
- sage/modular/pollack_stevens/dist.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/modular/pollack_stevens/dist.pxd +38 -0
- sage/modular/pollack_stevens/dist.pyx +1439 -0
- sage/quivers/algebra.py +691 -0
- sage/quivers/algebra_elements.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/quivers/algebra_elements.pxd +97 -0
- sage/quivers/algebra_elements.pxi +1324 -0
- sage/quivers/algebra_elements.pyx +1424 -0
- sage/quivers/all.py +1 -0
- sage/quivers/ar_quiver.py +917 -0
- sage/quivers/homspace.py +640 -0
- sage/quivers/morphism.py +1282 -0
- sage/quivers/path_semigroup.py +1155 -0
- sage/quivers/paths.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/quivers/paths.pxd +13 -0
- sage/quivers/paths.pyx +809 -0
- sage/quivers/representation.py +2975 -0
- sage/rings/all__sagemath_flint.py +37 -0
- sage/rings/cif.py +4 -0
- sage/rings/complex_arb.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_arb.pxd +29 -0
- sage/rings/complex_arb.pyx +5176 -0
- sage/rings/complex_interval.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_interval.pxd +30 -0
- sage/rings/complex_interval.pyx +2475 -0
- sage/rings/complex_interval_field.py +711 -0
- sage/rings/convert/all.py +1 -0
- sage/rings/convert/mpfi.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/convert/mpfi.pxd +6 -0
- sage/rings/convert/mpfi.pyx +576 -0
- sage/rings/factorint_flint.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/factorint_flint.pyx +99 -0
- sage/rings/fraction_field_FpT.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/fraction_field_FpT.pxd +28 -0
- sage/rings/fraction_field_FpT.pyx +2043 -0
- sage/rings/imaginary_unit.py +5 -0
- sage/rings/monomials.py +73 -0
- sage/rings/number_field/S_unit_solver.py +2870 -0
- sage/rings/number_field/all__sagemath_flint.py +7 -0
- sage/rings/number_field/bdd_height.py +664 -0
- sage/rings/number_field/class_group.py +762 -0
- sage/rings/number_field/galois_group.py +1307 -0
- sage/rings/number_field/homset.py +612 -0
- sage/rings/number_field/maps.py +687 -0
- sage/rings/number_field/morphism.py +272 -0
- sage/rings/number_field/number_field.py +12820 -0
- sage/rings/number_field/number_field_element.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_element.pxd +59 -0
- sage/rings/number_field/number_field_element.pyx +5735 -0
- sage/rings/number_field/number_field_element_quadratic.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
- sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
- sage/rings/number_field/number_field_ideal_rel.py +925 -0
- sage/rings/number_field/number_field_morphisms.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/number_field/number_field_morphisms.pyx +781 -0
- sage/rings/number_field/number_field_rel.py +2734 -0
- sage/rings/number_field/order.py +2981 -0
- sage/rings/number_field/order_ideal.py +804 -0
- sage/rings/number_field/selmer_group.py +715 -0
- sage/rings/number_field/small_primes_of_degree_one.py +242 -0
- sage/rings/number_field/splitting_field.py +606 -0
- sage/rings/number_field/structure.py +380 -0
- sage/rings/number_field/unit_group.py +721 -0
- sage/rings/padics/all__sagemath_flint.py +3 -0
- sage/rings/polynomial/all__sagemath_flint.py +1 -0
- sage/rings/polynomial/complex_roots.py +312 -0
- sage/rings/polynomial/evaluation_flint.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/evaluation_flint.pxd +7 -0
- sage/rings/polynomial/evaluation_flint.pyx +68 -0
- sage/rings/polynomial/hilbert.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/hilbert.pyx +602 -0
- sage/rings/polynomial/polynomial_complex_arb.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
- sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
- sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
- sage/rings/polynomial/polynomial_number_field.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_number_field.pyx +345 -0
- sage/rings/polynomial/polynomial_rational_flint.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
- sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
- sage/rings/polynomial/polynomial_zmod_flint.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
- sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
- sage/rings/polynomial/real_roots.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/real_roots.pxd +81 -0
- sage/rings/polynomial/real_roots.pyx +4704 -0
- sage/rings/polynomial/refine_root.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/refine_root.pyx +142 -0
- sage/rings/polynomial/weil/all.py +4 -0
- sage/rings/polynomial/weil/power_sums.h +46 -0
- sage/rings/polynomial/weil/weil_polynomials.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
- sage/rings/qqbar.py +9025 -0
- sage/rings/real_arb.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/real_arb.pxd +21 -0
- sage/rings/real_arb.pyx +4065 -0
- sage/rings/real_interval_absolute.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/real_interval_absolute.pyx +1073 -0
- sage/rings/real_mpfi.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/rings/real_mpfi.pyx +5428 -0
- sage/schemes/all__sagemath_flint.py +1 -0
- sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
- sage/schemes/elliptic_curves/descent_two_isogeny.cpython-310-x86_64-linux-gnu.so +0 -0
- sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-flint
|
Binary file
|
@@ -0,0 +1,555 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-flint
|
2
|
+
# cython: binding=True
|
3
|
+
# sage.doctest: needs sage.libs.flint sage.graphs
|
4
|
+
"""
|
5
|
+
Chromatic polynomial
|
6
|
+
|
7
|
+
AUTHORS:
|
8
|
+
|
9
|
+
- Gordon Royle - original C implementation
|
10
|
+
- Robert Miller - transplant
|
11
|
+
|
12
|
+
REFERENCE:
|
13
|
+
|
14
|
+
See [Rea1968]_ and the :wikipedia:`Chromatic_polynomial` for more details
|
15
|
+
on this notion in graphs.
|
16
|
+
|
17
|
+
"""
|
18
|
+
|
19
|
+
# ****************************************************************************
|
20
|
+
# Copyright (C) 2008 Robert Miller
|
21
|
+
# Copyright (C) 2008 Gordon Royle
|
22
|
+
#
|
23
|
+
# This program is free software: you can redistribute it and/or modify
|
24
|
+
# it under the terms of the GNU General Public License as published by
|
25
|
+
# the Free Software Foundation, either version 2 of the License, or
|
26
|
+
# (at your option) any later version.
|
27
|
+
# https://www.gnu.org/licenses/
|
28
|
+
# ****************************************************************************
|
29
|
+
|
30
|
+
from cysignals.signals cimport sig_check
|
31
|
+
from memory_allocator cimport MemoryAllocator
|
32
|
+
|
33
|
+
from sage.libs.gmp.mpz cimport *
|
34
|
+
from sage.rings.integer_ring import ZZ
|
35
|
+
from sage.rings.integer cimport Integer
|
36
|
+
from sage.rings.ring cimport CommutativeRing
|
37
|
+
from sage.rings.polynomial.polynomial_integer_dense_flint cimport Polynomial_integer_dense_flint
|
38
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
39
|
+
|
40
|
+
|
41
|
+
def chromatic_polynomial(G, return_tree_basis=False, algorithm='C', cache=None):
|
42
|
+
"""
|
43
|
+
Compute the chromatic polynomial of the graph G.
|
44
|
+
|
45
|
+
The algorithm used is a recursive one, based on the following observations
|
46
|
+
of Read [Rea1968]_:
|
47
|
+
|
48
|
+
- The chromatic polynomial of a tree on n vertices is x(x-1)^(n-1).
|
49
|
+
|
50
|
+
- If e is an edge of G, G' is the result of deleting the edge e, and G''
|
51
|
+
is the result of contracting e, then the chromatic polynomial of G is
|
52
|
+
equal to that of G' minus that of G''.
|
53
|
+
|
54
|
+
INPUT:
|
55
|
+
|
56
|
+
- ``G`` -- a Sage graph
|
57
|
+
|
58
|
+
- ``return_tree_basis`` -- boolean (default: ``False``); not used yet
|
59
|
+
|
60
|
+
- ``algorithm`` -- string (default: ``'C'``); the algorithm to use among
|
61
|
+
|
62
|
+
- ``'C'``, an implementation in C by Robert Miller and Gordon Royle.
|
63
|
+
|
64
|
+
- ``'Python'``, an implementation in Python using caching to avoid
|
65
|
+
recomputing the chromatic polynomial of a graph that has already been
|
66
|
+
seen. This seems faster on some dense graphs.
|
67
|
+
|
68
|
+
- ``cache`` -- dictionary (default: ``None``); this parameter is used only
|
69
|
+
for algorithm ``'Python'``. It is a dictionary keyed by canonical
|
70
|
+
labelings of graphs and used to cache the chromatic polynomials of the
|
71
|
+
graphs generated by the algorithm. In other words, it avoids computing
|
72
|
+
twice the chromatic polynomial of isometric graphs. One will be created
|
73
|
+
automatically if not provided.
|
74
|
+
|
75
|
+
EXAMPLES::
|
76
|
+
|
77
|
+
sage: graphs.CycleGraph(4).chromatic_polynomial()
|
78
|
+
x^4 - 4*x^3 + 6*x^2 - 3*x
|
79
|
+
sage: graphs.CycleGraph(3).chromatic_polynomial()
|
80
|
+
x^3 - 3*x^2 + 2*x
|
81
|
+
sage: graphs.CubeGraph(3).chromatic_polynomial()
|
82
|
+
x^8 - 12*x^7 + 66*x^6 - 214*x^5 + 441*x^4 - 572*x^3 + 423*x^2 - 133*x
|
83
|
+
sage: graphs.PetersenGraph().chromatic_polynomial()
|
84
|
+
x^10 - 15*x^9 + 105*x^8 - 455*x^7 + 1353*x^6 - 2861*x^5 + 4275*x^4 - 4305*x^3 + 2606*x^2 - 704*x
|
85
|
+
sage: graphs.CompleteBipartiteGraph(3,3).chromatic_polynomial()
|
86
|
+
x^6 - 9*x^5 + 36*x^4 - 75*x^3 + 78*x^2 - 31*x
|
87
|
+
sage: for i in range(2,7):
|
88
|
+
....: graphs.CompleteGraph(i).chromatic_polynomial().factor()
|
89
|
+
(x - 1) * x
|
90
|
+
(x - 2) * (x - 1) * x
|
91
|
+
(x - 3) * (x - 2) * (x - 1) * x
|
92
|
+
(x - 4) * (x - 3) * (x - 2) * (x - 1) * x
|
93
|
+
(x - 5) * (x - 4) * (x - 3) * (x - 2) * (x - 1) * x
|
94
|
+
sage: graphs.CycleGraph(5).chromatic_polynomial().factor()
|
95
|
+
(x - 2) * (x - 1) * x * (x^2 - 2*x + 2)
|
96
|
+
sage: graphs.OctahedralGraph().chromatic_polynomial().factor()
|
97
|
+
(x - 2) * (x - 1) * x * (x^3 - 9*x^2 + 29*x - 32)
|
98
|
+
sage: graphs.WheelGraph(5).chromatic_polynomial().factor()
|
99
|
+
(x - 2) * (x - 1) * x * (x^2 - 5*x + 7)
|
100
|
+
sage: graphs.WheelGraph(6).chromatic_polynomial().factor()
|
101
|
+
(x - 3) * (x - 2) * (x - 1) * x * (x^2 - 4*x + 5)
|
102
|
+
sage: C(x)=graphs.LCFGraph(24, [12,7,-7], 8).chromatic_polynomial() # long time (6s on sage.math, 2011)
|
103
|
+
sage: C(2) # long time
|
104
|
+
0
|
105
|
+
|
106
|
+
By definition, the chromatic number of a graph G is the least integer k such that
|
107
|
+
the chromatic polynomial of G is strictly positive at k::
|
108
|
+
|
109
|
+
sage: G = graphs.PetersenGraph()
|
110
|
+
sage: P = G.chromatic_polynomial()
|
111
|
+
sage: min(i for i in range(11) if P(i) > 0) == G.chromatic_number() # needs cliquer
|
112
|
+
True
|
113
|
+
|
114
|
+
sage: G = graphs.RandomGNP(10,0.7)
|
115
|
+
sage: P = G.chromatic_polynomial()
|
116
|
+
sage: min(i for i in range(11) if P(i) > 0) == G.chromatic_number() # needs cliquer
|
117
|
+
True
|
118
|
+
|
119
|
+
Check that algorithms ``'C'`` and ``'Python'`` return the same results::
|
120
|
+
|
121
|
+
sage: G = graphs.RandomGNP(8, randint(1, 9)*0.1)
|
122
|
+
sage: c = G.chromatic_polynomial(algorithm='C')
|
123
|
+
sage: p = G.chromatic_polynomial(algorithm='Python')
|
124
|
+
sage: c == p
|
125
|
+
True
|
126
|
+
|
127
|
+
TESTS:
|
128
|
+
|
129
|
+
Check that :issue:`21502` is solved::
|
130
|
+
|
131
|
+
sage: graphs.EmptyGraph().chromatic_polynomial()
|
132
|
+
1
|
133
|
+
|
134
|
+
Check that :issue:`27966` is solved::
|
135
|
+
|
136
|
+
sage: Graph([[1, 1]], multiedges=True, loops=True).chromatic_polynomial()
|
137
|
+
0
|
138
|
+
|
139
|
+
Giving a wrong algorithm::
|
140
|
+
|
141
|
+
sage: Graph().chromatic_polynomial(algorithm='foo')
|
142
|
+
Traceback (most recent call last):
|
143
|
+
...
|
144
|
+
ValueError: algorithm must be "C" or "Python"
|
145
|
+
"""
|
146
|
+
algorithm = algorithm.lower()
|
147
|
+
if algorithm not in ['c', 'python']:
|
148
|
+
raise ValueError('algorithm must be "C" or "Python"')
|
149
|
+
if algorithm == 'python':
|
150
|
+
return chromatic_polynomial_with_cache(G, cache=cache)
|
151
|
+
|
152
|
+
R = ZZ['x']
|
153
|
+
if not G:
|
154
|
+
return R.one()
|
155
|
+
if G.has_loops():
|
156
|
+
return R.zero()
|
157
|
+
if not G.is_connected():
|
158
|
+
return R.prod(chromatic_polynomial(g, algorithm='C') for g in G.connected_components_subgraphs())
|
159
|
+
x = R.gen()
|
160
|
+
if G.is_tree():
|
161
|
+
return x * (x - 1) ** (G.num_verts() - 1)
|
162
|
+
|
163
|
+
cdef int nverts, nedges, i, j, u, v, top, bot, num_chords, next_v
|
164
|
+
cdef int *queue
|
165
|
+
cdef int *chords1
|
166
|
+
cdef int *chords2
|
167
|
+
cdef int *bfs_reorder
|
168
|
+
cdef int *parent
|
169
|
+
cdef mpz_t m, coeff
|
170
|
+
cdef mpz_t *tot
|
171
|
+
cdef mpz_t *coeffs
|
172
|
+
G = G.relabel(inplace=False)
|
173
|
+
G.remove_multiple_edges()
|
174
|
+
G.remove_loops()
|
175
|
+
nverts = G.num_verts()
|
176
|
+
nedges = G.num_edges()
|
177
|
+
|
178
|
+
cdef MemoryAllocator mem = MemoryAllocator()
|
179
|
+
queue = <int *> mem.allocarray(nverts, sizeof(int))
|
180
|
+
chords1 = <int *> mem.allocarray((nedges - nverts + 1), sizeof(int))
|
181
|
+
chords2 = <int *> mem.allocarray((nedges - nverts + 1), sizeof(int))
|
182
|
+
parent = <int *> mem.allocarray(nverts, sizeof(int))
|
183
|
+
bfs_reorder = <int *> mem.allocarray(nverts, sizeof(int))
|
184
|
+
tot = <mpz_t *> mem.allocarray((nverts+1), sizeof(mpz_t))
|
185
|
+
coeffs = <mpz_t *> mem.allocarray((nverts+1), sizeof(mpz_t))
|
186
|
+
num_chords = 0
|
187
|
+
|
188
|
+
# Breadth first search from 0:
|
189
|
+
bfs_reorder[0] = 0
|
190
|
+
mpz_init(tot[0]) # sets to 0
|
191
|
+
for i in range(1, nverts):
|
192
|
+
bfs_reorder[i] = -1
|
193
|
+
mpz_init(tot[i]) # sets to 0
|
194
|
+
mpz_init(tot[nverts]) # sets to 0
|
195
|
+
queue[0] = 0
|
196
|
+
top = 1
|
197
|
+
bot = 0
|
198
|
+
next_v = 1
|
199
|
+
while top > bot:
|
200
|
+
v = queue[bot]
|
201
|
+
bot += 1
|
202
|
+
for u in G.neighbor_iterator(v):
|
203
|
+
if bfs_reorder[u] == -1: # if u is not yet in tree
|
204
|
+
bfs_reorder[u] = next_v
|
205
|
+
next_v += 1
|
206
|
+
queue[top] = u
|
207
|
+
top += 1
|
208
|
+
parent[bfs_reorder[u]] = bfs_reorder[v]
|
209
|
+
else:
|
210
|
+
if bfs_reorder[u] > bfs_reorder[v]:
|
211
|
+
chords1[num_chords] = bfs_reorder[u]
|
212
|
+
chords2[num_chords] = bfs_reorder[v]
|
213
|
+
else:
|
214
|
+
continue
|
215
|
+
i = num_chords
|
216
|
+
num_chords += 1
|
217
|
+
# bubble sort the chords
|
218
|
+
while i > 0:
|
219
|
+
if chords1[i-1] > chords1[i]:
|
220
|
+
break
|
221
|
+
if chords1[i-1] == chords1[i] and chords2[i-1] > chords2[i]:
|
222
|
+
break
|
223
|
+
j = chords1[i-1]
|
224
|
+
chords1[i-1] = chords1[i]
|
225
|
+
chords1[i] = j
|
226
|
+
j = chords2[i-1]
|
227
|
+
chords2[i-1] = chords2[i]
|
228
|
+
chords2[i] = j
|
229
|
+
i -= 1
|
230
|
+
try:
|
231
|
+
contract_and_count(chords1, chords2, num_chords, nverts, tot, parent)
|
232
|
+
except BaseException:
|
233
|
+
for i in range(nverts):
|
234
|
+
mpz_clear(tot[i])
|
235
|
+
raise
|
236
|
+
for i in range(nverts + 1):
|
237
|
+
mpz_init(coeffs[i]) # also sets them to 0
|
238
|
+
mpz_init(coeff)
|
239
|
+
mpz_init_set_si(m, -1)
|
240
|
+
# start with the zero polynomial: f(x) = 0
|
241
|
+
for i in range(nverts, 0, -1): # nverts >= i > 0
|
242
|
+
if not mpz_sgn(tot[i]):
|
243
|
+
continue
|
244
|
+
mpz_neg(m, m)
|
245
|
+
|
246
|
+
# do this:
|
247
|
+
# f += tot[i]*m*x*(x-1)**(i-1)
|
248
|
+
mpz_addmul(coeffs[i], m, tot[i])
|
249
|
+
mpz_set_si(coeff, 1)
|
250
|
+
for j in range(1, i):
|
251
|
+
# an iterative method for binomial coefficients...
|
252
|
+
mpz_mul_si(coeff, coeff, j-i)
|
253
|
+
mpz_divexact_ui(coeff, coeff, j)
|
254
|
+
# coeffs[i-j] += tot[i]*m*coeff
|
255
|
+
mpz_mul(coeff, coeff, m)
|
256
|
+
mpz_addmul(coeffs[i-j], coeff, tot[i])
|
257
|
+
mpz_mul(coeff, coeff, m)
|
258
|
+
coeffs_ZZ = []
|
259
|
+
cdef Integer c_ZZ
|
260
|
+
for i in range(nverts + 1):
|
261
|
+
c_ZZ = Integer(0)
|
262
|
+
mpz_set(c_ZZ.value, coeffs[i])
|
263
|
+
coeffs_ZZ.append(c_ZZ)
|
264
|
+
f = R(coeffs_ZZ)
|
265
|
+
|
266
|
+
for i in range(nverts + 1):
|
267
|
+
mpz_clear(tot[i])
|
268
|
+
mpz_clear(coeffs[i])
|
269
|
+
|
270
|
+
mpz_clear(coeff)
|
271
|
+
mpz_clear(m)
|
272
|
+
|
273
|
+
return f
|
274
|
+
|
275
|
+
|
276
|
+
cdef int contract_and_count(int *chords1, int *chords2, int num_chords, int nverts,
|
277
|
+
mpz_t *tot, int *parent) except -1:
|
278
|
+
if num_chords == 0:
|
279
|
+
mpz_add_ui(tot[nverts], tot[nverts], 1)
|
280
|
+
return 0
|
281
|
+
cdef MemoryAllocator mem = MemoryAllocator()
|
282
|
+
cdef int *new_chords1 = <int *> mem.allocarray(num_chords, sizeof(int))
|
283
|
+
cdef int *new_chords2 = <int *> mem.allocarray(num_chords, sizeof(int))
|
284
|
+
cdef int *ins_list1 = <int *> mem.allocarray(num_chords, sizeof(int))
|
285
|
+
cdef int *ins_list2 = <int *> mem.allocarray(num_chords, sizeof(int))
|
286
|
+
cdef int i, j, k, x1, xj, z, num, insnum, parent_checked
|
287
|
+
for i in range(num_chords):
|
288
|
+
sig_check()
|
289
|
+
|
290
|
+
# contract chord i, and recurse
|
291
|
+
z = chords1[i]
|
292
|
+
x1 = chords2[i]
|
293
|
+
j = i + 1
|
294
|
+
insnum = 0
|
295
|
+
parent_checked = 0
|
296
|
+
while j < num_chords and chords1[j] == z:
|
297
|
+
xj = chords2[j]
|
298
|
+
if parent[z] > xj:
|
299
|
+
parent_checked = 1
|
300
|
+
# now try adding {x1, parent[z]} to the list
|
301
|
+
if not parent[x1] == parent[z]:
|
302
|
+
if x1 > parent[z]:
|
303
|
+
ins_list1[insnum] = x1
|
304
|
+
ins_list2[insnum] = parent[z]
|
305
|
+
else:
|
306
|
+
ins_list1[insnum] = parent[z]
|
307
|
+
ins_list2[insnum] = x1
|
308
|
+
insnum += 1
|
309
|
+
if not parent[x1] == xj: # then {x1, xj} isn't already a tree edge
|
310
|
+
ins_list1[insnum] = x1
|
311
|
+
ins_list2[insnum] = xj
|
312
|
+
insnum += 1
|
313
|
+
j += 1
|
314
|
+
if not parent_checked:
|
315
|
+
if not parent[x1] == parent[z]:
|
316
|
+
if x1 > parent[z]:
|
317
|
+
ins_list1[insnum] = x1
|
318
|
+
ins_list2[insnum] = parent[z]
|
319
|
+
else:
|
320
|
+
ins_list1[insnum] = parent[z]
|
321
|
+
ins_list2[insnum] = x1
|
322
|
+
insnum += 1
|
323
|
+
|
324
|
+
# now merge new_chords and ins_list
|
325
|
+
num = 0
|
326
|
+
k = 0
|
327
|
+
while k < insnum and j < num_chords:
|
328
|
+
if (chords1[j] > ins_list1[k] or
|
329
|
+
(chords1[j] == ins_list1[k] and chords2[j] > ins_list2[k])):
|
330
|
+
new_chords1[num] = chords1[j]
|
331
|
+
new_chords2[num] = chords2[j]
|
332
|
+
num += 1
|
333
|
+
j += 1
|
334
|
+
elif (chords1[j] < ins_list1[k] or
|
335
|
+
(chords1[j] == ins_list1[k] and chords2[j] < ins_list2[k])):
|
336
|
+
new_chords1[num] = ins_list1[k]
|
337
|
+
new_chords2[num] = ins_list2[k]
|
338
|
+
num += 1
|
339
|
+
k += 1
|
340
|
+
else:
|
341
|
+
new_chords1[num] = chords1[j]
|
342
|
+
new_chords2[num] = chords2[j]
|
343
|
+
num += 1
|
344
|
+
j += 1
|
345
|
+
k += 1
|
346
|
+
if j == num_chords:
|
347
|
+
while k < insnum:
|
348
|
+
new_chords1[num] = ins_list1[k]
|
349
|
+
new_chords2[num] = ins_list2[k]
|
350
|
+
num += 1
|
351
|
+
k += 1
|
352
|
+
elif k == insnum:
|
353
|
+
while j < num_chords:
|
354
|
+
new_chords1[num] = chords1[j]
|
355
|
+
new_chords2[num] = chords2[j]
|
356
|
+
num += 1
|
357
|
+
j += 1
|
358
|
+
contract_and_count(new_chords1, new_chords2, num, nverts - 1, tot, parent)
|
359
|
+
mpz_add_ui(tot[nverts], tot[nverts], 1)
|
360
|
+
|
361
|
+
|
362
|
+
#
|
363
|
+
# Chromatic Polynomial with caching
|
364
|
+
#
|
365
|
+
|
366
|
+
def chromatic_polynomial_with_cache(G, cache=None):
|
367
|
+
r"""
|
368
|
+
Return the chromatic polynomial of the graph ``G``.
|
369
|
+
|
370
|
+
The algorithm used is here is the non recursive version of a recursive
|
371
|
+
algorithm based on the following observations of Read:
|
372
|
+
|
373
|
+
- The chromatic polynomial of a tree on `n` vertices is `x(x-1)^{n-1}`.
|
374
|
+
|
375
|
+
- If `e` is an edge of `G`, `G'` is the result of deleting the edge `e`,
|
376
|
+
and `G''` is the result of contracting `e`, then the chromatic
|
377
|
+
polynomial of `G` is equal to that of `G'` minus that of `G''`.
|
378
|
+
|
379
|
+
- If `G` is not connected, its the chromatic polynomial is the product
|
380
|
+
of the chromatic polynomials of its connected components.
|
381
|
+
|
382
|
+
Since this method makes extensive use of canonical labelings, it is
|
383
|
+
recommended to install optional package ``bliss``.
|
384
|
+
|
385
|
+
INPUT:
|
386
|
+
|
387
|
+
- ``G`` -- a Sage graph
|
388
|
+
|
389
|
+
- ``cache`` -- dictionary (default: ``None``); dictionary keyed by canonical
|
390
|
+
labelings of graphs and used to cache the chromatic polynomials of the
|
391
|
+
graphs generated by the algorithm. In other words, it avoids computing
|
392
|
+
twice the chromatic polynomial of isometric graphs. One will be created
|
393
|
+
automatically if not provided.
|
394
|
+
|
395
|
+
EXAMPLES::
|
396
|
+
|
397
|
+
sage: from sage.graphs.chrompoly import chromatic_polynomial_with_cache
|
398
|
+
sage: chromatic_polynomial_with_cache(graphs.CycleGraph(4))
|
399
|
+
x^4 - 4*x^3 + 6*x^2 - 3*x
|
400
|
+
sage: chromatic_polynomial_with_cache(graphs.CycleGraph(3))
|
401
|
+
x^3 - 3*x^2 + 2*x
|
402
|
+
sage: chromatic_polynomial_with_cache(graphs.CubeGraph(3))
|
403
|
+
x^8 - 12*x^7 + 66*x^6 - 214*x^5 + 441*x^4 - 572*x^3 + 423*x^2 - 133*x
|
404
|
+
sage: chromatic_polynomial_with_cache(graphs.PetersenGraph())
|
405
|
+
x^10 - 15*x^9 + 105*x^8 - 455*x^7 + 1353*x^6 - 2861*x^5 + 4275*x^4 - 4305*x^3 + 2606*x^2 - 704*x
|
406
|
+
sage: chromatic_polynomial_with_cache(graphs.CompleteBipartiteGraph(3,3))
|
407
|
+
x^6 - 9*x^5 + 36*x^4 - 75*x^3 + 78*x^2 - 31*x
|
408
|
+
|
409
|
+
If a cache is provided, it is fed::
|
410
|
+
|
411
|
+
sage: cache = {}
|
412
|
+
sage: G = graphs.CycleGraph(4)
|
413
|
+
sage: p = chromatic_polynomial_with_cache(graphs.CycleGraph(4), cache=cache)
|
414
|
+
sage: key = frozenset(G.canonical_label().edges(labels=False, sort=False))
|
415
|
+
sage: cache[key]
|
416
|
+
x^4 - 4*x^3 + 6*x^2 - 3*x
|
417
|
+
|
418
|
+
TESTS:
|
419
|
+
|
420
|
+
Corner cases::
|
421
|
+
|
422
|
+
sage: from sage.graphs.chrompoly import chromatic_polynomial_with_cache
|
423
|
+
sage: chromatic_polynomial_with_cache(graphs.EmptyGraph())
|
424
|
+
1
|
425
|
+
sage: chromatic_polynomial_with_cache(Graph(1))
|
426
|
+
x
|
427
|
+
sage: chromatic_polynomial_with_cache(Graph(2))
|
428
|
+
x^2
|
429
|
+
sage: chromatic_polynomial_with_cache(Graph(3))
|
430
|
+
x^3
|
431
|
+
sage: chromatic_polynomial_with_cache(Graph([[1, 1]], loops=True))
|
432
|
+
0
|
433
|
+
|
434
|
+
Parameter ``cache`` must be a dictionary::
|
435
|
+
|
436
|
+
sage: chromatic_polynomial_with_cache(Graph(2), cache=[])
|
437
|
+
Traceback (most recent call last):
|
438
|
+
...
|
439
|
+
TypeError: parameter cache must be a dictionary or None
|
440
|
+
"""
|
441
|
+
cdef CommutativeRing R = PolynomialRing(ZZ, "x", implementation="FLINT")
|
442
|
+
cdef Polynomial_integer_dense_flint one = R.one()
|
443
|
+
cdef Polynomial_integer_dense_flint zero = R.zero()
|
444
|
+
cdef Polynomial_integer_dense_flint x = R.gen()
|
445
|
+
|
446
|
+
if not G:
|
447
|
+
return one
|
448
|
+
if G.has_loops():
|
449
|
+
return zero
|
450
|
+
|
451
|
+
# Make a copy of the input graph and ensure that it's labeled [0..n-1]
|
452
|
+
G = G.relabel(inplace=False)
|
453
|
+
G.remove_multiple_edges()
|
454
|
+
|
455
|
+
# We use a cache to avoid computing twice the chromatic polynomial of
|
456
|
+
# isomorphic graphs
|
457
|
+
if cache is None:
|
458
|
+
cache = dict()
|
459
|
+
elif not isinstance(cache, dict):
|
460
|
+
raise TypeError("parameter cache must be a dictionary or None")
|
461
|
+
|
462
|
+
# We use a digraph to store intermediate values and store the current state
|
463
|
+
# of a vertex (either a graph, a key or a polynomial)
|
464
|
+
from sage.graphs.digraph import DiGraph
|
465
|
+
D = DiGraph(1)
|
466
|
+
D.set_vertex(0, G)
|
467
|
+
|
468
|
+
cdef int op_none = 0
|
469
|
+
cdef int op_mult = 1
|
470
|
+
cdef int op_diff = 2
|
471
|
+
|
472
|
+
# We use a stack to order operations in a depth first search fashion
|
473
|
+
from collections import deque
|
474
|
+
stack = deque()
|
475
|
+
stack.append((0, True, (op_none, )))
|
476
|
+
cdef bint firstseen
|
477
|
+
cdef int u, v, w, a, b
|
478
|
+
cdef tuple com
|
479
|
+
|
480
|
+
while stack:
|
481
|
+
|
482
|
+
v, firstseen, com = stack.pop()
|
483
|
+
|
484
|
+
if firstseen:
|
485
|
+
g = D.get_vertex(v)
|
486
|
+
key = frozenset(g.canonical_label().edges(labels=False, sort=False))
|
487
|
+
if key in cache:
|
488
|
+
D.set_vertex(v, cache[key])
|
489
|
+
|
490
|
+
elif g.has_loops():
|
491
|
+
D.set_vertex(v, zero)
|
492
|
+
cache[key] = D.get_vertex(v)
|
493
|
+
|
494
|
+
elif not g.is_connected():
|
495
|
+
# We have to compute the product of the chromatic polynomials of
|
496
|
+
# the connected components
|
497
|
+
D.set_vertex(v, key)
|
498
|
+
stack.append((v, False, (op_mult, )))
|
499
|
+
for h in g.connected_components_subgraphs():
|
500
|
+
w = D.add_vertex()
|
501
|
+
D.set_vertex(w, h)
|
502
|
+
D.add_edge(v, w)
|
503
|
+
stack.append((w, True, (op_none, )))
|
504
|
+
|
505
|
+
elif g.order() == g.size() + 1:
|
506
|
+
# g is a tree
|
507
|
+
D.set_vertex(v, x*(x - one)**(g.order() - 1))
|
508
|
+
cache[key] = D.get_vertex(v)
|
509
|
+
|
510
|
+
else:
|
511
|
+
# Otherwise, the chromatic polynomial of g is the chromatic
|
512
|
+
# polynomial of g without edge e minus the chromatic polynomial
|
513
|
+
# of g after the contraction of edge e
|
514
|
+
a = D.add_vertex()
|
515
|
+
b = D.add_vertex()
|
516
|
+
D.add_edge(v, a)
|
517
|
+
D.add_edge(v, b)
|
518
|
+
D.set_vertex(v, key)
|
519
|
+
stack.append((v, False, (op_diff, a, b)))
|
520
|
+
# We try to select an edge that could disconnect the graph
|
521
|
+
for u, w in g.bridges(labels=False):
|
522
|
+
break
|
523
|
+
else:
|
524
|
+
u, w = next(g.edge_iterator(labels=False))
|
525
|
+
|
526
|
+
g.delete_edge(u, w)
|
527
|
+
D.set_vertex(a, g.copy())
|
528
|
+
stack.append((a, True, (op_none, )))
|
529
|
+
g.add_edge(u, w)
|
530
|
+
g.merge_vertices([u, w])
|
531
|
+
g.remove_multiple_edges()
|
532
|
+
D.set_vertex(b, g)
|
533
|
+
stack.append((b, True, (op_none, )))
|
534
|
+
|
535
|
+
elif com[0] == op_mult:
|
536
|
+
# We compute the product of the connected components of the graph
|
537
|
+
# and delete the children from D
|
538
|
+
key = D.get_vertex(v)
|
539
|
+
cache[key] = R.prod(D.get_vertex(w) for w in D.neighbor_out_iterator(v))
|
540
|
+
D.set_vertex(v, cache[key])
|
541
|
+
D.delete_vertices(D.neighbor_out_iterator(v))
|
542
|
+
|
543
|
+
elif com[0] == op_diff:
|
544
|
+
# We compute the difference of the chromatic polynomials of the 2
|
545
|
+
# children and remove them from D
|
546
|
+
key = D.get_vertex(v)
|
547
|
+
cache[key] = D.get_vertex(com[1]) - D.get_vertex(com[2])
|
548
|
+
D.set_vertex(v, cache[key])
|
549
|
+
D.delete_vertices(D.neighbor_out_iterator(v))
|
550
|
+
|
551
|
+
else:
|
552
|
+
# We should never end here
|
553
|
+
raise ValueError("something goes wrong")
|
554
|
+
|
555
|
+
return D.get_vertex(0)
|
Binary file
|