passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
|
@@ -0,0 +1,1598 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Quotient Rings
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- William Stein
|
|
8
|
+
- Simon King (2011-04): Put it into the category framework, use the
|
|
9
|
+
new coercion model.
|
|
10
|
+
- Simon King (2011-04): Quotients of non-commutative rings by
|
|
11
|
+
twosided ideals.
|
|
12
|
+
|
|
13
|
+
TESTS::
|
|
14
|
+
|
|
15
|
+
sage: R.<x> = PolynomialRing(ZZ)
|
|
16
|
+
sage: I = R.ideal([4 + 3*x + x^2, 1 + x^2])
|
|
17
|
+
sage: S = R.quotient_ring(I)
|
|
18
|
+
|
|
19
|
+
.. TODO::
|
|
20
|
+
|
|
21
|
+
The following skipped tests should be removed once :issue:`13999` is fixed::
|
|
22
|
+
|
|
23
|
+
sage: TestSuite(S).run(skip=['_test_nonzero_equal', '_test_elements', '_test_zero'])
|
|
24
|
+
|
|
25
|
+
In :issue:`11068`, non-commutative quotient rings `R/I` were
|
|
26
|
+
implemented. The only requirement is that the two-sided ideal `I`
|
|
27
|
+
provides a ``reduce`` method so that ``I.reduce(x)`` is the normal
|
|
28
|
+
form of an element `x` with respect to `I` (i.e., we have
|
|
29
|
+
``I.reduce(x) == I.reduce(y)`` if `x-y \in I`, and
|
|
30
|
+
``x - I.reduce(x) in I``). Here is a toy example::
|
|
31
|
+
|
|
32
|
+
sage: from sage.rings.noncommutative_ideals import Ideal_nc
|
|
33
|
+
sage: from itertools import product
|
|
34
|
+
sage: class PowerIdeal(Ideal_nc):
|
|
35
|
+
....: def __init__(self, R, n):
|
|
36
|
+
....: self._power = n
|
|
37
|
+
....: self._power = n
|
|
38
|
+
....: Ideal_nc.__init__(self, R, [R.prod(m) for m in product(R.gens(), repeat=n)])
|
|
39
|
+
....: def reduce(self, x):
|
|
40
|
+
....: R = self.ring()
|
|
41
|
+
....: return add([c*R(m) for m,c in x if len(m)<self._power],R(0))
|
|
42
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ, 3) # needs sage.combinat sage.modules
|
|
43
|
+
sage: I3 = PowerIdeal(F,3); I3 # needs sage.combinat sage.modules
|
|
44
|
+
Twosided Ideal (x^3, x^2*y, x^2*z, x*y*x, x*y^2, x*y*z, x*z*x, x*z*y,
|
|
45
|
+
x*z^2, y*x^2, y*x*y, y*x*z, y^2*x, y^3, y^2*z, y*z*x, y*z*y, y*z^2,
|
|
46
|
+
z*x^2, z*x*y, z*x*z, z*y*x, z*y^2, z*y*z, z^2*x, z^2*y, z^3) of
|
|
47
|
+
Free Algebra on 3 generators (x, y, z) over Rational Field
|
|
48
|
+
|
|
49
|
+
Free algebras have a custom quotient method that serves at creating
|
|
50
|
+
finite dimensional quotients defined by multiplication matrices. We
|
|
51
|
+
are bypassing it, so that we obtain the default quotient::
|
|
52
|
+
|
|
53
|
+
sage: # needs sage.combinat sage.modules
|
|
54
|
+
sage: Q3.<a,b,c> = F.quotient(I3)
|
|
55
|
+
sage: Q3
|
|
56
|
+
Quotient of Free Algebra on 3 generators (x, y, z) over Rational Field by
|
|
57
|
+
the ideal (x^3, x^2*y, x^2*z, x*y*x, x*y^2, x*y*z, x*z*x, x*z*y, x*z^2,
|
|
58
|
+
y*x^2, y*x*y, y*x*z, y^2*x, y^3, y^2*z, y*z*x, y*z*y, y*z^2, z*x^2, z*x*y,
|
|
59
|
+
z*x*z, z*y*x, z*y^2, z*y*z, z^2*x, z^2*y, z^3)
|
|
60
|
+
sage: (a+b+2)^4
|
|
61
|
+
16 + 32*a + 32*b + 24*a^2 + 24*a*b + 24*b*a + 24*b^2
|
|
62
|
+
sage: Q3.is_commutative()
|
|
63
|
+
False
|
|
64
|
+
|
|
65
|
+
Even though `Q_3` is not commutative, there is commutativity for
|
|
66
|
+
products of degree three::
|
|
67
|
+
|
|
68
|
+
sage: a*(b*c)-(b*c)*a==F.zero() # needs sage.combinat sage.modules
|
|
69
|
+
True
|
|
70
|
+
|
|
71
|
+
If we quotient out all terms of degree two then of course the resulting
|
|
72
|
+
quotient ring is commutative::
|
|
73
|
+
|
|
74
|
+
sage: # needs sage.combinat sage.modules
|
|
75
|
+
sage: I2 = PowerIdeal(F,2); I2
|
|
76
|
+
Twosided Ideal (x^2, x*y, x*z, y*x, y^2, y*z, z*x, z*y, z^2) of Free Algebra
|
|
77
|
+
on 3 generators (x, y, z) over Rational Field
|
|
78
|
+
sage: Q2.<a,b,c> = F.quotient(I2)
|
|
79
|
+
sage: Q2.is_commutative()
|
|
80
|
+
True
|
|
81
|
+
sage: (a+b+2)^4
|
|
82
|
+
16 + 32*a + 32*b
|
|
83
|
+
|
|
84
|
+
Since :issue:`7797`, there is an implementation of free algebras
|
|
85
|
+
based on Singular's implementation of the Letterplace Algebra. Our
|
|
86
|
+
letterplace wrapper allows to provide the above toy example more
|
|
87
|
+
easily::
|
|
88
|
+
|
|
89
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
90
|
+
sage: from itertools import product
|
|
91
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace')
|
|
92
|
+
sage: Q3 = F.quo(F*[F.prod(m) for m in product(F.gens(), repeat=3)]*F)
|
|
93
|
+
sage: Q3
|
|
94
|
+
Quotient of Free Associative Unital Algebra on 3 generators (x, y, z)
|
|
95
|
+
over Rational Field by the ideal (x*x*x, x*x*y, x*x*z, x*y*x, x*y*y, x*y*z,
|
|
96
|
+
x*z*x, x*z*y, x*z*z, y*x*x, y*x*y, y*x*z, y*y*x, y*y*y, y*y*z, y*z*x, y*z*y,
|
|
97
|
+
y*z*z, z*x*x, z*x*y, z*x*z, z*y*x, z*y*y, z*y*z, z*z*x, z*z*y, z*z*z)
|
|
98
|
+
sage: Q3.0*Q3.1 - Q3.1*Q3.0
|
|
99
|
+
xbar*ybar - ybar*xbar
|
|
100
|
+
sage: Q3.0*(Q3.1*Q3.2) - (Q3.1*Q3.2)*Q3.0
|
|
101
|
+
0
|
|
102
|
+
sage: Q2 = F.quo(F*[F.prod(m) for m in product(F.gens(), repeat=2)]*F)
|
|
103
|
+
sage: Q2.is_commutative()
|
|
104
|
+
True
|
|
105
|
+
"""
|
|
106
|
+
# ****************************************************************************
|
|
107
|
+
# Copyright (C) 2005 William Stein <wstein@gmail.com>
|
|
108
|
+
#
|
|
109
|
+
# This program is free software: you can redistribute it and/or modify
|
|
110
|
+
# it under the terms of the GNU General Public License as published by
|
|
111
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
112
|
+
# (at your option) any later version.
|
|
113
|
+
# https://www.gnu.org/licenses/
|
|
114
|
+
# ****************************************************************************
|
|
115
|
+
import sage.interfaces.abc
|
|
116
|
+
import sage.misc.latex as latex
|
|
117
|
+
import sage.structure.parent_gens
|
|
118
|
+
|
|
119
|
+
from sage.structure.parent import Parent
|
|
120
|
+
from sage.categories.commutative_rings import CommutativeRings
|
|
121
|
+
from sage.categories.rings import Rings
|
|
122
|
+
from sage.misc.cachefunc import cached_method
|
|
123
|
+
from sage.rings import ideal, quotient_ring_element, ring
|
|
124
|
+
from sage.structure.category_object import normalize_names
|
|
125
|
+
from sage.structure.richcmp import richcmp, richcmp_method
|
|
126
|
+
from sage.structure.category_object import check_default_category
|
|
127
|
+
|
|
128
|
+
_Rings = Rings()
|
|
129
|
+
_CommRings = CommutativeRings()
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
MPolynomialIdeal_quotient = None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def QuotientRing(R, I, names=None, **kwds):
|
|
136
|
+
r"""
|
|
137
|
+
Create a quotient ring of the ring `R` by the twosided ideal `I`.
|
|
138
|
+
|
|
139
|
+
Variables are labeled by ``names`` (if the quotient ring is a quotient
|
|
140
|
+
of a polynomial ring). If ``names`` isn't given, 'bar' will be appended
|
|
141
|
+
to the variable names in `R`.
|
|
142
|
+
|
|
143
|
+
INPUT:
|
|
144
|
+
|
|
145
|
+
- ``R`` -- a ring
|
|
146
|
+
|
|
147
|
+
- ``I`` -- a twosided ideal of `R`
|
|
148
|
+
|
|
149
|
+
- ``names`` -- (optional) a list of strings to be used as names for
|
|
150
|
+
the variables in the quotient ring `R/I`
|
|
151
|
+
|
|
152
|
+
- further named arguments that will be passed to the constructor
|
|
153
|
+
of the quotient ring instance
|
|
154
|
+
|
|
155
|
+
OUTPUT: `R/I` - the quotient ring `R` mod the ideal `I`
|
|
156
|
+
|
|
157
|
+
ASSUMPTION:
|
|
158
|
+
|
|
159
|
+
``I`` has a method ``I.reduce(x)`` returning the normal form
|
|
160
|
+
of elements `x\in R`. In other words, it is required that
|
|
161
|
+
``I.reduce(x)==I.reduce(y)`` `\iff x-y \in I`, and
|
|
162
|
+
``x-I.reduce(x) in I``, for all `x,y\in R`.
|
|
163
|
+
|
|
164
|
+
EXAMPLES:
|
|
165
|
+
|
|
166
|
+
Some simple quotient rings with the integers::
|
|
167
|
+
|
|
168
|
+
sage: R = QuotientRing(ZZ, 7*ZZ); R
|
|
169
|
+
Quotient of Integer Ring by the ideal (7)
|
|
170
|
+
sage: R.gens()
|
|
171
|
+
(1,)
|
|
172
|
+
sage: 1*R(3); 6*R(3); 7*R(3)
|
|
173
|
+
3
|
|
174
|
+
4
|
|
175
|
+
0
|
|
176
|
+
|
|
177
|
+
::
|
|
178
|
+
|
|
179
|
+
sage: S = QuotientRing(ZZ,ZZ.ideal(8)); S
|
|
180
|
+
Quotient of Integer Ring by the ideal (8)
|
|
181
|
+
sage: 2*S(4)
|
|
182
|
+
0
|
|
183
|
+
|
|
184
|
+
With polynomial rings (note that the variable name of the quotient
|
|
185
|
+
ring can be specified as shown below)::
|
|
186
|
+
|
|
187
|
+
sage: # needs sage.libs.pari
|
|
188
|
+
sage: P.<x> = QQ[]
|
|
189
|
+
sage: R.<xx> = QuotientRing(P, P.ideal(x^2 + 1))
|
|
190
|
+
sage: R
|
|
191
|
+
Univariate Quotient Polynomial Ring in xx over Rational Field
|
|
192
|
+
with modulus x^2 + 1
|
|
193
|
+
sage: R.gens(); R.gen()
|
|
194
|
+
(xx,)
|
|
195
|
+
xx
|
|
196
|
+
sage: for n in range(4): xx^n
|
|
197
|
+
1
|
|
198
|
+
xx
|
|
199
|
+
-1
|
|
200
|
+
-xx
|
|
201
|
+
|
|
202
|
+
::
|
|
203
|
+
|
|
204
|
+
sage: # needs sage.libs.pari
|
|
205
|
+
sage: P.<x> = QQ[]
|
|
206
|
+
sage: S = QuotientRing(P, P.ideal(x^2 - 2))
|
|
207
|
+
sage: S
|
|
208
|
+
Univariate Quotient Polynomial Ring in xbar over Rational Field
|
|
209
|
+
with modulus x^2 - 2
|
|
210
|
+
sage: xbar = S.gen(); S.gen()
|
|
211
|
+
xbar
|
|
212
|
+
sage: for n in range(3): xbar^n
|
|
213
|
+
1
|
|
214
|
+
xbar
|
|
215
|
+
2
|
|
216
|
+
|
|
217
|
+
Sage coerces objects into ideals when possible::
|
|
218
|
+
|
|
219
|
+
sage: P.<x> = QQ[]
|
|
220
|
+
sage: R = QuotientRing(P, x^2 + 1); R # needs sage.libs.pari
|
|
221
|
+
Univariate Quotient Polynomial Ring in xbar over Rational Field
|
|
222
|
+
with modulus x^2 + 1
|
|
223
|
+
|
|
224
|
+
By Noether's homomorphism theorems, the quotient of a quotient ring
|
|
225
|
+
of `R` is just the quotient of `R` by the sum of the ideals. In this
|
|
226
|
+
example, we end up modding out the ideal `(x)` from the ring
|
|
227
|
+
`\QQ[x,y]`::
|
|
228
|
+
|
|
229
|
+
sage: # needs sage.libs.pari sage.libs.singular
|
|
230
|
+
sage: R.<x,y> = PolynomialRing(QQ, 2)
|
|
231
|
+
sage: S.<a,b> = QuotientRing(R, R.ideal(1 + y^2))
|
|
232
|
+
sage: T.<c,d> = QuotientRing(S, S.ideal(a))
|
|
233
|
+
sage: T
|
|
234
|
+
Quotient of Multivariate Polynomial Ring in x, y over Rational Field
|
|
235
|
+
by the ideal (x, y^2 + 1)
|
|
236
|
+
sage: R.gens(); S.gens(); T.gens()
|
|
237
|
+
(x, y)
|
|
238
|
+
(a, b)
|
|
239
|
+
(0, d)
|
|
240
|
+
sage: for n in range(4): d^n
|
|
241
|
+
1
|
|
242
|
+
d
|
|
243
|
+
-1
|
|
244
|
+
-d
|
|
245
|
+
|
|
246
|
+
TESTS:
|
|
247
|
+
|
|
248
|
+
By :issue:`11068`, the following does not return a generic
|
|
249
|
+
quotient ring but a usual quotient of the integer ring::
|
|
250
|
+
|
|
251
|
+
sage: R = Integers(8)
|
|
252
|
+
sage: I = R.ideal(2)
|
|
253
|
+
sage: R.quotient(I)
|
|
254
|
+
Ring of integers modulo 2
|
|
255
|
+
|
|
256
|
+
Here is an example of the quotient of a free algebra by a
|
|
257
|
+
twosided homogeneous ideal (see :issue:`7797`)::
|
|
258
|
+
|
|
259
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
260
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace')
|
|
261
|
+
sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F
|
|
262
|
+
sage: Q.<a,b,c> = F.quo(I); Q
|
|
263
|
+
Quotient of Free Associative Unital Algebra on 3 generators (x, y, z)
|
|
264
|
+
over Rational Field by the ideal (x*y + y*z, x*x + x*y - y*x - y*y)
|
|
265
|
+
sage: a*b
|
|
266
|
+
-b*c
|
|
267
|
+
sage: a^3
|
|
268
|
+
-b*c*a - b*c*b - b*c*c
|
|
269
|
+
sage: J = Q * [a^3 - b^3] * Q
|
|
270
|
+
sage: R.<i,j,k> = Q.quo(J); R
|
|
271
|
+
Quotient of Free Associative Unital Algebra on 3 generators (x, y, z)
|
|
272
|
+
over Rational Field by the ideal
|
|
273
|
+
(-y*y*z - y*z*x - 2*y*z*z, x*y + y*z, x*x + x*y - y*x - y*y)
|
|
274
|
+
sage: i^3
|
|
275
|
+
-j*k*i - j*k*j - j*k*k
|
|
276
|
+
sage: j^3
|
|
277
|
+
-j*k*i - j*k*j - j*k*k
|
|
278
|
+
|
|
279
|
+
Check that :issue:`5978` is fixed by if we quotient by the zero ideal `(0)`
|
|
280
|
+
then we just return ``R``::
|
|
281
|
+
|
|
282
|
+
sage: R = QQ['x']
|
|
283
|
+
sage: R.quotient(R.zero_ideal())
|
|
284
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
285
|
+
sage: R.<x> = PolynomialRing(ZZ)
|
|
286
|
+
sage: R is R.quotient(R.zero_ideal())
|
|
287
|
+
True
|
|
288
|
+
sage: I = R.ideal(0)
|
|
289
|
+
sage: R is R.quotient(I)
|
|
290
|
+
True
|
|
291
|
+
"""
|
|
292
|
+
# 1. Not all rings inherit from the base class of rings.
|
|
293
|
+
# 2. We want to support quotients of free algebras by homogeneous two-sided ideals.
|
|
294
|
+
from sage.rings.finite_rings.integer_mod_ring import Integers
|
|
295
|
+
from sage.rings.integer_ring import ZZ
|
|
296
|
+
if R not in _Rings:
|
|
297
|
+
raise TypeError("R must be a ring")
|
|
298
|
+
is_commutative = R in _CommRings
|
|
299
|
+
if names is None:
|
|
300
|
+
try:
|
|
301
|
+
names = tuple([x + 'bar' for x in R.variable_names()])
|
|
302
|
+
except ValueError: # no names are assigned
|
|
303
|
+
pass
|
|
304
|
+
else:
|
|
305
|
+
names = normalize_names(R.ngens(), names)
|
|
306
|
+
if kwds.get('implementation') == 'pbori':
|
|
307
|
+
from sage.rings.polynomial.polynomial_ring_constructor import (
|
|
308
|
+
BooleanPolynomialRing_constructor as BooleanPolynomialRing,
|
|
309
|
+
)
|
|
310
|
+
kwds.pop('implementation')
|
|
311
|
+
return BooleanPolynomialRing(R.ngens(), names=names, **kwds)
|
|
312
|
+
# workaround to silence warning from #34806
|
|
313
|
+
from sage.rings.abc import Order
|
|
314
|
+
if isinstance(R, Order):
|
|
315
|
+
if not R.is_maximal():
|
|
316
|
+
raise NotImplementedError('only implemented for maximal orders')
|
|
317
|
+
I = R.number_field().ideal(I)
|
|
318
|
+
elif not isinstance(I, ideal.Ideal_generic) or I.ring() != R:
|
|
319
|
+
I = R.ideal(I)
|
|
320
|
+
if I.is_zero():
|
|
321
|
+
return R
|
|
322
|
+
try:
|
|
323
|
+
if I.is_principal():
|
|
324
|
+
return R.quotient_by_principal_ideal(I.gen(), names)
|
|
325
|
+
except (AttributeError, NotImplementedError):
|
|
326
|
+
pass
|
|
327
|
+
if not is_commutative:
|
|
328
|
+
try:
|
|
329
|
+
if I.side() != 'twosided':
|
|
330
|
+
raise AttributeError
|
|
331
|
+
except AttributeError:
|
|
332
|
+
raise TypeError("A twosided ideal is required.")
|
|
333
|
+
if isinstance(R, QuotientRing_nc):
|
|
334
|
+
pi = R.cover()
|
|
335
|
+
S = pi.domain()
|
|
336
|
+
G = [pi.lift(x) for x in I.gens()]
|
|
337
|
+
I_lift = S.ideal(G)
|
|
338
|
+
J = R.defining_ideal()
|
|
339
|
+
if S == ZZ:
|
|
340
|
+
return Integers((I_lift + J).gen(), **kwds)
|
|
341
|
+
return R.__class__(S, I_lift + J, names=names)
|
|
342
|
+
if R in _CommRings:
|
|
343
|
+
return QuotientRing_generic(R, I, names, **kwds)
|
|
344
|
+
return QuotientRing_nc(R, I, names, **kwds)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def is_QuotientRing(x):
|
|
348
|
+
"""
|
|
349
|
+
Test whether or not ``x`` inherits from :class:`QuotientRing_nc`.
|
|
350
|
+
|
|
351
|
+
EXAMPLES::
|
|
352
|
+
|
|
353
|
+
sage: from sage.rings.quotient_ring import is_QuotientRing
|
|
354
|
+
sage: R.<x> = PolynomialRing(ZZ,'x')
|
|
355
|
+
sage: I = R.ideal([4 + 3*x + x^2, 1 + x^2])
|
|
356
|
+
sage: S = R.quotient_ring(I)
|
|
357
|
+
sage: is_QuotientRing(S)
|
|
358
|
+
doctest:warning...
|
|
359
|
+
DeprecationWarning: The function is_QuotientRing is deprecated;
|
|
360
|
+
use 'isinstance(..., QuotientRing_nc)' instead.
|
|
361
|
+
See https://github.com/sagemath/sage/issues/38266 for details.
|
|
362
|
+
True
|
|
363
|
+
sage: is_QuotientRing(R)
|
|
364
|
+
False
|
|
365
|
+
|
|
366
|
+
::
|
|
367
|
+
|
|
368
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
369
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace')
|
|
370
|
+
sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F
|
|
371
|
+
sage: Q = F.quo(I)
|
|
372
|
+
sage: is_QuotientRing(Q)
|
|
373
|
+
True
|
|
374
|
+
sage: is_QuotientRing(F)
|
|
375
|
+
False
|
|
376
|
+
"""
|
|
377
|
+
from sage.misc.superseded import deprecation
|
|
378
|
+
deprecation(38266,
|
|
379
|
+
"The function is_QuotientRing is deprecated; "
|
|
380
|
+
"use 'isinstance(..., QuotientRing_nc)' instead.")
|
|
381
|
+
return isinstance(x, QuotientRing_nc)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
_RingsQuotients = _Rings.Quotients()
|
|
385
|
+
_CommutativeRingsQuotients = _CommRings.Quotients()
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
@richcmp_method
|
|
389
|
+
class QuotientRing_nc(Parent):
|
|
390
|
+
"""
|
|
391
|
+
The quotient ring of `R` by a twosided ideal `I`.
|
|
392
|
+
|
|
393
|
+
This class is for rings that are not in the category
|
|
394
|
+
``Rings().Commutative()``.
|
|
395
|
+
|
|
396
|
+
EXAMPLES:
|
|
397
|
+
|
|
398
|
+
Here is a quotient of a free algebra by a twosided homogeneous ideal::
|
|
399
|
+
|
|
400
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
401
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace')
|
|
402
|
+
sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2]*F
|
|
403
|
+
sage: Q.<a,b,c> = F.quo(I); Q
|
|
404
|
+
Quotient of Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field
|
|
405
|
+
by the ideal (x*y + y*z, x*x + x*y - y*x - y*y)
|
|
406
|
+
sage: a*b
|
|
407
|
+
-b*c
|
|
408
|
+
sage: a^3
|
|
409
|
+
-b*c*a - b*c*b - b*c*c
|
|
410
|
+
|
|
411
|
+
A quotient of a quotient is just the quotient of the original top
|
|
412
|
+
ring by the sum of two ideals::
|
|
413
|
+
|
|
414
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
415
|
+
sage: J = Q * [a^3 - b^3] * Q
|
|
416
|
+
sage: R.<i,j,k> = Q.quo(J); R
|
|
417
|
+
Quotient of
|
|
418
|
+
Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field
|
|
419
|
+
by the ideal (-y*y*z - y*z*x - 2*y*z*z, x*y + y*z, x*x + x*y - y*x - y*y)
|
|
420
|
+
sage: i^3
|
|
421
|
+
-j*k*i - j*k*j - j*k*k
|
|
422
|
+
sage: j^3
|
|
423
|
+
-j*k*i - j*k*j - j*k*k
|
|
424
|
+
|
|
425
|
+
For rings that *do* inherit from :class:`~sage.rings.ring.CommutativeRing`,
|
|
426
|
+
we provide a subclass :class:`QuotientRing_generic`, for backwards
|
|
427
|
+
compatibility.
|
|
428
|
+
|
|
429
|
+
EXAMPLES::
|
|
430
|
+
|
|
431
|
+
sage: R.<x> = PolynomialRing(ZZ,'x')
|
|
432
|
+
sage: I = R.ideal([4 + 3*x + x^2, 1 + x^2])
|
|
433
|
+
sage: S = R.quotient_ring(I); S
|
|
434
|
+
Quotient of Univariate Polynomial Ring in x over Integer Ring
|
|
435
|
+
by the ideal (x^2 + 3*x + 4, x^2 + 1)
|
|
436
|
+
|
|
437
|
+
::
|
|
438
|
+
|
|
439
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
440
|
+
sage: S.<a,b> = R.quo(x^2 + y^2) # needs sage.libs.singular
|
|
441
|
+
sage: a^2 + b^2 == 0 # needs sage.libs.singular
|
|
442
|
+
True
|
|
443
|
+
sage: S(0) == a^2 + b^2 # needs sage.libs.singular
|
|
444
|
+
True
|
|
445
|
+
|
|
446
|
+
Again, a quotient of a quotient is just the quotient of the original top
|
|
447
|
+
ring by the sum of two ideals.
|
|
448
|
+
|
|
449
|
+
::
|
|
450
|
+
|
|
451
|
+
sage: # needs sage.libs.singular
|
|
452
|
+
sage: R.<x,y> = PolynomialRing(QQ, 2)
|
|
453
|
+
sage: S.<a,b> = R.quo(1 + y^2)
|
|
454
|
+
sage: T.<c,d> = S.quo(a)
|
|
455
|
+
sage: T
|
|
456
|
+
Quotient of Multivariate Polynomial Ring in x, y over Rational Field
|
|
457
|
+
by the ideal (x, y^2 + 1)
|
|
458
|
+
sage: T.gens()
|
|
459
|
+
(0, d)
|
|
460
|
+
"""
|
|
461
|
+
Element = quotient_ring_element.QuotientRingElement
|
|
462
|
+
|
|
463
|
+
def __init__(self, R, I, names, category=None):
|
|
464
|
+
"""
|
|
465
|
+
Create the quotient ring of `R` by the twosided ideal `I`.
|
|
466
|
+
|
|
467
|
+
INPUT:
|
|
468
|
+
|
|
469
|
+
- ``R`` -- a ring
|
|
470
|
+
|
|
471
|
+
- ``I`` -- a twosided ideal of `R`
|
|
472
|
+
|
|
473
|
+
- ``names`` -- list of generator names
|
|
474
|
+
|
|
475
|
+
EXAMPLES::
|
|
476
|
+
|
|
477
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
478
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace')
|
|
479
|
+
sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F
|
|
480
|
+
sage: Q.<a,b,c> = F.quo(I); Q
|
|
481
|
+
Quotient of
|
|
482
|
+
Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field
|
|
483
|
+
by the ideal (x*y + y*z, x*x + x*y - y*x - y*y)
|
|
484
|
+
sage: a*b
|
|
485
|
+
-b*c
|
|
486
|
+
sage: a^3
|
|
487
|
+
-b*c*a - b*c*b - b*c*c
|
|
488
|
+
"""
|
|
489
|
+
if R not in _Rings:
|
|
490
|
+
raise TypeError("The first argument must be a ring, but %s is not" % R)
|
|
491
|
+
# workaround to silence warning from #34806
|
|
492
|
+
from sage.rings.abc import Order
|
|
493
|
+
if isinstance(R, Order):
|
|
494
|
+
M = R.number_field().ideal_monoid()
|
|
495
|
+
else:
|
|
496
|
+
M = R.ideal_monoid()
|
|
497
|
+
if I not in M:
|
|
498
|
+
raise TypeError("The second argument must be an ideal of the given ring, but %s is not" % I)
|
|
499
|
+
self.__R = R
|
|
500
|
+
self.__I = I
|
|
501
|
+
|
|
502
|
+
# Unfortunately, computing the join of categories, which is done in
|
|
503
|
+
# check_default_category, is very expensive.
|
|
504
|
+
# However, we don't just want to use the given category without mixing in
|
|
505
|
+
# some quotient stuff - unless Parent.__init__ was called
|
|
506
|
+
# previously, in which case the quotient ring stuff is just
|
|
507
|
+
# a waste of time. This is the case for FiniteField_prime_modn.
|
|
508
|
+
if not self._is_category_initialized():
|
|
509
|
+
if category is None:
|
|
510
|
+
try:
|
|
511
|
+
commutative = R.is_commutative()
|
|
512
|
+
except (AttributeError, NotImplementedError):
|
|
513
|
+
commutative = False
|
|
514
|
+
if commutative:
|
|
515
|
+
category = check_default_category(_CommutativeRingsQuotients, category)
|
|
516
|
+
else:
|
|
517
|
+
category = check_default_category(_RingsQuotients, category)
|
|
518
|
+
Parent.__init__(self, base=R.base_ring(), names=names, category=category)
|
|
519
|
+
# self._populate_coercion_lists_([R]) # we don't want to do this, since subclasses will often implement improved coercion maps.
|
|
520
|
+
|
|
521
|
+
def construction(self):
|
|
522
|
+
"""
|
|
523
|
+
Return the functorial construction of ``self``.
|
|
524
|
+
|
|
525
|
+
EXAMPLES::
|
|
526
|
+
|
|
527
|
+
sage: R.<x> = PolynomialRing(ZZ,'x')
|
|
528
|
+
sage: I = R.ideal([4 + 3*x + x^2, 1 + x^2])
|
|
529
|
+
sage: R.quotient_ring(I).construction()
|
|
530
|
+
(QuotientFunctor, Univariate Polynomial Ring in x over Integer Ring)
|
|
531
|
+
|
|
532
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
533
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace')
|
|
534
|
+
sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F
|
|
535
|
+
sage: Q = F.quo(I)
|
|
536
|
+
sage: Q.construction()
|
|
537
|
+
(QuotientFunctor,
|
|
538
|
+
Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field)
|
|
539
|
+
|
|
540
|
+
TESTS::
|
|
541
|
+
|
|
542
|
+
sage: F, R = Integers(5).construction()
|
|
543
|
+
sage: F(R)
|
|
544
|
+
Ring of integers modulo 5
|
|
545
|
+
sage: F, R = GF(5).construction()
|
|
546
|
+
sage: F(R)
|
|
547
|
+
Finite Field of size 5
|
|
548
|
+
"""
|
|
549
|
+
from sage.categories.pushout import QuotientFunctor
|
|
550
|
+
|
|
551
|
+
# Is there a better generic way to distinguish between things like Z/pZ as a field and Z/pZ as a ring?
|
|
552
|
+
from sage.rings.ring import Field
|
|
553
|
+
try:
|
|
554
|
+
names = self.variable_names()
|
|
555
|
+
except ValueError:
|
|
556
|
+
try:
|
|
557
|
+
names = self.cover_ring().variable_names()
|
|
558
|
+
except ValueError:
|
|
559
|
+
names = None
|
|
560
|
+
if self in _CommRings:
|
|
561
|
+
return QuotientFunctor(self.__I, names=names, domain=_CommRings,
|
|
562
|
+
codomain=_CommRings,
|
|
563
|
+
as_field=isinstance(self, Field)), self.__R
|
|
564
|
+
else:
|
|
565
|
+
return QuotientFunctor(self.__I, names=names,
|
|
566
|
+
as_field=isinstance(self, Field)), self.__R
|
|
567
|
+
|
|
568
|
+
def _repr_(self):
|
|
569
|
+
"""
|
|
570
|
+
Return a string representation of ``self``.
|
|
571
|
+
|
|
572
|
+
EXAMPLES::
|
|
573
|
+
|
|
574
|
+
sage: R.<x> = PolynomialRing(ZZ,'x')
|
|
575
|
+
sage: I = R.ideal([4 + 3*x + x^2, 1 + x^2])
|
|
576
|
+
sage: R.quotient_ring(I)._repr_()
|
|
577
|
+
'Quotient of Univariate Polynomial Ring in x over Integer Ring by the ideal (x^2 + 3*x + 4, x^2 + 1)'
|
|
578
|
+
"""
|
|
579
|
+
return "Quotient of %s by the ideal %s" % (self.cover_ring(), self.defining_ideal()._repr_short())
|
|
580
|
+
|
|
581
|
+
def _latex_(self):
|
|
582
|
+
"""
|
|
583
|
+
Return a latex representation of ``self``.
|
|
584
|
+
|
|
585
|
+
EXAMPLES::
|
|
586
|
+
|
|
587
|
+
sage: R.<x> = PolynomialRing(ZZ,'x')
|
|
588
|
+
sage: I = R.ideal([4 + 3*x + x^2, 1 + x^2])
|
|
589
|
+
sage: R.quotient_ring(I)._latex_()
|
|
590
|
+
'\\Bold{Z}[x]/\\left(x^{2} + 3x + 4, x^{2} + 1\\right)\\Bold{Z}[x]'
|
|
591
|
+
"""
|
|
592
|
+
return "%s/%s" % (latex.latex(self.cover_ring()), latex.latex(self.defining_ideal()))
|
|
593
|
+
|
|
594
|
+
def is_commutative(self) -> bool:
|
|
595
|
+
"""
|
|
596
|
+
Tell whether this quotient ring is commutative.
|
|
597
|
+
|
|
598
|
+
.. NOTE::
|
|
599
|
+
|
|
600
|
+
This is certainly the case if the cover ring is commutative.
|
|
601
|
+
Otherwise, if this ring has a finite number of generators, it
|
|
602
|
+
is tested whether they commute. If the number of generators is
|
|
603
|
+
infinite, a :exc:`NotImplementedError` is raised.
|
|
604
|
+
|
|
605
|
+
AUTHOR:
|
|
606
|
+
|
|
607
|
+
- Simon King (2011-03-23): See :issue:`7797`.
|
|
608
|
+
|
|
609
|
+
EXAMPLES:
|
|
610
|
+
|
|
611
|
+
Any quotient of a commutative ring is commutative::
|
|
612
|
+
|
|
613
|
+
sage: P.<a,b,c> = QQ[]
|
|
614
|
+
sage: P.quo(P.random_element()).is_commutative()
|
|
615
|
+
True
|
|
616
|
+
|
|
617
|
+
The non-commutative case is more interesting::
|
|
618
|
+
|
|
619
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
620
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace')
|
|
621
|
+
sage: I = F * [x*y + y*z, x^2 + x*y - y*x - y^2] * F
|
|
622
|
+
sage: Q = F.quo(I)
|
|
623
|
+
sage: Q.is_commutative()
|
|
624
|
+
False
|
|
625
|
+
sage: Q.1*Q.2 == Q.2*Q.1
|
|
626
|
+
False
|
|
627
|
+
|
|
628
|
+
In the next example, the generators apparently commute::
|
|
629
|
+
|
|
630
|
+
sage: # needs sage.combinat sage.libs.singular sage.modules
|
|
631
|
+
sage: J = F * [x*y - y*x, x*z - z*x, y*z - z*y, x^3 - y^3] * F
|
|
632
|
+
sage: R = F.quo(J)
|
|
633
|
+
sage: R.is_commutative()
|
|
634
|
+
True
|
|
635
|
+
"""
|
|
636
|
+
try:
|
|
637
|
+
if self.__R.is_commutative():
|
|
638
|
+
return True
|
|
639
|
+
except (AttributeError, NotImplementedError):
|
|
640
|
+
pass
|
|
641
|
+
from sage.rings.infinity import Infinity
|
|
642
|
+
if self.ngens() == Infinity:
|
|
643
|
+
raise NotImplementedError("This quotient ring has an infinite number of generators.")
|
|
644
|
+
for i in range(self.ngens()):
|
|
645
|
+
gi = self.gen(i)
|
|
646
|
+
for j in range(i + 1, self.ngens()):
|
|
647
|
+
gj = self.gen(j)
|
|
648
|
+
if gi * gj != gj * gi:
|
|
649
|
+
return False
|
|
650
|
+
return True
|
|
651
|
+
|
|
652
|
+
@cached_method
|
|
653
|
+
def cover(self):
|
|
654
|
+
r"""
|
|
655
|
+
The covering ring homomorphism `R \to R/I`, equipped with a section.
|
|
656
|
+
|
|
657
|
+
EXAMPLES::
|
|
658
|
+
|
|
659
|
+
sage: R = ZZ.quo(3 * ZZ)
|
|
660
|
+
sage: pi = R.cover()
|
|
661
|
+
sage: pi
|
|
662
|
+
Ring morphism:
|
|
663
|
+
From: Integer Ring
|
|
664
|
+
To: Ring of integers modulo 3
|
|
665
|
+
Defn: Natural quotient map
|
|
666
|
+
sage: pi(5)
|
|
667
|
+
2
|
|
668
|
+
sage: l = pi.lift()
|
|
669
|
+
|
|
670
|
+
::
|
|
671
|
+
|
|
672
|
+
sage: # needs sage.libs.singular
|
|
673
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
674
|
+
sage: Q = R.quo((x^2, y^2))
|
|
675
|
+
sage: pi = Q.cover()
|
|
676
|
+
sage: pi(x^3 + y)
|
|
677
|
+
ybar
|
|
678
|
+
sage: l = pi.lift(x + y^3)
|
|
679
|
+
sage: l
|
|
680
|
+
x
|
|
681
|
+
sage: l = pi.lift(); l
|
|
682
|
+
Set-theoretic ring morphism:
|
|
683
|
+
From: Quotient of Multivariate Polynomial Ring in x, y over Rational Field
|
|
684
|
+
by the ideal (x^2, y^2)
|
|
685
|
+
To: Multivariate Polynomial Ring in x, y over Rational Field
|
|
686
|
+
Defn: Choice of lifting map
|
|
687
|
+
sage: l(x + y^3)
|
|
688
|
+
x
|
|
689
|
+
"""
|
|
690
|
+
try:
|
|
691
|
+
return self.__cover
|
|
692
|
+
except AttributeError:
|
|
693
|
+
from . import morphism
|
|
694
|
+
pi = morphism.RingHomomorphism_cover(self.__R.Hom(self))
|
|
695
|
+
lift = self.lifting_map()
|
|
696
|
+
pi._set_lift(lift)
|
|
697
|
+
self.__cover = pi
|
|
698
|
+
return self.__cover
|
|
699
|
+
|
|
700
|
+
@cached_method
|
|
701
|
+
def lifting_map(self):
|
|
702
|
+
"""
|
|
703
|
+
Return the lifting map to the cover.
|
|
704
|
+
|
|
705
|
+
EXAMPLES::
|
|
706
|
+
|
|
707
|
+
sage: # needs sage.libs.singular
|
|
708
|
+
sage: R.<x,y> = PolynomialRing(QQ, 2)
|
|
709
|
+
sage: S = R.quotient(x^2 + y^2)
|
|
710
|
+
sage: pi = S.cover(); pi
|
|
711
|
+
Ring morphism:
|
|
712
|
+
From: Multivariate Polynomial Ring in x, y over Rational Field
|
|
713
|
+
To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field
|
|
714
|
+
by the ideal (x^2 + y^2)
|
|
715
|
+
Defn: Natural quotient map
|
|
716
|
+
sage: L = S.lifting_map(); L
|
|
717
|
+
Set-theoretic ring morphism:
|
|
718
|
+
From: Quotient of Multivariate Polynomial Ring in x, y over Rational Field
|
|
719
|
+
by the ideal (x^2 + y^2)
|
|
720
|
+
To: Multivariate Polynomial Ring in x, y over Rational Field
|
|
721
|
+
Defn: Choice of lifting map
|
|
722
|
+
sage: L(S.0)
|
|
723
|
+
x
|
|
724
|
+
sage: L(S.1)
|
|
725
|
+
y
|
|
726
|
+
|
|
727
|
+
Note that some reduction may be applied so that the lift of a
|
|
728
|
+
reduction need not equal the original element::
|
|
729
|
+
|
|
730
|
+
sage: z = pi(x^3 + 2*y^2); z # needs sage.libs.singular
|
|
731
|
+
-xbar*ybar^2 + 2*ybar^2
|
|
732
|
+
sage: L(z) # needs sage.libs.singular
|
|
733
|
+
-x*y^2 + 2*y^2
|
|
734
|
+
sage: L(z) == x^3 + 2*y^2 # needs sage.libs.singular
|
|
735
|
+
False
|
|
736
|
+
|
|
737
|
+
Test that there also is a lift for rings that are no
|
|
738
|
+
instances of :class:`~sage.rings.ring.Ring` (see :issue:`11068`)::
|
|
739
|
+
|
|
740
|
+
sage: # needs sage.modules
|
|
741
|
+
sage: MS = MatrixSpace(GF(5), 2, 2)
|
|
742
|
+
sage: I = MS * [MS.0*MS.1, MS.2 + MS.3] * MS
|
|
743
|
+
sage: Q = MS.quo(I)
|
|
744
|
+
sage: Q.lift()
|
|
745
|
+
Set-theoretic ring morphism:
|
|
746
|
+
From: Quotient of Full MatrixSpace of 2 by 2 dense matrices
|
|
747
|
+
over Finite Field of size 5 by the ideal
|
|
748
|
+
(
|
|
749
|
+
[0 1]
|
|
750
|
+
[0 0],
|
|
751
|
+
<BLANKLINE>
|
|
752
|
+
[0 0]
|
|
753
|
+
[1 1]
|
|
754
|
+
)
|
|
755
|
+
<BLANKLINE>
|
|
756
|
+
To: Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 5
|
|
757
|
+
Defn: Choice of lifting map
|
|
758
|
+
"""
|
|
759
|
+
try:
|
|
760
|
+
return self.__lift
|
|
761
|
+
except AttributeError:
|
|
762
|
+
pass
|
|
763
|
+
from .morphism import RingMap_lift
|
|
764
|
+
m = RingMap_lift(self, self.__R)
|
|
765
|
+
self.__lift = m
|
|
766
|
+
return m
|
|
767
|
+
|
|
768
|
+
# The following is to make the category framework happy.
|
|
769
|
+
def lift(self, x=None):
|
|
770
|
+
"""
|
|
771
|
+
Return the lifting map to the cover, or the image
|
|
772
|
+
of an element under the lifting map.
|
|
773
|
+
|
|
774
|
+
.. NOTE::
|
|
775
|
+
|
|
776
|
+
The category framework imposes that ``Q.lift(x)`` returns
|
|
777
|
+
the image of an element `x` under the lifting map. For
|
|
778
|
+
backwards compatibility, we let ``Q.lift()`` return the
|
|
779
|
+
lifting map.
|
|
780
|
+
|
|
781
|
+
EXAMPLES::
|
|
782
|
+
|
|
783
|
+
sage: R.<x,y> = PolynomialRing(QQ, 2)
|
|
784
|
+
sage: S = R.quotient(x^2 + y^2)
|
|
785
|
+
sage: S.lift() # needs sage.libs.singular
|
|
786
|
+
Set-theoretic ring morphism:
|
|
787
|
+
From: Quotient of Multivariate Polynomial Ring in x, y over Rational Field
|
|
788
|
+
by the ideal (x^2 + y^2)
|
|
789
|
+
To: Multivariate Polynomial Ring in x, y over Rational Field
|
|
790
|
+
Defn: Choice of lifting map
|
|
791
|
+
sage: S.lift(S.0) == x # needs sage.libs.singular
|
|
792
|
+
True
|
|
793
|
+
"""
|
|
794
|
+
if x is None:
|
|
795
|
+
return self.lifting_map()
|
|
796
|
+
return self.lifting_map()(x)
|
|
797
|
+
|
|
798
|
+
def retract(self, x):
|
|
799
|
+
"""
|
|
800
|
+
The image of an element of the cover ring under the quotient map.
|
|
801
|
+
|
|
802
|
+
INPUT:
|
|
803
|
+
|
|
804
|
+
- ``x`` -- an element of the cover ring
|
|
805
|
+
|
|
806
|
+
OUTPUT: the image of the given element in ``self``
|
|
807
|
+
|
|
808
|
+
EXAMPLES::
|
|
809
|
+
|
|
810
|
+
sage: R.<x,y> = PolynomialRing(QQ, 2)
|
|
811
|
+
sage: S = R.quotient(x^2 + y^2)
|
|
812
|
+
sage: S.retract((x+y)^2) # needs sage.libs.singular
|
|
813
|
+
2*xbar*ybar
|
|
814
|
+
"""
|
|
815
|
+
return self.cover()(x)
|
|
816
|
+
|
|
817
|
+
def characteristic(self):
|
|
818
|
+
r"""
|
|
819
|
+
Return the characteristic of the quotient ring.
|
|
820
|
+
|
|
821
|
+
.. TODO::
|
|
822
|
+
|
|
823
|
+
Not yet implemented!
|
|
824
|
+
|
|
825
|
+
EXAMPLES::
|
|
826
|
+
|
|
827
|
+
sage: Q = QuotientRing(ZZ,7*ZZ)
|
|
828
|
+
sage: Q.characteristic()
|
|
829
|
+
Traceback (most recent call last):
|
|
830
|
+
...
|
|
831
|
+
NotImplementedError
|
|
832
|
+
"""
|
|
833
|
+
raise NotImplementedError
|
|
834
|
+
|
|
835
|
+
def defining_ideal(self):
|
|
836
|
+
r"""
|
|
837
|
+
Return the ideal generating this quotient ring.
|
|
838
|
+
|
|
839
|
+
EXAMPLES:
|
|
840
|
+
|
|
841
|
+
In the integers::
|
|
842
|
+
|
|
843
|
+
sage: Q = QuotientRing(ZZ,7*ZZ)
|
|
844
|
+
sage: Q.defining_ideal()
|
|
845
|
+
Principal ideal (7) of Integer Ring
|
|
846
|
+
|
|
847
|
+
An example involving a quotient of a quotient. By Noether's
|
|
848
|
+
homomorphism theorems, this is actually a quotient by a sum of two
|
|
849
|
+
ideals::
|
|
850
|
+
|
|
851
|
+
sage: # needs sage.libs.singular
|
|
852
|
+
sage: R.<x,y> = PolynomialRing(QQ, 2)
|
|
853
|
+
sage: S.<a,b> = QuotientRing(R, R.ideal(1 + y^2))
|
|
854
|
+
sage: T.<c,d> = QuotientRing(S, S.ideal(a))
|
|
855
|
+
sage: S.defining_ideal()
|
|
856
|
+
Ideal (y^2 + 1) of Multivariate Polynomial Ring in x, y over Rational Field
|
|
857
|
+
sage: T.defining_ideal()
|
|
858
|
+
Ideal (x, y^2 + 1) of Multivariate Polynomial Ring in x, y over Rational Field
|
|
859
|
+
"""
|
|
860
|
+
return self.__I
|
|
861
|
+
|
|
862
|
+
@cached_method
|
|
863
|
+
def is_field(self, proof=True):
|
|
864
|
+
r"""
|
|
865
|
+
Return ``True`` if the quotient ring is a field. Checks to see if the
|
|
866
|
+
defining ideal is maximal.
|
|
867
|
+
|
|
868
|
+
TESTS::
|
|
869
|
+
|
|
870
|
+
sage: Q = QuotientRing(ZZ, 7*ZZ)
|
|
871
|
+
sage: Q.is_field()
|
|
872
|
+
True
|
|
873
|
+
|
|
874
|
+
Requires the ``is_maximal`` method of the defining ideal to be
|
|
875
|
+
implemented::
|
|
876
|
+
|
|
877
|
+
sage: R.<x, y> = ZZ[]
|
|
878
|
+
sage: R.quotient_ring(R.ideal([2, 4 + x])).is_field()
|
|
879
|
+
Traceback (most recent call last):
|
|
880
|
+
...
|
|
881
|
+
NotImplementedError
|
|
882
|
+
"""
|
|
883
|
+
if proof:
|
|
884
|
+
return self.defining_ideal().is_maximal()
|
|
885
|
+
else:
|
|
886
|
+
try:
|
|
887
|
+
return self.defining_ideal().is_maximal()
|
|
888
|
+
except NotImplementedError:
|
|
889
|
+
return False
|
|
890
|
+
|
|
891
|
+
@cached_method
|
|
892
|
+
def is_integral_domain(self, proof=True):
|
|
893
|
+
r"""
|
|
894
|
+
With ``proof`` equal to ``True`` (the default), this function may
|
|
895
|
+
raise a :exc:`NotImplementedError`.
|
|
896
|
+
|
|
897
|
+
When ``proof`` is ``False``, if ``True`` is returned, then ``self`` is
|
|
898
|
+
definitely an integral domain. If the function returns ``False``,
|
|
899
|
+
then either ``self`` is not an integral domain or it was unable to
|
|
900
|
+
determine whether or not ``self`` is an integral domain.
|
|
901
|
+
|
|
902
|
+
EXAMPLES::
|
|
903
|
+
|
|
904
|
+
sage: R.<x,y> = QQ[]
|
|
905
|
+
sage: R.quo(x^2 - y).is_integral_domain() # needs sage.libs.singular
|
|
906
|
+
True
|
|
907
|
+
sage: R.quo(x^2 - y^2).is_integral_domain() # needs sage.libs.singular
|
|
908
|
+
False
|
|
909
|
+
sage: R.quo(x^2 - y^2).is_integral_domain(proof=False) # needs sage.libs.singular
|
|
910
|
+
False
|
|
911
|
+
sage: R.<a,b,c> = ZZ[]
|
|
912
|
+
sage: Q = R.quotient_ring([a, b])
|
|
913
|
+
sage: Q.is_integral_domain()
|
|
914
|
+
Traceback (most recent call last):
|
|
915
|
+
...
|
|
916
|
+
NotImplementedError
|
|
917
|
+
sage: Q.is_integral_domain(proof=False)
|
|
918
|
+
False
|
|
919
|
+
"""
|
|
920
|
+
if proof:
|
|
921
|
+
return self.defining_ideal().is_prime()
|
|
922
|
+
else:
|
|
923
|
+
try:
|
|
924
|
+
return self.defining_ideal().is_prime()
|
|
925
|
+
except NotImplementedError:
|
|
926
|
+
return False
|
|
927
|
+
|
|
928
|
+
def is_noetherian(self):
|
|
929
|
+
r"""
|
|
930
|
+
Return ``True`` if this ring is Noetherian.
|
|
931
|
+
|
|
932
|
+
EXAMPLES::
|
|
933
|
+
|
|
934
|
+
sage: R = QuotientRing(ZZ, 102 * ZZ)
|
|
935
|
+
sage: R.is_noetherian()
|
|
936
|
+
True
|
|
937
|
+
|
|
938
|
+
sage: P.<x> = QQ[]
|
|
939
|
+
sage: R = QuotientRing(P, x^2 + 1) # needs sage.libs.pari
|
|
940
|
+
sage: R.is_noetherian()
|
|
941
|
+
True
|
|
942
|
+
|
|
943
|
+
If the cover ring of ``self`` is not Noetherian, we currently
|
|
944
|
+
have no way of testing whether ``self`` is Noetherian, so we
|
|
945
|
+
raise an error::
|
|
946
|
+
|
|
947
|
+
sage: R.<x> = InfinitePolynomialRing(QQ)
|
|
948
|
+
sage: R.is_noetherian()
|
|
949
|
+
False
|
|
950
|
+
sage: I = R.ideal([x[1]^2, x[2]])
|
|
951
|
+
sage: S = R.quotient(I)
|
|
952
|
+
sage: S.is_noetherian()
|
|
953
|
+
Traceback (most recent call last):
|
|
954
|
+
...
|
|
955
|
+
NotImplementedError
|
|
956
|
+
"""
|
|
957
|
+
# Naive test: if this is the quotient of a Noetherian ring,
|
|
958
|
+
# then it is Noetherian. Otherwise we give up.
|
|
959
|
+
if self.cover_ring().is_noetherian():
|
|
960
|
+
return True
|
|
961
|
+
|
|
962
|
+
raise NotImplementedError
|
|
963
|
+
|
|
964
|
+
def cover_ring(self):
|
|
965
|
+
r"""
|
|
966
|
+
Return the cover ring of the quotient ring: that is, the original
|
|
967
|
+
ring `R` from which we modded out an ideal, `I`.
|
|
968
|
+
|
|
969
|
+
EXAMPLES::
|
|
970
|
+
|
|
971
|
+
sage: Q = QuotientRing(ZZ, 7 * ZZ)
|
|
972
|
+
sage: Q.cover_ring()
|
|
973
|
+
Integer Ring
|
|
974
|
+
|
|
975
|
+
::
|
|
976
|
+
|
|
977
|
+
sage: P.<x> = QQ[]
|
|
978
|
+
sage: Q = QuotientRing(P, x^2 + 1) # needs sage.libs.pari
|
|
979
|
+
sage: Q.cover_ring() # needs sage.libs.pari
|
|
980
|
+
Univariate Polynomial Ring in x over Rational Field
|
|
981
|
+
"""
|
|
982
|
+
return self.__R
|
|
983
|
+
|
|
984
|
+
# This is to make the category framework happy
|
|
985
|
+
ambient = cover_ring
|
|
986
|
+
|
|
987
|
+
def ideal(self, *gens, **kwds):
|
|
988
|
+
"""
|
|
989
|
+
Return the ideal of ``self`` with the given generators.
|
|
990
|
+
|
|
991
|
+
EXAMPLES::
|
|
992
|
+
|
|
993
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
994
|
+
sage: S = R.quotient_ring(x^2 + y^2)
|
|
995
|
+
sage: S.ideal() # needs sage.libs.singular
|
|
996
|
+
Ideal (0) of Quotient of Multivariate Polynomial Ring in x, y
|
|
997
|
+
over Rational Field by the ideal (x^2 + y^2)
|
|
998
|
+
sage: S.ideal(x + y + 1) # needs sage.libs.singular
|
|
999
|
+
Ideal (xbar + ybar + 1) of Quotient of Multivariate Polynomial Ring in x, y
|
|
1000
|
+
over Rational Field by the ideal (x^2 + y^2)
|
|
1001
|
+
|
|
1002
|
+
TESTS:
|
|
1003
|
+
|
|
1004
|
+
We create an ideal of a fairly generic integer ring (see
|
|
1005
|
+
:issue:`5666`)::
|
|
1006
|
+
|
|
1007
|
+
sage: R = Integers(10)
|
|
1008
|
+
sage: R.ideal(1)
|
|
1009
|
+
Principal ideal (1) of Ring of integers modulo 10
|
|
1010
|
+
"""
|
|
1011
|
+
if len(gens) == 1:
|
|
1012
|
+
gens = gens[0]
|
|
1013
|
+
from sage.rings.polynomial.multi_polynomial_ring_base import (
|
|
1014
|
+
MPolynomialRing_base,
|
|
1015
|
+
)
|
|
1016
|
+
if not (isinstance(self.__R, MPolynomialRing_base) and self.__R._has_singular):
|
|
1017
|
+
# pass through
|
|
1018
|
+
return super().ideal(gens, **kwds)
|
|
1019
|
+
if isinstance(gens, sage.interfaces.abc.SingularElement):
|
|
1020
|
+
gens = list(gens)
|
|
1021
|
+
elif not isinstance(gens, (list, tuple)):
|
|
1022
|
+
gens = [gens]
|
|
1023
|
+
if 'coerce' in kwds and kwds['coerce']:
|
|
1024
|
+
gens = [self(x) for x in gens] # this will even coerce from singular ideals correctly!
|
|
1025
|
+
|
|
1026
|
+
global MPolynomialIdeal_quotient
|
|
1027
|
+
if MPolynomialIdeal_quotient is None:
|
|
1028
|
+
from sage.rings.polynomial.multi_polynomial_ideal import (
|
|
1029
|
+
MPolynomialIdeal_quotient,
|
|
1030
|
+
)
|
|
1031
|
+
return MPolynomialIdeal_quotient(self, gens, **kwds)
|
|
1032
|
+
|
|
1033
|
+
def _element_constructor_(self, x, coerce=True):
|
|
1034
|
+
"""
|
|
1035
|
+
Construct an element with ``self`` as the parent.
|
|
1036
|
+
|
|
1037
|
+
EXAMPLES::
|
|
1038
|
+
|
|
1039
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
1040
|
+
sage: S = R.quotient_ring(x^2 + y^2)
|
|
1041
|
+
sage: S(x) # indirect doctest # needs sage.libs.singular
|
|
1042
|
+
xbar
|
|
1043
|
+
sage: S(x^2 + y^2) # needs sage.libs.singular
|
|
1044
|
+
0
|
|
1045
|
+
|
|
1046
|
+
The rings that coerce into the quotient ring canonically, are:
|
|
1047
|
+
|
|
1048
|
+
- this ring
|
|
1049
|
+
|
|
1050
|
+
- anything that coerces into the ring of which this is the
|
|
1051
|
+
quotient
|
|
1052
|
+
|
|
1053
|
+
::
|
|
1054
|
+
|
|
1055
|
+
sage: # needs sage.libs.singular
|
|
1056
|
+
sage: R.<x,y> = PolynomialRing(QQ, 2)
|
|
1057
|
+
sage: S.<a,b> = R.quotient(x^2 + y^2)
|
|
1058
|
+
sage: S.coerce(0)
|
|
1059
|
+
0
|
|
1060
|
+
sage: S.coerce(2/3)
|
|
1061
|
+
2/3
|
|
1062
|
+
sage: S.coerce(a^2 - b)
|
|
1063
|
+
-b^2 - b
|
|
1064
|
+
sage: S.coerce(GF(7)(3))
|
|
1065
|
+
Traceback (most recent call last):
|
|
1066
|
+
...
|
|
1067
|
+
TypeError: no canonical coercion from Finite Field of size 7
|
|
1068
|
+
to Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
|
|
1069
|
+
|
|
1070
|
+
TESTS::
|
|
1071
|
+
|
|
1072
|
+
sage: S(x, coerce=False) # needs sage.libs.singular
|
|
1073
|
+
a
|
|
1074
|
+
"""
|
|
1075
|
+
if isinstance(x, quotient_ring_element.QuotientRingElement):
|
|
1076
|
+
if x.parent() is self:
|
|
1077
|
+
return x
|
|
1078
|
+
x = x.lift()
|
|
1079
|
+
if isinstance(x, sage.interfaces.abc.SingularElement):
|
|
1080
|
+
# self._singular_().set_ring()
|
|
1081
|
+
x = self.element_class(self, x.sage_poly(self.cover_ring()))
|
|
1082
|
+
return x
|
|
1083
|
+
if coerce:
|
|
1084
|
+
R = self.cover_ring()
|
|
1085
|
+
x = R(x)
|
|
1086
|
+
return self.element_class(self, x)
|
|
1087
|
+
|
|
1088
|
+
def _coerce_map_from_(self, R):
|
|
1089
|
+
"""
|
|
1090
|
+
Return ``True`` if there is a coercion map from ``R`` to ``self``.
|
|
1091
|
+
|
|
1092
|
+
EXAMPLES::
|
|
1093
|
+
|
|
1094
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
1095
|
+
sage: S = R.quotient_ring(x^2 + y^2)
|
|
1096
|
+
sage: S.has_coerce_map_from(R) # indirect doctest
|
|
1097
|
+
True
|
|
1098
|
+
sage: S.has_coerce_map_from(QQ)
|
|
1099
|
+
True
|
|
1100
|
+
sage: T = S.quotient_ring(x^3 - y) # needs sage.libs.singular
|
|
1101
|
+
sage: S.has_coerce_map_from(T) # needs sage.libs.singular
|
|
1102
|
+
False
|
|
1103
|
+
sage: T.has_coerce_map_from(R) # needs sage.libs.singular
|
|
1104
|
+
True
|
|
1105
|
+
|
|
1106
|
+
TESTS:
|
|
1107
|
+
|
|
1108
|
+
We check that :issue:`13682` is fixed::
|
|
1109
|
+
|
|
1110
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
1111
|
+
sage: I = R.ideal(x^2 + y^2)
|
|
1112
|
+
sage: J = R.ideal(x^2 + y^2, x^3 - y)
|
|
1113
|
+
sage: S = R.quotient(I)
|
|
1114
|
+
sage: T = R.quotient(J)
|
|
1115
|
+
|
|
1116
|
+
sage: # needs sage.libs.singular
|
|
1117
|
+
sage: I < J
|
|
1118
|
+
True
|
|
1119
|
+
sage: T.has_coerce_map_from(S)
|
|
1120
|
+
True
|
|
1121
|
+
sage: S.quotient_ring(x^4 - x*y + 1).has_coerce_map_from(S)
|
|
1122
|
+
True
|
|
1123
|
+
sage: S.has_coerce_map_from(T)
|
|
1124
|
+
False
|
|
1125
|
+
|
|
1126
|
+
We also allow coercions with the cover rings::
|
|
1127
|
+
|
|
1128
|
+
sage: Rp.<x,y> = PolynomialRing(ZZ)
|
|
1129
|
+
sage: Ip = Rp.ideal(x^2 + y^2)
|
|
1130
|
+
sage: Jp = Rp.ideal(x^2 + y^2, x^3 - y)
|
|
1131
|
+
sage: Sp = Rp.quotient(Ip)
|
|
1132
|
+
sage: Tp = Rp.quotient(Jp)
|
|
1133
|
+
sage: R.has_coerce_map_from(Rp)
|
|
1134
|
+
True
|
|
1135
|
+
sage: Sp.has_coerce_map_from(Sp)
|
|
1136
|
+
True
|
|
1137
|
+
sage: T.has_coerce_map_from(Sp) # needs sage.libs.singular
|
|
1138
|
+
True
|
|
1139
|
+
sage: Sp.has_coerce_map_from(T) # needs sage.libs.singular
|
|
1140
|
+
False
|
|
1141
|
+
"""
|
|
1142
|
+
C = self.cover_ring()
|
|
1143
|
+
if isinstance(R, QuotientRing_nc):
|
|
1144
|
+
if C == R.cover_ring():
|
|
1145
|
+
if R.defining_ideal() <= self.defining_ideal():
|
|
1146
|
+
return True
|
|
1147
|
+
elif C.has_coerce_map_from(R.cover_ring()):
|
|
1148
|
+
try:
|
|
1149
|
+
if R.defining_ideal().change_ring(C) <= self.defining_ideal():
|
|
1150
|
+
return True
|
|
1151
|
+
except AttributeError: # Not all ideals have a change_ring
|
|
1152
|
+
pass
|
|
1153
|
+
return C.has_coerce_map_from(R)
|
|
1154
|
+
|
|
1155
|
+
def __richcmp__(self, other, op):
|
|
1156
|
+
r"""
|
|
1157
|
+
Only quotients by the *same* ring and same ideal (with the same
|
|
1158
|
+
generators!!) are considered equal.
|
|
1159
|
+
|
|
1160
|
+
EXAMPLES::
|
|
1161
|
+
|
|
1162
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
1163
|
+
sage: S = R.quotient_ring(x^2 + y^2)
|
|
1164
|
+
sage: S == R.quotient_ring(x^2 + y^2)
|
|
1165
|
+
True
|
|
1166
|
+
|
|
1167
|
+
The ideals `(x^2 + y^2)` and `(-x^2-y^2)` are
|
|
1168
|
+
equal, but since the generators are different, the corresponding
|
|
1169
|
+
quotient rings are not equal::
|
|
1170
|
+
|
|
1171
|
+
sage: R.ideal(x^2 + y^2) == R.ideal(-x^2 - y^2) # needs sage.libs.singular
|
|
1172
|
+
True
|
|
1173
|
+
sage: R.quotient_ring(x^2 + y^2) == R.quotient_ring(-x^2 - y^2)
|
|
1174
|
+
False
|
|
1175
|
+
"""
|
|
1176
|
+
if not isinstance(other, QuotientRing_nc):
|
|
1177
|
+
return NotImplemented
|
|
1178
|
+
return richcmp((self.cover_ring(), self.defining_ideal().gens()),
|
|
1179
|
+
(other.cover_ring(), other.defining_ideal().gens()), op)
|
|
1180
|
+
|
|
1181
|
+
def ngens(self):
|
|
1182
|
+
r"""
|
|
1183
|
+
Return the number of generators for this quotient ring.
|
|
1184
|
+
|
|
1185
|
+
.. TODO::
|
|
1186
|
+
|
|
1187
|
+
Note that ``ngens`` counts 0 as a generator. Does
|
|
1188
|
+
this make sense? That is, since 0 only generates itself and the
|
|
1189
|
+
fact that this is true for all rings, is there a way to "knock it
|
|
1190
|
+
off" of the generators list if a generator of some original ring is
|
|
1191
|
+
modded out?
|
|
1192
|
+
|
|
1193
|
+
EXAMPLES::
|
|
1194
|
+
|
|
1195
|
+
sage: R = QuotientRing(ZZ, 7*ZZ)
|
|
1196
|
+
sage: R.gens(); R.ngens()
|
|
1197
|
+
(1,)
|
|
1198
|
+
1
|
|
1199
|
+
|
|
1200
|
+
::
|
|
1201
|
+
|
|
1202
|
+
sage: # needs sage.libs.singular
|
|
1203
|
+
sage: R.<x,y> = PolynomialRing(QQ,2)
|
|
1204
|
+
sage: S.<a,b> = QuotientRing(R, R.ideal(1 + y^2))
|
|
1205
|
+
sage: T.<c,d> = QuotientRing(S, S.ideal(a))
|
|
1206
|
+
sage: T
|
|
1207
|
+
Quotient of Multivariate Polynomial Ring in x, y over Rational Field
|
|
1208
|
+
by the ideal (x, y^2 + 1)
|
|
1209
|
+
sage: R.gens(); S.gens(); T.gens()
|
|
1210
|
+
(x, y)
|
|
1211
|
+
(a, b)
|
|
1212
|
+
(0, d)
|
|
1213
|
+
sage: R.ngens(); S.ngens(); T.ngens()
|
|
1214
|
+
2
|
|
1215
|
+
2
|
|
1216
|
+
2
|
|
1217
|
+
"""
|
|
1218
|
+
return self.cover_ring().ngens()
|
|
1219
|
+
|
|
1220
|
+
def gen(self, i=0):
|
|
1221
|
+
r"""
|
|
1222
|
+
Return the `i`-th generator for this quotient ring.
|
|
1223
|
+
|
|
1224
|
+
EXAMPLES::
|
|
1225
|
+
|
|
1226
|
+
sage: R = QuotientRing(ZZ, 7*ZZ)
|
|
1227
|
+
sage: R.gen(0)
|
|
1228
|
+
1
|
|
1229
|
+
|
|
1230
|
+
::
|
|
1231
|
+
|
|
1232
|
+
sage: # needs sage.libs.singular
|
|
1233
|
+
sage: R.<x,y> = PolynomialRing(QQ,2)
|
|
1234
|
+
sage: S.<a,b> = QuotientRing(R, R.ideal(1 + y^2))
|
|
1235
|
+
sage: T.<c,d> = QuotientRing(S, S.ideal(a))
|
|
1236
|
+
sage: T
|
|
1237
|
+
Quotient of Multivariate Polynomial Ring in x, y over Rational Field
|
|
1238
|
+
by the ideal (x, y^2 + 1)
|
|
1239
|
+
sage: R.gen(0); R.gen(1)
|
|
1240
|
+
x
|
|
1241
|
+
y
|
|
1242
|
+
sage: S.gen(0); S.gen(1)
|
|
1243
|
+
a
|
|
1244
|
+
b
|
|
1245
|
+
sage: T.gen(0); T.gen(1)
|
|
1246
|
+
0
|
|
1247
|
+
d
|
|
1248
|
+
"""
|
|
1249
|
+
return self(self.__R.gen(i))
|
|
1250
|
+
|
|
1251
|
+
def gens(self) -> tuple:
|
|
1252
|
+
r"""
|
|
1253
|
+
Return a tuple containing generators of ``self``.
|
|
1254
|
+
|
|
1255
|
+
EXAMPLES::
|
|
1256
|
+
|
|
1257
|
+
sage: # needs sage.libs.singular
|
|
1258
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
1259
|
+
sage: S = R.quotient_ring(x^2 + y^2)
|
|
1260
|
+
sage: S.gens()
|
|
1261
|
+
(xbar, ybar)
|
|
1262
|
+
"""
|
|
1263
|
+
return tuple(self(self.__R.gen(i))
|
|
1264
|
+
for i in range(self.cover_ring().ngens()))
|
|
1265
|
+
|
|
1266
|
+
def _singular_(self, singular=None):
|
|
1267
|
+
"""
|
|
1268
|
+
Return the Singular quotient ring of ``self`` if the base ring is
|
|
1269
|
+
coercible to Singular.
|
|
1270
|
+
|
|
1271
|
+
If a valid Singular representation is found it is used otherwise a
|
|
1272
|
+
new 'qring' is created.
|
|
1273
|
+
|
|
1274
|
+
INPUT:
|
|
1275
|
+
|
|
1276
|
+
- ``singular`` -- Singular instance (default: the
|
|
1277
|
+
default Singular instance)
|
|
1278
|
+
|
|
1279
|
+
.. NOTE::
|
|
1280
|
+
|
|
1281
|
+
This method also sets the current ring in Singular to ``self``
|
|
1282
|
+
|
|
1283
|
+
EXAMPLES::
|
|
1284
|
+
|
|
1285
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
1286
|
+
sage: S = R.quotient_ring(x^2 + y^2)
|
|
1287
|
+
sage: S._singular_() # needs sage.libs.singular
|
|
1288
|
+
polynomial ring, over a field, global ordering
|
|
1289
|
+
// coefficients: QQ...
|
|
1290
|
+
// number of vars : 2
|
|
1291
|
+
// block 1 : ordering dp
|
|
1292
|
+
// : names x y
|
|
1293
|
+
// block 2 : ordering C
|
|
1294
|
+
// quotient ring from ideal
|
|
1295
|
+
_[1]=x2+y2
|
|
1296
|
+
"""
|
|
1297
|
+
if singular is None:
|
|
1298
|
+
from sage.interfaces.singular import singular
|
|
1299
|
+
|
|
1300
|
+
try:
|
|
1301
|
+
Q = self.__singular
|
|
1302
|
+
if Q.parent() is not singular:
|
|
1303
|
+
raise ValueError
|
|
1304
|
+
Q._check_valid()
|
|
1305
|
+
return Q
|
|
1306
|
+
except (AttributeError, ValueError):
|
|
1307
|
+
self.__singular = self._singular_init_(singular)
|
|
1308
|
+
return self.__singular
|
|
1309
|
+
|
|
1310
|
+
def _singular_init_(self, singular=None):
|
|
1311
|
+
"""
|
|
1312
|
+
Return a newly created Singular quotient ring matching ``self`` if
|
|
1313
|
+
the base ring is coercible to Singular.
|
|
1314
|
+
|
|
1315
|
+
See ``_singular_``
|
|
1316
|
+
|
|
1317
|
+
EXAMPLES::
|
|
1318
|
+
|
|
1319
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
1320
|
+
sage: S = R.quotient_ring(x^2 + y^2)
|
|
1321
|
+
sage: T = S._singular_init_() # needs sage.libs.singular
|
|
1322
|
+
sage: parent(S)
|
|
1323
|
+
<class 'sage.rings.quotient_ring.QuotientRing_generic_with_category'>
|
|
1324
|
+
sage: parent(T) # needs sage.libs.singular
|
|
1325
|
+
Singular
|
|
1326
|
+
"""
|
|
1327
|
+
if singular is None:
|
|
1328
|
+
from sage.interfaces.singular import singular
|
|
1329
|
+
self.__R._singular_().set_ring()
|
|
1330
|
+
self.__singular = singular("%s" % self.__I._singular_().name(), "qring")
|
|
1331
|
+
return self.__singular
|
|
1332
|
+
|
|
1333
|
+
def _magma_init_(self, magma):
|
|
1334
|
+
r"""
|
|
1335
|
+
Return string that evaluates to Magma version of this quotient
|
|
1336
|
+
ring. This is called implicitly when doing conversions to Magma.
|
|
1337
|
+
|
|
1338
|
+
INPUT:
|
|
1339
|
+
|
|
1340
|
+
- ``magma`` -- a Magma instance
|
|
1341
|
+
|
|
1342
|
+
EXAMPLES::
|
|
1343
|
+
|
|
1344
|
+
sage: P.<x,y> = PolynomialRing(GF(2))
|
|
1345
|
+
sage: Q = P.quotient(sage.rings.ideal.FieldIdeal(P))
|
|
1346
|
+
sage: magma(Q) # indirect doctest # optional - magma
|
|
1347
|
+
Affine Algebra of rank 2 over GF(2)
|
|
1348
|
+
Graded Reverse Lexicographical Order
|
|
1349
|
+
Variables: x, y
|
|
1350
|
+
Quotient relations:
|
|
1351
|
+
[
|
|
1352
|
+
x^2 + x,
|
|
1353
|
+
y^2 + y
|
|
1354
|
+
]
|
|
1355
|
+
"""
|
|
1356
|
+
R = magma(self.__R)
|
|
1357
|
+
I = magma(self.__I.gens())
|
|
1358
|
+
return "quo<%s|%s>" % (R.name(), I._ref())
|
|
1359
|
+
|
|
1360
|
+
def term_order(self):
|
|
1361
|
+
"""
|
|
1362
|
+
Return the term order of this ring.
|
|
1363
|
+
|
|
1364
|
+
EXAMPLES::
|
|
1365
|
+
|
|
1366
|
+
sage: P.<a,b,c> = PolynomialRing(QQ)
|
|
1367
|
+
sage: I = Ideal([a^2 - a, b^2 - b, c^2 - c])
|
|
1368
|
+
sage: Q = P.quotient(I)
|
|
1369
|
+
sage: Q.term_order()
|
|
1370
|
+
Degree reverse lexicographic term order
|
|
1371
|
+
"""
|
|
1372
|
+
return self.__R.term_order()
|
|
1373
|
+
|
|
1374
|
+
def random_element(self):
|
|
1375
|
+
r"""
|
|
1376
|
+
Return a random element of this quotient ring obtained by
|
|
1377
|
+
sampling a random element of the cover ring and reducing
|
|
1378
|
+
it modulo the defining ideal.
|
|
1379
|
+
|
|
1380
|
+
EXAMPLES::
|
|
1381
|
+
|
|
1382
|
+
sage: R.<x,y> = QQ[]
|
|
1383
|
+
sage: S = R.quotient([x^3, y^2])
|
|
1384
|
+
sage: S.random_element() # random # needs sage.libs.singular
|
|
1385
|
+
-8/5*xbar^2 + 3/2*xbar*ybar + 2*xbar - 4/23
|
|
1386
|
+
|
|
1387
|
+
TESTS:
|
|
1388
|
+
|
|
1389
|
+
Make sure we are not just getting images of integers in this
|
|
1390
|
+
ring (which would be the case if the default implementation
|
|
1391
|
+
of this method was inherited from generic rings)::
|
|
1392
|
+
|
|
1393
|
+
sage: any(S.random_element() not in ZZ for _ in range(999)) # needs sage.libs.singular
|
|
1394
|
+
True
|
|
1395
|
+
"""
|
|
1396
|
+
return self.retract(self.cover_ring().random_element())
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
class QuotientRing_generic(QuotientRing_nc, ring.CommutativeRing):
|
|
1400
|
+
r"""
|
|
1401
|
+
Create a quotient ring of a *commutative* ring `R` by the ideal `I`.
|
|
1402
|
+
|
|
1403
|
+
EXAMPLES::
|
|
1404
|
+
|
|
1405
|
+
sage: R.<x> = PolynomialRing(ZZ)
|
|
1406
|
+
sage: I = R.ideal([4 + 3*x + x^2, 1 + x^2])
|
|
1407
|
+
sage: S = R.quotient_ring(I); S
|
|
1408
|
+
Quotient of Univariate Polynomial Ring in x over Integer Ring
|
|
1409
|
+
by the ideal (x^2 + 3*x + 4, x^2 + 1)
|
|
1410
|
+
"""
|
|
1411
|
+
|
|
1412
|
+
def __init__(self, R, I, names, category=None):
|
|
1413
|
+
"""
|
|
1414
|
+
Initialize ``self``.
|
|
1415
|
+
|
|
1416
|
+
INPUT:
|
|
1417
|
+
|
|
1418
|
+
- ``R`` -- a ring that is a :class:`~sage.rings.ring.CommutativeRing`
|
|
1419
|
+
|
|
1420
|
+
- ``I`` -- an ideal of `R`
|
|
1421
|
+
|
|
1422
|
+
- ``names`` -- list of generator names
|
|
1423
|
+
|
|
1424
|
+
TESTS::
|
|
1425
|
+
|
|
1426
|
+
sage: ZZ.quo(2) in Rings().Commutative() # indirect doctest
|
|
1427
|
+
True
|
|
1428
|
+
"""
|
|
1429
|
+
if R not in _CommRings:
|
|
1430
|
+
raise TypeError("This class is for quotients of commutative rings only.\n For non-commutative rings, use <sage.rings.quotient_ring.QuotientRing_nc>")
|
|
1431
|
+
if not self._is_category_initialized():
|
|
1432
|
+
category = check_default_category(_CommutativeRingsQuotients,
|
|
1433
|
+
category)
|
|
1434
|
+
QuotientRing_nc.__init__(self, R, I, names, category=category)
|
|
1435
|
+
|
|
1436
|
+
def _macaulay2_init_(self, macaulay2=None):
|
|
1437
|
+
r"""
|
|
1438
|
+
EXAMPLES:
|
|
1439
|
+
|
|
1440
|
+
Quotients of multivariate polynomial rings over `\QQ`, `\ZZ` and
|
|
1441
|
+
a finite field::
|
|
1442
|
+
|
|
1443
|
+
sage: R.<x,y> = PolynomialRing(QQ)
|
|
1444
|
+
sage: I = R.ideal([x^2 - y])
|
|
1445
|
+
sage: Q = R.quotient_ring(I); Q
|
|
1446
|
+
Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 - y)
|
|
1447
|
+
sage: Q._macaulay2_init_() # optional - macaulay2
|
|
1448
|
+
QQ[x...y]
|
|
1449
|
+
--------
|
|
1450
|
+
2
|
|
1451
|
+
x - y
|
|
1452
|
+
|
|
1453
|
+
sage: R.<x,y,z,w> = PolynomialRing(ZZ, 4)
|
|
1454
|
+
sage: I = R.ideal([x*y - z^2, y^2 - w^2])
|
|
1455
|
+
sage: Q = R.quotient(I); Q
|
|
1456
|
+
Quotient of Multivariate Polynomial Ring in x, y, z, w over Integer Ring by the ideal (x*y - z^2, y^2 - w^2)
|
|
1457
|
+
sage: Q._macaulay2_init_() # optional - macaulay2
|
|
1458
|
+
ZZ[x...z, w]
|
|
1459
|
+
-------------------
|
|
1460
|
+
2 2 2
|
|
1461
|
+
(x*y - z , y - w )
|
|
1462
|
+
|
|
1463
|
+
sage: R.<x,y> = PolynomialRing(GF(101), 2)
|
|
1464
|
+
sage: I = R.ideal([x^2 + x, y^2 + y])
|
|
1465
|
+
sage: Q = R.quotient_ring(I); Q
|
|
1466
|
+
Quotient of Multivariate Polynomial Ring in x, y over
|
|
1467
|
+
Finite Field of size 101 by the ideal (x^2 + x, y^2 + y)
|
|
1468
|
+
sage: Q._macaulay2_init_() # optional - macaulay2
|
|
1469
|
+
ZZ
|
|
1470
|
+
---[x...y]
|
|
1471
|
+
101
|
|
1472
|
+
----------------
|
|
1473
|
+
2 2
|
|
1474
|
+
(x + x, y + y)
|
|
1475
|
+
|
|
1476
|
+
Quotients of univariate polynomial rings::
|
|
1477
|
+
|
|
1478
|
+
sage: R.<x> = PolynomialRing(ZZ)
|
|
1479
|
+
sage: I = R.ideal([4 + 3*x + x^2, 1 + x^2])
|
|
1480
|
+
sage: Q = R.quotient_ring(I); Q
|
|
1481
|
+
Quotient of Univariate Polynomial Ring in x over Integer Ring by the ideal (x^2 + 3*x + 4, x^2 + 1)
|
|
1482
|
+
sage: Q._macaulay2_init_() # optional - macaulay2
|
|
1483
|
+
ZZ[x]
|
|
1484
|
+
---------------------
|
|
1485
|
+
2 2
|
|
1486
|
+
(x + 3x + 4, x + 1)
|
|
1487
|
+
"""
|
|
1488
|
+
if macaulay2 is None:
|
|
1489
|
+
from sage.interfaces.macaulay2 import macaulay2 as m2_default
|
|
1490
|
+
macaulay2 = m2_default
|
|
1491
|
+
I = self.defining_ideal()._macaulay2_(macaulay2)
|
|
1492
|
+
return I.ring()._operator('/', I)
|
|
1493
|
+
|
|
1494
|
+
def _ideal_class_(self, n=0):
|
|
1495
|
+
r"""
|
|
1496
|
+
Use a specialized class for quotient ring ideals.
|
|
1497
|
+
|
|
1498
|
+
INPUT:
|
|
1499
|
+
|
|
1500
|
+
- ``n`` -- integer (default: ``0``); the number of generators
|
|
1501
|
+
|
|
1502
|
+
EXAMPLES::
|
|
1503
|
+
|
|
1504
|
+
sage: type(Zmod(14).ideal(2))
|
|
1505
|
+
<class 'sage.rings.quotient_ring.QuotientRingIdeal_principal'>
|
|
1506
|
+
sage: type(Zmod(14).ideal([7]))
|
|
1507
|
+
<class 'sage.rings.quotient_ring.QuotientRingIdeal_principal'>
|
|
1508
|
+
sage: type(Zmod(14).ideal([2,7]))
|
|
1509
|
+
<class 'sage.rings.quotient_ring.QuotientRingIdeal_generic'>
|
|
1510
|
+
"""
|
|
1511
|
+
if n == 1:
|
|
1512
|
+
return QuotientRingIdeal_principal
|
|
1513
|
+
return QuotientRingIdeal_generic
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
class QuotientRingIdeal_generic(ideal.Ideal_generic):
|
|
1517
|
+
r"""
|
|
1518
|
+
Specialized class for quotient-ring ideals.
|
|
1519
|
+
|
|
1520
|
+
EXAMPLES::
|
|
1521
|
+
|
|
1522
|
+
sage: Zmod(9).ideal([-6,9])
|
|
1523
|
+
Ideal (3, 0) of Ring of integers modulo 9
|
|
1524
|
+
"""
|
|
1525
|
+
|
|
1526
|
+
def _lift(self):
|
|
1527
|
+
"""
|
|
1528
|
+
Return an ideal of the cover ring that corresponds to this ideal.
|
|
1529
|
+
|
|
1530
|
+
EXAMPLES::
|
|
1531
|
+
|
|
1532
|
+
sage: Zmod(15).ideal(6)._lift()
|
|
1533
|
+
Principal ideal (3) of Integer Ring
|
|
1534
|
+
sage: ZZ.ideal(Zmod(15).ideal(6)) # different from the above!
|
|
1535
|
+
Principal ideal (6) of Integer Ring
|
|
1536
|
+
|
|
1537
|
+
sage: # needs sage.libs.singular
|
|
1538
|
+
sage: R.<x,y> = QQ[]
|
|
1539
|
+
sage: S = R.quotient(x)
|
|
1540
|
+
sage: S.ideal(y)._lift()
|
|
1541
|
+
Ideal (x, y) of Multivariate Polynomial Ring in x, y over Rational Field
|
|
1542
|
+
"""
|
|
1543
|
+
R = self.ring()
|
|
1544
|
+
return R.defining_ideal() + R.cover_ring().ideal([g.lift() for g in self.gens()])
|
|
1545
|
+
|
|
1546
|
+
def _contains_(self, other):
|
|
1547
|
+
r"""
|
|
1548
|
+
Check whether this ideal contains the given element.
|
|
1549
|
+
|
|
1550
|
+
EXAMPLES::
|
|
1551
|
+
|
|
1552
|
+
sage: 1 in Zmod(15).ideal(2)
|
|
1553
|
+
True
|
|
1554
|
+
sage: 1 in Zmod(15).ideal(3)
|
|
1555
|
+
False
|
|
1556
|
+
sage: 1 in Zmod(15).ideal([5,10])
|
|
1557
|
+
False
|
|
1558
|
+
sage: 6 in Zmod(15).ideal([9])
|
|
1559
|
+
True
|
|
1560
|
+
sage: 1 in Zmod(15).ideal([3,5])
|
|
1561
|
+
True
|
|
1562
|
+
|
|
1563
|
+
::
|
|
1564
|
+
|
|
1565
|
+
sage: # needs sage.libs.pari
|
|
1566
|
+
sage: R.<T> = QQ[]
|
|
1567
|
+
sage: S.<t> = R.quotient(T^3 - 1)
|
|
1568
|
+
sage: 1 in S.ideal(t^2 - 1)
|
|
1569
|
+
False
|
|
1570
|
+
sage: 7 in S.ideal(t^2 + 1)
|
|
1571
|
+
True
|
|
1572
|
+
sage: 5-5*t in S.ideal(t^2 - 1)
|
|
1573
|
+
True
|
|
1574
|
+
"""
|
|
1575
|
+
assert other in self.ring()
|
|
1576
|
+
return other.lift() in self._lift()
|
|
1577
|
+
|
|
1578
|
+
def radical(self):
|
|
1579
|
+
"""
|
|
1580
|
+
Return the radical of this ideal.
|
|
1581
|
+
|
|
1582
|
+
EXAMPLES::
|
|
1583
|
+
|
|
1584
|
+
sage: Zmod(16).ideal(4).radical()
|
|
1585
|
+
Principal ideal (2) of Ring of integers modulo 16
|
|
1586
|
+
"""
|
|
1587
|
+
return self.ring().ideal(self._lift().radical())
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
class QuotientRingIdeal_principal(ideal.Ideal_principal, QuotientRingIdeal_generic):
|
|
1591
|
+
r"""
|
|
1592
|
+
Specialized class for principal quotient-ring ideals.
|
|
1593
|
+
|
|
1594
|
+
EXAMPLES::
|
|
1595
|
+
|
|
1596
|
+
sage: Zmod(9).ideal(-33)
|
|
1597
|
+
Principal ideal (3) of Ring of integers modulo 9
|
|
1598
|
+
"""
|