passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_combinat/__init__.py +3 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
- passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
- passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
- passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
- sage/algebras/affine_nil_temperley_lieb.py +263 -0
- sage/algebras/all.py +24 -0
- sage/algebras/all__sagemath_combinat.py +35 -0
- sage/algebras/askey_wilson.py +935 -0
- sage/algebras/associated_graded.py +345 -0
- sage/algebras/cellular_basis.py +350 -0
- sage/algebras/cluster_algebra.py +2766 -0
- sage/algebras/down_up_algebra.py +860 -0
- sage/algebras/free_algebra.py +1698 -0
- sage/algebras/free_algebra_element.py +345 -0
- sage/algebras/free_algebra_quotient.py +405 -0
- sage/algebras/free_algebra_quotient_element.py +295 -0
- sage/algebras/free_zinbiel_algebra.py +885 -0
- sage/algebras/hall_algebra.py +783 -0
- sage/algebras/hecke_algebras/all.py +4 -0
- sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
- sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
- sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
- sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
- sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
- sage/algebras/iwahori_hecke_algebra.py +3095 -0
- sage/algebras/jordan_algebra.py +1773 -0
- sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
- sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
- sage/algebras/lie_conformal_algebras/all.py +18 -0
- sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
- sage/algebras/lie_conformal_algebras/examples.py +43 -0
- sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
- sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
- sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
- sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
- sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
- sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
- sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
- sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
- sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
- sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
- sage/algebras/nil_coxeter_algebra.py +191 -0
- sage/algebras/q_commuting_polynomials.py +673 -0
- sage/algebras/q_system.py +608 -0
- sage/algebras/quantum_clifford.py +959 -0
- sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
- sage/algebras/quantum_groups/all.py +9 -0
- sage/algebras/quantum_groups/fock_space.py +2219 -0
- sage/algebras/quantum_groups/q_numbers.py +207 -0
- sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
- sage/algebras/quantum_groups/representations.py +591 -0
- sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
- sage/algebras/quantum_oscillator.py +623 -0
- sage/algebras/quaternion_algebra.py +20 -0
- sage/algebras/quaternion_algebra_element.py +55 -0
- sage/algebras/rational_cherednik_algebra.py +525 -0
- sage/algebras/schur_algebra.py +670 -0
- sage/algebras/shuffle_algebra.py +1011 -0
- sage/algebras/splitting_algebra.py +779 -0
- sage/algebras/tensor_algebra.py +709 -0
- sage/algebras/yangian.py +1082 -0
- sage/algebras/yokonuma_hecke_algebra.py +1018 -0
- sage/all__sagemath_combinat.py +35 -0
- sage/combinat/SJT.py +255 -0
- sage/combinat/affine_permutation.py +2405 -0
- sage/combinat/algebraic_combinatorics.py +55 -0
- sage/combinat/all.py +53 -0
- sage/combinat/all__sagemath_combinat.py +195 -0
- sage/combinat/alternating_sign_matrix.py +2063 -0
- sage/combinat/baxter_permutations.py +346 -0
- sage/combinat/bijectionist.py +3220 -0
- sage/combinat/binary_recurrence_sequences.py +1180 -0
- sage/combinat/blob_algebra.py +685 -0
- sage/combinat/catalog_partitions.py +27 -0
- sage/combinat/chas/all.py +23 -0
- sage/combinat/chas/fsym.py +1180 -0
- sage/combinat/chas/wqsym.py +2601 -0
- sage/combinat/cluster_complex.py +326 -0
- sage/combinat/colored_permutations.py +2039 -0
- sage/combinat/colored_permutations_representations.py +964 -0
- sage/combinat/composition_signed.py +142 -0
- sage/combinat/composition_tableau.py +855 -0
- sage/combinat/constellation.py +1729 -0
- sage/combinat/core.py +751 -0
- sage/combinat/counting.py +12 -0
- sage/combinat/crystals/affine.py +742 -0
- sage/combinat/crystals/affine_factorization.py +518 -0
- sage/combinat/crystals/affinization.py +331 -0
- sage/combinat/crystals/alcove_path.py +2013 -0
- sage/combinat/crystals/all.py +22 -0
- sage/combinat/crystals/bkk_crystals.py +141 -0
- sage/combinat/crystals/catalog.py +115 -0
- sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
- sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
- sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
- sage/combinat/crystals/crystals.py +257 -0
- sage/combinat/crystals/direct_sum.py +260 -0
- sage/combinat/crystals/elementary_crystals.py +1251 -0
- sage/combinat/crystals/fast_crystals.py +441 -0
- sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
- sage/combinat/crystals/generalized_young_walls.py +1076 -0
- sage/combinat/crystals/highest_weight_crystals.py +436 -0
- sage/combinat/crystals/induced_structure.py +695 -0
- sage/combinat/crystals/infinity_crystals.py +730 -0
- sage/combinat/crystals/kac_modules.py +863 -0
- sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
- sage/combinat/crystals/kyoto_path_model.py +497 -0
- sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/letters.pxd +79 -0
- sage/combinat/crystals/letters.pyx +3056 -0
- sage/combinat/crystals/littelmann_path.py +1518 -0
- sage/combinat/crystals/monomial_crystals.py +1262 -0
- sage/combinat/crystals/multisegments.py +462 -0
- sage/combinat/crystals/mv_polytopes.py +467 -0
- sage/combinat/crystals/pbw_crystal.py +511 -0
- sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/pbw_datum.pxd +4 -0
- sage/combinat/crystals/pbw_datum.pyx +487 -0
- sage/combinat/crystals/polyhedral_realization.py +372 -0
- sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/spins.pxd +21 -0
- sage/combinat/crystals/spins.pyx +756 -0
- sage/combinat/crystals/star_crystal.py +290 -0
- sage/combinat/crystals/subcrystal.py +464 -0
- sage/combinat/crystals/tensor_product.py +1177 -0
- sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/tensor_product_element.pxd +35 -0
- sage/combinat/crystals/tensor_product_element.pyx +1870 -0
- sage/combinat/crystals/virtual_crystal.py +420 -0
- sage/combinat/cyclic_sieving_phenomenon.py +204 -0
- sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/degree_sequences.pyx +588 -0
- sage/combinat/derangements.py +527 -0
- sage/combinat/descent_algebra.py +1008 -0
- sage/combinat/diagram.py +1551 -0
- sage/combinat/diagram_algebras.py +5886 -0
- sage/combinat/dyck_word.py +4349 -0
- sage/combinat/e_one_star.py +1623 -0
- sage/combinat/enumerated_sets.py +123 -0
- sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/fast_vector_partitions.pyx +346 -0
- sage/combinat/fqsym.py +1977 -0
- sage/combinat/free_dendriform_algebra.py +954 -0
- sage/combinat/free_prelie_algebra.py +1141 -0
- sage/combinat/fully_commutative_elements.py +1077 -0
- sage/combinat/fully_packed_loop.py +1523 -0
- sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
- sage/combinat/gray_codes.py +311 -0
- sage/combinat/grossman_larson_algebras.py +667 -0
- sage/combinat/growth.py +4352 -0
- sage/combinat/hall_polynomial.py +188 -0
- sage/combinat/hillman_grassl.py +866 -0
- sage/combinat/integer_matrices.py +329 -0
- sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
- sage/combinat/k_tableau.py +4564 -0
- sage/combinat/kazhdan_lusztig.py +215 -0
- sage/combinat/key_polynomial.py +885 -0
- sage/combinat/knutson_tao_puzzles.py +2286 -0
- sage/combinat/lr_tableau.py +311 -0
- sage/combinat/matrices/all.py +24 -0
- sage/combinat/matrices/hadamard_matrix.py +3790 -0
- sage/combinat/matrices/latin.py +2912 -0
- sage/combinat/misc.py +401 -0
- sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
- sage/combinat/ncsf_qsym/all.py +21 -0
- sage/combinat/ncsf_qsym/combinatorics.py +317 -0
- sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
- sage/combinat/ncsf_qsym/ncsf.py +5637 -0
- sage/combinat/ncsf_qsym/qsym.py +4053 -0
- sage/combinat/ncsf_qsym/tutorial.py +447 -0
- sage/combinat/ncsym/all.py +21 -0
- sage/combinat/ncsym/bases.py +855 -0
- sage/combinat/ncsym/dual.py +593 -0
- sage/combinat/ncsym/ncsym.py +2076 -0
- sage/combinat/necklace.py +551 -0
- sage/combinat/non_decreasing_parking_function.py +634 -0
- sage/combinat/nu_dyck_word.py +1474 -0
- sage/combinat/output.py +861 -0
- sage/combinat/parallelogram_polyomino.py +4326 -0
- sage/combinat/parking_functions.py +1602 -0
- sage/combinat/partition_algebra.py +1998 -0
- sage/combinat/partition_kleshchev.py +1982 -0
- sage/combinat/partition_shifting_algebras.py +584 -0
- sage/combinat/partition_tuple.py +3114 -0
- sage/combinat/path_tableaux/all.py +13 -0
- sage/combinat/path_tableaux/catalog.py +29 -0
- sage/combinat/path_tableaux/dyck_path.py +380 -0
- sage/combinat/path_tableaux/frieze.py +476 -0
- sage/combinat/path_tableaux/path_tableau.py +728 -0
- sage/combinat/path_tableaux/semistandard.py +510 -0
- sage/combinat/perfect_matching.py +779 -0
- sage/combinat/plane_partition.py +3300 -0
- sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/q_bernoulli.pyx +128 -0
- sage/combinat/quickref.py +81 -0
- sage/combinat/recognizable_series.py +2051 -0
- sage/combinat/regular_sequence.py +4316 -0
- sage/combinat/regular_sequence_bounded.py +543 -0
- sage/combinat/restricted_growth.py +81 -0
- sage/combinat/ribbon.py +20 -0
- sage/combinat/ribbon_shaped_tableau.py +489 -0
- sage/combinat/ribbon_tableau.py +1180 -0
- sage/combinat/rigged_configurations/all.py +46 -0
- sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
- sage/combinat/rigged_configurations/bij_infinity.py +370 -0
- sage/combinat/rigged_configurations/bij_type_A.py +163 -0
- sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
- sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
- sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
- sage/combinat/rigged_configurations/bij_type_B.py +900 -0
- sage/combinat/rigged_configurations/bij_type_C.py +267 -0
- sage/combinat/rigged_configurations/bij_type_D.py +771 -0
- sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
- sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
- sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
- sage/combinat/rigged_configurations/bijection.py +143 -0
- sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
- sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
- sage/combinat/rigged_configurations/rc_crystal.py +461 -0
- sage/combinat/rigged_configurations/rc_infinity.py +540 -0
- sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
- sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
- sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
- sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
- sage/combinat/rsk.py +3438 -0
- sage/combinat/schubert_polynomial.py +508 -0
- sage/combinat/set_partition.py +3318 -0
- sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/set_partition_iterator.pyx +136 -0
- sage/combinat/set_partition_ordered.py +1590 -0
- sage/combinat/sf/abreu_nigro.py +346 -0
- sage/combinat/sf/all.py +52 -0
- sage/combinat/sf/character.py +576 -0
- sage/combinat/sf/classical.py +319 -0
- sage/combinat/sf/dual.py +996 -0
- sage/combinat/sf/elementary.py +549 -0
- sage/combinat/sf/hall_littlewood.py +1028 -0
- sage/combinat/sf/hecke.py +336 -0
- sage/combinat/sf/homogeneous.py +464 -0
- sage/combinat/sf/jack.py +1428 -0
- sage/combinat/sf/k_dual.py +1458 -0
- sage/combinat/sf/kfpoly.py +447 -0
- sage/combinat/sf/llt.py +789 -0
- sage/combinat/sf/macdonald.py +2019 -0
- sage/combinat/sf/monomial.py +525 -0
- sage/combinat/sf/multiplicative.py +113 -0
- sage/combinat/sf/new_kschur.py +1786 -0
- sage/combinat/sf/ns_macdonald.py +964 -0
- sage/combinat/sf/orthogonal.py +246 -0
- sage/combinat/sf/orthotriang.py +355 -0
- sage/combinat/sf/powersum.py +963 -0
- sage/combinat/sf/schur.py +880 -0
- sage/combinat/sf/sf.py +1653 -0
- sage/combinat/sf/sfa.py +7053 -0
- sage/combinat/sf/symplectic.py +253 -0
- sage/combinat/sf/witt.py +721 -0
- sage/combinat/shifted_primed_tableau.py +2735 -0
- sage/combinat/shuffle.py +830 -0
- sage/combinat/sidon_sets.py +146 -0
- sage/combinat/similarity_class_type.py +1721 -0
- sage/combinat/sine_gordon.py +618 -0
- sage/combinat/six_vertex_model.py +784 -0
- sage/combinat/skew_partition.py +2053 -0
- sage/combinat/skew_tableau.py +2989 -0
- sage/combinat/sloane_functions.py +8935 -0
- sage/combinat/specht_module.py +1403 -0
- sage/combinat/species/all.py +48 -0
- sage/combinat/species/characteristic_species.py +321 -0
- sage/combinat/species/composition_species.py +273 -0
- sage/combinat/species/cycle_species.py +284 -0
- sage/combinat/species/empty_species.py +155 -0
- sage/combinat/species/functorial_composition_species.py +148 -0
- sage/combinat/species/generating_series.py +673 -0
- sage/combinat/species/library.py +148 -0
- sage/combinat/species/linear_order_species.py +169 -0
- sage/combinat/species/misc.py +83 -0
- sage/combinat/species/partition_species.py +290 -0
- sage/combinat/species/permutation_species.py +268 -0
- sage/combinat/species/product_species.py +423 -0
- sage/combinat/species/recursive_species.py +476 -0
- sage/combinat/species/set_species.py +192 -0
- sage/combinat/species/species.py +820 -0
- sage/combinat/species/structure.py +539 -0
- sage/combinat/species/subset_species.py +243 -0
- sage/combinat/species/sum_species.py +225 -0
- sage/combinat/subword.py +564 -0
- sage/combinat/subword_complex.py +2122 -0
- sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/subword_complex_c.pyx +119 -0
- sage/combinat/super_tableau.py +821 -0
- sage/combinat/superpartition.py +1154 -0
- sage/combinat/symmetric_group_algebra.py +3774 -0
- sage/combinat/symmetric_group_representations.py +1830 -0
- sage/combinat/t_sequences.py +877 -0
- sage/combinat/tableau.py +9506 -0
- sage/combinat/tableau_residues.py +860 -0
- sage/combinat/tableau_tuple.py +5353 -0
- sage/combinat/tiling.py +2432 -0
- sage/combinat/triangles_FHM.py +777 -0
- sage/combinat/tutorial.py +1857 -0
- sage/combinat/vector_partition.py +337 -0
- sage/combinat/words/abstract_word.py +1722 -0
- sage/combinat/words/all.py +59 -0
- sage/combinat/words/alphabet.py +268 -0
- sage/combinat/words/finite_word.py +7201 -0
- sage/combinat/words/infinite_word.py +113 -0
- sage/combinat/words/lyndon_word.py +652 -0
- sage/combinat/words/morphic.py +351 -0
- sage/combinat/words/morphism.py +3878 -0
- sage/combinat/words/paths.py +2932 -0
- sage/combinat/words/shuffle_product.py +278 -0
- sage/combinat/words/suffix_trees.py +1873 -0
- sage/combinat/words/word.py +769 -0
- sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_datatypes.pxd +4 -0
- sage/combinat/words/word_datatypes.pyx +1067 -0
- sage/combinat/words/word_generators.py +2026 -0
- sage/combinat/words/word_infinite_datatypes.py +1218 -0
- sage/combinat/words/word_options.py +99 -0
- sage/combinat/words/words.py +2396 -0
- sage/data_structures/all__sagemath_combinat.py +1 -0
- sage/databases/all__sagemath_combinat.py +13 -0
- sage/databases/findstat.py +4897 -0
- sage/databases/oeis.py +2058 -0
- sage/databases/sloane.py +393 -0
- sage/dynamics/all__sagemath_combinat.py +14 -0
- sage/dynamics/cellular_automata/all.py +7 -0
- sage/dynamics/cellular_automata/catalog.py +34 -0
- sage/dynamics/cellular_automata/elementary.py +612 -0
- sage/dynamics/cellular_automata/glca.py +477 -0
- sage/dynamics/cellular_automata/solitons.py +1463 -0
- sage/dynamics/finite_dynamical_system.py +1249 -0
- sage/dynamics/finite_dynamical_system_catalog.py +382 -0
- sage/games/all.py +7 -0
- sage/games/hexad.py +704 -0
- sage/games/quantumino.py +591 -0
- sage/games/sudoku.py +889 -0
- sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
- sage/games/sudoku_backtrack.pyx +189 -0
- sage/groups/all__sagemath_combinat.py +1 -0
- sage/groups/indexed_free_group.py +489 -0
- sage/libs/all__sagemath_combinat.py +6 -0
- sage/libs/lrcalc/__init__.py +1 -0
- sage/libs/lrcalc/lrcalc.py +525 -0
- sage/libs/symmetrica/__init__.py +7 -0
- sage/libs/symmetrica/all.py +101 -0
- sage/libs/symmetrica/kostka.pxi +168 -0
- sage/libs/symmetrica/part.pxi +193 -0
- sage/libs/symmetrica/plet.pxi +42 -0
- sage/libs/symmetrica/sab.pxi +196 -0
- sage/libs/symmetrica/sb.pxi +332 -0
- sage/libs/symmetrica/sc.pxi +192 -0
- sage/libs/symmetrica/schur.pxi +956 -0
- sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/symmetrica/symmetrica.pxi +1172 -0
- sage/libs/symmetrica/symmetrica.pyx +39 -0
- sage/monoids/all.py +13 -0
- sage/monoids/automatic_semigroup.py +1054 -0
- sage/monoids/free_abelian_monoid.py +315 -0
- sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/monoids/free_abelian_monoid_element.pxd +16 -0
- sage/monoids/free_abelian_monoid_element.pyx +397 -0
- sage/monoids/free_monoid.py +335 -0
- sage/monoids/free_monoid_element.py +431 -0
- sage/monoids/hecke_monoid.py +65 -0
- sage/monoids/string_monoid.py +817 -0
- sage/monoids/string_monoid_element.py +547 -0
- sage/monoids/string_ops.py +143 -0
- sage/monoids/trace_monoid.py +972 -0
- sage/rings/all__sagemath_combinat.py +2 -0
- sage/sat/all.py +4 -0
- sage/sat/boolean_polynomials.py +405 -0
- sage/sat/converters/__init__.py +6 -0
- sage/sat/converters/anf2cnf.py +14 -0
- sage/sat/converters/polybori.py +611 -0
- sage/sat/solvers/__init__.py +5 -0
- sage/sat/solvers/cryptominisat.py +287 -0
- sage/sat/solvers/dimacs.py +783 -0
- sage/sat/solvers/picosat.py +228 -0
- sage/sat/solvers/sat_lp.py +156 -0
- sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,1773 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Jordan Algebras
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- Travis Scrimshaw (2014-04-02): initial version
|
|
9
|
+
- Travis Scrimshaw (2023-05-09): added the 27 dimensional exceptional
|
|
10
|
+
Jordan algebra
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
#*****************************************************************************
|
|
14
|
+
# Copyright (C) 2014, 2023 Travis Scrimshaw <tscrim at ucdavis.edu>
|
|
15
|
+
#
|
|
16
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
17
|
+
# https://www.gnu.org/licenses/
|
|
18
|
+
#*****************************************************************************
|
|
19
|
+
|
|
20
|
+
from sage.structure.parent import Parent
|
|
21
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
22
|
+
from sage.structure.element import AlgebraElement
|
|
23
|
+
from sage.structure.richcmp import richcmp
|
|
24
|
+
from sage.categories.magmatic_algebras import MagmaticAlgebras
|
|
25
|
+
from sage.misc.cachefunc import cached_method
|
|
26
|
+
from sage.structure.element import Matrix
|
|
27
|
+
from sage.modules.free_module import FreeModule
|
|
28
|
+
from sage.matrix.constructor import matrix
|
|
29
|
+
from sage.sets.family import Family
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class JordanAlgebra(UniqueRepresentation, Parent):
|
|
33
|
+
r"""
|
|
34
|
+
A Jordan algebra.
|
|
35
|
+
|
|
36
|
+
A *Jordan algebra* is a magmatic algebra (over a commutative ring
|
|
37
|
+
`R`) whose multiplication satisfies the following axioms:
|
|
38
|
+
|
|
39
|
+
- `xy = yx`, and
|
|
40
|
+
- `(xy)(xx) = x(y(xx))` (the Jordan identity).
|
|
41
|
+
|
|
42
|
+
See [Ja1971]_, [Ch2012]_, and [McC1978]_, for example.
|
|
43
|
+
|
|
44
|
+
These axioms imply that a Jordan algebra is power-associative and the
|
|
45
|
+
following generalization of Jordan's identity holds [Al1947]_:
|
|
46
|
+
`(x^m y) x^n = x^m (y x^n)` for all `m, n \in \ZZ_{>0}`.
|
|
47
|
+
|
|
48
|
+
Let `A` be an associative algebra over a ring `R` in which `2` is
|
|
49
|
+
invertible. We construct a Jordan algebra `A^+` with ground set `A`
|
|
50
|
+
by defining the multiplication as
|
|
51
|
+
|
|
52
|
+
.. MATH::
|
|
53
|
+
|
|
54
|
+
x \circ y = \frac{xy + yx}{2}.
|
|
55
|
+
|
|
56
|
+
Often the multiplication is written as `x \circ y` to avoid confusion
|
|
57
|
+
with the product in the associative algebra `A`. We note that if `A` is
|
|
58
|
+
commutative then this reduces to the usual multiplication in `A`.
|
|
59
|
+
|
|
60
|
+
Jordan algebras constructed in this fashion, or their subalgebras,
|
|
61
|
+
are called *special*. All other Jordan algebras are called *exceptional*.
|
|
62
|
+
|
|
63
|
+
Jordan algebras can also be constructed from a module `M` over `R` with
|
|
64
|
+
a symmetric bilinear form `(\cdot, \cdot) : M \times M \to R`.
|
|
65
|
+
We begin with the module `M^* = R \oplus M` and define multiplication
|
|
66
|
+
in `M^*` by
|
|
67
|
+
|
|
68
|
+
.. MATH::
|
|
69
|
+
|
|
70
|
+
(\alpha + x) \circ (\beta + y) =
|
|
71
|
+
\underbrace{\alpha \beta + (x,y)}_{\in R}
|
|
72
|
+
+ \underbrace{\beta x + \alpha y}_{\in M},
|
|
73
|
+
|
|
74
|
+
where `\alpha, \beta \in R` and `x,y \in M`.
|
|
75
|
+
|
|
76
|
+
INPUT:
|
|
77
|
+
|
|
78
|
+
Can be either an associative algebra `A` or a symmetric bilinear
|
|
79
|
+
form given as a matrix (possibly followed by, or preceded by, a base
|
|
80
|
+
ring argument).
|
|
81
|
+
|
|
82
|
+
EXAMPLES:
|
|
83
|
+
|
|
84
|
+
We let the base algebra `A` be the free algebra on 3 generators::
|
|
85
|
+
|
|
86
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
87
|
+
sage: J = JordanAlgebra(F); J
|
|
88
|
+
Jordan algebra of Free Algebra on 3 generators (x, y, z) over Rational Field
|
|
89
|
+
sage: a,b,c = map(J, F.gens())
|
|
90
|
+
sage: a*b
|
|
91
|
+
1/2*x*y + 1/2*y*x
|
|
92
|
+
sage: b*a
|
|
93
|
+
1/2*x*y + 1/2*y*x
|
|
94
|
+
|
|
95
|
+
Jordan algebras are typically non-associative::
|
|
96
|
+
|
|
97
|
+
sage: (a*b)*c
|
|
98
|
+
1/4*x*y*z + 1/4*y*x*z + 1/4*z*x*y + 1/4*z*y*x
|
|
99
|
+
sage: a*(b*c)
|
|
100
|
+
1/4*x*y*z + 1/4*x*z*y + 1/4*y*z*x + 1/4*z*y*x
|
|
101
|
+
|
|
102
|
+
We check the Jordan identity::
|
|
103
|
+
|
|
104
|
+
sage: (a*b)*(a*a) == a*(b*(a*a))
|
|
105
|
+
True
|
|
106
|
+
sage: x = a + c
|
|
107
|
+
sage: y = b - 2*a
|
|
108
|
+
sage: (x*y)*(x*x) == x*(y*(x*x))
|
|
109
|
+
True
|
|
110
|
+
|
|
111
|
+
Next we construct a Jordan algebra from a symmetric bilinear form::
|
|
112
|
+
|
|
113
|
+
sage: m = matrix([[-2,3],[3,4]])
|
|
114
|
+
sage: J.<a,b,c> = JordanAlgebra(m); J
|
|
115
|
+
Jordan algebra over Integer Ring given by the symmetric bilinear form:
|
|
116
|
+
[-2 3]
|
|
117
|
+
[ 3 4]
|
|
118
|
+
sage: a
|
|
119
|
+
1 + (0, 0)
|
|
120
|
+
sage: b
|
|
121
|
+
0 + (1, 0)
|
|
122
|
+
sage: x = 3*a - 2*b + c; x
|
|
123
|
+
3 + (-2, 1)
|
|
124
|
+
|
|
125
|
+
We again show that Jordan algebras are usually non-associative::
|
|
126
|
+
|
|
127
|
+
sage: (x*b)*b
|
|
128
|
+
-6 + (7, 0)
|
|
129
|
+
sage: x*(b*b)
|
|
130
|
+
-6 + (4, -2)
|
|
131
|
+
|
|
132
|
+
We verify the Jordan identity::
|
|
133
|
+
|
|
134
|
+
sage: y = -a + 4*b - c
|
|
135
|
+
sage: (x*y)*(x*x) == x*(y*(x*x))
|
|
136
|
+
True
|
|
137
|
+
|
|
138
|
+
The base ring, while normally inferred from the matrix, can also
|
|
139
|
+
be explicitly specified::
|
|
140
|
+
|
|
141
|
+
sage: J.<a,b,c> = JordanAlgebra(m, QQ); J
|
|
142
|
+
Jordan algebra over Rational Field given by the symmetric bilinear form:
|
|
143
|
+
[-2 3]
|
|
144
|
+
[ 3 4]
|
|
145
|
+
sage: J.<a,b,c> = JordanAlgebra(QQ, m); J # either order work
|
|
146
|
+
Jordan algebra over Rational Field given by the symmetric bilinear form:
|
|
147
|
+
[-2 3]
|
|
148
|
+
[ 3 4]
|
|
149
|
+
|
|
150
|
+
REFERENCES:
|
|
151
|
+
|
|
152
|
+
- :wikipedia:`Jordan_algebra`
|
|
153
|
+
- [Ja1971]_
|
|
154
|
+
- [Ch2012]_
|
|
155
|
+
- [McC1978]_
|
|
156
|
+
- [Al1947]_
|
|
157
|
+
"""
|
|
158
|
+
@staticmethod
|
|
159
|
+
def __classcall_private__(self, arg0, arg1=None, names=None):
|
|
160
|
+
"""
|
|
161
|
+
Choose the correct parent based upon input.
|
|
162
|
+
|
|
163
|
+
TESTS:
|
|
164
|
+
|
|
165
|
+
We check arguments with passing in an associative algebra::
|
|
166
|
+
|
|
167
|
+
sage: cat = Algebras(QQ).WithBasis().FiniteDimensional()
|
|
168
|
+
sage: C = CombinatorialFreeModule(QQ, ['x','y','z'], category=cat)
|
|
169
|
+
sage: J1 = JordanAlgebra(C, names=['a','b','c'])
|
|
170
|
+
sage: J2.<a,b,c> = JordanAlgebra(C)
|
|
171
|
+
sage: J1 is J2
|
|
172
|
+
True
|
|
173
|
+
|
|
174
|
+
We check with passing in a symmetric bilinear form::
|
|
175
|
+
|
|
176
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
177
|
+
sage: J1 = JordanAlgebra(m)
|
|
178
|
+
sage: J2 = JordanAlgebra(QQ, m)
|
|
179
|
+
sage: J3 = JordanAlgebra(m, QQ)
|
|
180
|
+
sage: J1 is J2
|
|
181
|
+
False
|
|
182
|
+
sage: J2 is J3
|
|
183
|
+
True
|
|
184
|
+
sage: J4 = JordanAlgebra(ZZ, m)
|
|
185
|
+
sage: J1 is J4
|
|
186
|
+
True
|
|
187
|
+
sage: m = matrix(QQ, [[0,1],[1,1]])
|
|
188
|
+
sage: J1 = JordanAlgebra(m)
|
|
189
|
+
sage: J1 is J2
|
|
190
|
+
True
|
|
191
|
+
"""
|
|
192
|
+
if names is not None:
|
|
193
|
+
if isinstance(names, str):
|
|
194
|
+
names = names.split(',')
|
|
195
|
+
names = tuple(names)
|
|
196
|
+
|
|
197
|
+
if arg1 is None:
|
|
198
|
+
if not isinstance(arg0, Matrix):
|
|
199
|
+
from sage.algebras.octonion_algebra import OctonionAlgebra
|
|
200
|
+
if isinstance(arg0, OctonionAlgebra):
|
|
201
|
+
return ExceptionalJordanAlgebra(arg0)
|
|
202
|
+
if arg0.base_ring().characteristic() == 2:
|
|
203
|
+
raise ValueError("the base ring cannot have characteristic 2")
|
|
204
|
+
return SpecialJordanAlgebra(arg0, names)
|
|
205
|
+
arg0, arg1 = arg0.base_ring(), arg0
|
|
206
|
+
elif isinstance(arg0, Matrix):
|
|
207
|
+
arg0, arg1 = arg1, arg0
|
|
208
|
+
|
|
209
|
+
# arg0 is the base ring and arg1 is a matrix
|
|
210
|
+
if not arg1.is_symmetric():
|
|
211
|
+
raise ValueError("the bilinear form is not symmetric")
|
|
212
|
+
|
|
213
|
+
arg1 = arg1.change_ring(arg0) # This makes a copy
|
|
214
|
+
arg1.set_immutable()
|
|
215
|
+
return JordanAlgebraSymmetricBilinear(arg0, arg1, names=names)
|
|
216
|
+
|
|
217
|
+
def _test_jordan_relations(self, **options):
|
|
218
|
+
r"""
|
|
219
|
+
Test the Jordan algebra relations.
|
|
220
|
+
|
|
221
|
+
The Jordan algebra relations are
|
|
222
|
+
|
|
223
|
+
- `xy = yx`, and
|
|
224
|
+
- `(xy)(xx) = x(y(xx))` (the Jordan identity).
|
|
225
|
+
|
|
226
|
+
EXAMPLES::
|
|
227
|
+
|
|
228
|
+
sage: O = OctonionAlgebra(GF(7), 1, 3, 4)
|
|
229
|
+
sage: J = JordanAlgebra(O)
|
|
230
|
+
sage: J._test_jordan_relations()
|
|
231
|
+
"""
|
|
232
|
+
tester = self._tester(**options)
|
|
233
|
+
S = tester.some_elements()
|
|
234
|
+
from sage.misc.misc import some_tuples
|
|
235
|
+
for x, y in some_tuples(S, 2, tester._max_runs):
|
|
236
|
+
tester.assertEqual(x * y, y * x)
|
|
237
|
+
tester.assertEqual((x * y) * (x * x), x * (y * (x * x)))
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class SpecialJordanAlgebra(JordanAlgebra):
|
|
241
|
+
r"""
|
|
242
|
+
A (special) Jordan algebra `A^+` from an associative algebra `A`.
|
|
243
|
+
"""
|
|
244
|
+
def __init__(self, A, names=None):
|
|
245
|
+
"""
|
|
246
|
+
Initialize ``self``.
|
|
247
|
+
|
|
248
|
+
TESTS::
|
|
249
|
+
|
|
250
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
251
|
+
sage: J = JordanAlgebra(F)
|
|
252
|
+
sage: TestSuite(J).run()
|
|
253
|
+
sage: J.category()
|
|
254
|
+
Category of commutative unital algebras with basis over Rational Field
|
|
255
|
+
"""
|
|
256
|
+
R = A.base_ring()
|
|
257
|
+
C = MagmaticAlgebras(R)
|
|
258
|
+
if A not in C.Associative():
|
|
259
|
+
raise ValueError("A is not an associative algebra")
|
|
260
|
+
|
|
261
|
+
self._A = A
|
|
262
|
+
cat = C.Commutative()
|
|
263
|
+
if A in C.Unital():
|
|
264
|
+
cat = cat.Unital()
|
|
265
|
+
if A in C.WithBasis():
|
|
266
|
+
cat = cat.WithBasis()
|
|
267
|
+
if A in C.FiniteDimensional():
|
|
268
|
+
cat = cat.FiniteDimensional()
|
|
269
|
+
|
|
270
|
+
Parent.__init__(self, base=R, names=names, category=cat)
|
|
271
|
+
|
|
272
|
+
def _repr_(self):
|
|
273
|
+
"""
|
|
274
|
+
Return a string representation of ``self``.
|
|
275
|
+
|
|
276
|
+
EXAMPLES::
|
|
277
|
+
|
|
278
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
279
|
+
sage: JordanAlgebra(F)
|
|
280
|
+
Jordan algebra of Free Algebra on 3 generators (x, y, z) over Rational Field
|
|
281
|
+
"""
|
|
282
|
+
return "Jordan algebra of {}".format(self._A)
|
|
283
|
+
|
|
284
|
+
def _element_constructor_(self, x):
|
|
285
|
+
"""
|
|
286
|
+
Construct an element of ``self`` from ``x``.
|
|
287
|
+
|
|
288
|
+
EXAMPLES::
|
|
289
|
+
|
|
290
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
291
|
+
sage: J = JordanAlgebra(F)
|
|
292
|
+
sage: J(5)
|
|
293
|
+
5
|
|
294
|
+
sage: elt = J(x + 2*x*y); elt
|
|
295
|
+
x + 2*x*y
|
|
296
|
+
sage: elt.parent() is J
|
|
297
|
+
True
|
|
298
|
+
"""
|
|
299
|
+
return self.element_class(self, self._A(x))
|
|
300
|
+
|
|
301
|
+
def _an_element_(self):
|
|
302
|
+
"""
|
|
303
|
+
Return an element of ``self``.
|
|
304
|
+
|
|
305
|
+
EXAMPLES::
|
|
306
|
+
|
|
307
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
308
|
+
sage: J = JordanAlgebra(F)
|
|
309
|
+
sage: J.an_element()
|
|
310
|
+
2 + 2*x + 3*y
|
|
311
|
+
"""
|
|
312
|
+
return self.element_class(self, self._A.an_element())
|
|
313
|
+
|
|
314
|
+
@cached_method
|
|
315
|
+
def basis(self):
|
|
316
|
+
"""
|
|
317
|
+
Return the basis of ``self``.
|
|
318
|
+
|
|
319
|
+
EXAMPLES::
|
|
320
|
+
|
|
321
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
322
|
+
sage: J = JordanAlgebra(F)
|
|
323
|
+
sage: J.basis()
|
|
324
|
+
Lazy family (Term map(i))_{i in Free monoid on 3 generators (x, y, z)}
|
|
325
|
+
"""
|
|
326
|
+
B = self._A.basis()
|
|
327
|
+
return Family(B.keys(), lambda x: self.element_class(self, B[x]), name="Term map")
|
|
328
|
+
|
|
329
|
+
algebra_generators = basis
|
|
330
|
+
|
|
331
|
+
# TODO: Keep this until we can better handle R.<...> shorthand
|
|
332
|
+
def gens(self) -> tuple:
|
|
333
|
+
"""
|
|
334
|
+
Return the generators of ``self``.
|
|
335
|
+
|
|
336
|
+
EXAMPLES::
|
|
337
|
+
|
|
338
|
+
sage: cat = Algebras(QQ).WithBasis().FiniteDimensional()
|
|
339
|
+
sage: C = CombinatorialFreeModule(QQ, ['x','y','z'], category=cat)
|
|
340
|
+
sage: J = JordanAlgebra(C)
|
|
341
|
+
sage: J.gens()
|
|
342
|
+
(B['x'], B['y'], B['z'])
|
|
343
|
+
|
|
344
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
345
|
+
sage: J = JordanAlgebra(F)
|
|
346
|
+
sage: J.gens()
|
|
347
|
+
Traceback (most recent call last):
|
|
348
|
+
...
|
|
349
|
+
NotImplementedError: infinite set
|
|
350
|
+
"""
|
|
351
|
+
return tuple(self.algebra_generators())
|
|
352
|
+
|
|
353
|
+
@cached_method
|
|
354
|
+
def zero(self):
|
|
355
|
+
"""
|
|
356
|
+
Return the element `0`.
|
|
357
|
+
|
|
358
|
+
EXAMPLES::
|
|
359
|
+
|
|
360
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
361
|
+
sage: J = JordanAlgebra(F)
|
|
362
|
+
sage: J.zero()
|
|
363
|
+
0
|
|
364
|
+
"""
|
|
365
|
+
return self.element_class(self, self._A.zero())
|
|
366
|
+
|
|
367
|
+
@cached_method
|
|
368
|
+
def one(self):
|
|
369
|
+
"""
|
|
370
|
+
Return the element `1` if it exists.
|
|
371
|
+
|
|
372
|
+
EXAMPLES::
|
|
373
|
+
|
|
374
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
375
|
+
sage: J = JordanAlgebra(F)
|
|
376
|
+
sage: J.one()
|
|
377
|
+
1
|
|
378
|
+
"""
|
|
379
|
+
return self.element_class(self, self._A.one())
|
|
380
|
+
|
|
381
|
+
class Element(AlgebraElement):
|
|
382
|
+
"""
|
|
383
|
+
An element of a special Jordan algebra.
|
|
384
|
+
"""
|
|
385
|
+
def __init__(self, parent, x):
|
|
386
|
+
"""
|
|
387
|
+
Initialize ``self``.
|
|
388
|
+
|
|
389
|
+
EXAMPLES::
|
|
390
|
+
|
|
391
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
392
|
+
sage: J = JordanAlgebra(F)
|
|
393
|
+
sage: a,b,c = map(J, F.gens())
|
|
394
|
+
sage: TestSuite(a + 2*b - c).run()
|
|
395
|
+
"""
|
|
396
|
+
self._x = x
|
|
397
|
+
AlgebraElement.__init__(self, parent)
|
|
398
|
+
|
|
399
|
+
def _repr_(self):
|
|
400
|
+
"""
|
|
401
|
+
Return a string representation of ``self``.
|
|
402
|
+
|
|
403
|
+
EXAMPLES::
|
|
404
|
+
|
|
405
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
406
|
+
sage: J = JordanAlgebra(F)
|
|
407
|
+
sage: a,b,c = map(J, F.gens())
|
|
408
|
+
sage: a + 2*b - c
|
|
409
|
+
x + 2*y - z
|
|
410
|
+
"""
|
|
411
|
+
return repr(self._x)
|
|
412
|
+
|
|
413
|
+
def _latex_(self):
|
|
414
|
+
"""
|
|
415
|
+
Return a latex representation of ``self``.
|
|
416
|
+
|
|
417
|
+
EXAMPLES::
|
|
418
|
+
|
|
419
|
+
sage: F.<x0,x1,x2> = FreeAlgebra(QQ)
|
|
420
|
+
sage: J = JordanAlgebra(F)
|
|
421
|
+
sage: a,b,c = map(J, F.gens())
|
|
422
|
+
sage: latex(a + 2*b - c)
|
|
423
|
+
x_{0} + 2 x_{1} - x_{2}
|
|
424
|
+
"""
|
|
425
|
+
from sage.misc.latex import latex
|
|
426
|
+
return latex(self._x)
|
|
427
|
+
|
|
428
|
+
def __bool__(self) -> bool:
|
|
429
|
+
"""
|
|
430
|
+
Return if ``self`` is nonzero.
|
|
431
|
+
|
|
432
|
+
EXAMPLES::
|
|
433
|
+
|
|
434
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
435
|
+
sage: J = JordanAlgebra(F)
|
|
436
|
+
sage: a,b,c = map(J, F.gens())
|
|
437
|
+
sage: bool(a + 2*b - c)
|
|
438
|
+
True
|
|
439
|
+
"""
|
|
440
|
+
return bool(self._x)
|
|
441
|
+
|
|
442
|
+
def __eq__(self, other):
|
|
443
|
+
"""
|
|
444
|
+
Check equality.
|
|
445
|
+
|
|
446
|
+
EXAMPLES::
|
|
447
|
+
|
|
448
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
449
|
+
sage: J = JordanAlgebra(F)
|
|
450
|
+
sage: a,b,c = map(J, F.gens())
|
|
451
|
+
sage: elt = a + 2*b - c
|
|
452
|
+
sage: elt == elt
|
|
453
|
+
True
|
|
454
|
+
sage: elt == x
|
|
455
|
+
False
|
|
456
|
+
sage: elt == 2*b
|
|
457
|
+
False
|
|
458
|
+
"""
|
|
459
|
+
if not isinstance(other, SpecialJordanAlgebra.Element):
|
|
460
|
+
return False
|
|
461
|
+
if other.parent() != self.parent():
|
|
462
|
+
return False
|
|
463
|
+
return self._x == other._x
|
|
464
|
+
|
|
465
|
+
def __ne__(self, other):
|
|
466
|
+
"""
|
|
467
|
+
Check inequality.
|
|
468
|
+
|
|
469
|
+
EXAMPLES::
|
|
470
|
+
|
|
471
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
472
|
+
sage: J = JordanAlgebra(F)
|
|
473
|
+
sage: a,b,c = map(J, F.gens())
|
|
474
|
+
sage: elt = a + 2*b - c
|
|
475
|
+
sage: elt != elt
|
|
476
|
+
False
|
|
477
|
+
sage: elt != x
|
|
478
|
+
True
|
|
479
|
+
sage: elt != 2*b
|
|
480
|
+
True
|
|
481
|
+
"""
|
|
482
|
+
return not self == other
|
|
483
|
+
|
|
484
|
+
def _add_(self, other):
|
|
485
|
+
"""
|
|
486
|
+
Add ``self`` and ``other``.
|
|
487
|
+
|
|
488
|
+
EXAMPLES::
|
|
489
|
+
|
|
490
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
491
|
+
sage: J = JordanAlgebra(F)
|
|
492
|
+
sage: a,b,c = map(J, F.gens())
|
|
493
|
+
sage: a + 2*b
|
|
494
|
+
x + 2*y
|
|
495
|
+
"""
|
|
496
|
+
return self.__class__(self.parent(), self._x + other._x)
|
|
497
|
+
|
|
498
|
+
def _neg_(self):
|
|
499
|
+
"""
|
|
500
|
+
Negate ``self``.
|
|
501
|
+
|
|
502
|
+
EXAMPLES::
|
|
503
|
+
|
|
504
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
505
|
+
sage: J = JordanAlgebra(F)
|
|
506
|
+
sage: a,b,c = map(J, F.gens())
|
|
507
|
+
sage: -(a + 2*b)
|
|
508
|
+
-x - 2*y
|
|
509
|
+
"""
|
|
510
|
+
return self.__class__(self.parent(), -self._x)
|
|
511
|
+
|
|
512
|
+
def _sub_(self, other):
|
|
513
|
+
"""
|
|
514
|
+
Subtract ``other`` from ``self``.
|
|
515
|
+
|
|
516
|
+
EXAMPLES::
|
|
517
|
+
|
|
518
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
519
|
+
sage: J = JordanAlgebra(F)
|
|
520
|
+
sage: a,b,c = map(J, F.gens())
|
|
521
|
+
sage: a - 2*b
|
|
522
|
+
x - 2*y
|
|
523
|
+
"""
|
|
524
|
+
return self.__class__(self.parent(), self._x - other._x)
|
|
525
|
+
|
|
526
|
+
def _mul_(self, other):
|
|
527
|
+
"""
|
|
528
|
+
Multiply ``self`` and ``other``.
|
|
529
|
+
|
|
530
|
+
EXAMPLES::
|
|
531
|
+
|
|
532
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
533
|
+
sage: J = JordanAlgebra(F)
|
|
534
|
+
sage: a,b,c = map(J, F.gens())
|
|
535
|
+
sage: (a + 2*b) * (c - b)
|
|
536
|
+
-1/2*x*y + 1/2*x*z - 1/2*y*x - 2*y^2 + y*z + 1/2*z*x + z*y
|
|
537
|
+
|
|
538
|
+
sage: F.<x,y,z> = FreeAlgebra(GF(3))
|
|
539
|
+
sage: J = JordanAlgebra(F)
|
|
540
|
+
sage: a,b,c = map(J, F.gens())
|
|
541
|
+
sage: (a + 2*b) * (c - b)
|
|
542
|
+
x*y + 2*x*z + y*x + y^2 + y*z + 2*z*x + z*y
|
|
543
|
+
"""
|
|
544
|
+
x = self._x
|
|
545
|
+
y = other._x
|
|
546
|
+
# This is safer than dividing by 2
|
|
547
|
+
R = self.parent().base_ring()
|
|
548
|
+
return self.__class__(self.parent(), (x*y + y*x) * ~R(2))
|
|
549
|
+
|
|
550
|
+
def _lmul_(self, other):
|
|
551
|
+
"""
|
|
552
|
+
Multiply ``self`` by the scalar ``other`` on the left.
|
|
553
|
+
|
|
554
|
+
EXAMPLES::
|
|
555
|
+
|
|
556
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
557
|
+
sage: J = JordanAlgebra(F)
|
|
558
|
+
sage: a,b,c = map(J, F.gens())
|
|
559
|
+
sage: (a + b) * 2
|
|
560
|
+
2*x + 2*y
|
|
561
|
+
"""
|
|
562
|
+
return self.__class__(self.parent(), self._x * other)
|
|
563
|
+
|
|
564
|
+
def _rmul_(self, other):
|
|
565
|
+
"""
|
|
566
|
+
Multiply ``self`` and the scalar ``other`` by the right
|
|
567
|
+
action.
|
|
568
|
+
|
|
569
|
+
EXAMPLES::
|
|
570
|
+
|
|
571
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
572
|
+
sage: J = JordanAlgebra(F)
|
|
573
|
+
sage: a,b,c = map(J, F.gens())
|
|
574
|
+
sage: 2 * (a + b)
|
|
575
|
+
2*x + 2*y
|
|
576
|
+
"""
|
|
577
|
+
return self.__class__(self.parent(), other * self._x)
|
|
578
|
+
|
|
579
|
+
def monomial_coefficients(self, copy=True):
|
|
580
|
+
"""
|
|
581
|
+
Return a dictionary whose keys are indices of basis elements in
|
|
582
|
+
the support of ``self`` and whose values are the corresponding
|
|
583
|
+
coefficients.
|
|
584
|
+
|
|
585
|
+
INPUT:
|
|
586
|
+
|
|
587
|
+
- ``copy`` -- boolean (default: ``True``); if ``self`` is
|
|
588
|
+
internally represented by a dictionary ``d``, then make a copy of
|
|
589
|
+
``d``; if ``False``, then this can cause undesired behavior by
|
|
590
|
+
mutating ``d``
|
|
591
|
+
|
|
592
|
+
EXAMPLES::
|
|
593
|
+
|
|
594
|
+
sage: F.<x,y,z> = FreeAlgebra(QQ)
|
|
595
|
+
sage: J = JordanAlgebra(F)
|
|
596
|
+
sage: a,b,c = map(J, F.gens())
|
|
597
|
+
sage: elt = a + 2*b - c
|
|
598
|
+
sage: elt.monomial_coefficients()
|
|
599
|
+
{x: 1, y: 2, z: -1}
|
|
600
|
+
"""
|
|
601
|
+
return self._x.monomial_coefficients(copy)
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
class JordanAlgebraSymmetricBilinear(JordanAlgebra):
|
|
605
|
+
r"""
|
|
606
|
+
A Jordan algebra given by a symmetric bilinear form `m`.
|
|
607
|
+
"""
|
|
608
|
+
def __init__(self, R, form, names=None):
|
|
609
|
+
"""
|
|
610
|
+
Initialize ``self``.
|
|
611
|
+
|
|
612
|
+
TESTS::
|
|
613
|
+
|
|
614
|
+
sage: m = matrix([[-2,3],[3,4]])
|
|
615
|
+
sage: J = JordanAlgebra(m)
|
|
616
|
+
sage: TestSuite(J).run()
|
|
617
|
+
"""
|
|
618
|
+
self._form = form
|
|
619
|
+
self._M = FreeModule(R, form.ncols())
|
|
620
|
+
cat = MagmaticAlgebras(R).Commutative().Unital().FiniteDimensional().WithBasis()
|
|
621
|
+
Parent.__init__(self, base=R, names=names, category=cat)
|
|
622
|
+
|
|
623
|
+
def _repr_(self):
|
|
624
|
+
"""
|
|
625
|
+
Return a string representation of ``self``.
|
|
626
|
+
|
|
627
|
+
EXAMPLES::
|
|
628
|
+
|
|
629
|
+
sage: m = matrix([[-2,3],[3,4]])
|
|
630
|
+
sage: JordanAlgebra(m)
|
|
631
|
+
Jordan algebra over Integer Ring given by the symmetric bilinear form:
|
|
632
|
+
[-2 3]
|
|
633
|
+
[ 3 4]
|
|
634
|
+
"""
|
|
635
|
+
return "Jordan algebra over {} given by the symmetric bilinear" \
|
|
636
|
+
" form:\n{}".format(self.base_ring(), self._form)
|
|
637
|
+
|
|
638
|
+
def _element_constructor_(self, *args):
|
|
639
|
+
"""
|
|
640
|
+
Construct an element of ``self`` from ``s``.
|
|
641
|
+
|
|
642
|
+
Here ``s`` can be a pair of an element of `R` and an
|
|
643
|
+
element of `M`, or an element of `R`, or an element of
|
|
644
|
+
`M`, or an element of a(nother) Jordan algebra given
|
|
645
|
+
by a symmetric bilinear form.
|
|
646
|
+
|
|
647
|
+
EXAMPLES::
|
|
648
|
+
|
|
649
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
650
|
+
sage: J = JordanAlgebra(m)
|
|
651
|
+
sage: J(2)
|
|
652
|
+
2 + (0, 0)
|
|
653
|
+
sage: J((-4, (2, 5)))
|
|
654
|
+
-4 + (2, 5)
|
|
655
|
+
sage: J((-4, (ZZ^2)((2, 5))))
|
|
656
|
+
-4 + (2, 5)
|
|
657
|
+
sage: J(2, (-2, 3))
|
|
658
|
+
2 + (-2, 3)
|
|
659
|
+
sage: J(2, (ZZ^2)((-2, 3)))
|
|
660
|
+
2 + (-2, 3)
|
|
661
|
+
sage: J(-1, 1, 0)
|
|
662
|
+
-1 + (1, 0)
|
|
663
|
+
sage: J((ZZ^2)((1, 3)))
|
|
664
|
+
0 + (1, 3)
|
|
665
|
+
|
|
666
|
+
sage: m = matrix([[2]])
|
|
667
|
+
sage: J = JordanAlgebra(m)
|
|
668
|
+
sage: J(2)
|
|
669
|
+
2 + (0)
|
|
670
|
+
sage: J((-4, (2,)))
|
|
671
|
+
-4 + (2)
|
|
672
|
+
sage: J(2, (-2,))
|
|
673
|
+
2 + (-2)
|
|
674
|
+
sage: J(-1, 1)
|
|
675
|
+
-1 + (1)
|
|
676
|
+
sage: J((ZZ^1)((3,)))
|
|
677
|
+
0 + (3)
|
|
678
|
+
|
|
679
|
+
sage: m = Matrix(QQ, [])
|
|
680
|
+
sage: J = JordanAlgebra(m)
|
|
681
|
+
sage: J(2)
|
|
682
|
+
2 + ()
|
|
683
|
+
sage: J((-4, ()))
|
|
684
|
+
-4 + ()
|
|
685
|
+
sage: J(2, ())
|
|
686
|
+
2 + ()
|
|
687
|
+
sage: J(-1)
|
|
688
|
+
-1 + ()
|
|
689
|
+
sage: J((ZZ^0)(()))
|
|
690
|
+
0 + ()
|
|
691
|
+
"""
|
|
692
|
+
R = self.base_ring()
|
|
693
|
+
if len(args) == 1:
|
|
694
|
+
s = args[0]
|
|
695
|
+
|
|
696
|
+
if isinstance(s, JordanAlgebraSymmetricBilinear.Element):
|
|
697
|
+
if s.parent() is self:
|
|
698
|
+
return s
|
|
699
|
+
return self.element_class(self, R(s._s), self._M(s._v))
|
|
700
|
+
|
|
701
|
+
if isinstance(s, (list, tuple)):
|
|
702
|
+
if len(s) != 2:
|
|
703
|
+
raise ValueError("must be length 2")
|
|
704
|
+
return self.element_class(self, R(s[0]), self._M(s[1]))
|
|
705
|
+
|
|
706
|
+
if s in self._M:
|
|
707
|
+
return self.element_class(self, R.zero(), self._M(s))
|
|
708
|
+
|
|
709
|
+
return self.element_class(self, R(s), self._M.zero())
|
|
710
|
+
|
|
711
|
+
if len(args) == 2 and (isinstance(args[1], (list, tuple)) or args[1] in self._M):
|
|
712
|
+
return self.element_class(self, R(args[0]), self._M(args[1]))
|
|
713
|
+
|
|
714
|
+
if len(args) == self._form.ncols() + 1:
|
|
715
|
+
return self.element_class(self, R(args[0]), self._M(args[1:]))
|
|
716
|
+
|
|
717
|
+
raise ValueError("unable to construct an element from the given data")
|
|
718
|
+
|
|
719
|
+
def _coerce_map_from_base_ring(self):
|
|
720
|
+
"""
|
|
721
|
+
Return a coercion map from the base ring of ``self``.
|
|
722
|
+
|
|
723
|
+
TESTS::
|
|
724
|
+
|
|
725
|
+
sage: J = JordanAlgebra(Matrix([[0, 1], [1, 1]]))
|
|
726
|
+
sage: J._coerce_map_from_base_ring()
|
|
727
|
+
Conversion map:
|
|
728
|
+
From: Integer Ring
|
|
729
|
+
To: Jordan algebra over Integer Ring given by the symmetric bilinear form:
|
|
730
|
+
[0 1]
|
|
731
|
+
[1 1]
|
|
732
|
+
sage: J.coerce_map_from(ZZ)
|
|
733
|
+
Coercion map:
|
|
734
|
+
From: Integer Ring
|
|
735
|
+
To: Jordan algebra over Integer Ring given by the symmetric bilinear form:
|
|
736
|
+
[0 1]
|
|
737
|
+
[1 1]
|
|
738
|
+
"""
|
|
739
|
+
# Return a DefaultConvertMap_unique; this can pass additional
|
|
740
|
+
# arguments to _element_constructor_, unlike the map returned
|
|
741
|
+
# by UnitalAlgebras.ParentMethods._coerce_map_from_base_ring.
|
|
742
|
+
return self._generic_coerce_map(self.base_ring())
|
|
743
|
+
|
|
744
|
+
@cached_method
|
|
745
|
+
def basis(self):
|
|
746
|
+
"""
|
|
747
|
+
Return a basis of ``self``.
|
|
748
|
+
|
|
749
|
+
The basis returned begins with the unity of `R` and continues with
|
|
750
|
+
the standard basis of `M`.
|
|
751
|
+
|
|
752
|
+
EXAMPLES::
|
|
753
|
+
|
|
754
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
755
|
+
sage: J = JordanAlgebra(m)
|
|
756
|
+
sage: J.basis()
|
|
757
|
+
Family (1 + (0, 0), 0 + (1, 0), 0 + (0, 1))
|
|
758
|
+
"""
|
|
759
|
+
R = self.base_ring()
|
|
760
|
+
ret = (self.element_class(self, R.one(), self._M.zero()),)
|
|
761
|
+
ret += tuple(self.element_class(self, R.zero(), x)
|
|
762
|
+
for x in self._M.basis())
|
|
763
|
+
return Family(ret)
|
|
764
|
+
|
|
765
|
+
algebra_generators = basis
|
|
766
|
+
|
|
767
|
+
def gens(self) -> tuple:
|
|
768
|
+
"""
|
|
769
|
+
Return the generators of ``self``.
|
|
770
|
+
|
|
771
|
+
EXAMPLES::
|
|
772
|
+
|
|
773
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
774
|
+
sage: J = JordanAlgebra(m)
|
|
775
|
+
sage: J.gens()
|
|
776
|
+
(1 + (0, 0), 0 + (1, 0), 0 + (0, 1))
|
|
777
|
+
"""
|
|
778
|
+
return tuple(self.algebra_generators())
|
|
779
|
+
|
|
780
|
+
@cached_method
|
|
781
|
+
def zero(self):
|
|
782
|
+
"""
|
|
783
|
+
Return the element 0.
|
|
784
|
+
|
|
785
|
+
EXAMPLES::
|
|
786
|
+
|
|
787
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
788
|
+
sage: J = JordanAlgebra(m)
|
|
789
|
+
sage: J.zero()
|
|
790
|
+
0 + (0, 0)
|
|
791
|
+
"""
|
|
792
|
+
return self.element_class(self, self.base_ring().zero(), self._M.zero())
|
|
793
|
+
|
|
794
|
+
@cached_method
|
|
795
|
+
def one(self):
|
|
796
|
+
"""
|
|
797
|
+
Return the element 1 if it exists.
|
|
798
|
+
|
|
799
|
+
EXAMPLES::
|
|
800
|
+
|
|
801
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
802
|
+
sage: J = JordanAlgebra(m)
|
|
803
|
+
sage: J.one()
|
|
804
|
+
1 + (0, 0)
|
|
805
|
+
"""
|
|
806
|
+
return self.element_class(self, self.base_ring().one(), self._M.zero())
|
|
807
|
+
|
|
808
|
+
class Element(AlgebraElement):
|
|
809
|
+
"""
|
|
810
|
+
An element of a Jordan algebra defined by a symmetric bilinear form.
|
|
811
|
+
"""
|
|
812
|
+
def __init__(self, parent, s, v):
|
|
813
|
+
"""
|
|
814
|
+
Initialize ``self``.
|
|
815
|
+
|
|
816
|
+
TESTS::
|
|
817
|
+
|
|
818
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
819
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
820
|
+
sage: TestSuite(a + 2*b - c).run()
|
|
821
|
+
"""
|
|
822
|
+
self._s = s
|
|
823
|
+
self._v = v
|
|
824
|
+
AlgebraElement.__init__(self, parent)
|
|
825
|
+
|
|
826
|
+
def _repr_(self):
|
|
827
|
+
"""
|
|
828
|
+
Return a string representation of ``self``.
|
|
829
|
+
|
|
830
|
+
EXAMPLES::
|
|
831
|
+
|
|
832
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
833
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
834
|
+
sage: a + 2*b - c
|
|
835
|
+
1 + (2, -1)
|
|
836
|
+
"""
|
|
837
|
+
return "{} + {}".format(self._s, self._v)
|
|
838
|
+
|
|
839
|
+
def _latex_(self):
|
|
840
|
+
r"""
|
|
841
|
+
Return a latex representation of ``self``.
|
|
842
|
+
|
|
843
|
+
EXAMPLES::
|
|
844
|
+
|
|
845
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
846
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
847
|
+
sage: latex(a + 2*b - c)
|
|
848
|
+
1 + \left(2,\,-1\right)
|
|
849
|
+
"""
|
|
850
|
+
from sage.misc.latex import latex
|
|
851
|
+
return "{} + {}".format(latex(self._s), latex(self._v))
|
|
852
|
+
|
|
853
|
+
def __bool__(self) -> bool:
|
|
854
|
+
"""
|
|
855
|
+
Return if ``self`` is nonzero.
|
|
856
|
+
|
|
857
|
+
TESTS::
|
|
858
|
+
|
|
859
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
860
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
861
|
+
sage: bool(1)
|
|
862
|
+
True
|
|
863
|
+
sage: bool(b)
|
|
864
|
+
True
|
|
865
|
+
sage: bool(a + 2*b - c)
|
|
866
|
+
True
|
|
867
|
+
"""
|
|
868
|
+
return bool(self._s) or bool(self._v)
|
|
869
|
+
|
|
870
|
+
def __eq__(self, other):
|
|
871
|
+
"""
|
|
872
|
+
Check equality.
|
|
873
|
+
|
|
874
|
+
EXAMPLES::
|
|
875
|
+
|
|
876
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
877
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
878
|
+
sage: x = 4*a - b + 3*c
|
|
879
|
+
sage: x == J((4, (-1, 3)))
|
|
880
|
+
True
|
|
881
|
+
sage: a == x
|
|
882
|
+
False
|
|
883
|
+
|
|
884
|
+
sage: m = matrix([[-2,3],[3,4]])
|
|
885
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
886
|
+
sage: 4*a - b + 3*c == x
|
|
887
|
+
False
|
|
888
|
+
"""
|
|
889
|
+
if not isinstance(other, JordanAlgebraSymmetricBilinear.Element):
|
|
890
|
+
return False
|
|
891
|
+
if other.parent() != self.parent():
|
|
892
|
+
return False
|
|
893
|
+
return self._s == other._s and self._v == other._v
|
|
894
|
+
|
|
895
|
+
def __ne__(self, other):
|
|
896
|
+
"""
|
|
897
|
+
Check inequality.
|
|
898
|
+
|
|
899
|
+
EXAMPLES::
|
|
900
|
+
|
|
901
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
902
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
903
|
+
sage: x = 4*a - b + 3*c
|
|
904
|
+
sage: x != J((4, (-1, 3)))
|
|
905
|
+
False
|
|
906
|
+
sage: a != x
|
|
907
|
+
True
|
|
908
|
+
|
|
909
|
+
sage: m = matrix([[-2,3],[3,4]])
|
|
910
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
911
|
+
sage: 4*a - b + 3*c != x
|
|
912
|
+
True
|
|
913
|
+
"""
|
|
914
|
+
return not self == other
|
|
915
|
+
|
|
916
|
+
def _add_(self, other):
|
|
917
|
+
"""
|
|
918
|
+
Add ``self`` and ``other``.
|
|
919
|
+
|
|
920
|
+
EXAMPLES::
|
|
921
|
+
|
|
922
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
923
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
924
|
+
sage: a + b
|
|
925
|
+
1 + (1, 0)
|
|
926
|
+
sage: b + c
|
|
927
|
+
0 + (1, 1)
|
|
928
|
+
"""
|
|
929
|
+
return self.__class__(self.parent(), self._s + other._s, self._v + other._v)
|
|
930
|
+
|
|
931
|
+
def _neg_(self):
|
|
932
|
+
"""
|
|
933
|
+
Negate ``self``.
|
|
934
|
+
|
|
935
|
+
EXAMPLES::
|
|
936
|
+
|
|
937
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
938
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
939
|
+
sage: -(a + b - 2*c)
|
|
940
|
+
-1 + (-1, 2)
|
|
941
|
+
"""
|
|
942
|
+
return self.__class__(self.parent(), -self._s, -self._v)
|
|
943
|
+
|
|
944
|
+
def _sub_(self, other):
|
|
945
|
+
"""
|
|
946
|
+
Subtract ``other`` from ``self``.
|
|
947
|
+
|
|
948
|
+
EXAMPLES::
|
|
949
|
+
|
|
950
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
951
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
952
|
+
sage: a - b
|
|
953
|
+
1 + (-1, 0)
|
|
954
|
+
sage: b - c
|
|
955
|
+
0 + (1, -1)
|
|
956
|
+
"""
|
|
957
|
+
return self.__class__(self.parent(), self._s - other._s, self._v - other._v)
|
|
958
|
+
|
|
959
|
+
def _mul_(self, other):
|
|
960
|
+
"""
|
|
961
|
+
Multiply ``self`` and ``other``.
|
|
962
|
+
|
|
963
|
+
EXAMPLES::
|
|
964
|
+
|
|
965
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
966
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
967
|
+
sage: (4*a - b + 3*c)*(2*a + 2*b - c)
|
|
968
|
+
12 + (6, 2)
|
|
969
|
+
|
|
970
|
+
sage: m = matrix([[-2,3],[3,4]])
|
|
971
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
972
|
+
sage: (4*a - b + 3*c)*(2*a + 2*b - c)
|
|
973
|
+
21 + (6, 2)
|
|
974
|
+
"""
|
|
975
|
+
P = self.parent()
|
|
976
|
+
return self.__class__(P,
|
|
977
|
+
self._s * other._s
|
|
978
|
+
+ (self._v * P._form * other._v.column())[0],
|
|
979
|
+
other._s * self._v + self._s * other._v)
|
|
980
|
+
|
|
981
|
+
def _lmul_(self, other):
|
|
982
|
+
"""
|
|
983
|
+
Multiply ``self`` by the scalar ``other`` on the left.
|
|
984
|
+
|
|
985
|
+
EXAMPLES::
|
|
986
|
+
|
|
987
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
988
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
989
|
+
sage: (a + b - c) * 2
|
|
990
|
+
2 + (2, -2)
|
|
991
|
+
"""
|
|
992
|
+
return self.__class__(self.parent(), self._s * other, self._v * other)
|
|
993
|
+
|
|
994
|
+
def _rmul_(self, other):
|
|
995
|
+
"""
|
|
996
|
+
Multiply ``self`` with the scalar ``other`` by the right
|
|
997
|
+
action.
|
|
998
|
+
|
|
999
|
+
EXAMPLES::
|
|
1000
|
+
|
|
1001
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
1002
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
1003
|
+
sage: 2 * (a + b - c)
|
|
1004
|
+
2 + (2, -2)
|
|
1005
|
+
"""
|
|
1006
|
+
return self.__class__(self.parent(), other * self._s, other * self._v)
|
|
1007
|
+
|
|
1008
|
+
def monomial_coefficients(self, copy=True):
|
|
1009
|
+
"""
|
|
1010
|
+
Return a dictionary whose keys are indices of basis elements in
|
|
1011
|
+
the support of ``self`` and whose values are the corresponding
|
|
1012
|
+
coefficients.
|
|
1013
|
+
|
|
1014
|
+
INPUT:
|
|
1015
|
+
|
|
1016
|
+
- ``copy`` -- ignored
|
|
1017
|
+
|
|
1018
|
+
EXAMPLES::
|
|
1019
|
+
|
|
1020
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
1021
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
1022
|
+
sage: elt = a + 2*b - c
|
|
1023
|
+
sage: elt.monomial_coefficients()
|
|
1024
|
+
{0: 1, 1: 2, 2: -1}
|
|
1025
|
+
"""
|
|
1026
|
+
d = {0: self._s}
|
|
1027
|
+
for i,c in enumerate(self._v):
|
|
1028
|
+
d[i+1] = c
|
|
1029
|
+
return d
|
|
1030
|
+
|
|
1031
|
+
def trace(self):
|
|
1032
|
+
r"""
|
|
1033
|
+
Return the trace of ``self``.
|
|
1034
|
+
|
|
1035
|
+
The trace of an element `\alpha + x \in M^*` is given by
|
|
1036
|
+
`t(\alpha + x) = 2 \alpha`.
|
|
1037
|
+
|
|
1038
|
+
EXAMPLES::
|
|
1039
|
+
|
|
1040
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
1041
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
1042
|
+
sage: x = 4*a - b + 3*c
|
|
1043
|
+
sage: x.trace()
|
|
1044
|
+
8
|
|
1045
|
+
"""
|
|
1046
|
+
return 2 * self._s
|
|
1047
|
+
|
|
1048
|
+
def norm(self):
|
|
1049
|
+
r"""
|
|
1050
|
+
Return the norm of ``self``.
|
|
1051
|
+
|
|
1052
|
+
The norm of an element `\alpha + x \in M^*` is given by
|
|
1053
|
+
`n(\alpha + x) = \alpha^2 - (x, x)`.
|
|
1054
|
+
|
|
1055
|
+
EXAMPLES::
|
|
1056
|
+
|
|
1057
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
1058
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
1059
|
+
sage: x = 4*a - b + 3*c; x
|
|
1060
|
+
4 + (-1, 3)
|
|
1061
|
+
sage: x.norm()
|
|
1062
|
+
13
|
|
1063
|
+
"""
|
|
1064
|
+
return self._s * self._s - (self._v * self.parent()._form
|
|
1065
|
+
* self._v.column())[0]
|
|
1066
|
+
|
|
1067
|
+
def bar(self):
|
|
1068
|
+
r"""
|
|
1069
|
+
Return the result of the bar involution of ``self``.
|
|
1070
|
+
|
|
1071
|
+
The bar involution `\bar{\cdot}` is the `R`-linear
|
|
1072
|
+
endomorphism of `M^*` defined by `\bar{1} = 1` and
|
|
1073
|
+
`\bar{x} = -x` for `x \in M`.
|
|
1074
|
+
|
|
1075
|
+
EXAMPLES::
|
|
1076
|
+
|
|
1077
|
+
sage: m = matrix([[0,1],[1,1]])
|
|
1078
|
+
sage: J.<a,b,c> = JordanAlgebra(m)
|
|
1079
|
+
sage: x = 4*a - b + 3*c
|
|
1080
|
+
sage: x.bar()
|
|
1081
|
+
4 + (1, -3)
|
|
1082
|
+
|
|
1083
|
+
We check that it is an algebra morphism::
|
|
1084
|
+
|
|
1085
|
+
sage: y = 2*a + 2*b - c
|
|
1086
|
+
sage: x.bar() * y.bar() == (x*y).bar()
|
|
1087
|
+
True
|
|
1088
|
+
"""
|
|
1089
|
+
return self.__class__(self.parent(), self._s, -self._v)
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
class ExceptionalJordanAlgebra(JordanAlgebra):
|
|
1093
|
+
r"""
|
|
1094
|
+
The exceptional `27` dimensional Jordan algebra as self-adjoint
|
|
1095
|
+
`3 \times 3` matrix over an octonion algebra.
|
|
1096
|
+
|
|
1097
|
+
Let `\mathbf{O}` be the :class:`OctonionAlgebra` over a commutative
|
|
1098
|
+
ring `R` of characteristic not equal to `2`. The *exceptional Jordan
|
|
1099
|
+
algebra* `\mathfrak{h}_3(\mathbf{O})` is a `27` dimensional free
|
|
1100
|
+
`R`-module spanned by the matrices
|
|
1101
|
+
|
|
1102
|
+
.. MATH::
|
|
1103
|
+
|
|
1104
|
+
\begin{bmatrix}
|
|
1105
|
+
\alpha & x & y \\
|
|
1106
|
+
x^* & \beta & z \\
|
|
1107
|
+
y^* & z^* & \gamma
|
|
1108
|
+
\end{bmatrix}
|
|
1109
|
+
|
|
1110
|
+
for `\alpha, \beta, \gamma \in R` and `x, y, z \in \mathbf{O}`,
|
|
1111
|
+
with multiplication given by the usual symmetrizer operation
|
|
1112
|
+
`X \circ Y = \frac{1}{2}(XY + YX)`.
|
|
1113
|
+
|
|
1114
|
+
These are also known as *Albert algebras* due to the work of
|
|
1115
|
+
Abraham Adrian Albert on these algebras over `\RR`.
|
|
1116
|
+
|
|
1117
|
+
EXAMPLES:
|
|
1118
|
+
|
|
1119
|
+
We construct an exceptional Jordan algebra over `\QQ` and perform
|
|
1120
|
+
some basic computations::
|
|
1121
|
+
|
|
1122
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1123
|
+
sage: J = JordanAlgebra(O)
|
|
1124
|
+
sage: gens = J.gens()
|
|
1125
|
+
sage: gens[1]
|
|
1126
|
+
[0 0 0]
|
|
1127
|
+
[0 1 0]
|
|
1128
|
+
[0 0 0]
|
|
1129
|
+
sage: gens[3]
|
|
1130
|
+
[0 1 0]
|
|
1131
|
+
[1 0 0]
|
|
1132
|
+
[0 0 0]
|
|
1133
|
+
sage: gens[1] * gens[3]
|
|
1134
|
+
[ 0 1/2 0]
|
|
1135
|
+
[1/2 0 0]
|
|
1136
|
+
[ 0 0 0]
|
|
1137
|
+
|
|
1138
|
+
The Lie algebra of derivations of the exceptional Jordan algebra
|
|
1139
|
+
is isomorphic to the simple Lie algebra of type `F_4`. We verify
|
|
1140
|
+
that we the derivation module has the correct dimension::
|
|
1141
|
+
|
|
1142
|
+
sage: len(J.derivations_basis()) # long time
|
|
1143
|
+
52
|
|
1144
|
+
sage: LieAlgebra(QQ, cartan_type='F4').dimension() # needs sage.graphs
|
|
1145
|
+
52
|
|
1146
|
+
|
|
1147
|
+
REFERENCES:
|
|
1148
|
+
|
|
1149
|
+
- :wikipedia:`Albert_algebra`
|
|
1150
|
+
- :wikipedia:`Jordan_algebra#Examples`
|
|
1151
|
+
- :wikipedia:`Hurwitz's_theorem_(composition_algebras)#Applications_to_Jordan_algebras`
|
|
1152
|
+
- `<https://math.ucr.edu/home/baez/octonions/octonions.pdf>`_
|
|
1153
|
+
"""
|
|
1154
|
+
def __init__(self, O):
|
|
1155
|
+
r"""
|
|
1156
|
+
Initialize ``self``.
|
|
1157
|
+
|
|
1158
|
+
EXAMPLES::
|
|
1159
|
+
|
|
1160
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1161
|
+
sage: J = JordanAlgebra(O)
|
|
1162
|
+
sage: TestSuite(J).run() # long time
|
|
1163
|
+
|
|
1164
|
+
sage: O = OctonionAlgebra(QQ, 1, -2, 9)
|
|
1165
|
+
sage: J = JordanAlgebra(O)
|
|
1166
|
+
sage: TestSuite(J).run() # long time
|
|
1167
|
+
|
|
1168
|
+
sage: R.<x, y> = GF(11)[]
|
|
1169
|
+
sage: O = OctonionAlgebra(R, 1, x + y, 9)
|
|
1170
|
+
sage: J = JordanAlgebra(O)
|
|
1171
|
+
sage: TestSuite(J).run() # long time
|
|
1172
|
+
|
|
1173
|
+
sage: O = OctonionAlgebra(ZZ)
|
|
1174
|
+
sage: J = JordanAlgebra(O)
|
|
1175
|
+
Traceback (most recent call last):
|
|
1176
|
+
...
|
|
1177
|
+
ValueError: 2 must be invertible
|
|
1178
|
+
"""
|
|
1179
|
+
self._O = O
|
|
1180
|
+
R = O.base_ring()
|
|
1181
|
+
|
|
1182
|
+
if not R(2).is_unit():
|
|
1183
|
+
raise ValueError("2 must be invertible")
|
|
1184
|
+
self._half = R(2).inverse_of_unit()
|
|
1185
|
+
|
|
1186
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
1187
|
+
Onames = list(O.variable_names())
|
|
1188
|
+
Onames.extend(Onames[3] + Onames[i] for i in range(3))
|
|
1189
|
+
self._repr_poly_ring = PolynomialRing(R, Onames)
|
|
1190
|
+
|
|
1191
|
+
cat = MagmaticAlgebras(R).Unital().FiniteDimensional().WithBasis()
|
|
1192
|
+
Parent.__init__(self, base=R, category=cat)
|
|
1193
|
+
|
|
1194
|
+
def _repr_(self):
|
|
1195
|
+
r"""
|
|
1196
|
+
Return a string representation of ``self``.
|
|
1197
|
+
|
|
1198
|
+
EXAMPLES::
|
|
1199
|
+
|
|
1200
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1201
|
+
sage: JordanAlgebra(O)
|
|
1202
|
+
Exceptional Jordan algebra constructed from Octonion algebra
|
|
1203
|
+
over Rational Field
|
|
1204
|
+
"""
|
|
1205
|
+
return "Exceptional Jordan algebra constructed from {}".format(self._O)
|
|
1206
|
+
|
|
1207
|
+
def _element_constructor_(self, x):
|
|
1208
|
+
r"""
|
|
1209
|
+
Construct an element of ``self`` from ``s``.
|
|
1210
|
+
|
|
1211
|
+
EXAMPLES::
|
|
1212
|
+
|
|
1213
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1214
|
+
sage: J = JordanAlgebra(O)
|
|
1215
|
+
sage: J(2)
|
|
1216
|
+
[2 0 0]
|
|
1217
|
+
[0 2 0]
|
|
1218
|
+
[0 0 2]
|
|
1219
|
+
sage: J([2, 3, 0, -1, O.basis()[3], 2])
|
|
1220
|
+
[ 2 -1 k]
|
|
1221
|
+
[-1 3 2]
|
|
1222
|
+
[-k 2 0]
|
|
1223
|
+
"""
|
|
1224
|
+
R = self.base_ring()
|
|
1225
|
+
try:
|
|
1226
|
+
x = R(x)
|
|
1227
|
+
zero = self._O.zero()
|
|
1228
|
+
return self.element_class(self, [x, x, x, zero, zero, zero])
|
|
1229
|
+
except (ValueError, TypeError):
|
|
1230
|
+
pass
|
|
1231
|
+
x = list(x)
|
|
1232
|
+
if len(x) != 6:
|
|
1233
|
+
raise ValueError("invalid data to construct an element")
|
|
1234
|
+
R = self.base_ring()
|
|
1235
|
+
for i in range(3):
|
|
1236
|
+
x[i] = R(x[i])
|
|
1237
|
+
x[3+i] = self._O(x[3+i])
|
|
1238
|
+
return self.element_class(self, x)
|
|
1239
|
+
|
|
1240
|
+
def _test_multiplication_self_adjoint(self, **options):
|
|
1241
|
+
r"""
|
|
1242
|
+
Test that `(XY + YX) / 2` is self-adjoint.
|
|
1243
|
+
|
|
1244
|
+
EXAMPLES::
|
|
1245
|
+
|
|
1246
|
+
sage: O = OctonionAlgebra(GF(7), 1, 3, 4)
|
|
1247
|
+
sage: J = JordanAlgebra(O)
|
|
1248
|
+
sage: J._test_multiplication_self_adjoint()
|
|
1249
|
+
"""
|
|
1250
|
+
tester = self._tester(**options)
|
|
1251
|
+
S = tester.some_elements()
|
|
1252
|
+
data_pairs = [(0, 0), (1, 1), (2, 2), (0, 1), (0, 2), (1, 2)]
|
|
1253
|
+
zerO = self._O.zero()
|
|
1254
|
+
from sage.misc.misc import some_tuples
|
|
1255
|
+
for x, y in some_tuples(S, 2, tester._max_runs):
|
|
1256
|
+
SD = x._data
|
|
1257
|
+
OD = y._data
|
|
1258
|
+
X = [[SD[0], SD[3], SD[4]],
|
|
1259
|
+
[SD[3].conjugate(), SD[1], SD[5]],
|
|
1260
|
+
[SD[4].conjugate(), SD[5].conjugate(), SD[2]]]
|
|
1261
|
+
Y = [[OD[0], OD[3], OD[4]],
|
|
1262
|
+
[OD[3].conjugate(), OD[1], OD[5]],
|
|
1263
|
+
[OD[4].conjugate(), OD[5].conjugate(), OD[2]]]
|
|
1264
|
+
for r, c in data_pairs:
|
|
1265
|
+
if r != c:
|
|
1266
|
+
val = sum(X[r][i] * Y[i][c] + Y[r][i] * X[i][c] for i in range(3)) * self._half
|
|
1267
|
+
val_opp = sum(X[c][i] * Y[i][r] + Y[c][i] * X[i][r] for i in range(3)) * self._half
|
|
1268
|
+
tester.assertEqual(val, val_opp.conjugate())
|
|
1269
|
+
else:
|
|
1270
|
+
val = sum(X[r][i] * Y[i][c] + Y[r][i] * X[i][c] for i in range(3)) * self._half
|
|
1271
|
+
tester.assertEqual(val.imag_part(), zerO)
|
|
1272
|
+
|
|
1273
|
+
@cached_method
|
|
1274
|
+
def basis(self):
|
|
1275
|
+
r"""
|
|
1276
|
+
Return a basis of ``self``.
|
|
1277
|
+
|
|
1278
|
+
EXAMPLES::
|
|
1279
|
+
|
|
1280
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1281
|
+
sage: J = JordanAlgebra(O)
|
|
1282
|
+
sage: B = J.basis()
|
|
1283
|
+
sage: B[::6]
|
|
1284
|
+
([1 0 0]
|
|
1285
|
+
[0 0 0]
|
|
1286
|
+
[0 0 0],
|
|
1287
|
+
[ 0 k 0]
|
|
1288
|
+
[-k 0 0]
|
|
1289
|
+
[ 0 0 0],
|
|
1290
|
+
[ 0 0 i]
|
|
1291
|
+
[ 0 0 0]
|
|
1292
|
+
[-i 0 0],
|
|
1293
|
+
[ 0 0 lk]
|
|
1294
|
+
[ 0 0 0]
|
|
1295
|
+
[-lk 0 0],
|
|
1296
|
+
[ 0 0 0]
|
|
1297
|
+
[ 0 0 li]
|
|
1298
|
+
[ 0 -li 0])
|
|
1299
|
+
sage: len(B)
|
|
1300
|
+
27
|
|
1301
|
+
"""
|
|
1302
|
+
R = self.base_ring()
|
|
1303
|
+
OB = self._O.basis()
|
|
1304
|
+
base = [R.zero()] * 3 + [self._O.zero()] * 3
|
|
1305
|
+
ret = []
|
|
1306
|
+
for i in range(3):
|
|
1307
|
+
temp = list(base)
|
|
1308
|
+
temp[i] = R.one()
|
|
1309
|
+
ret.append(self.element_class(self, temp))
|
|
1310
|
+
for i in range(3):
|
|
1311
|
+
for b in OB:
|
|
1312
|
+
temp = list(base)
|
|
1313
|
+
temp[3+i] = b
|
|
1314
|
+
ret.append(self.element_class(self, temp))
|
|
1315
|
+
return Family(ret)
|
|
1316
|
+
|
|
1317
|
+
algebra_generators = basis
|
|
1318
|
+
|
|
1319
|
+
def gens(self) -> tuple:
|
|
1320
|
+
"""
|
|
1321
|
+
Return the generators of ``self``.
|
|
1322
|
+
|
|
1323
|
+
EXAMPLES::
|
|
1324
|
+
|
|
1325
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1326
|
+
sage: J = JordanAlgebra(O)
|
|
1327
|
+
sage: G = J.gens()
|
|
1328
|
+
sage: G[0]
|
|
1329
|
+
[1 0 0]
|
|
1330
|
+
[0 0 0]
|
|
1331
|
+
[0 0 0]
|
|
1332
|
+
sage: G[5]
|
|
1333
|
+
[ 0 j 0]
|
|
1334
|
+
[-j 0 0]
|
|
1335
|
+
[ 0 0 0]
|
|
1336
|
+
sage: G[22]
|
|
1337
|
+
[ 0 0 0]
|
|
1338
|
+
[ 0 0 k]
|
|
1339
|
+
[ 0 -k 0]
|
|
1340
|
+
"""
|
|
1341
|
+
return tuple(self.algebra_generators())
|
|
1342
|
+
|
|
1343
|
+
@cached_method
|
|
1344
|
+
def zero(self):
|
|
1345
|
+
r"""
|
|
1346
|
+
Return the additive identity.
|
|
1347
|
+
|
|
1348
|
+
EXAMPLES::
|
|
1349
|
+
|
|
1350
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1351
|
+
sage: J = JordanAlgebra(O)
|
|
1352
|
+
sage: J.zero()
|
|
1353
|
+
[0 0 0]
|
|
1354
|
+
[0 0 0]
|
|
1355
|
+
[0 0 0]
|
|
1356
|
+
"""
|
|
1357
|
+
Rz = self.base_ring().zero()
|
|
1358
|
+
Oz = self._O.zero()
|
|
1359
|
+
return self.element_class(self, (Rz, Rz, Rz, Oz, Oz, Oz))
|
|
1360
|
+
|
|
1361
|
+
@cached_method
|
|
1362
|
+
def one(self):
|
|
1363
|
+
r"""
|
|
1364
|
+
Return multiplicative identity.
|
|
1365
|
+
|
|
1366
|
+
EXAMPLES::
|
|
1367
|
+
|
|
1368
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1369
|
+
sage: J = JordanAlgebra(O)
|
|
1370
|
+
sage: J.one()
|
|
1371
|
+
[1 0 0]
|
|
1372
|
+
[0 1 0]
|
|
1373
|
+
[0 0 1]
|
|
1374
|
+
sage: all(J.one() * b == b for b in J.basis())
|
|
1375
|
+
True
|
|
1376
|
+
"""
|
|
1377
|
+
one = self.base_ring().one()
|
|
1378
|
+
zero = self._O.zero()
|
|
1379
|
+
return self.element_class(self, (one, one, one, zero, zero, zero))
|
|
1380
|
+
|
|
1381
|
+
def some_elements(self):
|
|
1382
|
+
r"""
|
|
1383
|
+
Return some elements of ``self``.
|
|
1384
|
+
|
|
1385
|
+
EXAMPLES::
|
|
1386
|
+
|
|
1387
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1388
|
+
sage: J = JordanAlgebra(O)
|
|
1389
|
+
sage: J.some_elements()
|
|
1390
|
+
[[6/5 0 0]
|
|
1391
|
+
[ 0 6/5 0]
|
|
1392
|
+
[ 0 0 6/5],
|
|
1393
|
+
[1 0 0]
|
|
1394
|
+
[0 1 0]
|
|
1395
|
+
[0 0 1],
|
|
1396
|
+
[0 0 0]
|
|
1397
|
+
[0 0 0]
|
|
1398
|
+
[0 0 0],
|
|
1399
|
+
[0 0 0]
|
|
1400
|
+
[0 1 0]
|
|
1401
|
+
[0 0 0],
|
|
1402
|
+
[ 0 j 0]
|
|
1403
|
+
[-j 0 0]
|
|
1404
|
+
[ 0 0 0],
|
|
1405
|
+
[ 0 0 lj]
|
|
1406
|
+
[ 0 0 0]
|
|
1407
|
+
[-lj 0 0],
|
|
1408
|
+
[ 0 0 0]
|
|
1409
|
+
[ 0 1 1/2*lj]
|
|
1410
|
+
[ 0 -1/2*lj 0],
|
|
1411
|
+
[ 1 0 j + 2*li]
|
|
1412
|
+
[ 0 1 0]
|
|
1413
|
+
[-j - 2*li 0 1],
|
|
1414
|
+
[ 1 j + lk l]
|
|
1415
|
+
[-j - lk 0 i + lj]
|
|
1416
|
+
[ -l -i - lj 0],
|
|
1417
|
+
[ 1 3/2*l 2*k]
|
|
1418
|
+
[-3/2*l 0 5/2*j]
|
|
1419
|
+
[ -2*k -5/2*j 0]]
|
|
1420
|
+
|
|
1421
|
+
sage: O = OctonionAlgebra(GF(3))
|
|
1422
|
+
sage: J = JordanAlgebra(O)
|
|
1423
|
+
sage: J.some_elements()
|
|
1424
|
+
[[-1 0 0]
|
|
1425
|
+
[ 0 -1 0]
|
|
1426
|
+
[ 0 0 -1],
|
|
1427
|
+
[1 0 0]
|
|
1428
|
+
[0 1 0]
|
|
1429
|
+
[0 0 1],
|
|
1430
|
+
[0 0 0]
|
|
1431
|
+
[0 0 0]
|
|
1432
|
+
[0 0 0],
|
|
1433
|
+
[0 0 0]
|
|
1434
|
+
[0 1 0]
|
|
1435
|
+
[0 0 0],
|
|
1436
|
+
[ 0 j 0]
|
|
1437
|
+
[-j 0 0]
|
|
1438
|
+
[ 0 0 0],
|
|
1439
|
+
[ 0 0 lj]
|
|
1440
|
+
[ 0 0 0]
|
|
1441
|
+
[-lj 0 0],
|
|
1442
|
+
[ 0 0 0]
|
|
1443
|
+
[ 0 1 -lj]
|
|
1444
|
+
[ 0 lj 0],
|
|
1445
|
+
[ 1 0 j - li]
|
|
1446
|
+
[ 0 1 0]
|
|
1447
|
+
[-j + li 0 1],
|
|
1448
|
+
[ 1 j + lk l]
|
|
1449
|
+
[-j - lk 0 i + lj]
|
|
1450
|
+
[ -l -i - lj 0],
|
|
1451
|
+
[ 1 0 -k]
|
|
1452
|
+
[ 0 0 j]
|
|
1453
|
+
[ k -j 0]]
|
|
1454
|
+
"""
|
|
1455
|
+
B = self.basis()
|
|
1456
|
+
S = [self.an_element(), self.one(), self.zero(),
|
|
1457
|
+
B[1], B[5], B[17], B[1] + self._half*B[25],
|
|
1458
|
+
self.one() + B[13] + 2*B[16]]
|
|
1459
|
+
S.append(sum(B[::5]))
|
|
1460
|
+
S.append(sum(self._half * ind * b for ind, b in enumerate(B[::7], start=2)))
|
|
1461
|
+
return S
|
|
1462
|
+
|
|
1463
|
+
class Element(AlgebraElement):
|
|
1464
|
+
r"""
|
|
1465
|
+
An element of an exceptional Jordan algebra.
|
|
1466
|
+
"""
|
|
1467
|
+
def __init__(self, parent, data):
|
|
1468
|
+
"""
|
|
1469
|
+
Initialize ``self``.
|
|
1470
|
+
|
|
1471
|
+
TESTS::
|
|
1472
|
+
|
|
1473
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1474
|
+
sage: J = JordanAlgebra(O)
|
|
1475
|
+
sage: elt = sum(J.basis())
|
|
1476
|
+
sage: TestSuite(elt).run()
|
|
1477
|
+
"""
|
|
1478
|
+
self._data = tuple(data)
|
|
1479
|
+
AlgebraElement.__init__(self, parent)
|
|
1480
|
+
|
|
1481
|
+
def _to_print_matrix(self):
|
|
1482
|
+
r"""
|
|
1483
|
+
Return ``self`` as a matrix for printing.
|
|
1484
|
+
|
|
1485
|
+
EXAMPLES::
|
|
1486
|
+
|
|
1487
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1488
|
+
sage: J = JordanAlgebra(O)
|
|
1489
|
+
sage: elt = J([2, 3, 0, -1 + O.basis()[2], O.basis()[3], -O.basis()[5] + 5*O.basis()[7]])
|
|
1490
|
+
sage: elt._to_print_matrix()
|
|
1491
|
+
[ 2 j - 1 k]
|
|
1492
|
+
[ -j - 1 3 -li + 5*lk]
|
|
1493
|
+
[ -k li - 5*lk 0]
|
|
1494
|
+
"""
|
|
1495
|
+
PR = self.parent()._repr_poly_ring
|
|
1496
|
+
gens = [PR.one()] + list(PR.gens())
|
|
1497
|
+
data = [PR(self._data[i]) for i in range(3)]
|
|
1498
|
+
data.extend(PR.sum(c * g for c, g in zip(self._data[3+i].vector(), gens))
|
|
1499
|
+
for i in range(3))
|
|
1500
|
+
# add the conjugates
|
|
1501
|
+
for i in range(1, 8):
|
|
1502
|
+
gens[i] = -gens[i]
|
|
1503
|
+
data.extend(PR.sum(c * g for c, g in zip(self._data[3+i].vector(), gens))
|
|
1504
|
+
for i in range(3))
|
|
1505
|
+
return matrix(PR, [[data[0], data[3], data[4]], [data[6], data[1], data[5]], [data[7], data[8], data[2]]])
|
|
1506
|
+
|
|
1507
|
+
def _repr_(self):
|
|
1508
|
+
r"""
|
|
1509
|
+
Return a string representation of ``self``.
|
|
1510
|
+
|
|
1511
|
+
EXAMPLES::
|
|
1512
|
+
|
|
1513
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1514
|
+
sage: J = JordanAlgebra(O)
|
|
1515
|
+
sage: J.an_element()
|
|
1516
|
+
[6/5 0 0]
|
|
1517
|
+
[ 0 6/5 0]
|
|
1518
|
+
[ 0 0 6/5]
|
|
1519
|
+
"""
|
|
1520
|
+
return repr(self._to_print_matrix())
|
|
1521
|
+
|
|
1522
|
+
def _latex_(self):
|
|
1523
|
+
r"""
|
|
1524
|
+
Return a latex representation of ``self``.
|
|
1525
|
+
|
|
1526
|
+
EXAMPLES::
|
|
1527
|
+
|
|
1528
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1529
|
+
sage: J = JordanAlgebra(O)
|
|
1530
|
+
sage: latex(J.an_element())
|
|
1531
|
+
\left(\begin{array}{rrr}
|
|
1532
|
+
\frac{6}{5} & 0 & 0 \\
|
|
1533
|
+
0 & \frac{6}{5} & 0 \\
|
|
1534
|
+
0 & 0 & \frac{6}{5}
|
|
1535
|
+
\end{array}\right)
|
|
1536
|
+
"""
|
|
1537
|
+
from sage.misc.latex import latex
|
|
1538
|
+
return latex(self._to_print_matrix())
|
|
1539
|
+
|
|
1540
|
+
def _ascii_art_(self):
|
|
1541
|
+
r"""
|
|
1542
|
+
Return an ascii art representation of ``self``.
|
|
1543
|
+
|
|
1544
|
+
EXAMPLES::
|
|
1545
|
+
|
|
1546
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1547
|
+
sage: J = JordanAlgebra(O)
|
|
1548
|
+
sage: ascii_art(J.an_element())
|
|
1549
|
+
[6/5 0 0]
|
|
1550
|
+
[ 0 6/5 0]
|
|
1551
|
+
[ 0 0 6/5]
|
|
1552
|
+
"""
|
|
1553
|
+
from sage.typeset.ascii_art import ascii_art
|
|
1554
|
+
return ascii_art(self._to_print_matrix())
|
|
1555
|
+
|
|
1556
|
+
def _unicode_art_(self):
|
|
1557
|
+
r"""
|
|
1558
|
+
Return a unicode art representation of ``self``.
|
|
1559
|
+
|
|
1560
|
+
EXAMPLES::
|
|
1561
|
+
|
|
1562
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1563
|
+
sage: J = JordanAlgebra(O)
|
|
1564
|
+
sage: unicode_art(J.an_element())
|
|
1565
|
+
⎛6/5 0 0⎞
|
|
1566
|
+
⎜ 0 6/5 0⎟
|
|
1567
|
+
⎝ 0 0 6/5⎠
|
|
1568
|
+
"""
|
|
1569
|
+
from sage.typeset.unicode_art import unicode_art
|
|
1570
|
+
return unicode_art(self._to_print_matrix())
|
|
1571
|
+
|
|
1572
|
+
def __bool__(self) -> bool:
|
|
1573
|
+
"""
|
|
1574
|
+
Return if ``self`` is nonzero.
|
|
1575
|
+
|
|
1576
|
+
TESTS::
|
|
1577
|
+
|
|
1578
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1579
|
+
sage: J = JordanAlgebra(O)
|
|
1580
|
+
sage: all(bool(b) for b in J.basis())
|
|
1581
|
+
True
|
|
1582
|
+
sage: bool(J.zero())
|
|
1583
|
+
False
|
|
1584
|
+
"""
|
|
1585
|
+
return any(d for d in self._data)
|
|
1586
|
+
|
|
1587
|
+
def _richcmp_(self, other, op):
|
|
1588
|
+
r"""
|
|
1589
|
+
Rich comparison of ``self`` with ``other`` by ``op``.
|
|
1590
|
+
|
|
1591
|
+
EXAMPLES::
|
|
1592
|
+
|
|
1593
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1594
|
+
sage: J = JordanAlgebra(O)
|
|
1595
|
+
sage: x = sum(J.basis()[::6])
|
|
1596
|
+
sage: y = sum(J.basis()[::5])
|
|
1597
|
+
sage: x == x
|
|
1598
|
+
True
|
|
1599
|
+
sage: x == y
|
|
1600
|
+
False
|
|
1601
|
+
sage: x < y
|
|
1602
|
+
True
|
|
1603
|
+
sage: x != J.zero()
|
|
1604
|
+
True
|
|
1605
|
+
"""
|
|
1606
|
+
return richcmp(self._data, other._data, op)
|
|
1607
|
+
|
|
1608
|
+
def _add_(self, other):
|
|
1609
|
+
"""
|
|
1610
|
+
Add ``self`` and ``other``.
|
|
1611
|
+
|
|
1612
|
+
EXAMPLES::
|
|
1613
|
+
|
|
1614
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1615
|
+
sage: J = JordanAlgebra(O)
|
|
1616
|
+
sage: x = sum(J.basis()[::6])
|
|
1617
|
+
sage: y = sum(J.basis()[::5])
|
|
1618
|
+
sage: x + x
|
|
1619
|
+
[ 2 2*k 2*i + 2*lk]
|
|
1620
|
+
[ -2*k 0 2*li]
|
|
1621
|
+
[-2*i - 2*lk -2*li 0]
|
|
1622
|
+
sage: x + y
|
|
1623
|
+
[ 2 j + k + lk i + l + lk]
|
|
1624
|
+
[ -j - k - lk 0 i + li + lj]
|
|
1625
|
+
[ -i - l - lk -i - li - lj 0]
|
|
1626
|
+
"""
|
|
1627
|
+
return self.__class__(self.parent(), [a + b for a, b in zip(self._data, other._data)])
|
|
1628
|
+
|
|
1629
|
+
def _neg_(self):
|
|
1630
|
+
"""
|
|
1631
|
+
Negate ``self``.
|
|
1632
|
+
|
|
1633
|
+
EXAMPLES::
|
|
1634
|
+
|
|
1635
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1636
|
+
sage: J = JordanAlgebra(O)
|
|
1637
|
+
sage: x = sum(J.basis()[::6])
|
|
1638
|
+
sage: -x
|
|
1639
|
+
[ -1 -k -i - lk]
|
|
1640
|
+
[ k 0 -li]
|
|
1641
|
+
[ i + lk li 0]
|
|
1642
|
+
"""
|
|
1643
|
+
return self.__class__(self.parent(), [-c for c in self._data])
|
|
1644
|
+
|
|
1645
|
+
def _sub_(self, other):
|
|
1646
|
+
r"""
|
|
1647
|
+
Subtract ``other`` from ``self``.
|
|
1648
|
+
|
|
1649
|
+
EXAMPLES::
|
|
1650
|
+
|
|
1651
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1652
|
+
sage: J = JordanAlgebra(O)
|
|
1653
|
+
sage: x = sum(J.basis()[::6])
|
|
1654
|
+
sage: y = sum(J.basis()[::5])
|
|
1655
|
+
sage: x - x
|
|
1656
|
+
[0 0 0]
|
|
1657
|
+
[0 0 0]
|
|
1658
|
+
[0 0 0]
|
|
1659
|
+
sage: x - y
|
|
1660
|
+
[ 0 -j + k - lk i - l + lk]
|
|
1661
|
+
[ j - k + lk 0 -i + li - lj]
|
|
1662
|
+
[ -i + l - lk i - li + lj 0]
|
|
1663
|
+
"""
|
|
1664
|
+
return self.__class__(self.parent(), [a - b for a, b in zip(self._data, other._data)])
|
|
1665
|
+
|
|
1666
|
+
def _mul_(self, other):
|
|
1667
|
+
"""
|
|
1668
|
+
Multiply ``self`` and ``other``.
|
|
1669
|
+
|
|
1670
|
+
EXAMPLES::
|
|
1671
|
+
|
|
1672
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1673
|
+
sage: J = JordanAlgebra(O)
|
|
1674
|
+
sage: x = sum(J.basis()[::7])
|
|
1675
|
+
sage: y = sum(J.basis()[::11])
|
|
1676
|
+
sage: x * y
|
|
1677
|
+
[ 1 -1/2*j + 1/2*l + 1/2 1/2*k + 1/2*lk + 1/2]
|
|
1678
|
+
[ 1/2*j - 1/2*l + 1/2 0 -1/2*l]
|
|
1679
|
+
[-1/2*k - 1/2*lk + 1/2 1/2*l 0]
|
|
1680
|
+
"""
|
|
1681
|
+
P = self.parent()
|
|
1682
|
+
SD = self._data
|
|
1683
|
+
OD = other._data
|
|
1684
|
+
X = [[SD[0], SD[3], SD[4]],
|
|
1685
|
+
[SD[3].conjugate(), SD[1], SD[5]],
|
|
1686
|
+
[SD[4].conjugate(), SD[5].conjugate(), SD[2]]]
|
|
1687
|
+
Y = [[OD[0], OD[3], OD[4]],
|
|
1688
|
+
[OD[3].conjugate(), OD[1], OD[5]],
|
|
1689
|
+
[OD[4].conjugate(), OD[5].conjugate(), OD[2]]]
|
|
1690
|
+
# we do a simplified multiplication for the diagonal entries since
|
|
1691
|
+
# we have, e.g., \alpha * \alpha' + (x (x')^* + x' x^* + y (y')^* + y' y^*) / 2
|
|
1692
|
+
ret = [X[0][0] * Y[0][0] + (X[0][1] * Y[1][0]).real_part() + (X[0][2] * Y[2][0]).real_part(),
|
|
1693
|
+
X[1][1] * Y[1][1] + (X[1][0] * Y[0][1]).real_part() + (X[1][2] * Y[2][1]).real_part(),
|
|
1694
|
+
X[2][2] * Y[2][2] + (X[2][0] * Y[0][2]).real_part() + (X[2][1] * Y[1][2]).real_part()]
|
|
1695
|
+
ret += [sum(X[r][i] * Y[i][c] + Y[r][i] * X[i][c] for i in range(3)) * P._half
|
|
1696
|
+
for r, c in [(0, 1), (0, 2), (1, 2)]]
|
|
1697
|
+
return self.__class__(P, ret)
|
|
1698
|
+
|
|
1699
|
+
def _lmul_(self, other):
|
|
1700
|
+
r"""
|
|
1701
|
+
Multiply ``self`` by the scalar ``other`` on the left.
|
|
1702
|
+
|
|
1703
|
+
EXAMPLES::
|
|
1704
|
+
|
|
1705
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1706
|
+
sage: J = JordanAlgebra(O)
|
|
1707
|
+
sage: elt = sum(2 * b for b in J.basis()[::6]); elt
|
|
1708
|
+
[ 2 2*k 2*i + 2*lk]
|
|
1709
|
+
[ -2*k 0 2*li]
|
|
1710
|
+
[-2*i - 2*lk -2*li 0]
|
|
1711
|
+
sage: elt * 2
|
|
1712
|
+
[ 4 4*k 4*i + 4*lk]
|
|
1713
|
+
[ -4*k 0 4*li]
|
|
1714
|
+
[-4*i - 4*lk -4*li 0]
|
|
1715
|
+
"""
|
|
1716
|
+
return self.__class__(self.parent(), [c * other for c in self._data])
|
|
1717
|
+
|
|
1718
|
+
def _rmul_(self, other):
|
|
1719
|
+
r"""
|
|
1720
|
+
Multiply ``self`` with the scalar ``other`` by the right
|
|
1721
|
+
action.
|
|
1722
|
+
|
|
1723
|
+
EXAMPLES::
|
|
1724
|
+
|
|
1725
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1726
|
+
sage: J = JordanAlgebra(O)
|
|
1727
|
+
sage: elt = sum(b * 2 for b in J.basis()[::6]); elt
|
|
1728
|
+
[ 2 2*k 2*i + 2*lk]
|
|
1729
|
+
[ -2*k 0 2*li]
|
|
1730
|
+
[-2*i - 2*lk -2*li 0]
|
|
1731
|
+
sage: (1/2) * elt
|
|
1732
|
+
[ 1 k i + lk]
|
|
1733
|
+
[ -k 0 li]
|
|
1734
|
+
[-i - lk -li 0]
|
|
1735
|
+
"""
|
|
1736
|
+
return self.__class__(self.parent(), [other * c for c in self._data])
|
|
1737
|
+
|
|
1738
|
+
def monomial_coefficients(self, copy=True):
|
|
1739
|
+
r"""
|
|
1740
|
+
Return a dictionary whose keys are indices of basis elements in
|
|
1741
|
+
the support of ``self`` and whose values are the corresponding
|
|
1742
|
+
coefficients.
|
|
1743
|
+
|
|
1744
|
+
INPUT:
|
|
1745
|
+
|
|
1746
|
+
- ``copy`` -- ignored
|
|
1747
|
+
|
|
1748
|
+
EXAMPLES::
|
|
1749
|
+
|
|
1750
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1751
|
+
sage: J = JordanAlgebra(O)
|
|
1752
|
+
sage: elt = sum(~QQ(ind) * b for ind, b in enumerate(J.basis()[::6], start=1)); elt
|
|
1753
|
+
[ 1 1/2*k 1/3*i + 1/4*lk]
|
|
1754
|
+
[ -1/2*k 0 1/5*li]
|
|
1755
|
+
[-1/3*i - 1/4*lk -1/5*li 0]
|
|
1756
|
+
sage: elt.monomial_coefficients()
|
|
1757
|
+
{0: 1, 6: 1/2, 12: 1/3, 18: 1/4, 24: 1/5}
|
|
1758
|
+
|
|
1759
|
+
TESTS::
|
|
1760
|
+
|
|
1761
|
+
sage: O = OctonionAlgebra(QQ)
|
|
1762
|
+
sage: J = JordanAlgebra(O)
|
|
1763
|
+
sage: all(b.monomial_coefficients() == {i: 1} for i,b in enumerate(J.basis()))
|
|
1764
|
+
True
|
|
1765
|
+
"""
|
|
1766
|
+
ret = {}
|
|
1767
|
+
for i in range(3):
|
|
1768
|
+
if self._data[i]:
|
|
1769
|
+
ret[i] = self._data[i]
|
|
1770
|
+
mc = self._data[3+i].monomial_coefficients()
|
|
1771
|
+
for k, coeff in mc.items():
|
|
1772
|
+
ret[3+i*8+k] = coeff
|
|
1773
|
+
return ret
|