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,959 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.libs.singular sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Quantum Clifford Algebras
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- Travis Scrimshaw (2021-05): initial version
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
#*****************************************************************************
|
|
12
|
+
# Copyright (C) 2021 Travis Scrimshaw <tcscrims at gmail.com>
|
|
13
|
+
#
|
|
14
|
+
# This program is free software: you can redistribute it and/or modify
|
|
15
|
+
# it under the terms of the GNU General Public License as published by
|
|
16
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
17
|
+
# (at your option) any later version.
|
|
18
|
+
# https://www.gnu.org/licenses/
|
|
19
|
+
#*****************************************************************************
|
|
20
|
+
|
|
21
|
+
from sage.misc.cachefunc import cached_method
|
|
22
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
23
|
+
from sage.rings.integer_ring import ZZ
|
|
24
|
+
from sage.categories.algebras import Algebras
|
|
25
|
+
from sage.categories.fields import Fields
|
|
26
|
+
from sage.combinat.free_module import CombinatorialFreeModule
|
|
27
|
+
from sage.categories.cartesian_product import cartesian_product
|
|
28
|
+
from sage.sets.family import Family
|
|
29
|
+
from sage.rings.fraction_field import FractionField
|
|
30
|
+
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
|
|
31
|
+
from itertools import product
|
|
32
|
+
from sage.combinat.subset import powerset
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class QuantumCliffordAlgebra(CombinatorialFreeModule):
|
|
36
|
+
r"""
|
|
37
|
+
The quantum Clifford algebra.
|
|
38
|
+
|
|
39
|
+
The *quantum Clifford algebra*, or `q`-Clifford algebra,
|
|
40
|
+
of rank `n` and twist `k` is the unital associative algebra
|
|
41
|
+
`\mathrm{Cl}_{q}(n, k)` over a field `F` with generators
|
|
42
|
+
`\psi_a, \psi_a^*, \omega_a` for `a = 1, \ldots, n` that
|
|
43
|
+
satisfy the following relations:
|
|
44
|
+
|
|
45
|
+
.. MATH::
|
|
46
|
+
|
|
47
|
+
\begin{aligned}
|
|
48
|
+
\omega_a \omega_b & = \omega_b \omega_a,
|
|
49
|
+
& \omega_a^{4k} & = (1 + q^{-2k}) \omega_a^{2k} - q^{-2k},
|
|
50
|
+
\\ \omega_a \psi_b & = q^{\delta_{ab}} \psi_b \omega_a,
|
|
51
|
+
& \omega_a \psi^*_b & = \psi^*_b \omega_a,
|
|
52
|
+
\\ \psi_a \psi_b & + \psi_b \psi_a = 0,
|
|
53
|
+
& \psi^*_a \psi^*_b & + \psi^*_b \psi^*_a = 0,
|
|
54
|
+
\\ \psi_a \psi^*_a & + q^k \psi^*_a \psi_a = \omega_a^{-k},
|
|
55
|
+
& \psi^*_a \psi_a & + q^{-k} \psi^*_a \psi_a = \omega_a^k,
|
|
56
|
+
\\ \psi_a \psi^*_b & + \psi_b^* \psi_a = 0
|
|
57
|
+
& & \text{if } a \neq b.
|
|
58
|
+
\end{aligned}
|
|
59
|
+
|
|
60
|
+
When `k = 2`, we recover the original definition given by Hayashi in
|
|
61
|
+
[Hayashi1990]_. The `k = 1` version was used in [Kwon2014]_.
|
|
62
|
+
|
|
63
|
+
INPUT:
|
|
64
|
+
|
|
65
|
+
- ``n`` -- positive integer; the rank
|
|
66
|
+
- ``k`` -- positive integer (default: 1); the twist
|
|
67
|
+
- ``q`` -- (optional) the parameter `q`
|
|
68
|
+
- ``F`` -- (default: `\QQ(q)`) the base field that contains ``q``
|
|
69
|
+
|
|
70
|
+
EXAMPLES:
|
|
71
|
+
|
|
72
|
+
We construct the rank 3 and twist 1 `q`-Clifford algebra::
|
|
73
|
+
|
|
74
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
75
|
+
sage: Cl
|
|
76
|
+
Quantum Clifford algebra of rank 3 and twist 1 with q=q over
|
|
77
|
+
Fraction Field of Univariate Polynomial Ring in q over Integer Ring
|
|
78
|
+
sage: q = Cl.q()
|
|
79
|
+
|
|
80
|
+
Some sample computations::
|
|
81
|
+
|
|
82
|
+
sage: p0, p1, p2, d0, d1, d2, w0, w1, w2 = Cl.gens()
|
|
83
|
+
sage: p0 * p1
|
|
84
|
+
psi0*psi1
|
|
85
|
+
sage: p1 * p0
|
|
86
|
+
-psi0*psi1
|
|
87
|
+
sage: p0 * w0 * p1 * d0 * w2
|
|
88
|
+
(1/(q^3-q))*psi1*w2 + (-q/(q^2-1))*psi1*w0^2*w2
|
|
89
|
+
sage: w0^4
|
|
90
|
+
-1/q^2 + ((q^2+1)/q^2)*w0^2
|
|
91
|
+
|
|
92
|
+
We construct the homomorphism from `U_q(\mathfrak{sl}_3)` to
|
|
93
|
+
`\mathrm{Cl}(3, 1)` given in (3.17) of [Hayashi1990]_::
|
|
94
|
+
|
|
95
|
+
sage: e1 = p0*d1; e2 = p1*d2
|
|
96
|
+
sage: f1 = p1*d0; f2 = p2*d1
|
|
97
|
+
sage: k1 = w0*~w1; k2 = w1*~w2
|
|
98
|
+
sage: k1i = w1*~w0; k2i = w2*~w1
|
|
99
|
+
sage: (e1, e2, f1, f2, k1, k2, k1i, k2i)
|
|
100
|
+
(psi0*psid1, psi1*psid2,
|
|
101
|
+
-psid0*psi1, -psid1*psi2,
|
|
102
|
+
(q^2+1)*w0*w1 - q^2*w0*w1^3, (q^2+1)*w1*w2 - q^2*w1*w2^3,
|
|
103
|
+
(q^2+1)*w0*w1 - q^2*w0^3*w1, (q^2+1)*w1*w2 - q^2*w1^3*w2)
|
|
104
|
+
|
|
105
|
+
We check that `k_i` and `k_i^{-1}` are inverses::
|
|
106
|
+
|
|
107
|
+
sage: k1 * k1i
|
|
108
|
+
1
|
|
109
|
+
sage: k2 * k2i
|
|
110
|
+
1
|
|
111
|
+
|
|
112
|
+
The relations between `e_i`, `f_i`, and `k_i`::
|
|
113
|
+
|
|
114
|
+
sage: k1 * f1 == q^-2 * f1 * k1
|
|
115
|
+
True
|
|
116
|
+
sage: k2 * f1 == q^1 * f1 * k2
|
|
117
|
+
True
|
|
118
|
+
sage: k2 * e1 == q^-1 * e1 * k2
|
|
119
|
+
True
|
|
120
|
+
sage: k1 * e1 == q^2 * e1 * k1
|
|
121
|
+
True
|
|
122
|
+
sage: e1 * f1 - f1 * e1 == (k1 - k1i)/(q-q^-1)
|
|
123
|
+
True
|
|
124
|
+
sage: e2 * f1 - f1 * e2
|
|
125
|
+
0
|
|
126
|
+
|
|
127
|
+
The `q`-Serre relations::
|
|
128
|
+
|
|
129
|
+
sage: e1 * e1 * e2 - (q^1 + q^-1) * e1 * e2 * e1 + e2 * e1 * e1
|
|
130
|
+
0
|
|
131
|
+
sage: f1 * f1 * f2 - (q^1 + q^-1) * f1 * f2 * f1 + f2 * f1 * f1
|
|
132
|
+
0
|
|
133
|
+
|
|
134
|
+
This also can be constructed at the special point when `q^{2k} = 1`,
|
|
135
|
+
but the basis used is different::
|
|
136
|
+
|
|
137
|
+
sage: Cl = algebras.QuantumClifford(1, 1, -1)
|
|
138
|
+
sage: Cl.inject_variables()
|
|
139
|
+
Defining psi0, psid0, w0
|
|
140
|
+
sage: psi0 * psid0
|
|
141
|
+
psi0*psid0
|
|
142
|
+
sage: psid0 * psi0
|
|
143
|
+
-w0 + psi0*psid0
|
|
144
|
+
sage: w0^2
|
|
145
|
+
1
|
|
146
|
+
"""
|
|
147
|
+
@staticmethod
|
|
148
|
+
def __classcall_private__(cls, n, k=1, q=None, F=None):
|
|
149
|
+
r"""
|
|
150
|
+
Standardize input to ensure a unique representation.
|
|
151
|
+
|
|
152
|
+
TESTS::
|
|
153
|
+
|
|
154
|
+
sage: Cl1 = algebras.QuantumClifford(3)
|
|
155
|
+
sage: q = PolynomialRing(ZZ, 'q').fraction_field().gen()
|
|
156
|
+
sage: Cl2 = algebras.QuantumClifford(3, q=q)
|
|
157
|
+
sage: Cl3 = algebras.QuantumClifford(3, 1, q, q.parent())
|
|
158
|
+
sage: Cl1 is Cl2 and Cl2 is Cl3
|
|
159
|
+
True
|
|
160
|
+
"""
|
|
161
|
+
if q is None:
|
|
162
|
+
q = PolynomialRing(ZZ, 'q').fraction_field().gen()
|
|
163
|
+
if F is None:
|
|
164
|
+
F = q.parent()
|
|
165
|
+
q = F(q)
|
|
166
|
+
if F not in Fields():
|
|
167
|
+
F = FractionField(F)
|
|
168
|
+
q = F(q)
|
|
169
|
+
|
|
170
|
+
if bool(q**(2*k) == 1):
|
|
171
|
+
return QuantumCliffordAlgebraRootUnity(n, k, q, F)
|
|
172
|
+
return QuantumCliffordAlgebraGeneric(n, k, q, F)
|
|
173
|
+
|
|
174
|
+
def __init__(self, n, k, q, F, psi, indices):
|
|
175
|
+
r"""
|
|
176
|
+
Initialize ``self``.
|
|
177
|
+
|
|
178
|
+
EXAMPLES::
|
|
179
|
+
|
|
180
|
+
sage: Cl = algebras.QuantumClifford(1, 2)
|
|
181
|
+
sage: TestSuite(Cl).run(elements=Cl.basis())
|
|
182
|
+
"""
|
|
183
|
+
self._n = n
|
|
184
|
+
self._k = k
|
|
185
|
+
self._q = q
|
|
186
|
+
self._w_poly = PolynomialRing(F, n, 'w')
|
|
187
|
+
self._psi = psi
|
|
188
|
+
indices = FiniteEnumeratedSet(indices)
|
|
189
|
+
|
|
190
|
+
cat = Algebras(F).FiniteDimensional().Semisimple().WithBasis()
|
|
191
|
+
CombinatorialFreeModule.__init__(self, F, indices, category=cat)
|
|
192
|
+
self._assign_names(self.algebra_generators().keys())
|
|
193
|
+
|
|
194
|
+
def _repr_(self):
|
|
195
|
+
r"""
|
|
196
|
+
Return a string representation of ``self``.
|
|
197
|
+
|
|
198
|
+
EXAMPLES::
|
|
199
|
+
|
|
200
|
+
sage: algebras.QuantumClifford(3)
|
|
201
|
+
Quantum Clifford algebra of rank 3 and twist 1 with q=q over
|
|
202
|
+
Fraction Field of Univariate Polynomial Ring in q over Integer Ring
|
|
203
|
+
"""
|
|
204
|
+
return "Quantum Clifford algebra of rank {} and twist {} with q={} over {}".format(
|
|
205
|
+
self._n, self._k, self._q, self.base_ring())
|
|
206
|
+
|
|
207
|
+
def _latex_(self):
|
|
208
|
+
r"""
|
|
209
|
+
Return a latex representation of ``self``.
|
|
210
|
+
|
|
211
|
+
EXAMPLES::
|
|
212
|
+
|
|
213
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
214
|
+
sage: latex(Cl)
|
|
215
|
+
\operatorname{Cl}_{q}(3, 1)
|
|
216
|
+
"""
|
|
217
|
+
return "\\operatorname{Cl}_{%s}(%s, %s)" % (self._q, self._n, self._k)
|
|
218
|
+
|
|
219
|
+
def q(self):
|
|
220
|
+
r"""
|
|
221
|
+
Return the `q` of ``self``.
|
|
222
|
+
|
|
223
|
+
EXAMPLES::
|
|
224
|
+
|
|
225
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
226
|
+
sage: Cl.q()
|
|
227
|
+
q
|
|
228
|
+
|
|
229
|
+
sage: Cl = algebras.QuantumClifford(3, q=QQ(-5))
|
|
230
|
+
sage: Cl.q()
|
|
231
|
+
-5
|
|
232
|
+
"""
|
|
233
|
+
return self._q
|
|
234
|
+
|
|
235
|
+
def twist(self):
|
|
236
|
+
r"""
|
|
237
|
+
Return the twist `k` of ``self``.
|
|
238
|
+
|
|
239
|
+
EXAMPLES::
|
|
240
|
+
|
|
241
|
+
sage: Cl = algebras.QuantumClifford(3, 2)
|
|
242
|
+
sage: Cl.twist()
|
|
243
|
+
2
|
|
244
|
+
"""
|
|
245
|
+
return self._k
|
|
246
|
+
|
|
247
|
+
def rank(self):
|
|
248
|
+
r"""
|
|
249
|
+
Return the rank `k` of ``self``.
|
|
250
|
+
|
|
251
|
+
EXAMPLES::
|
|
252
|
+
|
|
253
|
+
sage: Cl = algebras.QuantumClifford(3, 2)
|
|
254
|
+
sage: Cl.rank()
|
|
255
|
+
3
|
|
256
|
+
"""
|
|
257
|
+
return self._n
|
|
258
|
+
|
|
259
|
+
def dimension(self):
|
|
260
|
+
r"""
|
|
261
|
+
Return the dimension of ``self``.
|
|
262
|
+
|
|
263
|
+
EXAMPLES::
|
|
264
|
+
|
|
265
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
266
|
+
sage: Cl.dimension()
|
|
267
|
+
512
|
|
268
|
+
|
|
269
|
+
sage: Cl = algebras.QuantumClifford(4, 2) # long time
|
|
270
|
+
sage: Cl.dimension() # long time
|
|
271
|
+
65536
|
|
272
|
+
"""
|
|
273
|
+
return ZZ(8*self._k) ** self._n
|
|
274
|
+
|
|
275
|
+
@cached_method
|
|
276
|
+
def algebra_generators(self):
|
|
277
|
+
r"""
|
|
278
|
+
Return the algebra generators of ``self``.
|
|
279
|
+
|
|
280
|
+
EXAMPLES::
|
|
281
|
+
|
|
282
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
283
|
+
sage: Cl.algebra_generators()
|
|
284
|
+
Finite family {'psi0': psi0, 'psi1': psi1, 'psi2': psi2,
|
|
285
|
+
'psid0': psid0, 'psid1': psid1, 'psid2': psid2,
|
|
286
|
+
'w0': w0, 'w1': w1, 'w2': w2}
|
|
287
|
+
"""
|
|
288
|
+
one = (0,) * self._n # one in the corresponding free abelian group
|
|
289
|
+
zero = [0] * self._n
|
|
290
|
+
d = {}
|
|
291
|
+
for i in range(self._n):
|
|
292
|
+
r = list(zero) # Make a copy
|
|
293
|
+
r[i] = 1
|
|
294
|
+
d['psi%s' % i] = self.monomial((self._psi(r), one))
|
|
295
|
+
r[i] = -1
|
|
296
|
+
d['psid%s' % i] = self.monomial((self._psi(r), one))
|
|
297
|
+
zero = self._psi(zero)
|
|
298
|
+
for i in range(self._n):
|
|
299
|
+
temp = list(zero) # Make a copy
|
|
300
|
+
temp[i] = 1
|
|
301
|
+
d['w%s' % i] = self.monomial((zero, tuple(temp)))
|
|
302
|
+
return Family(sorted(d), lambda i: d[i])
|
|
303
|
+
|
|
304
|
+
@cached_method
|
|
305
|
+
def gens(self) -> tuple:
|
|
306
|
+
r"""
|
|
307
|
+
Return the generators of ``self``.
|
|
308
|
+
|
|
309
|
+
EXAMPLES::
|
|
310
|
+
|
|
311
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
312
|
+
sage: Cl.gens()
|
|
313
|
+
(psi0, psi1, psi2, psid0, psid1, psid2, w0, w1, w2)
|
|
314
|
+
"""
|
|
315
|
+
return tuple(self.algebra_generators())
|
|
316
|
+
|
|
317
|
+
@cached_method
|
|
318
|
+
def one_basis(self):
|
|
319
|
+
r"""
|
|
320
|
+
Return the index of the basis element of `1`.
|
|
321
|
+
|
|
322
|
+
EXAMPLES::
|
|
323
|
+
|
|
324
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
325
|
+
sage: Cl.one_basis()
|
|
326
|
+
((0, 0, 0), (0, 0, 0))
|
|
327
|
+
"""
|
|
328
|
+
return (self._psi([0]*self._n), (0,)*self._n)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
class QuantumCliffordAlgebraGeneric(QuantumCliffordAlgebra):
|
|
332
|
+
r"""
|
|
333
|
+
The quantum Clifford algebra when `q^{2k} \neq 1`.
|
|
334
|
+
|
|
335
|
+
The *quantum Clifford algebra*, or `q`-Clifford algebra,
|
|
336
|
+
of rank `n` and twist `k` is the unital associative algebra
|
|
337
|
+
`\mathrm{Cl}_{q}(n, k)` over a field `F` with generators
|
|
338
|
+
`\psi_a, \psi_a^*, \omega_a` for `a = 1, \ldots, n` that
|
|
339
|
+
satisfy the following relations:
|
|
340
|
+
|
|
341
|
+
.. MATH::
|
|
342
|
+
|
|
343
|
+
\begin{aligned}
|
|
344
|
+
\omega_a \omega_b & = \omega_b \omega_a,
|
|
345
|
+
& \omega_a^{4k} & = (1 + q^{-2k}) \omega_a^{2k} - q^{-2k},
|
|
346
|
+
\\ \omega_a \psi_b & = q^{\delta_{ab}} \psi_b \omega_a,
|
|
347
|
+
& \omega_a \psi^*_b & = \psi^*_b \omega_a,
|
|
348
|
+
\\ \psi_a \psi_b & + \psi_b \psi_a = 0,
|
|
349
|
+
& \psi^*_a \psi^*_b & + \psi^*_b \psi^*_a = 0,
|
|
350
|
+
\\ \psi_a \psi^*_a & = \frac{q^k \omega_a^{3k} - q^{-k} \omega_a^k}{q^k - q^{-k}},
|
|
351
|
+
& \psi^*_a \psi_a & = \frac{q^{2k} (\omega_a - \omega_a^{3k})}{q^k - q^{-k}},
|
|
352
|
+
\\ \psi_a \psi^*_b & + \psi_b^* \psi_a = 0
|
|
353
|
+
& & \text{if } a \neq b,
|
|
354
|
+
\end{aligned}
|
|
355
|
+
|
|
356
|
+
where `q \in F` such that `q^{2k} \neq 1`.
|
|
357
|
+
|
|
358
|
+
When `k = 2`, we recover the original definition given by Hayashi in
|
|
359
|
+
[Hayashi1990]_. The `k = 1` version was used in [Kwon2014]_.
|
|
360
|
+
"""
|
|
361
|
+
def __init__(self, n, k, q, F):
|
|
362
|
+
r"""
|
|
363
|
+
Initialize ``self``.
|
|
364
|
+
|
|
365
|
+
TESTS::
|
|
366
|
+
|
|
367
|
+
sage: Cl = algebras.QuantumClifford(1,3)
|
|
368
|
+
sage: TestSuite(Cl).run(elements=Cl.basis()) # long time
|
|
369
|
+
|
|
370
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
371
|
+
sage: elts = Cl.some_elements() + list(Cl.algebra_generators())
|
|
372
|
+
sage: TestSuite(Cl).run(elements=elts) # long time
|
|
373
|
+
|
|
374
|
+
sage: Cl = algebras.QuantumClifford(2, 4)
|
|
375
|
+
sage: elts = Cl.some_elements() + list(Cl.algebra_generators())
|
|
376
|
+
sage: TestSuite(Cl).run(elements=elts) # long time
|
|
377
|
+
"""
|
|
378
|
+
psi = cartesian_product([(-1,0,1)]*n)
|
|
379
|
+
indices = [(tuple(p), tuple(w))
|
|
380
|
+
for p in psi
|
|
381
|
+
for w in product(*[list(range((4-2*abs(p[i]))*k)) for i in range(n)])]
|
|
382
|
+
super().__init__(n, k, q, F, psi, indices)
|
|
383
|
+
|
|
384
|
+
def _repr_term(self, m):
|
|
385
|
+
r"""
|
|
386
|
+
Return a string representation of the basis element indexed by ``m``.
|
|
387
|
+
|
|
388
|
+
EXAMPLES::
|
|
389
|
+
|
|
390
|
+
sage: Cl = algebras.QuantumClifford(3, 3)
|
|
391
|
+
sage: Cl._repr_term( ((1, 0, -1), (0, 2, 5)) )
|
|
392
|
+
'psi0*psid2*w1^2*w2^5'
|
|
393
|
+
sage: Cl._repr_term( ((1, 0, -1), (0, 0, 0)) )
|
|
394
|
+
'psi0*psid2'
|
|
395
|
+
sage: Cl._repr_term( ((0, 0, 0), (0, 2, 5)) )
|
|
396
|
+
'w1^2*w2^5'
|
|
397
|
+
sage: Cl._repr_term( ((0, 0, 0), (0, 0, 0)) )
|
|
398
|
+
'1'
|
|
399
|
+
|
|
400
|
+
sage: Cl(5)
|
|
401
|
+
5
|
|
402
|
+
"""
|
|
403
|
+
p, v = m
|
|
404
|
+
rp = '*'.join('psi%s' % i if p[i] > 0 else 'psid%s' % i
|
|
405
|
+
for i in range(self._n) if p[i] != 0)
|
|
406
|
+
gen_str = lambda e: '' if e == 1 else '^%s' % e
|
|
407
|
+
rv = '*'.join('w%s' % i + gen_str(v[i]) for i in range(self._n) if v[i] != 0)
|
|
408
|
+
if rp:
|
|
409
|
+
if rv:
|
|
410
|
+
return rp + '*' + rv
|
|
411
|
+
return rp
|
|
412
|
+
if rv:
|
|
413
|
+
return rv
|
|
414
|
+
return '1'
|
|
415
|
+
|
|
416
|
+
def _latex_term(self, m):
|
|
417
|
+
r"""
|
|
418
|
+
Return a latex representation for the basis element indexed by ``m``.
|
|
419
|
+
|
|
420
|
+
EXAMPLES::
|
|
421
|
+
|
|
422
|
+
sage: Cl = algebras.QuantumClifford(3, 3)
|
|
423
|
+
sage: Cl._latex_term( ((1, 0, -1), (0, -2, 5)) )
|
|
424
|
+
'\\psi_{0}\\psi^{\\dagger}_{2}\\omega_{1}^{-2}\\omega_{2}^{5}'
|
|
425
|
+
sage: Cl._latex_term( ((1, 0, -1), (0, 0, 0)) )
|
|
426
|
+
'\\psi_{0}\\psi^{\\dagger}_{2}'
|
|
427
|
+
sage: Cl._latex_term( ((0, 0, 0), (0, -2, 5)) )
|
|
428
|
+
'\\omega_{1}^{-2}\\omega_{2}^{5}'
|
|
429
|
+
sage: Cl._latex_term( ((0, 0, 0), (0, 0, 0)) )
|
|
430
|
+
'1'
|
|
431
|
+
|
|
432
|
+
sage: latex(Cl(5))
|
|
433
|
+
5
|
|
434
|
+
"""
|
|
435
|
+
p, v = m
|
|
436
|
+
rp = ''.join('\\psi_{%s}' % i if p[i] > 0 else '\\psi^{\\dagger}_{%s}' % i
|
|
437
|
+
for i in range(self._n) if p[i] != 0)
|
|
438
|
+
gen_str = lambda e: '' if e == 1 else '^{%s}' % e
|
|
439
|
+
rv = ''.join('\\omega_{%s}' % i + gen_str(v[i])
|
|
440
|
+
for i in range(self._n) if v[i] != 0)
|
|
441
|
+
if not rp and not rv:
|
|
442
|
+
return '1'
|
|
443
|
+
return rp + rv
|
|
444
|
+
|
|
445
|
+
@cached_method
|
|
446
|
+
def product_on_basis(self, m1, m2):
|
|
447
|
+
r"""
|
|
448
|
+
Return the product of the basis elements indexed by ``m1`` and ``m2``.
|
|
449
|
+
|
|
450
|
+
EXAMPLES::
|
|
451
|
+
|
|
452
|
+
sage: Cl = algebras.QuantumClifford(3)
|
|
453
|
+
sage: Cl.inject_variables()
|
|
454
|
+
Defining psi0, psi1, psi2, psid0, psid1, psid2, w0, w1, w2
|
|
455
|
+
sage: psi0^2 # indirect doctest
|
|
456
|
+
0
|
|
457
|
+
sage: psid0^2
|
|
458
|
+
0
|
|
459
|
+
sage: w0 * psi0
|
|
460
|
+
q*psi0*w0
|
|
461
|
+
sage: w0 * psid0
|
|
462
|
+
1/q*psid0*w0
|
|
463
|
+
sage: w2 * w0
|
|
464
|
+
w0*w2
|
|
465
|
+
sage: w0^4
|
|
466
|
+
-1/q^2 + ((q^2+1)/q^2)*w0^2
|
|
467
|
+
"""
|
|
468
|
+
p1, w1 = m1
|
|
469
|
+
p2, w2 = m2
|
|
470
|
+
|
|
471
|
+
# Check for \psi_i^2 == 0 and for the dagger version
|
|
472
|
+
if any(p1[i] != 0 and p1[i] == p2[i] for i in range(self._n)):
|
|
473
|
+
return self.zero()
|
|
474
|
+
|
|
475
|
+
# \psi_i is represented by a 1 in p1[i] and p2[i]
|
|
476
|
+
# \psi_i^{\dagger} is represented by a -1 in p1[i] and p2[i]
|
|
477
|
+
|
|
478
|
+
k = self._k
|
|
479
|
+
q_power = 0
|
|
480
|
+
sign = 1
|
|
481
|
+
pairings = []
|
|
482
|
+
supported = []
|
|
483
|
+
p = [0] * self._n
|
|
484
|
+
# Move w1 * p2 to q^q_power * p2 * w1
|
|
485
|
+
# Also find pairs \psi_i \psi_i^{\dagger} (or vice versa)
|
|
486
|
+
for i in range(self._n):
|
|
487
|
+
if p2[i] != 0:
|
|
488
|
+
supported.append(i)
|
|
489
|
+
q_power += w1[i] * p2[i]
|
|
490
|
+
if p1[i] != 0:
|
|
491
|
+
# We make pairings 1-based because we cannot distinguish 0 and -0
|
|
492
|
+
pairings.append((i+1) * p1[i])
|
|
493
|
+
# we know p1[i] != p2[i] if nonzero, so their sum is -1, 0, 1
|
|
494
|
+
p[i] = p1[i] + p2[i]
|
|
495
|
+
|
|
496
|
+
supported.append(self._n-1) # To get between the last support and the end
|
|
497
|
+
# Get the sign of moving \psi_i and \psi_i^{\dagger} into position
|
|
498
|
+
for i in reversed(range(1, len(supported))):
|
|
499
|
+
if i % 2 != 0:
|
|
500
|
+
for j in reversed(range(supported[i-1]+1, supported[i]+1)):
|
|
501
|
+
if p1[j] != 0:
|
|
502
|
+
sign = (-1)**i * sign
|
|
503
|
+
|
|
504
|
+
# We move the pairs \psi_i \psi_i^{\dagger} (or the reverse) to the
|
|
505
|
+
# end of the \psi part. This does not change the sign because they
|
|
506
|
+
# move in pairs.
|
|
507
|
+
# We take the products.
|
|
508
|
+
vp = self._w_poly.gens()
|
|
509
|
+
poly = self._w_poly.one()
|
|
510
|
+
q = self._q
|
|
511
|
+
for i in pairings:
|
|
512
|
+
if i < 0:
|
|
513
|
+
i = -i - 1 # Go back to 0-based
|
|
514
|
+
vpik = -q**(2*k) * vp[i]**(3*k) + (1 + q**(2*k)) * vp[i]**k
|
|
515
|
+
poly *= -(vp[i]**k - vpik) / (q**k - q**(-k))
|
|
516
|
+
else:
|
|
517
|
+
i -= 1 # Go back to 0-based
|
|
518
|
+
vpik = -q**(2*k) * vp[i]**(3*k) + (1 + q**(2*k)) * vp[i]**k
|
|
519
|
+
poly *= (q**k * vp[i]**k - q**(-k) * vpik) / (q**k - q**(-k))
|
|
520
|
+
|
|
521
|
+
v = list(w1)
|
|
522
|
+
for i in range(self._n):
|
|
523
|
+
v[i] += w2[i]
|
|
524
|
+
|
|
525
|
+
# For all \psi_i v_i^k, convert this to either k = 0, 1
|
|
526
|
+
# and same for \psi_i^{\dagger}
|
|
527
|
+
for i in range(self._n):
|
|
528
|
+
if p[i] > 0 and v[i] != 0:
|
|
529
|
+
q_power -= 2 * k * (v[i] // (2*k))
|
|
530
|
+
v[i] = v[i] % (2*k)
|
|
531
|
+
if p[i] < 0 and v[i] != 0:
|
|
532
|
+
v[i] = v[i] % (2*k)
|
|
533
|
+
|
|
534
|
+
poly *= self._w_poly.monomial(*v)
|
|
535
|
+
poly = poly.reduce([vp[i]**(4*k) - (1 + q**(-2*k)) * vp[i]**(2*k) + q**(-2*k)
|
|
536
|
+
for i in range(self._n)])
|
|
537
|
+
pdict = poly.monomial_coefficients()
|
|
538
|
+
ret = {(self._psi(p), tuple(e)): pdict[e] * q**q_power * sign
|
|
539
|
+
for e in pdict}
|
|
540
|
+
|
|
541
|
+
return self._from_dict(ret)
|
|
542
|
+
|
|
543
|
+
class Element(CombinatorialFreeModule.Element):
|
|
544
|
+
def inverse(self):
|
|
545
|
+
r"""
|
|
546
|
+
Return the inverse if ``self`` is a basis element.
|
|
547
|
+
|
|
548
|
+
EXAMPLES::
|
|
549
|
+
|
|
550
|
+
sage: Cl = algebras.QuantumClifford(2)
|
|
551
|
+
sage: Cl.inject_variables()
|
|
552
|
+
Defining psi0, psi1, psid0, psid1, w0, w1
|
|
553
|
+
sage: w0^-1
|
|
554
|
+
(q^2+1)*w0 - q^2*w0^3
|
|
555
|
+
sage: w0^-1 * w0
|
|
556
|
+
1
|
|
557
|
+
sage: w0^-2
|
|
558
|
+
(q^2+1) - q^2*w0^2
|
|
559
|
+
sage: w0^-2 * w0^2
|
|
560
|
+
1
|
|
561
|
+
sage: w0^-2 * w0 == w0^-1
|
|
562
|
+
True
|
|
563
|
+
sage: w = w0 * w1
|
|
564
|
+
sage: w^-1
|
|
565
|
+
(q^4+2*q^2+1)*w0*w1 + (-q^4-q^2)*w0*w1^3
|
|
566
|
+
+ (-q^4-q^2)*w0^3*w1 + q^4*w0^3*w1^3
|
|
567
|
+
sage: w^-1 * w
|
|
568
|
+
1
|
|
569
|
+
sage: w * w^-1
|
|
570
|
+
1
|
|
571
|
+
|
|
572
|
+
sage: (2*w0)^-1
|
|
573
|
+
((q^2+1)/2)*w0 - q^2/2*w0^3
|
|
574
|
+
|
|
575
|
+
sage: (w0 + w1)^-1
|
|
576
|
+
Traceback (most recent call last):
|
|
577
|
+
...
|
|
578
|
+
ValueError: cannot invert self (= w1 + w0)
|
|
579
|
+
sage: (psi0 * w0)^-1
|
|
580
|
+
Traceback (most recent call last):
|
|
581
|
+
...
|
|
582
|
+
ValueError: cannot invert self (= psi0*w0)
|
|
583
|
+
|
|
584
|
+
sage: Cl = algebras.QuantumClifford(1, 2)
|
|
585
|
+
sage: Cl.inject_variables()
|
|
586
|
+
Defining psi0, psid0, w0
|
|
587
|
+
sage: (psi0 + psid0).inverse()
|
|
588
|
+
psid0*w0^2 + q^2*psi0*w0^2
|
|
589
|
+
|
|
590
|
+
sage: Cl = algebras.QuantumClifford(2, 2)
|
|
591
|
+
sage: Cl.inject_variables()
|
|
592
|
+
Defining psi0, psi1, psid0, psid1, w0, w1
|
|
593
|
+
sage: w0^-1
|
|
594
|
+
(q^4+1)*w0^3 - q^4*w0^7
|
|
595
|
+
sage: w0 * w0^-1
|
|
596
|
+
1
|
|
597
|
+
"""
|
|
598
|
+
if not self:
|
|
599
|
+
raise ZeroDivisionError
|
|
600
|
+
if len(self) != 1:
|
|
601
|
+
return super().__invert__()
|
|
602
|
+
Cl = self.parent()
|
|
603
|
+
((p, w), coeff), = list(self._monomial_coefficients.items())
|
|
604
|
+
if any(p[i] != 0 for i in range(Cl._n)):
|
|
605
|
+
return super().__invert__()
|
|
606
|
+
poly = Cl._w_poly.monomial(*w)
|
|
607
|
+
wp = Cl._w_poly.gens()
|
|
608
|
+
q = Cl._q
|
|
609
|
+
k = Cl._k
|
|
610
|
+
poly = poly.subs({wi: -q**(2*k) * wi**(4*k-1) + (1 + q**(2*k)) * wi**(2*k-1)
|
|
611
|
+
for wi in wp})
|
|
612
|
+
poly = poly.reduce([wi**(4*k) - (1 + q**(-2*k)) * wi**(2*k) + q**(-2*k)
|
|
613
|
+
for wi in wp])
|
|
614
|
+
pdict = poly.monomial_coefficients()
|
|
615
|
+
coeff = coeff.inverse_of_unit()
|
|
616
|
+
ret = {(p, tuple(e)): coeff * c for e, c in pdict.items()}
|
|
617
|
+
return Cl.element_class(Cl, ret)
|
|
618
|
+
|
|
619
|
+
__invert__ = inverse
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
class QuantumCliffordAlgebraRootUnity(QuantumCliffordAlgebra):
|
|
623
|
+
r"""
|
|
624
|
+
The quantum Clifford algebra when `q^{2k} = 1`.
|
|
625
|
+
|
|
626
|
+
The *quantum Clifford algebra*, or `q`-Clifford algebra,
|
|
627
|
+
of rank `n` and twist `k` is the unital associative algebra
|
|
628
|
+
`\mathrm{Cl}_{q}(n, k)` over a field `F` with generators
|
|
629
|
+
`\psi_a, \psi_a^*, \omega_a` for `a = 1, \ldots, n` that
|
|
630
|
+
satisfy the following relations:
|
|
631
|
+
|
|
632
|
+
.. MATH::
|
|
633
|
+
|
|
634
|
+
\begin{aligned}
|
|
635
|
+
\omega_a \omega_b & = \omega_b \omega_a,
|
|
636
|
+
& \omega_a^{2k} & = 1,
|
|
637
|
+
\\ \omega_a \psi_b & = q^{\delta_{ab}} \psi_b \omega_a,
|
|
638
|
+
& \omega_a \psi^*_b & = \psi^*_b \omega_a,
|
|
639
|
+
\\ \psi_a \psi_b & + \psi_b \psi_a = 0,
|
|
640
|
+
& \psi^*_a \psi^*_b & + \psi^*_b \psi^*_a = 0,
|
|
641
|
+
\\ \psi_a \psi^*_a & + q^k \psi^*_a \psi_a = \omega_a^k
|
|
642
|
+
& \psi_a \psi^*_b & + \psi_b^* \psi_a = 0 \quad (a \neq b),
|
|
643
|
+
\end{aligned}
|
|
644
|
+
|
|
645
|
+
where `q \in F` such that `q^{2k} = 1`. This has further relations of
|
|
646
|
+
|
|
647
|
+
.. MATH::
|
|
648
|
+
|
|
649
|
+
\begin{aligned}
|
|
650
|
+
\psi^*_a \psi_a \psi^*_a & = \psi^*_a \omega_a^k,
|
|
651
|
+
\\
|
|
652
|
+
\psi_a \psi^*_a \psi_a & = q^k \psi_a \omega_a^k,
|
|
653
|
+
\\
|
|
654
|
+
(\psi_a \psi^*_a)^2 & = \psi_a \psi^*_a \omega_a^k.
|
|
655
|
+
\end{aligned}
|
|
656
|
+
"""
|
|
657
|
+
def __init__(self, n, k, q, F):
|
|
658
|
+
r"""
|
|
659
|
+
Initialize ``self``.
|
|
660
|
+
|
|
661
|
+
EXAMPLES::
|
|
662
|
+
|
|
663
|
+
sage: Cl = algebras.QuantumClifford(1,2,-1)
|
|
664
|
+
sage: TestSuite(Cl).run(elements=Cl.basis())
|
|
665
|
+
|
|
666
|
+
sage: z = CyclotomicField(3).gen()
|
|
667
|
+
sage: Cl = algebras.QuantumClifford(1,3,z)
|
|
668
|
+
sage: TestSuite(Cl).run(elements=Cl.basis())
|
|
669
|
+
|
|
670
|
+
sage: Cl = algebras.QuantumClifford(3,1,-1)
|
|
671
|
+
sage: elts = Cl.some_elements() + list(Cl.algebra_generators())
|
|
672
|
+
sage: TestSuite(Cl).run(elements=elts) # long time
|
|
673
|
+
|
|
674
|
+
sage: Cl = algebras.QuantumClifford(2,4,-1)
|
|
675
|
+
sage: elts = Cl.some_elements() + list(Cl.algebra_generators())
|
|
676
|
+
sage: TestSuite(Cl).run(elements=elts) # long time
|
|
677
|
+
"""
|
|
678
|
+
psi = cartesian_product([(-1,0,1,2)]*n)
|
|
679
|
+
indices = [(tuple(p), tuple(w))
|
|
680
|
+
for p in psi
|
|
681
|
+
for w in product(list(range(2*k)), repeat=n)]
|
|
682
|
+
super().__init__(n, k, q, F, psi, indices)
|
|
683
|
+
|
|
684
|
+
def _repr_term(self, m):
|
|
685
|
+
r"""
|
|
686
|
+
Return a string representation of the basis element indexed by ``m``.
|
|
687
|
+
|
|
688
|
+
EXAMPLES::
|
|
689
|
+
|
|
690
|
+
sage: Cl = algebras.QuantumClifford(3, 3, -1)
|
|
691
|
+
sage: Cl._repr_term( ((1, 0, -1), (0, 2, 5)) )
|
|
692
|
+
'psi0*psid2*w1^2*w2^5'
|
|
693
|
+
sage: Cl._repr_term( ((1, 0, 2), (0, 0, 0)) )
|
|
694
|
+
'psi0*psi2*psid2'
|
|
695
|
+
sage: Cl._repr_term( ((0, 0, 0), (0, 2, 5)) )
|
|
696
|
+
'w1^2*w2^5'
|
|
697
|
+
sage: Cl._repr_term( ((0, 0, 0), (0, 0, 0)) )
|
|
698
|
+
'1'
|
|
699
|
+
|
|
700
|
+
sage: Cl(5)
|
|
701
|
+
5
|
|
702
|
+
"""
|
|
703
|
+
p, v = m
|
|
704
|
+
|
|
705
|
+
def ppr(i):
|
|
706
|
+
val = p[i]
|
|
707
|
+
if val == -1:
|
|
708
|
+
return 'psid%s' % i
|
|
709
|
+
elif val == 1:
|
|
710
|
+
return 'psi%s' % i
|
|
711
|
+
elif val == 2:
|
|
712
|
+
return 'psi%s*psid%s' % (i,i)
|
|
713
|
+
|
|
714
|
+
rp = '*'.join(ppr(i) for i in range(self._n) if p[i] != 0)
|
|
715
|
+
gen_str = lambda e: '' if e == 1 else '^%s' % e
|
|
716
|
+
rv = '*'.join('w%s' % i + gen_str(v[i]) for i in range(self._n) if v[i] != 0)
|
|
717
|
+
if rp:
|
|
718
|
+
if rv:
|
|
719
|
+
return rp + '*' + rv
|
|
720
|
+
return rp
|
|
721
|
+
if rv:
|
|
722
|
+
return rv
|
|
723
|
+
return '1'
|
|
724
|
+
|
|
725
|
+
def _latex_term(self, m):
|
|
726
|
+
r"""
|
|
727
|
+
Return a latex representation for the basis element indexed by ``m``.
|
|
728
|
+
|
|
729
|
+
EXAMPLES::
|
|
730
|
+
|
|
731
|
+
sage: Cl = algebras.QuantumClifford(3, 3, -1)
|
|
732
|
+
sage: Cl._latex_term( ((1, 0, -1), (0, 2, 5)) )
|
|
733
|
+
'\\psi_{0}\\psi^{\\dagger}_{2}\\omega_{1}^{2}\\omega_{2}^{5}'
|
|
734
|
+
sage: Cl._latex_term( ((1, 0, 2), (0, 0, 0)) )
|
|
735
|
+
'\\psi_{0}\\psi_{2}\\psi^{\\dagger}_{2}'
|
|
736
|
+
sage: Cl._latex_term( ((0, 0, 0), (0, 2, 5)) )
|
|
737
|
+
'\\omega_{1}^{2}\\omega_{2}^{5}'
|
|
738
|
+
sage: Cl._latex_term( ((0, 0, 0), (0, 0, 0)) )
|
|
739
|
+
'1'
|
|
740
|
+
|
|
741
|
+
sage: latex(Cl(5))
|
|
742
|
+
5
|
|
743
|
+
"""
|
|
744
|
+
p, v = m
|
|
745
|
+
|
|
746
|
+
def ppr(i):
|
|
747
|
+
val = p[i]
|
|
748
|
+
if val == -1:
|
|
749
|
+
return '\\psi^{\\dagger}_{%s}' % i
|
|
750
|
+
elif val == 1:
|
|
751
|
+
return '\\psi_{%s}' % i
|
|
752
|
+
elif val == 2:
|
|
753
|
+
return '\\psi_{%s}\\psi^{\\dagger}_{%s}' % (i, i)
|
|
754
|
+
|
|
755
|
+
rp = ''.join(ppr(i) for i in range(self._n) if p[i] != 0)
|
|
756
|
+
gen_str = lambda e: '' if e == 1 else '^{%s}' % e
|
|
757
|
+
rv = ''.join('\\omega_{%s}' % i + gen_str(v[i])
|
|
758
|
+
for i in range(self._n) if v[i] != 0)
|
|
759
|
+
if not rp and not rv:
|
|
760
|
+
return '1'
|
|
761
|
+
return rp + rv
|
|
762
|
+
|
|
763
|
+
@cached_method
|
|
764
|
+
def product_on_basis(self, m1, m2):
|
|
765
|
+
r"""
|
|
766
|
+
Return the product of the basis elements indexed by ``m1`` and ``m2``.
|
|
767
|
+
|
|
768
|
+
EXAMPLES::
|
|
769
|
+
|
|
770
|
+
sage: z = CyclotomicField(3).gen()
|
|
771
|
+
sage: Cl = algebras.QuantumClifford(3, 3, z)
|
|
772
|
+
sage: Cl.inject_variables()
|
|
773
|
+
Defining psi0, psi1, psi2, psid0, psid1, psid2, w0, w1, w2
|
|
774
|
+
sage: psi0^2 # indirect doctest
|
|
775
|
+
0
|
|
776
|
+
sage: psid0^2
|
|
777
|
+
0
|
|
778
|
+
sage: w0 * psi0
|
|
779
|
+
-(-zeta3)*psi0*w0
|
|
780
|
+
sage: w0 * psid0
|
|
781
|
+
-(zeta3+1)*psid0*w0
|
|
782
|
+
sage: psi0 * psid0
|
|
783
|
+
psi0*psid0
|
|
784
|
+
sage: psid0 * psi0
|
|
785
|
+
w0^3 - psi0*psid0
|
|
786
|
+
sage: w2 * w0
|
|
787
|
+
w0*w2
|
|
788
|
+
sage: w0^6
|
|
789
|
+
1
|
|
790
|
+
sage: psi0 * psi1
|
|
791
|
+
psi0*psi1
|
|
792
|
+
sage: psi1 * psi0
|
|
793
|
+
-psi0*psi1
|
|
794
|
+
sage: psi1 * (psi0 * psi2)
|
|
795
|
+
-psi0*psi1*psi2
|
|
796
|
+
|
|
797
|
+
sage: z = CyclotomicField(6).gen()
|
|
798
|
+
sage: Cl = algebras.QuantumClifford(3, 3, z)
|
|
799
|
+
sage: Cl.inject_variables()
|
|
800
|
+
Defining psi0, psi1, psi2, psid0, psid1, psid2, w0, w1, w2
|
|
801
|
+
|
|
802
|
+
sage: psid1 * (psi1 * psid1)
|
|
803
|
+
psid1*w1^3
|
|
804
|
+
sage: (psi1* psid1) * (psi1 * psid1)
|
|
805
|
+
psi1*psid1*w1^3
|
|
806
|
+
sage: (psi1 * psid1) * psi1
|
|
807
|
+
-psi1*w1^3
|
|
808
|
+
"""
|
|
809
|
+
p1, w1 = m1
|
|
810
|
+
p2, w2 = m2
|
|
811
|
+
k = self._k
|
|
812
|
+
tk = 2 * k
|
|
813
|
+
|
|
814
|
+
# \psi_i is represented by a 1 in p1[i] and p2[i]
|
|
815
|
+
# \psi_i^{\dagger} is represented by a -1 in p1[i] and p2[i]
|
|
816
|
+
# \psi_i \psi_i^{\dagger} is a 2 in p1[i] and p2[i]
|
|
817
|
+
|
|
818
|
+
# Check for \psi_i^2 == 0 and for the dagger version
|
|
819
|
+
if any((p1[i] % 2 != 0 and p1[i] == p2[i])
|
|
820
|
+
or (p1[i] == 2 and p2[i] == -1) or (p2[i] == 2 and p1[i] == 1)
|
|
821
|
+
for i in range(self._n)):
|
|
822
|
+
return self.zero()
|
|
823
|
+
|
|
824
|
+
# Reduce any v_i^{2k} = 1
|
|
825
|
+
v = [(w1[i] + w2[i]) % tk for i in range(self._n)]
|
|
826
|
+
|
|
827
|
+
q_power = 0
|
|
828
|
+
sign = 1
|
|
829
|
+
pairings = []
|
|
830
|
+
p = [0] * self._n
|
|
831
|
+
# Move w1 * p2 to q^q_power * p2 * w1
|
|
832
|
+
# Also find pairs \psi_i \psi_i^{\dagger} (or vice versa) and
|
|
833
|
+
# count the sign from moving \psi_i and \psi_i^{\dagger} into position
|
|
834
|
+
num_cross = 0
|
|
835
|
+
total_cross = 0
|
|
836
|
+
for i in range(self._n):
|
|
837
|
+
num_cross += p2[i]
|
|
838
|
+
if p2[i] == 2:
|
|
839
|
+
# By the above check, we cannot have p1[i] == 1
|
|
840
|
+
if p1[i] != 0:
|
|
841
|
+
v[i] = (v[i] + k) % tk
|
|
842
|
+
p[i] = p1[i]
|
|
843
|
+
else:
|
|
844
|
+
p[i] = p2[i]
|
|
845
|
+
elif p2[i] != 0: # == +1, -1
|
|
846
|
+
q_power += w1[i] * p2[i]
|
|
847
|
+
# By the above check, we cannot have p1[i] == p2[i]
|
|
848
|
+
if p1[i] == -1:
|
|
849
|
+
pairings.append(i)
|
|
850
|
+
total_cross -= 1 # correction
|
|
851
|
+
p[i] = None
|
|
852
|
+
elif p1[i] == 1:
|
|
853
|
+
total_cross -= 1 # correction
|
|
854
|
+
p[i] = 2
|
|
855
|
+
elif p1[i] == 2:
|
|
856
|
+
q_power += k
|
|
857
|
+
v[i] = (v[i] + k) % tk
|
|
858
|
+
p[i] = p2[i]
|
|
859
|
+
else:
|
|
860
|
+
p[i] = p2[i]
|
|
861
|
+
else:
|
|
862
|
+
p[i] = p1[i] # since p2[i] == 0
|
|
863
|
+
|
|
864
|
+
if abs(p1[i]) == 1:
|
|
865
|
+
total_cross += num_cross
|
|
866
|
+
|
|
867
|
+
# total_cross does not need to actually be the total number of crossings; just correct mod 2
|
|
868
|
+
if total_cross % 2:
|
|
869
|
+
sign = -sign
|
|
870
|
+
|
|
871
|
+
# Replace \psi_i^{\dagger} \psi_i = q^k ( w^k - \psi_i \psi_i^{\dagger} )
|
|
872
|
+
def key(X):
|
|
873
|
+
e = list(v) # Make a copy
|
|
874
|
+
for i in pairings:
|
|
875
|
+
if i in X:
|
|
876
|
+
p[i] = 2
|
|
877
|
+
else:
|
|
878
|
+
p[i] = 0
|
|
879
|
+
e[i] = (e[i] + k) % tk
|
|
880
|
+
return (self._psi(p), tuple(e))
|
|
881
|
+
|
|
882
|
+
q = self._q
|
|
883
|
+
ret = {key(X): (-1)**len(X) * sign * q**(q_power+k*(len(pairings) % 2))
|
|
884
|
+
for X in powerset(pairings)}
|
|
885
|
+
|
|
886
|
+
return self._from_dict(ret)
|
|
887
|
+
|
|
888
|
+
class Element(QuantumCliffordAlgebra.Element):
|
|
889
|
+
def inverse(self):
|
|
890
|
+
r"""
|
|
891
|
+
Return the inverse if ``self`` is a basis element.
|
|
892
|
+
|
|
893
|
+
EXAMPLES::
|
|
894
|
+
|
|
895
|
+
sage: Cl = algebras.QuantumClifford(3, 3, -1)
|
|
896
|
+
sage: Cl.inject_variables()
|
|
897
|
+
Defining psi0, psi1, psi2, psid0, psid1, psid2, w0, w1, w2
|
|
898
|
+
sage: w0^-1
|
|
899
|
+
w0^5
|
|
900
|
+
sage: w0^-1 * w0
|
|
901
|
+
1
|
|
902
|
+
sage: w0^-2
|
|
903
|
+
w0^4
|
|
904
|
+
sage: w0^-2 * w0^2
|
|
905
|
+
1
|
|
906
|
+
sage: w0^-2 * w0 == w0^-1
|
|
907
|
+
True
|
|
908
|
+
sage: w = w0 * w1^3
|
|
909
|
+
sage: w^-1
|
|
910
|
+
w0^5*w1^3
|
|
911
|
+
sage: w^-1 * w
|
|
912
|
+
1
|
|
913
|
+
sage: w * w^-1
|
|
914
|
+
1
|
|
915
|
+
|
|
916
|
+
sage: (2*w0)^-1
|
|
917
|
+
1/2*w0^5
|
|
918
|
+
|
|
919
|
+
sage: Cl = algebras.QuantumClifford(3, 1, -1)
|
|
920
|
+
sage: Cl.inject_variables()
|
|
921
|
+
Defining psi0, psi1, psi2, psid0, psid1, psid2, w0, w1, w2
|
|
922
|
+
|
|
923
|
+
sage: (w0 + w1)^-1
|
|
924
|
+
Traceback (most recent call last):
|
|
925
|
+
...
|
|
926
|
+
ValueError: cannot invert self (= w1 + w0)
|
|
927
|
+
sage: (psi0 * w0)^-1
|
|
928
|
+
Traceback (most recent call last):
|
|
929
|
+
...
|
|
930
|
+
ValueError: cannot invert self (= psi0*w0)
|
|
931
|
+
|
|
932
|
+
sage: z = CyclotomicField(6).gen()
|
|
933
|
+
sage: Cl = algebras.QuantumClifford(1, 3, z)
|
|
934
|
+
sage: Cl.inject_variables()
|
|
935
|
+
Defining psi0, psid0, w0
|
|
936
|
+
sage: (psi0 + psid0).inverse()
|
|
937
|
+
psid0*w0^3 - psi0*w0^3
|
|
938
|
+
|
|
939
|
+
sage: Cl = algebras.QuantumClifford(2, 2, -1)
|
|
940
|
+
sage: Cl.inject_variables()
|
|
941
|
+
Defining psi0, psi1, psid0, psid1, w0, w1
|
|
942
|
+
sage: w0^-1
|
|
943
|
+
w0^3
|
|
944
|
+
sage: w0 * w0^-1
|
|
945
|
+
1
|
|
946
|
+
"""
|
|
947
|
+
if not self:
|
|
948
|
+
raise ZeroDivisionError
|
|
949
|
+
if len(self) != 1:
|
|
950
|
+
return super().__invert__()
|
|
951
|
+
Cl = self.parent()
|
|
952
|
+
((p, w), coeff), = list(self._monomial_coefficients.items())
|
|
953
|
+
if any(p[i] != 0 for i in range(Cl._n)):
|
|
954
|
+
return super().__invert__()
|
|
955
|
+
tk = 2 * Cl._k
|
|
956
|
+
w = tuple([tk - val if val else 0 for val in w])
|
|
957
|
+
return Cl.element_class(Cl, {(p, w): coeff.inverse_of_unit()})
|
|
958
|
+
|
|
959
|
+
__invert__ = inverse
|