passagemath-combinat 10.6.42__cp314-cp314t-win_amd64.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/DELVEWHEEL +2 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +401 -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-10-3a5f019e2510aeaad918cab2b57a689d.dll +0 -0
- passagemath_combinat.libs/libsymmetrica-3-7dcf900932804d0df5fd0919b4668720.dll +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 +44 -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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,1623 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.modules sage.plot
|
|
3
|
+
r"""
|
|
4
|
+
Substitutions over unit cube faces (Rauzy fractals)
|
|
5
|
+
|
|
6
|
+
This module implements the `E_1^*(\sigma)` substitution
|
|
7
|
+
associated with a one-dimensional substitution `\sigma`,
|
|
8
|
+
that acts on unit faces of dimension `(d-1)` in `\RR^d`.
|
|
9
|
+
|
|
10
|
+
This module defines the following classes and functions:
|
|
11
|
+
|
|
12
|
+
- ``Face`` -- a class to model a face
|
|
13
|
+
|
|
14
|
+
- ``Patch`` -- a class to model a finite set of faces
|
|
15
|
+
|
|
16
|
+
- ``E1Star`` -- a class to model the `E_1^*(\sigma)` application
|
|
17
|
+
defined by the substitution sigma
|
|
18
|
+
|
|
19
|
+
See the documentation of these objects for more information.
|
|
20
|
+
|
|
21
|
+
The convention for the choice of the unit faces and the
|
|
22
|
+
definition of `E_1^*(\sigma)` varies from article to article.
|
|
23
|
+
Here, unit faces are defined by
|
|
24
|
+
|
|
25
|
+
.. MATH::
|
|
26
|
+
|
|
27
|
+
\begin{array}{ccc}
|
|
28
|
+
\,[x, 1]^* & = & \{x + \lambda e_2 + \mu e_3 : \lambda, \mu \in [0,1]\} \\
|
|
29
|
+
\,[x, 2]^* & = & \{x + \lambda e_1 + \mu e_3 : \lambda, \mu \in [0,1]\} \\
|
|
30
|
+
\,[x, 3]^* & = & \{x + \lambda e_1 + \mu e_2 : \lambda, \mu \in [0,1]\}
|
|
31
|
+
\end{array}
|
|
32
|
+
|
|
33
|
+
and the dual substitution `E_1^*(\sigma)` is defined by
|
|
34
|
+
|
|
35
|
+
.. MATH::
|
|
36
|
+
|
|
37
|
+
E_1^*(\sigma)([x,i]^*) =
|
|
38
|
+
\bigcup_{k = 1,2,3} \; \bigcup_{s | \sigma(k) = pis}
|
|
39
|
+
[M^{-1}(x + \ell(s)), k]^*,
|
|
40
|
+
|
|
41
|
+
where `\ell(s)` is the abelianized of `s`, and `M` is the matrix of `\sigma`.
|
|
42
|
+
|
|
43
|
+
AUTHORS:
|
|
44
|
+
|
|
45
|
+
- Franco Saliola (2009): initial version
|
|
46
|
+
- Vincent Delecroix, Timo Jolivet, Stepan Starosta, Sebastien Labbe (2010-05): redesign
|
|
47
|
+
- Timo Jolivet (2010-08, 2010-09, 2011): redesign
|
|
48
|
+
|
|
49
|
+
REFERENCES:
|
|
50
|
+
|
|
51
|
+
.. [AI] \P. Arnoux, S. Ito,
|
|
52
|
+
Pisot substitutions and Rauzy fractals,
|
|
53
|
+
Bull. Belg. Math. Soc. 8 (2), 2001, pp. 181--207
|
|
54
|
+
|
|
55
|
+
.. [SAI] \Y. Sano, P. Arnoux, S. Ito,
|
|
56
|
+
Higher dimensional extensions of substitutions and their dual maps,
|
|
57
|
+
J. Anal. Math. 83, 2001, pp. 183--206
|
|
58
|
+
|
|
59
|
+
EXAMPLES:
|
|
60
|
+
|
|
61
|
+
We start by drawing a simple three-face patch::
|
|
62
|
+
|
|
63
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
64
|
+
sage: x = [Face((0,0,0),1), Face((0,0,0),2), Face((0,0,0),3)]
|
|
65
|
+
sage: P = Patch(x)
|
|
66
|
+
sage: P
|
|
67
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*]
|
|
68
|
+
sage: P.plot() #not tested
|
|
69
|
+
|
|
70
|
+
We apply a substitution to this patch, and draw the result::
|
|
71
|
+
|
|
72
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
73
|
+
sage: E = E1Star(sigma)
|
|
74
|
+
sage: E(P)
|
|
75
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*, [(0, 1, -1), 2]*, [(1, 0, -1), 1]*]
|
|
76
|
+
sage: E(P).plot() #not tested
|
|
77
|
+
|
|
78
|
+
.. NOTE::
|
|
79
|
+
|
|
80
|
+
- The type of a face is given by an integer in ``[1, ..., d]``
|
|
81
|
+
where ``d`` is the length of the vector of the face.
|
|
82
|
+
|
|
83
|
+
- The alphabet of the domain and the codomain of `\sigma` must be
|
|
84
|
+
equal, and they must be of the form ``[1, ..., d]``, where ``d``
|
|
85
|
+
is a positive integer corresponding to the length of the vectors
|
|
86
|
+
of the faces on which `E_1^*(\sigma)` will act.
|
|
87
|
+
|
|
88
|
+
::
|
|
89
|
+
|
|
90
|
+
sage: P = Patch([Face((0,0,0),1), Face((0,0,0),2), Face((0,0,0),3)])
|
|
91
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
92
|
+
sage: E = E1Star(sigma)
|
|
93
|
+
sage: E(P)
|
|
94
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*, [(0, 1, -1), 2]*, [(1, 0, -1), 1]*]
|
|
95
|
+
|
|
96
|
+
The application of an ``E1Star`` substitution assigns to each new face the color of its preimage.
|
|
97
|
+
The ``repaint`` method allows us to repaint the faces of a patch.
|
|
98
|
+
A single color can also be assigned to every face, by specifying a list of a single color::
|
|
99
|
+
|
|
100
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
101
|
+
sage: P = E(P, 5)
|
|
102
|
+
sage: P.repaint(['green'])
|
|
103
|
+
sage: P.plot() #not tested
|
|
104
|
+
|
|
105
|
+
A list of colors allows us to color the faces sequentially::
|
|
106
|
+
|
|
107
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
108
|
+
sage: P = E(P)
|
|
109
|
+
sage: P.repaint(['red', 'yellow', 'green', 'blue', 'black'])
|
|
110
|
+
sage: P = E(P, 3)
|
|
111
|
+
sage: P.plot() #not tested
|
|
112
|
+
|
|
113
|
+
All the color schemes from ``list(matplotlib.cm.datad)`` can be used::
|
|
114
|
+
|
|
115
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
116
|
+
sage: P.repaint(cmap='summer')
|
|
117
|
+
sage: P = E(P, 3)
|
|
118
|
+
sage: P.plot() #not tested
|
|
119
|
+
sage: P.repaint(cmap='hsv')
|
|
120
|
+
sage: P = E(P, 2)
|
|
121
|
+
sage: P.plot() #not tested
|
|
122
|
+
|
|
123
|
+
It is also possible to specify a dictionary to color the faces according to their type::
|
|
124
|
+
|
|
125
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
126
|
+
sage: P = E(P, 5)
|
|
127
|
+
sage: P.repaint({1:(0.7, 0.7, 0.7), 2:(0.5,0.5,0.5), 3:(0.3,0.3,0.3)})
|
|
128
|
+
sage: P.plot() #not tested
|
|
129
|
+
sage: P.repaint({1:'red', 2:'yellow', 3:'green'})
|
|
130
|
+
sage: P.plot() #not tested
|
|
131
|
+
|
|
132
|
+
Let us look at a nice big patch in 3D::
|
|
133
|
+
|
|
134
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[3], 3:[1]})
|
|
135
|
+
sage: E = E1Star(sigma)
|
|
136
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
137
|
+
sage: P = P + P.translate([-1,1,0])
|
|
138
|
+
sage: P = E(P, 11)
|
|
139
|
+
sage: P.plot3d() #not tested
|
|
140
|
+
|
|
141
|
+
Plotting with TikZ pictures is possible::
|
|
142
|
+
|
|
143
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
144
|
+
sage: s = P.plot_tikz()
|
|
145
|
+
sage: print(s) #not tested
|
|
146
|
+
\begin{tikzpicture}
|
|
147
|
+
[x={(-0.216506cm,-0.125000cm)}, y={(0.216506cm,-0.125000cm)}, z={(0.000000cm,0.250000cm)}]
|
|
148
|
+
\definecolor{facecolor}{rgb}{0.000,1.000,0.000}
|
|
149
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
150
|
+
(0, 0, 0) -- (0, 0, 1) -- (1, 0, 1) -- (1, 0, 0) -- cycle;
|
|
151
|
+
\definecolor{facecolor}{rgb}{1.000,0.000,0.000}
|
|
152
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
153
|
+
(0, 0, 0) -- (0, 1, 0) -- (0, 1, 1) -- (0, 0, 1) -- cycle;
|
|
154
|
+
\definecolor{facecolor}{rgb}{0.000,0.000,1.000}
|
|
155
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
156
|
+
(0, 0, 0) -- (1, 0, 0) -- (1, 1, 0) -- (0, 1, 0) -- cycle;
|
|
157
|
+
\end{tikzpicture}
|
|
158
|
+
|
|
159
|
+
Plotting patches made of unit segments instead of unit faces::
|
|
160
|
+
|
|
161
|
+
sage: P = Patch([Face([0,0], 1), Face([0,0], 2)])
|
|
162
|
+
sage: E = E1Star(WordMorphism({1:[1,2],2:[1]}))
|
|
163
|
+
sage: F = E1Star(WordMorphism({1:[1,1,2],2:[2,1]}))
|
|
164
|
+
sage: E(P,5).plot() # needs sage.plot
|
|
165
|
+
Graphics object consisting of 21 graphics primitives
|
|
166
|
+
sage: F(P,3).plot() # needs sage.plot
|
|
167
|
+
Graphics object consisting of 34 graphics primitives
|
|
168
|
+
|
|
169
|
+
Everything works in any dimension (except for the plotting features
|
|
170
|
+
which only work in dimension two or three)::
|
|
171
|
+
|
|
172
|
+
sage: P = Patch([Face((0,0,0,0),1), Face((0,0,0,0),4)])
|
|
173
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1,4], 4:[1]})
|
|
174
|
+
sage: E = E1Star(sigma)
|
|
175
|
+
sage: E(P)
|
|
176
|
+
Patch: [[(0, 0, 0, 0), 3]*, [(0, 0, 0, 0), 4]*, [(0, 0, 1, -1), 3]*, [(0, 1, 0, -1), 2]*, [(1, 0, 0, -1), 1]*]
|
|
177
|
+
|
|
178
|
+
::
|
|
179
|
+
|
|
180
|
+
sage: sigma = WordMorphism({1:[1,2],2:[1,3],3:[1,4],4:[1,5],5:[1,6],6:[1,7],7:[1,8],8:[1,9],9:[1,10],10:[1,11],11:[1,12],12:[1]})
|
|
181
|
+
sage: E = E1Star(sigma)
|
|
182
|
+
sage: E
|
|
183
|
+
E_1^*(1->12, 10->1,11, 11->1,12, 12->1, 2->13, 3->14, 4->15, 5->16, 6->17, 7->18, 8->19, 9->1,10)
|
|
184
|
+
sage: P = Patch([Face((0,0,0,0,0,0,0,0,0,0,0,0),t) for t in [1,2,3]])
|
|
185
|
+
sage: for x in sorted(E(P), key=lambda x : (x.vector(),x.type())): print(x)
|
|
186
|
+
[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 1]*
|
|
187
|
+
[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 2]*
|
|
188
|
+
[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 12]*
|
|
189
|
+
[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1), 11]*
|
|
190
|
+
[(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1), 10]*
|
|
191
|
+
[(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1), 9]*
|
|
192
|
+
[(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1), 8]*
|
|
193
|
+
[(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1), 7]*
|
|
194
|
+
[(0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1), 6]*
|
|
195
|
+
[(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1), 5]*
|
|
196
|
+
[(0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1), 4]*
|
|
197
|
+
[(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1), 3]*
|
|
198
|
+
[(0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1), 2]*
|
|
199
|
+
[(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1), 1]*
|
|
200
|
+
"""
|
|
201
|
+
# ****************************************************************************
|
|
202
|
+
# Copyright (C) 2010 Franco Saliola <saliola@gmail.com>
|
|
203
|
+
# Vincent Delecroix <20100.delecroix@gmail.com>
|
|
204
|
+
# Timo Jolivet <timo.jolivet@gmail.com>
|
|
205
|
+
# Stepan Starosta <stepan.starosta@gmail.com>
|
|
206
|
+
# Sébastien Labbé <slabqc at gmail.com>
|
|
207
|
+
#
|
|
208
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
209
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
210
|
+
# the License, or (at your option) any later version.
|
|
211
|
+
# https://www.gnu.org/licenses/
|
|
212
|
+
# ****************************************************************************
|
|
213
|
+
from __future__ import annotations
|
|
214
|
+
|
|
215
|
+
from sage.misc.functional import det
|
|
216
|
+
from sage.structure.sage_object import SageObject
|
|
217
|
+
from sage.combinat.words.morphism import WordMorphism
|
|
218
|
+
from sage.misc.lazy_import import lazy_import
|
|
219
|
+
lazy_import("sage.plot.all", "Graphics")
|
|
220
|
+
lazy_import("sage.plot.colors", "Color")
|
|
221
|
+
lazy_import("sage.plot.polygon", "polygon")
|
|
222
|
+
lazy_import("sage.plot.line", "line")
|
|
223
|
+
from sage.rings.integer_ring import ZZ
|
|
224
|
+
from sage.misc.latex import LatexExpr
|
|
225
|
+
from sage.misc.cachefunc import cached_method
|
|
226
|
+
from sage.structure.richcmp import richcmp_by_eq_and_lt, richcmp_method
|
|
227
|
+
|
|
228
|
+
lazy_import('sage.matrix.constructor', 'matrix')
|
|
229
|
+
lazy_import('sage.modules.free_module_element', 'vector')
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# matplotlib color maps, loaded on-demand
|
|
233
|
+
cm = None
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@richcmp_method
|
|
237
|
+
class Face(SageObject):
|
|
238
|
+
r"""
|
|
239
|
+
A class to model a unit face of arbitrary dimension.
|
|
240
|
+
|
|
241
|
+
A unit face in dimension `d` is represented by
|
|
242
|
+
a `d`-dimensional vector ``v`` and a type ``t`` in `\{1, \ldots, d\}`.
|
|
243
|
+
The type of the face corresponds to the canonical unit vector
|
|
244
|
+
to which the face is orthogonal.
|
|
245
|
+
The optional ``color`` argument is used in plotting functions.
|
|
246
|
+
|
|
247
|
+
INPUT:
|
|
248
|
+
|
|
249
|
+
- ``v`` -- tuple of integers
|
|
250
|
+
- ``t`` -- integer in ``[1, ..., len(v)]``, type of the face. The face of type `i`
|
|
251
|
+
is orthogonal to the canonical vector `e_i`.
|
|
252
|
+
- ``color`` -- color (default: ``None``); color of the face,
|
|
253
|
+
used for plotting only. If ``None``, its value is guessed from the
|
|
254
|
+
face type.
|
|
255
|
+
|
|
256
|
+
EXAMPLES::
|
|
257
|
+
|
|
258
|
+
sage: from sage.combinat.e_one_star import Face
|
|
259
|
+
sage: f = Face((0,2,0), 3)
|
|
260
|
+
sage: f.vector()
|
|
261
|
+
(0, 2, 0)
|
|
262
|
+
sage: f.type()
|
|
263
|
+
3
|
|
264
|
+
|
|
265
|
+
::
|
|
266
|
+
|
|
267
|
+
sage: f = Face((0,2,0), 3, color=(0.5, 0.5, 0.5))
|
|
268
|
+
sage: f.color()
|
|
269
|
+
RGB color (0.5, 0.5, 0.5)
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
def __init__(self, v, t, color=None):
|
|
273
|
+
r"""
|
|
274
|
+
Face constructor. See class doc for more information.
|
|
275
|
+
|
|
276
|
+
EXAMPLES::
|
|
277
|
+
|
|
278
|
+
sage: from sage.combinat.e_one_star import Face
|
|
279
|
+
sage: f = Face((0,2,0), 3)
|
|
280
|
+
sage: f.vector()
|
|
281
|
+
(0, 2, 0)
|
|
282
|
+
sage: f.type()
|
|
283
|
+
3
|
|
284
|
+
|
|
285
|
+
TESTS:
|
|
286
|
+
|
|
287
|
+
We test that types can be given by an int (see :issue:`10699`)::
|
|
288
|
+
|
|
289
|
+
sage: f = Face((0,2,0), int(1))
|
|
290
|
+
"""
|
|
291
|
+
self._vector = (ZZ**len(v))(v)
|
|
292
|
+
self._vector.set_immutable()
|
|
293
|
+
|
|
294
|
+
if not ((t in ZZ) and 1 <= t <= len(v)):
|
|
295
|
+
raise ValueError('the type must be an integer between 1 and len(v)')
|
|
296
|
+
self._type = t
|
|
297
|
+
|
|
298
|
+
if color is None:
|
|
299
|
+
if self._type == 1:
|
|
300
|
+
color = Color((1, 0, 0))
|
|
301
|
+
elif self._type == 2:
|
|
302
|
+
color = Color((0, 1, 0))
|
|
303
|
+
elif self._type == 3:
|
|
304
|
+
color = Color((0, 0, 1))
|
|
305
|
+
else:
|
|
306
|
+
color = Color()
|
|
307
|
+
self._color = Color(color)
|
|
308
|
+
|
|
309
|
+
def __repr__(self) -> str:
|
|
310
|
+
r"""
|
|
311
|
+
String representation of a face.
|
|
312
|
+
|
|
313
|
+
EXAMPLES::
|
|
314
|
+
|
|
315
|
+
sage: from sage.combinat.e_one_star import Face
|
|
316
|
+
sage: f = Face((0,0,0,3), 3)
|
|
317
|
+
sage: f
|
|
318
|
+
[(0, 0, 0, 3), 3]*
|
|
319
|
+
|
|
320
|
+
::
|
|
321
|
+
|
|
322
|
+
sage: f = Face((0,0,0,3), 3)
|
|
323
|
+
sage: f
|
|
324
|
+
[(0, 0, 0, 3), 3]*
|
|
325
|
+
"""
|
|
326
|
+
return "[%s, %s]*" % (self.vector(), self.type())
|
|
327
|
+
|
|
328
|
+
__richcmp__ = richcmp_by_eq_and_lt('_eq', '_lt')
|
|
329
|
+
|
|
330
|
+
def _eq(self, other) -> bool:
|
|
331
|
+
r"""
|
|
332
|
+
Equality of faces.
|
|
333
|
+
|
|
334
|
+
EXAMPLES::
|
|
335
|
+
|
|
336
|
+
sage: from sage.combinat.e_one_star import Face
|
|
337
|
+
sage: f = Face((0,0,0,3), 3)
|
|
338
|
+
sage: g = Face((0,0,0,3), 3)
|
|
339
|
+
sage: f == g
|
|
340
|
+
True
|
|
341
|
+
"""
|
|
342
|
+
return (isinstance(other, Face) and
|
|
343
|
+
self.vector() == other.vector() and
|
|
344
|
+
self.type() == other.type())
|
|
345
|
+
|
|
346
|
+
def _lt(self, other) -> bool:
|
|
347
|
+
r"""
|
|
348
|
+
Compare ``self`` and ``other``.
|
|
349
|
+
|
|
350
|
+
The vectors of the faces are first compared,
|
|
351
|
+
and the types of the faces are compared if the vectors are equal.
|
|
352
|
+
|
|
353
|
+
EXAMPLES::
|
|
354
|
+
|
|
355
|
+
sage: from sage.combinat.e_one_star import Face
|
|
356
|
+
sage: Face([-2,1,0], 2) < Face([-1,2,2],3)
|
|
357
|
+
True
|
|
358
|
+
sage: Face([-2,1,0], 2) < Face([-2,1,0],3)
|
|
359
|
+
True
|
|
360
|
+
sage: Face([-2,1,0], 2) < Face([-2,1,0],2)
|
|
361
|
+
False
|
|
362
|
+
"""
|
|
363
|
+
if self.vector() < other.vector():
|
|
364
|
+
return True
|
|
365
|
+
if self.vector() == other.vector():
|
|
366
|
+
return self.type() < other.type()
|
|
367
|
+
return False
|
|
368
|
+
|
|
369
|
+
def __hash__(self) -> int:
|
|
370
|
+
r"""
|
|
371
|
+
EXAMPLES::
|
|
372
|
+
|
|
373
|
+
sage: from sage.combinat.e_one_star import Face
|
|
374
|
+
sage: f = Face((0,0,0,3), 3)
|
|
375
|
+
sage: g = Face((0,0,0,3), 3)
|
|
376
|
+
sage: hash(f) == hash(g)
|
|
377
|
+
True
|
|
378
|
+
"""
|
|
379
|
+
return hash((self.vector(), self.type()))
|
|
380
|
+
|
|
381
|
+
def __add__(self, other):
|
|
382
|
+
r"""
|
|
383
|
+
Addition of ``self`` with a Face, a Patch or a finite iterable of faces.
|
|
384
|
+
|
|
385
|
+
INPUT:
|
|
386
|
+
|
|
387
|
+
- ``other`` -- a Patch or a Face or a finite iterable of faces
|
|
388
|
+
|
|
389
|
+
EXAMPLES::
|
|
390
|
+
|
|
391
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
392
|
+
sage: f = Face([0,0,0], 3)
|
|
393
|
+
sage: g = Face([0,1,-1], 2)
|
|
394
|
+
sage: f + g
|
|
395
|
+
Patch: [[(0, 0, 0), 3]*, [(0, 1, -1), 2]*]
|
|
396
|
+
sage: P = Patch([Face([0,0,0], 1), Face([0,0,0], 2)])
|
|
397
|
+
sage: f + P
|
|
398
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*]
|
|
399
|
+
|
|
400
|
+
Adding a finite iterable of faces::
|
|
401
|
+
|
|
402
|
+
sage: from sage.combinat.e_one_star import Face
|
|
403
|
+
sage: f = Face([0,0,0], 3)
|
|
404
|
+
sage: f + [f,f]
|
|
405
|
+
Patch: [[(0, 0, 0), 3]*]
|
|
406
|
+
"""
|
|
407
|
+
if isinstance(other, Face):
|
|
408
|
+
return Patch([self, other])
|
|
409
|
+
else:
|
|
410
|
+
return Patch(other).union(self)
|
|
411
|
+
|
|
412
|
+
def vector(self):
|
|
413
|
+
r"""
|
|
414
|
+
Return the vector of the face.
|
|
415
|
+
|
|
416
|
+
EXAMPLES::
|
|
417
|
+
|
|
418
|
+
sage: from sage.combinat.e_one_star import Face
|
|
419
|
+
sage: f = Face((0,2,0), 3)
|
|
420
|
+
sage: f.vector()
|
|
421
|
+
(0, 2, 0)
|
|
422
|
+
"""
|
|
423
|
+
return self._vector
|
|
424
|
+
|
|
425
|
+
def type(self):
|
|
426
|
+
r"""
|
|
427
|
+
Return the type of the face.
|
|
428
|
+
|
|
429
|
+
EXAMPLES::
|
|
430
|
+
|
|
431
|
+
sage: from sage.combinat.e_one_star import Face
|
|
432
|
+
sage: f = Face((0,2,0), 3)
|
|
433
|
+
sage: f.type()
|
|
434
|
+
3
|
|
435
|
+
|
|
436
|
+
::
|
|
437
|
+
|
|
438
|
+
sage: f = Face((0,2,0), 3)
|
|
439
|
+
sage: f.type()
|
|
440
|
+
3
|
|
441
|
+
"""
|
|
442
|
+
return self._type
|
|
443
|
+
|
|
444
|
+
def color(self, color=None):
|
|
445
|
+
r"""
|
|
446
|
+
Return or change the color of the face.
|
|
447
|
+
|
|
448
|
+
INPUT:
|
|
449
|
+
|
|
450
|
+
- ``color`` -- string, rgb tuple, color (default: ``None``)
|
|
451
|
+
the new color to assign to the face. If ``None``, it returns the
|
|
452
|
+
color of the face.
|
|
453
|
+
|
|
454
|
+
OUTPUT: color or None
|
|
455
|
+
|
|
456
|
+
EXAMPLES::
|
|
457
|
+
|
|
458
|
+
sage: from sage.combinat.e_one_star import Face
|
|
459
|
+
sage: f = Face((0,2,0), 3)
|
|
460
|
+
sage: f.color()
|
|
461
|
+
RGB color (0.0, 0.0, 1.0)
|
|
462
|
+
sage: f.color('red')
|
|
463
|
+
sage: f.color()
|
|
464
|
+
RGB color (1.0, 0.0, 0.0)
|
|
465
|
+
"""
|
|
466
|
+
if color is not None:
|
|
467
|
+
self._color = Color(color)
|
|
468
|
+
else:
|
|
469
|
+
return self._color
|
|
470
|
+
|
|
471
|
+
def _plot(self, projmat, face_contour, opacity) -> Graphics:
|
|
472
|
+
r"""
|
|
473
|
+
Return a 2D graphic object representing the face.
|
|
474
|
+
|
|
475
|
+
INPUT:
|
|
476
|
+
|
|
477
|
+
- ``projmat`` -- 2*3 projection matrix (used only for faces in three dimensions)
|
|
478
|
+
- ``face_contour`` -- dict, maps the face type to vectors describing
|
|
479
|
+
the contour of unit faces (used only for faces in three dimensions)
|
|
480
|
+
- ``opacity`` -- the alpha value for the color of the face
|
|
481
|
+
|
|
482
|
+
OUTPUT: 2D graphic object
|
|
483
|
+
|
|
484
|
+
EXAMPLES::
|
|
485
|
+
|
|
486
|
+
sage: from sage.combinat.e_one_star import Face
|
|
487
|
+
sage: f = Face((0,0,3), 3)
|
|
488
|
+
sage: projmat = matrix(2, [-1.7320508075688772*0.5, 1.7320508075688772*0.5, 0, -0.5, -0.5, 1])
|
|
489
|
+
sage: face_contour = {}
|
|
490
|
+
sage: face_contour[1] = map(vector, [(0,0,0),(0,1,0),(0,1,1),(0,0,1)])
|
|
491
|
+
sage: face_contour[2] = map(vector, [(0,0,0),(0,0,1),(1,0,1),(1,0,0)])
|
|
492
|
+
sage: face_contour[3] = map(vector, [(0,0,0),(1,0,0),(1,1,0),(0,1,0)])
|
|
493
|
+
sage: G = f._plot(projmat, face_contour, 0.75) # needs sage.plot
|
|
494
|
+
|
|
495
|
+
::
|
|
496
|
+
|
|
497
|
+
sage: f = Face((0,0), 2)
|
|
498
|
+
sage: f._plot(None, None, 1) # needs sage.plot
|
|
499
|
+
Graphics object consisting of 1 graphics primitive
|
|
500
|
+
"""
|
|
501
|
+
v = self.vector()
|
|
502
|
+
t = self.type()
|
|
503
|
+
G = Graphics()
|
|
504
|
+
|
|
505
|
+
if len(v) == 2:
|
|
506
|
+
if t == 1:
|
|
507
|
+
G += line([v, v + vector([0, 1])], rgbcolor=self.color(), thickness=1.5, alpha=opacity)
|
|
508
|
+
elif t == 2:
|
|
509
|
+
G += line([v, v + vector([1, 0])], rgbcolor=self.color(), thickness=1.5, alpha=opacity)
|
|
510
|
+
|
|
511
|
+
elif len(v) == 3:
|
|
512
|
+
G += polygon([projmat * (u + v)
|
|
513
|
+
for u in face_contour[t]], alpha=opacity,
|
|
514
|
+
thickness=1, rgbcolor=self.color())
|
|
515
|
+
|
|
516
|
+
else:
|
|
517
|
+
raise NotImplementedError("plotting is implemented only for patches in two or three dimensions.")
|
|
518
|
+
|
|
519
|
+
return G
|
|
520
|
+
|
|
521
|
+
def _plot3d(self, face_contour):
|
|
522
|
+
r"""
|
|
523
|
+
3D representation of a unit face (Jmol).
|
|
524
|
+
|
|
525
|
+
INPUT:
|
|
526
|
+
|
|
527
|
+
- ``face_contour`` -- dict, maps the face type to vectors describing
|
|
528
|
+
the contour of unit faces
|
|
529
|
+
|
|
530
|
+
EXAMPLES::
|
|
531
|
+
|
|
532
|
+
sage: from sage.combinat.e_one_star import Face
|
|
533
|
+
sage: f = Face((0,0,3), 3)
|
|
534
|
+
sage: face_contour = {1: map(vector, [(0,0,0),(0,1,0),(0,1,1),(0,0,1)]), 2: map(vector, [(0,0,0),(0,0,1),(1,0,1),(1,0,0)]), 3: map(vector, [(0,0,0),(1,0,0),(1,1,0),(0,1,0)])}
|
|
535
|
+
sage: G = f._plot3d(face_contour) #not tested
|
|
536
|
+
"""
|
|
537
|
+
v = self.vector()
|
|
538
|
+
t = self.type()
|
|
539
|
+
c = self.color()
|
|
540
|
+
G = polygon([u + v for u in face_contour[t]], rgbcolor=c)
|
|
541
|
+
return G
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
class Patch(SageObject):
|
|
545
|
+
r"""
|
|
546
|
+
A class to model a collection of faces. A patch is represented by an immutable set of Faces.
|
|
547
|
+
|
|
548
|
+
.. NOTE::
|
|
549
|
+
|
|
550
|
+
The dimension of a patch is the length of the vectors of the faces in the patch,
|
|
551
|
+
which is assumed to be the same for every face in the patch.
|
|
552
|
+
|
|
553
|
+
.. NOTE::
|
|
554
|
+
|
|
555
|
+
Since version 4.7.1, Patches are immutable, except for the colors of the faces,
|
|
556
|
+
which are not taken into account for equality tests and hash functions.
|
|
557
|
+
|
|
558
|
+
INPUT:
|
|
559
|
+
|
|
560
|
+
- ``faces`` -- finite iterable of faces
|
|
561
|
+
- ``face_contour`` -- dictionary (default: ``None``); maps the face
|
|
562
|
+
type to vectors describing the contour of unit faces. If ``None``,
|
|
563
|
+
defaults contour are assumed for faces of type 1, 2, 3 or 1, 2, 3.
|
|
564
|
+
Used in plotting methods only.
|
|
565
|
+
|
|
566
|
+
EXAMPLES::
|
|
567
|
+
|
|
568
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
569
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
570
|
+
sage: P
|
|
571
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*]
|
|
572
|
+
|
|
573
|
+
::
|
|
574
|
+
|
|
575
|
+
sage: face_contour = {}
|
|
576
|
+
sage: face_contour[1] = map(vector, [(0,0,0),(0,1,0),(0,1,1),(0,0,1)])
|
|
577
|
+
sage: face_contour[2] = map(vector, [(0,0,0),(0,0,1),(1,0,1),(1,0,0)])
|
|
578
|
+
sage: face_contour[3] = map(vector, [(0,0,0),(1,0,0),(1,1,0),(0,1,0)])
|
|
579
|
+
sage: Patch([Face((0,0,0),t) for t in [1,2,3]], face_contour=face_contour)
|
|
580
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*]
|
|
581
|
+
"""
|
|
582
|
+
|
|
583
|
+
def __init__(self, faces, face_contour=None):
|
|
584
|
+
r"""
|
|
585
|
+
Constructor of a patch (set of faces).
|
|
586
|
+
|
|
587
|
+
See class doc for more information.
|
|
588
|
+
|
|
589
|
+
EXAMPLES::
|
|
590
|
+
|
|
591
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
592
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
593
|
+
sage: P
|
|
594
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*]
|
|
595
|
+
|
|
596
|
+
TESTS:
|
|
597
|
+
|
|
598
|
+
We test that colors are not anymore mixed up between
|
|
599
|
+
Patches (see :issue:`11255`)::
|
|
600
|
+
|
|
601
|
+
sage: P = Patch([Face([0,0,0],2)])
|
|
602
|
+
sage: Q = Patch(P)
|
|
603
|
+
sage: next(iter(P)).color()
|
|
604
|
+
RGB color (0.0, 1.0, 0.0)
|
|
605
|
+
sage: next(iter(Q)).color('yellow')
|
|
606
|
+
sage: next(iter(P)).color()
|
|
607
|
+
RGB color (0.0, 1.0, 0.0)
|
|
608
|
+
"""
|
|
609
|
+
self._faces = frozenset(Face(f.vector(), f.type(), f.color()) for f in faces)
|
|
610
|
+
|
|
611
|
+
try:
|
|
612
|
+
f0 = next(iter(self._faces))
|
|
613
|
+
except StopIteration:
|
|
614
|
+
self._dimension = None
|
|
615
|
+
else:
|
|
616
|
+
self._dimension = len(f0.vector())
|
|
617
|
+
|
|
618
|
+
if face_contour is not None:
|
|
619
|
+
self._face_contour = face_contour
|
|
620
|
+
|
|
621
|
+
else:
|
|
622
|
+
self._face_contour = {
|
|
623
|
+
1: [vector(t) for t in [(0, 0, 0), (0, 1, 0),
|
|
624
|
+
(0, 1, 1), (0, 0, 1)]],
|
|
625
|
+
2: [vector(t) for t in [(0, 0, 0), (0, 0, 1),
|
|
626
|
+
(1, 0, 1), (1, 0, 0)]],
|
|
627
|
+
3: [vector(t) for t in [(0, 0, 0), (1, 0, 0),
|
|
628
|
+
(1, 1, 0), (0, 1, 0)]]
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
def __eq__(self, other) -> bool:
|
|
632
|
+
r"""
|
|
633
|
+
Equality test for Patch.
|
|
634
|
+
|
|
635
|
+
INPUT:
|
|
636
|
+
|
|
637
|
+
- ``other`` -- an object
|
|
638
|
+
|
|
639
|
+
EXAMPLES::
|
|
640
|
+
|
|
641
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
642
|
+
sage: P = Patch([Face((0,0,0),1), Face((0,0,0),2), Face((0,0,0),3)])
|
|
643
|
+
sage: Q = Patch([Face((0,1,0),1), Face((0,0,0),3)])
|
|
644
|
+
sage: P == P
|
|
645
|
+
True
|
|
646
|
+
sage: P == Q
|
|
647
|
+
False
|
|
648
|
+
sage: P == 4
|
|
649
|
+
False
|
|
650
|
+
|
|
651
|
+
::
|
|
652
|
+
|
|
653
|
+
sage: s = WordMorphism({1:[1,3], 2:[1,2,3], 3:[3]})
|
|
654
|
+
sage: t = WordMorphism({1:[1,2,3], 2:[2,3], 3:[3]})
|
|
655
|
+
sage: P = Patch([Face((0,0,0), 1), Face((0,0,0), 2), Face((0,0,0), 3)])
|
|
656
|
+
sage: E1Star(s)(P) == E1Star(t)(P)
|
|
657
|
+
False
|
|
658
|
+
sage: E1Star(s*t)(P) == E1Star(t)(E1Star(s)(P))
|
|
659
|
+
True
|
|
660
|
+
"""
|
|
661
|
+
return (isinstance(other, Patch) and self._faces == other._faces)
|
|
662
|
+
|
|
663
|
+
def __hash__(self) -> int:
|
|
664
|
+
r"""
|
|
665
|
+
Hash function of Patch.
|
|
666
|
+
|
|
667
|
+
EXAMPLES::
|
|
668
|
+
|
|
669
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
670
|
+
sage: x = [Face((0,0,0),t) for t in [1,2,3]]
|
|
671
|
+
sage: P = Patch(x)
|
|
672
|
+
sage: hash(P) #random
|
|
673
|
+
-4839605361791007520
|
|
674
|
+
|
|
675
|
+
TESTS:
|
|
676
|
+
|
|
677
|
+
We test that two equal patches have the same hash (see :issue:`11255`)::
|
|
678
|
+
|
|
679
|
+
sage: P = Patch([Face([0,0,0],1), Face([0,0,0],2)])
|
|
680
|
+
sage: Q = Patch([Face([0,0,0],2), Face([0,0,0],1)])
|
|
681
|
+
sage: P == Q
|
|
682
|
+
True
|
|
683
|
+
sage: hash(P) == hash(Q)
|
|
684
|
+
True
|
|
685
|
+
|
|
686
|
+
Changing the color does not affect the hash value::
|
|
687
|
+
|
|
688
|
+
sage: p = Patch([Face((0,0,0), t) for t in [1,2,3]])
|
|
689
|
+
sage: H1 = hash(p)
|
|
690
|
+
sage: p.repaint(['blue'])
|
|
691
|
+
sage: H2 = hash(p)
|
|
692
|
+
sage: H1 == H2
|
|
693
|
+
True
|
|
694
|
+
"""
|
|
695
|
+
return hash(self._faces)
|
|
696
|
+
|
|
697
|
+
def __len__(self) -> int:
|
|
698
|
+
r"""
|
|
699
|
+
Return the number of faces contained in the patch.
|
|
700
|
+
|
|
701
|
+
OUTPUT: integer
|
|
702
|
+
|
|
703
|
+
EXAMPLES::
|
|
704
|
+
|
|
705
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
706
|
+
sage: x = [Face((0,0,0),t) for t in [1,2,3]]
|
|
707
|
+
sage: P = Patch(x)
|
|
708
|
+
sage: len(P) #indirect doctest
|
|
709
|
+
3
|
|
710
|
+
"""
|
|
711
|
+
return len(self._faces)
|
|
712
|
+
|
|
713
|
+
def __iter__(self):
|
|
714
|
+
r"""
|
|
715
|
+
Return an iterator over the faces of the patch.
|
|
716
|
+
|
|
717
|
+
OUTPUT: iterator
|
|
718
|
+
|
|
719
|
+
EXAMPLES::
|
|
720
|
+
|
|
721
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
722
|
+
sage: x = [Face((0,0,0),t) for t in [1,2,3]]
|
|
723
|
+
sage: P = Patch(x)
|
|
724
|
+
sage: it = iter(P)
|
|
725
|
+
sage: type(next(it))
|
|
726
|
+
<class 'sage.combinat.e_one_star.Face'>
|
|
727
|
+
sage: type(next(it))
|
|
728
|
+
<class 'sage.combinat.e_one_star.Face'>
|
|
729
|
+
sage: type(next(it))
|
|
730
|
+
<class 'sage.combinat.e_one_star.Face'>
|
|
731
|
+
sage: type(next(it))
|
|
732
|
+
Traceback (most recent call last):
|
|
733
|
+
...
|
|
734
|
+
StopIteration
|
|
735
|
+
"""
|
|
736
|
+
return iter(self._faces)
|
|
737
|
+
|
|
738
|
+
def __add__(self, other):
|
|
739
|
+
r"""
|
|
740
|
+
Addition of patches (union).
|
|
741
|
+
|
|
742
|
+
INPUT:
|
|
743
|
+
|
|
744
|
+
- ``other`` -- a Patch or a Face or a finite iterable of faces
|
|
745
|
+
|
|
746
|
+
EXAMPLES::
|
|
747
|
+
|
|
748
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
749
|
+
sage: P = Patch([Face([0,0,0], 1), Face([0,0,0], 2)])
|
|
750
|
+
sage: Q = P.translate([1,-1,0])
|
|
751
|
+
sage: P + Q
|
|
752
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(1, -1, 0), 1]*, [(1, -1, 0), 2]*]
|
|
753
|
+
sage: P + Face([0,0,0],3)
|
|
754
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*]
|
|
755
|
+
sage: P + [Face([0,0,0],3), Face([1,1,1],2)]
|
|
756
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*, [(1, 1, 1), 2]*]
|
|
757
|
+
"""
|
|
758
|
+
return self.union(other)
|
|
759
|
+
|
|
760
|
+
def __sub__(self, other):
|
|
761
|
+
r"""
|
|
762
|
+
Subtraction of patches (difference).
|
|
763
|
+
|
|
764
|
+
INPUT:
|
|
765
|
+
|
|
766
|
+
- ``other`` -- a Patch or a Face or a finite iterable of faces
|
|
767
|
+
|
|
768
|
+
EXAMPLES::
|
|
769
|
+
|
|
770
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
771
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
772
|
+
sage: P - Face([0,0,0],2)
|
|
773
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 3]*]
|
|
774
|
+
sage: P - P
|
|
775
|
+
Patch: []
|
|
776
|
+
"""
|
|
777
|
+
return self.difference(other)
|
|
778
|
+
|
|
779
|
+
def __repr__(self) -> str:
|
|
780
|
+
r"""
|
|
781
|
+
String representation of a patch.
|
|
782
|
+
|
|
783
|
+
Displays all the faces if there less than 20,
|
|
784
|
+
otherwise displays only the number of faces.
|
|
785
|
+
|
|
786
|
+
EXAMPLES::
|
|
787
|
+
|
|
788
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
789
|
+
sage: x = [Face((0,0,0),t) for t in [1,2,3]]
|
|
790
|
+
sage: P = Patch(x)
|
|
791
|
+
sage: P
|
|
792
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*]
|
|
793
|
+
|
|
794
|
+
::
|
|
795
|
+
|
|
796
|
+
sage: x = [Face((0,0,a),1) for a in range(25)]
|
|
797
|
+
sage: P = Patch(x)
|
|
798
|
+
sage: P
|
|
799
|
+
Patch of 25 faces
|
|
800
|
+
"""
|
|
801
|
+
if len(self) <= 20:
|
|
802
|
+
L = list(self)
|
|
803
|
+
L.sort(key=lambda x: (x.vector(), x.type()))
|
|
804
|
+
return "Patch: %s" % L
|
|
805
|
+
else:
|
|
806
|
+
return "Patch of %s faces" % len(self)
|
|
807
|
+
|
|
808
|
+
def union(self, other) -> Patch:
|
|
809
|
+
r"""
|
|
810
|
+
Return a Patch consisting of the union of ``self`` and ``other``.
|
|
811
|
+
|
|
812
|
+
INPUT:
|
|
813
|
+
|
|
814
|
+
- ``other`` -- a Patch or a Face or a finite iterable of faces
|
|
815
|
+
|
|
816
|
+
EXAMPLES::
|
|
817
|
+
|
|
818
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
819
|
+
sage: P = Patch([Face((0,0,0),1), Face((0,0,0),2)])
|
|
820
|
+
sage: P.union(Face((1,2,3), 3))
|
|
821
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(1, 2, 3), 3]*]
|
|
822
|
+
sage: P.union([Face((1,2,3), 3), Face((2,3,3), 2)])
|
|
823
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(1, 2, 3), 3]*, [(2, 3, 3), 2]*]
|
|
824
|
+
"""
|
|
825
|
+
if isinstance(other, Face):
|
|
826
|
+
return Patch(self._faces.union([other]))
|
|
827
|
+
else:
|
|
828
|
+
return Patch(self._faces.union(other))
|
|
829
|
+
|
|
830
|
+
def difference(self, other) -> Patch:
|
|
831
|
+
r"""
|
|
832
|
+
Return the difference of ``self`` and ``other``.
|
|
833
|
+
|
|
834
|
+
INPUT:
|
|
835
|
+
|
|
836
|
+
- ``other`` -- a finite iterable of faces or a single face
|
|
837
|
+
|
|
838
|
+
EXAMPLES::
|
|
839
|
+
|
|
840
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
841
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
842
|
+
sage: P.difference(Face([0,0,0],2))
|
|
843
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 3]*]
|
|
844
|
+
sage: P.difference(P)
|
|
845
|
+
Patch: []
|
|
846
|
+
"""
|
|
847
|
+
if isinstance(other, Face):
|
|
848
|
+
return Patch(self._faces.difference([other]))
|
|
849
|
+
else:
|
|
850
|
+
return Patch(self._faces.difference(other))
|
|
851
|
+
|
|
852
|
+
def dimension(self) -> None | int:
|
|
853
|
+
r"""
|
|
854
|
+
Return the dimension of the vectors of the faces of ``self``.
|
|
855
|
+
|
|
856
|
+
It returns ``None`` if ``self`` is the empty patch.
|
|
857
|
+
|
|
858
|
+
The dimension of a patch is the length of the vectors of the faces in the patch,
|
|
859
|
+
which is assumed to be the same for every face in the patch.
|
|
860
|
+
|
|
861
|
+
EXAMPLES::
|
|
862
|
+
|
|
863
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
864
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
865
|
+
sage: P.dimension()
|
|
866
|
+
3
|
|
867
|
+
|
|
868
|
+
TESTS::
|
|
869
|
+
|
|
870
|
+
sage: from sage.combinat.e_one_star import Patch
|
|
871
|
+
sage: p = Patch([])
|
|
872
|
+
sage: p.dimension() is None
|
|
873
|
+
True
|
|
874
|
+
|
|
875
|
+
It works when the patch is created from an iterator::
|
|
876
|
+
|
|
877
|
+
sage: p = Patch(Face((0,0,0),t) for t in [1,2,3])
|
|
878
|
+
sage: p.dimension()
|
|
879
|
+
3
|
|
880
|
+
"""
|
|
881
|
+
return self._dimension
|
|
882
|
+
|
|
883
|
+
def faces_of_vector(self, v) -> list[Face]:
|
|
884
|
+
r"""
|
|
885
|
+
Return a list of the faces whose vector is ``v``.
|
|
886
|
+
|
|
887
|
+
INPUT:
|
|
888
|
+
|
|
889
|
+
- ``v`` -- a vector
|
|
890
|
+
|
|
891
|
+
EXAMPLES::
|
|
892
|
+
|
|
893
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
894
|
+
sage: P = Patch([Face((0,0,0),1), Face((1,2,0),3), Face((1,2,0),1)])
|
|
895
|
+
sage: sorted(P.faces_of_vector([1,2,0]))
|
|
896
|
+
[[(1, 2, 0), 1]*, [(1, 2, 0), 3]*]
|
|
897
|
+
"""
|
|
898
|
+
v = vector(v)
|
|
899
|
+
return [f for f in self if f.vector() == v]
|
|
900
|
+
|
|
901
|
+
def faces_of_type(self, t) -> list[Face]:
|
|
902
|
+
r"""
|
|
903
|
+
Return a list of the faces that have type ``t``.
|
|
904
|
+
|
|
905
|
+
INPUT:
|
|
906
|
+
|
|
907
|
+
- ``t`` -- integer or any other type
|
|
908
|
+
|
|
909
|
+
EXAMPLES::
|
|
910
|
+
|
|
911
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
912
|
+
sage: P = Patch([Face((0,0,0),1), Face((1,2,0),3), Face((1,2,0),1)])
|
|
913
|
+
sage: sorted(P.faces_of_type(1))
|
|
914
|
+
[[(0, 0, 0), 1]*, [(1, 2, 0), 1]*]
|
|
915
|
+
"""
|
|
916
|
+
return [f for f in self if f.type() == t]
|
|
917
|
+
|
|
918
|
+
def faces_of_color(self, color) -> list[Face]:
|
|
919
|
+
r"""
|
|
920
|
+
Return a list of the faces that have the given color.
|
|
921
|
+
|
|
922
|
+
INPUT:
|
|
923
|
+
|
|
924
|
+
- ``color`` -- color
|
|
925
|
+
|
|
926
|
+
EXAMPLES::
|
|
927
|
+
|
|
928
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
929
|
+
sage: P = Patch([Face((0,0,0),1, 'red'), Face((1,2,0),3, 'blue'), Face((1,2,0),1, 'red')])
|
|
930
|
+
sage: sorted(P.faces_of_color('red'))
|
|
931
|
+
[[(0, 0, 0), 1]*, [(1, 2, 0), 1]*]
|
|
932
|
+
"""
|
|
933
|
+
color = tuple(Color(color))
|
|
934
|
+
return [f for f in self if tuple(f.color()) == color]
|
|
935
|
+
|
|
936
|
+
def translate(self, v) -> Patch:
|
|
937
|
+
r"""
|
|
938
|
+
Return a translated copy of ``self`` by vector `v`.
|
|
939
|
+
|
|
940
|
+
INPUT:
|
|
941
|
+
|
|
942
|
+
- ``v`` -- vector or tuple
|
|
943
|
+
|
|
944
|
+
EXAMPLES::
|
|
945
|
+
|
|
946
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
947
|
+
sage: P = Patch([Face((0,0,0),1), Face((1,2,0),3), Face((1,2,0),1)])
|
|
948
|
+
sage: P.translate([-1,-2,0])
|
|
949
|
+
Patch: [[(-1, -2, 0), 1]*, [(0, 0, 0), 1]*, [(0, 0, 0), 3]*]
|
|
950
|
+
"""
|
|
951
|
+
v = vector(v)
|
|
952
|
+
return Patch(Face(f.vector() + v, f.type(), f.color()) for f in self)
|
|
953
|
+
|
|
954
|
+
def occurrences_of(self, other) -> list:
|
|
955
|
+
r"""
|
|
956
|
+
Return all positions at which other appears in self, that is,
|
|
957
|
+
all vectors v such that ``set(other.translate(v)) <= set(self)``.
|
|
958
|
+
|
|
959
|
+
INPUT:
|
|
960
|
+
|
|
961
|
+
- ``other`` -- a Patch
|
|
962
|
+
|
|
963
|
+
OUTPUT: list of vectors
|
|
964
|
+
|
|
965
|
+
EXAMPLES::
|
|
966
|
+
|
|
967
|
+
sage: from sage.combinat.e_one_star import Face, Patch, E1Star
|
|
968
|
+
sage: P = Patch([Face([0,0,0], 1), Face([0,0,0], 2), Face([0,0,0], 3)])
|
|
969
|
+
sage: Q = Patch([Face([0,0,0], 1), Face([0,0,0], 2)])
|
|
970
|
+
sage: P.occurrences_of(Q)
|
|
971
|
+
[(0, 0, 0)]
|
|
972
|
+
sage: Q = Q.translate([1,2,3])
|
|
973
|
+
sage: P.occurrences_of(Q)
|
|
974
|
+
[(-1, -2, -3)]
|
|
975
|
+
|
|
976
|
+
::
|
|
977
|
+
|
|
978
|
+
sage: E = E1Star(WordMorphism({1:[1,2], 2:[1,3], 3:[1]}))
|
|
979
|
+
sage: P = Patch([Face([0,0,0], 1), Face([0,0,0], 2), Face([0,0,0], 3)])
|
|
980
|
+
sage: P = E(P,4)
|
|
981
|
+
sage: Q = Patch([Face([0,0,0], 1), Face([0,0,0], 2)])
|
|
982
|
+
sage: L = P.occurrences_of(Q)
|
|
983
|
+
sage: sorted(L)
|
|
984
|
+
[(0, 0, 0), (0, 0, 1), (0, 1, -1), (1, 0, -1), (1, 1, -3), (1, 1, -2)]
|
|
985
|
+
"""
|
|
986
|
+
f0 = next(iter(other))
|
|
987
|
+
x = f0.vector()
|
|
988
|
+
t = f0.type()
|
|
989
|
+
L = self.faces_of_type(t)
|
|
990
|
+
positions = []
|
|
991
|
+
for f in L:
|
|
992
|
+
y = f.vector()
|
|
993
|
+
if other.translate(y - x)._faces.issubset(self._faces):
|
|
994
|
+
positions.append(y - x)
|
|
995
|
+
return positions
|
|
996
|
+
|
|
997
|
+
def repaint(self, cmap='Set1') -> None:
|
|
998
|
+
r"""
|
|
999
|
+
Repaint all the faces of ``self`` from the given color map.
|
|
1000
|
+
|
|
1001
|
+
This only changes the colors of the faces of ``self``.
|
|
1002
|
+
|
|
1003
|
+
INPUT:
|
|
1004
|
+
|
|
1005
|
+
- ``cmap`` -- color map (default: ``'Set1'``). It can be one of the
|
|
1006
|
+
following:
|
|
1007
|
+
|
|
1008
|
+
- ``string`` -- a coloring map; for available coloring map names type:
|
|
1009
|
+
``sorted(colormaps)``
|
|
1010
|
+
- ``list`` -- list of colors to assign cyclically to the faces
|
|
1011
|
+
A list of a single color colors all the faces with the same color
|
|
1012
|
+
- ``dict`` -- dictionary of face types mapped to colors, to color the
|
|
1013
|
+
faces according to their type
|
|
1014
|
+
- ``{}``, the empty dict -- shortcut for
|
|
1015
|
+
``{1:'red', 2:'green', 3:'blue'}``
|
|
1016
|
+
|
|
1017
|
+
EXAMPLES:
|
|
1018
|
+
|
|
1019
|
+
Using a color map::
|
|
1020
|
+
|
|
1021
|
+
sage: from sage.combinat.e_one_star import Face, Patch
|
|
1022
|
+
sage: color = (0, 0, 0)
|
|
1023
|
+
sage: P = Patch([Face((0,0,0),t,color) for t in [1,2,3]])
|
|
1024
|
+
sage: for f in P: f.color()
|
|
1025
|
+
RGB color (0.0, 0.0, 0.0)
|
|
1026
|
+
RGB color (0.0, 0.0, 0.0)
|
|
1027
|
+
RGB color (0.0, 0.0, 0.0)
|
|
1028
|
+
sage: P.repaint()
|
|
1029
|
+
sage: next(iter(P)).color() #random
|
|
1030
|
+
RGB color (0.498..., 0.432..., 0.522...)
|
|
1031
|
+
|
|
1032
|
+
Using a list of colors::
|
|
1033
|
+
|
|
1034
|
+
sage: P = Patch([Face((0,0,0),t,color) for t in [1,2,3]])
|
|
1035
|
+
sage: P.repaint([(0.9, 0.9, 0.9), (0.65,0.65,0.65), (0.4,0.4,0.4)])
|
|
1036
|
+
sage: for f in P: f.color()
|
|
1037
|
+
RGB color (0.9, 0.9, 0.9)
|
|
1038
|
+
RGB color (0.65, 0.65, 0.65)
|
|
1039
|
+
RGB color (0.4, 0.4, 0.4)
|
|
1040
|
+
|
|
1041
|
+
Using a dictionary to color faces according to their type::
|
|
1042
|
+
|
|
1043
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1044
|
+
sage: P.repaint({1:'black', 2:'yellow', 3:'green'})
|
|
1045
|
+
sage: P.plot() #not tested
|
|
1046
|
+
sage: P.repaint({})
|
|
1047
|
+
sage: P.plot() #not tested
|
|
1048
|
+
"""
|
|
1049
|
+
if cmap == {}:
|
|
1050
|
+
cmap = {1: 'red', 2: 'green', 3: 'blue'}
|
|
1051
|
+
|
|
1052
|
+
if isinstance(cmap, dict):
|
|
1053
|
+
for f in self:
|
|
1054
|
+
f.color(cmap[f.type()])
|
|
1055
|
+
|
|
1056
|
+
elif isinstance(cmap, list):
|
|
1057
|
+
L = len(cmap)
|
|
1058
|
+
for i, f in enumerate(self):
|
|
1059
|
+
f.color(cmap[i % L])
|
|
1060
|
+
|
|
1061
|
+
elif isinstance(cmap, str):
|
|
1062
|
+
# matplotlib color maps
|
|
1063
|
+
global cm
|
|
1064
|
+
if cm is None:
|
|
1065
|
+
from matplotlib import cm
|
|
1066
|
+
assert cm is not None
|
|
1067
|
+
if cmap not in cm.datad:
|
|
1068
|
+
raise RuntimeError("color map %s not known (type sorted(colors) for valid names)" % cmap)
|
|
1069
|
+
cmap = cm.__dict__[cmap]
|
|
1070
|
+
dim = float(len(self))
|
|
1071
|
+
for i, f in enumerate(self):
|
|
1072
|
+
f.color(cmap(i / dim)[:3])
|
|
1073
|
+
|
|
1074
|
+
else:
|
|
1075
|
+
raise TypeError("type of cmap (=%s) must be dict, list or str" % cmap)
|
|
1076
|
+
|
|
1077
|
+
def plot(self, projmat=None, opacity=0.75) -> Graphics:
|
|
1078
|
+
r"""
|
|
1079
|
+
Return a 2D graphic object depicting the patch.
|
|
1080
|
+
|
|
1081
|
+
INPUT:
|
|
1082
|
+
|
|
1083
|
+
- ``projmat`` -- matrix (default: ``None``); the projection
|
|
1084
|
+
matrix. Its number of lines must be two. Its number of columns
|
|
1085
|
+
must equal the dimension of the ambient space of the faces. If
|
|
1086
|
+
``None``, the isometric projection is used by default.
|
|
1087
|
+
|
|
1088
|
+
- ``opacity`` -- float between ``0`` and ``1`` (default: ``0.75``)
|
|
1089
|
+
opacity of the face
|
|
1090
|
+
|
|
1091
|
+
.. WARNING::
|
|
1092
|
+
|
|
1093
|
+
Plotting is implemented only for patches in two or three dimensions.
|
|
1094
|
+
|
|
1095
|
+
EXAMPLES::
|
|
1096
|
+
|
|
1097
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1098
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1099
|
+
sage: P.plot() # needs sage.plot
|
|
1100
|
+
Graphics object consisting of 3 graphics primitives
|
|
1101
|
+
|
|
1102
|
+
::
|
|
1103
|
+
|
|
1104
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1105
|
+
sage: E = E1Star(sigma)
|
|
1106
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1107
|
+
sage: P = E(P, 5)
|
|
1108
|
+
sage: P.plot() # needs sage.plot
|
|
1109
|
+
Graphics object consisting of 57 graphics primitives
|
|
1110
|
+
|
|
1111
|
+
Plot with a different projection matrix::
|
|
1112
|
+
|
|
1113
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1114
|
+
sage: E = E1Star(sigma)
|
|
1115
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1116
|
+
sage: M = matrix(2, 3, [1,0,-1,0.3,1,-3])
|
|
1117
|
+
sage: P = E(P, 3)
|
|
1118
|
+
sage: P.plot(projmat=M) # needs sage.plot
|
|
1119
|
+
Graphics object consisting of 17 graphics primitives
|
|
1120
|
+
|
|
1121
|
+
Plot patches made of unit segments::
|
|
1122
|
+
|
|
1123
|
+
sage: P = Patch([Face([0,0], 1), Face([0,0], 2)])
|
|
1124
|
+
sage: E = E1Star(WordMorphism({1:[1,2],2:[1]}))
|
|
1125
|
+
sage: F = E1Star(WordMorphism({1:[1,1,2],2:[2,1]}))
|
|
1126
|
+
sage: E(P,5).plot() # needs sage.plot
|
|
1127
|
+
Graphics object consisting of 21 graphics primitives
|
|
1128
|
+
sage: F(P,3).plot() # needs sage.plot
|
|
1129
|
+
Graphics object consisting of 34 graphics primitives
|
|
1130
|
+
"""
|
|
1131
|
+
if self.dimension() == 2:
|
|
1132
|
+
G = Graphics()
|
|
1133
|
+
for face in self:
|
|
1134
|
+
G += face._plot(None, None, 1)
|
|
1135
|
+
G.set_aspect_ratio(1)
|
|
1136
|
+
return G
|
|
1137
|
+
|
|
1138
|
+
if self.dimension() == 3:
|
|
1139
|
+
if projmat is None:
|
|
1140
|
+
projmat = matrix(2, [-1.7320508075688772 * 0.5,
|
|
1141
|
+
1.7320508075688772 * 0.5,
|
|
1142
|
+
0, -0.5, -0.5, 1])
|
|
1143
|
+
|
|
1144
|
+
G = Graphics()
|
|
1145
|
+
for face in self:
|
|
1146
|
+
G += face._plot(projmat, self._face_contour, opacity)
|
|
1147
|
+
G.set_aspect_ratio(1)
|
|
1148
|
+
return G
|
|
1149
|
+
|
|
1150
|
+
else:
|
|
1151
|
+
raise NotImplementedError("plotting is implemented only for patches in two or three dimensions.")
|
|
1152
|
+
|
|
1153
|
+
def plot3d(self):
|
|
1154
|
+
r"""
|
|
1155
|
+
Return a 3D graphics object depicting the patch.
|
|
1156
|
+
|
|
1157
|
+
.. WARNING::
|
|
1158
|
+
|
|
1159
|
+
3D plotting is implemented only for patches in three dimensions.
|
|
1160
|
+
|
|
1161
|
+
EXAMPLES::
|
|
1162
|
+
|
|
1163
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1164
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1165
|
+
sage: P.plot3d() #not tested
|
|
1166
|
+
|
|
1167
|
+
::
|
|
1168
|
+
|
|
1169
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1170
|
+
sage: E = E1Star(sigma)
|
|
1171
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1172
|
+
sage: P = E(P, 5)
|
|
1173
|
+
sage: P.repaint()
|
|
1174
|
+
sage: P.plot3d() #not tested
|
|
1175
|
+
"""
|
|
1176
|
+
if self.dimension() != 3:
|
|
1177
|
+
raise NotImplementedError("3D plotting is implemented only for patches in three dimensions")
|
|
1178
|
+
|
|
1179
|
+
face_list = [face._plot3d(self._face_contour) for face in self]
|
|
1180
|
+
G = sum(face_list)
|
|
1181
|
+
return G
|
|
1182
|
+
|
|
1183
|
+
def plot_tikz(self, projmat=None, print_tikz_env=True, edgecolor='black',
|
|
1184
|
+
scale=0.25, drawzero=False, extra_code_before='', extra_code_after='') -> str:
|
|
1185
|
+
r"""
|
|
1186
|
+
Return a string containing some TikZ code to be included into
|
|
1187
|
+
a LaTeX document, depicting the patch.
|
|
1188
|
+
|
|
1189
|
+
.. WARNING::
|
|
1190
|
+
|
|
1191
|
+
Tikz Plotting is implemented only for patches in three dimensions.
|
|
1192
|
+
|
|
1193
|
+
INPUT:
|
|
1194
|
+
|
|
1195
|
+
- ``projmat`` -- matrix (default: ``None``); the projection
|
|
1196
|
+
matrix. Its number of lines must be two. Its number of columns
|
|
1197
|
+
must equal the dimension of the ambient space of the faces. If
|
|
1198
|
+
``None``, the isometric projection is used by default.
|
|
1199
|
+
- ``print_tikz_env`` -- boolean (default: ``True``); if ``True``,
|
|
1200
|
+
the tikzpicture environment are printed
|
|
1201
|
+
- ``edgecolor`` -- string (default: ``'black'``); either
|
|
1202
|
+
``'black'`` or ``'facecolor'`` (color of unit face edges)
|
|
1203
|
+
- ``scale`` -- real number (default: ``0.25``) scaling
|
|
1204
|
+
constant for the whole figure
|
|
1205
|
+
- ``drawzero`` -- boolean (default: ``False``); if ``True``,
|
|
1206
|
+
mark the origin by a black dot
|
|
1207
|
+
- ``extra_code_before`` -- string (default: ``''``); extra code to
|
|
1208
|
+
include in the tikz picture
|
|
1209
|
+
- ``extra_code_after`` -- string (default: ``''``); extra code to
|
|
1210
|
+
include in the tikz picture
|
|
1211
|
+
|
|
1212
|
+
EXAMPLES::
|
|
1213
|
+
|
|
1214
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1215
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1216
|
+
sage: s = P.plot_tikz()
|
|
1217
|
+
sage: len(s)
|
|
1218
|
+
602
|
|
1219
|
+
sage: print(s) #not tested
|
|
1220
|
+
\begin{tikzpicture}
|
|
1221
|
+
[x={(-0.216506cm,-0.125000cm)}, y={(0.216506cm,-0.125000cm)}, z={(0.000000cm,0.250000cm)}]
|
|
1222
|
+
\definecolor{facecolor}{rgb}{0.000,1.000,0.000}
|
|
1223
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
1224
|
+
(0, 0, 0) -- (0, 0, 1) -- (1, 0, 1) -- (1, 0, 0) -- cycle;
|
|
1225
|
+
\definecolor{facecolor}{rgb}{1.000,0.000,0.000}
|
|
1226
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
1227
|
+
(0, 0, 0) -- (0, 1, 0) -- (0, 1, 1) -- (0, 0, 1) -- cycle;
|
|
1228
|
+
\definecolor{facecolor}{rgb}{0.000,0.000,1.000}
|
|
1229
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
1230
|
+
(0, 0, 0) -- (1, 0, 0) -- (1, 1, 0) -- (0, 1, 0) -- cycle;
|
|
1231
|
+
\end{tikzpicture}
|
|
1232
|
+
|
|
1233
|
+
::
|
|
1234
|
+
|
|
1235
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1236
|
+
sage: E = E1Star(sigma)
|
|
1237
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1238
|
+
sage: P = E(P, 4)
|
|
1239
|
+
sage: from sage.misc.latex import latex #not tested
|
|
1240
|
+
sage: latex.add_to_preamble('\\usepackage{tikz}') #not tested
|
|
1241
|
+
sage: view(P) #not tested
|
|
1242
|
+
|
|
1243
|
+
Plot using shades of gray (useful for article figures)::
|
|
1244
|
+
|
|
1245
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1246
|
+
sage: E = E1Star(sigma)
|
|
1247
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1248
|
+
sage: P.repaint([(0.9, 0.9, 0.9), (0.65,0.65,0.65), (0.4,0.4,0.4)])
|
|
1249
|
+
sage: P = E(P, 4)
|
|
1250
|
+
sage: s = P.plot_tikz()
|
|
1251
|
+
|
|
1252
|
+
Plotting with various options::
|
|
1253
|
+
|
|
1254
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1255
|
+
sage: E = E1Star(sigma)
|
|
1256
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1257
|
+
sage: M = matrix(2,3,[float(u) for u in [1,0,-0.7071,0,1,-0.7071]])
|
|
1258
|
+
sage: P = E(P, 3)
|
|
1259
|
+
sage: s = P.plot_tikz(projmat=M, edgecolor='facecolor', scale=0.6, drawzero=True)
|
|
1260
|
+
|
|
1261
|
+
Adding X, Y, Z axes using the extra code feature::
|
|
1262
|
+
|
|
1263
|
+
sage: length = 1.5
|
|
1264
|
+
sage: space = 0.3
|
|
1265
|
+
sage: axes = ''
|
|
1266
|
+
sage: axes += "\\draw[->, thick, black] (0,0,0) -- (%s, 0, 0);\n" % length
|
|
1267
|
+
sage: axes += "\\draw[->, thick, black] (0,0,0) -- (0, %s, 0);\n" % length
|
|
1268
|
+
sage: axes += "\\node at (%s,0,0) {$x$};\n" % (length + space)
|
|
1269
|
+
sage: axes += "\\node at (0,%s,0) {$y$};\n" % (length + space)
|
|
1270
|
+
sage: axes += "\\node at (0,0,%s) {$z$};\n" % (length + space)
|
|
1271
|
+
sage: axes += "\\draw[->, thick, black] (0,0,0) -- (0, 0, %s);\n" % length
|
|
1272
|
+
sage: cube = Patch([Face((0,0,0),1), Face((0,0,0),2), Face((0,0,0),3)])
|
|
1273
|
+
sage: options = dict(scale=0.5,drawzero=True,extra_code_before=axes)
|
|
1274
|
+
sage: s = cube.plot_tikz(**options)
|
|
1275
|
+
sage: len(s)
|
|
1276
|
+
986
|
|
1277
|
+
sage: print(s) #not tested
|
|
1278
|
+
\begin{tikzpicture}
|
|
1279
|
+
[x={(-0.433013cm,-0.250000cm)}, y={(0.433013cm,-0.250000cm)}, z={(0.000000cm,0.500000cm)}]
|
|
1280
|
+
\draw[->, thick, black] (0,0,0) -- (1.50000000000000, 0, 0);
|
|
1281
|
+
\draw[->, thick, black] (0,0,0) -- (0, 1.50000000000000, 0);
|
|
1282
|
+
\node at (1.80000000000000,0,0) {$x$};
|
|
1283
|
+
\node at (0,1.80000000000000,0) {$y$};
|
|
1284
|
+
\node at (0,0,1.80000000000000) {$z$};
|
|
1285
|
+
\draw[->, thick, black] (0,0,0) -- (0, 0, 1.50000000000000);
|
|
1286
|
+
\definecolor{facecolor}{rgb}{0.000,1.000,0.000}
|
|
1287
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
1288
|
+
(0, 0, 0) -- (0, 0, 1) -- (1, 0, 1) -- (1, 0, 0) -- cycle;
|
|
1289
|
+
\definecolor{facecolor}{rgb}{1.000,0.000,0.000}
|
|
1290
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
1291
|
+
(0, 0, 0) -- (0, 1, 0) -- (0, 1, 1) -- (0, 0, 1) -- cycle;
|
|
1292
|
+
\definecolor{facecolor}{rgb}{0.000,0.000,1.000}
|
|
1293
|
+
\fill[fill=facecolor, draw=black, shift={(0,0,0)}]
|
|
1294
|
+
(0, 0, 0) -- (1, 0, 0) -- (1, 1, 0) -- (0, 1, 0) -- cycle;
|
|
1295
|
+
\node[circle,fill=black,draw=black,minimum size=1.5mm,inner sep=0pt] at (0,0,0) {};
|
|
1296
|
+
\end{tikzpicture}
|
|
1297
|
+
"""
|
|
1298
|
+
if self.dimension() != 3:
|
|
1299
|
+
raise NotImplementedError("Tikz plotting is implemented only for patches in three dimensions")
|
|
1300
|
+
|
|
1301
|
+
if projmat is None:
|
|
1302
|
+
projmat = matrix(2, [-1.7320508075688772 * 0.5,
|
|
1303
|
+
1.7320508075688772 * 0.5,
|
|
1304
|
+
0, -0.5, -0.5, 1]) * scale
|
|
1305
|
+
|
|
1306
|
+
e1 = projmat * vector([1, 0, 0])
|
|
1307
|
+
e2 = projmat * vector([0, 1, 0])
|
|
1308
|
+
e3 = projmat * vector([0, 0, 1])
|
|
1309
|
+
face_contour = self._face_contour
|
|
1310
|
+
color = None
|
|
1311
|
+
|
|
1312
|
+
# string s contains the TiKZ code of the patch
|
|
1313
|
+
s = ''
|
|
1314
|
+
|
|
1315
|
+
if print_tikz_env:
|
|
1316
|
+
s += '\\begin{tikzpicture}\n'
|
|
1317
|
+
s += '[x={(%fcm,%fcm)}, y={(%fcm,%fcm)}, z={(%fcm,%fcm)}]\n' % (e1[0], e1[1], e2[0], e2[1], e3[0], e3[1])
|
|
1318
|
+
|
|
1319
|
+
s += extra_code_before
|
|
1320
|
+
|
|
1321
|
+
for f in self:
|
|
1322
|
+
t = f.type()
|
|
1323
|
+
x, y, z = f.vector()
|
|
1324
|
+
|
|
1325
|
+
if color is None or color != f.color():
|
|
1326
|
+
color = f.color()
|
|
1327
|
+
s += '\\definecolor{facecolor}{rgb}{%.3f,%.3f,%.3f}\n' % (color[0], color[1], color[2])
|
|
1328
|
+
|
|
1329
|
+
s += '\\fill[fill=facecolor, draw=%s, shift={(%d,%d,%d)}]\n' % (edgecolor, x, y, z)
|
|
1330
|
+
s += ' -- '.join(map(str, face_contour[t])) + ' -- cycle;\n'
|
|
1331
|
+
|
|
1332
|
+
s += extra_code_after
|
|
1333
|
+
|
|
1334
|
+
if drawzero:
|
|
1335
|
+
s += '\\node[circle,fill=black,draw=black,minimum size=1.5mm,inner sep=0pt] at (0,0,0) {};\n'
|
|
1336
|
+
|
|
1337
|
+
if print_tikz_env:
|
|
1338
|
+
s += '\\end{tikzpicture}'
|
|
1339
|
+
|
|
1340
|
+
return LatexExpr(s)
|
|
1341
|
+
|
|
1342
|
+
_latex_ = plot_tikz
|
|
1343
|
+
|
|
1344
|
+
|
|
1345
|
+
class E1Star(SageObject):
|
|
1346
|
+
r"""
|
|
1347
|
+
A class to model the `E_1^*(\sigma)` map associated with
|
|
1348
|
+
a unimodular substitution `\sigma`.
|
|
1349
|
+
|
|
1350
|
+
INPUT:
|
|
1351
|
+
|
|
1352
|
+
- ``sigma`` -- unimodular ``WordMorphism``, i.e. such that its incidence
|
|
1353
|
+
matrix has determinant `\pm 1`
|
|
1354
|
+
|
|
1355
|
+
- ``method`` -- 'prefix' or 'suffix' (default: ``'suffix'``);
|
|
1356
|
+
enables to use an alternative definition `E_1^*(\sigma)` substitutions,
|
|
1357
|
+
where the abelianized of the prefix` is used instead of the suffix
|
|
1358
|
+
|
|
1359
|
+
.. NOTE::
|
|
1360
|
+
|
|
1361
|
+
The alphabet of the domain and the codomain of `\sigma` must be
|
|
1362
|
+
equal, and they must be of the form ``[1, ..., d]``, where ``d``
|
|
1363
|
+
is a positive integer corresponding to the length of the vectors
|
|
1364
|
+
of the faces on which `E_1^*(\sigma)` will act.
|
|
1365
|
+
|
|
1366
|
+
EXAMPLES::
|
|
1367
|
+
|
|
1368
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1369
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1370
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1371
|
+
sage: E = E1Star(sigma)
|
|
1372
|
+
sage: E(P)
|
|
1373
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*, [(0, 1, -1), 2]*, [(1, 0, -1), 1]*]
|
|
1374
|
+
|
|
1375
|
+
::
|
|
1376
|
+
|
|
1377
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1378
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1379
|
+
sage: E = E1Star(sigma, method='prefix')
|
|
1380
|
+
sage: E(P)
|
|
1381
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*, [(0, 0, 1), 1]*, [(0, 0, 1), 2]*]
|
|
1382
|
+
|
|
1383
|
+
::
|
|
1384
|
+
|
|
1385
|
+
sage: x = [Face((0,0,0,0),1), Face((0,0,0,0),4)]
|
|
1386
|
+
sage: P = Patch(x)
|
|
1387
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1,4], 4:[1]})
|
|
1388
|
+
sage: E = E1Star(sigma)
|
|
1389
|
+
sage: E(P)
|
|
1390
|
+
Patch: [[(0, 0, 0, 0), 3]*, [(0, 0, 0, 0), 4]*, [(0, 0, 1, -1), 3]*, [(0, 1, 0, -1), 2]*, [(1, 0, 0, -1), 1]*]
|
|
1391
|
+
"""
|
|
1392
|
+
|
|
1393
|
+
def __init__(self, sigma, method='suffix'):
|
|
1394
|
+
r"""
|
|
1395
|
+
E1Star constructor. See class doc for more information.
|
|
1396
|
+
|
|
1397
|
+
EXAMPLES::
|
|
1398
|
+
|
|
1399
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1400
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1401
|
+
sage: E = E1Star(sigma)
|
|
1402
|
+
sage: E
|
|
1403
|
+
E_1^*(1->12, 2->13, 3->1)
|
|
1404
|
+
"""
|
|
1405
|
+
if not isinstance(sigma, WordMorphism):
|
|
1406
|
+
raise TypeError("sigma (=%s) must be an instance of WordMorphism" % sigma)
|
|
1407
|
+
|
|
1408
|
+
if sigma.domain().alphabet() != sigma.codomain().alphabet():
|
|
1409
|
+
raise ValueError("the domain and codomain of (%s) must be the same" % sigma)
|
|
1410
|
+
|
|
1411
|
+
if abs(det(matrix(sigma))) != 1:
|
|
1412
|
+
raise ValueError("the substitution (%s) must be unimodular" % sigma)
|
|
1413
|
+
|
|
1414
|
+
first_letter = sigma.codomain().alphabet()[0]
|
|
1415
|
+
if first_letter not in ZZ or first_letter < 1:
|
|
1416
|
+
raise ValueError(f"the substitution ({sigma}) must be defined on positive integers")
|
|
1417
|
+
|
|
1418
|
+
self._sigma = WordMorphism(sigma)
|
|
1419
|
+
self._d = self._sigma.domain().alphabet().cardinality()
|
|
1420
|
+
|
|
1421
|
+
# self._base_iter is a base for the iteration of the application of self on set
|
|
1422
|
+
# of faces. (Exploits the linearity of `E_1^*(\sigma)` to optimize computation.)
|
|
1423
|
+
alphabet = self._sigma.domain().alphabet()
|
|
1424
|
+
X = {}
|
|
1425
|
+
for k in alphabet:
|
|
1426
|
+
subst_im = self._sigma.image(k)
|
|
1427
|
+
for n, letter in enumerate(subst_im):
|
|
1428
|
+
if method == 'suffix':
|
|
1429
|
+
image_word = subst_im[n + 1:]
|
|
1430
|
+
elif method == 'prefix':
|
|
1431
|
+
image_word = subst_im[:n]
|
|
1432
|
+
else:
|
|
1433
|
+
raise ValueError("option 'method' can only be 'prefix' or 'suffix'")
|
|
1434
|
+
if letter not in X:
|
|
1435
|
+
X[letter] = []
|
|
1436
|
+
v = self.inverse_matrix() * vector(image_word.abelian_vector())
|
|
1437
|
+
X[letter].append((v, k))
|
|
1438
|
+
self._base_iter = X
|
|
1439
|
+
|
|
1440
|
+
def __eq__(self, other) -> bool:
|
|
1441
|
+
r"""
|
|
1442
|
+
Equality test for E1Star morphisms.
|
|
1443
|
+
|
|
1444
|
+
INPUT:
|
|
1445
|
+
|
|
1446
|
+
- ``other`` -- an object
|
|
1447
|
+
|
|
1448
|
+
EXAMPLES::
|
|
1449
|
+
|
|
1450
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1451
|
+
sage: s = WordMorphism({1:[1,3], 2:[1,2,3], 3:[3]})
|
|
1452
|
+
sage: t = WordMorphism({1:[1,2,3], 2:[2,3], 3:[3]})
|
|
1453
|
+
sage: S = E1Star(s)
|
|
1454
|
+
sage: T = E1Star(t)
|
|
1455
|
+
sage: S == T
|
|
1456
|
+
False
|
|
1457
|
+
sage: S2 = E1Star(s, method='prefix')
|
|
1458
|
+
sage: S == S2
|
|
1459
|
+
False
|
|
1460
|
+
"""
|
|
1461
|
+
return (isinstance(other, E1Star) and self._base_iter == other._base_iter)
|
|
1462
|
+
|
|
1463
|
+
def __call__(self, patch, iterations=1) -> Patch:
|
|
1464
|
+
r"""
|
|
1465
|
+
Applies a generalized substitution to a Patch; this returns a new object.
|
|
1466
|
+
|
|
1467
|
+
The color of every new face in the image is given the same color as its preimage.
|
|
1468
|
+
|
|
1469
|
+
INPUT:
|
|
1470
|
+
|
|
1471
|
+
- ``patch`` -- a patch
|
|
1472
|
+
- ``iterations`` -- integer (default: 1); number of iterations
|
|
1473
|
+
|
|
1474
|
+
OUTPUT: a patch
|
|
1475
|
+
|
|
1476
|
+
EXAMPLES::
|
|
1477
|
+
|
|
1478
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1479
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1480
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1481
|
+
sage: E = E1Star(sigma)
|
|
1482
|
+
sage: E(P)
|
|
1483
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*, [(0, 1, -1), 2]*, [(1, 0, -1), 1]*]
|
|
1484
|
+
sage: E(P, iterations=4)
|
|
1485
|
+
Patch of 31 faces
|
|
1486
|
+
|
|
1487
|
+
TESTS:
|
|
1488
|
+
|
|
1489
|
+
We test that iterations=0 works (see :issue:`10699`)::
|
|
1490
|
+
|
|
1491
|
+
sage: P = Patch([Face((0,0,0),t) for t in [1,2,3]])
|
|
1492
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1493
|
+
sage: E = E1Star(sigma)
|
|
1494
|
+
sage: E(P, iterations=0)
|
|
1495
|
+
Patch: [[(0, 0, 0), 1]*, [(0, 0, 0), 2]*, [(0, 0, 0), 3]*]
|
|
1496
|
+
"""
|
|
1497
|
+
if iterations == 0:
|
|
1498
|
+
return Patch(patch)
|
|
1499
|
+
elif iterations < 0:
|
|
1500
|
+
raise ValueError("iterations (=%s) must be >= 0" % iterations)
|
|
1501
|
+
else:
|
|
1502
|
+
old_faces = patch
|
|
1503
|
+
for _ in range(iterations):
|
|
1504
|
+
new_faces = []
|
|
1505
|
+
for f in old_faces:
|
|
1506
|
+
new_faces.extend(self._call_on_face(f, color=f.color()))
|
|
1507
|
+
old_faces = new_faces
|
|
1508
|
+
return Patch(new_faces)
|
|
1509
|
+
|
|
1510
|
+
def __mul__(self, other) -> E1Star:
|
|
1511
|
+
r"""
|
|
1512
|
+
Return the product of ``self`` and ``other``.
|
|
1513
|
+
|
|
1514
|
+
The product satisfies the following rule:
|
|
1515
|
+
`E_1^*(\sigma\circ\sigma') = E_1^*(\sigma')` \circ E_1^*(\sigma)`
|
|
1516
|
+
|
|
1517
|
+
INPUT:
|
|
1518
|
+
|
|
1519
|
+
- ``other`` -- an instance of E1Star
|
|
1520
|
+
|
|
1521
|
+
OUTPUT: an instance of E1Star
|
|
1522
|
+
|
|
1523
|
+
EXAMPLES::
|
|
1524
|
+
|
|
1525
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1526
|
+
sage: s = WordMorphism({1:[2],2:[3],3:[1,2]})
|
|
1527
|
+
sage: t = WordMorphism({1:[1,3,1],2:[1],3:[1,1,3,2]})
|
|
1528
|
+
sage: E1Star(s) * E1Star(t)
|
|
1529
|
+
E_1^*(1->1, 2->1132, 3->1311)
|
|
1530
|
+
sage: E1Star(t * s)
|
|
1531
|
+
E_1^*(1->1, 2->1132, 3->1311)
|
|
1532
|
+
"""
|
|
1533
|
+
if not isinstance(other, E1Star):
|
|
1534
|
+
raise TypeError("other (=%s) must be an instance of E1Star" % other)
|
|
1535
|
+
return E1Star(other.sigma() * self.sigma())
|
|
1536
|
+
|
|
1537
|
+
def __repr__(self) -> str:
|
|
1538
|
+
r"""
|
|
1539
|
+
String representation of a patch.
|
|
1540
|
+
|
|
1541
|
+
EXAMPLES::
|
|
1542
|
+
|
|
1543
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1544
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1545
|
+
sage: E = E1Star(sigma)
|
|
1546
|
+
sage: E
|
|
1547
|
+
E_1^*(1->12, 2->13, 3->1)
|
|
1548
|
+
"""
|
|
1549
|
+
return "E_1^*(%s)" % str(self._sigma)
|
|
1550
|
+
|
|
1551
|
+
def _call_on_face(self, face, color=None):
|
|
1552
|
+
r"""
|
|
1553
|
+
Return an iterator of faces obtained by applying ``self`` on the face.
|
|
1554
|
+
|
|
1555
|
+
INPUT:
|
|
1556
|
+
|
|
1557
|
+
- ``face`` -- a face
|
|
1558
|
+
- ``color`` -- string (default: ``None``); RGB tuple or color
|
|
1559
|
+
|
|
1560
|
+
OUTPUT: iterator of faces
|
|
1561
|
+
|
|
1562
|
+
EXAMPLES::
|
|
1563
|
+
|
|
1564
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1565
|
+
sage: f = Face((0,2,0), 1)
|
|
1566
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1567
|
+
sage: E = E1Star(sigma)
|
|
1568
|
+
sage: list(E._call_on_face(f))
|
|
1569
|
+
[[(3, 0, -3), 1]*, [(2, 1, -3), 2]*, [(2, 0, -2), 3]*]
|
|
1570
|
+
"""
|
|
1571
|
+
if len(face.vector()) != self._d:
|
|
1572
|
+
raise ValueError("the dimension of the faces must be equal to the size of the alphabet of the substitution")
|
|
1573
|
+
x_new = self.inverse_matrix() * face.vector()
|
|
1574
|
+
t = face.type()
|
|
1575
|
+
return (Face(x_new + v, k, color=color) for v, k in self._base_iter[t])
|
|
1576
|
+
|
|
1577
|
+
@cached_method
|
|
1578
|
+
def matrix(self):
|
|
1579
|
+
r"""
|
|
1580
|
+
Return the matrix associated with ``self``.
|
|
1581
|
+
|
|
1582
|
+
EXAMPLES::
|
|
1583
|
+
|
|
1584
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1585
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1586
|
+
sage: E = E1Star(sigma)
|
|
1587
|
+
sage: E.matrix()
|
|
1588
|
+
[1 1 1]
|
|
1589
|
+
[1 0 0]
|
|
1590
|
+
[0 1 0]
|
|
1591
|
+
"""
|
|
1592
|
+
return self._sigma.incidence_matrix()
|
|
1593
|
+
|
|
1594
|
+
@cached_method
|
|
1595
|
+
def inverse_matrix(self):
|
|
1596
|
+
r"""
|
|
1597
|
+
Return the inverse of the matrix associated with ``self``.
|
|
1598
|
+
|
|
1599
|
+
EXAMPLES::
|
|
1600
|
+
|
|
1601
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1602
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1603
|
+
sage: E = E1Star(sigma)
|
|
1604
|
+
sage: E.inverse_matrix()
|
|
1605
|
+
[ 0 1 0]
|
|
1606
|
+
[ 0 0 1]
|
|
1607
|
+
[ 1 -1 -1]
|
|
1608
|
+
"""
|
|
1609
|
+
return self.matrix().inverse()
|
|
1610
|
+
|
|
1611
|
+
def sigma(self) -> WordMorphism:
|
|
1612
|
+
r"""
|
|
1613
|
+
Return the ``WordMorphism`` associated with ``self``.
|
|
1614
|
+
|
|
1615
|
+
EXAMPLES::
|
|
1616
|
+
|
|
1617
|
+
sage: from sage.combinat.e_one_star import E1Star, Face, Patch
|
|
1618
|
+
sage: sigma = WordMorphism({1:[1,2], 2:[1,3], 3:[1]})
|
|
1619
|
+
sage: E = E1Star(sigma)
|
|
1620
|
+
sage: E.sigma()
|
|
1621
|
+
WordMorphism: 1->12, 2->13, 3->1
|
|
1622
|
+
"""
|
|
1623
|
+
return self._sigma
|