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,783 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
"""
|
|
3
|
+
SAT-Solvers via DIMACS Files
|
|
4
|
+
|
|
5
|
+
Sage supports calling SAT solvers using the popular DIMACS format. This module implements
|
|
6
|
+
infrastructure to make it easy to add new such interfaces and some example interfaces.
|
|
7
|
+
|
|
8
|
+
Currently, interfaces to **RSat** and **Glucose** are included by default.
|
|
9
|
+
|
|
10
|
+
.. NOTE::
|
|
11
|
+
|
|
12
|
+
Our SAT solver interfaces are 1-based, i.e., literals start at 1. This is consistent with the
|
|
13
|
+
popular DIMACS format for SAT solving but not with Pythion's 0-based convention. However, this
|
|
14
|
+
also allows to construct clauses using simple integers.
|
|
15
|
+
|
|
16
|
+
AUTHORS:
|
|
17
|
+
|
|
18
|
+
- Martin Albrecht (2012): first version
|
|
19
|
+
- Sébastien Labbé (2018): adding Glucose SAT solver
|
|
20
|
+
- Sébastien Labbé (2023): adding Kissat SAT solver
|
|
21
|
+
|
|
22
|
+
Classes and Methods
|
|
23
|
+
-------------------
|
|
24
|
+
"""
|
|
25
|
+
##############################################################################
|
|
26
|
+
# Copyright (C) 2012 Martin Albrecht <martinralbrecht@googlemail.com>
|
|
27
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
28
|
+
# The full text of the GPL is available at:
|
|
29
|
+
# https://www.gnu.org/licenses/
|
|
30
|
+
##############################################################################
|
|
31
|
+
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
import sys
|
|
34
|
+
import subprocess
|
|
35
|
+
import shlex
|
|
36
|
+
from time import sleep
|
|
37
|
+
|
|
38
|
+
from sage.features.sat import Glucose as Glucose_executable, Kissat as Kissat_executable
|
|
39
|
+
from sage.sat.solvers.satsolver import SatSolver
|
|
40
|
+
from sage.misc.temporary_file import tmp_filename
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class DIMACS(SatSolver):
|
|
44
|
+
"""
|
|
45
|
+
Generic DIMACS Solver.
|
|
46
|
+
|
|
47
|
+
.. NOTE::
|
|
48
|
+
|
|
49
|
+
Usually, users will not have to use this class directly but some
|
|
50
|
+
class which inherits from this class.
|
|
51
|
+
|
|
52
|
+
.. automethod:: __init__
|
|
53
|
+
.. automethod:: __call__
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
command = ""
|
|
57
|
+
|
|
58
|
+
def __init__(self, command=None, filename=None, verbosity=0, **kwds):
|
|
59
|
+
"""
|
|
60
|
+
Construct a new generic DIMACS solver.
|
|
61
|
+
|
|
62
|
+
INPUT:
|
|
63
|
+
|
|
64
|
+
- ``command`` -- a named format string or list of strings with the
|
|
65
|
+
command to run. The string must contain {input} and may contain
|
|
66
|
+
{output} if the solvers writes the solution to an output
|
|
67
|
+
file. For example "sat-solver {input}" is a valid
|
|
68
|
+
command. If ``None`` then the class variable ``command`` is
|
|
69
|
+
used. (default: ``None``)
|
|
70
|
+
|
|
71
|
+
- ``filename`` -- a filename to write clauses to in DIMACS
|
|
72
|
+
format, must be writable. If ``None`` a temporary filename
|
|
73
|
+
is chosen automatically. (default: ``None``)
|
|
74
|
+
|
|
75
|
+
- ``verbosity`` -- a verbosity level, where zero means silent
|
|
76
|
+
and anything else means verbose output. (default: ``0``)
|
|
77
|
+
|
|
78
|
+
- ``**kwds`` -- accepted for compatibility with other solvers; ignored
|
|
79
|
+
|
|
80
|
+
TESTS::
|
|
81
|
+
|
|
82
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
83
|
+
sage: DIMACS()
|
|
84
|
+
DIMACS Solver: ''
|
|
85
|
+
"""
|
|
86
|
+
self._headname_file_created_during_init = False
|
|
87
|
+
if filename is None:
|
|
88
|
+
filename = tmp_filename()
|
|
89
|
+
self._headname_file_created_during_init = True
|
|
90
|
+
|
|
91
|
+
self._headname = filename
|
|
92
|
+
self._verbosity = verbosity
|
|
93
|
+
|
|
94
|
+
if command is not None:
|
|
95
|
+
self._command = command
|
|
96
|
+
else:
|
|
97
|
+
self._command = self.__class__.command
|
|
98
|
+
|
|
99
|
+
self._tail = open(tmp_filename(), 'w')
|
|
100
|
+
self._var = 0
|
|
101
|
+
self._lit = 0
|
|
102
|
+
|
|
103
|
+
def __repr__(self):
|
|
104
|
+
"""
|
|
105
|
+
TESTS::
|
|
106
|
+
|
|
107
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
108
|
+
sage: DIMACS(command="iliketurtles {input}")
|
|
109
|
+
DIMACS Solver: 'iliketurtles {input}'
|
|
110
|
+
"""
|
|
111
|
+
command = self._command
|
|
112
|
+
if not isinstance(command, str):
|
|
113
|
+
command = ' '.join((arg if isinstance(arg, str) else arg.executable)
|
|
114
|
+
for arg in command)
|
|
115
|
+
return "DIMACS Solver: '%s'" % command
|
|
116
|
+
|
|
117
|
+
def __del__(self):
|
|
118
|
+
"""
|
|
119
|
+
TESTS::
|
|
120
|
+
|
|
121
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
122
|
+
sage: d = DIMACS(command="iliketurtles {input}")
|
|
123
|
+
sage: del d
|
|
124
|
+
|
|
125
|
+
We check that files created during initialization are properly
|
|
126
|
+
deleted (:issue:`38328`)::
|
|
127
|
+
|
|
128
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
129
|
+
sage: d = DIMACS(command="iliketurtles {input}")
|
|
130
|
+
sage: filename = d._headname
|
|
131
|
+
sage: os.path.exists(filename)
|
|
132
|
+
True
|
|
133
|
+
sage: del d
|
|
134
|
+
sage: os.path.exists(filename)
|
|
135
|
+
False
|
|
136
|
+
|
|
137
|
+
::
|
|
138
|
+
|
|
139
|
+
sage: fn = tmp_filename()
|
|
140
|
+
sage: d = DIMACS(filename=fn)
|
|
141
|
+
sage: del d
|
|
142
|
+
"""
|
|
143
|
+
if not self._tail.closed:
|
|
144
|
+
self._tail.close()
|
|
145
|
+
Path(self._tail.name).unlink(missing_ok=True)
|
|
146
|
+
if self._headname_file_created_during_init:
|
|
147
|
+
Path(self._headname).unlink(missing_ok=True)
|
|
148
|
+
|
|
149
|
+
def var(self, decision=None):
|
|
150
|
+
"""
|
|
151
|
+
Return a *new* variable.
|
|
152
|
+
|
|
153
|
+
INPUT:
|
|
154
|
+
|
|
155
|
+
- ``decision`` -- accepted for compatibility with other solvers; ignored
|
|
156
|
+
|
|
157
|
+
EXAMPLES::
|
|
158
|
+
|
|
159
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
160
|
+
sage: solver = DIMACS()
|
|
161
|
+
sage: solver.var()
|
|
162
|
+
1
|
|
163
|
+
"""
|
|
164
|
+
self._var += 1
|
|
165
|
+
return self._var
|
|
166
|
+
|
|
167
|
+
def nvars(self):
|
|
168
|
+
"""
|
|
169
|
+
Return the number of variables.
|
|
170
|
+
|
|
171
|
+
EXAMPLES::
|
|
172
|
+
|
|
173
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
174
|
+
sage: solver = DIMACS()
|
|
175
|
+
sage: solver.var()
|
|
176
|
+
1
|
|
177
|
+
sage: solver.var(decision=True)
|
|
178
|
+
2
|
|
179
|
+
sage: solver.nvars()
|
|
180
|
+
2
|
|
181
|
+
"""
|
|
182
|
+
return self._var
|
|
183
|
+
|
|
184
|
+
def add_clause(self, lits):
|
|
185
|
+
"""
|
|
186
|
+
Add a new clause to set of clauses.
|
|
187
|
+
|
|
188
|
+
INPUT:
|
|
189
|
+
|
|
190
|
+
- ``lits`` -- tuple of nonzero integers
|
|
191
|
+
|
|
192
|
+
.. NOTE::
|
|
193
|
+
|
|
194
|
+
If any element ``e`` in ``lits`` has ``abs(e)`` greater
|
|
195
|
+
than the number of variables generated so far, then new
|
|
196
|
+
variables are created automatically.
|
|
197
|
+
|
|
198
|
+
EXAMPLES::
|
|
199
|
+
|
|
200
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
201
|
+
sage: solver = DIMACS()
|
|
202
|
+
sage: solver.var()
|
|
203
|
+
1
|
|
204
|
+
sage: solver.var(decision=True)
|
|
205
|
+
2
|
|
206
|
+
sage: solver.add_clause( (1, -2 , 3) )
|
|
207
|
+
sage: solver
|
|
208
|
+
DIMACS Solver: ''
|
|
209
|
+
"""
|
|
210
|
+
l = []
|
|
211
|
+
for lit in lits:
|
|
212
|
+
lit = int(lit)
|
|
213
|
+
while abs(lit) > self.nvars():
|
|
214
|
+
self.var()
|
|
215
|
+
l.append(str(lit))
|
|
216
|
+
l.append("0\n")
|
|
217
|
+
self._tail.write(" ".join(l))
|
|
218
|
+
self._lit += 1
|
|
219
|
+
|
|
220
|
+
def write(self, filename=None):
|
|
221
|
+
"""
|
|
222
|
+
Write DIMACS file.
|
|
223
|
+
|
|
224
|
+
INPUT:
|
|
225
|
+
|
|
226
|
+
- ``filename`` -- if ``None`` default filename specified at initialization is used for
|
|
227
|
+
writing to (default: ``None``)
|
|
228
|
+
|
|
229
|
+
EXAMPLES::
|
|
230
|
+
|
|
231
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
232
|
+
sage: fn = tmp_filename()
|
|
233
|
+
sage: solver = DIMACS(filename=fn)
|
|
234
|
+
sage: solver.add_clause( (1, -2 , 3) )
|
|
235
|
+
sage: _ = solver.write()
|
|
236
|
+
sage: for line in open(fn).readlines():
|
|
237
|
+
....: print(line)
|
|
238
|
+
p cnf 3 1
|
|
239
|
+
1 -2 3 0
|
|
240
|
+
|
|
241
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
242
|
+
sage: fn = tmp_filename()
|
|
243
|
+
sage: solver = DIMACS()
|
|
244
|
+
sage: solver.add_clause( (1, -2 , 3) )
|
|
245
|
+
sage: _ = solver.write(fn)
|
|
246
|
+
sage: for line in open(fn).readlines():
|
|
247
|
+
....: print(line)
|
|
248
|
+
p cnf 3 1
|
|
249
|
+
1 -2 3 0
|
|
250
|
+
"""
|
|
251
|
+
headname = self._headname if filename is None else filename
|
|
252
|
+
head = open(headname, "w")
|
|
253
|
+
head.truncate(0)
|
|
254
|
+
head.write("p cnf %d %d\n" % (self._var, self._lit))
|
|
255
|
+
head.close()
|
|
256
|
+
|
|
257
|
+
tail = self._tail
|
|
258
|
+
tail.close()
|
|
259
|
+
|
|
260
|
+
head = open(headname, "a")
|
|
261
|
+
tail = open(self._tail.name)
|
|
262
|
+
head.write(tail.read())
|
|
263
|
+
tail.close()
|
|
264
|
+
head.close()
|
|
265
|
+
|
|
266
|
+
self._tail = open(self._tail.name, "a")
|
|
267
|
+
return headname
|
|
268
|
+
|
|
269
|
+
def clauses(self, filename=None):
|
|
270
|
+
"""
|
|
271
|
+
Return original clauses.
|
|
272
|
+
|
|
273
|
+
INPUT:
|
|
274
|
+
|
|
275
|
+
- ``filename`` -- if not ``None`` clauses are written to ``filename`` in
|
|
276
|
+
DIMACS format (default: ``None``)
|
|
277
|
+
|
|
278
|
+
OUTPUT:
|
|
279
|
+
|
|
280
|
+
If ``filename`` is ``None`` then a list of ``lits, is_xor, rhs``
|
|
281
|
+
tuples is returned, where ``lits`` is a tuple of literals,
|
|
282
|
+
``is_xor`` is always ``False`` and ``rhs`` is always ``None``.
|
|
283
|
+
|
|
284
|
+
If ``filename`` points to a writable file, then the list of original
|
|
285
|
+
clauses is written to that file in DIMACS format.
|
|
286
|
+
|
|
287
|
+
EXAMPLES::
|
|
288
|
+
|
|
289
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
290
|
+
sage: fn = tmp_filename()
|
|
291
|
+
sage: solver = DIMACS()
|
|
292
|
+
sage: solver.add_clause( (1, 2, 3) )
|
|
293
|
+
sage: solver.clauses()
|
|
294
|
+
[((1, 2, 3), False, None)]
|
|
295
|
+
|
|
296
|
+
sage: solver.add_clause( (1, 2, -3) )
|
|
297
|
+
sage: solver.clauses(fn)
|
|
298
|
+
sage: print(open(fn).read())
|
|
299
|
+
p cnf 3 2
|
|
300
|
+
1 2 3 0
|
|
301
|
+
1 2 -3 0
|
|
302
|
+
<BLANKLINE>
|
|
303
|
+
"""
|
|
304
|
+
if filename is not None:
|
|
305
|
+
self.write(filename)
|
|
306
|
+
else:
|
|
307
|
+
tail = self._tail
|
|
308
|
+
tail.close()
|
|
309
|
+
tail = open(self._tail.name)
|
|
310
|
+
|
|
311
|
+
clauses = []
|
|
312
|
+
for line in tail.readlines():
|
|
313
|
+
if line.startswith("p") or line.startswith("c"):
|
|
314
|
+
continue
|
|
315
|
+
clause = []
|
|
316
|
+
for lit in line.split(" "):
|
|
317
|
+
lit = int(lit)
|
|
318
|
+
if lit == 0:
|
|
319
|
+
break
|
|
320
|
+
clause.append(lit)
|
|
321
|
+
clauses.append((tuple(clause), False, None))
|
|
322
|
+
tail.close()
|
|
323
|
+
self._tail = open(self._tail.name, "a")
|
|
324
|
+
return clauses
|
|
325
|
+
|
|
326
|
+
@staticmethod
|
|
327
|
+
def render_dimacs(clauses, filename, nlits):
|
|
328
|
+
"""
|
|
329
|
+
Produce DIMACS file ``filename`` from ``clauses``.
|
|
330
|
+
|
|
331
|
+
INPUT:
|
|
332
|
+
|
|
333
|
+
- ``clauses`` -- list of clauses, either in simple format as a list of
|
|
334
|
+
literals or in extended format for CryptoMiniSat: a tuple of literals,
|
|
335
|
+
``is_xor`` and ``rhs``.
|
|
336
|
+
|
|
337
|
+
- ``filename`` -- the file to write to
|
|
338
|
+
|
|
339
|
+
- ``nlits -- the number of literals appearing in ``clauses``
|
|
340
|
+
|
|
341
|
+
EXAMPLES::
|
|
342
|
+
|
|
343
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
344
|
+
sage: fn = tmp_filename()
|
|
345
|
+
sage: solver = DIMACS()
|
|
346
|
+
sage: solver.add_clause( (1, 2, -3) )
|
|
347
|
+
sage: DIMACS.render_dimacs(solver.clauses(), fn, solver.nvars())
|
|
348
|
+
sage: print(open(fn).read())
|
|
349
|
+
p cnf 3 1
|
|
350
|
+
1 2 -3 0
|
|
351
|
+
<BLANKLINE>
|
|
352
|
+
|
|
353
|
+
This is equivalent to::
|
|
354
|
+
|
|
355
|
+
sage: solver.clauses(fn)
|
|
356
|
+
sage: print(open(fn).read())
|
|
357
|
+
p cnf 3 1
|
|
358
|
+
1 2 -3 0
|
|
359
|
+
<BLANKLINE>
|
|
360
|
+
|
|
361
|
+
This function also accepts a "simple" format::
|
|
362
|
+
|
|
363
|
+
sage: DIMACS.render_dimacs([ (1,2), (1,2,-3) ], fn, 3)
|
|
364
|
+
sage: print(open(fn).read())
|
|
365
|
+
p cnf 3 2
|
|
366
|
+
1 2 0
|
|
367
|
+
1 2 -3 0
|
|
368
|
+
<BLANKLINE>
|
|
369
|
+
"""
|
|
370
|
+
with open(filename, "w") as fh:
|
|
371
|
+
fh.write("p cnf %d %d\n" % (nlits, len(clauses)))
|
|
372
|
+
for clause in clauses:
|
|
373
|
+
if len(clause) == 3 and clause[1] in (True, False) and clause[2] in (True, False, None):
|
|
374
|
+
lits, is_xor, rhs = clause
|
|
375
|
+
else:
|
|
376
|
+
lits, is_xor, rhs = clause, False, None
|
|
377
|
+
|
|
378
|
+
if is_xor:
|
|
379
|
+
closing = lits[-1] if rhs else -lits[-1]
|
|
380
|
+
fh.write("x" + " ".join(map(str, lits[:-1])) + " %d 0\n" % closing)
|
|
381
|
+
else:
|
|
382
|
+
fh.write(" ".join(map(str, lits)) + " 0\n")
|
|
383
|
+
|
|
384
|
+
def _run(self):
|
|
385
|
+
r"""
|
|
386
|
+
Run 'command' and collect output.
|
|
387
|
+
|
|
388
|
+
TESTS:
|
|
389
|
+
|
|
390
|
+
This class is not meant to be called directly::
|
|
391
|
+
|
|
392
|
+
sage: from sage.sat.solvers.dimacs import DIMACS
|
|
393
|
+
sage: fn = tmp_filename()
|
|
394
|
+
sage: solver = DIMACS(filename=fn)
|
|
395
|
+
sage: solver.add_clause( (1, -2 , 3) )
|
|
396
|
+
sage: solver._run()
|
|
397
|
+
Traceback (most recent call last):
|
|
398
|
+
...
|
|
399
|
+
ValueError: no SAT solver command selected
|
|
400
|
+
|
|
401
|
+
It is used by subclasses::
|
|
402
|
+
|
|
403
|
+
sage: from sage.sat.solvers import Glucose
|
|
404
|
+
sage: solver = Glucose()
|
|
405
|
+
sage: solver.add_clause( (1, 2, 3) )
|
|
406
|
+
sage: solver.add_clause( (-1,) )
|
|
407
|
+
sage: solver.add_clause( (-2,) )
|
|
408
|
+
sage: solver._run() # optional - glucose
|
|
409
|
+
sage: solver._output # optional - glucose
|
|
410
|
+
[...
|
|
411
|
+
's SATISFIABLE\n',
|
|
412
|
+
'v -1 -2 3 0\n']
|
|
413
|
+
"""
|
|
414
|
+
from sage.misc.verbose import get_verbose
|
|
415
|
+
|
|
416
|
+
self.write()
|
|
417
|
+
output_filename = None
|
|
418
|
+
self._output = []
|
|
419
|
+
|
|
420
|
+
command = self._command
|
|
421
|
+
|
|
422
|
+
if not command:
|
|
423
|
+
raise ValueError("no SAT solver command selected")
|
|
424
|
+
|
|
425
|
+
if "{output}" in command:
|
|
426
|
+
output_filename = tmp_filename()
|
|
427
|
+
|
|
428
|
+
if isinstance(command, str):
|
|
429
|
+
command = command.strip().format(input=self._headname, output=output_filename)
|
|
430
|
+
args = shlex.split(command)
|
|
431
|
+
else:
|
|
432
|
+
args = [(arg.format(input=self._headname, output=output_filename)
|
|
433
|
+
if isinstance(arg, str)
|
|
434
|
+
else arg.absolute_filename())
|
|
435
|
+
for arg in command]
|
|
436
|
+
|
|
437
|
+
try:
|
|
438
|
+
process = subprocess.Popen(args, stdout=subprocess.PIPE)
|
|
439
|
+
except OSError:
|
|
440
|
+
raise OSError("Could not run '%s', perhaps you need to add your SAT solver to $PATH?" % (" ".join(args)))
|
|
441
|
+
|
|
442
|
+
try:
|
|
443
|
+
while process.poll() is None:
|
|
444
|
+
for line in iter(process.stdout.readline, b''):
|
|
445
|
+
if get_verbose() or self._verbosity:
|
|
446
|
+
print(line)
|
|
447
|
+
sys.stdout.flush()
|
|
448
|
+
self._output.append(line.decode('utf-8'))
|
|
449
|
+
sleep(0.1)
|
|
450
|
+
if output_filename:
|
|
451
|
+
self._output.extend(open(output_filename).readlines())
|
|
452
|
+
except BaseException:
|
|
453
|
+
process.kill()
|
|
454
|
+
raise
|
|
455
|
+
|
|
456
|
+
def __call__(self, assumptions=None):
|
|
457
|
+
"""
|
|
458
|
+
Solve this instance and return the parsed output.
|
|
459
|
+
|
|
460
|
+
INPUT:
|
|
461
|
+
|
|
462
|
+
- ``assumptions`` -- ignored, accepted for compatibility with
|
|
463
|
+
other solvers (default: ``None``)
|
|
464
|
+
|
|
465
|
+
OUTPUT:
|
|
466
|
+
|
|
467
|
+
- If this instance is SAT: A tuple of length ``nvars()+1``
|
|
468
|
+
where the ``i``-th entry holds an assignment for the
|
|
469
|
+
``i``-th variables (the ``0``-th entry is always ``None``).
|
|
470
|
+
|
|
471
|
+
- If this instance is UNSAT: ``False``
|
|
472
|
+
|
|
473
|
+
EXAMPLES:
|
|
474
|
+
|
|
475
|
+
When the problem is SAT::
|
|
476
|
+
|
|
477
|
+
sage: from sage.sat.solvers import RSat
|
|
478
|
+
sage: solver = RSat()
|
|
479
|
+
sage: solver.add_clause( (1, 2, 3) )
|
|
480
|
+
sage: solver.add_clause( (-1,) )
|
|
481
|
+
sage: solver.add_clause( (-2,) )
|
|
482
|
+
sage: solver() # optional - rsat
|
|
483
|
+
(None, False, False, True)
|
|
484
|
+
|
|
485
|
+
When the problem is UNSAT::
|
|
486
|
+
|
|
487
|
+
sage: solver = RSat()
|
|
488
|
+
sage: solver.add_clause((1,2))
|
|
489
|
+
sage: solver.add_clause((-1,2))
|
|
490
|
+
sage: solver.add_clause((1,-2))
|
|
491
|
+
sage: solver.add_clause((-1,-2))
|
|
492
|
+
sage: solver() # optional - rsat
|
|
493
|
+
False
|
|
494
|
+
|
|
495
|
+
With Glucose::
|
|
496
|
+
|
|
497
|
+
sage: from sage.sat.solvers.dimacs import Glucose
|
|
498
|
+
sage: solver = Glucose()
|
|
499
|
+
sage: solver.add_clause((1,2))
|
|
500
|
+
sage: solver.add_clause((-1,2))
|
|
501
|
+
sage: solver.add_clause((1,-2))
|
|
502
|
+
sage: solver() # optional - glucose
|
|
503
|
+
(None, True, True)
|
|
504
|
+
sage: solver.add_clause((-1,-2))
|
|
505
|
+
sage: solver() # optional - glucose
|
|
506
|
+
False
|
|
507
|
+
|
|
508
|
+
With GlucoseSyrup::
|
|
509
|
+
|
|
510
|
+
sage: from sage.sat.solvers.dimacs import GlucoseSyrup
|
|
511
|
+
sage: solver = GlucoseSyrup()
|
|
512
|
+
sage: solver.add_clause((1,2))
|
|
513
|
+
sage: solver.add_clause((-1,2))
|
|
514
|
+
sage: solver.add_clause((1,-2))
|
|
515
|
+
sage: solver() # optional - glucose
|
|
516
|
+
(None, True, True)
|
|
517
|
+
sage: solver.add_clause((-1,-2))
|
|
518
|
+
sage: solver() # optional - glucose
|
|
519
|
+
False
|
|
520
|
+
|
|
521
|
+
TESTS::
|
|
522
|
+
|
|
523
|
+
sage: from sage.sat.boolean_polynomials import solve as solve_sat
|
|
524
|
+
sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True) # needs sage.rings.finite_rings sage.rings.polynomial.pbori
|
|
525
|
+
sage: while True: # workaround (see :issue:`31891`) # needs sage.rings.finite_rings sage.rings.polynomial.pbori
|
|
526
|
+
....: try:
|
|
527
|
+
....: F, s = sr.polynomial_system()
|
|
528
|
+
....: break
|
|
529
|
+
....: except ZeroDivisionError:
|
|
530
|
+
....: pass
|
|
531
|
+
sage: solve_sat(F, solver=sage.sat.solvers.RSat) # optional - rsat, needs sage.rings.finite_rings sage.rings.polynomial.pbori
|
|
532
|
+
"""
|
|
533
|
+
if assumptions is not None:
|
|
534
|
+
raise NotImplementedError("Assumptions are not supported for DIMACS based solvers.")
|
|
535
|
+
|
|
536
|
+
self._run()
|
|
537
|
+
|
|
538
|
+
v_lines = []
|
|
539
|
+
for line in self._output:
|
|
540
|
+
if line.startswith("c"):
|
|
541
|
+
continue
|
|
542
|
+
if line.startswith("s"):
|
|
543
|
+
if "UNSAT" in line:
|
|
544
|
+
return False
|
|
545
|
+
if line.startswith("v"):
|
|
546
|
+
v_lines.append(line[1:].strip())
|
|
547
|
+
|
|
548
|
+
if v_lines:
|
|
549
|
+
L = " ".join(v_lines).split(" ")
|
|
550
|
+
assert L[-1] == "0", "last digit of solution line must be zero (not {})".format(L[-1])
|
|
551
|
+
return (None,) + tuple(int(e) > 0 for e in L[:-1])
|
|
552
|
+
else:
|
|
553
|
+
raise ValueError("When parsing the output(={}), no line starts with letter v or s".format(self._output))
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
class RSat(DIMACS):
|
|
557
|
+
"""
|
|
558
|
+
An instance of the RSat solver.
|
|
559
|
+
|
|
560
|
+
For information on RSat see: http://reasoning.cs.ucla.edu/rsat/
|
|
561
|
+
|
|
562
|
+
EXAMPLES::
|
|
563
|
+
|
|
564
|
+
sage: from sage.sat.solvers import RSat
|
|
565
|
+
sage: solver = RSat()
|
|
566
|
+
sage: solver
|
|
567
|
+
DIMACS Solver: 'rsat {input} -v -s'
|
|
568
|
+
|
|
569
|
+
When the problem is SAT::
|
|
570
|
+
|
|
571
|
+
sage: from sage.sat.solvers import RSat
|
|
572
|
+
sage: solver = RSat()
|
|
573
|
+
sage: solver.add_clause( (1, 2, 3) )
|
|
574
|
+
sage: solver.add_clause( (-1,) )
|
|
575
|
+
sage: solver.add_clause( (-2,) )
|
|
576
|
+
sage: solver() # optional - rsat
|
|
577
|
+
(None, False, False, True)
|
|
578
|
+
|
|
579
|
+
When the problem is UNSAT::
|
|
580
|
+
|
|
581
|
+
sage: solver = RSat()
|
|
582
|
+
sage: solver.add_clause((1,2))
|
|
583
|
+
sage: solver.add_clause((-1,2))
|
|
584
|
+
sage: solver.add_clause((1,-2))
|
|
585
|
+
sage: solver.add_clause((-1,-2))
|
|
586
|
+
sage: solver() # optional - rsat
|
|
587
|
+
False
|
|
588
|
+
"""
|
|
589
|
+
command = ["rsat", "{input}", "-v", "-s"]
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
class Glucose(DIMACS):
|
|
593
|
+
"""
|
|
594
|
+
An instance of the Glucose solver.
|
|
595
|
+
|
|
596
|
+
For information on Glucose see: http://www.labri.fr/perso/lsimon/glucose/
|
|
597
|
+
|
|
598
|
+
EXAMPLES::
|
|
599
|
+
|
|
600
|
+
sage: from sage.sat.solvers import Glucose
|
|
601
|
+
sage: solver = Glucose()
|
|
602
|
+
sage: solver
|
|
603
|
+
DIMACS Solver: 'glucose -verb=0 -model {input}'
|
|
604
|
+
|
|
605
|
+
When the problem is SAT::
|
|
606
|
+
|
|
607
|
+
sage: from sage.sat.solvers import Glucose
|
|
608
|
+
sage: solver1 = Glucose()
|
|
609
|
+
sage: solver1.add_clause( (1, 2, 3) )
|
|
610
|
+
sage: solver1.add_clause( (-1,) )
|
|
611
|
+
sage: solver1.add_clause( (-2,) )
|
|
612
|
+
sage: solver1() # optional - glucose
|
|
613
|
+
(None, False, False, True)
|
|
614
|
+
|
|
615
|
+
When the problem is UNSAT::
|
|
616
|
+
|
|
617
|
+
sage: solver2 = Glucose()
|
|
618
|
+
sage: solver2.add_clause((1,2))
|
|
619
|
+
sage: solver2.add_clause((-1,2))
|
|
620
|
+
sage: solver2.add_clause((1,-2))
|
|
621
|
+
sage: solver2.add_clause((-1,-2))
|
|
622
|
+
sage: solver2() # optional - glucose
|
|
623
|
+
False
|
|
624
|
+
|
|
625
|
+
With one hundred variables::
|
|
626
|
+
|
|
627
|
+
sage: solver3 = Glucose()
|
|
628
|
+
sage: solver3.add_clause( (1, 2, 100) )
|
|
629
|
+
sage: solver3.add_clause( (-1,) )
|
|
630
|
+
sage: solver3.add_clause( (-2,) )
|
|
631
|
+
sage: solver3() # optional - glucose
|
|
632
|
+
(None, False, False, ..., True)
|
|
633
|
+
|
|
634
|
+
TESTS::
|
|
635
|
+
|
|
636
|
+
sage: print(''.join(solver1._output)) # optional - glucose
|
|
637
|
+
c...
|
|
638
|
+
s SATISFIABLE
|
|
639
|
+
v -1 -2 3 0
|
|
640
|
+
|
|
641
|
+
::
|
|
642
|
+
|
|
643
|
+
sage: print(''.join(solver2._output)) # optional - glucose
|
|
644
|
+
c...
|
|
645
|
+
s UNSATISFIABLE
|
|
646
|
+
|
|
647
|
+
Glucose gives large solution on one single line::
|
|
648
|
+
|
|
649
|
+
sage: print(''.join(solver3._output)) # optional - glucose
|
|
650
|
+
c...
|
|
651
|
+
s SATISFIABLE
|
|
652
|
+
v -1 -2 ... 100 0
|
|
653
|
+
"""
|
|
654
|
+
command = [Glucose_executable(), "-verb=0", "-model", "{input}"]
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
class GlucoseSyrup(DIMACS):
|
|
658
|
+
"""
|
|
659
|
+
An instance of the Glucose-syrup parallel solver.
|
|
660
|
+
|
|
661
|
+
For information on Glucose see: http://www.labri.fr/perso/lsimon/glucose/
|
|
662
|
+
|
|
663
|
+
EXAMPLES::
|
|
664
|
+
|
|
665
|
+
sage: from sage.sat.solvers import GlucoseSyrup
|
|
666
|
+
sage: solver = GlucoseSyrup()
|
|
667
|
+
sage: solver
|
|
668
|
+
DIMACS Solver: 'glucose-syrup -model -verb=0 {input}'
|
|
669
|
+
|
|
670
|
+
When the problem is SAT::
|
|
671
|
+
|
|
672
|
+
sage: solver1 = GlucoseSyrup()
|
|
673
|
+
sage: solver1.add_clause( (1, 2, 3) )
|
|
674
|
+
sage: solver1.add_clause( (-1,) )
|
|
675
|
+
sage: solver1.add_clause( (-2,) )
|
|
676
|
+
sage: solver1() # optional - glucose
|
|
677
|
+
(None, False, False, True)
|
|
678
|
+
|
|
679
|
+
When the problem is UNSAT::
|
|
680
|
+
|
|
681
|
+
sage: solver2 = GlucoseSyrup()
|
|
682
|
+
sage: solver2.add_clause((1,2))
|
|
683
|
+
sage: solver2.add_clause((-1,2))
|
|
684
|
+
sage: solver2.add_clause((1,-2))
|
|
685
|
+
sage: solver2.add_clause((-1,-2))
|
|
686
|
+
sage: solver2() # optional - glucose
|
|
687
|
+
False
|
|
688
|
+
|
|
689
|
+
With one hundred variables::
|
|
690
|
+
|
|
691
|
+
sage: solver3 = GlucoseSyrup()
|
|
692
|
+
sage: solver3.add_clause( (1, 2, 100) )
|
|
693
|
+
sage: solver3.add_clause( (-1,) )
|
|
694
|
+
sage: solver3.add_clause( (-2,) )
|
|
695
|
+
sage: solver3() # optional - glucose
|
|
696
|
+
(None, False, False, ..., True)
|
|
697
|
+
|
|
698
|
+
TESTS::
|
|
699
|
+
|
|
700
|
+
sage: print(''.join(solver1._output)) # optional - glucose
|
|
701
|
+
c...
|
|
702
|
+
s SATISFIABLE
|
|
703
|
+
v -1 -2 3 0
|
|
704
|
+
|
|
705
|
+
::
|
|
706
|
+
|
|
707
|
+
sage: print(''.join(solver2._output)) # optional - glucose
|
|
708
|
+
c...
|
|
709
|
+
s UNSATISFIABLE
|
|
710
|
+
|
|
711
|
+
GlucoseSyrup gives large solution on one single line::
|
|
712
|
+
|
|
713
|
+
sage: print(''.join(solver3._output)) # optional - glucose
|
|
714
|
+
c...
|
|
715
|
+
s SATISFIABLE
|
|
716
|
+
v -1 -2 ... 100 0
|
|
717
|
+
"""
|
|
718
|
+
command = [Glucose_executable("glucose-syrup"), "-model", "-verb=0", "{input}"]
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
class Kissat(DIMACS):
|
|
722
|
+
"""
|
|
723
|
+
An instance of the Kissat SAT solver.
|
|
724
|
+
|
|
725
|
+
For information on Kissat see: http://fmv.jku.at/kissat/
|
|
726
|
+
|
|
727
|
+
EXAMPLES::
|
|
728
|
+
|
|
729
|
+
sage: from sage.sat.solvers import Kissat
|
|
730
|
+
sage: solver = Kissat()
|
|
731
|
+
sage: solver
|
|
732
|
+
DIMACS Solver: 'kissat -q {input}'
|
|
733
|
+
|
|
734
|
+
When the problem is SAT::
|
|
735
|
+
|
|
736
|
+
sage: solver1 = Kissat()
|
|
737
|
+
sage: solver1.add_clause( (1, 2, 3) )
|
|
738
|
+
sage: solver1.add_clause( (-1,) )
|
|
739
|
+
sage: solver1.add_clause( (-2,) )
|
|
740
|
+
sage: solver1() # optional - kissat
|
|
741
|
+
(None, False, False, True)
|
|
742
|
+
|
|
743
|
+
When the problem is UNSAT::
|
|
744
|
+
|
|
745
|
+
sage: solver2 = Kissat()
|
|
746
|
+
sage: solver2.add_clause((1,2))
|
|
747
|
+
sage: solver2.add_clause((-1,2))
|
|
748
|
+
sage: solver2.add_clause((1,-2))
|
|
749
|
+
sage: solver2.add_clause((-1,-2))
|
|
750
|
+
sage: solver2() # optional - kissat
|
|
751
|
+
False
|
|
752
|
+
|
|
753
|
+
With one hundred variables::
|
|
754
|
+
|
|
755
|
+
sage: solver3 = Kissat()
|
|
756
|
+
sage: solver3.add_clause( (1, 2, 100) )
|
|
757
|
+
sage: solver3.add_clause( (-1,) )
|
|
758
|
+
sage: solver3.add_clause( (-2,) )
|
|
759
|
+
sage: solver3() # optional - kissat
|
|
760
|
+
(None, False, False, ..., True)
|
|
761
|
+
|
|
762
|
+
TESTS::
|
|
763
|
+
|
|
764
|
+
sage: print(''.join(solver1._output)) # optional - kissat
|
|
765
|
+
s SATISFIABLE
|
|
766
|
+
v -1 -2 3 0
|
|
767
|
+
|
|
768
|
+
::
|
|
769
|
+
|
|
770
|
+
sage: print(''.join(solver2._output)) # optional - kissat
|
|
771
|
+
s UNSATISFIABLE
|
|
772
|
+
|
|
773
|
+
Here the output contains many lines starting with letter "v"::
|
|
774
|
+
|
|
775
|
+
sage: print(''.join(solver3._output)) # optional - kissat
|
|
776
|
+
s SATISFIABLE
|
|
777
|
+
v -1 -2 ...
|
|
778
|
+
v ...
|
|
779
|
+
v ...
|
|
780
|
+
v ... 100 0
|
|
781
|
+
"""
|
|
782
|
+
|
|
783
|
+
command = [Kissat_executable(), "-q", "{input}"]
|