passagemath-flint 10.6.1rc10__cp311-cp311-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-311-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-311-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-311-x86_64-linux-gnu.so +0 -0
- sage/graphs/chrompoly.pyx +555 -0
- sage/graphs/matchpoly.cpython-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-x86_64-linux-gnu.so +0 -0
- sage/matrix/change_ring.pyx +43 -0
- sage/matrix/matrix_complex_ball_dense.cpython-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-x86_64-linux-gnu.so +0 -0
- sage/rings/factorint_flint.pyx +99 -0
- sage/rings/fraction_field_FpT.cpython-311-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-311-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-311-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-311-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-311-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-311-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/hilbert.pyx +602 -0
- sage/rings/polynomial/polynomial_complex_arb.cpython-311-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-311-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-311-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_number_field.pyx +345 -0
- sage/rings/polynomial/polynomial_rational_flint.cpython-311-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-311-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-311-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-311-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-311-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-311-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-311-x86_64-linux-gnu.so +0 -0
- sage/rings/real_interval_absolute.pyx +1073 -0
- sage/rings/real_mpfi.cpython-311-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-311-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
sage/quivers/morphism.py
ADDED
@@ -0,0 +1,1282 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-flint
|
2
|
+
# sage.doctest: needs sage.graphs sage.modules
|
3
|
+
"""
|
4
|
+
Quiver Morphisms
|
5
|
+
"""
|
6
|
+
|
7
|
+
# ****************************************************************************
|
8
|
+
# Copyright (C) 2012 Jim Stark <jstarx@gmail.com>
|
9
|
+
# 2013 Simon King <simon.king@uni-jena.de>
|
10
|
+
#
|
11
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
12
|
+
#
|
13
|
+
# This code is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty
|
15
|
+
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
16
|
+
#
|
17
|
+
# See the GNU General Public License for more details; the full text
|
18
|
+
# is available at:
|
19
|
+
#
|
20
|
+
# https://www.gnu.org/licenses/
|
21
|
+
# ****************************************************************************
|
22
|
+
|
23
|
+
from sage.categories.morphism import CallMorphism
|
24
|
+
from sage.matrix.constructor import Matrix
|
25
|
+
|
26
|
+
|
27
|
+
class QuiverRepHom(CallMorphism):
|
28
|
+
r"""
|
29
|
+
A homomorphism of quiver representations (of one and the same quiver)
|
30
|
+
is given by specifying, for each vertex of the quiver, a homomorphism
|
31
|
+
of the spaces assigned to this vertex such that these homomorphisms
|
32
|
+
commute with the edge maps. The domain and codomain of the
|
33
|
+
homomorphism are required to be representations of the same quiver
|
34
|
+
over the same base ring.
|
35
|
+
|
36
|
+
INPUT:
|
37
|
+
|
38
|
+
- ``domain`` -- :class:`QuiverRep`, the domain of the homomorphism
|
39
|
+
|
40
|
+
- ``codomain`` -- :class:`QuiverRep`, the codomain of the homomorphism
|
41
|
+
|
42
|
+
- ``data`` -- dict, list, or :class:`QuiverRepElement`
|
43
|
+
(default: empty dict),
|
44
|
+
with the following meaning:
|
45
|
+
|
46
|
+
- list: ``data`` can be a list of images for the generators of
|
47
|
+
the domain. "Generators" means the output of the ``gens()``
|
48
|
+
method. An error will be generated if the map so defined
|
49
|
+
is not equivariant with respect to the action of the quiver.
|
50
|
+
- dictionary: ``data`` can be a dictionary associating to each
|
51
|
+
vertex of the quiver either a homomorphism with domain and
|
52
|
+
codomain the spaces associated to this vertex in the domain
|
53
|
+
and codomain modules respectively, or a matrix defining such
|
54
|
+
a homomorphism, or an object that sage can construct such a
|
55
|
+
matrix from. Not all vertices must be specified, unspecified
|
56
|
+
vertices are assigned the zero map, and keys not corresponding
|
57
|
+
to vertices of the quiver are ignored. An error will be
|
58
|
+
generated if these maps do not commute with the edge maps of
|
59
|
+
the domain and codomain.
|
60
|
+
- :class:`QuiverRepElement`: if the domain is a
|
61
|
+
:class:`QuiverRep_with_path_basis` then ``data`` can be a single
|
62
|
+
:class:`QuiverRepElement` belonging to the codomain. The map is
|
63
|
+
then defined by sending each path, ``p``, in the basis to ``data*p``.
|
64
|
+
If ``data`` is not an element of the codomain or the domain is not a
|
65
|
+
:class:`QuiverRep_with_path_basis` then an error will be generated.
|
66
|
+
- :class:`QuiverRepHom`: the input can also be a map `f : D \to C` such
|
67
|
+
that there is a coercion from the domain of ``self`` to ``D``
|
68
|
+
and from ``C`` to the codomain of ``self``. The composition
|
69
|
+
of these maps is the result.
|
70
|
+
|
71
|
+
OUTPUT: :class:`QuiverRepHom`
|
72
|
+
|
73
|
+
EXAMPLES::
|
74
|
+
|
75
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
76
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
77
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
78
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
79
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
80
|
+
sage: S = Q.representation(QQ, spaces2)
|
81
|
+
|
82
|
+
With no additional data this creates the zero map::
|
83
|
+
|
84
|
+
sage: f = S.hom(M)
|
85
|
+
sage: f.is_zero()
|
86
|
+
True
|
87
|
+
|
88
|
+
We must specify maps at the vertices to get a nonzero homomorphism.
|
89
|
+
Note that if the dimensions of the spaces assigned to the domain and
|
90
|
+
codomain of a vertex are equal then Sage will construct the identity
|
91
|
+
matrix from ``1``::
|
92
|
+
|
93
|
+
sage: maps2 = {2:[1, -1], 3:1}
|
94
|
+
sage: g = S.hom(maps2, M)
|
95
|
+
|
96
|
+
Here we create the same map by specifying images for the generators::
|
97
|
+
|
98
|
+
sage: x = M({2: (1, -1)})
|
99
|
+
sage: y = M({3: (1,)})
|
100
|
+
sage: h = S.hom([x, y], M)
|
101
|
+
sage: g == h
|
102
|
+
True
|
103
|
+
|
104
|
+
If the domain is a module of type QuiverRep_with_path_basis (for example,
|
105
|
+
the indecomposable projectives) we can create maps by specifying a single
|
106
|
+
image::
|
107
|
+
|
108
|
+
sage: Proj = Q.P(GF(7), 3)
|
109
|
+
sage: Simp = Q.S(GF(7), 3)
|
110
|
+
sage: im = Simp({3: (1,)})
|
111
|
+
sage: Proj.hom(im, Simp).is_surjective()
|
112
|
+
True
|
113
|
+
"""
|
114
|
+
|
115
|
+
###########################################################################
|
116
|
+
# #
|
117
|
+
# PRIVATE FUNCTIONS #
|
118
|
+
# These functions are not meant to be seen by the end user. #
|
119
|
+
# #
|
120
|
+
###########################################################################
|
121
|
+
|
122
|
+
def __init__(self, domain, codomain, data={}):
|
123
|
+
"""
|
124
|
+
Initialize ``self``. Type ``QuiverRepHom?`` for more information.
|
125
|
+
|
126
|
+
TESTS::
|
127
|
+
|
128
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
129
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
130
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
131
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
132
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
133
|
+
sage: S = Q.representation(QQ, spaces2)
|
134
|
+
sage: f = S.hom(M)
|
135
|
+
sage: f.is_zero()
|
136
|
+
True
|
137
|
+
sage: maps2 = {2:[1, -1], 3:1}
|
138
|
+
sage: g = S.hom(maps2, M)
|
139
|
+
sage: x = M({2: (1, -1)})
|
140
|
+
sage: y = M({3: (1,)})
|
141
|
+
sage: h = S.hom([x, y], M)
|
142
|
+
sage: g == h
|
143
|
+
True
|
144
|
+
sage: Proj = Q.P(GF(7), 3)
|
145
|
+
sage: Simp = Q.S(GF(7), 3)
|
146
|
+
sage: im = Simp({3: (1,)})
|
147
|
+
sage: Proj.hom(im, Simp).is_surjective()
|
148
|
+
True
|
149
|
+
|
150
|
+
::
|
151
|
+
|
152
|
+
sage: Q = DiGraph({1:{2:['a']}}).path_semigroup()
|
153
|
+
sage: H1 = Q.P(GF(3), 2).Hom(Q.S(GF(3), 2))
|
154
|
+
sage: H2 = Q.P(GF(3), 2).Hom(Q.S(GF(3), 1))
|
155
|
+
sage: H1.an_element() in H1 # indirect doctest
|
156
|
+
True
|
157
|
+
"""
|
158
|
+
# The data of a representation is held in the following private
|
159
|
+
# variables:
|
160
|
+
#
|
161
|
+
# * _quiver
|
162
|
+
# The quiver of the representation.
|
163
|
+
# * _base_ring
|
164
|
+
# The base ring of the representation.
|
165
|
+
# * _domain
|
166
|
+
# The QuiverRep object that is the domain of the homomorphism.
|
167
|
+
# * _codomain
|
168
|
+
# The QuiverRep object that is the codomain of the homomorphism.
|
169
|
+
# * _vector
|
170
|
+
# A vector in some free module over the base ring of a length such
|
171
|
+
# that each coordinate corresponds to an entry in the matrix of a
|
172
|
+
# homomorphism attached to a vertex.
|
173
|
+
#
|
174
|
+
# The variable data can also be a vector of appropriate length. When
|
175
|
+
# this is the case it will be loaded directly into _vector and then
|
176
|
+
# _assert_valid_hom is called.
|
177
|
+
|
178
|
+
from sage.quivers.representation import (
|
179
|
+
QuiverRep_with_path_basis,
|
180
|
+
QuiverRepElement,
|
181
|
+
)
|
182
|
+
|
183
|
+
self._domain = domain
|
184
|
+
self._codomain = codomain
|
185
|
+
self._quiver = domain._quiver
|
186
|
+
self._base_ring = domain.base_ring()
|
187
|
+
|
188
|
+
# Check that the quiver and base ring match
|
189
|
+
if codomain._quiver != self._quiver:
|
190
|
+
raise ValueError("the quivers of the domain and codomain must be equal")
|
191
|
+
if codomain.base_ring() != self._base_ring:
|
192
|
+
raise ValueError("the base ring of the domain and codomain must be equal")
|
193
|
+
|
194
|
+
# Get the dimensions of the spaces
|
195
|
+
mat_dims = {}
|
196
|
+
domain_dims = {}
|
197
|
+
codomain_dims = {}
|
198
|
+
for v in self._quiver:
|
199
|
+
domain_dims[v] = domain._spaces[v].dimension()
|
200
|
+
codomain_dims[v] = codomain._spaces[v].dimension()
|
201
|
+
mat_dims[v] = domain_dims[v] * codomain_dims[v]
|
202
|
+
total_dim = sum(mat_dims.values())
|
203
|
+
|
204
|
+
# Handle the case when data is a vector
|
205
|
+
if data in self._base_ring**total_dim:
|
206
|
+
self._vector = data
|
207
|
+
self._assert_valid_hom()
|
208
|
+
super().__init__(domain.Hom(codomain))
|
209
|
+
return
|
210
|
+
|
211
|
+
# If data is not a dict, create one
|
212
|
+
if isinstance(data, dict):
|
213
|
+
maps_dict = data
|
214
|
+
else:
|
215
|
+
# If data is not a list create one, then create a dict from it
|
216
|
+
if isinstance(data, list):
|
217
|
+
im_list = data
|
218
|
+
# If data is a QuiverRepHom, create a list from it
|
219
|
+
elif isinstance(data, QuiverRepHom):
|
220
|
+
f = data._domain.coerce_map_from(domain)
|
221
|
+
g = self._codomain.coerce_map_from(data._codomain)
|
222
|
+
im_list = [g(data(f(x))) for x in domain.gens()]
|
223
|
+
|
224
|
+
# The only case left is that data is a QuiverRepElement
|
225
|
+
else:
|
226
|
+
if not isinstance(data, QuiverRepElement):
|
227
|
+
raise TypeError("input data must be dictionary, list, "
|
228
|
+
"QuiverRepElement or vector")
|
229
|
+
if not isinstance(domain, QuiverRep_with_path_basis):
|
230
|
+
raise TypeError("if data is a QuiverRepElement then domain "
|
231
|
+
"must be a QuiverRep_with_path_basis.")
|
232
|
+
if data not in codomain:
|
233
|
+
raise ValueError("if data is a QuiverRepElement then it must "
|
234
|
+
"be an element of codomain")
|
235
|
+
im_list = [codomain.right_edge_action(data, p) for v in domain._quiver for p in domain._bases[v]]
|
236
|
+
|
237
|
+
# WARNING: This code assumes that the function QuiverRep.gens() returns
|
238
|
+
# the generators ordered first by vertex and then by the order of the
|
239
|
+
# gens() method of the space associated to that vertex. In particular
|
240
|
+
# this is the order that corresponds to how maps are represented via
|
241
|
+
# matrices
|
242
|
+
|
243
|
+
# Get the gens of the domain and check that im_list is the right length
|
244
|
+
dom_gens = domain.gens()
|
245
|
+
if len(im_list) != len(dom_gens):
|
246
|
+
raise ValueError(("domain is dimension {} but only {} images"
|
247
|
+
" were supplied").format(len(dom_gens), len(im_list)))
|
248
|
+
|
249
|
+
# Get the matrices of the maps
|
250
|
+
start_index = 0
|
251
|
+
maps_dict = {}
|
252
|
+
for v in self._quiver:
|
253
|
+
maps_dict[v] = []
|
254
|
+
dim = domain._spaces[v].dimension()
|
255
|
+
for i in range(start_index, start_index + dim):
|
256
|
+
if im_list[i].support() and im_list[i].support() != [v]:
|
257
|
+
# If the element does not have the correct
|
258
|
+
# support raise an error here, otherwise we
|
259
|
+
# might create a valid hom that does not map
|
260
|
+
# the generators to the supplied images
|
261
|
+
txt = "generator supported at vertex {} cannot"
|
262
|
+
txt += " map to element with support {}"
|
263
|
+
raise ValueError(txt.format(v, im_list[i].support()))
|
264
|
+
else:
|
265
|
+
# If the support works out add the images coordinates
|
266
|
+
# as a row of the matrix
|
267
|
+
maps_dict[v].append(codomain._spaces[v].coordinates(im_list[i]._elems[v]))
|
268
|
+
|
269
|
+
start_index += dim
|
270
|
+
|
271
|
+
# Get the coordinates of the vector
|
272
|
+
from sage.categories.map import Map
|
273
|
+
vector = []
|
274
|
+
for v in self._quiver:
|
275
|
+
if v in maps_dict:
|
276
|
+
if isinstance(maps_dict[v], Map):
|
277
|
+
try:
|
278
|
+
m = maps_dict[v].matrix()
|
279
|
+
except (AttributeError, ValueError):
|
280
|
+
gens_images = [codomain._spaces[v].coordinate_vector(maps_dict[v](x))
|
281
|
+
for x in domain._spaces[v].gens()]
|
282
|
+
m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v], gens_images)
|
283
|
+
else:
|
284
|
+
m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v], maps_dict[v])
|
285
|
+
else:
|
286
|
+
m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v])
|
287
|
+
for i in range(domain_dims[v]):
|
288
|
+
vector += list(m[i])
|
289
|
+
|
290
|
+
# Wrap as a vector, check it, and return
|
291
|
+
self._vector = (self._base_ring**total_dim)(vector)
|
292
|
+
self._assert_valid_hom()
|
293
|
+
super().__init__(domain.Hom(codomain))
|
294
|
+
|
295
|
+
def _repr_(self):
|
296
|
+
"""
|
297
|
+
Default string representation.
|
298
|
+
|
299
|
+
TESTS::
|
300
|
+
|
301
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
302
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
303
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
304
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
305
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
306
|
+
sage: S = Q.representation(QQ, spaces2)
|
307
|
+
sage: S.hom(M) # indirect doctest
|
308
|
+
Homomorphism of representations of Multi-digraph on 3 vertices
|
309
|
+
"""
|
310
|
+
return "Homomorphism of representations of " + repr(self._quiver)
|
311
|
+
|
312
|
+
def _call_(self, x):
|
313
|
+
"""
|
314
|
+
TESTS::
|
315
|
+
|
316
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
317
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
318
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
319
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
320
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
321
|
+
sage: S = Q.representation(QQ, spaces2)
|
322
|
+
sage: x = M({2: (1, -1)})
|
323
|
+
sage: y = M({3: (1,)})
|
324
|
+
sage: h = S.hom([x, y], M)
|
325
|
+
sage: h(S.gens()[0]) == x
|
326
|
+
True
|
327
|
+
sage: h(S.gens()[1]) == y
|
328
|
+
True
|
329
|
+
|
330
|
+
The following was an issue during work on :issue:`12630`::
|
331
|
+
|
332
|
+
sage: Q = DiGraph({1: {}}).path_semigroup()
|
333
|
+
sage: M = Q.I(GF(3), 1)
|
334
|
+
sage: m = M.an_element()
|
335
|
+
sage: R = M.quotient(M)
|
336
|
+
sage: R(m)
|
337
|
+
Element of quiver representation
|
338
|
+
"""
|
339
|
+
from sage.quivers.representation import QuiverRepElement
|
340
|
+
# Check the input
|
341
|
+
if not isinstance(x, QuiverRepElement):
|
342
|
+
raise ValueError("QuiverRepHom can only be called on QuiverRepElement")
|
343
|
+
|
344
|
+
elements = {v: self.get_map(v)(x._elems[v]) for v in self._quiver}
|
345
|
+
return self._codomain(elements)
|
346
|
+
|
347
|
+
def __add__(left, right):
|
348
|
+
"""
|
349
|
+
This function overloads the ``+`` operator.
|
350
|
+
|
351
|
+
TESTS::
|
352
|
+
|
353
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
354
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
355
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
356
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
357
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
358
|
+
sage: S = Q.representation(QQ, spaces2)
|
359
|
+
sage: x = M({2: (1, -1)})
|
360
|
+
sage: z = M.zero()
|
361
|
+
sage: h = S.hom([x, z], M)
|
362
|
+
sage: g = S.hom([z, z], M)
|
363
|
+
sage: f = g + h
|
364
|
+
sage: f(S.gens()[0]) == x
|
365
|
+
True
|
366
|
+
sage: f(S.gens()[1]) == z
|
367
|
+
True
|
368
|
+
"""
|
369
|
+
new_vector = left._vector + right._vector
|
370
|
+
return left._domain.hom(new_vector, left._codomain)
|
371
|
+
|
372
|
+
def __iadd__(self, other):
|
373
|
+
"""
|
374
|
+
This function overloads the ``+=`` operator.
|
375
|
+
|
376
|
+
TESTS::
|
377
|
+
|
378
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
379
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
380
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
381
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
382
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
383
|
+
sage: S = Q.representation(QQ, spaces2)
|
384
|
+
sage: x = M({2: (1, -1)})
|
385
|
+
sage: z = M.zero()
|
386
|
+
sage: h = S.hom([x, z], M)
|
387
|
+
sage: g = S.hom([z, z], M)
|
388
|
+
sage: g += h
|
389
|
+
sage: g(S.gens()[0]) == x
|
390
|
+
True
|
391
|
+
sage: g(S.gens()[1]) == z
|
392
|
+
True
|
393
|
+
"""
|
394
|
+
self._vector += other._vector
|
395
|
+
return self
|
396
|
+
|
397
|
+
def __sub__(left, right):
|
398
|
+
"""
|
399
|
+
This function overloads the ``-`` operator.
|
400
|
+
|
401
|
+
TESTS::
|
402
|
+
|
403
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
404
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
405
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
406
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
407
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
408
|
+
sage: S = Q.representation(QQ, spaces2)
|
409
|
+
sage: x = M({2: (1, -1)})
|
410
|
+
sage: y = M({3: (1,)})
|
411
|
+
sage: z = M.zero()
|
412
|
+
sage: h = S.hom([x, z], M)
|
413
|
+
sage: g = S.hom([z, y], M)
|
414
|
+
sage: f = h - g
|
415
|
+
sage: f(S.gens()[0]) == x
|
416
|
+
True
|
417
|
+
sage: f(S.gens()[1]) == -y
|
418
|
+
True
|
419
|
+
"""
|
420
|
+
new_vector = left._vector - right._vector
|
421
|
+
return left._domain.hom(new_vector, left._codomain)
|
422
|
+
|
423
|
+
def __isub__(self, other):
|
424
|
+
"""
|
425
|
+
This function overloads the ``-=`` operator.
|
426
|
+
|
427
|
+
TESTS::
|
428
|
+
|
429
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
430
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
431
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
432
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
433
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
434
|
+
sage: S = Q.representation(QQ, spaces2)
|
435
|
+
sage: x = M({2: (1, -1)})
|
436
|
+
sage: y = M({3: (1,)})
|
437
|
+
sage: z = M.zero()
|
438
|
+
sage: h = S.hom([x, z], M)
|
439
|
+
sage: g = S.hom([z, y], M)
|
440
|
+
sage: h -= g
|
441
|
+
sage: h(S.gens()[0]) == x
|
442
|
+
True
|
443
|
+
sage: h(S.gens()[1]) == -y
|
444
|
+
True
|
445
|
+
"""
|
446
|
+
self._vector -= other._vector
|
447
|
+
return self
|
448
|
+
|
449
|
+
def __neg__(self):
|
450
|
+
"""
|
451
|
+
This function overrides the unary ``-`` operator.
|
452
|
+
|
453
|
+
TESTS::
|
454
|
+
|
455
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
456
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
457
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
458
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
459
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
460
|
+
sage: S = Q.representation(QQ, spaces2)
|
461
|
+
sage: x = M({2: (1, -1)})
|
462
|
+
sage: y = M({3: (1,)})
|
463
|
+
sage: h = S.hom([x, y], M)
|
464
|
+
sage: g = -h
|
465
|
+
sage: g(S.gens()[0]) == -x
|
466
|
+
True
|
467
|
+
sage: g(S.gens()[1]) == -y
|
468
|
+
True
|
469
|
+
"""
|
470
|
+
return self._domain.hom(-self._vector, self._codomain)
|
471
|
+
|
472
|
+
def __pos__(self):
|
473
|
+
"""
|
474
|
+
This function overrides the unary ``+`` operator.
|
475
|
+
|
476
|
+
TESTS::
|
477
|
+
|
478
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
479
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
480
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
481
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
482
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
483
|
+
sage: S = Q.representation(QQ, spaces2)
|
484
|
+
sage: x = M({2: (1, -1)})
|
485
|
+
sage: y = M({3: (1,)})
|
486
|
+
sage: h = S.hom([x, y], M)
|
487
|
+
sage: g = +h
|
488
|
+
sage: g == h
|
489
|
+
True
|
490
|
+
"""
|
491
|
+
return self
|
492
|
+
|
493
|
+
def __eq__(self, other):
|
494
|
+
"""
|
495
|
+
This function overrides the ``==`` operator.
|
496
|
+
|
497
|
+
TESTS::
|
498
|
+
|
499
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
500
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
501
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
502
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
503
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
504
|
+
sage: S = Q.representation(QQ, spaces2)
|
505
|
+
sage: x = M({2: (1, -1)})
|
506
|
+
sage: y = M({3: (1,)})
|
507
|
+
sage: g = S.hom([x, y], M)
|
508
|
+
sage: h = S.hom([x, y], M)
|
509
|
+
sage: g == h
|
510
|
+
True
|
511
|
+
"""
|
512
|
+
# A homomorphism can only be equal to another homomorphism between the
|
513
|
+
# same domain and codomain
|
514
|
+
if not isinstance(other, QuiverRepHom) or self._domain != other._domain or self._codomain != other._codomain:
|
515
|
+
return False
|
516
|
+
|
517
|
+
# If all that holds just check the vectors
|
518
|
+
return self._vector == other._vector
|
519
|
+
|
520
|
+
def __hash__(self):
|
521
|
+
"""
|
522
|
+
Return the hash of ``self``.
|
523
|
+
|
524
|
+
EXAMPLES::
|
525
|
+
|
526
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
527
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
528
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
529
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
530
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
531
|
+
sage: S = Q.representation(QQ, spaces2)
|
532
|
+
sage: x = M({2: (1, -1)})
|
533
|
+
sage: y = M({3: (1,)})
|
534
|
+
sage: g = S.hom([x, y], M)
|
535
|
+
sage: H = hash(g)
|
536
|
+
"""
|
537
|
+
return hash(tuple(self._vector))
|
538
|
+
|
539
|
+
def __ne__(self, other):
|
540
|
+
"""
|
541
|
+
This function overrides the ``!=`` operator.
|
542
|
+
|
543
|
+
TESTS::
|
544
|
+
|
545
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
546
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
547
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
548
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
549
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
550
|
+
sage: S = Q.representation(QQ, spaces2)
|
551
|
+
sage: x = M({2: (1, -1)})
|
552
|
+
sage: y = M({3: (1,)})
|
553
|
+
sage: z = M.zero()
|
554
|
+
sage: g = S.hom([x, y], M)
|
555
|
+
sage: h = S.hom([x, z], M)
|
556
|
+
sage: g != h
|
557
|
+
True
|
558
|
+
"""
|
559
|
+
# A homomorphism can only be equal to another homomorphism between the
|
560
|
+
# same domain and codomain
|
561
|
+
if not isinstance(other, QuiverRepHom) or self._domain != other._domain or self._codomain != other._codomain:
|
562
|
+
return True
|
563
|
+
|
564
|
+
# If all that holds just check the vectors
|
565
|
+
return self._vector != other._vector
|
566
|
+
|
567
|
+
def __bool__(self) -> bool:
|
568
|
+
"""
|
569
|
+
Return whether ``self`` is the zero morphism.
|
570
|
+
|
571
|
+
EXAMPLES::
|
572
|
+
|
573
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
574
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
575
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
576
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
577
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
578
|
+
sage: S = Q.representation(QQ, spaces2)
|
579
|
+
sage: x = M({2: (1, -1)})
|
580
|
+
sage: y = M({3: (1,)})
|
581
|
+
sage: z = M.zero()
|
582
|
+
sage: g = S.hom([x, y], M)
|
583
|
+
sage: h = S.hom([z, z], M)
|
584
|
+
sage: bool(g)
|
585
|
+
True
|
586
|
+
sage: bool(h)
|
587
|
+
False
|
588
|
+
"""
|
589
|
+
return any(self._vector)
|
590
|
+
|
591
|
+
def __mul__(self, other):
|
592
|
+
"""
|
593
|
+
This function overrides the ``*`` operator.
|
594
|
+
|
595
|
+
TESTS::
|
596
|
+
|
597
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
598
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
599
|
+
sage: S = Q.representation(QQ, spaces2)
|
600
|
+
sage: x = S.gens()[0]
|
601
|
+
sage: y = S.gens()[1]
|
602
|
+
sage: g = S.hom([x, y], S)
|
603
|
+
sage: h = S.hom(S)
|
604
|
+
sage: (g*h).is_zero()
|
605
|
+
True
|
606
|
+
"""
|
607
|
+
maps = {v: other.get_matrix(v) * self.get_matrix(v)
|
608
|
+
for v in self._quiver}
|
609
|
+
return other._domain.hom(maps, self._codomain)
|
610
|
+
|
611
|
+
###########################################################################
|
612
|
+
# #
|
613
|
+
# WELL DEFINEDNESS FUNCTIONS #
|
614
|
+
# These functions test and assert well definedness of the #
|
615
|
+
# homomorphism. #
|
616
|
+
# #
|
617
|
+
###########################################################################
|
618
|
+
|
619
|
+
def _assert_valid_hom(self):
|
620
|
+
"""
|
621
|
+
Raise a :exc:`ValueError` if the homomorphism is not well defined.
|
622
|
+
|
623
|
+
Specifically it checks that the domain and codomains of the maps are
|
624
|
+
correct and that the edge diagrams commute.
|
625
|
+
|
626
|
+
EXAMPLES::
|
627
|
+
|
628
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
629
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
630
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
631
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
632
|
+
sage: spaces2 = {2: QQ^1, 3: QQ^1}
|
633
|
+
sage: S = Q.representation(QQ, spaces2)
|
634
|
+
sage: maps2 = {2:[1, -1], 3:1}
|
635
|
+
sage: g = S.hom(maps2, M) # indirect doctest
|
636
|
+
sage: f = S.hom(maps2, S) # indirect doctest
|
637
|
+
Traceback (most recent call last):
|
638
|
+
...
|
639
|
+
TypeError: unable to convert {2: [1, -1], 3: 1} to an element of Dimension 2 QuiverHomSpace
|
640
|
+
"""
|
641
|
+
# Check that the domain and codomains dimensions add correctly
|
642
|
+
totaldim = 0
|
643
|
+
for v in self._quiver:
|
644
|
+
totaldim += self._domain._spaces[v].dimension() * self._codomain._spaces[v].dimension()
|
645
|
+
if totaldim != len(self._vector):
|
646
|
+
raise ValueError("dimensions do not match domain and codomain")
|
647
|
+
|
648
|
+
# Check that the edge diagrams commute
|
649
|
+
for e in self._domain._semigroup._sorted_edges:
|
650
|
+
if self.get_matrix(e[0]) * self._codomain._maps[e].matrix() != self._domain._maps[e].matrix() * self.get_matrix(e[1]):
|
651
|
+
raise ValueError("the diagram of edge {} does not commute".format(e))
|
652
|
+
|
653
|
+
###########################################################################
|
654
|
+
# #
|
655
|
+
# ACCESS FUNCTIONS #
|
656
|
+
# These functions are used to view the homomorphism data. #
|
657
|
+
# #
|
658
|
+
###########################################################################
|
659
|
+
|
660
|
+
def domain(self):
|
661
|
+
"""
|
662
|
+
Return the domain of the homomorphism.
|
663
|
+
|
664
|
+
OUTPUT: :class:`QuiverRep`; the domain
|
665
|
+
|
666
|
+
EXAMPLES::
|
667
|
+
|
668
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
669
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
670
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
671
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
672
|
+
sage: S = Q.representation(QQ)
|
673
|
+
sage: g = M.hom(S)
|
674
|
+
sage: g.domain() is M
|
675
|
+
True
|
676
|
+
"""
|
677
|
+
return self._domain
|
678
|
+
|
679
|
+
def codomain(self):
|
680
|
+
"""
|
681
|
+
Return the codomain of the homomorphism.
|
682
|
+
|
683
|
+
OUTPUT: :class:`QuiverRep`; the codomain
|
684
|
+
|
685
|
+
EXAMPLES::
|
686
|
+
|
687
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
688
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
689
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
690
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
691
|
+
sage: S = Q.representation(QQ)
|
692
|
+
sage: g = S.hom(M)
|
693
|
+
sage: g.codomain() is M
|
694
|
+
True
|
695
|
+
"""
|
696
|
+
return self._codomain
|
697
|
+
|
698
|
+
def get_matrix(self, vertex):
|
699
|
+
"""
|
700
|
+
Return the matrix of the homomorphism attached to vertex
|
701
|
+
``vertex``.
|
702
|
+
|
703
|
+
INPUT:
|
704
|
+
|
705
|
+
- ``vertex`` -- integer; a vertex of the quiver
|
706
|
+
|
707
|
+
OUTPUT: the matrix representing the homomorphism associated to
|
708
|
+
the given vertex
|
709
|
+
|
710
|
+
EXAMPLES::
|
711
|
+
|
712
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
713
|
+
sage: I = Q.I(QQ, 3)
|
714
|
+
sage: M = I/I.radical()
|
715
|
+
sage: f = M.coerce_map_from(I)
|
716
|
+
sage: f.get_matrix(1)
|
717
|
+
[1 0]
|
718
|
+
[0 1]
|
719
|
+
"""
|
720
|
+
# Get dimensions
|
721
|
+
startdim = 0
|
722
|
+
for v in self._quiver:
|
723
|
+
if v == vertex:
|
724
|
+
break
|
725
|
+
startdim += self._domain._spaces[v].dimension() * self._codomain._spaces[v].dimension()
|
726
|
+
|
727
|
+
rows = self._domain._spaces[vertex].dimension()
|
728
|
+
cols = self._codomain._spaces[vertex].dimension()
|
729
|
+
|
730
|
+
# Slice out the matrix and return
|
731
|
+
return Matrix(self._base_ring, rows, cols,
|
732
|
+
self._vector.list()[startdim:startdim + rows * cols])
|
733
|
+
|
734
|
+
def get_map(self, vertex):
|
735
|
+
"""
|
736
|
+
Return the homomorphism at the given vertex ``vertex``.
|
737
|
+
|
738
|
+
INPUT:
|
739
|
+
|
740
|
+
- ``vertex`` -- integer; a vertex of the quiver
|
741
|
+
|
742
|
+
OUTPUT: the homomorphism associated to the given vertex
|
743
|
+
|
744
|
+
EXAMPLES::
|
745
|
+
|
746
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
747
|
+
sage: P = Q.P(QQ, 1)
|
748
|
+
sage: S = P/P.radical()
|
749
|
+
sage: f = S.coerce_map_from(P)
|
750
|
+
sage: f.get_map(1).is_bijective()
|
751
|
+
True
|
752
|
+
"""
|
753
|
+
return self._domain._spaces[vertex].hom(self.get_matrix(vertex), self._codomain._spaces[vertex])
|
754
|
+
|
755
|
+
def quiver(self):
|
756
|
+
"""
|
757
|
+
Return the quiver of the representations in the domain/codomain.
|
758
|
+
|
759
|
+
OUTPUT:
|
760
|
+
|
761
|
+
- :class:`DiGraph`, the quiver of the representations in the domain
|
762
|
+
and codomain
|
763
|
+
|
764
|
+
EXAMPLES::
|
765
|
+
|
766
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
767
|
+
sage: P = Q.P(QQ, 1)
|
768
|
+
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
|
769
|
+
sage: f.quiver() is Q.quiver()
|
770
|
+
True
|
771
|
+
"""
|
772
|
+
return self._quiver
|
773
|
+
|
774
|
+
def base_ring(self):
|
775
|
+
"""
|
776
|
+
Return the base ring of the representation in the codomain.
|
777
|
+
|
778
|
+
OUTPUT: the base ring of the codomain
|
779
|
+
|
780
|
+
EXAMPLES::
|
781
|
+
|
782
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
783
|
+
sage: P = Q.P(QQ, 1)
|
784
|
+
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
|
785
|
+
sage: f.base_ring() is QQ
|
786
|
+
True
|
787
|
+
"""
|
788
|
+
return self._base_ring
|
789
|
+
|
790
|
+
###########################################################################
|
791
|
+
# #
|
792
|
+
# DATA FUNCTIONS #
|
793
|
+
# These functions return data collected from the homomorphism. #
|
794
|
+
# #
|
795
|
+
###########################################################################
|
796
|
+
|
797
|
+
def is_injective(self) -> bool:
|
798
|
+
"""
|
799
|
+
Test whether the homomorphism is injective.
|
800
|
+
|
801
|
+
OUTPUT: boolean; ``True`` if the homomorphism is injective, ``False``
|
802
|
+
otherwise
|
803
|
+
|
804
|
+
EXAMPLES::
|
805
|
+
|
806
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
807
|
+
sage: P = Q.P(QQ, 1)
|
808
|
+
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
|
809
|
+
sage: f.is_injective()
|
810
|
+
True
|
811
|
+
sage: g = P.hom(P)
|
812
|
+
sage: g.is_injective()
|
813
|
+
False
|
814
|
+
"""
|
815
|
+
# The homomorphism is injective if and only if it is injective at every
|
816
|
+
# vertex
|
817
|
+
return not any(self.get_matrix(v).nullity() for v in self._quiver)
|
818
|
+
|
819
|
+
def is_surjective(self) -> bool:
|
820
|
+
"""
|
821
|
+
Test whether the homomorphism is surjective.
|
822
|
+
|
823
|
+
OUTPUT: boolean; ``True`` if the homomorphism is surjective, ``False``
|
824
|
+
otherwise
|
825
|
+
|
826
|
+
EXAMPLES::
|
827
|
+
|
828
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
829
|
+
sage: P = Q.P(QQ, 1)
|
830
|
+
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
|
831
|
+
sage: f.is_surjective()
|
832
|
+
True
|
833
|
+
sage: g = P.hom(P)
|
834
|
+
sage: g.is_surjective()
|
835
|
+
False
|
836
|
+
"""
|
837
|
+
# The homomorphism is surjective if and only if it is surjective at
|
838
|
+
# every vertex
|
839
|
+
for v in self._quiver:
|
840
|
+
m = self.get_matrix(v)
|
841
|
+
if m.rank() != m.ncols():
|
842
|
+
return False
|
843
|
+
|
844
|
+
return True
|
845
|
+
|
846
|
+
def is_isomorphism(self) -> bool:
|
847
|
+
"""
|
848
|
+
Test whether the homomorphism is an isomorphism.
|
849
|
+
|
850
|
+
OUTPUT: boolean; ``True`` if the homomorphism is bijective, ``False``
|
851
|
+
otherwise
|
852
|
+
|
853
|
+
EXAMPLES::
|
854
|
+
|
855
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
856
|
+
sage: P = Q.P(QQ, 1)
|
857
|
+
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
|
858
|
+
sage: f.is_isomorphism()
|
859
|
+
True
|
860
|
+
sage: g = P.hom(P)
|
861
|
+
sage: g.is_isomorphism()
|
862
|
+
False
|
863
|
+
"""
|
864
|
+
# It's an iso if and only if it's an iso at every vertex
|
865
|
+
return all(self.get_matrix(v).is_invertible() for v in self._quiver)
|
866
|
+
|
867
|
+
def is_zero(self) -> bool:
|
868
|
+
"""
|
869
|
+
Test whether the homomorphism is the zero homomorphism.
|
870
|
+
|
871
|
+
OUTPUT: boolean; ``True`` if the homomorphism is zero, ``False``
|
872
|
+
otherwise
|
873
|
+
|
874
|
+
EXAMPLES::
|
875
|
+
|
876
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
877
|
+
sage: P = Q.P(QQ, 1)
|
878
|
+
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
|
879
|
+
sage: f.is_zero()
|
880
|
+
False
|
881
|
+
sage: g = P.hom(P)
|
882
|
+
sage: g.is_zero()
|
883
|
+
True
|
884
|
+
"""
|
885
|
+
# The homomorphism is zero if and only if it is zero at every vertex
|
886
|
+
return all(self.get_matrix(v).is_zero() for v in self._quiver)
|
887
|
+
|
888
|
+
def is_endomorphism(self) -> bool:
|
889
|
+
"""
|
890
|
+
Test whether the homomorphism is an endomorphism.
|
891
|
+
|
892
|
+
OUTPUT: boolean; ``True`` if the domain equals the codomain, ``False``
|
893
|
+
otherwise
|
894
|
+
|
895
|
+
EXAMPLES::
|
896
|
+
|
897
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
898
|
+
sage: P = Q.P(QQ, 1)
|
899
|
+
sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
|
900
|
+
sage: f.is_endomorphism()
|
901
|
+
True
|
902
|
+
sage: S = P/P.radical()
|
903
|
+
sage: g = S.coerce_map_from(P)
|
904
|
+
sage: g.is_endomorphism()
|
905
|
+
False
|
906
|
+
"""
|
907
|
+
return self._domain == self._codomain
|
908
|
+
|
909
|
+
def rank(self):
|
910
|
+
"""
|
911
|
+
Return the rank of the homomorphism ``self`` (as a `k`-linear
|
912
|
+
map).
|
913
|
+
|
914
|
+
OUTPUT: integer; the rank
|
915
|
+
|
916
|
+
EXAMPLES::
|
917
|
+
|
918
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
919
|
+
sage: P = Q.P(QQ, 1)
|
920
|
+
sage: S = P/P.radical()
|
921
|
+
sage: f = S.coerce_map_from(P)
|
922
|
+
sage: assert(f.rank() == 1)
|
923
|
+
"""
|
924
|
+
# The rank is the sum of the ranks at each vertex
|
925
|
+
return sum(self.get_matrix(v).rank() for v in self._quiver)
|
926
|
+
|
927
|
+
###########################################################################
|
928
|
+
# #
|
929
|
+
# CONSTRUCTION FUNCTIONS #
|
930
|
+
# These functions create new homomorphisms, representations, and #
|
931
|
+
# elements from the given homomorphism. #
|
932
|
+
# #
|
933
|
+
###########################################################################
|
934
|
+
|
935
|
+
def kernel(self):
|
936
|
+
"""
|
937
|
+
Return the kernel of ``self``.
|
938
|
+
|
939
|
+
OUTPUT: :class:`QuiverRep`; the kernel
|
940
|
+
|
941
|
+
.. NOTE::
|
942
|
+
|
943
|
+
To get the inclusion map of the kernel, ``K``, into the
|
944
|
+
domain, ``D``, use ``D.coerce_map_from(K)``.
|
945
|
+
|
946
|
+
EXAMPLES::
|
947
|
+
|
948
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
949
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
950
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
951
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
952
|
+
sage: spaces2 = {2: QQ^2, 3: QQ^1}
|
953
|
+
sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
|
954
|
+
sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
|
955
|
+
sage: g = N.hom(maps2, M)
|
956
|
+
sage: g.kernel().dimension_vector()
|
957
|
+
(0, 1, 0)
|
958
|
+
"""
|
959
|
+
spaces = {v: self.get_map(v).kernel() for v in self._quiver}
|
960
|
+
return self._domain._submodule(spaces)
|
961
|
+
|
962
|
+
def image(self):
|
963
|
+
"""
|
964
|
+
Return the image of ``self``.
|
965
|
+
|
966
|
+
OUTPUT: :class:`QuiverRep`; the image
|
967
|
+
|
968
|
+
.. NOTE::
|
969
|
+
|
970
|
+
To get the inclusion map of the image, ``I``, into the
|
971
|
+
codomain, ``C``, use ``C.coerce_map_from(I)``.
|
972
|
+
|
973
|
+
EXAMPLES::
|
974
|
+
|
975
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
976
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
977
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
978
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
979
|
+
sage: spaces2 = {2: QQ^2, 3: QQ^1}
|
980
|
+
sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
|
981
|
+
sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
|
982
|
+
sage: g = N.hom(maps2, M)
|
983
|
+
sage: g.image().dimension_vector()
|
984
|
+
(0, 1, 1)
|
985
|
+
"""
|
986
|
+
spaces = {v: self.get_map(v).image() for v in self._quiver}
|
987
|
+
return self._codomain._submodule(spaces)
|
988
|
+
|
989
|
+
def cokernel(self):
|
990
|
+
"""
|
991
|
+
Return the cokernel of ``self``.
|
992
|
+
|
993
|
+
OUTPUT: :class:`QuiverRep`; the cokernel
|
994
|
+
|
995
|
+
.. NOTE::
|
996
|
+
|
997
|
+
To get the factor map of the codomain, ``D``, onto the
|
998
|
+
cokernel, ``C``, use ``C.coerce_map_from(D)``.
|
999
|
+
|
1000
|
+
EXAMPLES::
|
1001
|
+
|
1002
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
1003
|
+
sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
|
1004
|
+
sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
|
1005
|
+
sage: M = Q.representation(QQ, spaces, maps)
|
1006
|
+
sage: spaces2 = {2: QQ^2, 3: QQ^1}
|
1007
|
+
sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
|
1008
|
+
sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
|
1009
|
+
sage: g = N.hom(maps2, M)
|
1010
|
+
sage: g.cokernel().dimension_vector()
|
1011
|
+
(2, 1, 0)
|
1012
|
+
"""
|
1013
|
+
return self._codomain.quotient(self.image())
|
1014
|
+
|
1015
|
+
def linear_dual(self):
|
1016
|
+
r"""
|
1017
|
+
Compute the linear dual `Df : DN \to DM` of
|
1018
|
+
``self`` = `f : M \to N` where `D(-) = Hom_k(-, k)`.
|
1019
|
+
|
1020
|
+
OUTPUT: :class:`QuiverRepHom`; the map `Df : DN \to DM`
|
1021
|
+
|
1022
|
+
.. NOTE::
|
1023
|
+
|
1024
|
+
If `e` is an edge of the quiver `Q` and `g` is an element of
|
1025
|
+
`Hom_k(N, k)` then we let `(ga)(m) = g(ma)`. This gives
|
1026
|
+
`Hom_k(N, k)` its structure as a module over the opposite
|
1027
|
+
quiver ``Q.reverse()``. The map `Hom_k(N, k) \to Hom_k(M, k)`
|
1028
|
+
returned sends `g` to `gf`.
|
1029
|
+
|
1030
|
+
EXAMPLES::
|
1031
|
+
|
1032
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
|
1033
|
+
sage: P = Q.P(QQ, 1)
|
1034
|
+
sage: S = P/P.radical()
|
1035
|
+
sage: f = S.coerce_map_from(P)
|
1036
|
+
|
1037
|
+
The dual of a surjective map is injective and vice versa::
|
1038
|
+
|
1039
|
+
sage: f.is_surjective()
|
1040
|
+
True
|
1041
|
+
sage: g = f.linear_dual()
|
1042
|
+
sage: g.is_injective()
|
1043
|
+
True
|
1044
|
+
|
1045
|
+
The dual of a right module is a left module for the same quiver, Sage
|
1046
|
+
represents this as a right module for the opposite quiver::
|
1047
|
+
|
1048
|
+
sage: g.quiver().path_semigroup() is Q.reverse()
|
1049
|
+
True
|
1050
|
+
|
1051
|
+
The double dual of a map is the original representation::
|
1052
|
+
|
1053
|
+
sage: g.linear_dual() == f
|
1054
|
+
True
|
1055
|
+
"""
|
1056
|
+
# The effect of the functor D is that it just transposes the matrix of
|
1057
|
+
# a hom
|
1058
|
+
maps = {v: self.get_matrix(v).transpose() for v in self._quiver}
|
1059
|
+
return self._codomain.linear_dual().hom(maps, self._domain.linear_dual())
|
1060
|
+
|
1061
|
+
def algebraic_dual(self):
|
1062
|
+
r"""
|
1063
|
+
Compute the algebraic dual `f^t : N^t \to M^t` of
|
1064
|
+
``self`` = `f : M \to N` where `(-)^t = Hom_Q(-, kQ)`.
|
1065
|
+
|
1066
|
+
OUTPUT: :class:`QuiverRepHom`; the map `f^t : N^t \to M^t`
|
1067
|
+
|
1068
|
+
.. NOTE::
|
1069
|
+
|
1070
|
+
If `e` is an edge of the quiver `Q` and `g` is an element of
|
1071
|
+
`Hom_Q(N, kQ)` then we let `(ge)(m) = eg(m)`. This gives
|
1072
|
+
`Hom_Q(N, kQ)` its structure as a module over the opposite
|
1073
|
+
quiver ``Q.reverse()``. The map
|
1074
|
+
`Hom_Q(N, kQ) \to Hom_Q(M, kQ)` returned sends `g` to `gf`.
|
1075
|
+
|
1076
|
+
EXAMPLES::
|
1077
|
+
|
1078
|
+
sage: Q = DiGraph({1:{2:['a'], 3:['b','c','d']}, 2:{4:['e','f']}, 3:{4:['g']}, 5:{2:['h','i']}}).path_semigroup()
|
1079
|
+
sage: P1 = Q.P(QQ, 4)
|
1080
|
+
sage: P1.algebraic_dual()
|
1081
|
+
Representation with dimension vector (5, 2, 1, 1, 4)
|
1082
|
+
|
1083
|
+
The algebraic dual of an indecomposable projective is the indecomposable
|
1084
|
+
projective of the same vertex in the opposite quiver. ::
|
1085
|
+
|
1086
|
+
sage: Q.reverse().P(QQ, 4)
|
1087
|
+
Representation with dimension vector (5, 2, 1, 1, 4)
|
1088
|
+
"""
|
1089
|
+
# Get the domain, its basis, and the codomain
|
1090
|
+
domain, domain_gens = self._codomain.algebraic_dual(True)
|
1091
|
+
codomain, co_domain_gens = self._domain.algebraic_dual(True)
|
1092
|
+
|
1093
|
+
# Find the images in the domain and create the module
|
1094
|
+
# H = QuiverHomSpace(self._domain, self._quiver.free_module(self._base_ring))
|
1095
|
+
im_gens = [codomain({v: (g * self)._vector})
|
1096
|
+
for v in self._quiver for g in domain_gens[v]]
|
1097
|
+
return domain.hom(im_gens, codomain)
|
1098
|
+
|
1099
|
+
def direct_sum(self, maps, return_maps=False, pinch=None):
|
1100
|
+
r"""
|
1101
|
+
Return the direct sum of ``self`` with the maps in the list ``maps``.
|
1102
|
+
|
1103
|
+
INPUT:
|
1104
|
+
|
1105
|
+
- ``maps`` -- :class:`QuiverRepHom` or list of :class:`QuiverRepHom`'s
|
1106
|
+
|
1107
|
+
- ``return_maps`` -- boolean (default: ``False``); if ``False``, then
|
1108
|
+
the return value is a :class:`QuiverRepHom` which is the direct sum
|
1109
|
+
of ``self`` with the :class:`QuiverRepHoms` in ``maps``.
|
1110
|
+
If ``True``, then the return value is a tuple of length either 3
|
1111
|
+
or 5. The first entry of the tuple is the QuiverRepHom giving
|
1112
|
+
the direct sum. If ``pinch`` is either ``None`` or
|
1113
|
+
``'codomain'`` then the next two entries in the tuple are lists
|
1114
|
+
giving respectively the inclusion and the projection maps for
|
1115
|
+
the factors of the direct sum. Summands are ordered as given
|
1116
|
+
in maps with ``self`` as the zeroth summand. If ``pinch`` is
|
1117
|
+
either ``None`` or ``'domain'`` then the next two entries in the
|
1118
|
+
tuple are the inclusion and projection maps for the codomain.
|
1119
|
+
Thus if ``pinch`` is ``None`` then the tuple will have length 5.
|
1120
|
+
If ``pinch`` is either ``'domain'`` or ``'codomain'`` then the
|
1121
|
+
tuple will have length 3.
|
1122
|
+
|
1123
|
+
- ``pinch`` -- string or ``None`` (default: ``None``); if this is
|
1124
|
+
equal to ``'domain'``, then the domains of ``self`` and the
|
1125
|
+
given maps must be equal. The direct sum of `f: A \to B` and
|
1126
|
+
`g: A \to C` returned is then the map `A \to B \oplus C` defined
|
1127
|
+
by sending `x` to `(f(x), g(x))`. If ``pinch`` equals
|
1128
|
+
``'codomain'``, then the codomains of ``self`` and the given
|
1129
|
+
maps must be equal. The direct sum of `f: A \to C` and
|
1130
|
+
`g: B \to C` returned is then the map `A \oplus B \to C` defined
|
1131
|
+
by sending `(x, y)` to `f(x) + g(y)`. Finally, if ``pinch`` is
|
1132
|
+
anything other than ``'domain'`` or ``'codomain'``, then the
|
1133
|
+
direct sum of `f: A \to B` and `g: C \to D` returned is the map
|
1134
|
+
`A \oplus C \to B \oplus D` defined by sending `(x, y)` to
|
1135
|
+
`(f(x), g(y))`.
|
1136
|
+
|
1137
|
+
OUTPUT: :class:`QuiverRepHom` or tuple
|
1138
|
+
|
1139
|
+
EXAMPLES::
|
1140
|
+
|
1141
|
+
sage: Q = DiGraph({1:{2:['a', 'b']}}).path_semigroup()
|
1142
|
+
sage: P1 = Q.P(GF(3), 1)
|
1143
|
+
sage: P2 = Q.P(GF(3), 2)
|
1144
|
+
sage: S1 = P1/P1.radical()
|
1145
|
+
sage: S2 = P2/P2.radical()
|
1146
|
+
sage: pi1 = S1.coerce_map_from(P1)
|
1147
|
+
sage: pi2 = S2.coerce_map_from(P2)
|
1148
|
+
sage: f = pi1.direct_sum(pi2)
|
1149
|
+
sage: f.domain().dimension_vector() == Q.free_module(GF(3)).dimension_vector()
|
1150
|
+
True
|
1151
|
+
sage: f.is_surjective()
|
1152
|
+
True
|
1153
|
+
sage: id = P1.Hom(P1).identity()
|
1154
|
+
sage: g = pi1.direct_sum(id, pinch='domain')
|
1155
|
+
sage: g.is_surjective()
|
1156
|
+
False
|
1157
|
+
"""
|
1158
|
+
# Get the list of maps to be summed
|
1159
|
+
if isinstance(maps, QuiverRepHom):
|
1160
|
+
maplist = [self, maps]
|
1161
|
+
else:
|
1162
|
+
maplist = [self] + maps
|
1163
|
+
|
1164
|
+
# Check that the quivers/base rings are the same. If pinching also
|
1165
|
+
# check that the domain/codomains are correct
|
1166
|
+
for x in maplist:
|
1167
|
+
if not isinstance(x, QuiverRepHom):
|
1168
|
+
raise TypeError("maps must be a QuiverRepHom or list of QuiverRepHoms")
|
1169
|
+
if self._quiver is not x._quiver:
|
1170
|
+
raise ValueError("cannot direct sum maps from different quivers")
|
1171
|
+
if self._base_ring is not x._base_ring:
|
1172
|
+
raise ValueError("base rings must be identical")
|
1173
|
+
if pinch == 'domain' and self._domain is not x._domain:
|
1174
|
+
raise ValueError("cannot pinch maps, domains do not agree")
|
1175
|
+
if pinch == 'codomain' and self._codomain is not x._codomain:
|
1176
|
+
raise ValueError("cannot pinch maps, codomains do not agree")
|
1177
|
+
|
1178
|
+
# Get the sums and their maps
|
1179
|
+
if pinch == 'domain':
|
1180
|
+
domain = self._domain
|
1181
|
+
else:
|
1182
|
+
domain, d_incl, d_proj = self._domain.direct_sum([x._domain for x in maplist[1:]], return_maps=True)
|
1183
|
+
if pinch == 'codomain':
|
1184
|
+
codomain = self._codomain
|
1185
|
+
else:
|
1186
|
+
codomain, c_incl, c_proj = self._codomain.direct_sum([x._codomain for x in maplist[1:]], return_maps=True)
|
1187
|
+
|
1188
|
+
# Start with the zero map
|
1189
|
+
result = domain.hom(codomain)
|
1190
|
+
|
1191
|
+
# Add each factor
|
1192
|
+
for i in range(len(maplist)):
|
1193
|
+
if pinch == 'domain':
|
1194
|
+
result += c_incl[i] * maplist[i]
|
1195
|
+
elif pinch == 'codomain':
|
1196
|
+
result += maplist[i] * d_proj[i]
|
1197
|
+
else:
|
1198
|
+
result += c_incl[i] * maplist[i] * d_proj[i]
|
1199
|
+
|
1200
|
+
# Return the results
|
1201
|
+
if return_maps:
|
1202
|
+
if pinch == 'domain':
|
1203
|
+
return (result, c_incl, c_proj)
|
1204
|
+
elif pinch == 'codomain':
|
1205
|
+
return (result, d_incl, d_proj)
|
1206
|
+
else:
|
1207
|
+
return (result, d_incl, d_proj, c_incl, c_proj)
|
1208
|
+
else:
|
1209
|
+
return result
|
1210
|
+
|
1211
|
+
def lift(self, x):
|
1212
|
+
"""
|
1213
|
+
Given an element `x` of the image, return an element of the domain
|
1214
|
+
that maps onto it under ``self``.
|
1215
|
+
|
1216
|
+
INPUT:
|
1217
|
+
|
1218
|
+
- ``x`` -- :class:`QuiverRepElement`
|
1219
|
+
|
1220
|
+
OUTPUT: :class:`QuiverRepElement`
|
1221
|
+
|
1222
|
+
EXAMPLES::
|
1223
|
+
|
1224
|
+
sage: Q = DiGraph({1:{2:['a','b']}, 2:{3:['c','d']}}).path_semigroup()
|
1225
|
+
sage: P = Q.P(QQ, 3)
|
1226
|
+
sage: S = P/P.radical()
|
1227
|
+
sage: proj = S.coerce_map_from(P)
|
1228
|
+
sage: x = S.an_element()
|
1229
|
+
sage: y = proj.lift(x)
|
1230
|
+
sage: proj(y) == x
|
1231
|
+
True
|
1232
|
+
sage: zero = S.hom(S, {})
|
1233
|
+
sage: zero.lift(x)
|
1234
|
+
Traceback (most recent call last):
|
1235
|
+
...
|
1236
|
+
ValueError: element is not in the image
|
1237
|
+
"""
|
1238
|
+
# Lift at each vertex
|
1239
|
+
elems = {v: self.get_map(v).lift(x._elems[v]) for v in self._quiver}
|
1240
|
+
return self._domain(elems)
|
1241
|
+
|
1242
|
+
###########################################################################
|
1243
|
+
# #
|
1244
|
+
# ADDITIONAL OPERATIONS #
|
1245
|
+
# These functions operations that are not implemented via binary #
|
1246
|
+
# operators. #
|
1247
|
+
# #
|
1248
|
+
###########################################################################
|
1249
|
+
|
1250
|
+
def scalar_mult(self, scalar):
|
1251
|
+
r"""
|
1252
|
+
Return the result of the scalar multiplication ``scalar * self``,
|
1253
|
+
where ``scalar`` is an element of the base ring `k`.
|
1254
|
+
|
1255
|
+
EXAMPLES::
|
1256
|
+
|
1257
|
+
sage: Q = DiGraph({1:{2:['a','b']}}).path_semigroup()
|
1258
|
+
sage: M = Q.P(QQ, 1)
|
1259
|
+
sage: f = M.Hom(M).an_element()
|
1260
|
+
sage: x = M.an_element()
|
1261
|
+
sage: g = f.scalar_mult(6)
|
1262
|
+
sage: g(x) == 6*f(x)
|
1263
|
+
True
|
1264
|
+
"""
|
1265
|
+
return self._domain.hom(scalar * self._vector, self._codomain)
|
1266
|
+
|
1267
|
+
def iscalar_mult(self, scalar):
|
1268
|
+
"""
|
1269
|
+
Multiply ``self`` by ``scalar`` in place.
|
1270
|
+
|
1271
|
+
EXAMPLES::
|
1272
|
+
|
1273
|
+
sage: Q = DiGraph({1:{2:['a','b']}}).path_semigroup()
|
1274
|
+
sage: M = Q.P(QQ, 1)
|
1275
|
+
sage: f = M.Hom(M).an_element()
|
1276
|
+
sage: x = M.an_element()
|
1277
|
+
sage: y = f(x)
|
1278
|
+
sage: f.iscalar_mult(6)
|
1279
|
+
sage: f(x) == 6*y
|
1280
|
+
True
|
1281
|
+
"""
|
1282
|
+
self._vector *= scalar
|